From ada549f7765b80b4dddc527480cde96a4a080858 Mon Sep 17 00:00:00 2001 From: Todd Lipcon Date: Mon, 7 Dec 2009 05:22:16 +0000 Subject: [PATCH 001/756] Branching for 0.2 release git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.2.x@887836 13f79535-47bb-0310-9956-ffa450edef68 From 72a1a88c4a2a9cbf5bae49e5784454d95c58a3b0 Mon Sep 17 00:00:00 2001 From: Todd Lipcon Date: Tue, 8 Dec 2009 03:40:31 +0000 Subject: [PATCH 002/756] THRIFT-642. Release notes in NEWS file for 0.2.0 git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.2.x@888241 13f79535-47bb-0310-9956-ffa450edef68 --- NEWS | 409 +++++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 410 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 2369f61d318..0dc40b65cd9 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,412 @@ +Release Notes for Thrift 0.2.0 + +General changes: + * First release under the Apache Incubator + * THRIFT-34, THRIFT-270: Namespaces have been updated to Apache instead of Facebook + * THRIFT-110, THRIFT-332, THRIFT-333: Beginnings of a new "Compact Protocol" implemented in Ruby, Java, and C++ + * THRIFT-136: "async" has been renamed "oneway" + * THRIFT-409: Support for unions + * THRIFT-173: New HTML generator for generating documentation + +C++: + THRIFT-91. cpp: Fix compilation on Fedora Core 9 + THRIFT-95. cpp: Fix write buffer initialization in TBufferedTransport + THRIFT-96. cpp: TSocket.peek fails on FreeBSD + THRIFT-149. cpp: Make TNonblockingServer handle a shut-down ThreadManager + THRIFT-168. cpp: Clear transport buffers before a flush + THRIFT-177. cpp: Add a missing "std::" + THRIFT-178. java, csharp, cpp: Final Keyword + THRIFT-194. cpp: Properlyl namespace exception types in catch + THRIFT-203. cpp: Make library headers compile under g++ -pedantic + THRIFT-214. cpp: Qualify another cast + THRIFT-214. cpp: Qualify a cast to fix OSX compilation + THRIFT-215. cpp: Disable an assertion that fails on various platforms + THRIFT-225. java/cpp: Handle non-i32 integer constants properly + THRIFT-244. cpp: Fix TJSONProtocol::writeMessageBegin + THRIFT-244. cpp: Make TJSONProtocolFactor inherit from TProtocolFactory + THRIFT-255. cpp: Add TSimpleFileTransport, a wrapper around TFDTransport + THRIFT-265. cpp: Reset buffers every 512 calls in TNonblockingServer + THRIFT-289. cpp: Fix "make check" by defining a comparator for "Instanity" + THRIFT-333. cpp: Initial TCompactProtocol implementation + THRIFT-348. cpp: Fix readBool for vectors of bools (again) + THRIFT-351. cpp: Allow a custom ThreadFactory in TThreadedServer + Thrift-357. cpp: Fix buffer and connection bloat in TNonBlockingServer + THRIFT-411. cpp: Make TNonblockingServer::connectionStackLimit_ accessors use the right type + THRIFT-425. cpp: numeric_limits is declared in + THRIFT-426. cpp: Fix include path under test/cpp + THRIFT-464. cpp: Fix some STL misuse in the concurrency library + THRIFT-465. cpp: Fix some STL misuse in the concurrency library test + THRIFT-466. cpp: Make the concurrency library test more thorough + THRIFT-469. cpp: Fix a bug in TimerManager::add + THRIFT-497. cpp: Fix TSocket::read and peek on Max OS + THRIFT-555. cpp: Fix macro defintions for TCompact on non-GNU big endian + THRIFT-587. cpp: Properly set addrLen before accept calls + THRIFT-606. cpp: Fix build on Solaris Nevada + THRIFT-621. cpp: Fix generated files using "apache" namespaces + cpp: Add some missing includes to fix OpenBSD compilation + cpp: Deal with systems without AI_ADDRCONFIG (OpenBSD) + cpp: Deal with systems without sched_get_priority_{min,max} (OpenBSD) + cpp: Eliminate a buffer overflow in the tutorial server + cpp: Eliminate the use of fprintf [THRIFT-77] + cpp: Fix an OpenBSD compilation bug by moving a typedef + cpp: Fix an OpenBSD compilation error that appears to be a real bug + cpp: Fix compilation on OpenBSD by including sys/types.h + cpp: Fix compiler and library compilation with newer glibc + cpp: Fix implementations of "list" + cpp: Fix test server/client under test/cpp + cpp: Fix "make check" by defining a comparator for "Empty" + cpp: Make the test server compatible with the Python test client + cpp: Rename Makefiles under test/cpp + cpp: Resolve an ambiguous overload in some tests + +Java: + Minor whitespace fixes in the Java generator and gen-code + THRIFT-10. java: Descriptors used during serialization should be immutable objects + THRIFT-34 Java libraries should be namespaced under org.apache.thrift, not com.facebook.thrift + THRIFT-64. java: Allow TServerSocket to bind to a specific IP address + THRIFT-81. java: TNonblockingServer: Support a limit on read buffer size + THRIFT-100. java: Set __isset better in beans style + THRIFT-110. java: A more compact format + THRIFT-115. java: Isset structure has a large memory footprint + THRIFT-116. java: Isset fields for non-primitive types unnecessary + THRIFT-119. java: structs' toString omits unset optional fields + THRIFT-120. java: Make the nocamel option work for more methods + THRIFT-130. java: Eliminate frame{Read,Write} from TFramedTransport + THRIFT-138. java: Create deep-copy constructors for Thrift structs + THRIFT-138. java: Fix copy constructor for binary fields + THRIFT-139. java: Expose field ids in more useful ways + THRIFT-139. java: Fix indentation in beans mode + THRIFT-142. java: Better handling of required fields + THRIFT-144. java: Generated classes should implement Comparable + THRIFT-145. java: Make TNonblockingServer more robust against errors + THRIFT-152. java: Set isset appropriately in structure constructors + THRIFT-166. java: Java tests should be in lib/java/test/ THRIFT-221. java: Make java build classpath more dynamic and configurable + THRIFT-172. java: Improve toString output for binary fields + THRIFT-178. java, csharp, cpp: Final Keyword + THRIFT-179. java: Include per-field docstrings in generated code + THRIFT-191. java: Create a static field id -> name map for each struct + THRIFT-202: java: Fix "make check" + THRIFT-218. java: When validation fails on serialization/deserialization, print out the invalid object + THRIFT-222. java: Better exposure if __isset in beans style + THRIFT-225. java/cpp: Handle non-i32 integer constants properly + THRIFT-235. java: Explicitly cast integer constants to double + THRIFT-239. java: Generate @Override annotations for all overrided methods + THRIFT-240. java: TBase should implement Cloneable + THRIFT-249. java: Add @param lines to function docstrings + THRIFT-253. java: Enhance FieldMetaData + THRIFT-262. java: Generate Javadocs for library classes + THRIFT-278. java: #validate exceptions should contain the offending value + THRIFT-288. java: Generated code iterates maps during write inefficiently + THRIFT-289. test: "make check" no longer runs the Java tests + THRIFT-290. java: Metadata map doesn't properly reference external thrift file's types + THRIFT-292. Auto-generate the Java gen-code in build.xml + THRIFT-297. java: getFieldValue and setFieldValue should be abstract TBase methods + THRIFT-303. java: Changes to __isset interface + THRIFT-316. java: @Override isn't generated for hashCode() without the hash code builder + THRIFT-318. java: Performance of HashSet for enumeration VALID_VALUES seems poor + THRIFT-321. java: THRIFT-303 broke EqualityTest Regenerated test code. + THRIFT-359. java: nocamel style breaks generated services + THRIFT-364. java: Use of enums in other namespaces breaks java generated code + THRIFT-366. java: Lots of little warnings in java library + THRIFT-367. java: Some dead code in TNonblockingSocket.java + THRIFT-368. java: setFieldValue should allow nulls for all field types + THRIFT-378. java: Java servers do not turn internal errors into thrift exceptions + THRIFT-379. java: Print enum value names + THRIFT-382. java: Unused imports in generated code + THRIFT-409. java: Add "union" to Thrift + THRIFT-416. java: java.util.logging eats exceptions without warning + THRIFT-427. java: Fix print_const_value + THRIFT-446. java: PartialDeserialization in Java + THRIFT-450. java: Check for Apache Commons Lang also + THRIFT-450. java: Propagate CLASSPATH from ./configure to make and ant + THRIFT-450. java: Respect the global classpath during testing + THRIFT-453. java: By default, use Ivy to download Java dependencies + THRIFT-462. java: Installed jar shouldn't be executable + THRIFT-479. java: Add javadocs for enum types + THRIFT-482. java: build.xml does not specify a target version for compiled java classes + THRIFT-489. java: Java enum validation only validates explicitly assigned values + THRIFT-493. java: Stopping TNonblockingServer when it hasn't been starting results in an exception + THRIFT-529. java: Change generated constructors so that application code evolves better Optional fields are now excluded from constructors. + THRIFT-540. java: Have set methods return reference to self + THRIFT-543. java: Generate normal style java files should respect the "optional" keyword when serializing + THRIFT-551. java: Enumeration doesn't generate real enum in Java This patch makes the compiler generate actual Enum classes. + THRIFT-558. java: Replace use of log4j by commons-logging in Java library and generated Java code + THRIFT-565. java: Structs containing typedefs for incomparable objects will be considered comparable This patch causes the compiler to fully unwrap typedefs when determining comparability. + THRIFT-566. java: jar file should contain copies of LICENSE and NOTICE files + THRIFT-572. java: Union compareTo is broken + THRIFT-588. java: Generated .equals method throws NPE for thrift object + THRIFT-589. java: Add Field Name to Field ID Mapping Java Thrift structs now have a static mapping of field name to field ID. + THRIFT-620. java: Compact Protocol should call readAll, not read This patch switches to calling readAll instead of read. + THRIFT-623. java: Use a Java enum to represent field ids in generated structs + THRIFT-624. java: compareTo is broken for Unions with binary fields This patch adds a special case for byte[] values in TUnion. It also fixes a related bug in TBaseHelper for comparing two byte arrays. + THRIFT-628. java: Hash code method for _Fields objects does not behave as expected This patch switches to using the hashcode of the actual field id, instead of the field id enumeration. + java: Added SerializationBenchmark.java, helper class for performing tests on protocols. + java: Add a helper function to implement nocamel style + java: Add nocamel option to not CamelCase field accessors [THRIFT-42] + java: Close broken connections [THRIFT-73] + java: Fix a minor formatting problem in the gen-code + java: Specify in build.xml that we are using Java 1.5 + (THRIFT-5) A TNonblockingServers (single-threaded and thread-pool) for Java + (THRIFT-12) Make the Java library use java.util.logging instead of stdout. + [THRIFT-70] Allow the Java install prefix to be configured. + + +Erlang: + Add erl back to EXTRA_DIST because it doesn't use Automake. + Allow the Thrift compiler to be built without the Erlang generator. + Make the Erlang generator dynamic. + THRIFT-83. erlang: Don't flush an empty buffer in the http transport. + THRIFT-94. erlang: Fix a syntax error + THRIFT-126. erlang: TMemoryBuffer for Erlang + THRIFT-127. erlang: Skip fields that have the wrong type + THRIFT-136. s/async/oneway/ in Erlang + THRIFT-186. erl: Make the Makefile work on OpenSolaris + THRIFT-192. erlang: Commit test code missed in r757870 + THRIFT-192. erl: Fix handling of booleans + THRIFT-211. erlang: Allow clients to be created without connecting + THRIFT-211. erlang: Modify test_tether to test protocol error handling as well + THRIFT-211. erlang: Support unlinked Thrift clients. + THRIFT-211. erlang: Support "tethered" clients + THRIFT-266. erlang: Erlang atoms must always start with lower-case character + THRIFT-305. erlang: Fix http_options for thrift_http_transport + THRIFT-306. erlang: Let thrift_http_transport specify custom HTTP headers + THRIFT-307. erlang: Make HiPE optional + THRIFT-524. erlang: Decapitalize file names in include directives + THRIFT-574. erlang: Support framed transport for servers + + +Python: + Python generator exception namespacing, THRIFT-150 + THRIFT-48. python: Make TServerSocket work with Unix-domain sockets + THRIFT-67. python: Add TNonblockingServer + THRIFT-93. Remove unnecessary shebang lines from Python libraries + THRIFT-108. python: Fix call to PyDict_Next in fastbinary.c + THRIFT-109. python: Use self.assert* instead of assert in tests + THRIFT-148. py: Add support for Twisted + THRIFT-148. py: Add un-commited file missing from 749510 + THRIFT-148. py: One more time, reapply the most *recent* patch + THRIFT-154. python: Make THttpClient take a URL in its constructor + THRIFT-155. python: Reopen THttpClient on a flush + THRIFT-195. python: Add a simple THttpServer + THRIFT-212. python: Make TFramedTransport implement CReadableTransport + THRIFT-217. Use "--gen py" instead of "-py" in build scripts + THRIFT-241. python: Generate a better implementation of __repr__ + THRIFT-242. python: Used named arguments in __init__ instead of a dict + THRIFT-256. python: Fix inheritance of services in the same IDL file + THRIFT-282. Generate doccstrings for Python classes + THRIFT-284. python: Update tutorial files to use repr + THRIFT-285. python: Don't generate _result structs for async functions + THRIFT-292. Auto-generate the Python gen-code in build.xml + THRIFT-292. Restore fb303/FacebookBase.py + THRIFT-310. python: Generate valid code for empty services + THRIFT-329. python: Make TServerSocket.close() work properly + THRIFT-340. python: Detect endianness properly on FreeBSD + THRIFT-360. python: Make fastbinary skip struct fields with the wrong type + THRIFT-362. python: Detect endianness on Solaris + THRIFT-391. py: Fix memory leak in fastbinary + THRIFT-412. python: Fix some syntacticaly-incorrect code generation + THRIFT-463. python: Fix thrift_spec ordering bug from r760201 + THRIFT-471. python: Generated exceptions should implement __str__ + THRIFT-494. python: Update meta-information in setup.py + THRIFT-495. python: Raise a TTransportException if TSocket is not open + THRIFT-535. py: Twisted Thrift protocol max length is too small + THRIFT-535. py: Twisted Thrift protocol max length is too small (fix off-by-one error in MAX_LENGTH) + THRIFT-583. python: Allow new-style classes for Interfaces + THRIFT-586. python: TSocket incorrectly sets the exception type when an end of file error occurs + THRIFT-612. python: Fix exception bug in TFramedTransport.cstringio_refill + THRIFT-637. python: Fix mixing of oneway and regular requests in TNonblockingServer + cpp: Make the test server compatible with the Python test client + generate Twisted code in a separate directory (gen-py.twisted) + python: Add TFileObjectTransport + python: Eliminate the option of TFramedTransport to not frame + python: Make TFramedTransport use a cStringIO for reading + python: Make the unit tests run faster and more reliably + rb: Make TServer.py Python 2.4 compatible [THRIFT-44] + +Ruby: + Add Apache headers to Ruby libs and remove a few remaining Facebook notices + Add back OCamlMakefile and setup.rb to LICENSE + Fix "make distclean" when Ruby is not in use + Remove now defunct tests (they've been moved to specs in lib/rb) + THRFIT-231. rb: Make Thrift::Structs hashable + THRIFT-132. ruby: Ruby generator should use ::Thrift::Foo namespace form + THRIFT-157. rb: Quote strings and qualify class names properly + THRIFT-175. Specs in Ruby library should be run during make check + THRIFT-229. rb: Don't block indefinitely on connect() + THRIFT-245. rb: FIELDS constant should contain name of enumerated type for enum fields + THRIFT-246. rb: Generate #struct_fields rather than reflect. + THRIFT-248. ruby: Factor BinaryProtocolAccelerated into separate protocol and struct components + THRIFT-254. rb: Add optional strict version support to binary protocols + THRIFT-260. rb: Some Protocol methods shouldn't have default nil implementations + THRIFT-275. rb: Remove deprecated classes from Ruby library + THRIFT-276. rb: Ruby libraries should have one class per file + THRIFT-277. rb: Abstract Transport in Ruby #read method should throw NotImplementedException + THRIFT-298. ruby: Exception propagation seems broken for Ruby clients + THRIFT-302. ruby: Native extension fails to build + THRIFT-312. rb: Ruby unit tests fail due to change in BinaryProtocolAccelerated interface + THRIFT-313. rb: BinaryProtocolAccelerated and BinaryProtocol don't produce the same bytes when writes aren't strict + THRIFT-332. rb: Compact Protocol in Ruby + THRIFT-352. rb: Implicit enums should be valid values + THRIFT-353. rb: Capitalize module names on ruby generation + THRIFT-358. ruby: Change how external thrift files' generated code is required + THRIFT-372. rb: Ruby lib doesn't rescue properly from lack of native_thrift extension + THRIFT-374. rb: ruby 1.9 compatibility + THRIFT-375. rb: syntax error in benchmark.rb + THRIFT-396. rb: BinaryProtocol missing method implementations + THRIFT-401. rb: Speed up FramedTransport + THRIFT-402. rb: MemoryBuffer > 4096 bytes will truncate remaining bytes + THRIFT-408. rb: Ruby C extension doesn't build on 1.8.5 + THRIFT-410. rb: Ruby lib should have no checked in generated code + THRIFT-410. rb: Ruby lib should have no checked in generated code + THRIFT-415. rb: BinaryProtocolAccelerated does not behave properly when strict reads are turned off + THRIFT-417. rb: BufferedTransport can enter an infinite loop + THRIFT-421. rb: Fix tests broken by original patch + THRIFT-422. rb: scope all references to the Thrift module + THRIFT-430. rb: ruby tutorials and ruby tests require deprecated files and class names + THRIFT-431. rb: Capitalize namespace values + THRIFT-433. rb: 'rake spec' sort of fails + THRIFT-437. rb: fix benchmarking tools to require proper file names + THRIFT-444. rb: THRIFT-356 broke compact protocol spec + THRIFT-445. rb: client and processor do not inherit from the proper namespace scope + THRIFT-451. rb: ruby structs use lowercase enum while modules are capitalized + THRIFT-485. rb: Generated validate methods that reference external thrift files' types are not referenced correctly + THRIFT-486. rb: ruby tutorial needs updated require statements + THRIFT-498. rb: Compact and Binary native protocols, used at the same time, can cause some issues + THRIFT-501. rb: File.dirname(...) requires cause warnings in some scenarios + THRIFT-511. rb: Better performing hash method for generated structs + THRIFT-513. rb: spec test files broken, rake searching for misnamed files + THRIFT-516. rb: If TFramedTransport reads a negative frame size, throw a TTransportException descendant instead of the default NegativeArraySizeException + THRIFT-526. rb: Generated Ruby enums have no good way to get the names back out once you have a number. + THRIFT-547. rb: Thrift deserializer hangs when deserializing empty string + THRIFT-552. rb: gem requires exactly rubygems 1.2.0 + HRIFT-569. rb: Segmentation Fault when using BinaryProtocolAccelerated in Ruby + THRIFT-571. rb: compact_protocol.c:89: warning: format not a string literal and no format arguments + THRIFT-572. rb: fix RSTRING for 1.9 compatibility + THRIFT-603. rb: Struct read method does not call validate After reading a struct, we will now call the struct's validate method. + Thrift-421. rb: Underscore output file names and require file statments + rb: Add FramedTransport#borrow/consume! [THRIFT-117] + rb: Add TProtocolException to the backwards_compatibility_spec [THRIFT-88] + rb: Add docstrings to generated ruby code [THRIFT-147] + rb: Add ext/ to loadpath so BinaryProtocolAccelerated specs pass + rb: Add optional timeout argument to Thrift::Socket [THRIFT-74] + rb: Add pretty inspect, optional field hint for Thrift::Struct + rb: Add some additional error handling to Thrift::Socket [THRIFT-53] + rb: Add stubs for rake install/package when Echoe not present [THRIFT-52] + rb: BinaryProtocolAccelerated should use Thrift::ProtocolException [THRIFT-89] + rb: BufferedTransport should flush on close [THRIFT-49] + rb: Buffer the slice!s in MemoryBuffer for a significant performance increase [THRIFT-63] + rb: Bugfix for deprecation code [kevin@rapleaf.com][THRIFT-50] + rb: Change the license from Thrift Software License to Apache Software License [THRIFT-38] + rb: Check Thrift.type_checking earlier for a performance boost [THRIFT-55] + rb: Check container elements when Thrift.type_checking = true [THRIFT-104] + rb: Create constants for field ids in generated structs [THRIFT-165] + rb: Delete setup.rb [THRIFT-38] + rb: Display field name in type-checking error [THRIFT-78] + rb: Ensure the specs that expect deprecation warnings actually get them [THRIFT-56] + rb: Ensure the transport is closed if an exception is raised serializing data in Client.send_message [THRIFT-75] + rb: Improve IOStreamTransport to behave more like a real transport [THRIFT-76] + rb: Make TServer.py Python 2.4 compatible [THRIFT-44] + rb: Performance tweaks in Struct#initialize [THRIFT-188] + rb: Remove extra validate in read [THRIFT-207] + rb: Reorganize the Rakefile a bit [THRIFT-38] + rb: Spec out Thrift::BinaryProtocolAccelerated [THRIFT-90] + rb: Speed up Struct#initialize for optional fields [THRFIT-112] + rb: Support SSL and correct Content-Type in HTTPClient [THRIFT-156] + rb: Support `raise Xception, message` for Structs that inherit from ::Exception [THRIFT-58] + rb: Teach BinaryProtocolAccelerated to encode strings with NULs [THRIFT-97] + rb: The deprecation stuff should skip thrift library code when showing caller [THRIFT-56] + rb: The shared binary protocol specs lacked a test for read_message_begin + rb: Thrift.check_type should check struct classes [THRIFT-185] + rb: Update HTTPClientSpec for THRIFT-156 + rb: Use Echoe to manage the gem [THRIFT-38] + rb: Use File.dirname(__FILE__) in generated requires [THRIFT-57] + rb: Use defined? JRUBY_VERSION to detect JRuby [THRIFT-38] + rb: Validate struct _after_ read. [THRIFT-206] + rb: When passing unknown keys to Thrift::Struct.new, report those keys in the exception [THRIFT-51] + rb: raise if an object is serialized without required fields [THRIFT-143] + rb: require 'thrift' first in generated service definitions [THRIFT-38] + rb: rewrite the README [THRIFT-38] + +PHP: + Allow the Thrift compiler to be built without the PHP generator. + Make the PHP generator dynamic. + Make the PHP generator use non-hardcoded namespaces. + Remove obsolete php extension tag + THRIFT-99. php: Add scheme (http[s], etc.) support to THttpClient + THRIFT-349. php: Accelerated binary protocol serialization segementation fault + THRIFT-350. php: Fix the extension build when C++ is not already used + THRIFT-404. php: Make TPhpStream work for cli (cgi) scripts + THRIFT-405. php: Create a tutorial server + THRIFT-499. php: Thrift_protocol PHP extension does not handle signedness correctly + THRIFT-584. php: Generate a better directory structure + php: Fix an undefined variasble in an error message + php: Improve some docblock comments for TSocket + +Perl: + Perl library should honor the INSTALLDIRS variable + THRIFT-190. Added dependency check to perl Makefile + THRIFT-193: Patch for proper namespace support in perl compiler + THRIFT-199. perl: Let "make distclean" work when we are not using Perl + THRIFT-199: integrate perl into automake + THRIFT-470. fb303: Use a namespace in Perl gen-code + THRIFT-542: Perl compiler uses invalid method 'method_exists' and subsequent test + THRIFT-554: Perl improper namespace check for exception handling and writeMessageEnd missing on processor calls + THRIFT-590: send/recv timeout values interchanged in perl socket lib + THRIFT-619: Perl server and example + + +C#: + THRIFT-25. csharp: Various compiler and library improvements + THRIFT-46. csharp: Throw the correct exception for an unknown method + THRIFT-129. csharp: Make all Thrift structures extend TBase + THRIFT-158. csharp: Update headers to Apache + THRIFT-159. csharp: Compiler doesn't add package scope to exceptions in catch blocks and assigns to unused local var when reading + THRIFT-178. java, csharp, cpp: Final Keyword + THRIFT-204. csharp: C# Partial Classes + THRIFT-209. csharp: Make TTransportFactory.GetTransport virtual + THRIFT-258. csharp: Include all lib source files in Makefile.am + THRIFT-264. csharp: Include TBufferedTransport in the build on Linux + THRIFT-264. csharp: Use /langversion:linq to fix the Linux build + THRIFT-384. csharp: Fix handling of fields named "value" + THRIFT-467. csharp: Fix compilation on Debian Sid + THRIFT-525. csharp: ThriftTest project will not generate c# from .thrift file or generate ThriftImpl.dll + THRIFT-531. csharp: C# project and solution files reference external source control system + csharp: Remove a BOM and CRLF line endings from some test code + +Haskell: + Consolidate lib/hs/.gitignore into the top-level .gitignore + THRIFT-385. hs: 64-bit integer and double types incorrectly serialized on 32-bit platforms + THRIFT-390. hs: Cabalize Haskell library code + THRIFT-392. hs: Make test scripts easier to use + THRIFT-397. hs: Remove unnecessary redefinition of generate_program() + THRIFT-398. hs: Remove unnecessary parens from generated type annotations + THRIFT-399. hs: Fix set and number issues in generated constant code + THRIFT-407. hs: Refactor and improve Haskell-related code + +OCaml: + No changes + +Smalltalk: + smalltalk: Fix TBinaryProtocol readString for empty strings + +XSD: + Allow the Thrift compiler to be built without the XSD generator. + Make the XSD generator dynamic. + Make the XSD generator use non-hardcoded namespaces. + +HTML: + THRIFT-173. Commit the html generator + THRIFT-259. html: Generate "extends" link for extended services + THRIFT-365. html: HTML compiler infinite loop + +Cocoa: + THRIFT-280. Server-side Cocoa implementation. + THRIFT-343. Import instead of to support iPhone + THRIFT-344. Add a 'log_unexpected' option to the cocoa generator. off by default. when supplied, unexpected field IDs and types are logged when reading a struct. + THRIFT-520. Fix generation of cocoa constants when a namespace prefix is set. + + + Release Notes for Thrift 20080411 .equals and .hashCode() for Java scturcts (developed by dreiss). diff --git a/configure.ac b/configure.ac index a3b0b4b8295..50f747be717 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.59) -AC_INIT([thrift], [20080411]) +AC_INIT([thrift], [0.2.0]) AC_CONFIG_AUX_DIR([.]) From b405edb6ff46b894cb9abce1f1b2e0121770db3d Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Fri, 7 May 2010 18:44:48 +0000 Subject: [PATCH 003/756] cut a branch for preparing for the 0.3.0 release git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.0@942175 13f79535-47bb-0310-9956-ffa450edef68 From b9b7048bc37c3fc30e0631a5fa0be9e12ab20d71 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Fri, 7 May 2010 18:55:53 +0000 Subject: [PATCH 004/756] bump some version numbers to where they belong git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.0@942178 13f79535-47bb-0310-9956-ffa450edef68 --- configure.ac | 2 +- lib/rb/Rakefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 098b6cac514..c97c8fd31b9 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.59) -AC_INIT([thrift], [0.4.0-dev]) +AC_INIT([thrift], [0.3.0]) AC_CONFIG_AUX_DIR([.]) diff --git a/lib/rb/Rakefile b/lib/rb/Rakefile index 10383e7183a..a042fb8b525 100644 --- a/lib/rb/Rakefile +++ b/lib/rb/Rakefile @@ -82,7 +82,7 @@ begin p.summary = "Ruby libraries for Thrift (a language-agnostic RPC system)" p.url = "http://incubator.apache.org/thrift/" p.include_rakefile = true - p.version = "0.2.5" + p.version = "0.3.0" p.rubygems_version = ">= 1.2.0" end From fe55e75bbd0e5ff886d4b64b202f7a3e1e1df8a7 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Wed, 12 May 2010 21:16:44 +0000 Subject: [PATCH 005/756] THRIFT-373. Include js and as3 libraries in release tarballs git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.0@943690 13f79535-47bb-0310-9956-ffa450edef68 --- lib/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Makefile.am b/lib/Makefile.am index a7ae651e491..7df66d1b375 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -56,4 +56,6 @@ EXTRA_DIST = \ ocaml \ php \ erl \ + js \ + as3 \ st From 910cd831ed43ebf58e7fd27024d8950a36ec1f2b Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Wed, 19 May 2010 16:28:08 +0000 Subject: [PATCH 006/756] Merge in THRIFT-784 and THRIFT-646 git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.0@946261 13f79535-47bb-0310-9956-ffa450edef68 --- configure.ac | 6 ++++-- lib/erl/Makefile.am | 33 ++++++++++----------------------- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/configure.ac b/configure.ac index c97c8fd31b9..95a794a8b7d 100644 --- a/configure.ac +++ b/configure.ac @@ -93,9 +93,11 @@ AM_CONDITIONAL([WITH_JAVA], AX_THRIFT_LIB(erlang, [Erlang], yes) if test "$with_erlang" = "yes"; then - AC_PATH_PROG([ERLC], [erlc]) + AC_ERLANG_PATH_ERL + AC_ERLANG_PATH_ERLC + AC_ERLANG_SUBST_INSTALL_LIB_SUBDIR(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) fi -AM_CONDITIONAL(WITH_ERLANG, [test -n "$ERLC"]) +AM_CONDITIONAL(WITH_ERLANG, [test -n "$ERL" -a -n "$ERLC"]) AX_THRIFT_LIB(py, [Python], yes) if test "$with_py" = "yes"; then diff --git a/lib/erl/Makefile.am b/lib/erl/Makefile.am index ee8fbffd12d..33761a11144 100644 --- a/lib/erl/Makefile.am +++ b/lib/erl/Makefile.am @@ -17,9 +17,6 @@ # under the License. # -# directory where erlang library code should live -ERL_LIB_ROOT_DIR=$(shell erl -eval 'io:format("~s~n", [code:lib_dir()])' -s init stop -noshell) - MODULES = \ src @@ -28,30 +25,20 @@ all clean docs: (cd $$dir; ${MAKE} $@); \ done -ERLLIBDIR=$(DESTDIR)$(ERL_LIB_ROOT_DIR)/$(PACKAGE_NAME)-$(PACKAGE_VERSION) - install: all - mkdir -p $(ERLLIBDIR) ; \ - mkdir -p $(ERLLIBDIR)/ebin ; \ - mkdir -p $(ERLLIBDIR)/include ; \ - mkdir -p $(ERLLIBDIR)/src ; \ - for i in ebin/*.app* ; do $(INSTALL) $$i $(ERLLIBDIR)/$$i ; done ; \ - for i in ebin/*.beam ; do $(INSTALL) $$i $(ERLLIBDIR)/$$i ; done ; \ - for i in include/*.hrl ; do $(INSTALL) $$i $(ERLLIBDIR)/$$i ; done ; \ - for i in src/*.erl ; do $(INSTALL) $$i $(ERLLIBDIR)/$$i ; done + mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift) ; \ + mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/ebin ; \ + mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/include ; \ + mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/src ; \ + for p in ebin/*.app* ebin/*.beam include/*.hrl src/*.erl ; \ + do $(INSTALL) $$p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift)/$$p ; \ + done uninstall: - rm -rf $(ERLLIBDIR) + rm -rf $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift) -check: all -distclean: clean - -# Hack to make "make dist" work. -# This should not work, but it appears to. -distdir: +maintainer-clean-local: + rm -rf ebin MAINTAINERCLEANFILES = Makefile.in - -maintainer-clean: - test ! -d ebin || rm -rf ebin From 0851779daa867653e9603d6eb479f8f73ea40732 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Tue, 22 Jun 2010 18:53:53 +0000 Subject: [PATCH 007/756] THRIFT-799. Files missing proper Apache license header Added the Apache license header to a bunch of files that were missing it. git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.0@956975 13f79535-47bb-0310-9956-ffa450edef68 --- .../transport/TMemoryInputTransport.java | 18 ++++++++++++++++++ .../test/org/apache/thrift/TestStruct.java | 18 ++++++++++++++++++ .../org/apache/thrift/TestTBaseHelper.java | 18 ++++++++++++++++++ .../test/org/apache/thrift/TestTUnion.java | 18 ++++++++++++++++++ .../transport/TestTMemoryInputTransport.java | 18 ++++++++++++++++++ lib/js/test/src/test/TestHandler.java | 18 ++++++++++++++++++ lib/py/src/TSerialization.py | 19 +++++++++++++++++++ 7 files changed, 127 insertions(+) diff --git a/lib/java/src/org/apache/thrift/transport/TMemoryInputTransport.java b/lib/java/src/org/apache/thrift/transport/TMemoryInputTransport.java index 0a0998d7a63..13b5f834b45 100644 --- a/lib/java/src/org/apache/thrift/transport/TMemoryInputTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TMemoryInputTransport.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift.transport; public final class TMemoryInputTransport extends TTransport { diff --git a/lib/java/test/org/apache/thrift/TestStruct.java b/lib/java/test/org/apache/thrift/TestStruct.java index 4ab2a1e68cb..755534d91f0 100644 --- a/lib/java/test/org/apache/thrift/TestStruct.java +++ b/lib/java/test/org/apache/thrift/TestStruct.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift; import java.io.ByteArrayInputStream; diff --git a/lib/java/test/org/apache/thrift/TestTBaseHelper.java b/lib/java/test/org/apache/thrift/TestTBaseHelper.java index e2d786901c3..6f24093f938 100644 --- a/lib/java/test/org/apache/thrift/TestTBaseHelper.java +++ b/lib/java/test/org/apache/thrift/TestTBaseHelper.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift; import java.util.Arrays; diff --git a/lib/java/test/org/apache/thrift/TestTUnion.java b/lib/java/test/org/apache/thrift/TestTUnion.java index bf8ee83f039..2ff80e925b6 100644 --- a/lib/java/test/org/apache/thrift/TestTUnion.java +++ b/lib/java/test/org/apache/thrift/TestTUnion.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift; import org.apache.thrift.protocol.TBinaryProtocol; diff --git a/lib/java/test/org/apache/thrift/transport/TestTMemoryInputTransport.java b/lib/java/test/org/apache/thrift/transport/TestTMemoryInputTransport.java index 0b1702e6cd0..273145bd237 100644 --- a/lib/java/test/org/apache/thrift/transport/TestTMemoryInputTransport.java +++ b/lib/java/test/org/apache/thrift/transport/TestTMemoryInputTransport.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift.transport; import java.util.Arrays; diff --git a/lib/js/test/src/test/TestHandler.java b/lib/js/test/src/test/TestHandler.java index 2eaf6c60906..727a32b7dea 100644 --- a/lib/js/test/src/test/TestHandler.java +++ b/lib/js/test/src/test/TestHandler.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 test; import java.util.HashMap; diff --git a/lib/py/src/TSerialization.py b/lib/py/src/TSerialization.py index 8ec703db7d3..b19f98aa8a9 100644 --- a/lib/py/src/TSerialization.py +++ b/lib/py/src/TSerialization.py @@ -1,3 +1,22 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + from protocol import TBinaryProtocol from transport import TTransport From d08e3021af3e673cda5f5abd89a3aab1db98657c Mon Sep 17 00:00:00 2001 From: David Reiss Date: Thu, 24 Jun 2010 17:04:46 +0000 Subject: [PATCH 008/756] Renaming release 0.3.0 branch "0.3.x" to match convention git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.x@957631 13f79535-47bb-0310-9956-ffa450edef68 From b8ca398d5f4bb2c0f775e415004785afb4026ba2 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Fri, 23 Jul 2010 21:22:40 +0000 Subject: [PATCH 009/756] add apache license to TFieldIdEnum.java git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.x@967267 13f79535-47bb-0310-9956-ffa450edef68 --- .../src/org/apache/thrift/TFieldIdEnum.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/java/src/org/apache/thrift/TFieldIdEnum.java b/lib/java/src/org/apache/thrift/TFieldIdEnum.java index 6bcc9f23339..2956fba0bc9 100644 --- a/lib/java/src/org/apache/thrift/TFieldIdEnum.java +++ b/lib/java/src/org/apache/thrift/TFieldIdEnum.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift; /** From 15c9877f7b29748099a983728687acecdf8f0206 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Fri, 23 Jul 2010 21:24:04 +0000 Subject: [PATCH 010/756] add apache license header to TestTBinaryProtocol.java git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.x@967268 13f79535-47bb-0310-9956-ffa450edef68 --- .../thrift/protocol/TestTBinaryProtocol.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/java/test/org/apache/thrift/protocol/TestTBinaryProtocol.java b/lib/java/test/org/apache/thrift/protocol/TestTBinaryProtocol.java index aff1492e143..0cfd9377af2 100644 --- a/lib/java/test/org/apache/thrift/protocol/TestTBinaryProtocol.java +++ b/lib/java/test/org/apache/thrift/protocol/TestTBinaryProtocol.java @@ -1,5 +1,23 @@ -package org.apache.thrift.protocol; +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift.protocol; public class TestTBinaryProtocol extends ProtocolTestBase { @Override From fb3e1475de6279c3c061a6faccff410d7fde1834 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Mon, 26 Jul 2010 17:12:42 +0000 Subject: [PATCH 011/756] add some more missing licenses git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.x@979364 13f79535-47bb-0310-9956-ffa450edef68 --- lib/as3/src/org/apache/thrift/Set.as | 19 ++++++++++++++++++ .../ThriftMSBuildTask.csproj | 20 ++++++++++++++++++- lib/csharp/src/Thrift.csproj | 20 ++++++++++++++++++- lib/js/test/test.html | 19 ++++++++++++++++++ 4 files changed, 76 insertions(+), 2 deletions(-) diff --git a/lib/as3/src/org/apache/thrift/Set.as b/lib/as3/src/org/apache/thrift/Set.as index bc329e4ac97..ae5f428437d 100644 --- a/lib/as3/src/org/apache/thrift/Set.as +++ b/lib/as3/src/org/apache/thrift/Set.as @@ -1,3 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift { import flash.utils.Dictionary; diff --git a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj index d8212422753..15ccb7f0e9c 100644 --- a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj +++ b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj @@ -1,4 +1,22 @@ - + + Debug diff --git a/lib/csharp/src/Thrift.csproj b/lib/csharp/src/Thrift.csproj index b7e21088880..ad88f082d8b 100644 --- a/lib/csharp/src/Thrift.csproj +++ b/lib/csharp/src/Thrift.csproj @@ -1,4 +1,22 @@ - + + Debug AnyCPU diff --git a/lib/js/test/test.html b/lib/js/test/test.html index 903ea40189b..57563caed39 100644 --- a/lib/js/test/test.html +++ b/lib/js/test/test.html @@ -1,3 +1,22 @@ + + Thrift Javascript Bindings - Example From dcdd550419fccbf9e95cc3da371129278b5ecd24 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Wed, 28 Jul 2010 18:22:02 +0000 Subject: [PATCH 012/756] add ASL to handful of files git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.x@980144 13f79535-47bb-0310-9956-ffa450edef68 --- lib/hs/Thrift.cabal | 19 +++++++++++++++++++ lib/ocaml/README-OCamlMakefile | 3 +++ test/csharp/ThriftTest/ThriftTest.csproj | 19 +++++++++++++++++++ tutorial/hs/ThriftTutorial.cabal | 19 +++++++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/lib/hs/Thrift.cabal b/lib/hs/Thrift.cabal index 8132069b740..feb2e816e1b 100644 --- a/lib/hs/Thrift.cabal +++ b/lib/hs/Thrift.cabal @@ -1,3 +1,22 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. +-- + Name: Thrift Version: 0.1.1 Cabal-Version: >= 1.2 diff --git a/lib/ocaml/README-OCamlMakefile b/lib/ocaml/README-OCamlMakefile index 54787b967ea..0a97c64ff1d 100644 --- a/lib/ocaml/README-OCamlMakefile +++ b/lib/ocaml/README-OCamlMakefile @@ -1,3 +1,6 @@ +NOTE (bryanduxbury): OCamlMakefile is safe to include in the project after +https://issues.apache.org/jira/browse/LEGAL-58. + --------------------------------------------------------------------------- Distribution of "ocaml_make" diff --git a/test/csharp/ThriftTest/ThriftTest.csproj b/test/csharp/ThriftTest/ThriftTest.csproj index bb7f1765d94..a55583ab611 100644 --- a/test/csharp/ThriftTest/ThriftTest.csproj +++ b/test/csharp/ThriftTest/ThriftTest.csproj @@ -1,3 +1,22 @@ + + diff --git a/tutorial/hs/ThriftTutorial.cabal b/tutorial/hs/ThriftTutorial.cabal index 381f32a7573..1655ce7cd88 100644 --- a/tutorial/hs/ThriftTutorial.cabal +++ b/tutorial/hs/ThriftTutorial.cabal @@ -1,3 +1,22 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. +-- + Name: ThriftTutorial Version: 0.1.0 Cabal-Version: >= 1.2 From 51d1a50e62d1f60b272c777f03791a3554f35573 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Wed, 28 Jul 2010 19:04:25 +0000 Subject: [PATCH 013/756] Add ASL to Thrift.sln git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.x@980161 13f79535-47bb-0310-9956-ffa450edef68 --- lib/csharp/src/Thrift.sln | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/csharp/src/Thrift.sln b/lib/csharp/src/Thrift.sln index c4cdad80290..295537996a2 100644 --- a/lib/csharp/src/Thrift.sln +++ b/lib/csharp/src/Thrift.sln @@ -1,4 +1,22 @@ - +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + + Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift", "Thrift.csproj", "{499EB63C-D74C-47E8-AE48-A2FC94538E9D}" From 04345ad4f0cca9dd7c15954a1a54239f030bc7ba Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Wed, 28 Jul 2010 19:07:57 +0000 Subject: [PATCH 014/756] add rat_exclude file that contains patterns RAT should ignore git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.x@980164 13f79535-47bb-0310-9956-ffa450edef68 --- rat_exclude | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 rat_exclude diff --git a/rat_exclude b/rat_exclude new file mode 100644 index 00000000000..e0cced52f44 --- /dev/null +++ b/rat_exclude @@ -0,0 +1,34 @@ +.gitignore +CHANGES +CONTRIBUTORS +autoscan.log +config.guess +config.log +config.status +config.sub +configure +configure.scan +depcomp +install-sh +libtool +ltmain.sh +missing +stamp-h1 +ylwrap +*.m4 +autom4te.cache +thrifty.h +version.h +version.h.in +md5.c +md5.h +doc +lib/erl/vsn.mk +/lib/erl/build/**/* +lib/erl/src/Makefile +thrift.appup.src +OCamlMakefile +README-OCamlMakefile +TODO +Manifest +setup.rb From 4d8815037c091866e7275aa3f55844dbcae3db41 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Wed, 28 Jul 2010 19:13:12 +0000 Subject: [PATCH 015/756] Fix the NOTICE file git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.3.x@980167 13f79535-47bb-0310-9956-ffa450edef68 --- NOTICE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE b/NOTICE index dfd164e61b3..1ec63dc86e0 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache Thrift -Copyright 2006-2009 The Apache Software Foundation, et al. +Copyright 2008-2010 The Apache Software Foundation. This product includes software developed at The Apache Software Foundation (http://www.apache.org/). From 088e42e8501bb91e55937bcf7a80c57f98f66f87 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Fri, 13 Aug 2010 00:21:06 +0000 Subject: [PATCH 016/756] branching to prep 0.4 for release git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.4.x@985051 13f79535-47bb-0310-9956-ffa450edef68 From d26ef49c90ee94a140ebdf692b54158b8b249389 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Fri, 13 Aug 2010 02:50:02 +0000 Subject: [PATCH 017/756] THRIFT-247. Commit files missing from r985031 git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.4.x@985076 13f79535-47bb-0310-9956-ffa450edef68 --- lib/cpp/src/transport/THttpServer.cpp | 122 +++++++++++ lib/cpp/src/transport/THttpServer.h | 64 ++++++ lib/cpp/src/transport/THttpTransport.cpp | 251 +++++++++++++++++++++++ lib/cpp/src/transport/THttpTransport.h | 106 ++++++++++ 4 files changed, 543 insertions(+) create mode 100644 lib/cpp/src/transport/THttpServer.cpp create mode 100644 lib/cpp/src/transport/THttpServer.h create mode 100644 lib/cpp/src/transport/THttpTransport.cpp create mode 100644 lib/cpp/src/transport/THttpTransport.h diff --git a/lib/cpp/src/transport/THttpServer.cpp b/lib/cpp/src/transport/THttpServer.cpp new file mode 100644 index 00000000000..3ed869a35d1 --- /dev/null +++ b/lib/cpp/src/transport/THttpServer.cpp @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include + +#include +#include + +namespace apache { namespace thrift { namespace transport { + +using namespace std; + +THttpServer::THttpServer(boost::shared_ptr transport) : + THttpTransport(transport) { +} + +THttpServer::~THttpServer() {} + +void THttpServer::parseHeader(char* header) { + char* colon = strchr(header, ':'); + if (colon == NULL) { + return; + } + uint32_t sz = colon - header; + char* value = colon+1; + + if (strncmp(header, "Transfer-Encoding", sz) == 0) { + if (strstr(value, "chunked") != NULL) { + chunked_ = true; + } + } else if (strncmp(header, "Content-Length", sz) == 0) { + chunked_ = false; + contentLength_ = atoi(value); + } +} + +bool THttpServer::parseStatusLine(char* status) { + char* method = status; + + char* path = strchr(method, ' '); + if (path == NULL) { + throw TTransportException(string("Bad Status: ") + status); + } + + *path = '\0'; + while (*(++path) == ' '); + + char* http = strchr(path, ' '); + if (http == NULL) { + throw TTransportException(string("Bad Status: ") + status); + } + *http = '\0'; + + if (strcmp(method, "POST") == 0) { + // POST method ok, looking for content. + return true; + } + throw TTransportException(string("Bad Status (unsupported method): ") + status); +} + +void THttpServer::flush() { + // Fetch the contents of the write buffer + uint8_t* buf; + uint32_t len; + writeBuffer_.getBuffer(&buf, &len); + + // Construct the HTTP header + std::ostringstream h; + h << + "HTTP/1.1 200 OK" << CRLF << + "Date: " << getTimeRFC1123() << CRLF << + "Server: Thrift/" << VERSION << CRLF << + "Content-Type: application/x-thrift" << CRLF << + "Content-Length: " << len << CRLF << + "Connection: Keep-Alive" << CRLF << + CRLF; + string header = h.str(); + + // Write the header, then the data, then flush + transport_->write((const uint8_t*)header.c_str(), header.size()); + transport_->write(buf, len); + transport_->flush(); + + // Reset the buffer and header variables + writeBuffer_.resetBuffer(); + readHeaders_ = true; +} + +std::string THttpServer::getTimeRFC1123() +{ + static const char* Days[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; + static const char* Months[] = {"Jan","Feb","Mar", "Apr", "May", "Jun", "Jul","Aug", "Sep", "Oct","Nov","Dec"}; + char buff[128]; + time_t t = time(NULL); + tm* broken_t = gmtime(&t); + + sprintf(buff,"%s, %d %s %d %d:%d:%d GMT", + Days[broken_t->tm_wday], broken_t->tm_mday, Months[broken_t->tm_mon], + broken_t->tm_year + 1900, + broken_t->tm_hour,broken_t->tm_min,broken_t->tm_sec); + return std::string(buff); +} + +}}} // apache::thrift::transport diff --git a/lib/cpp/src/transport/THttpServer.h b/lib/cpp/src/transport/THttpServer.h new file mode 100644 index 00000000000..65234084a90 --- /dev/null +++ b/lib/cpp/src/transport/THttpServer.h @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_THTTPSERVER_H_ +#define _THRIFT_TRANSPORT_THTTPSERVER_H_ 1 + +#include + +namespace apache { namespace thrift { namespace transport { + +class THttpServer : public THttpTransport { + public: + THttpServer(boost::shared_ptr transport); + + virtual ~THttpServer(); + + virtual void flush(); + + protected: + + void readHeaders(); + virtual void parseHeader(char* header); + virtual bool parseStatusLine(char* status); + std::string getTimeRFC1123(); + +}; + +/** + * Wraps a transport into HTTP protocol + */ +class THttpServerTransportFactory : public TTransportFactory { + public: + THttpServerTransportFactory() {} + + virtual ~THttpServerTransportFactory() {} + + /** + * Wraps the transport into a buffered one. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return boost::shared_ptr(new THttpServer(trans)); + } + +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_THTTPSERVER_H_ diff --git a/lib/cpp/src/transport/THttpTransport.cpp b/lib/cpp/src/transport/THttpTransport.cpp new file mode 100644 index 00000000000..4010d6b8920 --- /dev/null +++ b/lib/cpp/src/transport/THttpTransport.cpp @@ -0,0 +1,251 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +namespace apache { namespace thrift { namespace transport { + +using namespace std; + +// Yeah, yeah, hacky to put these here, I know. +const char* THttpTransport::CRLF = "\r\n"; +const int THttpTransport::CRLF_LEN = 2; + +THttpTransport::THttpTransport(boost::shared_ptr transport) : + transport_(transport), + readHeaders_(true), + chunked_(false), + chunkedDone_(false), + chunkSize_(0), + contentLength_(0), + httpBuf_(NULL), + httpPos_(0), + httpBufLen_(0), + httpBufSize_(1024) { + init(); +} + +void THttpTransport::init() { + httpBuf_ = (char*)std::malloc(httpBufSize_+1); + if (httpBuf_ == NULL) { + throw TTransportException("Out of memory."); + } + httpBuf_[httpBufLen_] = '\0'; +} + +THttpTransport::~THttpTransport() { + if (httpBuf_ != NULL) { + std::free(httpBuf_); + } +} + +uint32_t THttpTransport::read(uint8_t* buf, uint32_t len) { + if (readBuffer_.available_read() == 0) { + readBuffer_.resetBuffer(); + uint32_t got = readMoreData(); + if (got == 0) { + return 0; + } + } + return readBuffer_.read(buf, len); +} + +void THttpTransport::readEnd() { + // Read any pending chunked data (footers etc.) + if (chunked_) { + while (!chunkedDone_) { + readChunked(); + } + } +} + +uint32_t THttpTransport::readMoreData() { + uint32_t size; + + // Get more data! + refill(); + + if (readHeaders_) { + readHeaders(); + } + + if (chunked_) { + size = readChunked(); + } else { + size = readContent(contentLength_); + } + readHeaders_ = true; + return size; +} + +uint32_t THttpTransport::readChunked() { + uint32_t length = 0; + + char* line = readLine(); + uint32_t chunkSize = parseChunkSize(line); + if (chunkSize == 0) { + readChunkedFooters(); + } else { + // Read data content + length += readContent(chunkSize); + // Read trailing CRLF after content + readLine(); + } + return length; +} + +void THttpTransport::readChunkedFooters() { + // End of data, read footer lines until a blank one appears + while (true) { + char* line = readLine(); + if (strlen(line) == 0) { + chunkedDone_ = true; + break; + } + } +} + +uint32_t THttpTransport::parseChunkSize(char* line) { + char* semi = strchr(line, ';'); + if (semi != NULL) { + *semi = '\0'; + } + int size = 0; + sscanf(line, "%x", &size); + return (uint32_t)size; +} + +uint32_t THttpTransport::readContent(uint32_t size) { + uint32_t need = size; + while (need > 0) { + uint32_t avail = httpBufLen_ - httpPos_; + if (avail == 0) { + // We have given all the data, reset position to head of the buffer + httpPos_ = 0; + httpBufLen_ = 0; + refill(); + + // Now have available however much we read + avail = httpBufLen_; + } + uint32_t give = avail; + if (need < give) { + give = need; + } + readBuffer_.write((uint8_t*)(httpBuf_+httpPos_), give); + httpPos_ += give; + need -= give; + } + return size; +} + +char* THttpTransport::readLine() { + while (true) { + char* eol = NULL; + + eol = strstr(httpBuf_+httpPos_, CRLF); + + // No CRLF yet? + if (eol == NULL) { + // Shift whatever we have now to front and refill + shift(); + refill(); + } else { + // Return pointer to next line + *eol = '\0'; + char* line = httpBuf_+httpPos_; + httpPos_ = (eol-httpBuf_) + CRLF_LEN; + return line; + } + } + +} + +void THttpTransport::shift() { + if (httpBufLen_ > httpPos_) { + // Shift down remaining data and read more + uint32_t length = httpBufLen_ - httpPos_; + memmove(httpBuf_, httpBuf_+httpPos_, length); + httpBufLen_ = length; + } else { + httpBufLen_ = 0; + } + httpPos_ = 0; + httpBuf_[httpBufLen_] = '\0'; +} + +void THttpTransport::refill() { + uint32_t avail = httpBufSize_ - httpBufLen_; + if (avail <= (httpBufSize_ / 4)) { + httpBufSize_ *= 2; + httpBuf_ = (char*)std::realloc(httpBuf_, httpBufSize_+1); + if (httpBuf_ == NULL) { + throw TTransportException("Out of memory."); + } + } + + // Read more data + uint32_t got = transport_->read((uint8_t*)(httpBuf_+httpBufLen_), httpBufSize_-httpBufLen_); + httpBufLen_ += got; + httpBuf_[httpBufLen_] = '\0'; + + if (got == 0) { + throw TTransportException("Could not refill buffer"); + } +} + +void THttpTransport::readHeaders() { + // Initialize headers state variables + contentLength_ = 0; + chunked_ = false; + chunkedDone_ = false; + chunkSize_ = 0; + + // Control state flow + bool statusLine = true; + bool finished = false; + + // Loop until headers are finished + while (true) { + char* line = readLine(); + + if (strlen(line) == 0) { + if (finished) { + readHeaders_ = false; + return; + } else { + // Must have been an HTTP 100, keep going for another status line + statusLine = true; + } + } else { + if (statusLine) { + statusLine = false; + finished = parseStatusLine(line); + } else { + parseHeader(line); + } + } + } +} + +void THttpTransport::write(const uint8_t* buf, uint32_t len) { + writeBuffer_.write(buf, len); +} + +}}} diff --git a/lib/cpp/src/transport/THttpTransport.h b/lib/cpp/src/transport/THttpTransport.h new file mode 100644 index 00000000000..e71dcbd1360 --- /dev/null +++ b/lib/cpp/src/transport/THttpTransport.h @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_THTTPTRANSPORT_H_ +#define _THRIFT_TRANSPORT_THTTPTRANSPORT_H_ 1 + +#include + +namespace apache { namespace thrift { namespace transport { + +/** + * HTTP implementation of the thrift transport. This was irritating + * to write, but the alternatives in C++ land are daunting. Linking CURL + * requires 23 dynamic libraries last time I checked (WTF?!?). All we have + * here is a VERY basic HTTP/1.1 client which supports HTTP 100 Continue, + * chunked transfer encoding, keepalive, etc. Tested against Apache. + */ +class THttpTransport : public TTransport { + public: + THttpTransport(boost::shared_ptr transport); + + virtual ~THttpTransport(); + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + return transport_->peek(); + } + + void close() { + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void readEnd(); + + void write(const uint8_t* buf, uint32_t len); + + virtual void flush() = 0; + + protected: + + boost::shared_ptr transport_; + + TMemoryBuffer writeBuffer_; + TMemoryBuffer readBuffer_; + + bool readHeaders_; + bool chunked_; + bool chunkedDone_; + uint32_t chunkSize_; + uint32_t contentLength_; + + char* httpBuf_; + uint32_t httpPos_; + uint32_t httpBufLen_; + uint32_t httpBufSize_; + + virtual void init(); + + uint32_t readMoreData(); + char* readLine(); + + void readHeaders(); + virtual void parseHeader(char* header) = 0; + virtual bool parseStatusLine(char* status) = 0; + + uint32_t readChunked(); + void readChunkedFooters(); + uint32_t parseChunkSize(char* line); + + uint32_t readContent(uint32_t size); + + void refill(); + void shift(); + + static const char* CRLF; + static const int CRLF_LEN; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_ From 2acb33cf4149306204286ac222243c86634f3392 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Fri, 13 Aug 2010 02:50:56 +0000 Subject: [PATCH 018/756] change version in configure.ac from 0.4.0-dev to 0.4.0 git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.4.x@985077 13f79535-47bb-0310-9956-ffa450edef68 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f6a8a0d3e86..6ff43caa9c2 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.59) -AC_INIT([thrift], [0.4.0-dev]) +AC_INIT([thrift], [0.4.0]) AC_CONFIG_AUX_DIR([.]) From 38e1ba3f8dca5cb7a9c4c6bedcbe6bb31dc4ccae Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Fri, 13 Aug 2010 04:28:04 +0000 Subject: [PATCH 019/756] update the changes file git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.4.x@985087 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/CHANGES b/CHANGES index e4d81933de3..2c2f3f8a4f2 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,54 @@ Thrift Changelog +Version 0.4.0 + +THRIFT-650 Build Make Check fails on Centos/OSX with 0.2.0 tarball (Anthony Molinaro) +THRIFT-770 Build Get 'make dist' to work without first compiling source code (Anthony Molinaro) +THRIFT-160 C# Created THttpTransport for the C# library based on WebHttpRequest (Michael Greene) +THRIFT-834 C# THttpClient resends contents of message after transport errors (Anatoly Fayngelerin) +THRIFT-247 C++ THttpServer Transport (Unassigned) +THRIFT-676 C++ Change C++ code generator so that generated classes can be wrapped with SWIG (Unassigned) +THRIFT-570 Compiler Thrift compiler does not error when duplicate method names are present (Bruce Simpson) +THRIFT-808 Compiler Segfault when constant declaration references a struct field that doesn't exist (Bryan Duxbury) +THRIFT-646 Erlang Erlang library is missing install target (Anthony Molinaro) +THRIFT-544 General multiple enums with the same key generate invalid code (Ben Taitelbaum) +THRIFT-434 General ruby compiler should warn when a reserved word is used (Michael Stockton) +THRIFT-799 General Files missing proper Apache license header (Bryan Duxbury) +THRIFT-832 HTML HTML generator shows unspecified struct fields as 'required' (Bryan Duxbury) +THRIFT-226 Java Collections with binary keys or values break equals() (Bryan Duxbury) +THRIFT-484 Java Ability to use a slice of a buffer instead of a direct byte[] for binary fields (Bryan Duxbury) +THRIFT-714 Java maxWorkerThreads parameter to THsHaServer has no effect (Bryan Duxbury) +THRIFT-751 Java Add clear() method to TBase (Bryan Duxbury) +THRIFT-765 Java Improved string encoding and decoding performance (Bryan Duxbury) +THRIFT-768 Java Async client for Java (Bryan Duxbury) +THRIFT-774 Java TDeserializer should provide a partialDeserialize method for primitive types (Piotr Kozikowski) +THRIFT-783 Java .equals java method is broken on structs containing binary-type fields (Unassigned) +THRIFT-804 Java CompareTo is broken for unions set to map, set, or list (Bryan Duxbury) +THRIFT-814 Java Include a TServlet in the standard Thrift distribution (Mathias Herberts) +THRIFT-818 Java Async client doesn't send method args (Bryan Duxbury) +THRIFT-830 Java Switch binary field implementation from byte[] to ByteBuffer (Bryan Duxbury) +THRIFT-831 Java FramedTransport implementation that reuses its buffers (Bryan Duxbury) +THRIFT-833 Java build.xml in lib/java is missing a classpathref attribute for the javadoc task (Bryan Duxbury) +THRIFT-836 Java Race condition causes CancelledKeyException in TAsyncClientManager (Bryan Duxbury) +THRIFT-842 Java Upgrade to current version of commons-lang (2.5 instead of 2.4) and/or change dependency in ivy.xml to not be exact (Bryan Duxbury) +THRIFT-815 JavaScript Deserialization of lists is critically broken. (T Jake Luciani) +THRIFT-827 OCaml OCaml generator to take default values into account (Lev Walkin) +THRIFT-647 PHP PHP library is missing install target (Anthony Molinaro) +THRIFT-682 PHP PHP extension doesn't compile on Mac OS X (Bryan Duxbury) +THRIFT-718 PHP Thrift PHP library includes closing tags and extraneous whitespace (Nicholas Telford) +THRIFT-778 PHP PHP socket listening server (Nick Jones) +THRIFT-780 PHP PHP extension sometimes causes an abort with two exceptions at the same time (David Reiss) +THRIFT-837 PHP PHP accelerator bug for writes > 8k (Thomas Kho) +THRIFT-782 Perl Perl code for writing containers doesn't count length of write*Begin or write*End (Conrad Hughes) +THRIFT-395 Python Python library + compiler does not support unicode strings (Unassigned) +THRIFT-133 Ruby 'namespace ruby' should error out, or be an alias to 'namespace rb' (Bryan Duxbury) +THRIFT-664 Ruby Ruby extension fails to build with Ruby 1.9.1 (Rajesh Malepati) +THRIFT-699 Ruby Excise unused "native protocol method table" stuff from thrift_native (Bryan Duxbury) +THRIFT-767 Ruby ruby compiler does not keep comments for enum values (Bryan Duxbury) +THRIFT-811 Ruby http_client_transport.rb: allow custom http headers (Tony Kamenick) +THRIFT-459 Ruby Ruby installation always tries to write to /Library/Ruby/site (Matthieu Imbert) + + Version 0.1.0 RC1 / Unreleased Compatibility Breaking Changes: From 48fa172d34b2e389b4316301bf67198b2ac715e9 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Sun, 15 Aug 2010 21:10:22 +0000 Subject: [PATCH 020/756] Update the NOTICE file git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.4.x@985759 13f79535-47bb-0310-9956-ffa450edef68 --- NOTICE | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/NOTICE b/NOTICE index dfd164e61b3..c23995a2315 100644 --- a/NOTICE +++ b/NOTICE @@ -1,6 +1,5 @@ Apache Thrift -Copyright 2006-2009 The Apache Software Foundation, et al. +Copyright 2006-2010 The Apache Software Foundation. This product includes software developed at -The Apache Software Foundation (http://www.apache.org/). - +The Apache Software Foundation (http://www.apache.org/). \ No newline at end of file From 0c4f88a9533ac99d8101fb97f9b22f0d5c22cb9a Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Mon, 16 Aug 2010 17:08:03 +0000 Subject: [PATCH 021/756] revert THRIFT-682, since it doesn't build anywhere, apparently. git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.4.x@986051 13f79535-47bb-0310-9956-ffa450edef68 --- .../ext/thrift_protocol/php_thrift_protocol.cpp | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp index 193669bba09..641fff2e66d 100644 --- a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp +++ b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp @@ -24,23 +24,10 @@ #include #include #include -#include -#include +#include +#include #include -#ifndef _BYTESWAP_H -#define _BYTESWAP_H - -#define bswap_64(x) (((uint64_t)(x) << 56) | \ - (((uint64_t)(x) << 40) & 0xff000000000000ULL) | \ - (((uint64_t)(x) << 24) & 0xff0000000000ULL) | \ - (((uint64_t)(x) << 8) & 0xff00000000ULL) | \ - (((uint64_t)(x) >> 8) & 0xff000000ULL) | \ - (((uint64_t)(x) >> 24) & 0xff0000ULL) | \ - (((uint64_t)(x) >> 40) & 0xff00ULL) | \ - ((uint64_t)(x) >> 56)) -#endif - #if __BYTE_ORDER == __LITTLE_ENDIAN #define htonll(x) bswap_64(x) #define ntohll(x) bswap_64(x) From 51099cca62c3fbe6c75a22cb49b78ace48f599d7 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Tue, 28 Sep 2010 16:06:42 +0000 Subject: [PATCH 022/756] Branching trunk to 0.5.x to prepare for release. git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.5.x@1002237 13f79535-47bb-0310-9956-ffa450edef68 From 0b483e11ef179c1480b3e61039f62cb72d82e9b3 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Tue, 28 Sep 2010 17:38:19 +0000 Subject: [PATCH 023/756] fix version and rubygem version git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.5.x@1002285 13f79535-47bb-0310-9956-ffa450edef68 --- configure.ac | 2 +- lib/rb/Rakefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 28c21238f87..e2185176913 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.65) -AC_INIT([thrift], [0.5.0-dev]) +AC_INIT([thrift], [0.5.0]) AC_CONFIG_AUX_DIR([.]) diff --git a/lib/rb/Rakefile b/lib/rb/Rakefile index 10383e7183a..e6f9a94ab93 100644 --- a/lib/rb/Rakefile +++ b/lib/rb/Rakefile @@ -82,7 +82,7 @@ begin p.summary = "Ruby libraries for Thrift (a language-agnostic RPC system)" p.url = "http://incubator.apache.org/thrift/" p.include_rakefile = true - p.version = "0.2.5" + p.version = "0.5.0" p.rubygems_version = ">= 1.2.0" end From 7f7795d0d2a025d4f75d4ae348bbc59600d9345f Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Thu, 30 Sep 2010 19:37:01 +0000 Subject: [PATCH 024/756] THRIFT-939. java: optional binary fields throw NPE on default byte[] getters This patch deals with null ByteBuffers correctly. git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/branches/0.5.x@1003215 13f79535-47bb-0310-9956-ffa450edef68 --- lib/java/src/org/apache/thrift/TBaseHelper.java | 7 +++++++ lib/java/test/org/apache/thrift/TestTBaseHelper.java | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/lib/java/src/org/apache/thrift/TBaseHelper.java b/lib/java/src/org/apache/thrift/TBaseHelper.java index 211ea620631..2837d0b5357 100644 --- a/lib/java/src/org/apache/thrift/TBaseHelper.java +++ b/lib/java/src/org/apache/thrift/TBaseHelper.java @@ -277,6 +277,9 @@ public static ByteBuffer rightSize(ByteBuffer 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()); @@ -288,6 +291,10 @@ public static ByteBuffer copyBinary(final ByteBuffer orig) { } 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; diff --git a/lib/java/test/org/apache/thrift/TestTBaseHelper.java b/lib/java/test/org/apache/thrift/TestTBaseHelper.java index a66e7892313..6d72ad84ce6 100644 --- a/lib/java/test/org/apache/thrift/TestTBaseHelper.java +++ b/lib/java/test/org/apache/thrift/TestTBaseHelper.java @@ -173,6 +173,8 @@ public void testCopyBinaryWithByteBuffer() throws Exception { assertEquals(1, b.position()); b.reset(); assertEquals(0, b.position()); + + assertNull(TBaseHelper.copyBinary((ByteBuffer)null)); } public void testCopyBinaryWithByteArray() throws Exception { @@ -180,5 +182,7 @@ public void testCopyBinaryWithByteArray() throws Exception { byte[] copy = TBaseHelper.copyBinary(bytes); assertEquals(ByteBuffer.wrap(bytes), ByteBuffer.wrap(copy)); assertNotSame(bytes, copy); + + assertNull(TBaseHelper.copyBinary((byte[])null)); } } From e76f2264b50a576fc2c339548fc2522c15f14f45 Mon Sep 17 00:00:00 2001 From: Gavin McDonald Date: Thu, 28 Oct 2010 02:12:01 +0000 Subject: [PATCH 025/756] Thrift now a TLP - INFRA-3116 git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.2.x@1028168 13f79535-47bb-0310-9956-ffa450edef68 From 2f5e7760c7973a4675f1372be43540f9179a3521 Mon Sep 17 00:00:00 2001 From: Gavin McDonald Date: Thu, 28 Oct 2010 02:12:01 +0000 Subject: [PATCH 026/756] Thrift now a TLP - INFRA-3116 git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.3.x@1028168 13f79535-47bb-0310-9956-ffa450edef68 From 1b7729f71e76af446d8d0119f67a51c4718e1f3b Mon Sep 17 00:00:00 2001 From: Gavin McDonald Date: Thu, 28 Oct 2010 02:12:01 +0000 Subject: [PATCH 027/756] Thrift now a TLP - INFRA-3116 git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.4.x@1028168 13f79535-47bb-0310-9956-ffa450edef68 From e25771d4c29a398ba5d23b447a37d15ab77e7f42 Mon Sep 17 00:00:00 2001 From: Gavin McDonald Date: Thu, 28 Oct 2010 02:12:01 +0000 Subject: [PATCH 028/756] Thrift now a TLP - INFRA-3116 git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.5.x@1028168 13f79535-47bb-0310-9956-ffa450edef68 From 981240d11e82b63529b7680b175bed35a95b93b4 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Fri, 7 Jan 2011 18:24:38 +0000 Subject: [PATCH 029/756] branch for the 0.6 release candidate git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1056441 13f79535-47bb-0310-9956-ffa450edef68 From 68a59b2acb300451bea53da0245e4251a124c502 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Fri, 7 Jan 2011 18:41:20 +0000 Subject: [PATCH 030/756] merge in changes to CHANGES file git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1056450 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/CHANGES b/CHANGES index 26872ddfd35..078643b2f82 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,67 @@ Thrift Changelog +Version 0.6.0 + +THRIFT-940 Build 'make check' fails if boost is not in the std include and link paths (Christian Lavoie) +THRIFT-1002 C glib CodeStyle: t_c_glib_generator.cc (Anatol Pomozov) +THRIFT-975 C glib lib/c_glib/README is missing => breaks make dist (Michael Lum) +THRIFT-1003 C glib Polishing c_glib code (Anatol Pomozov) +THRIFT-582 C glib C implementation of Thrift (Anatol Pomozov) +THRIFT-992 C# Naming convention in C# constructor is not consistent with other fields causes compile errors (Roger Meier) +THRIFT-977 C++ Hex Conversion Bug in C++ TJSONProtocol (Aravind Narayanan) +THRIFT-922 C++ Templatized [de]serialization code for C++ (David Reiss) +THRIFT-923 C++ Event-driven client and server support for C++ (David Reiss) +THRIFT-925 C++ Provide name<->value map for enums in C++ (David Reiss) +THRIFT-926 C++ Miscellaneous C++ improvements (David Reiss) +THRIFT-928 C++ Make more statistics available in C++ servers (David Reiss) +THRIFT-929 C++ Improvements to the C++ test suite (David Reiss) +THRIFT-868 Compiler (General) Referencing constant values doesn't work with with typedef types (David Reiss) +THRIFT-1006 General Impossible to correctly qualify an enum constant in an external thrift file (Bryan Duxbury) +THRIFT-932 Haskell Haskell tests need to be run through 'make check' (and probably 'cabal check') too (Christian Lavoie) +THRIFT-933 Haskell Haskell's Thrift.cabal has warnings (Christian Lavoie) +THRIFT-943 Haskell Silly readme typo fix. (Christian Lavoie) +THRIFT-944 Haskell Support all version-4s of base (Christian Lavoie) +THRIFT-950 Haskell Haskell bindings treat 'byte' as unsigned 8-bit int (Data.Word.Word8), java/cpp as signed (byte/int8_t). (Christian Lavoie) +THRIFT-1009 Java TUnion does not correctly deep copy a ByteBuffer (Takashi Yonebayashi) +THRIFT-1013 Java generated java code may have name clashes with thrift library (Peter Schuller) +THRIFT-1015 Java TUnion does not handle ByteBuffer in toString (Takashi Yonebayashi) +THRIFT-106 Java TSSLServerSocket (Nirmal Ranganathan) +THRIFT-377 Java TFileTransport port in Java (Joydeep Sen Sarma) +THRIFT-745 Java Make it easier to instantiate servers (Bryan Duxbury) +THRIFT-862 Java Async client issues / improvements (Ning Liang) +THRIFT-903 Java custom ThreadFactory in THsHaServer (Bryan Duxbury) +THRIFT-939 Java optional binary fields throw NPE on default byte[] getters (Bryan Duxbury) +THRIFT-947 Java Provide a helper method to determine the TProtocol used to serialize some data. (Mathias Herberts) +THRIFT-951 Java Add a new isServing() method to TServer (Bryan Duxbury) +THRIFT-957 Java THsHaServer: Change access modifier of the invoker field. (Benjamin Coverston) +THRIFT-958 Java Change accessmodifer on trans_ field in the FrameBuffer class to public. (Benjamin Coverston) +THRIFT-959 Java TSocket seems to do its own buffering inefficiently (Bryan Duxbury) +THRIFT-970 Java Under heavy load, THttpClient may fail with "too many open files" (Mathias Herberts) +THRIFT-971 Java java module can't be compiled without ivy and network connection (Roger Meier) +THRIFT-807 JavaScript JavaScript: Initialization of Base Types with 0 instead of null (Roger Meier) +THRIFT-913 JavaScript Test Case for Url encoded strings + simple enhancement to lib/js/test/RunTestServer.sh (Roger Meier) +THRIFT-961 JavaScript JavaScript TestSuite using ant/ivy and Java's ServerTestBase Handler (Roger Meier) +THRIFT-1005 Java Give unions byte[] signature methods to go along with their ByteBuffer counterparts (Bryan Duxbury) +THRIFT-1008 Java byte[] accessors throw NPE on unset field (Bryan Duxbury) +THRIFT-517 Java TExceptions thrown by server result in cryptic error message on client - Tried to read 4 bytes, but only got 0 bytes (Bryan Duxbury) +THRIFT-946 Java Augment FieldValueMetaData so it differentiates 'string' and 'binary' fields. (Mathias Herberts) +THRIFT-949 Java Modify the TEnum interface so it defines a method similar to findByValue (Mathias Herberts) +THRIFT-960 Java add TestServer, TestNonblockingServer and TestClient again (Roger Meier) +THRIFT-969 Java Java Tutorial broken, move CalculatorHandler to a separate file (Roger Meier) +THRIFT-71 Misc Debian packaging for thrift (Roger Meier) +THRIFT-1020 OCaml OCaml compiler generates invalid OCaml (Richard Low) +THRIFT-347 PHP PHP TSocket Timeout Issues (Tyler Hobbs) +THRIFT-924 PHP Fix generated php structure constants (David Reiss) +THRIFT-927 PHP Add option to modify the PHP include path (David Reiss) +THRIFT-935 PHP PHP Extension aborts the build if php-config is not installed (David Reiss) +THRIFT-941 PHP Make PHP C Extension use the defined Protocol writeMessageBegin function (Chris Goffinet) +THRIFT-955 PHP Thrift compiler for Windows uses lowercase names and directories which is inconsistent with compiling on other platforms (Roger Meier) +THRIFT-979 Ruby ruby bindings used to work on jruby (Jeff Hodges) +THRIFT-581 Test Suite Add a testsuite for txThrift (Twisted) (Esteve Fernandez) +THRIFT-1024 Tutorial Add Python Twisted example to the Tutorial (Roger Meier) +THRIFT-893 Tutorial add JavaScript to the tutorial examples (Roger Meier) + + Version 0.5.0 THRIFT-505 Build Make configure give a summary of the enabled components (David Reiss) From e22ff6dbea0d2e667052a778ade4bd9341333f77 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Fri, 7 Jan 2011 18:46:50 +0000 Subject: [PATCH 031/756] chop the -dev off all version numbers git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1056454 13f79535-47bb-0310-9956-ffa450edef68 --- configure.ac | 2 +- lib/hs/Thrift.cabal | 2 +- lib/java/ivy.xml | 2 +- lib/py/setup.py | 2 +- lib/rb/Rakefile | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 1294c263b20..629a83c0328 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.65) -AC_INIT([thrift], [0.6.0-dev]) +AC_INIT([thrift], [0.6.0]) AC_CONFIG_AUX_DIR([.]) diff --git a/lib/hs/Thrift.cabal b/lib/hs/Thrift.cabal index 53a4be47d5c..34412f8f793 100644 --- a/lib/hs/Thrift.cabal +++ b/lib/hs/Thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 0.6.0-dev +Version: 0.6.0 Cabal-Version: >= 1.4 License: OtherLicense Category: Foreign diff --git a/lib/java/ivy.xml b/lib/java/ivy.xml index 99ef9729334..6225e4c173c 100644 --- a/lib/java/ivy.xml +++ b/lib/java/ivy.xml @@ -15,7 +15,7 @@ limitations under the License. --> - + diff --git a/lib/py/setup.py b/lib/py/setup.py index d3ae3588f24..289b177c1a1 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -26,7 +26,7 @@ ) setup(name = 'Thrift', - version = '0.6.0-dev', + version = '0.6.0', description = 'Python bindings for the Apache Thrift RPC system', author = ['Thrift Developers'], author_email = ['dev@thrift.apache.org'], diff --git a/lib/rb/Rakefile b/lib/rb/Rakefile index 05cb7fc0cb4..84d099e9115 100644 --- a/lib/rb/Rakefile +++ b/lib/rb/Rakefile @@ -82,7 +82,7 @@ begin p.summary = "Ruby bindings for the Apache Thrift RPC system" p.url = "http://thrift.apache.org" p.include_rakefile = true - p.version = "0.6.0-dev" + p.version = "0.6.0" p.rubygems_version = ">= 1.2.0" end From 5baba45df99d625ca682e8ecafb81400a6cb56c5 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Tue, 11 Jan 2011 19:23:24 +0000 Subject: [PATCH 032/756] update the changes file git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1057812 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 078643b2f82..ee585481960 100644 --- a/CHANGES +++ b/CHANGES @@ -38,9 +38,7 @@ THRIFT-958 Java Change accessmodifer on trans_ field in the F THRIFT-959 Java TSocket seems to do its own buffering inefficiently (Bryan Duxbury) THRIFT-970 Java Under heavy load, THttpClient may fail with "too many open files" (Mathias Herberts) THRIFT-971 Java java module can't be compiled without ivy and network connection (Roger Meier) -THRIFT-807 JavaScript JavaScript: Initialization of Base Types with 0 instead of null (Roger Meier) -THRIFT-913 JavaScript Test Case for Url encoded strings + simple enhancement to lib/js/test/RunTestServer.sh (Roger Meier) -THRIFT-961 JavaScript JavaScript TestSuite using ant/ivy and Java's ServerTestBase Handler (Roger Meier) + JavaScript TestSuite using ant/ivy and Java's ServerTestBase Handler (Roger Meier) THRIFT-1005 Java Give unions byte[] signature methods to go along with their ByteBuffer counterparts (Bryan Duxbury) THRIFT-1008 Java byte[] accessors throw NPE on unset field (Bryan Duxbury) THRIFT-517 Java TExceptions thrown by server result in cryptic error message on client - Tried to read 4 bytes, but only got 0 bytes (Bryan Duxbury) @@ -48,6 +46,10 @@ THRIFT-946 Java Augment FieldValueMetaData so it differentiat THRIFT-949 Java Modify the TEnum interface so it defines a method similar to findByValue (Mathias Herberts) THRIFT-960 Java add TestServer, TestNonblockingServer and TestClient again (Roger Meier) THRIFT-969 Java Java Tutorial broken, move CalculatorHandler to a separate file (Roger Meier) +THRIFT-807 JavaScript JavaScript: Initialization of Base Types with 0 instead of null (Roger Meier) +THRIFT-913 JavaScript Test Case for Url encoded strings + simple enhancement to lib/js/test/RunTestServer.sh (Roger Meier) +THRIFT-961 JavaScript +THRIFT-1033 JavaScript Node.js support THRIFT-71 Misc Debian packaging for thrift (Roger Meier) THRIFT-1020 OCaml OCaml compiler generates invalid OCaml (Richard Low) THRIFT-347 PHP PHP TSocket Timeout Issues (Tyler Hobbs) From eb1e6f7107bb2f861ad008ed77e276a1fda270cb Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Thu, 13 Jan 2011 18:10:18 +0000 Subject: [PATCH 033/756] THRIFT-1032. make dist fails due to c_glib problem Patch: Michael Lum git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1058693 13f79535-47bb-0310-9956-ffa450edef68 --- lib/c_glib/test/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/c_glib/test/Makefile.am b/lib/c_glib/test/Makefile.am index 96ec4f24a23..7f2f3e3f8fa 100644 --- a/lib/c_glib/test/Makefile.am +++ b/lib/c_glib/test/Makefile.am @@ -115,7 +115,7 @@ if WITH_CPP check_LTLIBRARIES += libtestgencpp.la endif -libtestgenc_la_SOURCES = \ +nodist_libtestgenc_la_SOURCES = \ gen-c_glib/t_test_debug_proto_test_types.c \ gen-c_glib/t_test_empty_service.c \ gen-c_glib/t_test_inherited.c \ @@ -138,7 +138,7 @@ libtestgenc_la_SOURCES = \ gen-c_glib/t_test_thrift_test_types.h libtestgenc_la_LIBADD = $(top_builddir)/lib/c_glib/libthrift_c_glib.la -libtestgencpp_la_SOURCES = \ +nodist_libtestgencpp_la_SOURCES = \ gen-cpp/ThriftTest.cpp \ gen-cpp/ThriftTest_constants.cpp \ gen-cpp/ThriftTest_types.cpp \ From 3d60f81ce1a7cde3a801888117e2cbbf5ee774e8 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Thu, 13 Jan 2011 18:11:49 +0000 Subject: [PATCH 034/756] update CHANGES file git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1058695 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index ee585481960..3130e6efb8a 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,7 @@ Thrift Changelog Version 0.6.0 THRIFT-940 Build 'make check' fails if boost is not in the std include and link paths (Christian Lavoie) +THRIFT-1032 Build "make dist" fails due to c_glib problem (Michael Lum) THRIFT-1002 C glib CodeStyle: t_c_glib_generator.cc (Anatol Pomozov) THRIFT-975 C glib lib/c_glib/README is missing => breaks make dist (Michael Lum) THRIFT-1003 C glib Polishing c_glib code (Anatol Pomozov) From 923e453be43ed31d2c32ed3af28581a3785a79b4 Mon Sep 17 00:00:00 2001 From: Christian Lavoie Date: Mon, 24 Jan 2011 23:01:37 +0000 Subject: [PATCH 035/756] Fix haskell-related bug in the 0.6.x branch for RC1; make sure trunk receives the same patch. git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1063050 13f79535-47bb-0310-9956-ffa450edef68 --- lib/hs/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/hs/Makefile.am b/lib/hs/Makefile.am index 95734f06ee8..3464a4fdd5e 100644 --- a/lib/hs/Makefile.am +++ b/lib/hs/Makefile.am @@ -18,6 +18,7 @@ # EXTRA_DIST = \ + LICENSE \ README \ Setup.lhs \ TODO \ From 38b6574865f2646b0b455ca0ceb2ff3ba83315ee Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Wed, 26 Jan 2011 22:46:04 +0000 Subject: [PATCH 036/756] THRIFT-1038. java: Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable This patch causes Java Serialized Thrift structs to be serialized onto the stream via the Compact Protocol. Patch: Mathias Herberts git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1063911 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 1 + compiler/cpp/src/generate/t_java_generator.cc | 40 +++++++++++++++++++ .../test/org/apache/thrift/TestStruct.java | 23 +++++++++++ .../test/org/apache/thrift/TestTUnion.java | 22 ++++++++++ 4 files changed, 86 insertions(+) diff --git a/CHANGES b/CHANGES index 3130e6efb8a..0609ca227cc 100644 --- a/CHANGES +++ b/CHANGES @@ -26,6 +26,7 @@ THRIFT-950 Haskell Haskell bindings treat 'byte' as unsigned 8-b THRIFT-1009 Java TUnion does not correctly deep copy a ByteBuffer (Takashi Yonebayashi) THRIFT-1013 Java generated java code may have name clashes with thrift library (Peter Schuller) THRIFT-1015 Java TUnion does not handle ByteBuffer in toString (Takashi Yonebayashi) +THRIFT-1038 Java Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable (Mathias Herberts) THRIFT-106 Java TSSLServerSocket (Nirmal Ranganathan) THRIFT-377 Java TFileTransport port in Java (Joydeep Sen Sarma) THRIFT-745 Java Make it easier to instantiate servers (Bryan Duxbury) diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc index 376db026164..46b84396745 100644 --- a/compiler/cpp/src/generate/t_java_generator.cc +++ b/compiler/cpp/src/generate/t_java_generator.cc @@ -100,6 +100,8 @@ class t_java_generator : public t_oop_generator { void generate_java_struct_writer(std::ofstream& out, t_struct* tstruct); void generate_java_struct_tostring(std::ofstream& out, t_struct* tstruct); void generate_java_struct_clear(std::ofstream& out, t_struct* tstruct); + void generate_java_struct_write_object(std::ofstream& out, t_struct* tstruct); + void generate_java_struct_read_object(std::ofstream& out, t_struct* tstruct); void generate_java_meta_data_map(std::ofstream& out, t_struct* tstruct); void generate_field_value_meta_data(std::ofstream& out, t_type* type); std::string get_java_type_string(t_type* type); @@ -725,6 +727,14 @@ void t_java_generator::generate_java_union(t_struct* tstruct) { f_struct << endl; + generate_java_struct_write_object(f_struct, tstruct); + + f_struct << endl; + + generate_java_struct_read_object(f_struct, tstruct); + + f_struct << endl; + scope_down(f_struct); f_struct.close(); @@ -1261,6 +1271,10 @@ void t_java_generator::generate_java_struct_definition(ofstream &out, } generate_java_struct_tostring(out, tstruct); generate_java_validator(out, tstruct); + + generate_java_struct_write_object(out, tstruct); + generate_java_struct_read_object(out, tstruct); + scope_down(out); out << endl; } @@ -3957,6 +3971,32 @@ void t_java_generator::generate_java_struct_clear(std::ofstream& out, t_struct* indent(out) << "}" << endl << endl; } +// generates java method to serialize (in the Java sense) the object +void t_java_generator::generate_java_struct_write_object(ofstream& out, t_struct* tstruct) { + indent(out) << "private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {" << endl; + indent(out) << " try {" << endl; + indent(out) << " write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));" << endl; + indent(out) << " } catch (org.apache.thrift.TException te) {" << endl; + indent(out) << " throw new java.io.IOException(te);" << endl; + indent(out) << " }" << endl; + indent(out) << "}" << endl << endl; +} + +// generates java method to serialize (in the Java sense) the object +void t_java_generator::generate_java_struct_read_object(ofstream& out, t_struct* tstruct) { + indent(out) << "private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {" << endl; + indent(out) << " try {" << endl; + if (!tstruct->is_union() && has_bit_vector(tstruct)) { + indent(out) << " // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor." << endl; + indent(out) << " __isset_bit_vector = new BitSet(1);" << endl; + } + indent(out) << " read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));" << endl; + indent(out) << " } catch (org.apache.thrift.TException te) {" << endl; + indent(out) << " throw new java.io.IOException(te);" << endl; + indent(out) << " }" << endl; + indent(out) << "}" << endl << endl; +} + THRIFT_REGISTER_GENERATOR(java, "Java", " beans: Members will be private, and setter methods will return void.\n" " private-members: Members will be private, but setter methods will return 'this' like usual.\n" diff --git a/lib/java/test/org/apache/thrift/TestStruct.java b/lib/java/test/org/apache/thrift/TestStruct.java index 52e4017e0a6..61162d96068 100644 --- a/lib/java/test/org/apache/thrift/TestStruct.java +++ b/lib/java/test/org/apache/thrift/TestStruct.java @@ -18,6 +18,11 @@ */ package org.apache.thrift; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; @@ -309,4 +314,22 @@ public void testBytesBufferFeatures() throws Exception { o.setReq_bin((byte[])null); assertNull(o.getReq_bin()); } + + public void testJavaSerializable() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + + OneOfEach ooe = Fixtures.oneOfEach; + + // Serialize ooe the Java way... + oos.writeObject(ooe); + byte[] serialized = baos.toByteArray(); + + // Attempt to deserialize it + ByteArrayInputStream bais = new ByteArrayInputStream(serialized); + ObjectInputStream ois = new ObjectInputStream(bais); + OneOfEach ooe2 = (OneOfEach) ois.readObject(); + + assertEquals(ooe, ooe2); + } } diff --git a/lib/java/test/org/apache/thrift/TestTUnion.java b/lib/java/test/org/apache/thrift/TestTUnion.java index 775db52189a..a044101429d 100644 --- a/lib/java/test/org/apache/thrift/TestTUnion.java +++ b/lib/java/test/org/apache/thrift/TestTUnion.java @@ -18,6 +18,10 @@ */ package org.apache.thrift; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; @@ -200,4 +204,22 @@ public void testToString() throws Exception { String expectedString = ""; assertEquals(expectedString, cu.toString()); } + + public void testJavaSerializable() throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + + TestUnion tu = TestUnion.string_field("string"); + + // Serialize tu the Java way... + oos.writeObject(tu); + byte[] serialized = baos.toByteArray(); + + // Attempt to deserialize it + ByteArrayInputStream bais = new ByteArrayInputStream(serialized); + ObjectInputStream ois = new ObjectInputStream(bais); + TestUnion tu2 = (TestUnion) ois.readObject(); + + assertEquals(tu, tu2); + } } From 68634a0bac61d41b8ce057d0c9086aea82f4d853 Mon Sep 17 00:00:00 2001 From: T Jake Luciani Date: Mon, 31 Jan 2011 01:57:14 +0000 Subject: [PATCH 037/756] merge changes for 0.6 rc2 git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1065464 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 7 +- compiler/cpp/src/generate/t_js_generator.cc | 94 ++++++++++++------- lib/csharp/src/Transport/TFramedTransport.cs | 47 +++++++--- .../thrift/async/TAsyncClientManager.java | 1 - lib/js/thrift.js | 17 +++- lib/nodejs/lib/thrift/thrift.js | 12 ++- test/csharp/ThriftTest/TestClient.cs | 28 ++++-- test/csharp/ThriftTest/TestServer.cs | 33 +++++-- 8 files changed, 173 insertions(+), 66 deletions(-) diff --git a/CHANGES b/CHANGES index 0609ca227cc..1f92670d8f0 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,7 @@ THRIFT-975 C glib lib/c_glib/README is missing => breaks make d THRIFT-1003 C glib Polishing c_glib code (Anatol Pomozov) THRIFT-582 C glib C implementation of Thrift (Anatol Pomozov) THRIFT-992 C# Naming convention in C# constructor is not consistent with other fields causes compile errors (Roger Meier) +THRIFT-904 C# Disable nagle and linger THRIFT-977 C++ Hex Conversion Bug in C++ TJSONProtocol (Aravind Narayanan) THRIFT-922 C++ Templatized [de]serialization code for C++ (David Reiss) THRIFT-923 C++ Event-driven client and server support for C++ (David Reiss) @@ -48,10 +49,14 @@ THRIFT-946 Java Augment FieldValueMetaData so it differentiat THRIFT-949 Java Modify the TEnum interface so it defines a method similar to findByValue (Mathias Herberts) THRIFT-960 Java add TestServer, TestNonblockingServer and TestClient again (Roger Meier) THRIFT-969 Java Java Tutorial broken, move CalculatorHandler to a separate file (Roger Meier) +THRIFT-1051 Java Fix compiler issue for java 1.5 THRIFT-807 JavaScript JavaScript: Initialization of Base Types with 0 instead of null (Roger Meier) THRIFT-913 JavaScript Test Case for Url encoded strings + simple enhancement to lib/js/test/RunTestServer.sh (Roger Meier) THRIFT-961 JavaScript -THRIFT-1033 JavaScript Node.js support +THRIFT-1033 JavaScript Node.js support (Wade Simmons) +THRIFT-1042 JavaScript Node.js Fix TApplicationException.read Patch (Wade Simmons) +THRIFT-1043 JavaScript Node.js Fix how the length of a map is calculated +THRIFT-1044 JavaScript Fix JavaScript inheritance Patch (Wade Simmons) THRIFT-71 Misc Debian packaging for thrift (Roger Meier) THRIFT-1020 OCaml OCaml compiler generates invalid OCaml (Richard Low) THRIFT-347 PHP PHP TSocket Timeout Issues (Tyler Hobbs) diff --git a/compiler/cpp/src/generate/t_js_generator.cc b/compiler/cpp/src/generate/t_js_generator.cc index 4aa68116b68..a654fc98e2d 100644 --- a/compiler/cpp/src/generate/t_js_generator.cc +++ b/compiler/cpp/src/generate/t_js_generator.cc @@ -157,6 +157,7 @@ class t_js_generator : public t_oop_generator { */ std::string js_includes(); + std::string render_includes(); std::string declare_field(t_field* tfield, bool init=false, bool obj=false); std::string function_signature(t_function* tfunction, std::string prefix="", bool include_callback=false); std::string argument_list(t_struct* tstruct); @@ -191,11 +192,15 @@ class t_js_generator : public t_oop_generator { return pieces; } - std::string js_type_namespace(t_program* p) { + std::string js_type_namespace(t_type* ttype) { + t_program* program = ttype->get_program(); if (gen_node_) { + if (program != NULL && program != program_) { + return program->get_name() + "_ttypes."; + } return "ttypes."; } - return js_namespace(p); + return js_namespace(program); } std::string js_export_namespace(t_program* p) { @@ -286,6 +291,26 @@ string t_js_generator::js_includes() { return inc; } +/** + * Renders all the imports necessary for including another Thrift program + */ +string t_js_generator::render_includes() { + if (gen_node_) { + const vector& includes = program_->get_includes(); + string result = ""; + for (size_t i = 0; i < includes.size(); ++i) { + result += "var " + includes[i]->get_name() + "_ttypes = require('./" + includes[i]->get_name() + "_types')\n"; + } + if (includes.size() > 0) { + result += "\n"; + } + return result; + } + string inc; + + return inc; +} + /** * Close up (or down) some filez. */ @@ -311,7 +336,7 @@ void t_js_generator::generate_typedef(t_typedef* ttypedef) { * @param tenum The enumeration */ void t_js_generator::generate_enum(t_enum* tenum) { - f_types_ << js_type_namespace(tenum->get_program())<get_name()<<" = { "<get_name()<<" = { "< constants = tenum->get_constants(); vector::iterator c_iter; @@ -334,7 +359,7 @@ void t_js_generator::generate_const(t_const* tconst) { string name = tconst->get_name(); t_const_value* value = tconst->get_value(); - f_types_ << js_type_namespace(program_) << name << " = "; + f_types_ << js_type_namespace(type) << name << " = "; f_types_ << render_const_value(type, value) << endl; } @@ -376,7 +401,7 @@ string t_js_generator::render_const_value(t_type* type, t_const_value* value) { } else if (type->is_enum()) { out << value->get_integer(); } else if (type->is_struct() || type->is_xception()) { - out << "new " << js_type_namespace(type->get_program()) << type->get_name() << "({" << endl; + out << "new " << js_type_namespace(type) << type->get_name() << "({" << endl; indent_up(); const vector& fields = ((t_struct*)type)->get_members(); vector::const_iterator f_iter; @@ -541,19 +566,12 @@ void t_js_generator::generate_js_struct_definition(ofstream& out, out << "}\n"; if (is_exception) { - if (gen_node_) { - out << "require('util').inherits(" << - js_namespace(tstruct->get_program()) << - tstruct->get_name() << ", Thrift.TException)" << endl; - } else { - out << "for (var property in Thrift.TException)"<get_program())<get_name()<<"[property] = Thrift.TException[property]"<get_program())<get_name() <<".prototype = {}\n"; + out << "Thrift.inherits(" << + js_namespace(tstruct->get_program()) << + tstruct->get_name() << ", Thrift.TException)" << endl; + } else { + //init prototype + out << js_namespace(tstruct->get_program())<get_name() <<".prototype = {}\n"; } @@ -696,11 +714,23 @@ void t_js_generator::generate_service(t_service* tservice) { f_service_ << autogen_comment() << - js_includes() << endl; + js_includes() << endl << + render_includes() << endl; if (gen_node_) { - f_service_ << - "var ttypes = require('./" + program_->get_name() + "_types.js');" << endl; + if (tservice->get_extends() != NULL) { + f_service_ << + "var " << tservice->get_extends()->get_name() << + " = require('./" << tservice->get_extends()->get_name() << "')" << endl << + "var " << tservice->get_extends()->get_name() << "Client = " << + tservice->get_extends()->get_name() << ".Client" << endl; + + } + + if (gen_node_) { + f_service_ << + "var ttypes = require('./" + program_->get_name() + "_types');" << endl; + } } generate_service_helpers(tservice); @@ -935,17 +965,15 @@ void t_js_generator::generate_service_client(t_service* tservice) { if (tservice->get_extends() != NULL) { - extends = tservice->get_extends()->get_name(); - - f_service_ << "for (var property in "<get_program()) << service_name_<<"Client[property] = "<get_program()) << + service_name_ << "Client, " << + tservice->get_extends()->get_name() << "Client)" << endl; + } else { + //init prototype + indent(f_service_) << js_namespace(tservice->get_program())<get_program())< functions = tservice->get_functions(); vector::const_iterator f_iter; @@ -1231,7 +1259,7 @@ void t_js_generator::generate_deserialize_struct(ofstream &out, t_struct* tstruct, string prefix) { out << - indent() << prefix << " = new " << js_type_namespace(tstruct->get_program())<get_name() << "()" << endl << + indent() << prefix << " = new " << js_type_namespace(tstruct)<get_name() << "()" << endl << indent() << prefix << ".read(input)" << endl; } @@ -1478,7 +1506,7 @@ void t_js_generator::generate_serialize_container(ofstream &out, "output.writeMapBegin(" << type_to_enum(((t_map*)ttype)->get_key_type()) << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << - prefix << ".length)" << endl; + "Thrift.objectLength(" << prefix << "))" << endl; } else if (ttype->is_set()) { indent(out) << "output.writeSetBegin(" << @@ -1625,7 +1653,7 @@ string t_js_generator::declare_field(t_field* tfield, bool init, bool obj) { result += " = null"; } else if (type->is_struct() || type->is_xception()) { if (obj) { - result += " = new " +js_type_namespace(type->get_program()) + type->get_name() + "()"; + result += " = new " +js_type_namespace(type) + type->get_name() + "()"; } else { result += " = null"; } diff --git a/lib/csharp/src/Transport/TFramedTransport.cs b/lib/csharp/src/Transport/TFramedTransport.cs index b7ad5f240fe..e259f5a5973 100644 --- a/lib/csharp/src/Transport/TFramedTransport.cs +++ b/lib/csharp/src/Transport/TFramedTransport.cs @@ -24,9 +24,12 @@ namespace Thrift.Transport public class TFramedTransport : TTransport { protected TTransport transport = null; - protected MemoryStream writeBuffer = new MemoryStream(1024); + protected MemoryStream writeBuffer; protected MemoryStream readBuffer = null; + private const int header_size = 4; + private static byte[] header_dummy = new byte[header_size]; // used as header placeholder while initilizing new write buffer + public class Factory : TTransportFactory { public override TTransport GetTransport(TTransport trans) @@ -35,7 +38,12 @@ public override TTransport GetTransport(TTransport trans) } } - public TFramedTransport(TTransport transport) + public TFramedTransport() + { + InitWriteBuffer(); + } + + public TFramedTransport(TTransport transport) : this() { this.transport = transport; } @@ -77,8 +85,8 @@ public override int Read(byte[] buf, int off, int len) private void ReadFrame() { - byte[] i32rd = new byte[4]; - transport.ReadAll(i32rd, 0, 4); + byte[] i32rd = new byte[header_size]; + transport.ReadAll(i32rd, 0, header_size); int size = ((i32rd[0] & 0xff) << 24) | ((i32rd[1] & 0xff) << 16) | @@ -99,16 +107,31 @@ public override void Flush() { byte[] buf = writeBuffer.GetBuffer(); int len = (int)writeBuffer.Length; - writeBuffer = new MemoryStream(writeBuffer.Capacity); - - byte[] i32out = new byte[4]; - i32out[0] = (byte)(0xff & (len >> 24)); - i32out[1] = (byte)(0xff & (len >> 16)); - i32out[2] = (byte)(0xff & (len >> 8)); - i32out[3] = (byte)(0xff & (len)); - transport.Write(i32out, 0, 4); + int data_len = len - header_size; + if ( data_len < 0 ) + throw new System.InvalidOperationException (); // logic error actually + + InitWriteBuffer(); + + // Inject message header into the reserved buffer space + buf[0] = (byte)(0xff & (data_len >> 24)); + buf[1] = (byte)(0xff & (data_len >> 16)); + buf[2] = (byte)(0xff & (data_len >> 8)); + buf[3] = (byte)(0xff & (data_len)); + + // Send the entire message at once transport.Write(buf, 0, len); + transport.Flush(); } + + private void InitWriteBuffer () + { + // Create new buffer instance + writeBuffer = new MemoryStream(1024); + + // Reserve space for message header to be put right before sending it out + writeBuffer.Write ( header_dummy, 0, header_size ); + } } } diff --git a/lib/java/src/org/apache/thrift/async/TAsyncClientManager.java b/lib/java/src/org/apache/thrift/async/TAsyncClientManager.java index b28c3125922..98f71947d46 100644 --- a/lib/java/src/org/apache/thrift/async/TAsyncClientManager.java +++ b/lib/java/src/org/apache/thrift/async/TAsyncClientManager.java @@ -183,7 +183,6 @@ private void startPendingMethods() { /** Comparator used in TreeSet */ private static class TAsyncMethodCallTimeoutComparator implements Comparator { - @Override public int compare(TAsyncMethodCall left, TAsyncMethodCall right) { if (left.getTimeoutTimestamp() == right.getTimeoutTimestamp()) { return (int)(left.getSequenceId() - right.getSequenceId()); diff --git a/lib/js/thrift.js b/lib/js/thrift.js index 9b92658d0b4..c06e27a0a26 100644 --- a/lib/js/thrift.js +++ b/lib/js/thrift.js @@ -713,5 +713,20 @@ Thrift.Protocol.prototype = { } +Thrift.objectLength = function(obj) { + var length = 0; + for (k in obj) { + if (obj.hasOwnProperty(k)) { + length++; + } + } + return length; +} - +Thirft.inherits = function(constructor, superConstructor) { + // Prototypal Inheritance + // http://javascript.crockford.com/prototypal.html + function F() {} + F.prototype = superConstructor.prototype; + constructor.prototype = new F(); +} diff --git a/lib/nodejs/lib/thrift/thrift.js b/lib/nodejs/lib/thrift/thrift.js index 73f772b223b..53ca1066656 100644 --- a/lib/nodejs/lib/thrift/thrift.js +++ b/lib/nodejs/lib/thrift/thrift.js @@ -85,7 +85,7 @@ TApplicationException.prototype.read = function(input) { case 1: if( ret.ftype == Type.STRING ){ ret = input.readString() - this.message = ret.value + this.message = ret } else { ret = input.skip(ret.ftype) } @@ -94,7 +94,7 @@ TApplicationException.prototype.read = function(input) { case 2: if( ret.ftype == Type.I32 ){ ret = input.readI32() - this.type = ret.value + this.type = ret } else { ret = input.skip(ret.ftype) } @@ -128,3 +128,11 @@ TApplicationException.prototype.write = function(output){ output.writeFieldStop() output.writeStructEnd() } + +exports.objectLength = function(obj) { + return Object.keys(obj).length; +} + +exports.inherits = function(constructor, superConstructor) { + sys.inherits(constructor, superConstructor); +} diff --git a/test/csharp/ThriftTest/TestClient.cs b/test/csharp/ThriftTest/TestClient.cs index 1d7c75ea831..60fc995ee6b 100644 --- a/test/csharp/ThriftTest/TestClient.cs +++ b/test/csharp/ThriftTest/TestClient.cs @@ -39,7 +39,7 @@ public static void Execute(string[] args) int port = 9090; string url = null; int numThreads = 1; - bool buffered = false; + bool buffered = false, framed = false; try { @@ -67,6 +67,11 @@ public static void Execute(string[] args) buffered = true; Console.WriteLine("Using buffered sockets"); } + else if (args[i] == "-f" || args[i] == "-framed") + { + framed = true; + Console.WriteLine("Using framed transport"); + } else if (args[i] == "-t") { numThreads = Convert.ToInt32(args[++i]); @@ -89,16 +94,13 @@ public static void Execute(string[] args) threads[test] = t; if (url == null) { - TSocket socket = new TSocket(host, port); + TTransport trans = new TSocket(host, port); if (buffered) - { - TBufferedTransport buffer = new TBufferedTransport(socket); - t.Start(buffer); - } - else - { - t.Start(socket); - } + trans = new TBufferedTransport(trans as TStreamTransport); + if (framed) + trans = new TFramedTransport(trans); + + t.Start(trans); } else { @@ -428,6 +430,12 @@ public static void ClientTest(TTransport transport) Console.WriteLine("Test Oneway(1)"); client.testOneway(1); + + Console.Write("Test Calltime()"); + var startt = DateTime.UtcNow; + for ( int k=0; k<1000; ++k ) + client.testVoid(); + Console.WriteLine(" = " + (DateTime.UtcNow - startt).TotalSeconds.ToString() + " ms a testVoid() call" ); } } } diff --git a/test/csharp/ThriftTest/TestServer.cs b/test/csharp/ThriftTest/TestServer.cs index e3706404046..894ec9c236e 100644 --- a/test/csharp/ThriftTest/TestServer.cs +++ b/test/csharp/ThriftTest/TestServer.cs @@ -301,7 +301,7 @@ public static void Execute(string[] args) { try { - bool useBufferedSockets = false; + bool useBufferedSockets = false, useFramed = false; int port = 9090; if (args.Length > 0) { @@ -309,7 +309,23 @@ public static void Execute(string[] args) if (args.Length > 1) { - bool.TryParse(args[1], out useBufferedSockets); + if ( args[1] == "raw" ) + { + // as default + } + else if ( args[1] == "buffered" ) + { + useBufferedSockets = true; + } + else if ( args[1] == "framed" ) + { + useFramed = true; + } + else + { + // Fall back to the older boolean syntax + bool.TryParse(args[1], out useBufferedSockets); + } } } @@ -320,10 +336,12 @@ public static void Execute(string[] args) // Transport TServerSocket tServerSocket = new TServerSocket(port, 0, useBufferedSockets); - TServer serverEngine; - // Simple Server - serverEngine = new TSimpleServer(testProcessor, tServerSocket); + TServer serverEngine; + if ( useFramed ) + serverEngine = new TSimpleServer(testProcessor, tServerSocket, new TFramedTransport.Factory()); + else + serverEngine = new TSimpleServer(testProcessor, tServerSocket); // ThreadPool Server // serverEngine = new TThreadPoolServer(testProcessor, tServerSocket); @@ -334,7 +352,10 @@ public static void Execute(string[] args) testHandler.server = serverEngine; // Run it - Console.WriteLine("Starting the server on port " + port + (useBufferedSockets ? " with buffered socket" : "") + "..."); + Console.WriteLine("Starting the server on port " + port + + (useBufferedSockets ? " with buffered socket" : "") + + (useFramed ? " with framed transport" : "") + + "..."); serverEngine.Serve(); } From c76009881b2149ef5840692fdf50d0025acd069c Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Thu, 24 Mar 2011 22:20:12 +0000 Subject: [PATCH 038/756] THRIFT-1112. java: Maven deploy support Patch: Jake Farrell git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1085164 13f79535-47bb-0310-9956-ffa450edef68 --- lib/java/Makefile.am | 2 +- lib/java/build.xml | 458 +++++++++++++++++++++++++------------------ lib/java/ivy.xml | 38 ---- 3 files changed, 267 insertions(+), 231 deletions(-) delete mode 100644 lib/java/ivy.xml diff --git a/lib/java/Makefile.am b/lib/java/Makefile.am index cb1332e2338..c5c752173d7 100644 --- a/lib/java/Makefile.am +++ b/lib/java/Makefile.am @@ -17,7 +17,7 @@ # under the License. # -EXTRA_DIST = build.xml ivy.xml src test +EXTRA_DIST = build.xml src test export CLASSPATH diff --git a/lib/java/build.xml b/lib/java/build.xml index 7c664382143..81472144cf8 100644 --- a/lib/java/build.xml +++ b/lib/java/build.xml @@ -7,100 +7,127 @@ to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - + + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ---> + --> - + Thrift Build File - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + - + - - - - - + + + + + - - - - - - - - + + + + - - - - + + + + + + + - - - + + + - - + + - - - + + + @@ -111,110 +138,90 @@ - You need Apache Ivy 2.0 or later from http://ant.apache.org/ - It could not be loaded from ${ivy_repo_url} + You need Apache Ivy 2.0 or later from ${ivy.repo.url}. It could not be loaded from ${ivy.jar} - - - - - - - - - - - - - - - - - - - - + + + - + - + + + + + - + - - - + + + - - - + + + + + + - + - + + + + + - + - - + + - + - + - - - - + - - - - - + + + + + - + - - - - - - - - + - - - + + + - + @@ -224,90 +231,157 @@ - + Tests failed! - + - - + + - + - + - + - + - + - + - + - + + - + - + - + - + - - - - - - - - - + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/java/ivy.xml b/lib/java/ivy.xml deleted file mode 100644 index 6225e4c173c..00000000000 --- a/lib/java/ivy.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - Java bindings for the Apache Thrift RPC system - - - - - - - - - - - - - - - From 1735a73cc189ef874b44160fbd06e0b7b778cfa9 Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Thu, 24 Mar 2011 22:22:24 +0000 Subject: [PATCH 039/756] THRIFT-1074. .keystore and .truststore are missing from the 0.6.0 distribution Patch: Jake Farrell git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1085165 13f79535-47bb-0310-9956-ffa450edef68 --- Makefile.am | 4 +++- configure.ac | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 64522766365..abe87dadb23 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,9 @@ ACLOCAL_AMFLAGS = -I ./aclocal SUBDIRS = compiler/cpp lib test dist-hook: - find $(distdir) -name '.[a-zA-Z0-9]*' | xargs rm -rf + find $(distdir) -type f \( -iname ".deps" -or -iname ".libs" -or -iname ".gitignore" \ + -or -iname ".DS_Store" -or -iname "._*" \) | xargs rm -rf + find $(distdir) -type d \( -iname ".svn" -or -iname ".git" \) | xargs rm -rf print-version: @echo $(VERSION) diff --git a/configure.ac b/configure.ac index 629a83c0328..ab804da6e7c 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ AC_INIT([thrift], [0.6.0]) AC_CONFIG_AUX_DIR([.]) -AM_INIT_AUTOMAKE +AM_INIT_AUTOMAKE([1.9 tar-ustar]) AC_ARG_VAR([PY_PREFIX], [Prefix for installing Python modules. (Normal --prefix is ignored for Python because From 2511cdcef91f3aad716ec0aaca54e37746300cbd Mon Sep 17 00:00:00 2001 From: Bryan Duxbury Date: Thu, 24 Mar 2011 22:26:32 +0000 Subject: [PATCH 040/756] adjust version number to 0.6.1 git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1085168 13f79535-47bb-0310-9956-ffa450edef68 --- configure.ac | 2 +- lib/csharp/src/Properties/AssemblyInfo.cs | 36 +++++++++++------------ lib/hs/Thrift.cabal | 2 +- lib/java/build.xml | 2 +- lib/nodejs/package.json | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/py/setup.py | 2 +- lib/rb/Rakefile | 2 +- 8 files changed, 25 insertions(+), 25 deletions(-) diff --git a/configure.ac b/configure.ac index ab804da6e7c..f6ae886b593 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.65) -AC_INIT([thrift], [0.6.0]) +AC_INIT([thrift], [0.6.1]) AC_CONFIG_AUX_DIR([.]) diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs index 8320b4080ad..42e7576ccc7 100755 --- a/lib/csharp/src/Properties/AssemblyInfo.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.cs @@ -1,19 +1,19 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations * under the License. */ @@ -52,5 +52,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.6.0.*")] -[assembly: AssemblyFileVersion("0.6.0.*")] \ No newline at end of file +[assembly: AssemblyVersion("0.6.1.*")] +[assembly: AssemblyFileVersion("0.6.1.*")] \ No newline at end of file diff --git a/lib/hs/Thrift.cabal b/lib/hs/Thrift.cabal index 34412f8f793..af2da9a00e9 100644 --- a/lib/hs/Thrift.cabal +++ b/lib/hs/Thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 0.6.0 +Version: 0.6.1 Cabal-Version: >= 1.4 License: OtherLicense Category: Foreign diff --git a/lib/java/build.xml b/lib/java/build.xml index 81472144cf8..f626b3729e7 100644 --- a/lib/java/build.xml +++ b/lib/java/build.xml @@ -23,7 +23,7 @@ Thrift Build File - + diff --git a/lib/nodejs/package.json b/lib/nodejs/package.json index e6ebca9400b..32c0e76b966 100644 --- a/lib/nodejs/package.json +++ b/lib/nodejs/package.json @@ -19,7 +19,7 @@ { "name": "thrift", "description": "node-thrift", - "version": "0.6.0", + "version": "0.6.1", "author": "Apache Thrift", "directories" : { "lib" : "./lib/thrift" }, "main": "./lib/thrift", diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm index 39b051f14a9..7c939535ba3 100644 --- a/lib/perl/lib/Thrift.pm +++ b/lib/perl/lib/Thrift.pm @@ -17,7 +17,7 @@ # under the License. # -our $VERSION = '0.6.0-dev'; +our $VERSION = '0.6.1'; require 5.6.0; use strict; diff --git a/lib/py/setup.py b/lib/py/setup.py index 289b177c1a1..e4f10ae0418 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -26,7 +26,7 @@ ) setup(name = 'Thrift', - version = '0.6.0', + version = '0.6.1', description = 'Python bindings for the Apache Thrift RPC system', author = ['Thrift Developers'], author_email = ['dev@thrift.apache.org'], diff --git a/lib/rb/Rakefile b/lib/rb/Rakefile index 84d099e9115..5b6f432802f 100644 --- a/lib/rb/Rakefile +++ b/lib/rb/Rakefile @@ -82,7 +82,7 @@ begin p.summary = "Ruby bindings for the Apache Thrift RPC system" p.url = "http://thrift.apache.org" p.include_rakefile = true - p.version = "0.6.0" + p.version = "0.6.1" p.rubygems_version = ">= 1.2.0" end From 65e7544643bba71bd426a3a8ba7ed559079fa2e2 Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Thu, 14 Apr 2011 14:30:25 +0000 Subject: [PATCH 041/756] Thrift-1131: C# JSON Protocol is unable to decode escaped characters in string Client lib: csharp Patch: Maciek Weksej C# JSON Protocol throws TProtocolException after meeting an escaped character in UTF8 string, this casts the value being read to avoid this. git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1092282 13f79535-47bb-0310-9956-ffa450edef68 --- lib/csharp/src/Protocol/TJSONProtocol.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/csharp/src/Protocol/TJSONProtocol.cs b/lib/csharp/src/Protocol/TJSONProtocol.cs index e2834f8c239..8c30c481fd7 100644 --- a/lib/csharp/src/Protocol/TJSONProtocol.cs +++ b/lib/csharp/src/Protocol/TJSONProtocol.cs @@ -744,7 +744,7 @@ private byte[] ReadJSONString(bool skipContext) } else { - int off = Array.IndexOf(ESCAPE_CHARS, ch); + int off = Array.IndexOf(ESCAPE_CHARS, (char)ch); if (off == -1) { throw new TProtocolException(TProtocolException.INVALID_DATA, From b46cbbf3182dd2792ad3d34ddb083fed91573be4 Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Tue, 19 Apr 2011 21:11:54 +0000 Subject: [PATCH 042/756] Thrift-363: Maven Deploy Patch: jfarrell Client lib: java Adding the ability to publish the java client library as artifacts to the apache maven repository. Usage: ant -Drelease=true publish Note: You must have a gpg key setup and push it to pgp.mit.edu and have a ~/.m2/settings.xml file containing your apache and gpg information. Thrift-1114 will help make this file more secure or unnecessary. apache.releases.https @APACHE_USERNAME@ @APACHE_PASSWORD@ gpg @GPG_PASSPHRASE@ git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1095216 13f79535-47bb-0310-9956-ffa450edef68 --- lib/java/build.properties | 21 +++++ lib/java/build.xml | 165 +++++++++++++------------------------- 2 files changed, 78 insertions(+), 108 deletions(-) create mode 100644 lib/java/build.properties diff --git a/lib/java/build.properties b/lib/java/build.properties new file mode 100644 index 00000000000..3c75005e7ac --- /dev/null +++ b/lib/java/build.properties @@ -0,0 +1,21 @@ +thrift.version=0.6.1 +thrift.groupid=org.apache.thrift + +# Jar Versions +mvn.ant.task.version=2.1.3 + +# Local Install paths +install.path=/usr/local/lib +install.javadoc.path=${install.path} + +# Maven dependency download locations +mvn.repo=http://repo1.maven.org/maven2 +apache.repo=https://repository.apache.org/content/repositories/releases +mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version} +mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar + +# Apache Maven publish +license=http://www.apache.org/licenses/LICENSE-2.0.txt" +maven-repository-url=https://repository.apache.org/service/local/staging/deploy/maven2 +maven-repository-id=apache.releases.https + diff --git a/lib/java/build.xml b/lib/java/build.xml index f626b3729e7..cddf014cbd2 100644 --- a/lib/java/build.xml +++ b/lib/java/build.xml @@ -18,83 +18,57 @@ under the License. --> Thrift Build File - - - - - - - - - - - - - - - - - - - + + + + - + - - + + - - - - + + - - - + + + + - + - - - - - - + + - - - - - - + - + @@ -102,12 +76,12 @@ - - - + + + - + @@ -115,38 +89,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - You need Apache Ivy 2.0 or later from ${ivy.repo.url}. It could not be loaded from ${ivy.jar} - - - + - + - + @@ -176,11 +124,11 @@ - + - + @@ -191,13 +139,13 @@ - + - + @@ -207,13 +155,13 @@ - + + > @@ -236,35 +184,35 @@ Tests failed! - + - + - + - + - + - + @@ -280,25 +228,25 @@ - + - + - + - - + + - - + + - + + > @@ -332,7 +280,8 @@ - + + @@ -341,22 +290,22 @@ - + - + - + - + - + @@ -375,7 +324,7 @@ - + From 11676adeb37b8f13c0abd6b2dade85cadcc58382 Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Tue, 19 Apr 2011 21:15:17 +0000 Subject: [PATCH 043/756] Thrift-1109: Deploy fb303 along side libthrift to maven repo patch: jfarrell client: contrib fb303 java depends on: Thrift-363 Adding the ability to publish the fb303 java library as an artifact alongside libthrift to the apache maven repository. git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1095218 13f79535-47bb-0310-9956-ffa450edef68 --- contrib/fb303/java/build.xml | 188 ++++++++++++++---- .../fb303/java/{ => src}/FacebookBase.java | 0 2 files changed, 146 insertions(+), 42 deletions(-) rename contrib/fb303/java/{ => src}/FacebookBase.java (100%) diff --git a/contrib/fb303/java/build.xml b/contrib/fb303/java/build.xml index 48e7470970e..62699a43609 100755 --- a/contrib/fb303/java/build.xml +++ b/contrib/fb303/java/build.xml @@ -1,3 +1,4 @@ + - + --> + - - - - + + + + + + - - - + + + + + + + + + + + + + + + + + + + + - - - + + + - - + + - - - - generating thrift fb303 files - - + + + + - - - - - - - Building libfb303.jar .... - + + + - - - + + + - - + + + - + - - + + + - Cleaning old stuff .... - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/fb303/java/FacebookBase.java b/contrib/fb303/java/src/FacebookBase.java similarity index 100% rename from contrib/fb303/java/FacebookBase.java rename to contrib/fb303/java/src/FacebookBase.java From 209d6dcc0e2fece7e28e3092a8d7c52a7ab0d23f Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Wed, 20 Apr 2011 16:35:20 +0000 Subject: [PATCH 044/756] Thrift-1133: Java and JavaScript tutorial is broken since we have Java maven deployment patch: jfarrell client: js Fixing build.xml for the js test cases to use ant-tasks. git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1095454 13f79535-47bb-0310-9956-ffa450edef68 --- lib/js/test/build.xml | 127 +++++++++++++++++++++++------------------- lib/js/test/ivy.xml | 22 -------- 2 files changed, 70 insertions(+), 79 deletions(-) delete mode 100644 lib/js/test/ivy.xml diff --git a/lib/js/test/build.xml b/lib/js/test/build.xml index ee38edbe099..bd2faf25afd 100644 --- a/lib/js/test/build.xml +++ b/lib/js/test/build.xml @@ -7,7 +7,7 @@ "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 + http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an @@ -17,8 +17,8 @@ under the License. --> + xmlns:artifact="antlib:org.apache.maven.artifact.ant" + xmlns:jsl="antlib:com.googlecode.jslint4java"> Java Script Test based on Thrift Java Library @@ -32,16 +32,19 @@ - + + - - - + - - - + + + + + + + @@ -55,25 +58,15 @@ - - + + - You need libthrift.jar located at - ${thrift.java.dir} + You need libthrift*.jar and libthrift*test.jar located at + ${thrift.java.dir}/build Did you compile Thrift Java library and its test suite by "ant compile-test"? - - - - - - - - - ivy is missing at ${ivy.dir} - @@ -89,6 +82,7 @@ + @@ -96,11 +90,11 @@ - + - + @@ -112,46 +106,65 @@ - + - - - - - + + + + + + + + + + + + + - - - + + check if gjslint is available: + + + - - - - + + + + + + - - - - - - - - - - - - - - - You need Apache Ivy 2.0 or later from http://ant.apache.org/ - It could not be loaded from ${ivy_repo_url} - + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/js/test/ivy.xml b/lib/js/test/ivy.xml deleted file mode 100644 index fdd2d9024b4..00000000000 --- a/lib/js/test/ivy.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - From 3ecea5005880b9fb86fc854b85e6812897d0683b Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Wed, 20 Apr 2011 19:48:12 +0000 Subject: [PATCH 045/756] Adding java build.properties file to the exported files list. client: java git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1095491 13f79535-47bb-0310-9956-ffa450edef68 --- lib/java/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/java/Makefile.am b/lib/java/Makefile.am index c5c752173d7..ea01978325f 100644 --- a/lib/java/Makefile.am +++ b/lib/java/Makefile.am @@ -17,7 +17,7 @@ # under the License. # -EXTRA_DIST = build.xml src test +EXTRA_DIST = build.xml build.properties src test export CLASSPATH From 5a53060de2af5959db0ef21ee4a865ae3fa67fd3 Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Wed, 20 Apr 2011 20:11:07 +0000 Subject: [PATCH 046/756] Updating CHANGES for 0.6.1. git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.6.x@1095500 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGES b/CHANGES index 1f92670d8f0..aa22f2fc9db 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,14 @@ Thrift Changelog +Version 0.6.1 + +THRIFT-1074 Build .keystore and .truststore are missing from the 0.6.0 distribution (Jake Farrell) +THRIFT-1131 C# C# JSON Protocol is unable to decode escaped characters in string (Maciek Weksej) +THRIFT-363 Java Maven Deploy (Jake Farrell) +THRIFT-1109 Java Deploy fb303 along side libthrift to maven repo (Jake Farrell) +THIRFT-1133 JavaScript Java and JavaScript tutorial is broken since we have Java maven deployment (Roger Meier, Jake Farrell) + + Version 0.6.0 THRIFT-940 Build 'make check' fails if boost is not in the std include and link paths (Christian Lavoie) From f32d13a9ad5508dcee627a9f0621316e1d523d20 Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Wed, 10 Aug 2011 17:10:32 +0000 Subject: [PATCH 047/756] Branching for 0.7 release git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.7.x@1156267 13f79535-47bb-0310-9956-ffa450edef68 From 7ac3d728bd2c8329674631b8d61a42d70eafb27f Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Wed, 10 Aug 2011 19:27:38 +0000 Subject: [PATCH 048/756] Changes updates and configure.ac version for 0.7.0 git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.7.x@1156328 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index c48c57be8fa..af0a576b720 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,133 @@ Thrift Changelog +Version 0.7.0 + +THRIFT-940 Build 'make check' fails if boost is not in the std include and link paths (Christian Lavoie) +THRIFT-1038 Java Generated Java code for structures containing binary fields are not serializable correctly +THRIFT-1098 PHP Undefined properties in TBinaryProtocolFactory +THRIFT-1076 Erlang Erlang Thrift socket server causes java framed client to throw ""out of sequence"" exception" +THRIFT-1171 Perl Perl write/readDouble assumes little-endian platform +THRIFT-151 C TSSLServerSocket and TSSLSocket implementation +THRIFT-1068 Python Python SSL Socket Support +THRIFT-1011 AS3 Error generating package imports when using classes from other packages +THRIFT-1069 Compiler (General) Add command line option to prevent thrift from inserting gen-* directories +THRIFT-1055 C# csharp TServerSocket and TSocket do not disable Nagle via Socket.NoDelay = true like cpp and java do +THRIFT-638 PHP BufferedTransport + C extensions block until recv timeout is reached on last fread call +THRIFT-867 PHP PHP accelerator module's output transport is incompatible with TFramedTransport +THRIFT-1054 explicit call to PKG_PROG_PKG_CONFIG is missing and first use of PKG_CHECK_MODULES may not happen +THRIFT-125 OCaml OCaml libraries don't compile with 32-bit ocaml +THRIFT-1200 JavaScript JS compiler generates code that clobbers existing namespaces +THRIFT-1102 Build "typo in configure.ac: ""=="" operator in 'test' (instead of""'="")" +THRIFT-994 Build Don't try to invoke phpize if we don't have it +THRIFT-864 Compiler (General) default value fails if identifier is a struct +THRIFT-1021 OCaml Framed transport support for OCaml +THRIFT-1032 make dist fails due to c_glib problem +THRIFT-1057 C++ casts in TBinaryProtocol.tcc causing dereferencing type-punned pointer will break strict-aliasing rules +THRIFT-1053 Java Make remote client's IP address available for all socket related transports +THRIFT-1036 C++ "Auto-generated C++ code fails to compile with ""-Werror -Wextra -Wall"" g++ compiler flags" +THRIFT-1063 Tutorial Fix Erlang Tutorial Files +THRIFT-625 Go Add support for 'Go' +THRIFT-1093 Python several bugs in python TCompactProtocol +THRIFT-1101 Java bytebuffer length calculation in TBinaryProtocol writeBinary +THRIFT-1094 Python bug in TCompactProto python readMessageEnd method and updated test cases +THRIFT-1100 Python python TSSLSocket improvements, including certificate validation +THRIFT-1104 Build INSTALLDIRS should be included in configure script +THRIFT-1103 Python TZlibTransport for python, a zlib compressed transport +THRIFT-1105 OCaml OCaml generator does not prefix methods of included structs with their type +THRIFT-1107 Python improvement for compiler-generated python for 'None' object comparisons +THRIFT-1109 Java Deploy fb303 along side libthrift to maven repo +THRIFT-1111 Compiler (General) The HTML generator does not distinguish between string and binary types +THRIFT-1074 Java .keystore and .truststore are missing from the 0.6.0 distribution +THRIFT-1119 C# TJSONProtocol fails to UTF8 decode strings +THRIFT-1120 C# - Compiler proto.WriteListEnd being called in the wrong place +THRIFT-1126 Erlang Extending struct_info for erlang bindings +THRIFT-1132 C# Deserialization error in TApplicationException C# +THRIFT-1131 C# C# JSON Protocol is unable to decode escaped characters in string +THRIFT-1133 Tutorial Java and JavaScript tutorial is broken since we have Java maven deployment +THRIFT-1140 GlibC Framed Transport Client using C (Glib) Library hangs when connecting to Ruby Server +THRIFT-342 PHP PHP: can't have sets of complex types +THRIFT-1149 Ruby Nonblocking server fails when client connection is reset +THRIFT-363 Java Maven Deploy +THRIFT-1155 Java Remove log4j dependency from java client +THRIFT-1170 Java Thrift Generated Code and Java 5 +THRIFT-835 AS3 Bad AS3 syntax in constructors that set default values +THRIFT-1174 Build Publish as3 client implementation via Maven for use by flex-mojos users +THRIFT-1178 Java Java: TBase signature should be T extends TBase +THRIFT-1067 PHP Tons of bugs in php implementation +THRIFT-1182 Ruby Native deserializer segfaults on incorrect list element type +THRIFT-1190 Java readBufferBytesAllocated in TNonblockingServer.java should be AtomicLong to fix FD leakage +THRIFT-1183 Ruby Pure-ruby CompactProtocol raises ArgumentError when deserializing under Ruby 1.9 +THRIFT-1192 Typo: TProtocol.h tests for HAVE_SYS_PARAM_H_ +THRIFT-1194 Java Java lib does not install artifacts to local dir correctly +THRIFT-1208 Python python TCompactProtocol.py writeBool and readBool not follow the compact-proto-spec-2.txt spec +THRIFT-1211 Java When using THttpClient, non 200 responses leave the connection open +THRIFT-627 C++ should c++ have setters for optional fields? +THRIFT-1218 GLibC c_glib uses wrong name in pkg-config +THRIFT-1189 Ruby Ruby deserializer speed improvements +THRIFT-1225 PHP TCompactProtocol for PHP +THRIFT-1227 Erlang Erlang implementation of thrift JSON protocol +THRIFT-1228 PHP The php accelerator module calls flush incorrectly +THRIFT-1234 Python thrift --help is missing doc on py:utf8strings +THRIFT-1237 Java Java fb303 missing some methods +THRIFT-1248 C++ pointer subtraction in TMemoryBuffer relies on undefined behavior +THRIFT-1253 Java Code generated for maps is not compiling +THRIFT-1255 Java Mismatch of method name between JavaME's lib and generated code (compareTo/compareObjects) +THRIFT-1238 JavaScript Thrift JS client cannot read map of structures +THRIFT-1213 Membuffer should provide a way to get back the buffer +THRIFT-1117 JavaScript JavaScript Unit Test does not work anymore because libthrift*.jar where moved by Maven Deployment +THRIFT-1164 JavaScript Segmentation fault on NULL pointer in t_js_generator::generate_const +THRIFT-788 PHP thrift_protocol.so: multiget/multiget_slice does not handle more than 17 keys correctly +THRIFT-1222 C++ Unhandled exception for TEvhttpServer request +THRIFT-1241 PHP php namespace generation +THRIFT-1236 Erlang Erlang Reconnecting Thrift Client +THRIFT-1151 Erlang Produce more informative runtime error in case of schema and data mismatch during serialization +THRIFT-1146 Java Android Incompatibility : in Android < 2.3 java.io.IOException doesn't support for Throwable +THRIFT-826 PHP PHP TSocket Write Timeout +THRIFT-27 Erlang Generated erlang types don't contain default values for records +THRIFT-1153 C++ HttpClient does not specify the connection close parameter +THRIFT-1154 Cocoa HttpClient does not specify the connection close parameter +THRIFT-1081 PHP PHP tests broken and somewhat incomplete +THRIFT-1078 Test Suite ThriftTest.thrift generates invalid PHP library +THRIFT-447 Java Make an abstract base Client class so we can generate less code +THRIFT-1181 AS3 AS3 compiler generates incorrect code for setting default values in constructor +THRIFT-997 Java Using valueOf for base types in getFieldValue +THRIFT-999 PHP Add TForkingServer +THRIFT-1041 Java TDeserializer holds onto a reference of the array it reads after it is done deserializing +THRIFT-1065 JavaScript Unexpected exceptions not proper handled on JS +THRIFT-993 C++ Some improvements in C++ stubs for oneway operations +THRIFT-1083 Python Preforking python process pool server +THRIFT-1092 Python generated validate() method has wrong indentation +THRIFT-1050 Java "Declaring an argument named ""manager"" to a service method produces code that fails compile +THRIFT-1106 C++ C++ code TAsyncProtocolProcessor.h & TAsyncBufferProcessor.h dont have virtual functions +THRIFT-1080 Erlang erlang test's 'make' fails on Mac OSX +THRIFT-731 Java configure doesn't check for ant >= 1.7 +THRIFT-1180 AS3 AS3 compiler generates uncompilable code for binary types. +THRIFT-1187 Ruby nonblocking_server shutdown race under Ruby 1.9 +THRIFT-1193 Ruby Potential infinite loop in nonblocking_server +THRIFT-891 Compiler (General) Comments are not properly handled in some cases +THRIFT-1216 Java build Java Library behind a proxy +THRIFT-1177 Go Update thrift to reflect changes in Go's networking libraries +THRIFT-1220 C++ TProcessor::process never returns false +THRIFT-1231 C++ Remove bogus include +THRIFT-1217 C++ Use evutil_socketpair instead of pipe (Windows port) +THRIFT-1215 JavaScript Undefined property Thirft in lib/js/thrift.js +THRIFT-418 Ruby Don't do runtime sorting of struct fields +THRIFT-1244 C++ 'using' to disambiguate between functions in different bases does not conform to C++ standard +THRIFT-892 Erlang Refactor erlang build system with rebar +THRIFT-690 Compiler (General) Update TApplicationException codes +THRIFT-1199 Java Union structs should have generated methods to test whether a specific field is currently set +THRIFT-113 Compiler (General) to-string methods should omit optional null fields from output +THRIFT-1049 Python Allow for TServerSocket python library to bind to a specific host +THRIFT-1152 PHP THRIFT-1144 Attributes from private to protected +THRIFT-1207 Ruby "Support DESTDIR on ""make install"" of ruby libs" +THRIFT-1123 C++ Patch to compile Thrift server and client for vc++ 9.0 and 10.0 +THRIFT-1031 C++ Patch to compile Thrift for vc++ 9.0 and 10.0 +THRIFT-1221 C++ Remove SimpleCallback.h +THRIFT-1233 C++ Remove unused include in generated C++ code +THRIFT-1246 Java Improve logging: Change TNonblockingServer internalRead to trace from warn +THRIFT-1251 Java Generated java code should indicate which fields are required and which are optional + + Version 0.6.0 THRIFT-940 Build 'make check' fails if boost is not in the std include and link paths (Christian Lavoie) diff --git a/configure.ac b/configure.ac index ad926b0772e..efabeffe3b0 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.65) -AC_INIT([thrift], [0.7.0-dev]) +AC_INIT([thrift], [0.7.0]) AC_CONFIG_AUX_DIR([.]) From be81e01f285684ec831fb30e121117335f2b2d2f Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Thu, 11 Aug 2011 19:09:13 +0000 Subject: [PATCH 049/756] Updating version number to 0.7.0 for clients git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.7.x@1156746 13f79535-47bb-0310-9956-ffa450edef68 --- contrib/debian/changelog | 6 ++++++ lib/hs/Thrift.cabal | 2 +- lib/java/build.properties | 4 +--- lib/js/thrift.js | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/py/setup.py | 36 ++++++++++++++++++------------------ lib/rb/Rakefile | 2 +- 7 files changed, 29 insertions(+), 25 deletions(-) diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 61bdf27cf9d..c37685a4c41 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +thrift (0.7.0) stable; urgency=low + + * update to 0.7.0 + + -- Jake Farrell Tue, 10 Aug 2011 17:01:53 -0500 + thrift (0.7.0-dev1) stable; urgency=low * added glib * fix location of libthrift.jar diff --git a/lib/hs/Thrift.cabal b/lib/hs/Thrift.cabal index 45bb5b214b1..ffa4dab156b 100644 --- a/lib/hs/Thrift.cabal +++ b/lib/hs/Thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 0.7.0-dev +Version: 0.7.0 Cabal-Version: >= 1.4 License: OtherLicense Category: Foreign diff --git a/lib/java/build.properties b/lib/java/build.properties index 03015efaba3..74b07c57321 100644 --- a/lib/java/build.properties +++ b/lib/java/build.properties @@ -1,4 +1,5 @@ thrift.version=0.7.0 +release=true thrift.groupid=org.apache.thrift # Jar Versions @@ -19,9 +20,6 @@ license=http://www.apache.org/licenses/LICENSE-2.0.txt" maven-repository-url=https://repository.apache.org/service/local/staging/deploy/maven2 maven-repository-id=apache.releases.https -thrift.version=0.7.0 -thrift.groupid=org.apache.thrift - # Jar Versions mvn.ant.task.version=2.1.3 diff --git a/lib/js/thrift.js b/lib/js/thrift.js index 91c446666b5..87877e6f3c2 100644 --- a/lib/js/thrift.js +++ b/lib/js/thrift.js @@ -17,7 +17,7 @@ * under the License. */ var Thrift = { - Version: '0.7.0-dev', + Version: '0.7.0' /* Description: 'JavaScript bindings for the Apache Thrift RPC system', License: 'http://www.apache.org/licenses/LICENSE-2.0', diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm index 3155714e648..46358197fe1 100644 --- a/lib/perl/lib/Thrift.pm +++ b/lib/perl/lib/Thrift.pm @@ -17,7 +17,7 @@ # under the License. # -our $VERSION = '0.7.0-dev'; +our $VERSION = '0.7.0'; require 5.6.0; use strict; diff --git a/lib/py/setup.py b/lib/py/setup.py index 7498bab0406..bf92f1b45b8 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -9,7 +9,7 @@ # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an @@ -22,23 +22,23 @@ from distutils.core import setup, Extension fastbinarymod = Extension('thrift.protocol.fastbinary', - sources = ['src/protocol/fastbinary.c'], - ) + sources = ['src/protocol/fastbinary.c'], + ) setup(name = 'Thrift', - version = '0.7.0-dev', - description = 'Python bindings for the Apache Thrift RPC system', - author = ['Thrift Developers'], - author_email = ['dev@thrift.apache.org'], - url = 'http://thrift.apache.org', - license = 'Apache License 2.0', - packages = [ - 'thrift', - 'thrift.protocol', - 'thrift.transport', - 'thrift.server', - ], - package_dir = {'thrift' : 'src'}, - ext_modules = [fastbinarymod], - ) + version = '0.7.0', + description = 'Python bindings for the Apache Thrift RPC system', + author = ['Thrift Developers'], + author_email = ['dev@thrift.apache.org'], + url = 'http://thrift.apache.org', + license = 'Apache License 2.0', + packages = [ + 'thrift', + 'thrift.protocol', + 'thrift.transport', + 'thrift.server', + ], + package_dir = {'thrift' : 'src'}, + ext_modules = [fastbinarymod], + ) diff --git a/lib/rb/Rakefile b/lib/rb/Rakefile index 7583c973ee7..6eb4f689dc7 100644 --- a/lib/rb/Rakefile +++ b/lib/rb/Rakefile @@ -82,7 +82,7 @@ begin p.summary = "Ruby bindings for the Apache Thrift RPC system" p.url = "http://thrift.apache.org" p.include_rakefile = true - p.version = "0.7.0dev" + p.version = "0.7.0" p.rubygems_version = ">= 1.2.0" end From ea3b5707cdbac60cc8d108a6e61c6cbac1f1b378 Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Thu, 11 Aug 2011 20:58:39 +0000 Subject: [PATCH 050/756] updating 0.7 changes for a missing ticket git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.7.x@1156828 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index af0a576b720..4f9ee3e50b8 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ Thrift Changelog Version 0.7.0 +THRIFT-1252 Ruby Segfault in Ruby deserializer THRIFT-940 Build 'make check' fails if boost is not in the std include and link paths (Christian Lavoie) THRIFT-1038 Java Generated Java code for structures containing binary fields are not serializable correctly THRIFT-1098 PHP Undefined properties in TBinaryProtocolFactory From aac34848b9ac2a61ab37f4e31c7d6773d57d02d4 Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Sat, 13 Aug 2011 22:24:26 +0000 Subject: [PATCH 051/756] adding missing comma in thrift.js client git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.7.x@1157432 13f79535-47bb-0310-9956-ffa450edef68 --- lib/js/thrift.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/js/thrift.js b/lib/js/thrift.js index 87877e6f3c2..498796d3f50 100644 --- a/lib/js/thrift.js +++ b/lib/js/thrift.js @@ -17,7 +17,7 @@ * under the License. */ var Thrift = { - Version: '0.7.0' + Version: '0.7.0', /* Description: 'JavaScript bindings for the Apache Thrift RPC system', License: 'http://www.apache.org/licenses/LICENSE-2.0', From 69bba6ef4630674f8dea0201ffdafe511278404b Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Wed, 17 Aug 2011 19:00:33 +0000 Subject: [PATCH 052/756] Updating python setup.py for deploying client to pypi git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.7.x@1158869 13f79535-47bb-0310-9956-ffa450edef68 --- lib/py/setup.py | 50 ++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/lib/py/setup.py b/lib/py/setup.py index bf92f1b45b8..60e2479f5c4 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -19,26 +19,38 @@ # under the License. # -from distutils.core import setup, Extension +try: + from setuptools import setup, Extension +except: + from distutils.core import setup, Extension fastbinarymod = Extension('thrift.protocol.fastbinary', - sources = ['src/protocol/fastbinary.c'], - ) + sources = ['src/protocol/fastbinary.c'], + ) -setup(name = 'Thrift', - version = '0.7.0', - description = 'Python bindings for the Apache Thrift RPC system', - author = ['Thrift Developers'], - author_email = ['dev@thrift.apache.org'], - url = 'http://thrift.apache.org', - license = 'Apache License 2.0', - packages = [ - 'thrift', - 'thrift.protocol', - 'thrift.transport', - 'thrift.server', - ], - package_dir = {'thrift' : 'src'}, - ext_modules = [fastbinarymod], - ) +setup(name = 'thrift', + version = '0.7.0', + description = 'Python bindings for the Apache Thrift RPC system', + author = ['Thrift Developers'], + author_email = ['dev@thrift.apache.org'], + url = 'http://thrift.apache.org', + license = 'Apache License 2.0', + packages = [ + 'thrift', + 'thrift.protocol', + 'thrift.transport', + 'thrift.server', + ], + package_dir = {'thrift' : 'src'}, + ext_modules = [fastbinarymod], + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Topic :: Software Development :: Libraries', + 'Topic :: System :: Networking' + ] +) From c303ab8ba5582e848bd5a794a1a87cefc57e693d Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Sat, 26 Nov 2011 18:59:52 +0000 Subject: [PATCH 053/756] Initial branch for the 0.8.x release git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.8.x@1206541 13f79535-47bb-0310-9956-ffa450edef68 From 48d2e64d6ae2277a554e90d06735971e964f6de4 Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Sat, 26 Nov 2011 19:51:38 +0000 Subject: [PATCH 054/756] Updating versioning to 0.8.0. git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.8.x@1206566 13f79535-47bb-0310-9956-ffa450edef68 --- compiler/cpp/src/windows/version.h | 2 +- configure.ac | 2 +- contrib/debian/changelog | 6 ++++++ lib/cpp/src/windows/config.h | 2 +- lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs | 4 ++-- lib/csharp/src/Properties/AssemblyInfo.cs | 4 ++-- lib/delphi/src/Thrift.pas | 2 +- lib/hs/Thrift.cabal | 2 +- lib/java/build.properties | 1 + lib/js/thrift.js | 2 +- lib/nodejs/package.json | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/py/setup.py | 2 +- lib/rb/thrift.gemspec | 2 +- 14 files changed, 21 insertions(+), 14 deletions(-) diff --git a/compiler/cpp/src/windows/version.h b/compiler/cpp/src/windows/version.h index fab932f37a3..90d1c50fb71 100644 --- a/compiler/cpp/src/windows/version.h +++ b/compiler/cpp/src/windows/version.h @@ -29,7 +29,7 @@ #endif #define PATH_MAX MAX_PATH -#define THRIFT_VERSION "0.8.0-dev" +#define THRIFT_VERSION "0.8.0" #ifndef S_ISDIR #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) diff --git a/configure.ac b/configure.ac index 82ca641a872..37b24acb768 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.65) -AC_INIT([thrift], [0.8.0-dev]) +AC_INIT([thrift], [0.8.0]) AC_CONFIG_AUX_DIR([.]) diff --git a/contrib/debian/changelog b/contrib/debian/changelog index c37685a4c41..f741a1fd20d 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +thrift (0.8.0) stable; urgency=low + + * update to 0.8.0 + + -- Jake Farrell Sat, 26 Nov 2011 13:00:00 -0500 + thrift (0.7.0) stable; urgency=low * update to 0.7.0 diff --git a/lib/cpp/src/windows/config.h b/lib/cpp/src/windows/config.h index 6116caaf9b7..89a39b2bcb7 100644 --- a/lib/cpp/src/windows/config.h +++ b/lib/cpp/src/windows/config.h @@ -31,7 +31,7 @@ #pragma warning(disable: 4996) // Depreciated posix name. #pragma warning(disable: 4250) // Inherits via dominance. -#define VERSION "0.8.0-dev" +#define VERSION "0.8.0" #define HAVE_GETTIMEOFDAY 1 #define HAVE_SYS_STAT_H 1 diff --git a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs index 8769f1aca3c..4107e4d4935 100644 --- a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs +++ b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs @@ -56,5 +56,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.7.0.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.8.0.*")] +[assembly: AssemblyFileVersion("0.8.0.*")] diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs index 9c6ecdd9431..a37fe6ef5a6 100755 --- a/lib/csharp/src/Properties/AssemblyInfo.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.cs @@ -52,5 +52,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.7.0.*")] -[assembly: AssemblyFileVersion("0.7.0.*")] +[assembly: AssemblyVersion("0.8.0.*")] +[assembly: AssemblyFileVersion("0.8.0.*")] diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index dceb256c66b..a84f0ea50ae 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -25,7 +25,7 @@ interface SysUtils, Thrift.Protocol; const - Version = '0.8.0-dev'; + Version = '0.8.0'; type IProcessor = interface diff --git a/lib/hs/Thrift.cabal b/lib/hs/Thrift.cabal index 3e7418b7dbb..ca35c5c6293 100644 --- a/lib/hs/Thrift.cabal +++ b/lib/hs/Thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 0.8.0-dev +Version: 0.8.0 Cabal-Version: >= 1.4 License: OtherLicense Category: Foreign diff --git a/lib/java/build.properties b/lib/java/build.properties index 0d372b3cc00..e1869ad4057 100644 --- a/lib/java/build.properties +++ b/lib/java/build.properties @@ -1,4 +1,5 @@ thrift.version=0.8.0 +release=true thrift.groupid=org.apache.thrift # Jar Versions diff --git a/lib/js/thrift.js b/lib/js/thrift.js index d1c9adf9f77..6d9dceccd83 100644 --- a/lib/js/thrift.js +++ b/lib/js/thrift.js @@ -17,7 +17,7 @@ * under the License. */ var Thrift = { - Version: '0.8.0-dev', + Version: '0.8.0', /* Description: 'JavaScript bindings for the Apache Thrift RPC system', License: 'http://www.apache.org/licenses/LICENSE-2.0', diff --git a/lib/nodejs/package.json b/lib/nodejs/package.json index e378d2d9718..8af1622595c 100644 --- a/lib/nodejs/package.json +++ b/lib/nodejs/package.json @@ -6,7 +6,7 @@ { "type" : "svn", "url" : "http://svn.apache.org/repos/asf/thrift/trunk/" }, - "version": "0.8.0-dev", + "version": "0.8.0", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm index 1863d3e4782..c736d16dc94 100644 --- a/lib/perl/lib/Thrift.pm +++ b/lib/perl/lib/Thrift.pm @@ -17,7 +17,7 @@ # under the License. # -our $VERSION = '0.8.0-dev'; +our $VERSION = '0.8.0'; require 5.6.0; use strict; diff --git a/lib/py/setup.py b/lib/py/setup.py index 5870cd080ae..dab35bf8828 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -66,7 +66,7 @@ def run_setup(with_binary): extensions = dict() setup(name = 'thrift', - version = '0.8.0-dev', + version = '0.8.0', description = 'Python bindings for the Apache Thrift RPC system', author = ['Thrift Developers'], author_email = ['dev@thrift.apache.org'], diff --git a/lib/rb/thrift.gemspec b/lib/rb/thrift.gemspec index 90d1bf8fd5a..992791e3e15 100644 --- a/lib/rb/thrift.gemspec +++ b/lib/rb/thrift.gemspec @@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__) Gem::Specification.new do |s| s.name = 'thrift' - s.version = '0.8.0.1' + s.version = '0.8.0' s.authors = ['Thrift Developers'] s.email = ['dev@thrift.apache.org'] s.homepage = 'http://thrift.apache.org' From be691f4ebfcc0496aaefc464803210e4e40f62ad Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Sat, 26 Nov 2011 21:24:24 +0000 Subject: [PATCH 055/756] Updating CHANGES for 0.8.0 release git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.8.x@1206597 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/CHANGES b/CHANGES index 4f9ee3e50b8..497cf6ef2d8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,117 @@ Thrift Changelog +Version 0.8.0 + +THRIFT-1330 PHP PHP Namespaces no longer generated +THRIFT-1392 PHP Enabling both namespaces and autoloading in generated PHP code won't work. +THRIFT-386 Python Make it possible to build the Python library without the extension +THRIFT-1431 Node.js Rename 'sys' module to 'util' +THRIFT-1435 Delphi make TException.Message property conformant to the usual expectations +THRIFT-1432 JavaScript Javascript struct constants declared in the same file as their struct cause an error +THRIFT-1391 Delphi Improved Delphi XE test cases +THRIFT-1387 C++ Build MSVC libraries with Boost Threads instead of Pthreads +THRIFT-1426 Build Process Dist package missing files for release 0.8 +THRIFT-1428 Tutorial shared.thrft does not include namespace for php, compiler generate incorrect name +THRIFT-1411 Java java generator does not provide type parameter for TBaseProcessor +THRIFT-1425 Node.js The Node package is incompatible with latest node (0.6) & npm (1.0.27) +THRIFT-1401 Delphi JSON-protocol for Delphi XE Libraries +THRIFT-1424 Ruby Ruby specs fail when run with rake +THRIFT-1382 Ruby Bundle install doesnot work because thrift crashes +THRIFT-1251 Java Generated java code should indicate which fields are required and which are optional +THRIFT-1361 C++ Optional replacement of pthread by boost::thread +THRIFT-1415 Delphi delphi: add version Info to the library +THRIFT-1031 C++ Patch to compile Thrift for vc++ 9.0 and 10.0 +THRIFT-1420 Java Nonblocking and HsHa server should close all socket connections when the selector exits +THRIFT-1419 Java AbstractNonBlockingServer does not catch errors when invoking the processor +THRIFT-1416 Python Python Unit test is broken on ci +THRIFT-1409 Delphi Name conflict check does not work properly for exception object(Delphi). +THRIFT-1413 Delphi Generated code does not read MapEnd / ListEnd / SetEnd +THRIFT-1408 Delphi Delphi Test Server: Exception test case fails due to naming conflict with e.message +THRIFT-1407 Python Typo in Python socket server causes Thrift to fail when we enable a global socket timout +THRIFT-1405 Delphi Delphi compiler does not generates container serializer properly. +THRIFT-1399 Delphi One of the TServerImpl.Create CTORs lacks implementation +THRIFT-1406 Delphi Build error after applying THRIFT-1395 +THRIFT-1404 Delphi Delphi compiler generates struct reader code with problem. +THRIFT-1395 Delphi Patch to prevent warnings for integer types in some cases +THRIFT-1400 Ruby Ruby native extension aborts with __stack_chk_fail in OSX +THRIFT-1397 Test Suite CI server fails during build due to unused parameters in delphi generator +THRIFT-1396 Delphi Dephi generator has dependacy on boost 1.42 later. +THRIFT-1390 Build Process Debian packages build fix for Squeeze (build from the official 0.7.0 tarball) +THRIFT-1393 PHP TTransportException's thrown from THttpClient has extra slashes in the Exception message +THRIFT-1366 Delphi Delphi generator, lirbrary and unit test. +THRIFT-1130 Compiler (General) Add the ability to specify symbolic default value for optional boolean +THRIFT-1381 C++ Thrift C++ libs have incorrectly versioned names +THRIFT-1384 Javame Java help menu missing newline near javame flag +THRIFT-1373 C++ Fix user-defined exception generation in thrift (python) +THRIFT-1379 C++ fix uninitialized enum values in thrift C++ objects +THRIFT-1377 C++ abort PHP deserialization on unknown field type +THRIFT-1376 C++ Make port specification option in thrift remote +THRIFT-1375 C++ fixed a hex char conversion bug in TJSONProtocol +THRIFT-1370 C glib Debian packaging should Build-Depend on libglib2.0-dev +THRIFT-1121 Java Java server performance regression in 0.6 +THRIFT-1365 Java TupleProtocol#writeBitSet unintentionally writes a variable length byte array +THRIFT-1359 C++ --gen-cob cpp:cob_style does not compile anymore +THRIFT-1355 Ruby Running make in lib/rb doesn't build the native extensions +THRIFT-1354 Ruby Add rake task to build just the gem file +THRIFT-857 Test Suite tests run by "make install" fail if generators are disabled +THRIFT-1339 Java Extend Tuple Protocol to TUnions +THRIFT-1331 Ruby Ruby library deserializes an empty map to nil +THRIFT-1350 Go Go library code does not build as of r60 (most recent release) +THRIFT-1227 Erlang Erlang implementation of thrift JSON protocol +THRIFT-1335 C++ Add accept timeout to TServerSocket +THRIFT-1345 Build Process Allow building without tests +THRIFT-1342 Python Compilation problem on Windows of fastbinary.c +THRIFT-1341 C++ TProtocol.h endian detection wrong with boost +THRIFT-1243 C++ TAsyncChannel callbacks +THRIFT-1238 JavaScript Thrift JS client cannot read map of structures +THRIFT-1333 C++ Make RWGuard not copyable +THRIFT-1334 C++ Add more info to IllegalStateException +THRIFT-1332 Java TSSLTransportParameters class uses hard coded value keyManagerType: SunX509 +THRIFT-1328 Java TBaseHelper.toString(...) appends ByteBuffer data outside of valid buffer range +THRIFT-1322 OCaml OCaml lib fail to compile: Thrift.ml line 305, int vs int32 mismatch +THRIFT-1279 PHP type set is handled incorrectly when writing object +THRIFT-1320 C++ Consistency of configure generated config.h +THRIFT-1319 Java Mismatch between how a union reads and writes a container +THRIFT-1316 C++ thrift: update server classes to accept +THRIFT-1314 C++ thrift: add TProcessorFactory +THRIFT-1315 C++ thrift: generate server interface factory classes +THRIFT-1317 C++ Remove copy constructibility from +THRIFT-1305 C++ thrift: make TConnection a private inner class of +THRIFT-1286 Ruby Modernize the Thrift Ruby Library Dev Environment +THRIFT-1304 C++ TNonblockingServer: pass in the connection context to +THRIFT-1302 C++ thrift: raise an exception if send() times out in +THRIFT-1301 C++ thrift: consolidate common code in TNonblockingServer +THRIFT-1298 Java Standard scheme doesn't read or write metadata along with field values +THRIFT-1257 Java thrift's dependency scope on javax.servlet:servlet-api should be 'provided' +THRIFT-1240 PHP TBinarySerializer invalid serialization due to TBufferTransport not flushing +THRIFT-1295 C++ Duplicate include in TSocket.cpp +THRIFT-1294 C++ thrift: fix log message typos in TSimpleServer +THRIFT-1293 C++ thrift: improve handling of exceptions thrown by +THRIFT-1292 C++ thrift: silence log spew from TThreadedServer +THRIFT-1290 C++ thrift: TNonblockingServer: clean up state in the +THRIFT-1289 C++ thrift: implement TNonblockingServer::stop() +THRIFT-1288 C++ Allow typedefed exceptions in throws clauses +THRIFT-1287 C++ thrift: start refactoring some of the C++ processor +THRIFT-1280 C++ Thrift: Improve Monitor exception-free interfaces +THRIFT-1281 Compiler (General) add @generated to the docblock +THRIFT-1282 Java Upgrade httpclient to 4.1.2 (from 4.0.1) +THRIFT-1284 C++ thrift: fix processor inheritance +THRIFT-1283 C++ thrift: wrap t_cpp_generator::generate_process_function() to 80 +THRIFT-1278 Java javadoc warnings - compilation +THRIFT-1254 JavaME Code compiled against a regular JRE: Object.clone() override has a different return type +THRIFT-1271 C++ thrift: fix missing namespace in generated local +THRIFT-1274 C++ thrift: fail compilation if an unexpected token is +THRIFT-1275 C++ thrift: always prefix namespaces with " ::" +THRIFT-1265 C++ C++ container deserialize +THRIFT-1167 Java Java nonblocking server with more than one thread for select and handling IO +THRIFT-380 Python Use setuptools for python build +THRIFT-1270 C++ thrift: add --allow-neg-keys argument to allow +THRIFT-1263 Ruby publish ruby client to rubygems +THRIFT-1205 Java port server unduly fragile with arbitrary input +THRIFT-769 Java Pluggable Serializers +THRIFT-1239 Java TupleProtocol- An extremely compact, temporary protocol + + Version 0.7.0 THRIFT-1252 Ruby Segfault in Ruby deserializer From dddc5df81f3bb7fa41bc40f78dff969e858db90c Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Thu, 11 Oct 2012 00:39:23 +0000 Subject: [PATCH 056/756] Initial branch for the 0.9.x release git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.9.x@1396885 13f79535-47bb-0310-9956-ffa450edef68 From c6c01f26dbf8c8fdb218d67354ac68b1703e2e08 Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Thu, 11 Oct 2012 20:22:24 +0000 Subject: [PATCH 057/756] Updating CHANGES and versioning for 0.9.0 release. git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.9.x@1397283 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 293 +++++++++++++++++- configure.ac | 2 +- contrib/debian/changelog | 6 + contrib/fb303/py/setup.py | 2 +- lib/cpp/src/thrift/windows/config.h | 2 +- lib/csharp/src/Properties/AssemblyInfo.WP7.cs | 1 - lib/csharp/src/Properties/AssemblyInfo.cs | 5 +- lib/delphi/src/Thrift.pas | 2 +- lib/erl/src/thrift.app.src | 2 +- lib/hs/Thrift.cabal | 2 +- lib/java/build.properties | 1 + lib/js/thrift.js | 2 +- lib/nodejs/package.json | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/py/setup.py | 2 +- test/nodejs/package.json | 2 +- 16 files changed, 307 insertions(+), 21 deletions(-) diff --git a/CHANGES b/CHANGES index 4f9ee3e50b8..16156499378 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,286 @@ Thrift Changelog +Version 0.9.0 + +THRIFT-164 Website Build web tutorial on Incubator web site +THRIFT-304 Python Building the Python library requires development headers +THRIFT-317 Java Issues with Java struct validation +THRIFT-330 Compiler (General) Additional method to called when connection is broken +THRIFT-336 Csharp Compact Protocol in C# +THRIFT-369 Ruby Sets and maps break equality +THRIFT-481 Ruby Indentation of ruby classes is off by a few +THRIFT-491 C++ Ripping raw pthreads out of TFileTransport and associated test issues +THRIFT-541 Cocoa Cocoa code generator doesn't put keywords before all arguments. +THRIFT-556 Ruby not correctly referred to top-level modules when a submodule masks the top-level name +THRIFT-681 Compiler (General) The HTML generator does not handle JavaDoc style comments very well +THRIFT-956 Python Python module's version meta-data should be updated +THRIFT-973 Cocoa Cocoa library won't compile using clang +THRIFT-982 JavaME add version Info to the library +THRIFT-1023 Ruby Thrift encoding (UTF-8) issue with Ruby 1.9.2 +THRIFT-1061 Java, PHP Read an invalid frame size of 0. Are you using TFramedTransport on the client side? +THRIFT-1072 Cocoa Missing - (id) initWithSharedProcessor in TSharedProcessorFactory.h +THRIFT-1082 Perl Thrift::FramedTransport sometimes calls close() on an undefined value +THRIFT-1090 Website Document the generation of a file called "Constants.java" +THRIFT-111 Python TBase class for dynamic (de)serialization, and __slots__ option for memory savings +THRIFT-1128 Build OS X thrift.h incompatibility with Thrift.h +THRIFT-1159 CSharp THttpClient->Flush() issue (connection thru proxy) +THRIFT-1204 Ruby Ruby autogenerated files should require 'thrift' gem +THRIFT-1224 Ruby Cannot insert UTF-8 text +THRIFT-1235 C++ How could I use THttpServerTransportFactory withTNonBlockingServer +THRIFT-1267 JavaScript Node.js can't throw exceptions. +THRIFT-1277 JavaScript Node.js serializes false booleans as null +THRIFT-1326 C++ on some platforms, #include is necessary to be included in Thrift.h +THRIFT-1327 Ruby Fix Spec Suite under Ruby-1.8.7 (works for MRI Ruby-1.9.2) +THRIFT-1338 Build Process Do not use an unpatched autoconf 2.65 to generate release tarball +THRIFT-1340 Cocoa Add support of ARC to Objective-C +THRIFT-1343 Erlang no_auto_import min/2 to avoid compile warning +THRIFT-1344 Erlang Using the httpc module directly rather than the deprecated http layer +THRIFT-1368 Java TNonblockingServer usage +THRIFT-1394 C++ Treatment of optional fields is not consistent between C++ and Java +THRIFT-1421 Build Process Debian Packages can not be built +THRIFT-1427 PHP PHP library uses non-multibyte safe functions with mbstring function overloading +THRIFT-1429 Java The nonblocking servers is supposed to use TransportFactory to read the data +THRIFT-1433 C++ TServerSocket fix for MSVC +THRIFT-1438 C++ lib/cpp/src/windows/config.h should read version from configure.ac rather than a #define +THRIFT-1441 Delphi Generate constructor with parameters for exception class for message property auto update +THRIFT-1443 C++ define a TProcessor helper class to implement process() +THRIFT-1444 C++ FunctionRunner - add syntactic sugar to create shared_ptrs +THRIFT-1446 Delphi Compile error with Delphi 2009 in constant initializer +THRIFT-1447 Java NullpointerException in ProcessFunction.class :in "oneway" method +THRIFT-1449 Ruby Ruby client does not work on solaris (?) +THRIFT-1450 Build Process Problems building thrift 0.8.0 for Python and Ruby +THRIFT-1451 C++ FramedTransport: Prevent infinite loop when writing +THRIFT-1452 C++ generate a swap() method for all generated structs +THRIFT-1453 C++ Don't change types of arguments when serializing with thrift php extension +THRIFT-1456 C# System.Net.HttpWebRequest' does not contain a definition for 'Proxy' +THRIFT-1460 Python why not add unicode strings support to python directly? +THRIFT-1461 C++ Recent TNonblockingServer changes broke --enable-boostthreads=yes, Windows +THRIFT-1463 Compiler Decouple Thrift IDL from generators +THRIFT-1464 Java AbstractNonblockingServer.FrameBuffer TNonblockingTransport changed public to private +THRIFT-1465 Java Visibility of methods in generated java code +THRIFT-1466 C glib Proper Documentation for Thrift C Glib +THRIFT-1467 Delphi Possible AV with empty strings when using JSON protocol +THRIFT-1468 Java Memory leak in TSaslServerTransport +THRIFT-1469 Java Java isset space optimization +THRIFT-1473 Delphi JSON context stack left in an incorrect state when exception thrown during read/write +THRIFT-1475 Erlang Incomplete records generation for Erlang +THRIFT-1479 PHP Compiled PHP process functions missing writeMessageEnd() +THRIFT-1480 Python remove tabs, adjust whitespace and address PEP8 warnings +THRIFT-1483 Java java compiler does not generate type parameters for services in extended clauses +THRIFT-1484 PHP Introduce phpunit test suite +THRIFT-1485 Delphi Performance: pass large and/or refcounted arguments as "const" +THRIFT-1486 Test Suite Javascript manual testserver not returning content types +THRIFT-1488 Build Process invalid conversion 'pthread_t {aka _opaque_pthread_t*}' to {aka long long unsigned int}' +THRIFT-1490 C++ Windows-specific header files - fixes & tweaks +THRIFT-1491 C++ Uninitialize processorFactory_ member in TServer.h +THRIFT-1492 C glib enabling c_glib render thrift unusable (even for C++ code) +THRIFT-1495 Test Suite PHP TestClient fatals on missing class +THRIFT-1496 PHP PHP compiler not namespacing enums +THRIFT-1498 Java Allow TThreadedPoolServer.Args to pass a ExecutorService +THRIFT-1500 D D programming language support +THRIFT-1501 PHP PHP old namespaces not generated for enums +THRIFT-1502 C++ TSimpleServer::serve(): Do not print out error message if server was stopped. +THRIFT-1504 Cocoa Cocoa Generator should use local file imports for base Thrift headers +THRIFT-1508 C++ TServerSocket does not allow for the user to specify the IP address to bind to +THRIFT-1510 Ruby There should be an implementation of the JsonProtocol for ruby +THRIFT-1511 Java Server with oneway support ( JAVA ) +THRIFT-1512 C++ Thrift socket support for Windows XP +THRIFT-1515 Python NameError: global name 'TApplicationException' is not defined +THRIFT-1518 C++ Generated C++ code sends the first optional field in the write() function for a struct. +THRIFT-1519 Ruby Thirft Build Failure referencing rb_intern2 symbol +THRIFT-1520 Erlang Embed version number in erlang .app file +THRIFT-1521 PHP Two patches for more Performance +THRIFT-1523 Java clientTimeout not worked as expected in TServerSocket created by TSSLTransportFactory +THRIFT-1524 C++ TNonBlockingServer does not compile in Visual Studio 2010 +THRIFT-1526 Java Union TupleSchemeFactory returns StandardSchemes +THRIFT-1527 Java Gen tupleReadStruct in unions return null when the setfield is unrecognized +THRIFT-1529 Java TupleProtocol unintentionally includes extra byte in bit vectors with ptional fields is 8 +THRIFT-1532 Erlang The type specifications in the gen Erlang code should include "undefined" for default val +THRIFT-1534 Delphi Required fields in the Delphi code generator. +THRIFT-1535 Java Why thrift don't use wrapped class for optional fields ? +THRIFT-1537 Delphi TFramedTransport issues +THRIFT-1539 Python Build and distribute the fb303 python libraries along with thrift +THRIFT-1553 Node.js thrift nodejs service side can't read map structure, key as enum, value as Object +THRIFT-1554 Delphi Inherited service methods are not resolved in derived service implementations +THRIFT-1555 Delphi Delphi version of the tutorial code +THRIFT-1567 C++ Thrift/cpp: Allow alternate classes to be used for +THRIFT-1571 Ruby Update Ruby HTTP transport for recent Ruby versions +THRIFT-1575 C++ Typo in server/TThreadPoolServer.h +THRIFT-1578 C glib C_GLib generated code does not compile +THRIFT-1582 C glib Bad includes of nested thrift files in c_glib +THRIFT-1583 C glib c_glib leaks memory +THRIFT-1591 Ruby Enable TCP_NODELAY for ruby gem +THRIFT-1593 Erlang Pass on errors like "connection closed" to the handler module +THRIFT-1596 Delphi Test clients should have a return codes that reflect whether they succeeded or not +THRIFT-1597 PHP TJSONProtocol.php is missing from Makefile.am +THRIFT-1602 PHP PHP C Extension is not Compatible with PHP 5.4 +THRIFT-1604 Python Python exception handeling for changes from PEP 3110 +THRIFT-1606 C++ Race condition in BoostThreadFactory.cpp +THRIFT-1607 Build Process Incorrect file modes for several source files +THRIFT-1610 C# IWebProxy not available on WP7 platform +THRIFT-1611 Delphi Improved code generation for typedefs +THRIFT-1612 C# Base64 encoding is broken +THRIFT-1613 Java Add code back into empty source file ToStringTest.java +THRIFT-1615 PHP PHP Namespace +THRIFT-1621 Delphi Memory leaks +THRIFT-1622 C++ Incorrect size returned on read +THRIFT-1624 Java Isset Generated differently on different platforms +THRIFT-1627 Build Process compiler built using compilers.vcxproj cannot be used to build some test .thrift files +THRIFT-1631 C++ Fix C++ server constructor typos +THRIFT-1632 Ruby data corruption in thrift_native implementation of MemoryBufferTransport +THRIFT-1644 Ruby Upgrade RSpec to 2.10.x and refactor specs as needed +THRIFT-1645 Ruby Replace Object#tee with more conventional Object#tap in specs +THRIFT-1650 Ruby Update clean items and svn:ignore entries for OS X artifacts +THRIFT-1652 Java TSaslTransport does not log the error when kerberos auth fails +THRIFT-1653 Java TThreadedSelectorServer leaks CLOSE_WAIT sockets +THRIFT-1654 C glib c_glib thrift_socket_read() returns corrupted data +THRIFT-1655 Build Process Configure still trying to use thrift_generators in output +THRIFT-1656 C++ Set proper headers in THttpServer.cpp so "Cross-Origin Resource Sharing" to fix js client +THRIFT-1658 Java Java thrift server is not throwing TApplicationException +THRIFT-1661 Build Process Add --with-qt4 configure option +THRIFT-1662 Cocoa "removeObject:" should be "removeObserver:" in [-TSocketServer dealloc]? +THRIFT-1663 Java Java Thrift server is not throwing exceptions +THRIFT-1664 Build Process Reference to non-existing variable in build script +THRIFT-1665 Java TBinaryProtocol: exceeded message length raises generic TException +THRIFT-1668 Build Process Compile error in contrib/fb303, thrift/TDispatchProcessor.h: No such file or directory +THRIFT-1669 Python NameError: global name 'TApplicationException' is not defined +THRIFT-1670 Delphi Incompatibilities between different versions of a Thrift interface +THRIFT-1671 Cocoa Cocoa code generator does not put keywords into generated method calls +THRIFT-1672 C# MonoTouch (and Mono for Android) compatibility +THRIFT-1673 Ruby Ruby compile flags for extension for multi arch builds (os x) +THRIFT-1674 D Update Thrift D library to be compatible with 2.060 +THRIFT-1675 Java Do we have any plan to support scala? +THRIFT-1676 C++ Allow specifying IP/hostname in TServer::serve +THRIFT-1685 Website Please add "aereo.com" to "Powered by Apache Thrift" list in about page +THRIFT-1686 PHP php generator uses "and" instead of "&&", and causes compiler errors with Visual Studio +THRIFT-1688 Website Update IDL page markup +THRIFT-1689 C++ don't exit(-1) in TNonblockingServer +THRIFT-1691 Delphi Serializer/deserializer support for Delphi +THRIFT-1693 Java libthrift has dependency on two different versions of httpcore +THRIFT-1694 C# Re-Enable serialization for WP7 Silverlight +THRIFT-1702 Documentation a thrift manual +THRIFT-1707 Ruby Adjust server_spec.rb for RSpec 2.11.x and Ruby 1.9.3 +THRIFT-1709 C# Warning "Bitwise-or operator used on a sign-extended operand;" cast error +THRIFT-1710 Delphi Minor issues in test case code +THRIFT-1714 Ruby Explicitly add CWD to Ruby test_suites.rb +THRIFT-1718 C++ Incorrect check in TFileTransportTest +THRIFT-1721 Build Dist broken due to 0.8.0 to 0.9.0 changes +THRIFT-1722 Csharp C# WP7 Assembly addition beaks mono build +THRIFT-1725 Website Tutorial web pages for Delphi and C# + + +Version 0.8.0 + +THRIFT-1330 PHP PHP Namespaces no longer generated +THRIFT-1392 PHP Enabling both namespaces and autoloading in generated PHP code won't work. +THRIFT-386 Python Make it possible to build the Python library without the extension +THRIFT-1431 Node.js Rename 'sys' module to 'util' +THRIFT-1435 Delphi make TException.Message property conformant to the usual expectations +THRIFT-1432 JavaScript Javascript struct constants declared in the same file as their struct cause an error +THRIFT-1391 Delphi Improved Delphi XE test cases +THRIFT-1387 C++ Build MSVC libraries with Boost Threads instead of Pthreads +THRIFT-1426 Build Process Dist package missing files for release 0.8 +THRIFT-1428 Tutorial shared.thrft does not include namespace for php, compiler generate incorrect name +THRIFT-1411 Java java generator does not provide type parameter for TBaseProcessor +THRIFT-1425 Node.js The Node package is incompatible with latest node (0.6) & npm (1.0.27) +THRIFT-1401 Delphi JSON-protocol for Delphi XE Libraries +THRIFT-1424 Ruby Ruby specs fail when run with rake +THRIFT-1382 Ruby Bundle install doesnot work because thrift crashes +THRIFT-1251 Java Generated java code should indicate which fields are required and which are optional +THRIFT-1361 C++ Optional replacement of pthread by boost::thread +THRIFT-1415 Delphi delphi: add version Info to the library +THRIFT-1031 C++ Patch to compile Thrift for vc++ 9.0 and 10.0 +THRIFT-1420 Java Nonblocking and HsHa server should close all socket connections when the selector exits +THRIFT-1419 Java AbstractNonBlockingServer does not catch errors when invoking the processor +THRIFT-1416 Python Python Unit test is broken on ci +THRIFT-1409 Delphi Name conflict check does not work properly for exception object(Delphi). +THRIFT-1413 Delphi Generated code does not read MapEnd / ListEnd / SetEnd +THRIFT-1408 Delphi Delphi Test Server: Exception test case fails due to naming conflict with e.message +THRIFT-1407 Python Typo in Python socket server causes Thrift to fail when we enable a global socket timout +THRIFT-1405 Delphi Delphi compiler does not generates container serializer properly. +THRIFT-1399 Delphi One of the TServerImpl.Create CTORs lacks implementation +THRIFT-1406 Delphi Build error after applying THRIFT-1395 +THRIFT-1404 Delphi Delphi compiler generates struct reader code with problem. +THRIFT-1395 Delphi Patch to prevent warnings for integer types in some cases +THRIFT-1400 Ruby Ruby native extension aborts with __stack_chk_fail in OSX +THRIFT-1397 Test Suite CI server fails during build due to unused parameters in delphi generator +THRIFT-1396 Delphi Dephi generator has dependacy on boost 1.42 later. +THRIFT-1390 Build Process Debian packages build fix for Squeeze (build from the official 0.7.0 tarball) +THRIFT-1393 PHP TTransportException's thrown from THttpClient has extra slashes in the Exception message +THRIFT-1366 Delphi Delphi generator, lirbrary and unit test. +THRIFT-1130 Compiler (General) Add the ability to specify symbolic default value for optional boolean +THRIFT-1381 C++ Thrift C++ libs have incorrectly versioned names +THRIFT-1384 Javame Java help menu missing newline near javame flag +THRIFT-1373 C++ Fix user-defined exception generation in thrift (python) +THRIFT-1379 C++ fix uninitialized enum values in thrift C++ objects +THRIFT-1377 C++ abort PHP deserialization on unknown field type +THRIFT-1376 C++ Make port specification option in thrift remote +THRIFT-1375 C++ fixed a hex char conversion bug in TJSONProtocol +THRIFT-1370 C glib Debian packaging should Build-Depend on libglib2.0-dev +THRIFT-1121 Java Java server performance regression in 0.6 +THRIFT-1365 Java TupleProtocol#writeBitSet unintentionally writes a variable length byte array +THRIFT-1359 C++ --gen-cob cpp:cob_style does not compile anymore +THRIFT-1355 Ruby Running make in lib/rb doesn't build the native extensions +THRIFT-1354 Ruby Add rake task to build just the gem file +THRIFT-857 Test Suite tests run by "make install" fail if generators are disabled +THRIFT-1339 Java Extend Tuple Protocol to TUnions +THRIFT-1331 Ruby Ruby library deserializes an empty map to nil +THRIFT-1350 Go Go library code does not build as of r60 (most recent release) +THRIFT-1227 Erlang Erlang implementation of thrift JSON protocol +THRIFT-1335 C++ Add accept timeout to TServerSocket +THRIFT-1345 Build Process Allow building without tests +THRIFT-1342 Python Compilation problem on Windows of fastbinary.c +THRIFT-1341 C++ TProtocol.h endian detection wrong with boost +THRIFT-1243 C++ TAsyncChannel callbacks +THRIFT-1238 JavaScript Thrift JS client cannot read map of structures +THRIFT-1333 C++ Make RWGuard not copyable +THRIFT-1334 C++ Add more info to IllegalStateException +THRIFT-1332 Java TSSLTransportParameters class uses hard coded value keyManagerType: SunX509 +THRIFT-1328 Java TBaseHelper.toString(...) appends ByteBuffer data outside of valid buffer range +THRIFT-1322 OCaml OCaml lib fail to compile: Thrift.ml line 305, int vs int32 mismatch +THRIFT-1279 PHP type set is handled incorrectly when writing object +THRIFT-1320 C++ Consistency of configure generated config.h +THRIFT-1319 Java Mismatch between how a union reads and writes a container +THRIFT-1316 C++ thrift: update server classes to accept +THRIFT-1314 C++ thrift: add TProcessorFactory +THRIFT-1315 C++ thrift: generate server interface factory classes +THRIFT-1317 C++ Remove copy constructibility from +THRIFT-1305 C++ thrift: make TConnection a private inner class of +THRIFT-1286 Ruby Modernize the Thrift Ruby Library Dev Environment +THRIFT-1304 C++ TNonblockingServer: pass in the connection context to +THRIFT-1302 C++ thrift: raise an exception if send() times out in +THRIFT-1301 C++ thrift: consolidate common code in TNonblockingServer +THRIFT-1298 Java Standard scheme doesn't read or write metadata along with field values +THRIFT-1257 Java thrift's dependency scope on javax.servlet:servlet-api should be 'provided' +THRIFT-1240 PHP TBinarySerializer invalid serialization due to TBufferTransport not flushing +THRIFT-1295 C++ Duplicate include in TSocket.cpp +THRIFT-1294 C++ thrift: fix log message typos in TSimpleServer +THRIFT-1293 C++ thrift: improve handling of exceptions thrown by +THRIFT-1292 C++ thrift: silence log spew from TThreadedServer +THRIFT-1290 C++ thrift: TNonblockingServer: clean up state in the +THRIFT-1289 C++ thrift: implement TNonblockingServer::stop() +THRIFT-1288 C++ Allow typedefed exceptions in throws clauses +THRIFT-1287 C++ thrift: start refactoring some of the C++ processor +THRIFT-1280 C++ Thrift: Improve Monitor exception-free interfaces +THRIFT-1281 Compiler (General) add @generated to the docblock +THRIFT-1282 Java Upgrade httpclient to 4.1.2 (from 4.0.1) +THRIFT-1284 C++ thrift: fix processor inheritance +THRIFT-1283 C++ thrift: wrap t_cpp_generator::generate_process_function() to 80 +THRIFT-1278 Java javadoc warnings - compilation +THRIFT-1254 JavaME Code compiled against a regular JRE: Object.clone() override has a different return type +THRIFT-1271 C++ thrift: fix missing namespace in generated local +THRIFT-1274 C++ thrift: fail compilation if an unexpected token is +THRIFT-1275 C++ thrift: always prefix namespaces with " ::" +THRIFT-1265 C++ C++ container deserialize +THRIFT-1167 Java Java nonblocking server with more than one thread for select and handling IO +THRIFT-380 Python Use setuptools for python build +THRIFT-1270 C++ thrift: add --allow-neg-keys argument to allow +THRIFT-1263 Ruby publish ruby client to rubygems +THRIFT-1205 Java port server unduly fragile with arbitrary input +THRIFT-769 Java Pluggable Serializers +THRIFT-1239 Java TupleProtocol- An extremely compact, temporary protocol + + Version 0.7.0 THRIFT-1252 Ruby Segfault in Ruby deserializer @@ -72,17 +353,17 @@ THRIFT-1234 Python thrift --help is missing doc on py:utf8string THRIFT-1237 Java Java fb303 missing some methods THRIFT-1248 C++ pointer subtraction in TMemoryBuffer relies on undefined behavior THRIFT-1253 Java Code generated for maps is not compiling -THRIFT-1255 Java Mismatch of method name between JavaME's lib and generated code (compareTo/compareObjects) +THRIFT-1255 Java Mismatch of method name between JavaME's lib and generated code (compareTo/compareObjects) THRIFT-1238 JavaScript Thrift JS client cannot read map of structures THRIFT-1213 Membuffer should provide a way to get back the buffer -THRIFT-1117 JavaScript JavaScript Unit Test does not work anymore because libthrift*.jar where moved by Maven Deployment +THRIFT-1117 JavaScript JavaScript Unit Test does fail due to libthrift*.jar where moved by Maven Deployment THRIFT-1164 JavaScript Segmentation fault on NULL pointer in t_js_generator::generate_const -THRIFT-788 PHP thrift_protocol.so: multiget/multiget_slice does not handle more than 17 keys correctly +THRIFT-788 PHP thrift_protocol.so: multiget/multiget_slice does not handle more than 17 keys correctly THRIFT-1222 C++ Unhandled exception for TEvhttpServer request THRIFT-1241 PHP php namespace generation THRIFT-1236 Erlang Erlang Reconnecting Thrift Client -THRIFT-1151 Erlang Produce more informative runtime error in case of schema and data mismatch during serialization -THRIFT-1146 Java Android Incompatibility : in Android < 2.3 java.io.IOException doesn't support for Throwable +THRIFT-1151 Erlang Produce informative runtime error in case of schema and data mismatch on serialization +THRIFT-1146 Java Android Incompatibility: Android < 2.3 java.io.IOException doesn't support for Throwable THRIFT-826 PHP PHP TSocket Write Timeout THRIFT-27 Erlang Generated erlang types don't contain default values for records THRIFT-1153 C++ HttpClient does not specify the connection close parameter @@ -93,7 +374,7 @@ THRIFT-447 Java Make an abstract base Client class so we can THRIFT-1181 AS3 AS3 compiler generates incorrect code for setting default values in constructor THRIFT-997 Java Using valueOf for base types in getFieldValue THRIFT-999 PHP Add TForkingServer -THRIFT-1041 Java TDeserializer holds onto a reference of the array it reads after it is done deserializing +THRIFT-1041 Java TDeserializer holds onto a reference of the array it reads after it is done deserializing THRIFT-1065 JavaScript Unexpected exceptions not proper handled on JS THRIFT-993 C++ Some improvements in C++ stubs for oneway operations THRIFT-1083 Python Preforking python process pool server diff --git a/configure.ac b/configure.ac index 43904ef766e..25f4e363569 100755 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.65) -AC_INIT([thrift], [0.9.0-dev]) +AC_INIT([thrift], [0.9.0]) AC_CONFIG_AUX_DIR([.]) diff --git a/contrib/debian/changelog b/contrib/debian/changelog index 3d26cdd6b72..a889fc2f577 100644 --- a/contrib/debian/changelog +++ b/contrib/debian/changelog @@ -1,3 +1,9 @@ +thrift (0.9.0) stable; urgency=low + + * update to 0.9.0 + + -- Jake Farrell Wed, 10 Oct 2012 12:00:00 -0500 + thrift (0.7.0) stable; urgency=low * update to 0.7.0 diff --git a/contrib/fb303/py/setup.py b/contrib/fb303/py/setup.py index 7feddcba83b..82b14d93d35 100644 --- a/contrib/fb303/py/setup.py +++ b/contrib/fb303/py/setup.py @@ -26,7 +26,7 @@ from distutils.core import setup, Extension, Command setup(name = 'thrift', - version = '0.9.0-dev', + version = '0.9.0', description = 'Python bindings for the Apache Thrift FB303', author = ['Thrift Developers'], author_email = ['dev@thrift.apache.org'], diff --git a/lib/cpp/src/thrift/windows/config.h b/lib/cpp/src/thrift/windows/config.h index fa836e4a2e1..3ec2db8c278 100644 --- a/lib/cpp/src/thrift/windows/config.h +++ b/lib/cpp/src/thrift/windows/config.h @@ -31,7 +31,7 @@ #pragma warning(disable: 4996) // Depreciated posix name. #pragma warning(disable: 4250) // Inherits via dominance. -#define VERSION "0.9.0-dev" +#define VERSION "0.9.0" #define HAVE_GETTIMEOFDAY 1 #define HAVE_SYS_STAT_H 1 diff --git a/lib/csharp/src/Properties/AssemblyInfo.WP7.cs b/lib/csharp/src/Properties/AssemblyInfo.WP7.cs index 697d7aa4ca2..4f804bc4e62 100644 --- a/lib/csharp/src/Properties/AssemblyInfo.WP7.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.WP7.cs @@ -51,6 +51,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.9.0.0")] [assembly: AssemblyFileVersion("0.9.0.0")] diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs index 0b39006a976..cdab35614b5 100644 --- a/lib/csharp/src/Properties/AssemblyInfo.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.cs @@ -51,6 +51,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.9.0.*")] -[assembly: AssemblyFileVersion("0.9.0.*")] +[assembly: AssemblyVersion("0.9.0.0")] +[assembly: AssemblyFileVersion("0.9.0.0")] diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index 8b13406cff6..68e1f7de46c 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -25,7 +25,7 @@ interface SysUtils, Thrift.Protocol; const - Version = '0.9.0-dev'; + Version = '0.9.0'; type IProcessor = interface diff --git a/lib/erl/src/thrift.app.src b/lib/erl/src/thrift.app.src index 88ca4bcc80c..fd556b4e44f 100644 --- a/lib/erl/src/thrift.app.src +++ b/lib/erl/src/thrift.app.src @@ -23,7 +23,7 @@ {description, "Thrift bindings"}, % The version of the applicaton - {vsn, "0.9.0-dev"}, + {vsn, "0.9.0"}, % All modules used by the application. {modules, [ diff --git a/lib/hs/Thrift.cabal b/lib/hs/Thrift.cabal index cf02e1233f3..d5e92e11361 100644 --- a/lib/hs/Thrift.cabal +++ b/lib/hs/Thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 0.9.0-dev +Version: 0.9.0 Cabal-Version: >= 1.4 License: OtherLicense Category: Foreign diff --git a/lib/java/build.properties b/lib/java/build.properties index 6e31bb48fce..8b3f990a2ee 100644 --- a/lib/java/build.properties +++ b/lib/java/build.properties @@ -1,5 +1,6 @@ thrift.version=0.9.0 thrift.groupid=org.apache.thrift +release=true # Jar Versions mvn.ant.task.version=2.1.3 diff --git a/lib/js/thrift.js b/lib/js/thrift.js index 2de5f1a30c5..e8436b99127 100644 --- a/lib/js/thrift.js +++ b/lib/js/thrift.js @@ -17,7 +17,7 @@ * under the License. */ var Thrift = { - Version: '0.9.0-dev', + Version: '0.9.0', /* Description: 'JavaScript bindings for the Apache Thrift RPC system', License: 'http://www.apache.org/licenses/LICENSE-2.0', diff --git a/lib/nodejs/package.json b/lib/nodejs/package.json index 386b7dfa6ec..015449d0549 100644 --- a/lib/nodejs/package.json +++ b/lib/nodejs/package.json @@ -6,7 +6,7 @@ { "type" : "svn", "url" : "http://svn.apache.org/repos/asf/thrift/trunk/" }, - "version": "0.9.0-dev", + "version": "0.9.0", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm index f3ff287f862..5c2b991c044 100644 --- a/lib/perl/lib/Thrift.pm +++ b/lib/perl/lib/Thrift.pm @@ -17,7 +17,7 @@ # under the License. # -our $VERSION = '0.9.0-dev'; +our $VERSION = '0.9.0'; require 5.6.0; use strict; diff --git a/lib/py/setup.py b/lib/py/setup.py index 5e4f923e918..f1e775cae71 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -66,7 +66,7 @@ def run_setup(with_binary): extensions = dict() setup(name = 'thrift', - version = '0.9.0-dev', + version = '0.9.0', description = 'Python bindings for the Apache Thrift RPC system', author = ['Thrift Developers'], author_email = ['dev@thrift.apache.org'], diff --git a/test/nodejs/package.json b/test/nodejs/package.json index 09c6b2c695d..627abb4ec45 100644 --- a/test/nodejs/package.json +++ b/test/nodejs/package.json @@ -1,6 +1,6 @@ { "name": "thrift-nodejs-test", - "version": "0.9.0-dev", + "version": "0.9.0", "description": "node.js test server and client for the Apache Thrift", "homepage": "http://thrift.apache.org/", "repository": From 1a15f7ceda9e0ed137a1a9808ed2a1b997ee78aa Mon Sep 17 00:00:00 2001 From: Jake Farrell Date: Fri, 12 Oct 2012 00:45:34 +0000 Subject: [PATCH 058/756] Thrift-1643:Denial of Service attack in TBinaryProtocol.readString Client: java Patch: Niraj Tolia In readString, if the string field's size is greater than the number of bytes remaining in the byte array to deserialize, libthrift will happily allocate a byte array of that size in readStringBody, filling the heap. git-svn-id: https://svn.apache.org/repos/asf/thrift/branches/0.9.x@1397398 13f79535-47bb-0310-9956-ffa450edef68 --- .../thrift/protocol/TCompactProtocol.java | 19 +++++++++++-------- .../thrift/protocol/TestTBinaryProtocol.java | 18 ++++++++++++++++++ .../thrift/protocol/TestTCompactProtocol.java | 18 ++++++++++++++++++ 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java index 3db256defc4..7b273c5e039 100644 --- a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java +++ b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java @@ -639,15 +639,12 @@ public double readDouble() throws TException { */ public String readString() throws TException { int length = readVarint32(); + checkReadLength(length); if (length == 0) { return ""; } - if (maxNetworkBytes_ != -1 && length > maxNetworkBytes_) { - throw new TException("Read size greater than max allowed."); - } - try { if (trans_.getBytesRemainingInBuffer() >= length) { String str = new String(trans_.getBuffer(), trans_.getBufferPosition(), length, "UTF-8"); @@ -666,12 +663,9 @@ public String readString() throws TException { */ public ByteBuffer readBinary() throws TException { int length = readVarint32(); + checkReadLength(length); if (length == 0) return ByteBuffer.wrap(new byte[0]); - if (maxNetworkBytes_ != -1 && length > maxNetworkBytes_) { - throw new TException("Read size greater than max allowed."); - } - byte[] buf = new byte[length]; trans_.readAll(buf, 0, length); return ByteBuffer.wrap(buf); @@ -688,6 +682,15 @@ private byte[] readBinary(int length) throws TException { return buf; } + private void checkReadLength(int length) throws TProtocolException { + if (length < 0) { + throw new TProtocolException("Negative length: " + length); + } + if (maxNetworkBytes_ != -1 && length > maxNetworkBytes_) { + throw new TProtocolException("Length exceeded max allowed: " + length); + } + } + // // These methods are here for the struct to call, but don't have any wire // encoding. diff --git a/lib/java/test/org/apache/thrift/protocol/TestTBinaryProtocol.java b/lib/java/test/org/apache/thrift/protocol/TestTBinaryProtocol.java index 0cfd9377af2..a2f79d79fa0 100644 --- a/lib/java/test/org/apache/thrift/protocol/TestTBinaryProtocol.java +++ b/lib/java/test/org/apache/thrift/protocol/TestTBinaryProtocol.java @@ -19,6 +19,11 @@ package org.apache.thrift.protocol; +import org.apache.thrift.TDeserializer; +import org.apache.thrift.TException; + +import thrift.test.Bonk; + public class TestTBinaryProtocol extends ProtocolTestBase { @Override protected TProtocolFactory getFactory() { @@ -29,4 +34,17 @@ protected TProtocolFactory getFactory() { protected boolean canBeUsedNaked() { return true; } + + public void testOOMDenialOfService() throws Exception { + TDeserializer deser = new TDeserializer(new TBinaryProtocol + .Factory(false, false, 1000)); + Bonk bonk = new Bonk(); + try { + // Invalid read length specified here. Would cause an OOM + // without the limit on the read length + deser.deserialize(bonk, new byte[]{11, 0, 1, 127, -1, -1, -1}); + } catch (TException e) { + // Ignore as we are only checking for OOM in the failure case + } + } } diff --git a/lib/java/test/org/apache/thrift/protocol/TestTCompactProtocol.java b/lib/java/test/org/apache/thrift/protocol/TestTCompactProtocol.java index f0d78955ede..b4c0888a409 100644 --- a/lib/java/test/org/apache/thrift/protocol/TestTCompactProtocol.java +++ b/lib/java/test/org/apache/thrift/protocol/TestTCompactProtocol.java @@ -20,6 +20,10 @@ package org.apache.thrift.protocol; +import org.apache.thrift.TDeserializer; +import org.apache.thrift.TException; + +import thrift.test.Bonk; public class TestTCompactProtocol extends ProtocolTestBase { @Override @@ -32,6 +36,20 @@ protected boolean canBeUsedNaked() { return true; } + public void testOOMDenialOfService() throws Exception { + // Struct header, Integer.MAX_VALUE length, and only one real + // byte of data + byte [] bytes = {24, -1, -1, -1, -17, 49}; + TDeserializer deser = new TDeserializer(new TCompactProtocol + .Factory(1000)); + Bonk bonk = new Bonk(); + try { + deser.deserialize(bonk, bytes); + } catch (TException e) { + // Ignore as we are only checking for OOM in the failure case + } + } + public static void main(String args[]) throws Exception { new TestTCompactProtocol().benchmark(); } From 352a50eb36b851bfb3f69469db580e6edfd6250f Mon Sep 17 00:00:00 2001 From: jfarrell Date: Fri, 29 Mar 2013 10:51:58 -0500 Subject: [PATCH 059/756] Thrift-1743: Add Composer.json for Thrift 0.9.x release Client: PHP Patch: Xavier HAUSHERR Adds the composer.json file for the specific release for publishing the php client. --- composer.json | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 00000000000..b6318bc6f95 --- /dev/null +++ b/composer.json @@ -0,0 +1,31 @@ +{ + "name": "apache/thrift", + "description": "Apache Thrift RPC system", + "homepage": "http://thrift.apache.org/", + "type": "library", + "license": "Apache-2.0", + "authors": [ + { + "name": "Apache Thrift Developers", + "email": "dev@thrift.apache.org", + "homepage": "http://thrift.apache.org" + } + ], + "support": { + "email": "dev@thrift.apache.org", + "issues": "https://issues.apache.org/jira/browse/THRIFT" + }, + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-0": {"Thrift": "lib/php/src/"} + }, + "target-dir": "lib/php", + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "0.9.x-dev" + } + } +} From ff980c1432936c6bc897c60469ab05b5e0c6cb5e Mon Sep 17 00:00:00 2001 From: jfarrell Date: Sun, 18 Aug 2013 19:54:39 -0400 Subject: [PATCH 060/756] 0.9.1 versioning and CHANGES --- CHANGES | 196 ++++++++++++++++++ configure.ac | 2 +- contrib/thrift.spec | 4 +- debian/changelog | 8 +- doap.rdf | 7 +- .../Properties/AssemblyInfo.cs | 4 +- lib/csharp/src/Properties/AssemblyInfo.cs | 4 +- lib/d/src/thrift/base.d | 2 +- lib/delphi/src/Thrift.pas | 2 +- lib/erl/src/thrift.app.src | 2 +- lib/hs/Thrift.cabal | 2 +- lib/java/build.properties | 4 +- lib/js/thrift.js | 2 +- lib/nodejs/package.json | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/py/setup.py | 2 +- lib/rb/thrift.gemspec | 2 +- 17 files changed, 225 insertions(+), 22 deletions(-) diff --git a/CHANGES b/CHANGES index 637cd8ae3a5..3275de4c13e 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,202 @@ Thrift Changelog Version 1.0 - Coming Soon +Version 0.9.1 + +THRIFT-2137 Ruby Ruby test lib fails jenkins build #864 +THRIFT-2136 Build Proces Vagrant build not compiling java, ruby, php, go libs due to missing dependencies +THRIFT-2135 Go GO lib leaves behind test files that are auto generated +THRIFT-2134 Compiler mingw-cross-compile script failing with strip errors +THRIFT-2133 Java java TestTBinaryProtocol.java test failing +THRIFT-2129 PHP php ext missing from dist +THRIFT-2128 Go lib GO tests fail with funct ends without a return statement +THRIFT-2126 C++ lib/cpp/src/thrift/concurrency/STD* files missing from DIST +THRIFT-2125 Build Process debian missing from DIST +THRIFT-2124 Build Process .o, .so, .la, .deps, .libs, gen-* files left tutorials, test and lib/cpp when making DIST +THRIFT-2123 GO lib missing files in DIST build +THRIFT-2118 Certificate error handling still incorrect +THRIFT-2117 Cocoa Cocoa TBinaryProtocol strictWrite should be set to true by default +THRIFT-2112 Go Error in Go generator when using typedefs in map keys +THRIFT-2109 Secure connections should be supported in Go +THRIFT-2107 Go minor Go generator fixes +THRIFT-2106 Fix support for namespaces in GO generator +THRIFT-2105 Generated code for default values of collections ignores t_field::T_REQUIRED +THRIFT-2102 constants are not referencing to correct type when included from another thrift file +THRIFT-2100 typedefs are not correctly referenced when including from other thrift files +THRIFT-2091 Unnecessary 'friend' declaration causes warning in TWinsockSingleton +THRIFT-2090 Go Go generator, fix including of other thrift files +THRIFT-2088 Compiler Typos in Thrift compiler help text +THRIFT-2084 Delphi Delphi: Ability to create entity Thrift-generated instances based on TypeInfo +THRIFT-2083 Go Improve the go lib: buffered Transport, save memory allocation, handle concurrent request +THRIFT-2082 Build Process Executing "gmake clean" is broken +THRIFT-2081 Specified timeout should be used in TSocket.Open() +THRIFT-2080 C# C# multiplex processor does not catch IOException +THRIFT-2070 Improper `HexChar' and 'HexVal' implementation in TJSONProtocol.cs +THRIFT-2066 Build Process 'make install' does not install two headers required for C++ bindings +THRIFT-2065 Java Not valid constants filename in Java +THRIFT-2057 Build Process Vagrant fails on php tests +THRIFT-2052 Build Process Vagrant machine image defaults to only 384MB of RAM +THRIFT-2051 Build Process Vagrant fails to build erlang +THRIFT-2050 Build Process Vagrant C# lib compile fails with TException missing +THRIFT-2047 Thrift.Protocol.TCompactProtocol, intToZigZag data lost (TCompactProtocol.cs) +THRIFT-2036 Thrift gem warns about class variable access from top level +THRIFT-2032 C# C# client leaks sockets/handles +THRIFT-2017 Compiler Resource Leak in thrift struct under compiler/cpp/src/parse/t_program.h +THRIFT-2014 C++ Change C++ lib includes to use style throughout +THRIFT-2012 Go Modernizing Go +THRIFT-2003 Deprecate senum +THRIFT-2002 Haskell Haskell: Test use Data.Maybe instead of Maybe +THRIFT-2001 Website http://thrift.apache.org/ Example "C++ Server" tab is broken +THRIFT-1997 Add accept backlog configuration method to TServerSocket +THRIFT-1996 JavaME JavaME Constants generation is broken / inconsistent with regular Java generation +THRIFT-1995 Compiler '.' allowed at end of identifier generates non-compilable code +THRIFT-1994 Compiler Deprecate slist +THRIFT-1993 Delphi Factory to create instances from known (generated) interface types with Delphi +THRIFT-1992 casts in TCompactProtocol.tcc causing "dereferencing type-punned pointer will break strict- +THRIFT-1988 When trying to build a debian package it fails as the file NEWS doesn't exist +THRIFT-1985 Build Process add a Vagrantfile to build and test Apache Thrift fully reproducable +THRIFT-1984 Python namespace collision in python bindings +THRIFT-1980 Go Modernize Go tooling, fix go client libary. +THRIFT-1978 Ruby Ruby: Thrift should allow for the SSL verify mode to be set +THRIFT-1977 C# C# compiler should generate constant files prefixed with thrift file name +THRIFT-1975 TBinaryProtocol CheckLength can't be used for a client +THRIFT-1973 C# TCompactProtocol in C# lib does not serialize and deserialize negative int32 and int64 numb +THRIFT-1972 Java Add support for async processors +THRIFT-1971 Tutorial [Graphviz] Adds tutorial/general description documentation +THRIFT-1970 [Graphviz] Adds option to render exceptions relationships +THRIFT-1969 C# C#: Tests not properly linked from the solution +THRIFT-1966 Support different files for SSL certificates and keys +THRIFT-1965 Adds Graphviz (graph description language) generator +THRIFT-1962 Multiplex processor should send any TApplicationException back to client +THRIFT-1961 C# C# tests should be in lib/csharp/test/... +THRIFT-1960 main() declares 22 unused gen bools +THRIFT-1959 C# C#: Add Union TMemoryBuffer support +THRIFT-1958 C# C#: Use static Object.Equals instead of .Equals() calls in equals +THRIFT-1957 Node.js NodeJS TFramedTransport and TBufferedTransport read bytes as unsigned +THRIFT-1956 Java Switch to Apache Commons Lang 3 +THRIFT-1955 Union Type writer generated in C# does not WriteStructBegin +THRIFT-1952 Build Process Travis CI +THRIFT-1951 Java libthrift.jar has source files in it +THRIFT-1949 WP7 build broken +THRIFT-1943 docstrings for enum values are ignored +THRIFT-1942 PHP Binary accelerated cpp extension does not use Thrift namespaces for Exceptions +THRIFT-1934 Tutorial Tabs in Example section on main page are not working +THRIFT-1933 Delphi generator crashes when a typedef references another typedef from an included file +THRIFT-1930 C# C# generates unsigned byte for Thrift "byte" type +THRIFT-1929 Website Update website to use Mirrors for downloads +THRIFT-1928 Race may still exist in TFileTransport::flush() +THRIFT-1924 Delphi Delphi: Inconsistency in serialization of optional fields +THRIFT-1922 C# C#: Inconsistency in serialization of optional fields +THRIFT-1919 libthrift depends on httpcore-4.1.3 (directly) and httpcore-4.1.4 (transitively) +THRIFT-1913 skipping unknown fields in java unions +THRIFT-1907 Compiling namespace and sub-namespace directives for unrecognized generators should only be +THRIFT-1904 Incorrect code is generated for typedefs which use included types +THRIFT-1903 PHP PHP namespaces cause binary protocols to not be used +THRIFT-1902 C++ C++: Support for Multiplexing Services on any Transport, Protocol and Server +THRIFT-1901 C# C#: Support for Multiplexing Services on any Transport, Protocol and Server +THRIFT-1899 Celphi Delphi: Support for Multiplexing Services on any Transport, Protocol and Server +THRIFT-1897 Support validation of required fields +THRIFT-1896 Cocoa Add TBase protocol for Cocoa +THRIFT-1895 Delphi Delphi: reserved variable name "result" not detected properly +THRIFT-1890 C++ C++: Make named pipes server work asynchronously +THRIFT-1888 Java Java Thrift client can't connect to Python Thrift server on same host +THRIFT-1882 Use single include +THRIFT-1881 TNonblockingServer does not release open connections or threads on shutdown +THRIFT-1880 Make named pipes server work asynchronously (overlapped) to allow for clean server stops +THRIFT-1878 Add the possibility to send custom headers +THRIFT-1876 Use enum names instead of casted integers in assignments +THRIFT-1874 timeout for the server-side end of a named pipe +THRIFT-1873 Binary protocol factory ignores struct read/write flags +THRIFT-1872 issues with TBufferedTransport buffer +THRIFT-1869 Java TThreadPoolServer (java) dies when threadpool is consumed +THRIFT-1864 implement event handler for non-blocking server +THRIFT-1859 C++ Generated error c++ code with -out and include_prefix param +THRIFT-1850 make check hangs on TSocket tests in TransportTest.cpp +THRIFT-1846 Restore socket.h header to support builds with Android NDK +THRIFT-1842 Memory leak with Pipes +THRIFT-1838 Compiler Can't build compiler on OS X because of missing thrifty.h +THRIFT-1831 Bug in list deserializer +THRIFT-1824 many compile warning, becase Thread.h includes config.h +THRIFT-1823 Missing parenthesis breaks "IS_..." macro in generated code +THRIFT-1822 PHP unit test does not work +THRIFT-1816 Need "require" included thrift files in "xxx_types.js" +THRIFT-1815 Code generators line buffer output +THRIFT-1806 Python generation always truncates __init__.py files +THRIFT-1804 Build Proces Binary+compact protocol single byte error in Ruby library (ARM architecture): caused by dif +THRIFT-1800 Documentation text not always escaped correctly when rendered to HTML +THRIFT-1799 Option to generate HTML in "standalone mode" +THRIFT-1794 C# C# asyncctp broken +THRIFT-1793 C# C#: Use static read instead of instance read +THRIFT-1791 Haskell thrift's namespace directive when generating haskell code +THRIFT-1788 C# C#: Constants static constructor does not compile +THRIFT-1786 C# C# Union Typing +THRIFT-1785 C# C#: Add TMemoryBuffer serializer/deserializer +THRIFT-1783 C# C# doesn't handle required fields correctly +THRIFT-1782 Javascript async only defined in silverlight +THRIFT-1780 Add option to generate nullable values +THRIFT-1779 Missing process_XXXX method in generated TProcessor implementation for all 'oneway' service +THRIFT-1778 Configure requires manual intervention due to tar failure +THRIFT-1777 TPipeServer is UNSTOPPABLE +THRIFT-1773 Python Python library should run on python 2.4 +THRIFT-1769 unions can't have required fields (C++) +THRIFT-1768 unions can't have required fields (Compiler) +THRIFT-1767 unions can't have required fields (Delphi) +THRIFT-1765 Incorrect error message printed for null or negative keys +THRIFT-1764 how to get the context of client when on a rpc call in server side? +THRIFT-1756 Build Process 'make -j 8' fails with "unterminated #ifdef" error +THRIFT-1753 C++ Multiple C++ Windows, OSX, and iOS portability issues +THRIFT-1749 Python Python TSSLSocket error handling obscures actual error +THRIFT-1748 Guard and RWGuard macros defined in global namespace +THRIFT-1742 C# Optionally implement hashcode and equals in c# +THRIFT-1740 C++ Make C++ library build on OS X and iOS +THRIFT-1739 Node.js missing license header in node.js files +THRIFT-1735 Tutorials integrate tutorial into regular build +THRIFT-1734 Website Front webpage is still advertising v0.8 as current release +THRIFT-1733 Build Process Fix RPM build issues on RHEL6/OL6 systems +THRIFT-1729 GLibC C glib refactor left empty folders in svn +THRIFT-1728 Upgradation of httpcomponents +THRIFT-1720 Ruby JRuby times out on successful connection +THRIFT-1716 max allowed connections should be PIPE_UNLIMITED_INSTANCES +THRIFT-1715 Allow excluding python parts when building contrib/fb303 +THRIFT-1713 Named and Anonymous Pipe transport (Delphi) +THRIFT-1699 Native Union#read has extra read_field_end call +THRIFT-1695 allow warning-free compilation in VS 2012 and GNU 4.6 +THRIFT-1681 Lua Add Lua Support +THRIFT-1666 CPP htonll usage in TBinaryProtocol.tcc generates warning with MSVC2010 +THRIFT-1660 Python Python Thrift library can be installed with pip but not easy_install +THRIFT-1657 Javascript Chrome browser sending OPTIONS method before POST in xmlHttpRequest +THRIFT-1648 Node.js NodeJS clients always receive 0 for 'double' values. +THRIFT-1637 Node.js NPM registry does not include version 0.8 +THRIFT-1629 Ruby Ruby 1.9 Compatibility during Thrift configure, make, install +THRIFT-1614 Thrift build from svn repo sources fails with automake-1.12 +THRIFT-1603 Thrift IDL allows for multiple exceptions, args or struct member names to be the same +THRIFT-1600 Go - Compile Thrift Go Compiler and Library out of date with Go 1 Release. +THRIFT-1595 Java test server should follow the documented behavior as of THRIFT-1590 +THRIFT-1594 Java test clients should have a return codes that reflect whether it succeeds or not. +THRIFT-1574 Apache project branding requirements: DOAP file [PATCH] +THRIFT-1440 debian packaging: minor-ish policy problems +THRIFT-1402 Generated Y_types.js does not require() X_types.js when an include in the IDL file was used +THRIFT-1353 Switch to performance branch, get rid of BinaryParser +THRIFT-1347 GO Unify the exceptions returned in generated Go code +THRIFT-1264 Cocoa TSocketClient is queried by run loop after deallocation in Cocoa +THRIFT-1062 Python Problems with python tutorials +THRIFT-991 Haskell Refactor Haskell code and generator +THRIFT-990 C++ Sanify gettimeofday usage codebase-wide +THRIFT-986 Smalltalk st: add version Info to the library +THRIFT-985 PHP php: add version Info to the library +THRIFT-984 OCaml ocaml: add version Info to the library +THRIFT-930 Haskell Ruby and Haskell bindings don't properly support DESTDIR (makes packaging painful) +THRIFT-864 default value fails if identifier is a struct +THRIFT-820 The readLength attribute of TBinaryProtocol is used as an instance variable and is decremen +THRIFT-801 Ruby Provide an interactive shell (irb) when generating ruby bindings +THRIFT-791 C++ Let C++ TSimpleServer be driven by an external main loop +THRIFT-591 Make the C++ runtime library be compatible with Windows and Visual Studio +THRIFT-563 Support for Multiplexing Services on any Transport, Protocol and Server +THRIFT-514 Compiler Add option to configure compiler output directory +THRIFT-474 Ruby Generating Ruby on Rails friendly code +THRIFT-274 Build Process Towards a working release/versioning process + + Version 0.9.0 THRIFT-164 Website Build web tutorial on Incubator web site diff --git a/configure.ac b/configure.ac index 9dd0e2da6e4..93e1a57aa03 100755 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.65) -AC_INIT([thrift], [1.0.0-dev]) +AC_INIT([thrift], [0.9.1]) AC_CONFIG_AUX_DIR([.]) diff --git a/contrib/thrift.spec b/contrib/thrift.spec index b0bccb2dd23..d95a502649b 100644 --- a/contrib/thrift.spec +++ b/contrib/thrift.spec @@ -24,7 +24,7 @@ Name: thrift License: Apache License v2.0 Group: Development Summary: RPC and serialization framework -Version: 0.9.0 +Version: 0.9.1 Release: 0 URL: http://thrift.apache.org Packager: Thrift Developers @@ -178,5 +178,7 @@ umask 007 /sbin/ldconfig > /dev/null 2>&1 %changelog +* Wed Aug 21 2013 Thrift Dev +- Thrift 0.9.1 release. * Wed Oct 10 2012 Thrift Dev - Thrift 0.9.0 release. diff --git a/debian/changelog b/debian/changelog index f2da2327e3c..ebe30e9db0a 100755 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,8 @@ -thrift (1.0.0-dev) stable; urgency=low - * update version - * fix libthrift0.install +thrift (0.9.1) stable; urgency=low - -- Roger Meier Tue, 08 Jan 2013 22:40:12 +0100 + * update to 0.9.1 + + -- Jake Farrell Sun, 18 Aug 2013 12:00:00 -0500 thrift (0.9.0) stable; urgency=low diff --git a/doap.rdf b/doap.rdf index 80e7fa7b7ac..f110e4324f9 100755 --- a/doap.rdf +++ b/doap.rdf @@ -57,7 +57,12 @@ Apache Thrift - 2011-10-15 + 2013-08-22 + 0.9.1 + + + Apache Thrift + 2012-10-15 0.9.0 diff --git a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs index 2e08e66787a..e0a5702f50c 100644 --- a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs +++ b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs @@ -56,5 +56,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.9.0.*")] -[assembly: AssemblyFileVersion("0.9.0.*")] +[assembly: AssemblyVersion("0.9.1.*")] +[assembly: AssemblyFileVersion("0.9.1.*")] diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs index dcbe74738b8..101e6bf4d0a 100644 --- a/lib/csharp/src/Properties/AssemblyInfo.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.1")] -[assembly: AssemblyFileVersion("1.0.0.1")] +[assembly: AssemblyVersion("0.9.1.1")] +[assembly: AssemblyFileVersion("0.9.1.1")] diff --git a/lib/d/src/thrift/base.d b/lib/d/src/thrift/base.d index 266201b73de..3b265cb9e3f 100644 --- a/lib/d/src/thrift/base.d +++ b/lib/d/src/thrift/base.d @@ -50,7 +50,7 @@ class TCompoundOperationException : TException { /// The Thrift version string, used for informative purposes. // Note: This is currently hardcoded, but will likely be filled in by the build // system in future versions. -enum VERSION = "0.9.0 dev"; +enum VERSION = "0.9.1"; /** * Functions used for logging inside Thrift. diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index 44f12d78394..d5a961b6b9e 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -25,7 +25,7 @@ interface SysUtils, Thrift.Protocol; const - Version = '1.0.0-dev'; + Version = '0.9.1'; type IProcessor = interface diff --git a/lib/erl/src/thrift.app.src b/lib/erl/src/thrift.app.src index 90ebc62b45e..db198972c25 100644 --- a/lib/erl/src/thrift.app.src +++ b/lib/erl/src/thrift.app.src @@ -23,7 +23,7 @@ {description, "Thrift bindings"}, % The version of the applicaton - {vsn, "1.0.0-dev"}, + {vsn, "0.9.1"}, % All modules used by the application. {modules, [ diff --git a/lib/hs/Thrift.cabal b/lib/hs/Thrift.cabal index 6dd9146e243..6c22e35f201 100644 --- a/lib/hs/Thrift.cabal +++ b/lib/hs/Thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 1.0.0-dev +Version: 0.9.1 Cabal-Version: >= 1.4 License: OtherLicense Category: Foreign diff --git a/lib/java/build.properties b/lib/java/build.properties index 8d603a681fc..b73c38f5475 100644 --- a/lib/java/build.properties +++ b/lib/java/build.properties @@ -1,6 +1,6 @@ -thrift.version=1.0.0 +thrift.version=0.9.1 thrift.groupid=org.apache.thrift -release=false +release=true # Jar Versions mvn.ant.task.version=2.1.3 diff --git a/lib/js/thrift.js b/lib/js/thrift.js index 39b0a5cc939..5dcfec19e7b 100644 --- a/lib/js/thrift.js +++ b/lib/js/thrift.js @@ -17,7 +17,7 @@ * under the License. */ var Thrift = { - Version: '1.0.0-dev', + Version: '0.9.1', /* Description: 'JavaScript bindings for the Apache Thrift RPC system', License: 'http://www.apache.org/licenses/LICENSE-2.0', diff --git a/lib/nodejs/package.json b/lib/nodejs/package.json index c57a07bab5f..78dc14180d2 100755 --- a/lib/nodejs/package.json +++ b/lib/nodejs/package.json @@ -6,7 +6,7 @@ { "type" : "git", "url" : "https://git-wip-us.apache.org/repos/asf/thrift.git" }, - "version": "1.0.0-dev", + "version": "0.9.1", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm index 67186f23cf9..6bdb375d8b2 100644 --- a/lib/perl/lib/Thrift.pm +++ b/lib/perl/lib/Thrift.pm @@ -17,7 +17,7 @@ # under the License. # -our $VERSION = '1.0.0-dev'; +our $VERSION = '0.9.1'; require 5.6.0; use strict; diff --git a/lib/py/setup.py b/lib/py/setup.py index c196415ce7a..d44fd9cd417 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -66,7 +66,7 @@ def run_setup(with_binary): extensions = dict() setup(name = 'thrift', - version = '1.0.0-dev', + version = '0.9.1', description = 'Python bindings for the Apache Thrift RPC system', author = ['Thrift Developers'], author_email = ['dev@thrift.apache.org'], diff --git a/lib/rb/thrift.gemspec b/lib/rb/thrift.gemspec index 67cc3c9cdb1..daff1de454a 100644 --- a/lib/rb/thrift.gemspec +++ b/lib/rb/thrift.gemspec @@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__) Gem::Specification.new do |s| s.name = 'thrift' - s.version = '0.9.0.1' + s.version = '0.9.1.1' s.authors = ['Thrift Developers'] s.email = ['dev@thrift.apache.org'] s.homepage = 'http://thrift.apache.org' From 9c929c8979fab8d883b83df87034ed81373effb5 Mon Sep 17 00:00:00 2001 From: Roger Meier Date: Fri, 9 May 2014 22:37:51 +0200 Subject: [PATCH 061/756] THRIFT-1743: Add composer.json for new Symfony 2.1 Dependency Manager From 583c1107169ed4ea8880e7e660064797c4759b7a Mon Sep 17 00:00:00 2001 From: Mauro Maggi Date: Fri, 28 Mar 2014 12:27:05 +0100 Subject: [PATCH 1/3] Add Composer.json for Thrift 0.9.1 release Github Pull Request: This closes #90 --- composer.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 00000000000..521841e9405 --- /dev/null +++ b/composer.json @@ -0,0 +1,25 @@ +{ + "name": "apache/thrift", + "description": "Apache Thrift RPC system", + "homepage": "http://thrift.apache.org/", + "type": "library", + "license": "Apache-2.0", + "authors": [ + { + "name": "Apache Thrift Developers", + "email": "dev@thrift.apache.org", + "homepage": "http://thrift.apache.org" + } + ], + "support": { + "email": "dev@thrift.apache.org", + "issues": "https://issues.apache.org/jira/browse/THRIFT" + }, + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-0": {"Thrift": "lib/php/lib/"} + }, + "minimum-stability": "dev" +} From 591e20f9636c37527a70dc03598218c3468a0eff Mon Sep 17 00:00:00 2001 From: jfarrell Date: Tue, 4 Nov 2014 21:12:20 -0500 Subject: [PATCH 062/756] Thrift-2600: 0.9.2 release client: release patch: jfarrell Versioning for 0.9.2 release rc1. --- CHANGES | 783 +++++++++++------- bower.json | 2 +- configure.ac | 2 +- contrib/Rebus/Properties/AssemblyInfo.cs | 4 +- contrib/fb303/py/setup.py | 2 +- contrib/thrift.spec | 4 +- debian/changelog | 8 +- lib/cocoa/src/Thrift.h | 2 +- lib/cpp/src/thrift/windows/config.h | 2 +- .../Properties/AssemblyInfo.cs | 4 +- lib/csharp/src/Properties/AssemblyInfo.WP7.cs | 4 +- lib/csharp/src/Properties/AssemblyInfo.cs | 4 +- .../test/JSON/Properties/AssemblyInfo.cs | 4 +- .../Client/Properties/AssemblyInfo.cs | 4 +- .../Server/Properties/AssemblyInfo.cs | 4 +- .../ThriftTest/Properties/AssemblyInfo.cs | 4 +- lib/d/src/thrift/base.d | 2 +- lib/delphi/src/Thrift.pas | 2 +- lib/erl/src/thrift.app.src | 2 +- lib/hs/Thrift.cabal | 2 +- lib/java/build.properties | 4 +- lib/js/package.json | 2 +- lib/js/src/thrift.js | 2 +- lib/lua/Thrift.lua | 2 +- lib/nodejs/package.json | 2 +- lib/ocaml/_oasis | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/py/setup.py | 2 +- lib/rb/thrift.gemspec | 2 +- lib/st/package.xml | 2 +- sonar-project.properties | 4 +- test/Makefile.am | 3 + test/erl/src/thrift_test.app.src | 2 +- tutorial/ocaml/_oasis | 2 +- 34 files changed, 528 insertions(+), 350 deletions(-) diff --git a/CHANGES b/CHANGES index 28c1f40e00d..0371d1f761b 100644 --- a/CHANGES +++ b/CHANGES @@ -3,409 +3,576 @@ Apache Thrift Changelog Thrift 0.9.2 -------------------------------------------------------------------------------- ## Bug - * [THRIFT-1481] - Unix domain sockets in C++ do not support the abstract namespace - * [THRIFT-1455] - TBinaryProtocolT::writeString casts from size_t to uint32_t, which is not safe on 64-bit platforms - * [THRIFT-1579] - PHP Extention - function thrift_protocol_read_binary not working from TBinarySerializer::deserialize - * [THRIFT-1584] - Error: could not SetMinThreads in ThreadPool on single-core machines - * [THRIFT-1614] - Thrift build from svn repo sources fails with automake-1.12 - * [THRIFT-1047] - rb_thrift_memory_buffer_write treats arg as string without check, segfaults if you pass non-string - * [THRIFT-1639] - Java/Python: Serialization/Deserialization of double type using CompactProtocol - * [THRIFT-1647] - NodeJS BufferedTransport does not work beyond the hello-world example - * [THRIFT-2130] - Thrift's D library/test: parts of "make check" code do not compile with recent dmd-2.062 through dmd-2.064alpha - * [THRIFT-2140] - Error compiling cpp tutorials - * [THRIFT-2139] - MSVC 2012 Error - Cannot compile due to BoostThreadFactory - * [THRIFT-2138] - pkgconfig file created with wrong include path - * [THRIFT-2160] - Warning in thrift.h when compiling with -Wunused and NDEBUG - * [THRIFT-2158] - Compact, JSON, and SimpleJSON protocols are not working correctly - * [THRIFT-2167] - nodejs lib throws error if options argument isn't passed - * [THRIFT-2288] - Go impl of Thrift JSON protocol wrongly writes/expects true/false for bools - * [THRIFT-2147] - Thrift IDL grammar allows for dotted identifier names - * [THRIFT-2145] - Rack and Thin are not just development dependencies - * [THRIFT-2267] - Should be able to choose socket family in Python TSocket - * [THRIFT-2276] - java path in spec file needs updating - * [THRIFT-2281] - Generated send/recv code ignores errors returned by the underlying protocol - * [THRIFT-2280] - TJSONProtocol.Flush() does not really flush the transport - * [THRIFT-2274] - TNonblockingServer and TThreadedSelectorServer do not close their channel selectors on exit and leak file descriptors - * [THRIFT-2265] - php library doesn't build - * [THRIFT-2232] - IsSet* broken in Go - * [THRIFT-2246] - Unset enum value is printed by ToString() - * [THRIFT-2240] - thrift.vim (contrib) does not correctly handle 'union' - * [THRIFT-2243] - TNonblockingServer in thrift crashes when TFramedTransport opens - * [THRIFT-2230] - Cannot Build on RHEL/Centos/Amazon Linux 6.x - * [THRIFT-2247] - Go generator doesn't deal well with map keys of type binary - * [THRIFT-2253] - Python Tornado TTornadoServer base class change - * [THRIFT-2261] - java: error: unmappable character for encoding ASCII - * [THRIFT-2259] - C#: unexpected null logDelegate() pointer causes AV in TServer.serve() - * [THRIFT-2225] - SSLContext destroy before cleanupOpenSSL - * [THRIFT-2224] - TSSLSocket.h and TSSLServerSocket.h should use the platfromsocket too - * [THRIFT-2229] - thrift failed to build on OSX 10.9 GM - * [THRIFT-2227] - Thrift compiler generates spurious warnings with Xlint - * [THRIFT-2219] - Thrift gem fails to build on OS X Mavericks with 1.9.3 rubies - * [THRIFT-2226] - TServerSocket - keepAlive wrong initialization order - * [THRIFT-2285] - TJsonProtocol implementation for Java doesn't allow a slash (/) to be escaped (\/) - * [THRIFT-2216] - Extraneous semicolon in TProtocolUtil.h makes clang mad - * [THRIFT-2215] - Generated HTML/Graphviz lists referenced enum identifiers as UNKNOWN. - * [THRIFT-2211] - Exception constructor does not contain namespace prefix. - * [THRIFT-2210] - lib/java TSimpleJSONProtocol can emit invalid JSON - * [THRIFT-2209] - Ruby generator -- please namespace classes - * [THRIFT-2202] - Delphi TServerImpl.DefaultLogDelegate may stop the server with I/O-Error 105 - * [THRIFT-2201] - Ternary operator returns different types (build error for some compilers) - * [THRIFT-2200] - nested structs cause generate_fingerprint() to slow down at excessive CPU load - * [THRIFT-2197] - fix jar output directory in rpm spec file - * [THRIFT-2196] - Fix invalid dependency in Makefile.am - * [THRIFT-2194] - Node: Not actually prepending residual data in TFramedTransport.receiver - * [THRIFT-2193] - Java code generator emits spurious semicolon when deep copying binary data - * [THRIFT-2191] - Fix charp JSONProtocol.ReadJSONDouble (specify InvariantCulture) - * [THRIFT-2214] - System header sys/param.h is included inside the Thrift namespace - * [THRIFT-2178] - Thrift generator returns error exit code on --version - * [THRIFT-2171] - NodeJS implementation has extremely low test coverage - * [THRIFT-2183] - gem install fails on zsh - * [THRIFT-2182] - segfault in regression tests (GC bug in rb_thrift_memory_buffer_write) - * [THRIFT-2181] - oneway calls don't work in NodeJS - * [THRIFT-2169] - JavaME Thrift Library causes "java.io.IOException: No Response Entries Available" after using the Thrift client for some time - * [THRIFT-2168] - Node.js appears broken (at least, examples don't work as intended) - * [THRIFT-2293] - TSSLTransportFactory.createSSLContext() leaves files open - * [THRIFT-2279] - TSerializer only returns the first 1024 bytes serialized - * [THRIFT-2278] - Buffered transport doesn't support writes > buffer size - * [THRIFT-2275] - Fix memory leak in golang compact_protocol. - * [THRIFT-2282] - Incorect code generated for some typedefs - * [THRIFT-2009] - Go redeclaration error - * [THRIFT-1964] - 'Isset' causes problems with C#/.NET serializers - * [THRIFT-2026] - Fix TCompactProtocol 64 bit builds - * [THRIFT-2108] - Fix TAsyncClientManager timeout race - * [THRIFT-2068] - Multiple calls from same connection are not processed in node - * [THRIFT-1750] - Make compiler build cleanly under visual studio 10 - * [THRIFT-1755] - Comment parsing bug - * [THRIFT-1771] - "make check" fails on x64 for libboost_unit_test_framework.a - * [THRIFT-1841] - NodeJS Thrift incorrectly parses non-UTF8-string types - * [THRIFT-1908] - Using php thrift_protocol accelerated transfer causes core dump - * [THRIFT-1892] - Socket timeouts are declared in milli-seconds, but are actually set in micro-seconds - * [THRIFT-2303] - TBufferredTransport not properly closing underlying transport - * [THRIFT-2313] - nodejs server crash after processing the first request when using MultiplexedProcessor/FramedBuffer/BinaryProtocol - * [THRIFT-2311] - Go: invalid code generated when exception name is a go keyword - * [THRIFT-2308] - node: TJSONProtocol parse error when reading from buffered message - * [THRIFT-2316] - ccp: TFileTransportTest - * [THRIFT-2352] - msvc failed to compile thrift tests - * [THRIFT-2337] - Golang does not report TIMED_OUT exceptions - * [THRIFT-2340] - Generated server implementation does not send response type EXCEPTION on the Thrift.TApplicationExceptionType.UNKNOWN_METHOD exception - * [THRIFT-2354] - Connection errors can lead to case_clause exceptions - * [THRIFT-2339] - Uncaught exception in thrift c# driver - * [THRIFT-2356] - c++ thrift client not working with ssl (SSL_connect hangs) - * [THRIFT-2331] - Missing call to ReadStructBegin() in TApplicationException.Read() - * [THRIFT-2323] - Uncompileable Delphi code generated for typedef'd structs - * [THRIFT-2322] - Correctly show the number of times ExecutorService (java) has rejected the client. - * [THRIFT-2389] - namespaces handled wrongly in acrionscript 3.0 implementation - * [THRIFT-2388] - GoLang - Fix data races in simple_server and server_socket - * [THRIFT-2386] - Thrift refuses to link yylex - * [THRIFT-2375] - Excessive
's in generated HTML - * [THRIFT-2373] - warning CS0414 in THttpClient.cs: private field 'Thrift.Transport.THttpClient.connection' assigned but never used - * [THRIFT-2372] - thrift/json_protocol.go:160: function ends without a return statement - * [THRIFT-2371] - ruby bundler version fails on ~1.3.1, remove and take latest avail - * [THRIFT-2370] - Compiler SEGFAULTs generating HTML documentation for complex strucre - * [THRIFT-2384] - Binary map keys produce uncompilable code in go - * [THRIFT-2380] - unreachable code (CID 1174546, CID 1174679) - * [THRIFT-2378] - service method arguments of binary type lead to uncompileable Go code - * [THRIFT-2363] - Issue with character encoding of Success returned from Login using Thrift Proxy and NodeJS - * [THRIFT-2359] - TBufferedTransport doesn't clear it's buffer on a failed flush call - * [THRIFT-2428] - Python 3 setup.py support - * [THRIFT-2367] - Build failure: stdlib and boost both define uint64_t - * [THRIFT-2365] - C# decodes too many binary bytes from JSON - * [THRIFT-2402] - byte count of FrameBuffer in AWAITING_CLOSE state is not subtracted from readBufferBytesAllocated - * [THRIFT-2396] - Build Error on MacOSX - * [THRIFT-2395] - thrift Ruby gem requires development dependency 'thin' regardless of environment - * [THRIFT-2414] - c_glib fix several bug. - * [THRIFT-2420] - Go argument parser for methods without arguments does not skip fields - * [THRIFT-2439] - Bug in TProtocolDecorator Class causes parsing errors - * [THRIFT-2419] - golang - Fix fmt.Errorf in generated code - * [THRIFT-2418] - Go handler function panics on internal error - * [THRIFT-2405] - Node.js Multiplexer tests fail (silently) + * [THRIFT-2645] - generated Go server code always sets Success retval + * [THRIFT-2634] - undocumented php "nsglobal" option + * [THRIFT-2627] - erlang backend doesn't support corecursive structs + * [THRIFT-2595] - Node.js: Fix global leaks and copy-paste errors + * [THRIFT-2594] - JS Compiler: Single quotes are not being escaped in constants. + * [THRIFT-2610] - MSVC warning in TSocket.cpp + * [THRIFT-2607] - ThreadManager.cpp warning on clang++ 3.4 + * [THRIFT-2609] - TFileTransport.h unused field warning (clang 3.4) + * [THRIFT-2608] - TNonblockingServer.cpp warnings on clang 3.4 + * [THRIFT-2606] - ThreadManager.h warning in clang++ 3.4 + * [THRIFT-2605] - TSocket warning on gcc 4.8.3 + * [THRIFT-2604] - Fix debian packaging + * [THRIFT-2601] - Fix vagrant to work again for builds again + * [THRIFT-2599] - Uncompileable Delphi code due to naming conflicts with IDL + * [THRIFT-2622] - Expecting > 4 bytes, found only 2 + * [THRIFT-2620] - Fix python packaging + * [THRIFT-2619] - Go lib http transport does not handle EOF correctly + * [THRIFT-2618] - Unignore /aclocal files required for build + * [THRIFT-2614] - TNonblockingServer.cpp warnings on MSVC + * [THRIFT-2591] - TFramedTransport does not handle payloads split across packets correctly + * [THRIFT-2679] - golang generation fails for service names less than 5 characters + * [THRIFT-2666] - Usage of PYTHONHASHSEED breaks older Python code + * [THRIFT-2584] - Error handler not listened on javascript client + * [THRIFT-2582] - "FileTransport error" exception is raised when trying to use Java's TFileTransport * [THRIFT-2581] - TFDTransport destructor should not throw - * [THRIFT-2575] - Thrift includes siginfo_t within apache::thrift::protocol namespace + * [THRIFT-2588] - Thrift compiler is not buildable in Visual Studio 2010 * [THRIFT-2577] - TFileTransport missuse of closesocket on windows platform * [THRIFT-2576] - Implement Thrift.Protocol.prototype.skip method in JavaScript library - * [THRIFT-2588] - Thrift compiler is not buildable in Visual Studio 2010 - * [THRIFT-2594] - JS Compiler: Single quotes are not being escaped in constants. - * [THRIFT-2591] - TFramedTransport does not handle payloads split across packets correctly - * [THRIFT-2599] - Uncompileable Delphi code due to naming conflicts with IDL - * [THRIFT-2590] - C++ Visual Studio solution doesn't include Multiplexing support - * [THRIFT-2595] - Node.js: Fix global leaks and copy-paste errors + * [THRIFT-2575] - Thrift includes siginfo_t within apache::thrift::protocol namespace + * [THRIFT-2570] - Wrong URL given in http://thrift.apache.org/developers + * [THRIFT-2559] - Centos 6.5 unable to "make" with Thrift 0.9.1 * [THRIFT-2565] - autoconf fails to find mingw-g++ cross compiler on travis CI * [THRIFT-2555] - excessive "unused field" comments * [THRIFT-2554] - double initialization in generated Read() method - * [THRIFT-2551] - OutOfMemoryError "unable to create new native thread" kills serve thread - * [THRIFT-2543] - Generated enum type in haskell should be qualified + * [THRIFT-2562] - ./configure create MakeFile in lib/d with errors * [THRIFT-2560] - Thrift compiler generator tries to concat ints with strings using + - * [THRIFT-2559] - Centos 6.5 unable to "make" with Thrift 0.9.1 - * [THRIFT-2526] - Assignment operators and copy constructors in c++ don't copy the __isset struct - * [THRIFT-2454] - c_glib: There is no gethostbyname_r() in some OS. - * [THRIFT-2451] - Do not use pointers for optional fields with defaults. Do not write such fields if its value set to default. Also, do not use pointers for any optional fields mapped to go map or slice. generate Get accessors - * [THRIFT-2450] - include HowToContribute in the src repo - * [THRIFT-2448] - thrift/test/test.sh has incorrect Node.js test path - * [THRIFT-2460] - unopened socket fd must be less than zero. - * [THRIFT-2459] - --version should not exit 1 - * [THRIFT-2468] - Timestamp handling - * [THRIFT-2467] - Unable to build contrib/fb303 on OSX 10.9.2 - * [THRIFT-2466] - Improper error handling for SSL/TLS connections that don't complete a handshake - * [THRIFT-2463] - test/py/RunClientServer.py fails sometimes - * [THRIFT-2458] - Generated golang server code for "oneway" methods is incorrect - * [THRIFT-2456] - THttpClient fails when using async support outside Silverlight - * [THRIFT-2524] - Visual Studio project is missing TThreadedServer files - * [THRIFT-2523] - Visual Studio project is missing OverlappedSubmissionThread files - * [THRIFT-2520] - cpp:cob_style generates incorrect .tcc file + * [THRIFT-2545] - Test CPP fails to build (possibly typo) + * [THRIFT-2537] - Path for "go get" does not work (pull request 115) + * [THRIFT-2551] - OutOfMemoryError "unable to create new native thread" kills serve thread + * [THRIFT-2515] - TLS Method error during make * [THRIFT-2508] - Uncompileable C# code due to language keywords in IDL + * [THRIFT-2557] - CS0542 member names cannot be the same as their enclosing type * [THRIFT-2506] - Update TProtocolException error codes to be used consistently throughout the library * [THRIFT-2505] - go: struct should always be a pointer to avoid copying of potentially size-unbounded structs - * [THRIFT-2515] - TLS Method error during make - * [THRIFT-2503] - C++: Fix name collision when a struct has a member named "val" - * [THRIFT-2477] - thrift --help text with misplaced comma + * [THRIFT-2523] - Visual Studio project is missing OverlappedSubmissionThread files + * [THRIFT-2528] - Thrift Erlang Library: Multiple thrift applications in one bundle + * [THRIFT-2533] - Boost version in requirements should be updated + * [THRIFT-2532] - Java version in installation requirements should be updated + * [THRIFT-2529] - TBufferedTransport split Tcp data bug in nodeJs + * [THRIFT-2524] - Visual Studio project is missing TThreadedServer files + * [THRIFT-2520] - cpp:cob_style generates incorrect .tcc file + * [THRIFT-2590] - C++ Visual Studio solution doesn't include Multiplexing support * [THRIFT-2492] - test/cpp does not compile on mac - * [THRIFT-2500] - sending random data crashes thrift(golang) service - * [THRIFT-2475] - c_glib: buffered_transport_write function return always TRUE. - * [THRIFT-2495] - JavaScript/Node string constants lack proper escaping * [THRIFT-2491] - unable to import generated ThriftTest service * [THRIFT-2490] - c_glib: if fail to read a exception from server, client may be occurred double free + * [THRIFT-2489] - Peer host name not provied when performing AccessManager common name verification. + * [THRIFT-2487] - Tutorial requires two IDL files but only one is linked from the Thrift web site + * [THRIFT-2477] - thrift --help text with misplaced comma + * [THRIFT-2340] - Generated server implementation does not send response type EXCEPTION on the Thrift.TApplicationExceptionType.UNKNOWN_METHOD exception + * [THRIFT-2337] - Golang does not report TIMED_OUT exceptions + * [THRIFT-2331] - Missing call to ReadStructBegin() in TApplicationException.Read() + * [THRIFT-2329] - missing release tags within git + * [THRIFT-2323] - Uncompileable Delphi code generated for typedef'd structs + * [THRIFT-2322] - Correctly show the number of times ExecutorService (java) has rejected the client. + * [THRIFT-2316] - ccp: TFileTransportTest + * [THRIFT-2313] - nodejs server crash after processing the first request when using MultiplexedProcessor/FramedBuffer/BinaryProtocol + * [THRIFT-2311] - Go: invalid code generated when exception name is a go keyword + * [THRIFT-2367] - Build failure: stdlib and boost both define uint64_t + * [THRIFT-2365] - C# decodes too many binary bytes from JSON + * [THRIFT-2363] - Issue with character encoding of Success returned from Login using Thrift Proxy and NodeJS + * [THRIFT-2359] - TBufferedTransport doesn't clear it's buffer on a failed flush call + * [THRIFT-2357] - recurse option has no effect when generating php + * [THRIFT-2356] - c++ thrift client not working with ssl (SSL_connect hangs) + * [THRIFT-2354] - Connection errors can lead to case_clause exceptions + * [THRIFT-2352] - msvc failed to compile thrift tests + * [THRIFT-2351] - PHP TCompactProtocol has fails to decode messages + * [THRIFT-2308] - node: TJSONProtocol parse error when reading from buffered message + * [THRIFT-2306] - concurent client calls with nodejs + * [THRIFT-2303] - TBufferredTransport not properly closing underlying transport + * [THRIFT-2285] - TJsonProtocol implementation for Java doesn't allow a slash (/) to be escaped (\/) + * [THRIFT-2282] - Incorect code generated for some typedefs + * [THRIFT-2280] - TJSONProtocol.Flush() does not really flush the transport + * [THRIFT-2281] - Generated send/recv code ignores errors returned by the underlying protocol + * [THRIFT-2279] - TSerializer only returns the first 1024 bytes serialized + * [THRIFT-2278] - Buffered transport doesn't support writes > buffer size + * [THRIFT-2276] - java path in spec file needs updating + * [THRIFT-2275] - Fix memory leak in golang compact_protocol. + * [THRIFT-2240] - thrift.vim (contrib) does not correctly handle 'union' + * [THRIFT-2232] - IsSet* broken in Go + * [THRIFT-2230] - Cannot Build on RHEL/Centos/Amazon Linux 6.x + * [THRIFT-2227] - Thrift compiler generates spurious warnings with Xlint + * [THRIFT-2226] - TServerSocket - keepAlive wrong initialization order + * [THRIFT-2259] - C#: unexpected null logDelegate() pointer causes AV in TServer.serve() + * [THRIFT-2253] - Python Tornado TTornadoServer base class change + * [THRIFT-2248] - Go generator doesn't deal well with map keys of type binary + * [THRIFT-2247] - Go generator doesn't deal well with map keys of type binary + * [THRIFT-2246] - Unset enum value is printed by ToString() + * [THRIFT-2243] - TNonblockingServer in thrift crashes when TFramedTransport opens + * [THRIFT-2225] - SSLContext destroy before cleanupOpenSSL + * [THRIFT-2224] - TSSLSocket.h and TSSLServerSocket.h should use the platfromsocket too + * [THRIFT-2222] - ruby gem cannot be compiled on OS X mavericks + * [THRIFT-2219] - Thrift gem fails to build on OS X Mavericks with 1.9.3 rubies + * [THRIFT-2216] - Extraneous semicolon in TProtocolUtil.h makes clang mad + * [THRIFT-2215] - Generated HTML/Graphviz lists referenced enum identifiers as UNKNOWN. + * [THRIFT-2503] - C++: Fix name collision when a struct has a member named "val" + * [THRIFT-2500] - sending random data crashes thrift(golang) service + * [THRIFT-2498] - Error message "Invalid method name" while trying to call HBase Thrift API + * [THRIFT-2495] - JavaScript/Node string constants lack proper escaping + * [THRIFT-2475] - c_glib: buffered_transport_write function return always TRUE. * [THRIFT-2470] - THttpHandler swallows exceptions from processor - * [THRIFT-2533] - Boost version in requirements should be updated - * [THRIFT-2532] - Java version in installation requirements should be updated - * [THRIFT-2529] - TBufferedTransport split Tcp data bug in nodeJs - * [THRIFT-2537] - Path for "go get" does not work (pull request 115) + * [THRIFT-2468] - Timestamp handling + * [THRIFT-2467] - Unable to build contrib/fb303 on OSX 10.9.2 + * [THRIFT-2466] - Improper error handling for SSL/TLS connections that don't complete a handshake + * [THRIFT-2463] - test/py/RunClientServer.py fails sometimes + * [THRIFT-2461] - Can't install thrift-0.8.0 on OS X 10.9.2 + * [THRIFT-2454] - c_glib: There is no gethostbyname_r() in some OS. + * [THRIFT-2448] - thrift/test/test.sh has incorrect Node.js test path + * [THRIFT-2459] - --version should not exit 1 + * [THRIFT-2458] - Generated golang server code for "oneway" methods is incorrect * [THRIFT-2443] - Node fails cross lang tests + * [THRIFT-2456] - THttpClient fails when using async support outside Silverlight + * [THRIFT-2451] - Do not use pointers for optional fields with defaults. Do not write such fields if its value set to default. Also, do not use pointers for any optional fields mapped to go map or slice. generate Get accessors + * [THRIFT-2450] - include HowToContribute in the src repo + * [THRIFT-2460] - unopened socket fd must be less than zero. + * [THRIFT-2442] - Fix issue with cpp server on Windows (WSAStartup wasn't called) + * [THRIFT-2439] - Bug in TProtocolDecorator Class causes parsing errors + * [THRIFT-2438] - Unexpected readFieldEnd call causes JSON Parsing errors * [THRIFT-2437] - Author fields in Python setup.py must be strings not lists. * [THRIFT-2435] - Java compiler doesn't like struct member names that are identical to an existing enum or struct type * [THRIFT-2434] - Missing namespace import for php TMultiplexedProcessor implementation * [THRIFT-2432] - Flaky parallel build * [THRIFT-2430] - Crash during TThreadPoolServer shutdown - * [THRIFT-667] - Period should not be allowed in identifier names - * [THRIFT-1212] - Members capital case conflict - * [THRIFT-2584] - Error handler not listened on javascript client - * [THRIFT-2294] - Incorrect Makefile generation - * [THRIFT-2601] - Fix vagrant to work again for builds again - * [THRIFT-2092] - TNonblocking server should release handler as soon as connection closes - * [THRIFT-2557] - CS0542 member names cannot be the same as their enclosing type - * [THRIFT-2605] - TSocket warning on gcc 4.8.3 - * [THRIFT-2607] - ThreadManager.cpp warning on clang++ 3.4 - * [THRIFT-1998] - TCompactProtocol.tcc - one more warning on Visual 2010 - * [THRIFT-2610] - MSVC warning in TSocket.cpp - * [THRIFT-2614] - TNonblockingServer.cpp warnings on MSVC - * [THRIFT-2608] - TNonblockingServer.cpp warnings on clang 3.4 - * [THRIFT-2606] - ThreadManager.h warning in clang++ 3.4 - * [THRIFT-2609] - TFileTransport.h unused field warning (clang 3.4) + * [THRIFT-2428] - Python 3 setup.py support + * [THRIFT-2426] - clarify IP rights and contributions from fbthrift + * [THRIFT-2420] - Go argument parser for methods without arguments does not skip fields + * [THRIFT-2419] - golang - Fix fmt.Errorf in generated code + * [THRIFT-2418] - Go handler function panics on internal error * [THRIFT-2416] - Cannot use TCompactProtocol with MSVC - * [THRIFT-1803] - Ruby Thrift 0.9.0 tries to encode UUID to UTF8 and crashes + * [THRIFT-2414] - c_glib fix several bug. + * [THRIFT-2405] - Node.js Multiplexer tests fail (silently) + * [THRIFT-2402] - byte count of FrameBuffer in AWAITING_CLOSE state is not subtracted from readBufferBytesAllocated + * [THRIFT-2399] - thrift.el: recognize "//"-style comments in emacs thrift-mode + * [THRIFT-2400] - thrift.el: recognize "//"-style comments in emacs thrift-mode + * [THRIFT-2396] - Build Error on MacOSX + * [THRIFT-2395] - thrift Ruby gem requires development dependency 'thin' regardless of environment + * [THRIFT-2390] - no close event when connection lost + * [THRIFT-2389] - namespaces handled wrongly in acrionscript 3.0 implementation + * [THRIFT-2388] - GoLang - Fix data races in simple_server and server_socket + * [THRIFT-2386] - Thrift refuses to link yylex * [THRIFT-2385] - Problem with gethostbyname2 during make check + * [THRIFT-2384] - Binary map keys produce uncompilable code in go + * [THRIFT-2381] - code which generated by thrift2/hbase.thrift compile error + * [THRIFT-2380] - unreachable code (CID 1174546, CID 1174679) + * [THRIFT-2378] - service method arguments of binary type lead to uncompileable Go code + * [THRIFT-2375] - Excessive
's in generated HTML + * [THRIFT-2373] - warning CS0414 in THttpClient.cs: private field 'Thrift.Transport.THttpClient.connection' assigned but never used + * [THRIFT-2372] - thrift/json_protocol.go:160: function ends without a return statement + * [THRIFT-2371] - ruby bundler version fails on ~1.3.1, remove and take latest avail + * [THRIFT-2370] - Compiler SEGFAULTs generating HTML documentation for complex strucre + * [THRIFT-2147] - Thrift IDL grammar allows for dotted identifier names + * [THRIFT-2145] - Rack and Thin are not just development dependencies + * [THRIFT-2146] - Unable to pass multiple "--gen" options to the thrift compiler + * [THRIFT-2140] - Error compiling cpp tutorials + * [THRIFT-2182] - segfault in regression tests (GC bug in rb_thrift_memory_buffer_write) + * [THRIFT-2171] - NodeJS implementation has extremely low test coverage + * [THRIFT-2169] - JavaME Thrift Library causes "java.io.IOException: No Response Entries Available" after using the Thrift client for some time + * [THRIFT-2165] - Thrift Compiler fails at input files with UTF-8 BOM + * [THRIFT-2160] - Warning in thrift.h when compiling with -Wunused and NDEBUG + * [THRIFT-2158] - Compact, JSON, and SimpleJSON protocols are not working correctly + * [THRIFT-2181] - oneway calls don't work in NodeJS + * [THRIFT-2178] - Thrift generator returns error exit code on --version + * [THRIFT-2173] - Move FrameBuffer creation to a factory method for cusomization + * [THRIFT-2168] - Node.js appears broken (at least, examples don't work as intended) + * [THRIFT-2167] - nodejs lib throws error if options argument isn't passed + * [THRIFT-2139] - MSVC 2012 Error - Cannot compile due to BoostThreadFactory + * [THRIFT-2138] - pkgconfig file created with wrong include path + * [THRIFT-2130] - Thrift's D library/test: parts of "make check" code do not compile with recent dmd-2.062 through dmd-2.064alpha + * [THRIFT-2122] - NPE in TSSLTransportFactory.createClient when no truststore password is passed in custom SSL params + * [THRIFT-2288] - Go impl of Thrift JSON protocol wrongly writes/expects true/false for bools + * [THRIFT-2294] - Incorrect Makefile generation + * [THRIFT-2293] - TSSLTransportFactory.createSSLContext() leaves files open + * [THRIFT-2274] - TNonblockingServer and TThreadedSelectorServer do not close their channel selectors on exit and leak file descriptors + * [THRIFT-2273] - Please delete old releases from mirroring system + * [THRIFT-2270] - Faulty library version numbering at build or documentation + * [THRIFT-2267] - Should be able to choose socket family in Python TSocket + * [THRIFT-2266] - ThreadManager.h:24:10: fatal error: 'tr1/functional' file not found on Mac 10.9 (Mavericks) + * [THRIFT-2265] - php library doesn't build * [THRIFT-2262] - thrift server 'MutateRow' operation gives no indication of success / failure - * [THRIFT-2048] - Prefer boolean context to nullptr_t conversion - * [THRIFT-2528] - Thrift Erlang Library: Multiple thrift applications in one bundle - * [THRIFT-1999] - warning on gcc 4.7 while compiling BoostMutex.cpp + * [THRIFT-2261] - java: error: unmappable character for encoding ASCII * [THRIFT-2104] - Structs lose binary data when transferred from server to client in Java + * [THRIFT-2209] - Ruby generator -- please namespace classes + * [THRIFT-2210] - lib/java TSimpleJSONProtocol can emit invalid JSON + * [THRIFT-2201] - Ternary operator returns different types (build error for some compilers) + * [THRIFT-2200] - nested structs cause generate_fingerprint() to slow down at excessive CPU load + * [THRIFT-2197] - fix jar output directory in rpm spec file + * [THRIFT-2196] - Fix invalid dependency in Makefile.am + * [THRIFT-2191] - Fix charp JSONProtocol.ReadJSONDouble (specify InvariantCulture) + * [THRIFT-2203] - Tests keeping failing on Jenkins and Travis CI + * [THRIFT-2202] - Delphi TServerImpl.DefaultLogDelegate may stop the server with I/O-Error 105 + * [THRIFT-2187] - Guard against ambiguous occurrences + * [THRIFT-2214] - System header sys/param.h is included inside the Thrift namespace + * [THRIFT-2211] - Exception constructor does not contain namespace prefix. + * [THRIFT-2194] - Node: Not actually prepending residual data in TFramedTransport.receiver + * [THRIFT-2193] - Java code generator emits spurious semicolon when deep copying binary data * [THRIFT-2184] - undefined method rspec_verify for Thrift::MemoryBufferTransport - * [THRIFT-2351] - PHP TCompactProtocol has fails to decode messages + * [THRIFT-2183] - gem install fails on zsh + * [THRIFT-2108] - Fix TAsyncClientManager timeout race + * [THRIFT-2092] - TNonblocking server should release handler as soon as connection closes + * [THRIFT-1999] - warning on gcc 4.7 while compiling BoostMutex.cpp + * [THRIFT-1998] - TCompactProtocol.tcc - one more warning on Visual 2010 + * [THRIFT-2009] - Go redeclaration error * [THRIFT-2016] - Resource Leak in thrift struct under compiler/cpp/src/parse/t_function.h - * [THRIFT-2273] - Please delete old releases from mirroring system - * [THRIFT-2270] - Faulty library version numbering at build or documentation - * [THRIFT-2203] - Tests keeping failing on Jenkins and Travis CI - * [THRIFT-2399] - thrift.el: recognize "//"-style comments in emacs thrift-mode - * [THRIFT-2582] - "FileTransport error" exception is raised when trying to use Java's TFileTransport - * [THRIFT-1682] - Multiple thread calling a Service function unsafely causes message corruption and terminates with Broken Pipe - * [THRIFT-2357] - recurse option has no effect when generating php - * [THRIFT-2248] - Go generator doesn't deal well with map keys of type binary - * [THRIFT-2426] - clarify IP rights and contributions from fbthrift + * [THRIFT-2045] - C++ compiler warning and build cleanup + * [THRIFT-2026] - Fix TCompactProtocol 64 bit builds + * [THRIFT-2025] - Fix TSSLServerSocket 64-bit builds + * [THRIFT-1964] - 'Isset' causes problems with C#/.NET serializers + * [THRIFT-1908] - Using php thrift_protocol accelerated transfer causes core dump + * [THRIFT-1892] - Socket timeouts are declared in milli-seconds, but are actually set in micro-seconds + * [THRIFT-2069] - TPipeServer creates overlapped pipes, then uses synchronous I/O on them with TPipe + * [THRIFT-2068] - Multiple calls from same connection are not processed in node + * [THRIFT-2048] - Prefer boolean context to nullptr_t conversion * [THRIFT-2041] - TNonblocking server compilation on windows (ARITHMETIC_RIGHT_SHIFT) - * [THRIFT-2400] - thrift.el: recognize "//"-style comments in emacs thrift-mode + * [THRIFT-1682] - Multiple thread calling a Service function unsafely causes message corruption and terminates with Broken Pipe + * [THRIFT-1647] - NodeJS BufferedTransport does not work beyond the hello-world example + * [THRIFT-1639] - Java/Python: Serialization/Deserialization of double type using CompactProtocol + * [THRIFT-1771] - "make check" fails on x64 for libboost_unit_test_framework.a + * [THRIFT-1841] - NodeJS Thrift incorrectly parses non-UTF8-string types + * [THRIFT-1755] - Comment parsing bug + * [THRIFT-1750] - Make compiler build cleanly under visual studio 10 + * [THRIFT-1803] - Ruby Thrift 0.9.0 tries to encode UUID to UTF8 and crashes * [THRIFT-1717] - Fix deb build in jenkins - * [THRIFT-2266] - ThreadManager.h:24:10: fatal error: 'tr1/functional' file not found on Mac 10.9 (Mavericks) + * [THRIFT-1609] - Cocoa import namespace + * [THRIFT-1614] - Thrift build from svn repo sources fails with automake-1.12 + * [THRIFT-1584] - Error: could not SetMinThreads in ThreadPool on single-core machines + * [THRIFT-1579] - PHP Extention - function thrift_protocol_read_binary not working from TBinarySerializer::deserialize + * [THRIFT-1455] - TBinaryProtocolT::writeString casts from size_t to uint32_t, which is not safe on 64-bit platforms + * [THRIFT-1481] - Unix domain sockets in C++ do not support the abstract namespace + * [THRIFT-1357] - Erlang Dependency breaks build + * [THRIFT-1260] - The thrift THttpclient in c# client is not closing the connections when calling SendRequest * [THRIFT-1300] - Test failures with parallel builds (make -j) - * [THRIFT-2487] - Tutorial requires two IDL files but only one is linked from the Thrift web site - * [THRIFT-2329] - missing release tags within git - * [THRIFT-2306] - concurent client calls with nodejs - * [THRIFT-2222] - ruby gem cannot be compiled on OS X mavericks - * [THRIFT-2381] - code which generated by thrift2/hbase.thrift compile error - * [THRIFT-2390] - no close event when connection lost - * [THRIFT-2146] - Unable to pass multiple "--gen" options to the thrift compiler - * [THRIFT-2438] - Unexpected readFieldEnd call causes JSON Parsing errors - * [THRIFT-2498] - Error message "Invalid method name" while trying to call HBase Thrift API + * [THRIFT-1212] - Members capital case conflict * [THRIFT-841] - Build cruft - * [THRIFT-2570] - Wrong URL given in http://thrift.apache.org/developers - * [THRIFT-2604] - Fix debian packaging - * [THRIFT-2618] - Unignore /aclocal files required for build - * [THRIFT-2562] - ./configure create MakeFile in lib/d with errors + * [THRIFT-1047] - rb_thrift_memory_buffer_write treats arg as string without check, segfaults if you pass non-string + * [THRIFT-667] - Period should not be allowed in identifier names + * [THRIFT-1389] - c_glib_generator.cc generates leaking code for cassandra_client_get_slice() and cassandra_client_get() + * [THRIFT-2675] - md5 file content is malformed in the download website + * [THRIFT-2284] - java.lang.OutOfMemoryError: Java heap space + * [THRIFT-2596] - Cannot compile haskell thrift 0.6.0 + * [THRIFT-2064] - Node thrift can't handle maps with primitive values + * [THRIFT-2656] - ./configure mis-reports minimum bison version required + * [THRIFT-908] - Make required types actually required by the Haskell type system + * [THRIFT-2690] - c_glib: Incorrect behaviour when serializing a map with typedef'd keys + * [THRIFT-2651] - struct names that are restricted erlang terms generate invalid type signatures + * [THRIFT-2667] - create Windows Installer via CPack + * [THRIFT-1028] - field names of structs used with wrong casing in the generated haskell code + * [THRIFT-2647] - compiler-hs: don't decapitalize field names, do decapitalize argument bindings + * [THRIFT-2649] - TAsyncClientManager leaks the selector + * [THRIFT-2683] - c_glib: Seg fault when deserializing a map with typedef'd keys + * [THRIFT-2686] - Another extraneous semicolon - TBinaryProtocol.h + * [THRIFT-1497] - i64 type not supported in JavaScript. Low-order bits lost. + * [THRIFT-1266] - generated C code for iterating over nested maps is wrong + * [THRIFT-2680] - c_glib: ThriftFramedTransport fails when peer unexpectedly closes connection + * [THRIFT-2660] - Validate the bytes received in TSaslTransport + * [THRIFT-2152] - Generated Haskell files does not compile + * [THRIFT-2198] - THRIFT_CLOSESOCKET on win32 platforms is wrong defined for TFileProtocol + * [THRIFT-2673] - PHP: generated Service_method_result code should not have validators + * [THRIFT-2657] - py.twisted/test_suite.py:ThriftTestCase.testOneway spuriously fails on loaded machines + * [THRIFT-2617] - Missing -lboost_system when compiling with boost threads + * [THRIFT-2687] - struct/class inconsitency between forward decl and definition + * [THRIFT-2696] - Unable to stop socket server while there are idle clients + * [THRIFT-2702] - empty enums lead to invalid code + * [THRIFT-2694] - Minor glitches in Delphi cross-test code + * [THRIFT-2714] - Graphviz generator is missing from MSVC++ project files + * [THRIFT-2706] - D library does not support "oneway" message type + * [THRIFT-2676] - Cocoa code generator emits reserved symbol, 'i386' + * [THRIFT-2543] - Generated enum type in haskell should be qualified + * [THRIFT-2526] - Assignment operators and copy constructors in c++ don't copy the __isset struct + * [THRIFT-2339] - Uncaught exception in thrift c# driver + * [THRIFT-2719] - ObjectDisposedException in TSocket when sending rapidly + * [THRIFT-2707] - Ruby library does not support "oneway" message type + * [THRIFT-2701] - Update TCompactProtocol.php + * [THRIFT-2711] - Travis reports false possitive while building with mingw + * [THRIFT-2693] - Erlang test leaves a lot of generated files + * [THRIFT-2716] - automake-1.13.4 reports warnings for some Makefile.am + * [THRIFT-2664] - Python tornado generated oneway client functions crash on server error + * [THRIFT-2662] - python bindings generate incorrect indentation for functions after a oneway function + * [THRIFT-2663] - python library should not use the root logger * [THRIFT-2593] - Unable to build thrift on ubuntu-12.04 (Precise) - * [THRIFT-2461] - Can't install thrift-0.8.0 on OS X 10.9.2 + * [THRIFT-585] - exceptions in the autogenerated send_METHOD functions are not propagated (Twisted) + * [THRIFT-2669] - javascript thrift library can not deserialize nested list structure + * [THRIFT-1847] - TSSLSocket.cpp and TFileTransport.cpp incorrectly excluded from Visual Studio project file + * [THRIFT-2745] - C++ - Unit-test compilation on Windows fixes + * [THRIFT-2665] - tornado library debug messages are too verbose + * [THRIFT-2715] - Wrong Import-Package directive in MANIFEST + * [THRIFT-2229] - thrift failed to build on OSX 10.9 GM + * [THRIFT-2759] - Trusty Vagrantfile does not make clean + * [THRIFT-2186] - Build failure of Haskell example + * [THRIFT-2778] - nodejs build cleanup + * [THRIFT-2589] - C# generator: const of BaseType in IDL generates static instead of const properties * [THRIFT-2602] - Fix missing dist files - * [THRIFT-2620] - Fix python packaging - * [THRIFT-2545] - Test CPP fails to build (possibly typo) + * [THRIFT-1940] - Deploy Haskell package as part of release process + * [THRIFT-2700] - Compiling from source for haskell reveals a missing cabal dependency + * [THRIFT-2792] - Wrong option level for setsockopt(...TCP_DEFER_ACCEPT) + * [THRIFT-2769] - D: std.traits.pointerTarget is deprecated + * [THRIFT-2722] - Fix javascript service inheritance namespacing + * [THRIFT-2628] - erlang: struct member name conflicts due to lowercased names + * [THRIFT-2757] - TCompactProtocol and TJSONProtocol need boundary checking + * [THRIFT-2775] - static assert fails in src/thrift/internal/ctfe.d + * [THRIFT-2781] - D compiler stuck at idlgen due to compiler bug + * [THRIFT-2782] - D: Timing-insensitive unit tests for thrift.internal.resource_pool + * [THRIFT-2689] - struct names that differ only in capitalization of first character generate broken erlang code + * [THRIFT-2767] - Transport.Empty is not externally available + * [THRIFT-2788] - Java client and server does not enable tcp keep alive. + * [THRIFT-2776] - D tests failing + * [THRIFT-2770] - D: thrift.internal.traits unittest fails due to std.metastrings import + * [THRIFT-2720] - nodejs - Error with enum generation + * [THRIFT-2777] - erlang lib tests may fail due to permissions error ## Documentation - * [THRIFT-2155] - Adding one liner guide to rename the version.h.in and rename thrifty.cc.h - * [THRIFT-1991] - Add exceptions to examples * [THRIFT-2334] - add a tutorial for node JS * [THRIFT-2392] - Actionscript tutorial * [THRIFT-2383] - contrib: sample for connecting Thrift with Rebus * [THRIFT-2382] - contrib: sample for connecting Thrift with STOMP + * [THRIFT-2155] - Adding one liner guide to rename the version.h.in and rename thrifty.cc.h + * [THRIFT-1991] - Add exceptions to examples ## Improvement - * [THRIFT-1457] - Capacity of TframedTransport write buffer is never reset - * [THRIFT-1135] - Node.js tutorial - * [THRIFT-1371] - Socket timeouts (SO_RCVTIMEO and SO_SNDTIMEO) not supported on Solaris - * [THRIFT-2142] - Minor tweaks to thrift.el for better emacs package compatibility - * [THRIFT-2268] - Modify TSaslTransport to ignore TCP health checks from loadbalancers - * [THRIFT-2264] - GitHub page incorrectly states that Thrift is still incubating - * [THRIFT-2263] - Always generate good hashCode for Java - * [THRIFT-2233] - Java compiler should defensively copy its binary inputs - * [THRIFT-2239] - Address FindBugs errors - * [THRIFT-2249] - Add SMP Build option to thrift.spec (and three config defines) - * [THRIFT-2254] - Exceptions generated by Go compiler should implement error interface - * [THRIFT-2260] - Thrift imposes unneeded dependency on commons-lang3 - * [THRIFT-2258] - Add TLS v1.1/1.2 support to TSSLSocket.cpp - * [THRIFT-2205] - Node.js Test Server to support test.js JavaScript Browser test and sundry fixes - * [THRIFT-2204] - SSL client for the cocoa client - * [THRIFT-2172] - Java compiler allocates optionals array for every struct with an optional field - * [THRIFT-2185] - use cabal instead of runhaskell in haskell library - * [THRIFT-1926] - PHP Constant Generation Refactoring - * [THRIFT-2029] - Port C++ tests to Windows - * [THRIFT-2054] - TSimpleFileTransport - Java Lib has no straight forward TTransport based file transport - * [THRIFT-2040] - "uninitialized variable" warnings on MSVC/windows - * [THRIFT-2034] - Give developers' C++ code direct access to socket FDs on server side - * [THRIFT-2095] - Use print function for Python 3 compatiblity - * [THRIFT-1868] - Make the TPC backlog configurable in the Java servers - * [THRIFT-1813] - Add @Generated annotation to generated classes - * [THRIFT-1815] - Code generators line buffer output - * [THRIFT-2305] - TFramedTransport empty constructor should probably be private - * [THRIFT-2304] - Move client assignments from construtor in method - * [THRIFT-2309] - Ruby (gem) & PHP RPM subpackages + * [THRIFT-2639] - c_glib: Expose as properties members of generated structs + * [THRIFT-2653] - improved Delphi const generation + * [THRIFT-2638] - travis: build with Haskell + * [THRIFT-2636] - c_glib: ThriftApplicationException: Expose "type" and "message" properties + * [THRIFT-2635] - Travis CI build and test matrix + * [THRIFT-2633] - remove 'this is a dummy struct' structs from generated erlang + * [THRIFT-2632] - PHP: add "validate" option to generate read/write validation code + * [THRIFT-2629] - JavaDoc style documentation should be reused + * [THRIFT-2631] - c_glib: Support service inheritance in clients + * [THRIFT-2624] - Add TServerEventHandler support to C# + * [THRIFT-2612] - Java TCompactProtocol.readBinary zero copying + * [THRIFT-2621] - Add basic default hash code method to python + * [THRIFT-2574] - Compiler option to generate namespace directories for Ruby + * [THRIFT-2568] - Implement own certificate handler + * [THRIFT-2569] - Introduce file to specify third party library locations on Windows + * [THRIFT-2549] - Generate json tag for struct members. use go.tag annotation to override the default generated tag. + * [THRIFT-2541] - reclaim TFramedTransport's read and write buffers for thrift cpp + * [THRIFT-2535] - TJSONProtocol when serialized yields TField ids rather than names + * [THRIFT-2544] - Add support for socket transport for c# library when using Windows Phone projects + * [THRIFT-2552] - eliminate warning from configure.ac + * [THRIFT-2571] - Simplify cross compilation using CMake + * [THRIFT-2511] - Node.js needs the compact protocol + * [THRIFT-2579] - Windows CE support + * [THRIFT-2341] - Enable generation of Delphi XMLDoc comments (a.k.a. "Help Insight") + * [THRIFT-2332] - RPMBUILD: run bootstrap (if needed) + * [THRIFT-2330] - Generate PHPDoc comments + * [THRIFT-2320] - Program level doctext does not get attached by parser * [THRIFT-2318] - perl: dependency Class::Accessor not checked * [THRIFT-2317] - exclude tutorial from build - * [THRIFT-2320] - Program level doctext does not get attached by parser + * [THRIFT-2309] - Ruby (gem) & PHP RPM subpackages + * [THRIFT-2355] - Add SSL and Web Socket Support to Node and JavaScript + * [THRIFT-2350] - Add async calls to normal JavaScript * [THRIFT-2349] - Golang - improve tutorial * [THRIFT-2348] - PHP Generator: add array typehint to functions * [THRIFT-2344] - configure.ac: compiler-only option * [THRIFT-2343] - Golang - Return a single error for all exceptions instead of multiple return values - * [THRIFT-2341] - Enable generation of Delphi XMLDoc comments (a.k.a. "Help Insight") - * [THRIFT-2355] - Add SSL and Web Socket Support to Node and JavaScript - * [THRIFT-2350] - Add async calls to normal JavaScript - * [THRIFT-2330] - Generate PHPDoc comments - * [THRIFT-2332] - RPMBUILD: run bootstrap (if needed) - * [THRIFT-2391] - simple socket transport for actionscript 3.0 - * [THRIFT-2376] - nodejs: allow Promise style calls for client and server - * [THRIFT-2369] - Add ssl support for nodejs implementation - * [THRIFT-2401] - Haskell tutorial compiles + * [THRIFT-2305] - TFramedTransport empty constructor should probably be private + * [THRIFT-2304] - Move client assignments from construtor in method + * [THRIFT-2300] - D configure info output should follow same format as other languages + * [THRIFT-2239] - Address FindBugs errors + * [THRIFT-2233] - Java compiler should defensively copy its binary inputs + * [THRIFT-2260] - Thrift imposes unneeded dependency on commons-lang3 + * [THRIFT-2258] - Add TLS v1.1/1.2 support to TSSLSocket.cpp + * [THRIFT-2254] - Exceptions generated by Go compiler should implement error interface + * [THRIFT-2249] - Add SMP Build option to thrift.spec (and three config defines) + * [THRIFT-2220] - Add a new struct structv? + * [THRIFT-2497] - server and client for test/go, also several fixes and improvements + * [THRIFT-2496] - server and client for test/go, also several fixes and improvements + * [THRIFT-2494] - Add enum toString helper function in c_glib + * [THRIFT-2502] - Optimize go implementations of binary and compact protocols for speed + * [THRIFT-2471] - Make cpp.ref annotation language agnostic + * [THRIFT-2449] - Enhance typedef structure to distinguish between forwards and real typedefs + * [THRIFT-2453] - haskell tutorial: fix up division by 0 example + * [THRIFT-2455] - Allow client certificates to be used with THttpClient + * [THRIFT-2446] - There is no way to handle server stream errors + * [THRIFT-2433] - Allow manual control of OpenSSL initialization/cleanup * [THRIFT-2417] - C# Union classes are not partial * [THRIFT-2415] - Named pipes server performance & message mode + * [THRIFT-2407] - use markdown (rename README => README.md) * [THRIFT-2404] - emit warning on (typically inefficient) list + * [THRIFT-2401] - Haskell tutorial compiles * [THRIFT-2398] - Improve Node Server Library * [THRIFT-2397] - Add CORS and CSP support for JavaScript and Node.js libraries - * [THRIFT-2407] - use markdown (rename README => README.md) - * [THRIFT-2300] - D configure info output should follow same format as other languages - * [THRIFT-2579] - Windows CE support - * [THRIFT-2574] - Compiler option to generate namespace directories for Ruby - * [THRIFT-2571] - Simplify cross compilation using CMake - * [THRIFT-2569] - Introduce file to specify third party library locations on Windows - * [THRIFT-2568] - Implement own certificate handler - * [THRIFT-2552] - eliminate warning from configure.ac - * [THRIFT-2549] - Generate json tag for struct members. use go.tag annotation to override the default generated tag. - * [THRIFT-2544] - Add support for socket transport for c# library when using Windows Phone projects - * [THRIFT-2453] - haskell tutorial: fix up division by 0 example - * [THRIFT-2449] - Enhance typedef structure to distinguish between forwards and real typedefs - * [THRIFT-2446] - There is no way to handle server stream errors - * [THRIFT-2455] - Allow client certificates to be used with THttpClient - * [THRIFT-2511] - Node.js needs the compact protocol - * [THRIFT-2493] - Node.js lib needs HTTP client - * [THRIFT-2502] - Optimize go implementations of binary and compact protocols for speed - * [THRIFT-2494] - Add enum toString helper function in c_glib - * [THRIFT-2471] - Make cpp.ref annotation language agnostic - * [THRIFT-2497] - server and client for test/go, also several fixes and improvements - * [THRIFT-2535] - TJSONProtocol when serialized yields TField ids rather than names - * [THRIFT-2220] - Add a new struct structv? - * [THRIFT-1352] - Thrift server - * [THRIFT-989] - Push boost m4 macros upstream - * [THRIFT-1349] - Remove unnecessary print outs - * [THRIFT-2496] - server and client for test/go, also several fixes and improvements - * [THRIFT-1114] - Maven publish shouldn't require passwords hardcoded in settings.xml + * [THRIFT-2394] - TCurlClient: an HTTP transport implementation using libcurl + * [THRIFT-2391] - simple socket transport for actionscript 3.0 + * [THRIFT-2387] - nodejs: external imports should be centralized in index.js + * [THRIFT-2376] - nodejs: allow Promise style calls for client and server + * [THRIFT-2369] - Add ssl support for nodejs implementation + * [THRIFT-2142] - Minor tweaks to thrift.el for better emacs package compatibility + * [THRIFT-2172] - Java compiler allocates optionals array for every struct with an optional field + * [THRIFT-2268] - Modify TSaslTransport to ignore TCP health checks from loadbalancers + * [THRIFT-2263] - Always generate good hashCode for Java + * [THRIFT-2264] - GitHub page incorrectly states that Thrift is still incubating + * [THRIFT-2095] - Use print function for Python 3 compatiblity + * [THRIFT-2185] - use cabal instead of runhaskell in haskell library + * [THRIFT-2204] - SSL client for the cocoa client + * [THRIFT-2205] - Node.js Test Server to support test.js JavaScript Browser test and sundry fixes + * [THRIFT-2054] - TSimpleFileTransport - Java Lib has no straight forward TTransport based file transport + * [THRIFT-2037] - More general macro THRIFT_UNUSED_VARIABLE + * [THRIFT-2029] - Port C++ tests to Windows + * [THRIFT-2034] - Give developers' C++ code direct access to socket FDs on server side + * [THRIFT-1926] - PHP Constant Generation Refactoring + * [THRIFT-2040] - "uninitialized variable" warnings on MSVC/windows * [THRIFT-2043] - visual 2010 warnings - unreachable code * [THRIFT-1683] - Implement alternatives to Javascript Client side Transport protocol, just as NPAPI and WebSocket. - * [THRIFT-1746] - provide a SPDX file + * [THRIFT-1868] - Make the TPC backlog configurable in the Java servers * [THRIFT-1772] - Serialization does not check types of embedded structures. - * [THRIFT-2387] - nodejs: external imports should be centralized in index.js - * [THRIFT-2037] - More general macro THRIFT_UNUSED_VARIABLE + * [THRIFT-1743] - Add composer.json for new Symfony 2.1 Dependency Manager + * [THRIFT-1746] - provide a SPDX file + * [THRIFT-1815] - Code generators line buffer output + * [THRIFT-1813] - Add @Generated annotation to generated classes + * [THRIFT-1541] - The thrift compiler is not buildable with visual studio 2010 in Windows 7 + * [THRIFT-1544] - Create correct Ruby namespace directories + * [THRIFT-1457] - Capacity of TframedTransport write buffer is never reset + * [THRIFT-1442] - TNonblockingServer: Refactor to allow multiple IO Threads + * [THRIFT-1371] - Socket timeouts (SO_RCVTIMEO and SO_SNDTIMEO) not supported on Solaris + * [THRIFT-1349] - Remove unnecessary print outs + * [THRIFT-1352] - Thrift server + * [THRIFT-1135] - Node.js tutorial + * [THRIFT-1114] - Maven publish shouldn't require passwords hardcoded in settings.xml + * [THRIFT-989] - Push boost m4 macros upstream + * [THRIFT-2691] - C++ - new operator<< could be used in tutorial + * [THRIFT-2067] - Thrift objects should have a default string representation + * [THRIFT-2641] - Improvements to Haskell Compiler/Libraries + * [THRIFT-2231] - Support tornado-4.x (Python) + * [THRIFT-2643] - Optional offset/length for TDeserializer.deserialize() + * [THRIFT-2684] - c_glib: Improvements to map deserialization in generated code + * [THRIFT-2672] - Provide origin of call via TTransport + * [THRIFT-2677] - Haskell library needs to build with network >= 2.6 + * [THRIFT-2648] - cleanup erlang lib + * [THRIFT-2493] - Node.js lib needs HTTP client + * [THRIFT-2718] - Align command line args for Thrift test server/client + * [THRIFT-2709] - c_glib: Support server implementation + * [THRIFT-976] - c_glib tutorial + * [THRIFT-2752] - Centos 6.5 Installation Docs update + * [THRIFT-2269] - Can deploy libthrift-source.jar to maven center repository + * [THRIFT-2512] - lib/${language}/README.md + * [THRIFT-2783] - Correctly propagate binary encoding of WebSocket frames Node.js library + * [THRIFT-2692] - Allow unit testing of compiler parts + * [THRIFT-2787] - Delphi Lib README + * [THRIFT-2786] - Cpp Tutorial: Make TThreadPoolServer / TThreadedServer a bit easier to use + * [THRIFT-2785] - Wrap errors in iostream_transport.go + * [THRIFT-2062] - cpp flag for using unordered_set instead of set + * [THRIFT-2654] - reduce number of server exceptions + * [THRIFT-2360] - Json Generator + * [THRIFT-2791] - Allowing use of buffered sockets in go server + * [THRIFT-809] - Javascript client: Please make required fields actually required. + * [THRIFT-2784] - Eliminate compiler warnings in generated C++ code + * [THRIFT-2538] - Apache Thrift needs an official NuGet package + * [THRIFT-2046] - The worktask can be timed out in TThreadPoolServer (Java) when the max# thrift thread is reached ## New Feature - * [THRIFT-1012] - Transport for DataInput DataOutput interface + * [THRIFT-2637] - "java:fullcamel_service_methods" option to automatically camel-case Java service methods + * [THRIFT-2572] - Add string/collection length limit checks (from C++) to java protocol readers + * [THRIFT-795] - Importing service functions (simulation multiple inheritance) + * [THRIFT-2347] - C# TLS Transport based on THRIFT-181 * [THRIFT-2256] - Using c++11/c++0x std library replace boost library + * [THRIFT-2255] - add Parent Class for generated Struct class * [THRIFT-2250] - JSON and MemoryBuffer for JavaME + * [THRIFT-2469] - "java:fullcamel" option to automatically camel-case underscored attribute names + * [THRIFT-2408] - Named Pipe Transport Option for C# + * [THRIFT-2377] - Allow addition of custom HTTP Headers to an HTTP Transport + * [THRIFT-2164] - Add a Get/Post Http Server to Node along with examples * [THRIFT-2114] - Python Service Remote SSL Option - * [THRIFT-1719] - SASL client support for Python * [THRIFT-1894] - Thrift multi-threaded async Java Server using Java 7 AsynchronousChannelGroup + * [THRIFT-2058] - Add reconnect support to node.js library + * [THRIFT-1719] - SASL client support for Python + * [THRIFT-1188] - C++: Use bit fields for a more compact __isset struct + * [THRIFT-1012] - Transport for DataInput DataOutput interface + * [THRIFT-2688] - Generating *Null implementations should be optional + * [THRIFT-728] - Make generated Haskell code an instance of Arbitrary + * [THRIFT-2522] - TypeScript extension for Thrift Compiler * [THRIFT-1893] - HTTP/JSON server/client for node js - * [THRIFT-2347] - C# TLS Transport based on THRIFT-181 - * [THRIFT-2377] - Allow addition of custom HTTP Headers to an HTTP Transport - * [THRIFT-2408] - Named Pipe Transport Option for C# - * [THRIFT-2572] - Add string/collection length limit checks (from C++) to java protocol readers - * [THRIFT-2469] - "java:fullcamel" option to automatically camel-case underscored attribute names - * [THRIFT-795] - Importing service functions (simulation multiple inheritance) - * [THRIFT-2164] - Add a Get/Post Http Server to Node along with examples - * [THRIFT-2255] - add Parent Class for generated Struct class + * [THRIFT-2670] - Android Parcelable Java generation option + * [THRIFT-1536] - Maven thrift plugin + * [THRIFT-2712] - PHP: add "json" option to create JsonSerializable code ## Question + * [THRIFT-2573] - thrift 0.9.2 release + * [THRIFT-2567] - Csharp slow ? * [THRIFT-2539] - Tsocket.cpp addrinfo ai_flags = AI_ADDRCONFIG + * [THRIFT-2277] - Thrift: installing fb303 error * [THRIFT-2440] - how to connect as3 to java by thrift , * [THRIFT-2379] - Memmory leaking while using multithreading in C++ server. - * [THRIFT-2277] - Thrift: installing fb303 error - * [THRIFT-2567] - Csharp slow ? - * [THRIFT-2573] - thrift 0.9.2 release + * [THRIFT-2699] - Which version of Thrift to be used for WinCE + * [THRIFT-2703] - Thrift on Windows CE + * [THRIFT-2705] - make a package out of the haskell libraries for thrift ## Sub-task - * [THRIFT-981] - cocoa: add version Info to the library - * [THRIFT-2132] - Go: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-2534] - Cross language test results should recorded to a status.md or status.html file automatically + * [THRIFT-2558] - CSharp compiler generator tries to concat ints with strings using + + * [THRIFT-2507] - Additional LUA TProtocolException error code needed? + * [THRIFT-334] - Compact Protocol for PHP + * [THRIFT-66] - Java: Allow multiplexing multiple services over a single TCP connection + * [THRIFT-2338] - First doctext wrongly interpreted as program doctext in some cases + * [THRIFT-2325] - SSL test certificates + * [THRIFT-2310] - PHP: Client-side support for Multiplexing Services + * [THRIFT-2358] - C++: add compact protocol to cross language test suite + * [THRIFT-2297] - TJsonProtocol implementation for Delphi does not allow for both possible slash (solidus) encodings * [THRIFT-2299] - TJsonProtocol implementation for Ruby does not allow for both possible slash (solidus) encodings * [THRIFT-2298] - TJsonProtocol implementation for C# does not allow for both possible slash (solidus) encodings - * [THRIFT-2297] - TJsonProtocol implementation for Delphi does not allow for both possible slash (solidus) encodings - * [THRIFT-2271] - JavaScript: Support for Multiplexing Services * [THRIFT-2251] - go test for compact protocol is not running - * [THRIFT-2195] - Delphi: Add event handlers for server and processing events - * [THRIFT-2176] - TSimpleJSONProtocol.ReadFieldBegin() does not return field type and ID + * [THRIFT-2499] - Compiler: allow annotations without "= value" + * [THRIFT-2444] - pull request 88: thrift: clean up enum value assignment + * [THRIFT-2425] - PHP: Server-side support for Multiplexing Services + * [THRIFT-2421] - Tree/Recursive struct support in thrift * [THRIFT-2175] - Wrong field type set for binary + * [THRIFT-2176] - TSimpleJSONProtocol.ReadFieldBegin() does not return field type and ID * [THRIFT-2174] - Deserializing JSON fails in specific cases + * [THRIFT-2132] - Go: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-2290] - Update Go tutorial to align with THRIFT-2232 + * [THRIFT-2271] - JavaScript: Support for Multiplexing Services + * [THRIFT-2195] - Delphi: Add event handlers for server and processing events * [THRIFT-2053] - NodeJS: Support for Multiplexing Services * [THRIFT-1914] - Python: Support for Multiplexing Services on any Transport, Protocol and Server * [THRIFT-1810] - add ruby to test/test.sh - * [THRIFT-2310] - PHP: Client-side support for Multiplexing Services - * [THRIFT-2346] - C#: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2345] - Delphi: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2338] - First doctext wrongly interpreted as program doctext in some cases - * [THRIFT-2325] - SSL test certificates - * [THRIFT-2358] - C++: add compact protocol to cross language test suite - * [THRIFT-2425] - PHP: Server-side support for Multiplexing Services - * [THRIFT-2421] - Tree/Recursive struct support in thrift - * [THRIFT-2290] - Update Go tutorial to align with THRIFT-2232 - * [THRIFT-2558] - CSharp compiler generator tries to concat ints with strings using + - * [THRIFT-2507] - Additional LUA TProtocolException error code needed? - * [THRIFT-2499] - Compiler: allow annotations without "= value" - * [THRIFT-2534] - Cross language test results should recorded to a status.md or status.html file automatically - * [THRIFT-66] - Java: Allow multiplexing multiple services over a single TCP connection * [THRIFT-1681] - Add Lua Support + * [THRIFT-1766] - [Ruby] Provide support for binary types * [THRIFT-1727] - Ruby-1.9: data loss: "binary" fields are re-encoded * [THRIFT-1726] - Ruby-1.9: "binary" fields are represented by string whose encoding is "UTF-8" * [THRIFT-988] - perl: add version Info to the library via configure - * [THRIFT-334] - Compact Protocol for PHP - * [THRIFT-2444] - pull request 88: thrift: clean up enum value assignment + * [THRIFT-981] - cocoa: add version Info to the library + * [THRIFT-2345] - Delphi: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2346] - C#: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2652] - THRIFT_TEST_PORT variable via to run tests in parallel + * [THRIFT-2513] - clean up enum value assignment + * [THRIFT-2144] - Cocoa: Client-side support for Multiplexing Services on any Transport and Protocol + * [THRIFT-2746] - Compiler C++98 conformance + * [THRIFT-2750] - JS Lib ant build.xml fails on older ants + * [THRIFT-2751] - NodeJS Lib clean up + * [THRIFT-2749] - C++ Lib Transport Clean Up + * [THRIFT-2747] - Add .vagrant to .gitignore + * [THRIFT-2758] - lib/go/test/Makefile.am uses ln -s which breaks in vagrant + * [THRIFT-2760] - thrift/test/cpp depends on boost libs not installed by Vagrantfile + * [THRIFT-2762] - Python Twisted tests crash in Trusty Vagrantfile + * [THRIFT-2768] - Whitespace fixups + * [THRIFT-2761] - go make crashes with Trusty Vagrantfile + * [THRIFT-2763] - D is not installed (and thus not built/tested) in the Trusty Vagrantfile + * [THRIFT-2774] - Add documentation for new erlang case feature flag + * [THRIFT-2764] - Haskell does not build/test when using the Trusty Vagrantfile + * [THRIFT-1462] - add more strict compiler flags + * [THRIFT-2727] - C glib coding standards + * [THRIFT-2728] - C# coding standards + * [THRIFT-2741] - Python coding standards ## Task - * [THRIFT-2223] - Spam links on wiki * [THRIFT-2566] - Please create a DOAP file for your TLP * [THRIFT-2237] - Update archive to contain all versions + * [THRIFT-2223] - Spam links on wiki * [THRIFT-962] - Tutorial page on our website is really unhelpful ## Test * [THRIFT-2327] - nodejs: nodejs test suite should be bundled with the library - * [THRIFT-2445] - THRIFT-2384 (code generation for go maps with binary keys) should be tested * [THRIFT-2501] - C# The test parameters from the TestServer and TestClient are different from the http://thrift.apache.org/test/ + * [THRIFT-2445] - THRIFT-2384 (code generation for go maps with binary keys) should be tested + * [THRIFT-2685] - c_glib: Include in integration test suite + * [THRIFT-2754] - erlang lib tests don't clean up after themselves properly ## Wish * [THRIFT-2190] - Add the JavaScript thrift.js lib to the Bower registry * [THRIFT-2076] - boost::optional instead of __isset - Thrift 0.9.1 -------------------------------------------------------------------------------- ## Bug diff --git a/bower.json b/bower.json index 52e70ff3cc7..ebe79fa7f97 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.9.1", + "version": "0.9.2", "homepage": "https://git-wip-us.apache.org/repos/asf/thrift.git", "authors": [ "Apache Thrift " diff --git a/configure.ac b/configure.ac index c49cb603996..5fa611e25d7 100755 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ AC_PREREQ(2.65) -AC_INIT([thrift], [1.0.0-dev]) +AC_INIT([thrift], [0.9.2]) AC_CONFIG_AUX_DIR([.]) diff --git a/contrib/Rebus/Properties/AssemblyInfo.cs b/contrib/Rebus/Properties/AssemblyInfo.cs index e476eab7656..1d9d9a280d4 100644 --- a/contrib/Rebus/Properties/AssemblyInfo.cs +++ b/contrib/Rebus/Properties/AssemblyInfo.cs @@ -34,5 +34,5 @@ [assembly: Guid("0af10984-40d3-453d-b1e5-421529e8c7e2")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.9.2.0")] +[assembly: AssemblyFileVersion("0.9.2.0")] diff --git a/contrib/fb303/py/setup.py b/contrib/fb303/py/setup.py index 6710c8f61db..8b68df4dc07 100644 --- a/contrib/fb303/py/setup.py +++ b/contrib/fb303/py/setup.py @@ -26,7 +26,7 @@ from distutils.core import setup, Extension, Command setup(name = 'thrift_fb303', - version = '1.0.0-dev', + version = '0.9.2', description = 'Python bindings for the Apache Thrift FB303', author = ['Thrift Developers'], author_email = ['dev@thrift.apache.org'], diff --git a/contrib/thrift.spec b/contrib/thrift.spec index 93f000c9140..0eb7b067e82 100644 --- a/contrib/thrift.spec +++ b/contrib/thrift.spec @@ -28,7 +28,7 @@ Name: thrift License: Apache License v2.0 Group: Development Summary: RPC and serialization framework -Version: 0.9.1 +Version: 0.9.2 Release: 0 URL: http://thrift.apache.org Packager: Thrift Developers @@ -234,5 +234,7 @@ umask 007 /sbin/ldconfig > /dev/null 2>&1 %changelog +* Thu Oct 31 2014 Thrift Dev +- Thrift 0.9.2 release. * Wed Oct 10 2012 Thrift Dev - Thrift 0.9.0 release. diff --git a/debian/changelog b/debian/changelog index f2da2327e3c..983dd2124b3 100755 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,10 @@ -thrift (1.0.0-dev) stable; urgency=low +thrift (0.9.2) stable; urgency=low + + * update to 0.9.2 + + -- Jake Farrell Thu, 30 Oct 2014 12:00:00 -0500 + +thrift (0.9.1) stable; urgency=low * update version * fix libthrift0.install diff --git a/lib/cocoa/src/Thrift.h b/lib/cocoa/src/Thrift.h index 6fc594a4b22..e15a50e41b2 100644 --- a/lib/cocoa/src/Thrift.h +++ b/lib/cocoa/src/Thrift.h @@ -17,4 +17,4 @@ * under the License. */ -#define ThriftVersion @"1.0.0-dev" +#define ThriftVersion @"0.9.2" diff --git a/lib/cpp/src/thrift/windows/config.h b/lib/cpp/src/thrift/windows/config.h index 9261ca8de60..6af01d37403 100644 --- a/lib/cpp/src/thrift/windows/config.h +++ b/lib/cpp/src/thrift/windows/config.h @@ -60,7 +60,7 @@ #pragma warning(disable: 4996) // Deprecated posix name. -#define VERSION "1.0.0-dev" +#define VERSION "0.9.2" #define HAVE_GETTIMEOFDAY 1 #define HAVE_SYS_STAT_H 1 diff --git a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs index 2e08e66787a..078e7cbfc0f 100644 --- a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs +++ b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs @@ -56,5 +56,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.9.0.*")] -[assembly: AssemblyFileVersion("0.9.0.*")] +[assembly: AssemblyVersion("0.9.2.*")] +[assembly: AssemblyFileVersion("0.9.2.*")] diff --git a/lib/csharp/src/Properties/AssemblyInfo.WP7.cs b/lib/csharp/src/Properties/AssemblyInfo.WP7.cs index cbe1763e368..9c08a9b4a62 100644 --- a/lib/csharp/src/Properties/AssemblyInfo.WP7.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.WP7.cs @@ -51,5 +51,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.1")] -[assembly: AssemblyFileVersion("1.0.0.1")] +[assembly: AssemblyVersion("0.9.2.0")] +[assembly: AssemblyFileVersion("0.9.2.0")] diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs index dcbe74738b8..e52f5b9bc3f 100644 --- a/lib/csharp/src/Properties/AssemblyInfo.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.1")] -[assembly: AssemblyFileVersion("1.0.0.1")] +[assembly: AssemblyVersion("0.9.2.0")] +[assembly: AssemblyFileVersion("0.9.2.0")] diff --git a/lib/csharp/test/JSON/Properties/AssemblyInfo.cs b/lib/csharp/test/JSON/Properties/AssemblyInfo.cs index 6788bc3e13d..304ccfcfbab 100644 --- a/lib/csharp/test/JSON/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/JSON/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.9.2.0")] +[assembly: AssemblyFileVersion("0.9.2.0")] diff --git a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs index ee234bfd1b9..0e565c3e8d6 100644 --- a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.9.2.0")] +[assembly: AssemblyFileVersion("0.9.2.0")] diff --git a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs index 9b9dd6fd0d8..e2456e4fb67 100644 --- a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.9.2.0")] +[assembly: AssemblyFileVersion("0.9.2.0")] diff --git a/lib/csharp/test/ThriftTest/Properties/AssemblyInfo.cs b/lib/csharp/test/ThriftTest/Properties/AssemblyInfo.cs index 504ca8de7ad..9e57e41a05d 100644 --- a/lib/csharp/test/ThriftTest/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/ThriftTest/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.9.2.0")] +[assembly: AssemblyFileVersion("0.9.2.0")] diff --git a/lib/d/src/thrift/base.d b/lib/d/src/thrift/base.d index 266201b73de..b39b1f13d54 100644 --- a/lib/d/src/thrift/base.d +++ b/lib/d/src/thrift/base.d @@ -50,7 +50,7 @@ class TCompoundOperationException : TException { /// The Thrift version string, used for informative purposes. // Note: This is currently hardcoded, but will likely be filled in by the build // system in future versions. -enum VERSION = "0.9.0 dev"; +enum VERSION = "0.9.2"; /** * Functions used for logging inside Thrift. diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index 65f23abf2cd..81c49887273 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -25,7 +25,7 @@ interface SysUtils, Thrift.Protocol; const - Version = '1.0.0-dev'; + Version = '0.9.2'; type TApplicationException = class( SysUtils.Exception ) diff --git a/lib/erl/src/thrift.app.src b/lib/erl/src/thrift.app.src index 28b8cb5ba0c..810ead5143f 100644 --- a/lib/erl/src/thrift.app.src +++ b/lib/erl/src/thrift.app.src @@ -22,7 +22,7 @@ {description, "Thrift bindings"}, % The version of the applicaton - {vsn, "1.0.0-dev"}, + {vsn, "0.9.2"}, % All modules used by the application. {modules, [ diff --git a/lib/hs/Thrift.cabal b/lib/hs/Thrift.cabal index b9501cb1f6d..4fdb49a22e4 100755 --- a/lib/hs/Thrift.cabal +++ b/lib/hs/Thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 1.0.0-dev +Version: 0.9.2 Cabal-Version: >= 1.8 License: OtherLicense Category: Foreign diff --git a/lib/java/build.properties b/lib/java/build.properties index b3a4755c6bc..c9a2179a925 100644 --- a/lib/java/build.properties +++ b/lib/java/build.properties @@ -1,6 +1,6 @@ -thrift.version=1.0.0 +thrift.version=0.9.2 thrift.groupid=org.apache.thrift -release=false +release=true # Jar Versions mvn.ant.task.version=2.1.3 diff --git a/lib/js/package.json b/lib/js/package.json index 5cdd1455416..808fe8aa57b 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "1.0.0", + "version": "0.9.2", "devDependencies": { "grunt": "~0.4.1", "grunt-contrib-uglify": "~0.2.2", diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 7a18206b38d..0b7330b28b6 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -46,7 +46,7 @@ var Thrift = { * @const {string} Version * @memberof Thrift */ - Version: '1.0.0-dev', + Version: '0.9.2', /** * Thrift IDL type string to Id mapping. diff --git a/lib/lua/Thrift.lua b/lib/lua/Thrift.lua index 6ff8ecbc181..76ae5126afe 100644 --- a/lib/lua/Thrift.lua +++ b/lib/lua/Thrift.lua @@ -40,7 +40,7 @@ function terror(e) error(e) end -version = 1.0 +version = 0.9.2 TType = { STOP = 0, diff --git a/lib/nodejs/package.json b/lib/nodejs/package.json index d7e39e48b4f..a61665d1e87 100755 --- a/lib/nodejs/package.json +++ b/lib/nodejs/package.json @@ -6,7 +6,7 @@ { "type" : "git", "url" : "https://git-wip-us.apache.org/repos/asf/thrift.git" }, - "version": "1.0.0-dev", + "version": "0.9.2", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", diff --git a/lib/ocaml/_oasis b/lib/ocaml/_oasis index 4dd95e5ceb5..a9ba2ccf351 100644 --- a/lib/ocaml/_oasis +++ b/lib/ocaml/_oasis @@ -1,5 +1,5 @@ Name: libthrift-ocaml -Version: 1.0 +Version: 0.9.2 OASISFormat: 0.3 Synopsis: OCaml bindings for the Apache Thrift RPC system Authors: Apache Thrift Developers diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm index 67186f23cf9..f4f651246fe 100644 --- a/lib/perl/lib/Thrift.pm +++ b/lib/perl/lib/Thrift.pm @@ -17,7 +17,7 @@ # under the License. # -our $VERSION = '1.0.0-dev'; +our $VERSION = '0.9.2'; require 5.6.0; use strict; diff --git a/lib/py/setup.py b/lib/py/setup.py index bd177b337d0..43e77f2bb3f 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -71,7 +71,7 @@ def run_setup(with_binary): extensions = dict() setup(name = 'thrift', - version = '1.0.0-dev', + version = '0.9.2', description = 'Python bindings for the Apache Thrift RPC system', author = 'Thrift Developers', author_email = 'dev@thrift.apache.org', diff --git a/lib/rb/thrift.gemspec b/lib/rb/thrift.gemspec index 43e5a7f6b58..67b45dc3c1f 100644 --- a/lib/rb/thrift.gemspec +++ b/lib/rb/thrift.gemspec @@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__) Gem::Specification.new do |s| s.name = 'thrift' - s.version = '1.0.0.0' + s.version = '0.9.2.0' s.authors = ['Thrift Developers'] s.email = ['dev@thrift.apache.org'] s.homepage = 'http://thrift.apache.org' diff --git a/lib/st/package.xml b/lib/st/package.xml index 72194fc9347..b2b4b2fbaa7 100644 --- a/lib/st/package.xml +++ b/lib/st/package.xml @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. --> - + libthrift-st thrift.st diff --git a/sonar-project.properties b/sonar-project.properties index b465fd12e81..43baaefc4fc 100755 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -16,7 +16,7 @@ development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between all major languages. # Apache Thrift Version -sonar.projectVersion=1.0.0-dev +sonar.projectVersion=0.9.2 # use this to set another version string # $ sonar-runner -D sonar.projectVersion=`git rev-parse HEAD` # set projectDate in combination with projectVersion for imports of old releases @@ -54,7 +54,7 @@ module1.sonar.projectName=Apache Thrift - Java Library module1.sonar.projectBaseDir=lib/java module1.sonar.sources=src module1.sonar.tests=test -module1.sonar.binaries=build/libthrift-1.0.0.jar +module1.sonar.binaries=build/libthrift-0.9.2.jar module1.sonar.libraries=build/lib/*.jar module1.sonar.language=java diff --git a/test/Makefile.am b/test/Makefile.am index cc1f43d2982..138484c916b 100755 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -87,6 +87,7 @@ EXTRA_DIST = \ DebugProtoTest.thrift \ DenseLinkingTest.thrift \ DocTest.thrift \ + EnumTest.thrift \ Include.thrift \ JavaBeansTest.thrift \ ManyOptionals.thrift \ @@ -98,5 +99,7 @@ EXTRA_DIST = \ SmallTest.thrift \ StressTest.thrift \ ThriftTest.thrift \ + TypedefTest.thrift \ FastbinaryTest.py \ + result.html \ README.md diff --git a/test/erl/src/thrift_test.app.src b/test/erl/src/thrift_test.app.src index 4dcd3773431..69e2e28bd1b 100644 --- a/test/erl/src/thrift_test.app.src +++ b/test/erl/src/thrift_test.app.src @@ -22,7 +22,7 @@ {description, "tests for thrift erlang compiler backend"}, % The version of the applicaton - {vsn, "1.0.0-dev"}, + {vsn, "0.9.2"}, % All modules used by the application. {modules, [legacy_names_test, name_conflict_test, thrift_test_test]}, diff --git a/tutorial/ocaml/_oasis b/tutorial/ocaml/_oasis index 4cab0806394..d8e4e9063c9 100644 --- a/tutorial/ocaml/_oasis +++ b/tutorial/ocaml/_oasis @@ -1,5 +1,5 @@ Name: tutorial -Version: 1.0 +Version: 0.9.2 OASISFormat: 0.3 Synopsis: OCaml Tutorial example Authors: Apache Thrift Developers From 53dd39833a08ce33582e5ff31fa18bb4735d6731 Mon Sep 17 00:00:00 2001 From: jfarrell Date: Fri, 25 Sep 2015 02:30:29 -0400 Subject: [PATCH 063/756] THRIFT-2805: 0.9.3 release client: release Patch: jfarrell Versioning for 0.9.3 release rc0 --- CHANGES | 437 ++++++++++++++++++ bower.json | 2 +- build/cmake/DefineCMakeDefaults.cmake | 2 +- configure.ac | 2 +- contrib/Rebus/Properties/AssemblyInfo.cs | 6 +- contrib/fb303/py/setup.py | 2 +- contrib/thrift-maven-plugin/pom.xml | 2 +- contrib/thrift.spec | 6 +- contrib/zeromq/csharp/ThriftZMQ.csproj | 4 +- debian/changelog | 16 +- doap.rdf | 5 + lib/cocoa/src/Thrift.h | 2 +- lib/cpp/src/thrift/windows/config.h | 2 +- .../Properties/AssemblyInfo.cs | 4 +- lib/csharp/src/Properties/AssemblyInfo.WP7.cs | 4 +- lib/csharp/src/Properties/AssemblyInfo.cs | 4 +- .../test/JSON/Properties/AssemblyInfo.cs | 4 +- .../Client/Properties/AssemblyInfo.cs | 6 +- .../Server/Properties/AssemblyInfo.cs | 6 +- .../ThriftTest/Properties/AssemblyInfo.cs | 6 +- lib/d/src/thrift/base.d | 2 +- lib/delphi/src/Thrift.pas | 2 +- lib/erl/src/thrift.app.src | 2 +- lib/haxe/haxelib.json | 2 +- lib/hs/Thrift.cabal | 2 +- lib/java/build.properties | 4 +- lib/js/package.json | 2 +- lib/js/src/thrift.js | 2 +- lib/lua/Thrift.lua | 2 +- lib/ocaml/_oasis | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/py/setup.py | 2 +- lib/rb/thrift.gemspec | 2 +- lib/st/package.xml | 2 +- package.json | 2 +- sonar-project.properties | 2 +- test/erl/src/thrift_test.app.src | 2 +- tutorial/ocaml/_oasis | 2 +- 38 files changed, 505 insertions(+), 55 deletions(-) diff --git a/CHANGES b/CHANGES index a0d2a3ced97..86992614a86 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,442 @@ Apache Thrift Changelog +Thrift 0.9.3 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-2441] - Cannot shutdown TThreadedServer when clients are still connected + * [THRIFT-2465] - TBinaryProtocolT breaks if copied/moved + * [THRIFT-2474] - thrift.h causes a compile failure + * [THRIFT-2540] - Running configure from outside the source directory fails + * [THRIFT-2598] - Add check for minimum Go version to configure.ac + * [THRIFT-2647] - compiler-hs: don't decapitalize field names, do decapitalize argument bindings + * [THRIFT-2773] - Generated Java code for 'oneway' methods is incorrect. + * [THRIFT-2789] - TNonblockingServer leaks socket FD's under load + * [THRIFT-2682] - TThreadedServer leaks per-thread memory + * [THRIFT-2674] - JavaScript: declare Accept: and Content-Type: in request + * [THRIFT-3078] - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket + * [THRIFT-3077] - C++ TFileTransport ignores return code from ftruncate + * [THRIFT-3067] - C++ cppcheck performance related warnings + * [THRIFT-3066] - C++ TDenseProtocol assert modifies instead of checks + * [THRIFT-3071] - bootstrap.sh on Ubuntu 12.04 (Precise) automake error + * [THRIFT-3069] - C++ TServerSocket leaks socket on fcntl get or set flags error + * [THRIFT-3079] - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket + * [THRIFT-3080] - C++ TNonblockingServer connection leak while accept huge number connections. + * [THRIFT-3086] - C++ Valgrind Error Cleanup + * [THRIFT-3085] - thrift_reconnecting_client never try to reconnect + * [THRIFT-3123] - Missing include in compiler/cpp/src/main.h breaks build in some environments + * [THRIFT-3125] - Fix the list of exported headers in automake input + * [THRIFT-3126] - PHP JSON serializer converts empty or int-indexed maps to lists + * [THRIFT-3132] - Properly format date in Java @Generated annotations + * [THRIFT-3137] - Travis build hangs after failure + * [THRIFT-3138] - "make check" parallel execution is underministic + * [THRIFT-3139] - JS library test is flaky + * [THRIFT-3140] - ConcurrentModificationException is thrown by JavaScript test server + * [THRIFT-3124] - Some signed/unsigned warnings while building compiler + * [THRIFT-3128] - Go generated code produces name collisions between services + * [THRIFT-3146] - Graphviz generates function name collisions between services + * [THRIFT-3147] - Segfault while receiving data + * [THRIFT-3148] - Markdown links to coding_standards are dead + * [THRIFT-3090] - cmake build is broken on MacOSX + * [THRIFT-3097] - cmake targets unconditionally depend on optional libraries + * [THRIFT-3094] - master as of 2015-APR-13 fails -DBOOST_THREADS cmake build + * [THRIFT-3099] - cmake build is broken on FreeBSD + * [THRIFT-3089] - Assigning default ENUM values results in non-compilable java code if java namespace is not defined + * [THRIFT-3093] - mingw compile fixes for c++ library 0.9.2 + * [THRIFT-3098] - Thrift does not pretty print binary typedefs the way it does binary fields + * [THRIFT-3091] - c_glib service method should return result from handler method + * [THRIFT-3088] - TThreadPoolServer with Sasl auth may leak CLOSE_WAIT socket + * [THRIFT-3109] - Cross test log file cannot be browsed when served in HTTP server + * [THRIFT-3113] - m4 C++11 macro issue + * [THRIFT-3105] - C++ libthriftnb library on Windows build failure + * [THRIFT-3115] - Uncompileable code due to name collision with predefined used types + * [THRIFT-3117] - Java TSSLTransportFactory can't load certificates within JAR archive + * [THRIFT-3102] - could not make check for Go Library + * [THRIFT-3120] - Minor spelling errors and an outdated URL + * [THRIFT-3121] - Librt does not exist on OS X + * [THRIFT-3152] - Compiler error on Mac OSX (missing #include ) + * [THRIFT-3162] - make fails for dmd 2.067 + * [THRIFT-3164] - Thrift C++ library SSL socket by default allows for unsecure SSLv3 negotiation + * [THRIFT-3168] - Fix Maven POM + * [THRIFT-3170] - Initialism code in the Go compiler causes chaos + * [THRIFT-3169] - Do not export thrift.TestStruct and thrift.TestEnum in thrift Go library + * [THRIFT-3191] - Perl compiler does not add support for unexpected exception handling + * [THRIFT-3178] - glib C does not compile + * [THRIFT-3189] - Perl ServerSocket should allow a specific interface to be listened to + * [THRIFT-3252] - Missing TConcurrentClientSyncInfo.h in cpp Makefile, so doesn't install + * [THRIFT-3255] - Thrift generator doesn't exclude 'package' keyword for thrift property names breaking java builds + * [THRIFT-3260] - multiple warnings in c_glib tutorial + * [THRIFT-3256] - Some D test timings are too aggressive for slow machines + * [THRIFT-3257] - warning: extra tokens at end of #endif directive + * [THRIFT-3184] - Thrift Go leaves file descriptors open + * [THRIFT-3203] - DOAP - please fix "Ocaml" => "OCaml" + * [THRIFT-3210] - (uncompileable) code generated for server events while are events not enabled + * [THRIFT-3215] - TJSONProtocol '(c++) uses "throw new" to throw exceptions instead of "throw" + * [THRIFT-3202] - Allow HSHAServer to configure min and max worker threads separately. + * [THRIFT-3205] - TCompactProtocol return a wrong error when the io.EOF happens + * [THRIFT-3209] - LGPL mentioned in license file + * [THRIFT-3197] - keepAliveTime is hard coded as 60 sec in TThreadPoolServer + * [THRIFT-3196] - Misspelling in lua TBinaryProtocol (stirctWrite => strictWrite) + * [THRIFT-3198] - Allow construction of TTransportFactory with a specified maxLength + * [THRIFT-3192] - Go import paths changed in 1.4, and expired June 1 + * [THRIFT-3271] - Could not find or load main class configtest_ax_javac_and_java on some non-english systems + * [THRIFT-3273] - c_glib: Generated code tries to convert between function and void pointers + * [THRIFT-3264] - Fix Erlang 16 namespaced types + * [THRIFT-3270] - reusing TNonblockingServer::TConnection cause dirty TSocket + * [THRIFT-3267] - c_glib: "Critical" failure during unit tests + * [THRIFT-3277] - THttpClient leaks connections if it's used for multiple requests + * [THRIFT-3278] - NodeJS: Fix exception stack traces and names + * [THRIFT-3279] - Fix a bug in retry_max_delay (NodeJS) + * [THRIFT-3280] - Initialize retry variables on construction + * [THRIFT-3283] - c_glib: Tutorial server always exits with warning + * [THRIFT-3284] - c_glib: Empty service produces unused-variable warning + * [THRIFT-1925] - c_glib generated code does not compile + * [THRIFT-1849] - after transport->open() opens isOpen returns true and next open() goes thru when it shall not + * [THRIFT-1866] - java compiler generates non-compiling code with const's defined in a thrift when name includes non-identifier chars + * [THRIFT-1938] - FunctionRunner.h -- uses wrong path for Thread.h when installed + * [THRIFT-1844] - Password string not cleared + * [THRIFT-2004] - Thrift::Union violates :== method contract and crashes + * [THRIFT-2073] - Thrift C++ THttpClient error: cannot refill buffer + * [THRIFT-2127] - Autoconf scripting does not properly account for cross-compile + * [THRIFT-2180] - Integer types issues in Cocoa lib on ARM64 + * [THRIFT-2189] - Go needs "isset" to fully support "union" type (and optionals) + * [THRIFT-2192] - autotools on Redhat based systems + * [THRIFT-2546] - cross language tests fails at 'TestMultiException' when using nodejs server + * [THRIFT-2547] - nodejs servers and clients fails to connect with cpp using compact protocol + * [THRIFT-2548] - Nodejs servers and clients does not work properly with -ssl + * [THRIFT-1471] - toString() does not print ByteBuffer values when nested in a List + * [THRIFT-1201] - getaddrinfo resource leak + * [THRIFT-615] - TThreadPoolServer doesn't call task_done after pulling tasks from it's clients queue + * [THRIFT-162] - Thrift structures are unhashable, preventing them from being used as set elements + * [THRIFT-810] - Crashed client on TSocket::close under loads + * [THRIFT-557] - charset problem with file Autogenerated by Thrift + * [THRIFT-233] - IDL doesn't support negative hex literals + * [THRIFT-1649] - contrib/zeromq does not build in 0.8.0 + * [THRIFT-1642] - Miscalculation lead to throw unexpected "TTransportException::TIMED_OUT"(or called "EAGAIN (timed out)") exception + * [THRIFT-1587] - TSocket::setRecvTimeout error + * [THRIFT-1248] - pointer subtraction in TMemoryBuffer relies on undefined behavior + * [THRIFT-1774] - Sasl Transport client would hang when trying to connect non-sasl transport server + * [THRIFT-1754] - RangeError in buffer handling + * [THRIFT-1618] - static structMap in FieldMetaData is not thread safe and can lead to deadlocks + * [THRIFT-2335] - thrift incompatibility with py:tornado as server, java as client + * [THRIFT-2803] - TCP_DEFER_ACCEPT not supported with domain sockets + * [THRIFT-2799] - Build Problem(s): ld: library not found for -l:libboost_unit_test_framework.a + * [THRIFT-2801] - C++ test suite compilation warnings + * [THRIFT-2802] - C++ tutorial compilation warnings + * [THRIFT-2795] - thrift_binary_protocol.c: 'dereferencing type-punned pointer will break strict-aliasing rules' + * [THRIFT-2817] - TSimpleJSONProtocol reads beyond end of message + * [THRIFT-2826] - html:standalone sometimes ignored + * [THRIFT-2829] - Support haxelib installation via github + * [THRIFT-2828] - slightly wrong help screen indent + * [THRIFT-2831] - Removes dead code in web_server.js introduced in THRIFT-2819 + * [THRIFT-2823] - All JS-tests are failing when run with grunt test + * [THRIFT-2827] - Thrift 0.9.2 fails to compile on Yosemite due to tr1/functional include in ProcessorTest.cpp + * [THRIFT-2843] - Automake configure.ac has possible typo related to Java + * [THRIFT-2813] - multiple haxe library fixes/improvements + * [THRIFT-2825] - Supplying unicode to python Thrift client can cause next request arguments to get overwritten + * [THRIFT-2840] - Cabal file points to LICENSE file outside the path of the Haskell project. + * [THRIFT-2818] - Trailing commas in array + * [THRIFT-2830] - Clean up ant warnings in tutorial dir + * [THRIFT-2842] - Erlang thrift client has infinite timeout + * [THRIFT-2810] - Do not leave the underlying ServerSocket open if construction of TServerSocket fails + * [THRIFT-2812] - Go server adding redundant buffering layer + * [THRIFT-2839] - TFramedTransport read bug + * [THRIFT-2844] - Nodejs support broken when running under Browserify + * [THRIFT-2814] - args/result classes not found when no namespace is set + * [THRIFT-2847] - function IfValue() is a duplicate of System.StrUtils.IfThen + * [THRIFT-2848] - certain Delphi tests do not build if TypeRegistry is used + * [THRIFT-2854] - Go Struct writer and reader looses important error information + * [THRIFT-2858] - Enable header field case insensitive match in THttpServer + * [THRIFT-2857] - C# generator creates uncompilable code for struct constants + * [THRIFT-2860] - Delphi server closes connection on unexpected exceptions + * [THRIFT-2868] - Enhance error handling in the Go client + * [THRIFT-2879] - TMemoryBuffer: using lua string in wrong way + * [THRIFT-2851] - Remove strange public Peek() from Go transports + * [THRIFT-2852] - Better Open/IsOpen/Close behavior for StreamTransport. + * [THRIFT-2871] - Missing semicolon in thrift.js + * [THRIFT-2872] - ThreadManager deadlock for task expiration + * [THRIFT-2881] - Handle errors from Accept() correctly + * [THRIFT-2849] - Spell errors reported by codespell tool + * [THRIFT-2870] - C++ TJSONProtocol using locale dependent formatting + * [THRIFT-2882] - Lua Generator: using string.len funtion to get struct(map,list,set) size + * [THRIFT-2864] - JSON generator missing from Visual Studio build project + * [THRIFT-2878] - Go validation support of required fields + * [THRIFT-2873] - TPipe and TPipeServer don't compile on Windows with UNICODE enabled + * [THRIFT-2888] - import of is missing in JSON generator + * [THRIFT-2900] - Python THttpClient does not reset socket timeout on exception + * [THRIFT-2907] - 'ntohll' macro redefined + * [THRIFT-2884] - Map does not serialize correctly for JSON protocol in Go library + * [THRIFT-2887] - --with-openssl configure flag is ignored + * [THRIFT-2894] - PHP json serializer skips maps with int/bool keys + * [THRIFT-2904] - json_protocol_test.go fails + * [THRIFT-2906] - library not found for -l:libboost_unit_test_framework.a + * [THRIFT-2890] - binary data may lose bytes with JSON transport under specific circumstances + * [THRIFT-2891] - binary data may cause a failure with JSON transport under specific circumstances + * [THRIFT-2901] - Fix for generated TypeScript functions + indentation of JavaScript maps + * [THRIFT-2916] - make check fails for D language + * [THRIFT-2918] - Race condition in Python TProcessPoolServer test + * [THRIFT-2920] - Erlang Thrift test uses wrong IDL file + * [THRIFT-2922] - $TRIAL is used with Python tests but not tested accordingly + * [THRIFT-2912] - Autotool build for C++ Qt library is invalid + * [THRIFT-2914] - explicit dependency to Lua5.2 fails on some systems + * [THRIFT-2910] - libevent is not really optional + * [THRIFT-2911] - fix c++ version zeromq transport, the old version cannot work + * [THRIFT-2915] - Lua generator missing from Visual Studio build project + * [THRIFT-2917] - "make clean" breaks test/c_glib + * [THRIFT-2919] - Haxe test server timeout too large + * [THRIFT-2923] - JavaScript client assumes a message being written + * [THRIFT-2924] - TNonblockingServer crashes when user-provided event_base is used + * [THRIFT-2925] - CMake build does not work with OpenSSL nor anything installed in non-system location + * [THRIFT-2931] - Access to undeclared static property: Thrift\Protocol\TProtocol::$TBINARYPROTOCOLACCELERATED + * [THRIFT-2893] - CMake build fails with boost thread or std thread + * [THRIFT-2902] - Generated c_glib code does not compile with clang + * [THRIFT-2903] - Qt4 library built with CMake does not work + * [THRIFT-2942] - CSharp generate invalid code for property named read or write + * [THRIFT-2932] - Node.js Thrift connection libraries throw Exceptions into event emitter + * [THRIFT-2933] - v0.9.2: doubles encoded in node with compact protocol cannot be decoded by python + * [THRIFT-2934] - createServer signature mismatch + * [THRIFT-2981] - IDL with no namespace produces unparsable PHP + * [THRIFT-2999] - Addition of .gitattributes text auto in THRIFT-2724 causes modified files on checkout + * [THRIFT-2949] - typo in compiler/cpp/README.md + * [THRIFT-2957] - warning: source file %s is in a subdirectory, but option 'subdir-objects' is disabled + * [THRIFT-2953] - TNamedPipeServerTransport is not Stop()able + * [THRIFT-2962] - Docker Thrift env for development and testing + * [THRIFT-2971] - C++ test and tutorial parallel build is unstable + * [THRIFT-2972] - Missing backslash in lib/cpp/test/Makefile.am + * [THRIFT-2951] - Fix Erlang name conflict test + * [THRIFT-2955] - Using list of typedefs does not compile on Go + * [THRIFT-2960] - namespace regression for Ruby + * [THRIFT-2959] - nodejs: fix binary unit tests + * [THRIFT-2966] - nodejs: Fix bad references to TProtocolException and TProtocolExceptionType + * [THRIFT-2970] - grunt-jsdoc fails due to dependency issues + * [THRIFT-3001] - C# Equals fails for binary fields (byte[]) + * [THRIFT-3003] - Missing LICENSE file prevents package from being installed + * [THRIFT-3008] - Node.js server does not fully support exception + * [THRIFT-3007] - Travis build is broken because of directory conflict + * [THRIFT-3009] - TSSLSocket does not use the correct hostname (breaks certificate checks) + * [THRIFT-3011] - C# test server testException() not implemented according to specs + * [THRIFT-3012] - Timing problems in NamedPipe implementation due to unnecessary open/close + * [THRIFT-3019] - Golang generator missing docstring for structs + * [THRIFT-3021] - Service remote tool does not import stub package with package prefix + * [THRIFT-3026] - TMultiplexedProcessor does not have a constructor + * [THRIFT-3028] - Regression caused by THRIFT-2180 + * [THRIFT-3017] - order of map key/value types incorrect for one CTOR + * [THRIFT-3020] - Cannot compile thrift as C++03 + * [THRIFT-3024] - User-Agent "BattleNet" used in some Thrift library files + * [THRIFT-3047] - Uneven calls to indent_up and indent_down in Cocoa generator + * [THRIFT-3048] - NodeJS decoding of I64 is inconsistent across protocols + * [THRIFT-3043] - go compiler generator uses non C++98 code + * [THRIFT-3044] - Docker README.md paths to Dockerfiles are incorrect + * [THRIFT-3040] - bower.json wrong "main" path + * [THRIFT-3051] - Go Thrift generator creates bad go code + * [THRIFT-3057] - Java compiler build is broken + * [THRIFT-3061] - C++ TSSLSocket shutdown delay/vulnerability + * [THRIFT-3062] - C++ TServerSocket invalid port number (over 999999) causes stack corruption + * [THRIFT-3065] - Update libthrift dependencies (slf4j, httpcore, httpclient) + * [THRIFT-3244] - TypeScript: fix namespace of included types + * [THRIFT-3246] - Reduce the number of trivial warnings in Windows C++ CMake builds + * [THRIFT-3224] - Fix TNamedPipeServer unpredictable behavior on accept + * [THRIFT-3230] - Python compiler generates wrong code if there is function throwing a typedef of exception with another namespace + * [THRIFT-3236] - MaxSkipDepth never checked + * [THRIFT-3239] - Limit recursion depth + * [THRIFT-3241] - fatal error: runtime: cannot map pages in arena address space + * [THRIFT-3242] - OSGi Import-Package directive is missing the Apache HTTP packages + * [THRIFT-3234] - Limit recursion depth + * [THRIFT-3222] - TypeScript: Generated Enums are quoted + * [THRIFT-3229] - unexpected Timeout exception when desired bytes are only partially available + * [THRIFT-3231] - CPP: Limit recursion depth to 64 + * [THRIFT-3235] - Limit recursion depth + * [THRIFT-3175] - fastbinary.c python deserialize can cause huge allocations from garbage + * [THRIFT-3176] - Union incorrectly implements == + * [THRIFT-3177] - Fails to run rake test + * [THRIFT-3180] - lua plugin: framed transport do not work + * [THRIFT-3179] - lua plugin cant connect to remote server because function l_socket_create_and_connect always bind socket to localhost + * [THRIFT-3248] - TypeScript: additional comma in method signature without parameters + * [THRIFT-3302] - Go JSON protocol should encode Thrift byte type as signed integer string + * [THRIFT-3297] - c_glib: an abstract base class is not generated + * [THRIFT-3294] - TZlibTransport for Java does not write data correctly + * [THRIFT-3296] - Go cross test does not conform to spec + * [THRIFT-3295] - C# library does not build on Mono 4.0.2.5 or later + * [THRIFT-3293] - JavaScript: null values turn into empty structs in constructor + * [THRIFT-3310] - lib/erl/README.md has incorrect formatting + * [THRIFT-3319] - CSharp tutorial will not build using the *.sln + * [THRIFT-3335] - Ruby server does not handle processor exception + * [THRIFT-3338] - Stray underscore in generated go when service name starts with "New" + * [THRIFT-3324] - Update Go Docs for pulling all packages + * [THRIFT-3345] - Clients blocked indefinitely when a java.lang.Error is thrown + * [THRIFT-3332] - make dist fails on clean build + * [THRIFT-3326] - Tests do not compile under *BSD + * [THRIFT-3334] - Markdown notation of protocol spec is malformed + * [THRIFT-3331] - warning: ‘etype’ may be used uninitialized in this function + * [THRIFT-3349] - Python server does not handle processor exception + * [THRIFT-3343] - Fix haskell README + * [THRIFT-3340] - Python: enable json tests again + * [THRIFT-3311] - Top level README.md has incorrect formmating + * [THRIFT-2936] - Minor memory leak in SSL + * [THRIFT-3290] - Using from in variable names causes the generated Python code to have errors + * [THRIFT-3225] - Fix TPipeServer unpredictable behavior on interrupt() + * [THRIFT-3354] - Fix word-extraction substr bug in initialism code + * [THRIFT-2006] - TBinaryProtocol message header call name length is not validated and can be used to core the server + * [THRIFT-3329] - C++ library unit tests don't compile against the new boost-1.59 unit test framework + * [THRIFT-2630] - windows7 64bit pc. ipv4 and ipv6 pc.can't use + * [THRIFT-3336] - Thrift generated streaming operators added in 0.9.2 cannot be overridden + * [THRIFT-2681] - Core of unwind_cleanup + * [THRIFT-3317] - cpp namespace org.apache issue appears in 0.9 + +## Documentation + * [THRIFT-3286] - Apache Ant is a necessary dependency + +## Improvement + * [THRIFT-227] - Byte[] in collections aren't pretty printed like regular binary fields + * [THRIFT-2744] - Vagrantfile for Centos 6.5 + * [THRIFT-2644] - Haxe support + * [THRIFT-2756] - register Media Type @ IANA + * [THRIFT-3076] - Compatibility with Haxe 3.2.0 + * [THRIFT-3081] - C++ Consolidate client processing loops in TServers + * [THRIFT-3083] - C++ Consolidate server processing loops in TSimpleServer, TThreadedServer, TThreadPoolServer + * [THRIFT-3084] - C++ add concurrent client limit to threaded servers + * [THRIFT-3074] - Add compiler/cpp/lex.yythriftl.cc to gitignore. + * [THRIFT-3134] - Remove use of deprecated "phantom.args" + * [THRIFT-3133] - Allow "make cross" and "make precross" to run without building all languages + * [THRIFT-3142] - Make JavaScript use downloaded libraries + * [THRIFT-3141] - Improve logging of JavaScript test + * [THRIFT-3144] - Proposal: make String representation of enums in generated go code less verbose + * [THRIFT-3130] - Remove the last vestiges of THRIFT_OVERLOAD_IF from THRIFT-1316 + * [THRIFT-3131] - Consolidate suggested import path for go thrift library to git.apache.org in docs and code + * [THRIFT-3092] - Generated Haskell types should derive Generic + * [THRIFT-3110] - Print error log after cross test failures on Travis + * [THRIFT-3114] - Using local temp variables to not pollute the global table + * [THRIFT-3106] - CMake summary should give more information why a library is set to off + * [THRIFT-3119] - Java's TThreadedSelectorServer has indistinguishable log messages in run() + * [THRIFT-3122] - Javascript struct constructor should properly initialize struct and container members from plain js arguments + * [THRIFT-3151] - Fix links to git-wip* - should be git.apache.org + * [THRIFT-3167] - Windows build from source instructions need to be revised + * [THRIFT-3155] - move contrib/mingw32-toolchain.cmake to build/cmake/ + * [THRIFT-3160] - Make generated go enums implement TextMarshaller and TextUnmarshaller interfaces + * [THRIFT-3150] - Add an option to thrift go generator to make Read and Write methods private + * [THRIFT-3149] - Make ReadFieldN methods in generated Go code private + * [THRIFT-3172] - Add tutorial to Thrift web site + * [THRIFT-3214] - Add Erlang option for using maps instead of dicts + * [THRIFT-3201] - Capture github test artifacts for failed builds + * [THRIFT-3266] - c_glib: Multiple compiler warnings building unit tests + * [THRIFT-3285] - c_glib: Build library with all warnings enabled, no warnings generated + * [THRIFT-1954] - Allow for a separate connection timeout value + * [THRIFT-2098] - Add support for Qt5+ + * [THRIFT-2199] - Remove Dense protocol (was: move to Contrib) + * [THRIFT-406] - C++ Test suite cleanup + * [THRIFT-902] - socket and connect timeout in TSocket should be distinguished + * [THRIFT-388] - Use a separate wire format for async calls + * [THRIFT-727] - support native C++ language specific exception message + * [THRIFT-1784] - pep-3110 compliance for exception handling + * [THRIFT-1025] - C++ ServerSocket should inherit from Socket with the necessary Ctor to listen on connections from a specific host + * [THRIFT-2269] - Can deploy libthrift-source.jar to maven center repository + * [THRIFT-2804] - Pull an interface out of TBaseAsyncProcessor + * [THRIFT-2806] - more whitespace fixups + * [THRIFT-2811] - Make remote socket address accessible + * [THRIFT-2809] - .gitignore update for compiler's visual project + * [THRIFT-2846] - Expose ciphers parameter from ssl.wrap_socket() + * [THRIFT-2859] - JSON generator: output complete descriptors + * [THRIFT-2861] - add buffered transport + * [THRIFT-2865] - Test case for Go: SeqId out of sequence + * [THRIFT-2866] - Go generator source code is hard to read and maintain + * [THRIFT-2880] - Read the network address from the listener if available. + * [THRIFT-2875] - Typo in TDenseProtocol.h comment + * [THRIFT-2874] - TBinaryProtocol member variable "string_buf_" is never used. + * [THRIFT-2855] - Move contributing.md to the root of the repository + * [THRIFT-2862] - Enable RTTI and/or build macros for generated code + * [THRIFT-2876] - Add test for THRIFT-2526 Assignment operators and copy constructors in c++ don't copy the __isset struct + * [THRIFT-2897] - Generate -isEqual: and -hash methods + * [THRIFT-2909] - Improve travis build + * [THRIFT-2921] - Make Erlang impl ready for OTP 18 release (dict/0 and set/0 are deprecated) + * [THRIFT-2928] - Rename the erlang test_server module + * [THRIFT-2940] - Allow installing Thrift from git as NPM module by providing package.json in top level directory + * [THRIFT-2937] - Allow setting a maximum frame size in TFramedTransport + * [THRIFT-2976] - nodejs: xhr and websocket support for browserify + * [THRIFT-2996] - Test for Haxe 3.1.3 or better + * [THRIFT-2969] - nodejs: DRY up library tests + * [THRIFT-2973] - Update Haxe lib readme regarding Haxe 3.1.3 + * [THRIFT-2952] - Improve handling of Server.Stop() + * [THRIFT-2964] - nodejs: move protocols and transports into separate files + * [THRIFT-2963] - nodejs - add test coverage + * [THRIFT-3006] - Attach 'omitempty' json tag for optional fields in Go + * [THRIFT-3027] - Go compiler does not ensure common initialisms have consistent case + * [THRIFT-3030] - TThreadedServer: Property for number of clientThreads + * [THRIFT-3023] - Go compiler is a little overly conservative with names of attributes + * [THRIFT-3018] - Compact protocol for Delphi + * [THRIFT-3025] - Change pure Int constants into @enums (where possible) + * [THRIFT-3031] - migrate "shouldStop" flag to TServer + * [THRIFT-3022] - Compact protocol for Haxe + * [THRIFT-3041] - Generate asynchronous clients for Cocoa + * [THRIFT-3053] - Perl SSL Socket Support (Encryption) + * [THRIFT-3247] - Generate a C++ thread-safe client + * [THRIFT-3217] - Provide a little endian variant of the binary protocol in C++ + * [THRIFT-3223] - TypeScript: Add initial support for Enum Maps + * [THRIFT-3220] - Option to suppress @Generated Annotation entirely + * [THRIFT-3300] - Reimplement TZlibTransport in Java using streams + * [THRIFT-3288] - c_glib: Build unit tests with all warnings enabled, no warnings generated + * [THRIFT-3347] - Improve cross test servers and clients + * [THRIFT-3342] - Improve ruby cross test client and server compatibility + * [THRIFT-2296] - Add C++ Base class for service + * [THRIFT-3337] - Add testBool method to cross tests + * [THRIFT-3303] - Disable concurrent cabal jobs on Travis to avoid GHC crash + * [THRIFT-2623] - Docker container for Thrift + * [THRIFT-3298] - thrift endian converters may conflict with other libraries + * [THRIFT-1559] - Provide memory pool for TBinaryProtocol to eliminate memory fragmentation + * [THRIFT-424] - Steal ProtocolBuffers' VarInt implementation for C++ + +## New Feature + * [THRIFT-3070] - Add ability to set the LocalCertificateSelectionCallback + * [THRIFT-1909] - Java: Add compiler flag to use the "option pattern" for optional fields + * [THRIFT-2099] - Stop TThreadPoolServer with alive connections. + * [THRIFT-123] - implement TZlibTransport in Java + * [THRIFT-2368] - New option: reuse-objects for Java generator + * [THRIFT-2836] - Optionally generate C++11 MoveConstructible types + * [THRIFT-2824] - Flag to disable html escaping doctext + * [THRIFT-2819] - Add WebsSocket client to node.js + * [THRIFT-3050] - Client certificate authentication for non-http TLS in C# + * [THRIFT-3292] - Implement TZlibTransport in Go + +## Question + * [THRIFT-2583] - Thrift on xPC target (SpeedGoat) + * [THRIFT-2592] - thrift server using c_glib + * [THRIFT-2832] - c_glib: Handle string lists correctly + * [THRIFT-3136] - thrift installation problem on mac + * [THRIFT-3346] - c_glib: Tutorials example crashes saying Calculator.ping implementation returned FALSE but did not set an error + +## Sub-task + * [THRIFT-2578] - Moving 'make cross' from test.sh to test.py + * [THRIFT-2734] - Go coding standards + * [THRIFT-2748] - Add Vagrantfile for Centos 6.5 + * [THRIFT-2753] - Misc. Haxe improvements + * [THRIFT-2640] - Compact Protocol in Cocoa + * [THRIFT-3262] - warning: overflow in implicit constant conversion in DenseProtoTest.cpp + * [THRIFT-3194] - Can't build with go enabled. gomock SCC path incorrect. + * [THRIFT-3275] - c_glib tutorial warnings in generated code + * [THRIFT-1125] - Multiplexing support for the Ruby Library + * [THRIFT-2807] - PHP Code Style + * [THRIFT-2841] - Add comprehensive integration tests for the whole Go stack + * [THRIFT-2815] - Haxe: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-2886] - Integrate binary type in standard Thrift cross test + * [THRIFT-2946] - Enhance usability of cross test framework + * [THRIFT-2967] - Add .editorconfig to root + * [THRIFT-3033] - Perl: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-3174] - Initialism code in the Go compiler doesn't check first word + * [THRIFT-3193] - Option to supress date value in @Generated annotation + * [THRIFT-3305] - Missing dist files for 0.9.3 release candidate + * [THRIFT-3341] - Add testBool methods + * [THRIFT-3308] - Fix broken test cases for 0.9.3 release candidate + +## Task + * [THRIFT-2834] - Remove semi-colons from python code generator + * [THRIFT-2853] - Adjust comments not applying anymore after THRIFT-2852 + +## Test + * [THRIFT-3211] - Add make cross support for php TCompactProtocol + +## Wish + * [THRIFT-2838] - TNonblockingServer can bind to port 0 (i.e., get an OS-assigned port) but there is no way to get the port number + + + Thrift 0.9.2 -------------------------------------------------------------------------------- ## Bug diff --git a/bower.json b/bower.json index afd8561ff0c..e0612e32533 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.9.2", + "version": "0.9.3", "homepage": "https://git-wip-us.apache.org/repos/asf/thrift.git", "authors": [ "Apache Thrift " diff --git a/build/cmake/DefineCMakeDefaults.cmake b/build/cmake/DefineCMakeDefaults.cmake index 7073e8ef83d..34ff7381f30 100644 --- a/build/cmake/DefineCMakeDefaults.cmake +++ b/build/cmake/DefineCMakeDefaults.cmake @@ -35,7 +35,7 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) set(CMAKE_COLOR_MAKEFILE ON) # Define the generic version of the libraries here -set(GENERIC_LIB_VERSION "0.1.0") +set(GENERIC_LIB_VERSION "0.9.3") set(GENERIC_LIB_SOVERSION "0") # Set the default build type to release with debug info diff --git a/configure.ac b/configure.ac index 880cc3225bb..18e323341b4 100755 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ(2.65) AC_CONFIG_MACRO_DIR([./aclocal]) -AC_INIT([thrift], [1.0.0-dev]) +AC_INIT([thrift], [0.9.3]) AC_CONFIG_AUX_DIR([.]) diff --git a/contrib/Rebus/Properties/AssemblyInfo.cs b/contrib/Rebus/Properties/AssemblyInfo.cs index e476eab7656..5de6a147d3c 100644 --- a/contrib/Rebus/Properties/AssemblyInfo.cs +++ b/contrib/Rebus/Properties/AssemblyInfo.cs @@ -26,7 +26,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("RebusSample")] -[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -34,5 +34,5 @@ [assembly: Guid("0af10984-40d3-453d-b1e5-421529e8c7e2")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.9.3.0")] +[assembly: AssemblyFileVersion("0.9.3.0")] diff --git a/contrib/fb303/py/setup.py b/contrib/fb303/py/setup.py index 6710c8f61db..6d42bd1c1c8 100644 --- a/contrib/fb303/py/setup.py +++ b/contrib/fb303/py/setup.py @@ -26,7 +26,7 @@ from distutils.core import setup, Extension, Command setup(name = 'thrift_fb303', - version = '1.0.0-dev', + version = '0.9.3', description = 'Python bindings for the Apache Thrift FB303', author = ['Thrift Developers'], author_email = ['dev@thrift.apache.org'], diff --git a/contrib/thrift-maven-plugin/pom.xml b/contrib/thrift-maven-plugin/pom.xml index 5bc10041436..b12a8213137 100644 --- a/contrib/thrift-maven-plugin/pom.xml +++ b/contrib/thrift-maven-plugin/pom.xml @@ -27,7 +27,7 @@ thrift-maven-plugin maven-plugin thrift-maven-plugin - 1.0-SNAPSHOT + 0.9.3 diff --git a/contrib/thrift.spec b/contrib/thrift.spec index 93f000c9140..dab3275ec0f 100644 --- a/contrib/thrift.spec +++ b/contrib/thrift.spec @@ -28,7 +28,7 @@ Name: thrift License: Apache License v2.0 Group: Development Summary: RPC and serialization framework -Version: 0.9.1 +Version: 0.9.3 Release: 0 URL: http://thrift.apache.org Packager: Thrift Developers @@ -234,5 +234,5 @@ umask 007 /sbin/ldconfig > /dev/null 2>&1 %changelog -* Wed Oct 10 2012 Thrift Dev -- Thrift 0.9.0 release. +* Wed Sept 25 2015 Thrift Dev +- Thrift 0.9.3 release. diff --git a/contrib/zeromq/csharp/ThriftZMQ.csproj b/contrib/zeromq/csharp/ThriftZMQ.csproj index 6b465306554..958fc55cc1b 100755 --- a/contrib/zeromq/csharp/ThriftZMQ.csproj +++ b/contrib/zeromq/csharp/ThriftZMQ.csproj @@ -25,7 +25,7 @@ false true 0 - 1.0.0.%2a + 0.9.3.%2a false false true @@ -88,4 +88,4 @@ -
\ No newline at end of file +
diff --git a/debian/changelog b/debian/changelog index f2da2327e3c..4638a1f1035 100755 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,16 @@ -thrift (1.0.0-dev) stable; urgency=low - * update version - * fix libthrift0.install +thrift (0.9.3) stable; urgency=low + * update to 0.9.3 - -- Roger Meier Tue, 08 Jan 2013 22:40:12 +0100 + -- Jake Farrell Fri, 25 Sep 2015 12:00:00 -0500 + +thrift (0.9.2) stable; urgency=low + + * update to 0.9.2 + + -- Jake Farrell Thu, 30 Oct 2014 12:00:00 -0500 + +thrift (0.9.1) stable; urgency=low + * update to 0.9.1 thrift (0.9.0) stable; urgency=low diff --git a/doap.rdf b/doap.rdf index b6396d9a5bb..5ff99458a2d 100755 --- a/doap.rdf +++ b/doap.rdf @@ -55,6 +55,11 @@ + + Apache Thrift + 2015-09-25 + 0.9.3 + Apache Thrift 2013-08-22 diff --git a/lib/cocoa/src/Thrift.h b/lib/cocoa/src/Thrift.h index 6fc594a4b22..9cedb66284d 100644 --- a/lib/cocoa/src/Thrift.h +++ b/lib/cocoa/src/Thrift.h @@ -17,4 +17,4 @@ * under the License. */ -#define ThriftVersion @"1.0.0-dev" +#define ThriftVersion @"0.9.3" diff --git a/lib/cpp/src/thrift/windows/config.h b/lib/cpp/src/thrift/windows/config.h index 24a94f86fc4..580d68008ba 100644 --- a/lib/cpp/src/thrift/windows/config.h +++ b/lib/cpp/src/thrift/windows/config.h @@ -60,7 +60,7 @@ #pragma warning(disable : 4996) // Deprecated posix name. -#define VERSION "1.0.0-dev" +#define VERSION "0.9.3" #define HAVE_GETTIMEOFDAY 1 #define HAVE_SYS_STAT_H 1 diff --git a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs index 2e08e66787a..7b074f0ee61 100644 --- a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs +++ b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs @@ -56,5 +56,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.9.0.*")] -[assembly: AssemblyFileVersion("0.9.0.*")] +[assembly: AssemblyVersion("0.9.3.*")] +[assembly: AssemblyFileVersion("0.9.3.*")] diff --git a/lib/csharp/src/Properties/AssemblyInfo.WP7.cs b/lib/csharp/src/Properties/AssemblyInfo.WP7.cs index cbe1763e368..9237506fcd5 100644 --- a/lib/csharp/src/Properties/AssemblyInfo.WP7.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.WP7.cs @@ -51,5 +51,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.1")] -[assembly: AssemblyFileVersion("1.0.0.1")] +[assembly: AssemblyVersion("0.9.3.0")] +[assembly: AssemblyFileVersion("0.9.3.0")] diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs index dcbe74738b8..090126e531a 100644 --- a/lib/csharp/src/Properties/AssemblyInfo.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.1")] -[assembly: AssemblyFileVersion("1.0.0.1")] +[assembly: AssemblyVersion("0.9.3.0")] +[assembly: AssemblyFileVersion("0.9.3.0")] diff --git a/lib/csharp/test/JSON/Properties/AssemblyInfo.cs b/lib/csharp/test/JSON/Properties/AssemblyInfo.cs index 6788bc3e13d..f0faf9a6da2 100644 --- a/lib/csharp/test/JSON/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/JSON/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.9.3.0")] +[assembly: AssemblyFileVersion("0.9.3.0")] diff --git a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs index ee234bfd1b9..26c279057f8 100644 --- a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs @@ -29,7 +29,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("MultiplexClient")] -[assembly: AssemblyCopyright("Copyright © 2013 The Apache Software Foundation")] +[assembly: AssemblyCopyright("Copyright © 2015 The Apache Software Foundation")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.9.3.0")] +[assembly: AssemblyFileVersion("0.9.3.0")] diff --git a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs index 9b9dd6fd0d8..3a95839ebd7 100644 --- a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs @@ -29,7 +29,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("MultiplexServer")] -[assembly: AssemblyCopyright("Copyright © 2013 The Apache Software Foundation")] +[assembly: AssemblyCopyright("Copyright © 2015 The Apache Software Foundation")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.9.3.0")] +[assembly: AssemblyFileVersion("0.9.3.0")] diff --git a/lib/csharp/test/ThriftTest/Properties/AssemblyInfo.cs b/lib/csharp/test/ThriftTest/Properties/AssemblyInfo.cs index 504ca8de7ad..62a4a23f5d4 100644 --- a/lib/csharp/test/ThriftTest/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/ThriftTest/Properties/AssemblyInfo.cs @@ -29,7 +29,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ThriftTest")] -[assembly: AssemblyCopyright("Copyright © 2009 The Apache Software Foundation")] +[assembly: AssemblyCopyright("Copyright © 2015 The Apache Software Foundation")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.9.3.0")] +[assembly: AssemblyFileVersion("0.9.3.0")] diff --git a/lib/d/src/thrift/base.d b/lib/d/src/thrift/base.d index 57aec1818d3..6e1b5587ad4 100644 --- a/lib/d/src/thrift/base.d +++ b/lib/d/src/thrift/base.d @@ -50,7 +50,7 @@ class TCompoundOperationException : TException { /// The Thrift version string, used for informative purposes. // Note: This is currently hardcoded, but will likely be filled in by the build // system in future versions. -enum VERSION = "0.9.0 dev"; +enum VERSION = "0.9.3"; /** * Functions used for logging inside Thrift. diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index 65f23abf2cd..096d6a1657d 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -25,7 +25,7 @@ interface SysUtils, Thrift.Protocol; const - Version = '1.0.0-dev'; + Version = '0.9.3'; type TApplicationException = class( SysUtils.Exception ) diff --git a/lib/erl/src/thrift.app.src b/lib/erl/src/thrift.app.src index 28b8cb5ba0c..c306e0afddc 100644 --- a/lib/erl/src/thrift.app.src +++ b/lib/erl/src/thrift.app.src @@ -22,7 +22,7 @@ {description, "Thrift bindings"}, % The version of the applicaton - {vsn, "1.0.0-dev"}, + {vsn, "0.9.3"}, % All modules used by the application. {modules, [ diff --git a/lib/haxe/haxelib.json b/lib/haxe/haxelib.json index c780ebe2199..bd07ac5343c 100644 --- a/lib/haxe/haxelib.json +++ b/lib/haxe/haxelib.json @@ -4,7 +4,7 @@ "license": "Apache 2.0", "tags": ["thrift", "rpc", "serialization", "cross", "framework"], "description": "Haxe bindings for the Apache Thrift RPC and serialization framework", - "version": "1.0.0-dev.141115", + "version": "0.9.3", "releasenote": "The Apache Thrift compiler needs to be installed separately, see http://thrift.apache.org", "contributors": ["Apache Software Foundation (ASF)"], "dependencies": { } diff --git a/lib/hs/Thrift.cabal b/lib/hs/Thrift.cabal index 5610a5cc9ad..0aa6555b79e 100755 --- a/lib/hs/Thrift.cabal +++ b/lib/hs/Thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 1.0.0-dev +Version: 0.9.3 Cabal-Version: >= 1.8 License: OtherLicense Category: Foreign diff --git a/lib/java/build.properties b/lib/java/build.properties index 96cf8d32c53..abe1c10d0da 100644 --- a/lib/java/build.properties +++ b/lib/java/build.properties @@ -1,6 +1,6 @@ -thrift.version=1.0.0 +thrift.version=0.9.3 thrift.groupid=org.apache.thrift -release=false +release=true # Jar Versions mvn.ant.task.version=2.1.3 diff --git a/lib/js/package.json b/lib/js/package.json index a60c00ab9de..f40e8b38bdb 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "1.0.0", + "version": "0.9.3", "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-uglify": "~0.2.2", diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 9bd1198ae98..955c2de2198 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -46,7 +46,7 @@ var Thrift = { * @const {string} Version * @memberof Thrift */ - Version: '1.0.0-dev', + Version: '0.9.3', /** * Thrift IDL type string to Id mapping. diff --git a/lib/lua/Thrift.lua b/lib/lua/Thrift.lua index a9a90780007..9b8eb2f130b 100644 --- a/lib/lua/Thrift.lua +++ b/lib/lua/Thrift.lua @@ -48,7 +48,7 @@ function ttable_size(t) return count end -version = 1.0 +version = 0.9.3 TType = { STOP = 0, diff --git a/lib/ocaml/_oasis b/lib/ocaml/_oasis index 4dd95e5ceb5..cbfa7d1c1f8 100644 --- a/lib/ocaml/_oasis +++ b/lib/ocaml/_oasis @@ -1,5 +1,5 @@ Name: libthrift-ocaml -Version: 1.0 +Version: 0.9.3 OASISFormat: 0.3 Synopsis: OCaml bindings for the Apache Thrift RPC system Authors: Apache Thrift Developers diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm index 06e110b4807..2e70dcd8578 100644 --- a/lib/perl/lib/Thrift.pm +++ b/lib/perl/lib/Thrift.pm @@ -17,7 +17,7 @@ # under the License. # -our $VERSION = '1.0.0-dev'; +our $VERSION = '0.9.3'; require 5.6.0; use strict; diff --git a/lib/py/setup.py b/lib/py/setup.py index 7e0a964646a..836cf71ba17 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -71,7 +71,7 @@ def run_setup(with_binary): extensions = dict() setup(name = 'thrift', - version = '1.0.0-dev', + version = '0.9.3', description = 'Python bindings for the Apache Thrift RPC system', author = 'Thrift Developers', author_email = 'dev@thrift.apache.org', diff --git a/lib/rb/thrift.gemspec b/lib/rb/thrift.gemspec index 43e5a7f6b58..b4074cbd507 100644 --- a/lib/rb/thrift.gemspec +++ b/lib/rb/thrift.gemspec @@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__) Gem::Specification.new do |s| s.name = 'thrift' - s.version = '1.0.0.0' + s.version = '0.9.3.0' s.authors = ['Thrift Developers'] s.email = ['dev@thrift.apache.org'] s.homepage = 'http://thrift.apache.org' diff --git a/lib/st/package.xml b/lib/st/package.xml index 72194fc9347..d4060180d9d 100644 --- a/lib/st/package.xml +++ b/lib/st/package.xml @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. --> - + libthrift-st thrift.st diff --git a/package.json b/package.json index b931a159ee3..7cc1ef970fb 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://git-wip-us.apache.org/repos/asf/thrift.git" }, - "version": "1.0.0-dev", + "version": "0.9.3", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", diff --git a/sonar-project.properties b/sonar-project.properties index b465fd12e81..21fec3d91db 100755 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -16,7 +16,7 @@ development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between all major languages. # Apache Thrift Version -sonar.projectVersion=1.0.0-dev +sonar.projectVersion=0.9.3 # use this to set another version string # $ sonar-runner -D sonar.projectVersion=`git rev-parse HEAD` # set projectDate in combination with projectVersion for imports of old releases diff --git a/test/erl/src/thrift_test.app.src b/test/erl/src/thrift_test.app.src index 4dcd3773431..a0c348f153a 100644 --- a/test/erl/src/thrift_test.app.src +++ b/test/erl/src/thrift_test.app.src @@ -22,7 +22,7 @@ {description, "tests for thrift erlang compiler backend"}, % The version of the applicaton - {vsn, "1.0.0-dev"}, + {vsn, "0.9.3"}, % All modules used by the application. {modules, [legacy_names_test, name_conflict_test, thrift_test_test]}, diff --git a/tutorial/ocaml/_oasis b/tutorial/ocaml/_oasis index 4cab0806394..869caf10d7d 100644 --- a/tutorial/ocaml/_oasis +++ b/tutorial/ocaml/_oasis @@ -1,5 +1,5 @@ Name: tutorial -Version: 1.0 +Version: 0.9.3 OASISFormat: 0.3 Synopsis: OCaml Tutorial example Authors: Apache Thrift Developers From b2a4d4ae21c789b689dd162deb819665567f481c Mon Sep 17 00:00:00 2001 From: jfarrell Date: Mon, 4 Apr 2016 14:25:03 -0400 Subject: [PATCH 064/756] THRIFT-3775: 0.10.0 release Client: release Patch: jfarrell Versioning for 0.10.0 release candidate --- CHANGES | 587 ++++++++++++++++++ README.md | 42 +- Thrift.podspec | 4 +- bower.json | 2 +- build/cmake/DefineCMakeDefaults.cmake | 2 +- build/docker/debian/Dockerfile | 4 +- build/docker/ubuntu/Dockerfile | 1 + composer.json | 2 +- configure.ac | 2 +- contrib/fb303/py/setup.py | 2 +- contrib/thrift-maven-plugin/pom.xml | 10 +- contrib/thrift.spec | 4 +- contrib/zeromq/csharp/ThriftZMQ.csproj | 4 +- debian/changelog | 8 +- doap.rdf | 8 +- lib/cocoa/src/Thrift.h | 2 +- lib/cpp/src/thrift/windows/config.h | 2 +- .../Properties/AssemblyInfo.cs | 4 +- lib/csharp/src/Properties/AssemblyInfo.cs | 4 +- lib/d/src/thrift/base.d | 2 +- lib/dart/pubspec.yaml | 2 +- lib/delphi/src/Thrift.pas | 2 +- lib/erl/src/thrift.app.src | 2 +- lib/haxe/haxelib.json | 2 +- lib/hs/Thrift.cabal | 2 +- lib/java/build.properties | 8 +- lib/js/package.json | 2 +- lib/js/src/thrift.js | 146 ++--- lib/lua/THttpTransport.lua | 2 +- lib/lua/Thrift.lua | 2 +- lib/ocaml/_oasis | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/py/setup.py | 2 +- lib/rb/thrift.gemspec | 2 +- lib/st/package.xml | 6 +- package.json | 2 +- sonar-project.properties | 4 +- test/dart/test_client/pubspec.yaml | 2 +- test/erl/src/thrift_test.app.src | 2 +- .../CsharpClient/Properties/AssemblyInfo.cs | 4 +- .../CsharpServer/Properties/AssemblyInfo.cs | 4 +- tutorial/dart/client/pubspec.yaml | 2 +- tutorial/dart/console_client/pubspec.yaml | 2 +- tutorial/dart/server/pubspec.yaml | 2 +- tutorial/hs/ThriftTutorial.cabal | 2 +- tutorial/ocaml/_oasis | 2 +- 46 files changed, 750 insertions(+), 158 deletions(-) diff --git a/CHANGES b/CHANGES index 1cf8b34167c..7b674d6f658 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,592 @@ Apache Thrift Changelog +Thrift 0.10.0 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-1840] - Thrift Generated Code Causes Global Variable Leaks + * [THRIFT-1828] - moc_TQTcpServer.cpp was removed from source tree but is in thrift-0.9.0.tar.gz + * [THRIFT-1790] - cocoa: Duplicate interface definition error + * [THRIFT-1776] - TPipeServer should implement "listen", so that TServerEventHandler preServe will work right + * [THRIFT-1351] - Compiler does not care about binary strings + * [THRIFT-1229] - Python fastbinary.c can not handle unicode as generated python code + * [THRIFT-749] - C++ TBufferedTransports do not flush their buffers on delete + * [THRIFT-747] - C++ TSocket->close calls shutdown breaking forked parent process + * [THRIFT-732] - server exits abnormally when client calls send_xxx function without calling recv_xxx function + * [THRIFT-3942] - TSSLSocket does not honor send and receive timeouts + * [THRIFT-3941] - WinXP version of thrift_poll() relies on undefined behavior by passing a destructed variable to select() + * [THRIFT-3940] - Visual Studio project file for compiler is broken + * [THRIFT-3943] - Coverity Scan identified some high severity defects + * [THRIFT-3929] - PHP "nsglobal" Option Results in Syntax Error in Generated Code (Trailing Backslash) + * [THRIFT-3936] - Cannot compile 0.10.0 development tip with VS2013 and earlier (snprintf, uint32_t) + * [THRIFT-3935] - Incorrect skipping of map and set + * [THRIFT-3920] - Ruby: Ensuring that HTTP failures will clear the http transport outbuf var + * [THRIFT-3919] - C# TTLSServerSocket does not use clientTimeout + * [THRIFT-3917] - Check backports.ssl_match_hostname module version + * [THRIFT-3909] - Fix c_glib static lib CMake build + * [THRIFT-3904] - Typo in node tutorial leads to wrong transport being used + * [THRIFT-3848] - As an implementer of a perl socket server, I do not want to have to remember to ignore SIGCHLD for it to work properly + * [THRIFT-3844] - thrift_protocol cannot compile in 7.0.7 + * [THRIFT-3843] - integer issues with Haxe PHP targets cause ZigZag encoding to fail + * [THRIFT-3842] - Dart generates incorrect code for a const struct + * [THRIFT-3841] - dart compact protocol incorrectly serializes/deserialized doubles + * [THRIFT-3708] - NameError: global name 'TProtocol' is not defined + * [THRIFT-3704] - "TConnectedClient died: Could not refill buffer" message shown when using HTTP Server + * [THRIFT-3678] - Fix javadoc errors on JDK 8 + * [THRIFT-3014] - AppVeyor support + * [THRIFT-2994] - Node.js TJSONProtocol cannot be used for object serialization. + * [THRIFT-2974] - writeToParcel throws NPE for optional enum fields + * [THRIFT-2948] - Python TJSONProtocol doesn't handle structs with binary fields containing invalid unicode. + * [THRIFT-2845] - ChildService.Plo: No such file or directory + * [THRIFT-3276] - Binary data does not decode correctly using the TJSONProtocol when the base64 encoded data is padded. + * [THRIFT-3253] - Using latest version of D gives deprecation notices + * [THRIFT-2883] - TTwisted.py, during ConnectionLost processing: exceptions.RuntimeError: dictionary changed size during iteration + * [THRIFT-2019] - Writing on a disconnected socket on Mac causes SIG PIPE + * [THRIFT-2020] - Thrift library has some empty files that haven't really been deleted + * [THRIFT-2049] - Go compiler doesn't build on native Windows + * [THRIFT-2024] - TServer.cpp warns on 64-bit platforms about truncating an rlim_t into an int + * [THRIFT-2023] - gettimeofday implementation on Windows errors when no time zone is passed in. + * [THRIFT-2022] - CoB and dense code generation still uses TR1 bind, even though that doesn't work with clang + * [THRIFT-2027] - Minor 64-bit and NOMINMAX issues in C++ library + * [THRIFT-2156] - TServerSocket::listen() is throwing exceptions with misleading information + * [THRIFT-2154] - Missing #deepCopy should return T + * [THRIFT-3157] - TBase signature should be TBase, F extends TFieldIdEnum> + * [THRIFT-3156] - Node TLS: server executes processing logic two full times + * [THRIFT-3154] - tutorial/py.tornado throw EOF exception + * [THRIFT-3063] - C++ build -Wunused-parameter warnings on processor_test, TransportTest + * [THRIFT-3056] - Add string/collection length limits for Python protocol readers + * [THRIFT-3237] - Fix TNamedPipeServer::createNamedPipe memory leak + * [THRIFT-3233] - Fix C++ ThreadManager::Impl::removeWorker worker join + * [THRIFT-3232] - Cannot deserialize json messages created with fieldNamesAsString + * [THRIFT-3206] - Fix Visual Studio build failure due 'pthread_self': identifier not found + * [THRIFT-3200] - JS and nodejs do not encode JSON protocol binary fields as base64 + * [THRIFT-3199] - Exception field has basic metadata + * [THRIFT-3182] - TFramedTransport is in an invalid state after frame size exception + * [THRIFT-2536] - new TSocket, uninitialised value reported by valgrind + * [THRIFT-2527] - Apache Thrift IDL Compiler code generated for Node.js should be jshint clean + * [THRIFT-2519] - "processor" class is not being generated + * [THRIFT-2431] - TFileTransportTest fails with "check delta < XXX failed" + * [THRIFT-2708] - Erlang library does not support "oneway" message type + * [THRIFT-3377] - Deep copy is actually shallow when using typedef members + * [THRIFT-3376] - C# and Python JSON protocol double values lose precision + * [THRIFT-3373] - Various fixes for cross test servers and clients + * [THRIFT-3370] - errno extern variable redefined. Not compiling for Android + * [THRIFT-3379] - Potential out of range panic in Go JSON protocols + * [THRIFT-3371] - Abstract namespace Unix domain sockets broken in C++ + * [THRIFT-3380] - nodejs: 0.9.2 -> 0.9.3 upgrade breaks Protocol and Transport requires + * [THRIFT-3367] - Fix bad links to coding_standards.md #634 + * [THRIFT-3401] - Nested collections emit Objective-C code that cannot compile + * [THRIFT-3403] - JSON String reader doesn't recognize UTF-16 surrogate pairs + * [THRIFT-3362] - make check fails for C++ at the SecurityTest + * [THRIFT-3395] - Cocoa compiler produces corrupt code when boxing enums inside map. + * [THRIFT-3394] - compiler generates uncompilable code + * [THRIFT-3388] - hash doesn't work on set/list + * [THRIFT-3391] - Wrong bool formatting in test server + * [THRIFT-3390] - TTornado server doesn't handle closed connections properly + * [THRIFT-3382] - TBase class for C++ Library + * [THRIFT-3392] - Java TZlibTransport does not close its wrapper streams upon close() + * [THRIFT-3383] - i64 related warnings + * [THRIFT-3386] - misc. warnings with make check + * [THRIFT-3385] - warning: format ‘%lu’ expects ‘long unsigned int’, but has type ‘std::basic_string::size_type {aka unsigned int} + * [THRIFT-3355] - npm WARN package.json thrift@1.0.0-dev No license field. + * [THRIFT-3360] - Improve cross test servers and clients further + * [THRIFT-3359] - Binary field incompatibilities + * [THRIFT-3354] - Fix word-extraction substr bug in initialism code + * [THRIFT-3350] - Python JSON protocol does not encode binary as Base64 + * [THRIFT-3577] - assertion failed at line 512 of testcontainertest.c + * [THRIFT-3576] - Boost test --log_format arg does not accept lowercase + * [THRIFT-3575] - Go compiler tries to use unexported library methods when using read_write_private + * [THRIFT-3574] - Cocoa generator makes uncompilable imports + * [THRIFT-3570] - Remove duplicate instances that are added by upstream + * [THRIFT-3571] - Make feature test result browsable + * [THRIFT-3569] - c_glib protocols do not check number of bytes read by transport + * [THRIFT-3568] - THeader server crashes on readSlow + * [THRIFT-3567] - GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed + * [THRIFT-3566] - C++/Qt: TQTcpServerTest::test_communicate() is never executed + * [THRIFT-3564] - C++/Qt: potential core dump in TQTcpServer in case an exception occurs in TAsyncProcessor::process() + * [THRIFT-3558] - typos in c_glib tests + * [THRIFT-3559] - Fix awkward extra semi-colons with Cocoa container literals + * [THRIFT-3555] - 'configure' script does not honor --with-openssl= for libcrypto for BN_init + * [THRIFT-3554] - Constant decls may lead to "Error: internal error: prepare_member_name_mapping() already active for different struct" + * [THRIFT-3552] - glib_c Memory Leak + * [THRIFT-3551] - Thrift perl library missing package declaration + * [THRIFT-3549] - Exceptions are not properly stringified in Perl library + * [THRIFT-3546] - NodeJS code should not be namespaced (and is currently not strict-mode compliant) + * [THRIFT-3545] - Container type literals do not compile + * [THRIFT-3538] - Remove UnboundMethodType in TProtocolDecorator + * [THRIFT-3536] - Error 'char' does not contain a definition for 'IsLowSurrogate' for WP7 target + * [THRIFT-3534] - Link error when building with Qt5 + * [THRIFT-3533] - Can not send nil pointer as service method argument + * [THRIFT-3507] - THttpClient does not use proxy from http_proxy, https_proxy environment variables + * [THRIFT-3502] - C++ TServerSocket passes small buffer to getsockname + * [THRIFT-3501] - Forward slash in comment causes compiler error + * [THRIFT-3498] - C++ library assumes optional function pthread_attr_setschedpolicy is available + * [THRIFT-3497] - Build fails with "invalid use of incomplete type" + * [THRIFT-3496] - C++: Cob style client fails when sending a consecutive request + * [THRIFT-3493] - libthrift does not compile on windows using visual studio + * [THRIFT-3488] - warning: unused variable 'program' + * [THRIFT-3489] - warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings] + * [THRIFT-3487] - Full support for newer Delphi versions + * [THRIFT-3528] - Fix warnings in thrift.ll + * [THRIFT-3527] - -gen py:dynamic,utf8strings ignores utf8strings option + * [THRIFT-3526] - Code generated by py:utf8strings does not work for Python3 + * [THRIFT-3524] - dcc32 warning "W1000 Symbol 'IsLowSurrogate' is deprecated: 'Use TCharHelper'" in Thrift.Protocol.JSON.pas + * [THRIFT-3525] - py:dynamic fails to handle binary list/set/map element + * [THRIFT-3521] - TSimpleJSONProtocolTest is not deterministic (fails when run on JDK 8) + * [THRIFT-3520] - Dart TSocket onError stream should be typed as Object + * [THRIFT-3519] - fastbinary does not work with -gen py:utf8strings + * [THRIFT-3518] - TConcurrentClientSyncInfo files were missing for Visual Studio + * [THRIFT-3512] - c_glib: Build fails due to missing features.h + * [THRIFT-3483] - Incorrect empty binary handling introduced by THRIFT-3359 + * [THRIFT-3479] - Oneway calls should not return exceptions to clients + * [THRIFT-3478] - Restore dropped method to THsHaServer.java + * [THRIFT-3477] - Parser fails on enum item that starts with 'E' letter and continues with number + * [THRIFT-3476] - Missing include in ./src/thrift/protocol/TJSONProtocol.cpp + * [THRIFT-3474] - Docker: thrift-compiler + * [THRIFT-3473] - When "optional' is used with a struct member, C++ server seems to not return it correctly + * [THRIFT-3468] - Dart TSocketTransport onError handler is too restrictive + * [THRIFT-3451] - thrift_protocol PHP extension missing config.m4 file + * [THRIFT-3456] - rounding issue in static assert + * [THRIFT-3455] - struct write method's return value is incorrect + * [THRIFT-3454] - Python Tornado tutorial is broken + * [THRIFT-3463] - Java can't be disabled in CMake build + * [THRIFT-3450] - NPE when using SSL + * [THRIFT-3449] - TBaseAsyncProcessor fb.responseReady() never called for oneway functions + * [THRIFT-3471] - Dart generator does not handle uppercase argument names + * [THRIFT-3470] - Sporadic timeouts with pipes + * [THRIFT-3465] - Go Code With Complex Const Initializer Compilation Depends On Struct Order + * [THRIFT-3464] - Fix several defects in c_glib code generator + * [THRIFT-3462] - Cocoa generates Incorrect #import header names + * [THRIFT-3453] - remove rat_exclude + * [THRIFT-3418] - Use of ciphers in ssl.wrap_socket() breaks python 2.6 compatibility + * [THRIFT-3417] - "namespace xsd" is not really working + * [THRIFT-3413] - Thrift code generation bug in Go when extending service + * [THRIFT-3420] - C++: TSSLSockets are not interruptable + * [THRIFT-3415] - include unistd.h conditionally + * [THRIFT-3414] - #include in THeaderTransport.h breaks windows build + * [THRIFT-3411] - Go generates remotes with wrong package qualifiers when including + * [THRIFT-3430] - Go THttpClient does not read HTTP response body to completion when closing + * [THRIFT-3423] - First call to thrift_transport:read_exact fails to dispatch correct function + * [THRIFT-3422] - Go TServerSocket doesn't close on Interrupt + * [THRIFT-3421] - rebar as dependency instead of bundling (was: rebar fails if PWD contains Unicode) + * [THRIFT-3428] - Go test fails when running make check + * [THRIFT-3445] - Throwable messages are hidden from JVM stack trace output + * [THRIFT-3443] - Thrift include can generate uncompilable code + * [THRIFT-3444] - Large 64 bit Integer does not preserve value through Node.js JSONProtocol + * [THRIFT-3436] - misc. cross test issues with UTF-8 path names + * [THRIFT-3435] - Put generated Java code for fullcamel tests in a separate package/namespace + * [THRIFT-3433] - Doubles aren't interpreted correctly + * [THRIFT-3437] - Mingw-w64 build fail + * [THRIFT-3434] - Dart generator produces empty name in pubspec.yaml for includes without namespaces + * [THRIFT-3408] - JSON generator emits incorrect types + * [THRIFT-3406] - Cocoa client should not schedule streams on main runloop + * [THRIFT-3404] - JSON String reader doesn't recognize UTF-16 surrogate pair + * [THRIFT-3636] - Double precision is not fully preserved in C++ TJSONProtocol + * [THRIFT-3632] - c_glib testserialization fails with glib assertion + * [THRIFT-3619] - Using Thrift 0.9.3 with googletest on Linux gcc 4.9 / C++11 + * [THRIFT-3617] - CMake does not build gv/xml generators + * [THRIFT-3615] - Fix Python SSL client resource leak on connection failure + * [THRIFT-3616] - lib/py/test/test_sslsocket.py is flaky + * [THRIFT-3643] - Perl SSL server crushes if a client disconnect without handshake + * [THRIFT-3639] - C# Thrift library forces TLS 1.0, thwarting TLS 1.2 usage + * [THRIFT-3633] - Travis "C C++ - GCC" build was using clang + * [THRIFT-3634] - Fix Python TSocket resource leak on connection failure + * [THRIFT-3630] - Debian/Ubuntu install docs need an update + * [THRIFT-3629] - Parser sets exitcode on errors, but generator does not + * [THRIFT-3608] - lib/cpp/test/SecurityTest is flaky in jenkins Thrift-precommit build. + * [THRIFT-3601] - Better conformance to PEP8 for generated code + * [THRIFT-3599] - Validate client IP address against cert's SubjectAltName + * [THRIFT-3598] - TBufferedTransport doesn't instantiate client connection + * [THRIFT-3597] - `make check` hangs in go tests + * [THRIFT-3589] - Dart generator uses wrong name in constructor for uppercase arguments with defaults + * [THRIFT-3588] - Using TypeScript with --noImplicitAny fails + * [THRIFT-3584] - boolean false value cannot be transferred + * [THRIFT-3578] - Make THeaderTransport detect TCompact framed and unframed + * [THRIFT-3323] - Python library does not handle escaped forward slash ("/") in JSON + * [THRIFT-3322] - CMake generated "make check" failes on python_test + * [THRIFT-3321] - Thrift can't be added as a subdirectory of another CMake-based project + * [THRIFT-3314] - Dots in file names of includes causes dots in javascript variable names + * [THRIFT-3307] - Segfault in Ruby serializer + * [THRIFT-3309] - Missing TConstant.php in /lib/php/Makefile.am + * [THRIFT-3810] - unresolved external symbol public: virtual void __cdecl apache::thrift::server::TServerFramework::serve(void) + * [THRIFT-3736] - C++ library build fails if OpenSSL does not surrpot SSLv3 + * [THRIFT-3878] - Compile error in TSSLSocket.cpp with new OpenSSL [CRYPTO_num_locks] + * [THRIFT-3949] - missing make dist entry for compiler/cpp/test + * [THRIFT-449] - The wire format of the JSON Protocol may not always be valid JSON if it contains non-UTF8 encoded strings + * [THRIFT-162] - Thrift structures are unhashable, preventing them from being used as set elements + * [THRIFT-3961] - TConnectedClient does not terminate the connection to the client if an exception while processing the received message occures. + * [THRIFT-3881] - Travis CI builds are failing due to docker failures (three retries, and gives up) + * [THRIFT-3937] - Cannot compile 0.10.0 development tip with gcc-4.6.x + * [THRIFT-3964] - Unsupported mechanism type ????? due to dependency on default OS-dependent charset + * [THRIFT-3038] - Use of volatile in cpp library + * [THRIFT-3301] - Java generated code uses imports that can lead to class name collisions with IDL defined types + * [THRIFT-3348] - PHP TCompactProtocol bool&int64 readvalue bug + * [THRIFT-3955] - TThreadedServer Memory Leak + * [THRIFT-3829] - Thrift does not install Python Libraries if Twisted is not installed + * [THRIFT-3932] - C++ ThreadManager has a rare termination race + * [THRIFT-3828] - cmake fails when Boost_INCLUDE_DIRS (and other variables passed to include_directories()) is empty + * [THRIFT-3958] - CMake WITH_MT option for windows static runtime linking does not support the cmake build type RelWithDebInfo + * [THRIFT-3957] - TConnectedClient does not disconnect from clients when their timeout is reached. + * [THRIFT-3953] - TSSLSocket::close should handle exceptions from waitForEvent because it is called by the destructor. + * [THRIFT-3977] - PHP extension creates undefined values when deserializing sets + * [THRIFT-3947] - sockaddr type isn't always large enough for the return of getsockname + * [THRIFT-2755] - ThreadSanitizer reports data race in ThreadManager::Impl::addWorker + * [THRIFT-3948] - errno is not the correct method of getting the error in windows + * [THRIFT-4008] - broken ci due to upstream dependency versioning break + * [THRIFT-3999] - Fix Debian & Ubuntu package dependencies + * [THRIFT-3886] - PHP cross test client returns 0 even when failing + * [THRIFT-3997] - building thrift libs does not support new openssl + +## Documentation + * [THRIFT-3867] - Specify BinaryProtocol and CompactProtocol + +## Epic + * [THRIFT-3049] - As an iOS developer, I want a generator and library that produces Swift code + * [THRIFT-2336] - UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + +## Improvement + * [THRIFT-1867] - Python client/server should support client-side certificates. + * [THRIFT-1313] - c_glib compact support + * [THRIFT-1385] - make install doesn't install java library in the setted folder + * [THRIFT-1437] - Update RPM spec + * [THRIFT-847] - Test Framework harmonization across all languages + * [THRIFT-819] - add Enumeration for protocol, transport and server types + * [THRIFT-3927] - Emit an error instead of throw an error in the async callback + * [THRIFT-3931] - TSimpleServer: If process request encounter UNKNOWN_METHOD, don't close transport. + * [THRIFT-3934] - Automatically resolve OpenSSL binary version on Windows CI + * [THRIFT-3918] - Run subset of make cross + * [THRIFT-3908] - Remove redundant dependencies from Dockerfile + * [THRIFT-3907] - Skip Docker image build on CI when unchanged + * [THRIFT-3868] - Java struct equals should do identity check before field comparison + * [THRIFT-3849] - Port Go serializer and deserializer to dart + * [THRIFT-2989] - Complete CMake build for Apache Thrift + * [THRIFT-2980] - ThriftMemoryBuffer doesn't have a constructor option to take an existing buffer + * [THRIFT-2856] - refactor erlang basic transports and unify interfaces + * [THRIFT-2877] - Optimize generated hashCode + * [THRIFT-2869] - JSON: run schema validation from tests + * [THRIFT-3112] - [Java] AsyncMethodCallback should be typed in generated AsyncIface + * [THRIFT-3263] - PHP jsonSerialize() should cast scalar types + * [THRIFT-2905] - Cocoa compiler should have option to produce "modern" Objective-C + * [THRIFT-2821] - Enable the use of custom HTTP-Header in the Transport + * [THRIFT-2093] - added the ability to set compression level in C++ zlib transport + * [THRIFT-2089] - Compiler ignores duplicate typenames + * [THRIFT-2056] - Moved all #include config.h statements to #include + * [THRIFT-2031] - Make SO_KEEPALIVE configurable for C++ lib + * [THRIFT-2021] - Improve large binary protocol string performance + * [THRIFT-2028] - Cleanup threading headers / libraries + * [THRIFT-2014] - Change C++ lib includes to use style throughout + * [THRIFT-2312] - travis.yml: build everything + * [THRIFT-1915] - Multiplexing Services + * [THRIFT-1736] - Visual Studio top level project files within msvc + * [THRIFT-1735] - integrate tutorial into regular build + * [THRIFT-1533] - Make TTransport should be Closeable + * [THRIFT-35] - Move language tests into their appropriate library directory + * [THRIFT-1079] - Support i64 in AS3 + * [THRIFT-1108] - SSL support for the Ruby library + * [THRIFT-3856] - update debian package deependencies + * [THRIFT-3833] - haxe http server implementation (by embeding into php web server) + * [THRIFT-3839] - Performance issue with big message deserialization using php extension + * [THRIFT-3820] - Erlang: Detect OTP >= 18 to use new time correction + * [THRIFT-3816] - Reduce docker build duration on Travis-CI + * [THRIFT-3815] - Put appveyor dependency versions to one place + * [THRIFT-3788] - Compatibility improvements and Win64 support + * [THRIFT-3792] - Timeouts for anonymous pipes should be configurable + * [THRIFT-3794] - Split Delphi application, protocol and transport exception subtypes into separate exceptions + * [THRIFT-3774] - The generated code should have exception_names meta info + * [THRIFT-3762] - Fix build warnings for deprecated Thrift "byte" fields + * [THRIFT-3756] - Improve requiredness documentation + * [THRIFT-3761] - Add debian package for Python3 + * [THRIFT-3742] - haxe php cli support + * [THRIFT-3733] - Socket timeout improvements + * [THRIFT-3728] - http transport for thrift-lua + * [THRIFT-3905] - Dart compiler does not initialize bool, int, and double properties + * [THRIFT-3911] - Loosen Ruby dev dependency version requirements + * [THRIFT-3906] - Run C# tests with make check + * [THRIFT-3900] - Add Python SSL flags + * [THRIFT-3897] - Provide meaningful exception type based on WebExceptionStatus in case of timeout + * [THRIFT-3808] - Missing `DOUBLE` in thrift type enumeration + * [THRIFT-3803] - Remove "file" attribute from XML generator + * [THRIFT-3660] - Add V4 mapped address to test client cert's altname + * [THRIFT-3661] - Use https to download meck in erlang test build + * [THRIFT-3659] - Check configure result of CMake on CI + * [THRIFT-3667] - Add TLS SNI support to clients + * [THRIFT-3651] - Make backports.match_hostname and ipaddress optional + * [THRIFT-3666] - Build D tutorial as part of Autotools build + * [THRIFT-3665] - Add D libevent and OpenSSL to docker images + * [THRIFT-3664] - Remove md5.c + * [THRIFT-3662] - Add Haskell to debian docker image + * [THRIFT-3711] - Add D to cross language test + * [THRIFT-3691] - Run flake8 Python style check on Travis-CI + * [THRIFT-3692] - (Re)enable Appveyor C++ and Python build + * [THRIFT-3677] - Improve CMake Java build + * [THRIFT-3679] - Add stdout log to testBinary in Java test server + * [THRIFT-3718] - Reduce size of docker image for build environment + * [THRIFT-3698] - [Travis-CI] Introduce retry to apt commands + * [THRIFT-3127] - switch -recurse to --recurse and reserve -r + * [THRIFT-3087] - Pass on errors like "connection closed" + * [THRIFT-3240] - Thrift Python client should support subjectAltName and wildcard certs in TSSLSocket + * [THRIFT-3213] - make cross should indicate when it skips a known failing test + * [THRIFT-3208] - Fix Visual Studio solution build failure due to missing source + * [THRIFT-3186] - Add TServerHTTP to Go library + * [THRIFT-2342] - Add __FILE__ and __LINE__ to Thrift C++ excpetions + * [THRIFT-3372] - Add dart generator to Visual Studio project + * [THRIFT-3366] - ThriftTest to implement standard return values + * [THRIFT-3402] - Provide a perl Unix Socket implementation + * [THRIFT-3361] - Improve C# library + * [THRIFT-3393] - Introduce i8 to provide consistent set of Thrift IDL integer types + * [THRIFT-3339] - Support for database/sql + * [THRIFT-3565] - C++: T[Async]Processor::getEventHandler() should be declared as const member functions + * [THRIFT-3563] - C++/Qt: removed usage of macro QT_PREPEND_NAMESPACE as it isn't consequently used for all references to Qt types. + * [THRIFT-3562] - Removed unused TAsyncProcessor::getAsyncServer() + * [THRIFT-3561] - C++/Qt: make use of Q_DISABLE_COPY() to get rid of copy ctor and assignment operator + * [THRIFT-3556] - c_glib file descriptor transport + * [THRIFT-3544] - Make cross test fail when server process died unexpectedly + * [THRIFT-3540] - Make python tutorial more in line with PEP8 + * [THRIFT-3535] - Dart generator argument to produce a file structure usable in parent library + * [THRIFT-3505] - Enhance Python TSSLSocket + * [THRIFT-3506] - Eliminate old style classes from library code + * [THRIFT-3503] - Enable py:utf8string by default + * [THRIFT-3499] - Add package_prefix to python generator + * [THRIFT-3495] - Minor enhancements and fixes for cross test + * [THRIFT-3486] - Java generated `getFieldValue` is incompatible with `setFieldValue` for binary values. + * [THRIFT-3484] - Consolidate temporary buffers in Java's TCompactProtocol + * [THRIFT-3516] - Add feature test for THeader TBinaryProtocol interop + * [THRIFT-3515] - Python 2.6 compatibility and test on CI + * [THRIFT-3514] - PHP 7 compatible version of binary protocol + * [THRIFT-3469] - Docker: Debian support + * [THRIFT-3416] - Retire old "xxx_namespace" declarations from the IDL + * [THRIFT-3426] - Align autogen comment in XSD + * [THRIFT-3424] - Add CMake android build option + * [THRIFT-3439] - Run make cross using Python3 when available + * [THRIFT-3440] - Python make check takes too much time + * [THRIFT-3441] - Stabilize Travis-CI builds + * [THRIFT-3431] - Avoid "schemes" HashMap lookups during struct reads/writes + * [THRIFT-3432] - Add a TByteBuffer transport to the Java library + * [THRIFT-3438] - Enable py:new_style by default + * [THRIFT-3405] - Go THttpClient misuses http.Client objects + * [THRIFT-3614] - Improve logging of test_sslsocket.py + * [THRIFT-3647] - Fix php extension build warnings + * [THRIFT-3642] - Speed up cross test runner + * [THRIFT-3637] - Implement compact protocol for dart + * [THRIFT-3613] - Port Python C extension to Python 3 + * [THRIFT-3612] - Add Python C extension for compact protocol + * [THRIFT-3611] - Add --regex filter to cross test runner + * [THRIFT-3631] - JSON protocol implementation for Lua + * [THRIFT-3609] - Remove or replace TestPortFixture.h + * [THRIFT-3605] - Have the compiler complain about invalid arguments and options + * [THRIFT-3596] - Better conformance to PEP8 + * [THRIFT-3585] - Compact protocol implementation for Lua + * [THRIFT-3582] - Erlang libraries should have service metadata + * [THRIFT-3579] - Introduce retry to make cross + * [THRIFT-3306] - Java: TBinaryProtocol: Use 1 temp buffer instead of allocating 8 + * [THRIFT-3910] - Do not invoke pip as part of build process + * [THRIFT-1857] - Python 3.X Support + * [THRIFT-1944] - Binding to zero port + * [THRIFT-3954] - Enable the usage of structs called "Object" in Java + * [THRIFT-3981] - Enable analyzer strong mode in Dart library + * [THRIFT-3998] - Document ability to add custom tags to thrift structs + * [THRIFT-4006] - Add a removeEventListener method on TSocket + +## New Feature + * [THRIFT-640] - Support deprecation + * [THRIFT-948] - SSL socket support for PHP + * [THRIFT-764] - add Support for Vala language + * [THRIFT-3046] - Allow PSR4 class loading for generated classes (PHP) + * [THRIFT-2113] - Erlang SSL Socket Support + * [THRIFT-1482] - Unix domain socket support under PHP + * [THRIFT-519] - Support collections of types without having to explicitly define it + * [THRIFT-468] - Rack Middleware Application for Rails + * [THRIFT-1708] - Add event handlers for processor events + * [THRIFT-3834] - Erlang namespacing and exception metadata + * [THRIFT-2510] - Implement TNonblockingServer's ability to listen on unix domain sockets + * [THRIFT-3397] - Implement TProcessorFactory in C# to enable per-client processors + * [THRIFT-3523] - XML Generator + * [THRIFT-3510] - Add HttpTaskAsyncHandler implementation + * [THRIFT-3318] - PHP: SimpleJSONProtocol Implementation + * [THRIFT-3299] - Dart language bindings in Thrift + * [THRIFT-2835] - Add possibility to distribute generators separately from thrift core, and load them dynamically + * [THRIFT-184] - Add OSGi Manifest headers to the libthrift java library to be able to use Thrift in the OSGi runtime + * [THRIFT-141] - If a required field is not present on serialization, throw an exception + * [THRIFT-1891] - Add Windows ALPC transport which is right counterpart of Unix domain sockets + +## Question + * [THRIFT-1808] - The Thrift struct should be considered self-contained? + * [THRIFT-2895] - Tutorial cpp + * [THRIFT-3860] - Elephant-bird application Test fails for Thrift + * [THRIFT-3811] - HTTPS Support for C++ applications + * [THRIFT-3509] - "make check" error + +## Story + * [THRIFT-3452] - .travis.yml: Migrating from legacy to container-based infrastructure + +## Sub-task + * [THRIFT-1811] - ruby tutorial as part of the regular build + * [THRIFT-2779] - PHP TJSONProtocol encode unicode into UCS-4LE which can't be parsed by other language bindings + * [THRIFT-2110] - Erlang: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-3852] - A Travis-CI job fails with "write error" + * [THRIFT-3740] - Fix haxelib.json classpath + * [THRIFT-3653] - incorrect union serialization + * [THRIFT-3652] - incorrect serialization of optionals + * [THRIFT-3655] - incorrect union serialization + * [THRIFT-3654] - incorrect serialization of optionals + * [THRIFT-3656] - incorrect serialization of optionals + * [THRIFT-3699] - Fix integer limit symbol includes in Python C extension + * [THRIFT-3693] - Fix include issue in C++ TSSLSocketInterruptTest on Windows + * [THRIFT-3694] - [Windows] Disable tests of a few servers that are not supported + * [THRIFT-3696] - Install pip to CentOS Docker images to fix Python builds + * [THRIFT-3638] - Fix haxelib.json + * [THRIFT-3251] - Add http transport for server to Go lib + * [THRIFT-2424] - Recursive Types + * [THRIFT-2423] - THeader + * [THRIFT-2413] - Python: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2409] - Java: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2412] - D: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2411] - C++: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2410] - JavaMe: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2668] - TestSuite: detailed result on passed tests by feature + * [THRIFT-2659] - python Test Server fails when throwing TException + * [THRIFT-3398] - Add CMake build for Haskell library and tests + * [THRIFT-3396] - DART: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-3364] - Fix ruby binary field encoding in TJSONProtocol + * [THRIFT-3381] - Fix for misc. codegen issues with THRIFT-2905 + * [THRIFT-3573] - No rule to make target `../../../test/c_glib/src/.deps/testthrifttest-thrift_test_handler.Po'. + * [THRIFT-3572] - "Unable to determine the behavior of a signed right shift" + * [THRIFT-3542] - Add length limit support to Java test server + * [THRIFT-3537] - Remove the (now obsolete) csharp:asyncctp flag + * [THRIFT-3532] - Add configurable string and container read size limit to Python protocols + * [THRIFT-3531] - Create cross lang feature test for string and container read length limit + * [THRIFT-3482] - Haskell JSON protocol does not encode binary field as Base64 + * [THRIFT-3425] - Minor fixes + simplification for CentOS Dockerfile + * [THRIFT-3442] - Run CMake tests on Appveyor + * [THRIFT-3409] - NodeJS binary field issues + * [THRIFT-3621] - Fix lib/cpp/test/SecurityTest.cpp to use ephemeral ports + * [THRIFT-3628] - Fix lib/cpp/test/TServerIntegrationTest.cpp to use ephemeral ports + * [THRIFT-3625] - Kill unused #include "TestPortFixture.h" in lib/cpp/test/TServerTransportTest.cpp. + * [THRIFT-3646] - Fix Python extension build warnings + * [THRIFT-3626] - Fix lib/cpp/test/TSocketInterruptTest.cpp to use ephemeral ports. + * [THRIFT-3624] - Fix lib/cpp/test/TServerSocketTest.cpp to use ephemeral ports + * [THRIFT-3623] - Fix Fix cpp/lib/test/TSSLSocketInterruptTest.cpp to use ephemeral ports + * [THRIFT-3592] - Add basic test client + * [THRIFT-3980] - add TExtendedBinaryProtocol.java + +## Task + * [THRIFT-1801] - Sync up TApplicationException codes across languages and thrift implementations + * [THRIFT-1259] - Automate versioning + +## Test + * [THRIFT-3400] - Add Erlang to cross test + * [THRIFT-3504] - Fix FastbinaryTest.py + +## Wish + * [THRIFT-3923] - Maybe remove Aereo from the "Powered by" list + * [THRIFT-2149] - Add an option to disable the generation of default operators + + + Thrift 0.9.3 -------------------------------------------------------------------------------- ## Bug diff --git a/README.md b/README.md index a55389a02b5..07cd32f0982 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,9 @@ Apache Thrift ============= -Last Modified: 2014-03-16 ++[![Build Status](https://travis-ci.org/apache/thrift.svg?branch=master)](https://travis-ci.org/apache/thrift) +- +[![AppVeyor Build status](https://ci.appveyor.com/api/projects/status/e2qks7enyp9gw7ma?svg=true)](https://ci.appveyor.com/project/apache/thrift) -License -======= - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. Introduction ============ @@ -162,3 +144,23 @@ To run the cross-language test suite, please run: This will run a set of tests that use different language clients and servers. + +License +======= + +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. diff --git a/Thrift.podspec b/Thrift.podspec index 39d378053ac..2ead0e93df3 100644 --- a/Thrift.podspec +++ b/Thrift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Thrift" - s.version = "1.0.0" + s.version = "0.10.0" s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC." s.description = <<-DESC The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages. @@ -13,6 +13,6 @@ The Apache Thrift software framework, for scalable cross-language services devel s.osx.deployment_target = '10.8' s.ios.framework = 'CFNetwork' s.osx.framework = 'CoreServices' - s.source = { :git => "https://github.com/apache/thrift.git", :tag => "thrift-1.0.0" } + s.source = { :git => "https://github.com/apache/thrift.git", :tag => "thrift-0.10.0" } s.source_files = 'lib/cocoa/src/**/*.{h,m,swift}' end \ No newline at end of file diff --git a/bower.json b/bower.json index e0612e32533..9ec59fcb5dc 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.9.3", + "version": "0.10.0", "homepage": "https://git-wip-us.apache.org/repos/asf/thrift.git", "authors": [ "Apache Thrift " diff --git a/build/cmake/DefineCMakeDefaults.cmake b/build/cmake/DefineCMakeDefaults.cmake index 7073e8ef83d..8125de9d847 100644 --- a/build/cmake/DefineCMakeDefaults.cmake +++ b/build/cmake/DefineCMakeDefaults.cmake @@ -35,7 +35,7 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) set(CMAKE_COLOR_MAKEFILE ON) # Define the generic version of the libraries here -set(GENERIC_LIB_VERSION "0.1.0") +set(GENERIC_LIB_VERSION "0.10.0") set(GENERIC_LIB_SOVERSION "0") # Set the default build type to release with debug info diff --git a/build/docker/debian/Dockerfile b/build/docker/debian/Dockerfile index 99eda7ab902..29b7804db35 100644 --- a/build/docker/debian/Dockerfile +++ b/build/docker/debian/Dockerfile @@ -72,9 +72,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3-setuptools \ python3-pip -RUN apt-get update && apt-get install -y --no-install-recommends \ +RUN echo 'deb http://deb.debian.org/debian jessie-backports main' >> /etc/apt/sources.list \ + && apt-get update && apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ ruby \ + ruby-bundler \ ruby-dev \ `# Perl dependencies` \ libbit-vector-perl \ diff --git a/build/docker/ubuntu/Dockerfile b/build/docker/ubuntu/Dockerfile index 7792aae2095..7d245e806e3 100644 --- a/build/docker/ubuntu/Dockerfile +++ b/build/docker/ubuntu/Dockerfile @@ -94,6 +94,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ ruby \ + ruby-bundler \ ruby-dev \ `# Perl dependencies` \ libbit-vector-perl \ diff --git a/composer.json b/composer.json index 0f22b76eabb..d937bc7ac21 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "0.10.0" } } } diff --git a/configure.ac b/configure.ac index d3ea7917209..0972abfc9d9 100755 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ(2.65) AC_CONFIG_MACRO_DIR([./aclocal]) -AC_INIT([thrift], [1.0.0-dev]) +AC_INIT([thrift], [0.10.0]) AC_CONFIG_AUX_DIR([.]) diff --git a/contrib/fb303/py/setup.py b/contrib/fb303/py/setup.py index 4321ce258d5..f5b9bb379c2 100644 --- a/contrib/fb303/py/setup.py +++ b/contrib/fb303/py/setup.py @@ -26,7 +26,7 @@ from distutils.core import setup, Extension, Command setup(name='thrift_fb303', - version='1.0.0-dev', + version='0.10.0', description='Python bindings for the Apache Thrift FB303', author=['Thrift Developers'], author_email=['dev@thrift.apache.org'], diff --git a/contrib/thrift-maven-plugin/pom.xml b/contrib/thrift-maven-plugin/pom.xml index 5bc10041436..7973e69cd06 100644 --- a/contrib/thrift-maven-plugin/pom.xml +++ b/contrib/thrift-maven-plugin/pom.xml @@ -7,9 +7,9 @@ to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - + http://www.apache.org/licenses/LICENSE-2.0 - + Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -17,8 +17,8 @@ specific language governing permissions and limitations under the License. --> - @@ -27,7 +27,7 @@ thrift-maven-plugin maven-plugin thrift-maven-plugin - 1.0-SNAPSHOT + 0.10.0 diff --git a/contrib/thrift.spec b/contrib/thrift.spec index 93f000c9140..ccd35a50d10 100644 --- a/contrib/thrift.spec +++ b/contrib/thrift.spec @@ -28,7 +28,7 @@ Name: thrift License: Apache License v2.0 Group: Development Summary: RPC and serialization framework -Version: 0.9.1 +Version: 0.10.0 Release: 0 URL: http://thrift.apache.org Packager: Thrift Developers @@ -234,5 +234,5 @@ umask 007 /sbin/ldconfig > /dev/null 2>&1 %changelog -* Wed Oct 10 2012 Thrift Dev +* Wed Oct 10 2012 Thrift Dev - Thrift 0.9.0 release. diff --git a/contrib/zeromq/csharp/ThriftZMQ.csproj b/contrib/zeromq/csharp/ThriftZMQ.csproj index 6b465306554..ef2dbc3b971 100755 --- a/contrib/zeromq/csharp/ThriftZMQ.csproj +++ b/contrib/zeromq/csharp/ThriftZMQ.csproj @@ -3,7 +3,7 @@ Debug x86 - 9.0.21022 + 0.10.0 2.0 {17C63B90-DFD7-42AC-A7B0-749E6876C0A1} Exe @@ -25,7 +25,7 @@ false true 0 - 1.0.0.%2a + 0.10.0.%2a false false true diff --git a/debian/changelog b/debian/changelog index f2da2327e3c..640480e0479 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,8 @@ -thrift (1.0.0-dev) stable; urgency=low - * update version - * fix libthrift0.install +thrift (0.10.0) stable; urgency=low - -- Roger Meier Tue, 08 Jan 2013 22:40:12 +0100 + * update to 0.10.0 + + -- Jake Farrell Mon, 12 Dec 2016 12:00:00 -0500 thrift (0.9.0) stable; urgency=low diff --git a/doap.rdf b/doap.rdf index ac8d7854d74..14a8d6638d5 100755 --- a/doap.rdf +++ b/doap.rdf @@ -1,8 +1,8 @@ - + libthrift-st thrift.st diff --git a/package.json b/package.json index d5276415948..edfc3553ed5 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://git-wip-us.apache.org/repos/asf/thrift.git" }, - "version": "1.0.0-dev", + "version": "0.10.0", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", diff --git a/sonar-project.properties b/sonar-project.properties index b465fd12e81..6e6c5db90d1 100755 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -16,7 +16,7 @@ development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between all major languages. # Apache Thrift Version -sonar.projectVersion=1.0.0-dev +sonar.projectVersion=0.10.0 # use this to set another version string # $ sonar-runner -D sonar.projectVersion=`git rev-parse HEAD` # set projectDate in combination with projectVersion for imports of old releases @@ -54,7 +54,7 @@ module1.sonar.projectName=Apache Thrift - Java Library module1.sonar.projectBaseDir=lib/java module1.sonar.sources=src module1.sonar.tests=test -module1.sonar.binaries=build/libthrift-1.0.0.jar +module1.sonar.binaries=build/libthrift-0.10.0.jar module1.sonar.libraries=build/lib/*.jar module1.sonar.language=java diff --git a/test/dart/test_client/pubspec.yaml b/test/dart/test_client/pubspec.yaml index a91aa455a04..0b6bda21f75 100644 --- a/test/dart/test_client/pubspec.yaml +++ b/test/dart/test_client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: thrift_test_client -version: 1.0.0-dev +version: 0.10.0 description: A client integration test for the Dart Thrift library author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/test/erl/src/thrift_test.app.src b/test/erl/src/thrift_test.app.src index 7896a9525ab..66536396f2d 100644 --- a/test/erl/src/thrift_test.app.src +++ b/test/erl/src/thrift_test.app.src @@ -22,7 +22,7 @@ {description, "Thrift cross language test"}, % The version of the applicaton - {vsn, "1.0.0-dev"}, + {vsn, "0.10.0"}, % All modules used by the application. {modules, [ diff --git a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs index 72ae61697f1..bf4bc5d7cda 100644 --- a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs +++ b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.10.0.0")] +[assembly: AssemblyFileVersion("0.10.0.0")] diff --git a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs index 28a69d238a9..c416acc24c1 100644 --- a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs +++ b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.10.0.0")] +[assembly: AssemblyFileVersion("0.10.0.0")] diff --git a/tutorial/dart/client/pubspec.yaml b/tutorial/dart/client/pubspec.yaml index db64afcfc71..5f60f67c111 100644 --- a/tutorial/dart/client/pubspec.yaml +++ b/tutorial/dart/client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_client -version: 1.0.0-dev +version: 0.10.0 description: A Dart client implementation of the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/tutorial/dart/console_client/pubspec.yaml b/tutorial/dart/console_client/pubspec.yaml index cea13acd55b..32fd4ff26e8 100644 --- a/tutorial/dart/console_client/pubspec.yaml +++ b/tutorial/dart/console_client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_console_client -version: 1.0.0-dev +version: 0.10.0 description: > A Dart console client to implementation of the Apache Thrift tutorial author: Apache Thrift Developers diff --git a/tutorial/dart/server/pubspec.yaml b/tutorial/dart/server/pubspec.yaml index 4833a4af8f5..2a2644863d9 100644 --- a/tutorial/dart/server/pubspec.yaml +++ b/tutorial/dart/server/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_server -version: 1.0.0-dev +version: 0.10.0 description: A Dart server to support the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/tutorial/hs/ThriftTutorial.cabal b/tutorial/hs/ThriftTutorial.cabal index e6f01828398..d342ad53f48 100755 --- a/tutorial/hs/ThriftTutorial.cabal +++ b/tutorial/hs/ThriftTutorial.cabal @@ -18,7 +18,7 @@ -- Name: ThriftTutorial -Version: 0.1.0 +Version: 0.10.0 Cabal-Version: >= 1.4 License: OtherLicense Category: Foreign diff --git a/tutorial/ocaml/_oasis b/tutorial/ocaml/_oasis index 4cab0806394..23abdc621e0 100644 --- a/tutorial/ocaml/_oasis +++ b/tutorial/ocaml/_oasis @@ -1,5 +1,5 @@ Name: tutorial -Version: 1.0 +Version: 0.10.0 OASISFormat: 0.3 Synopsis: OCaml Tutorial example Authors: Apache Thrift Developers From 1c7bf3ebc43b8f2f2a800f6ed43643d001e12040 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 30 Nov 2017 22:30:03 +0100 Subject: [PATCH 065/756] THRIFT-4398 Update EXTRA_DIST for "make dist" Client: Build process Patch: Jens Geyer This closes #1431 --- Makefile.am | 4 ++++ lib/csharp/Makefile.am | 23 ++++++++++++----------- lib/dart/Makefile.am | 4 ++++ lib/erl/Makefile.am | 1 + lib/netcore/Makefile.am | 2 ++ lib/perl/Makefile.am | 3 +++ lib/py/Makefile.am | 1 + lib/rs/test/Makefile.am | 4 ++++ test/csharp/Makefile.am | 8 ++++++++ test/haxe/Makefile.am | 28 +++++++++++++++------------- test/netcore/Makefile.am | 1 + tutorial/dart/Makefile.am | 3 +++ tutorial/go/Makefile.am | 3 +++ tutorial/haxe/Makefile.am | 28 +++++++++++++++------------- tutorial/netcore/Makefile.am | 2 ++ 15 files changed, 78 insertions(+), 37 deletions(-) diff --git a/Makefile.am b/Makefile.am index 4b3157c9082..3d71fd4b73a 100755 --- a/Makefile.am +++ b/Makefile.am @@ -111,9 +111,13 @@ EXTRA_DIST = \ .clang-format \ .editorconfig \ .travis.yml \ + .rustfmt.toml \ + .dockerignore \ appveyor.yml \ bower.json \ build \ + bootstrap.sh \ + cleanup.sh \ CMakeLists.txt \ composer.json \ contrib \ diff --git a/lib/csharp/Makefile.am b/lib/csharp/Makefile.am index f113e1a4159..be49d5ecd82 100644 --- a/lib/csharp/Makefile.am +++ b/lib/csharp/Makefile.am @@ -97,14 +97,15 @@ clean-local: $(RM) Thrift.45.dll EXTRA_DIST = \ - $(THRIFTCODE) \ - ThriftMSBuildTask \ - src/Thrift.csproj \ - src/Thrift.45.csproj \ - src/Thrift.sln \ - src/Transport/TSilverlightSocket.cs \ - src/Transport/THttpTaskAsyncHandler.cs \ - src/TAsyncProcessor.cs \ - test \ - coding_standards.md \ - README.md + $(THRIFTCODE) \ + ThriftMSBuildTask \ + src/Thrift.csproj \ + src/Thrift.45.csproj \ + src/Thrift.sln \ + src/Net35/ExtensionsNet35.cs \ + src/Transport/TSilverlightSocket.cs \ + src/Transport/THttpTaskAsyncHandler.cs \ + src/TAsyncProcessor.cs \ + test \ + coding_standards.md \ + README.md diff --git a/lib/dart/Makefile.am b/lib/dart/Makefile.am index 910db50fcd4..ab6ddc02256 100644 --- a/lib/dart/Makefile.am +++ b/lib/dart/Makefile.am @@ -27,3 +27,7 @@ clean-local: find . -type f -name "pubspec.lock" | xargs $(RM) check-local: all + +EXTRA_DIST = \ + .analysis_options + diff --git a/lib/erl/Makefile.am b/lib/erl/Makefile.am index 20aadebb39d..8867f884e65 100644 --- a/lib/erl/Makefile.am +++ b/lib/erl/Makefile.am @@ -82,6 +82,7 @@ EXTRA_DIST = \ src \ coding_standards.md \ rebar.config \ + rebar.config.script \ rebar.test.config \ test \ README.md diff --git a/lib/netcore/Makefile.am b/lib/netcore/Makefile.am index 526299391b0..facee11dd52 100644 --- a/lib/netcore/Makefile.am +++ b/lib/netcore/Makefile.am @@ -25,6 +25,7 @@ TESTDIR = Tests/Thrift.PublicInterfaces.Compile.Tests GENDIR = $(TESTDIR)/gen-netcore THRIFTCODE = \ + Thrift/Thrift.csproj \ Thrift/ITAsyncProcessor.cs \ Thrift/ITProcessorFactory.cs \ Thrift/SingletonTProcessorFactory.cs \ @@ -72,6 +73,7 @@ THRIFTCODE = \ Thrift/Transports/Client/TTlsSocketClientTransport.cs \ Thrift/Transports/Server/THttpServerTransport.cs \ Thrift/Transports/Server/TNamedPipeServerTransport.cs \ + Thrift/Transports/Server/TServerFramedTransport.cs \ Thrift/Transports/Server/TServerSocketTransport.cs \ Thrift/Transports/Server/TTlsServerSocketTransport.cs diff --git a/lib/perl/Makefile.am b/lib/perl/Makefile.am index 0d2c8d3ea9e..fa0f16b8af0 100644 --- a/lib/perl/Makefile.am +++ b/lib/perl/Makefile.am @@ -38,12 +38,14 @@ clean-local: EXTRA_DIST = \ coding_standards.md \ + build-cpan-dist.sh \ Makefile.PL \ test.pl \ lib/Thrift.pm \ lib/Thrift.pm \ lib/Thrift/BinaryProtocol.pm \ lib/Thrift/BufferedTransport.pm \ + lib/Thrift/Exception.pm \ lib/Thrift/FramedTransport.pm \ lib/Thrift/HttpClient.pm \ lib/Thrift/MemoryBuffer.pm \ @@ -59,6 +61,7 @@ EXTRA_DIST = \ lib/Thrift/SSLServerSocket.pm \ lib/Thrift/UnixServerSocket.pm \ lib/Thrift/UnixSocket.pm \ + lib/Thrift/Type.pm \ lib/Thrift/Transport.pm \ README.md diff --git a/lib/py/Makefile.am b/lib/py/Makefile.am index fd9ce257e7d..5861858f46e 100644 --- a/lib/py/Makefile.am +++ b/lib/py/Makefile.am @@ -49,6 +49,7 @@ check-local: all py3-test EXTRA_DIST = \ CMakeLists.txt \ + MANIFEST.in \ coding_standards.md \ compat \ setup.py \ diff --git a/lib/rs/test/Makefile.am b/lib/rs/test/Makefile.am index 87208d7ba61..8edd756bfa3 100644 --- a/lib/rs/test/Makefile.am +++ b/lib/rs/test/Makefile.am @@ -44,6 +44,10 @@ clean-local: EXTRA_DIST = \ Cargo.toml \ + thrifts/Base_One.thrift \ + thrifts/Base_Two.thrift \ + thrifts/Midlayer.thrift \ + thrifts/Ultimate.thrift \ src/lib.rs \ src/bin/kitchen_sink_server.rs \ src/bin/kitchen_sink_client.rs diff --git a/test/csharp/Makefile.am b/test/csharp/Makefile.am index 7aa332ccfa9..ad166e38408 100644 --- a/test/csharp/Makefile.am +++ b/test/csharp/Makefile.am @@ -85,3 +85,11 @@ check-local: TestClientServer.exe MONO_PATH=$(LIBDIR) timeout 10 mono TestClientServer.exe server --port=$(TESTPORT) & sleep 1 MONO_PATH=$(LIBDIR) mono TestClientServer.exe client --port=$(TESTPORT) + +EXTRA_DIST = \ + Properties/AssemblyInfo.cs \ + ThriftTest.csproj \ + ThriftTest.sln \ + Program.cs \ + TestServer.cs \ + TestClient.cs diff --git a/test/haxe/Makefile.am b/test/haxe/Makefile.am index 4edaa30e51d..6c0483e9ebf 100644 --- a/test/haxe/Makefile.am +++ b/test/haxe/Makefile.am @@ -87,16 +87,18 @@ check_php_web: $(BIN_PHP_WEB) $(BIN_CPP) EXTRA_DIST = \ - src \ - cpp.hxml \ - csharp.hxml \ - flash.hxml \ - java.hxml \ - javascript.hxml \ - neko.hxml \ - php.hxml \ - python.hxml \ - project.hide \ - TestClientServer.hxproj \ - make_all.bat \ - make_all.sh + src \ + cpp.hxml \ + csharp.hxml \ + flash.hxml \ + java.hxml \ + javascript.hxml \ + neko.hxml \ + php.hxml \ + python.hxml \ + router.php \ + project.hide \ + php-web-server.hxml \ + TestClientServer.hxproj \ + make_all.bat \ + make_all.sh diff --git a/test/netcore/Makefile.am b/test/netcore/Makefile.am index e84a57aec7e..e029a24cb18 100644 --- a/test/netcore/Makefile.am +++ b/test/netcore/Makefile.am @@ -52,6 +52,7 @@ EXTRA_DIST = \ $(THRIFTCODE) \ ThriftTest.sln \ ThriftTest/ThriftTest.csproj \ + ThriftTest/Properties/launchSettings.json \ build.cmd \ build.sh \ README.md diff --git a/tutorial/dart/Makefile.am b/tutorial/dart/Makefile.am index 2e8cd342d80..0495aca6043 100644 --- a/tutorial/dart/Makefile.am +++ b/tutorial/dart/Makefile.am @@ -67,4 +67,7 @@ EXTRA_DIST = \ console_client/pubspec.yaml \ server/bin/main.dart \ server/pubspec.yaml \ + console_client/.analysis_options \ + client/.analysis_options \ + server/.analysis_options \ build.sh diff --git a/tutorial/go/Makefile.am b/tutorial/go/Makefile.am index 30662f53605..a146d5c9fa9 100644 --- a/tutorial/go/Makefile.am +++ b/tutorial/go/Makefile.am @@ -61,6 +61,9 @@ EXTRA_DIST = \ src/handler.go \ src/server.go \ src/main.go \ + src/go17.go \ + src/handler_go17.go \ + src/pre_go17.go \ server.crt \ server.key diff --git a/tutorial/haxe/Makefile.am b/tutorial/haxe/Makefile.am index 13ac48dac1d..e6f27134680 100644 --- a/tutorial/haxe/Makefile.am +++ b/tutorial/haxe/Makefile.am @@ -80,16 +80,18 @@ clean-local: $(RM) -r gen-haxe bin EXTRA_DIST = \ - src \ - cpp.hxml \ - csharp.hxml \ - flash.hxml \ - java.hxml \ - javascript.hxml \ - neko.hxml \ - php.hxml \ - python.hxml \ - project.hide \ - Tutorial.hxproj \ - make_all.bat \ - make_all.sh + src \ + cpp.hxml \ + csharp.hxml \ + flash.hxml \ + java.hxml \ + javascript.hxml \ + php-web-server.hxml \ + neko.hxml \ + php.hxml \ + python.hxml \ + router.php \ + project.hide \ + Tutorial.hxproj \ + make_all.bat \ + make_all.sh diff --git a/tutorial/netcore/Makefile.am b/tutorial/netcore/Makefile.am index 2e62ee05816..ef3d618fe73 100644 --- a/tutorial/netcore/Makefile.am +++ b/tutorial/netcore/Makefile.am @@ -65,8 +65,10 @@ EXTRA_DIST = \ Interfaces/Interfaces.csproj \ Client/Client.csproj \ Client/ThriftTest.pfx \ + Client/Properties/launchSettings.json \ Server/Server.csproj \ Server/ThriftTest.pfx \ + Server/Properties/launchSettings.json \ build.cmd \ build.sh \ README.md From 1310dc1eb4014457a667a7287d1fa113432c7a54 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 29 Nov 2017 22:35:29 +0100 Subject: [PATCH 066/756] Version 0.11.0 --- CHANGES | 303 ++++++++++++++++++ LANGUAGES.md | 2 +- Thrift.podspec | 4 +- appveyor.yml | 2 +- build/cmake/DefineCMakeDefaults.cmake | 2 +- composer.json | 2 +- configure.ac | 2 +- contrib/Rebus/Properties/AssemblyInfo.cs | 4 +- contrib/fb303/py/setup.py | 2 +- contrib/thrift-maven-plugin/pom.xml | 2 +- contrib/vagrant/centos-6.5/README.md | 2 +- contrib/zeromq/csharp/ThriftZMQ.csproj | 20 +- debian/changelog | 3 +- doap.rdf | 5 + lib/cocoa/src/Thrift.h | 2 +- lib/cpp/src/thrift/windows/config.h | 1 + .../ThriftMSBuildTask.csproj | 2 +- lib/csharp/src/Properties/AssemblyInfo.cs | 4 +- lib/csharp/src/Thrift.csproj | 2 +- .../test/JSON/Properties/AssemblyInfo.cs | 4 +- .../Multiplex/Client/MultiplexClient.csproj | 2 +- .../Client/Properties/AssemblyInfo.cs | 4 +- .../Multiplex/Server/MultiplexServer.csproj | 2 +- .../Server/Properties/AssemblyInfo.cs | 4 +- .../ThriftMVCTest/Properties/AssemblyInfo.cs | 4 +- lib/d/src/thrift/base.d | 2 +- lib/dart/pubspec.yaml | 4 +- lib/delphi/src/Thrift.pas | 2 +- lib/erl/src/thrift.app.src | 2 +- lib/go/thrift/serializer_types_test.go | 2 +- lib/haxe/README.md | 6 +- lib/haxe/haxelib.json | 2 +- lib/hs/thrift.cabal | 2 +- lib/java/build.properties | 2 +- lib/js/package.json | 2 +- lib/js/src/thrift.js | 2 +- lib/lua/THttpTransport.lua | 2 +- lib/netcore/Thrift/Properties/AssemblyInfo.cs | 4 +- .../Transports/Client/THttpClientTransport.cs | 2 +- lib/ocaml/_oasis | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/py/setup.py | 2 +- lib/rb/thrift.gemspec | 2 +- lib/rs/Cargo.toml | 2 +- lib/st/package.xml | 2 +- package.json | 2 +- sonar-project.properties | 6 +- test/csharp/Properties/AssemblyInfo.cs | 4 +- test/csharp/ThriftTest.csproj | 2 +- test/dart/test_client/pubspec.yaml | 2 +- test/erl/src/thrift_test.app.src | 2 +- .../CsharpClient/Properties/AssemblyInfo.cs | 4 +- .../CsharpServer/Properties/AssemblyInfo.cs | 4 +- tutorial/dart/client/pubspec.yaml | 4 +- tutorial/dart/console_client/pubspec.yaml | 2 +- tutorial/dart/server/pubspec.yaml | 2 +- .../delphi/DelphiClient/DelphiClient.dproj | 4 +- .../delphi/DelphiServer/DelphiServer.dproj | 4 +- tutorial/hs/ThriftTutorial.cabal | 2 +- tutorial/ocaml/_oasis | 2 +- 60 files changed, 404 insertions(+), 76 deletions(-) diff --git a/CHANGES b/CHANGES index 7b674d6f658..e0a3e0b8cc7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,308 @@ Apache Thrift Changelog +Thrift 0.11.0 +-------------------------------------------------------------------------------- +## Sub-task + * [THRIFT-2733] - Erlang coding standards + * [THRIFT-2740] - Perl coding standards + * [THRIFT-3610] - Streamline exception handling in Python server handler + * [THRIFT-3686] - Java processor should report internal error on uncaught exception + * [THRIFT-4047] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4048] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4049] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4050] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4051] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4052] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4053] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4054] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4055] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4056] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4057] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4058] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4136] - Align is_binary() method with is_string() to simplify those checks + * [THRIFT-4137] - Fix remaining undefined behavior invalid vptr casts in Thrift Compiler + * [THRIFT-4138] - Fix remaining undefined behavior invalid vptr casts in C++ library + * [THRIFT-4296] - Fix Ubuntu Xenial build environment for the python language + * [THRIFT-4298] - Fix Ubuntu Xenial build environment for the go 1.6 language + * [THRIFT-4299] - Fix Ubuntu Xenial build environment for the D language + * [THRIFT-4300] - Fix make cross in Ubuntu Xenial docker environment, once all language support issues are fixed + * [THRIFT-4302] - Fix Ubuntu Xenial make cross testing for lua and php7 + * [THRIFT-4398] - Update EXTRA_DIST for "make dist" + +## Bug + * [THRIFT-381] - Fail fast if configure detects C++ problems + * [THRIFT-1677] - MinGW support broken + * [THRIFT-1805] - Thrift should not swallow ALL exceptions + * [THRIFT-2026] - Fix TCompactProtocol 64 bit builds + * [THRIFT-2642] - Recursive structs don't work in python + * [THRIFT-2889] - stable release 0.9.2, erlang tutorial broken + * [THRIFT-2913] - Ruby Server Thrift::ThreadPoolServer should serve inside a thread + * [THRIFT-2998] - Node.js: Missing header from http request + * [THRIFT-3000] - .NET implementation has trouble with mixed IP modes + * [THRIFT-3281] - Travis CI build passed but the log says BUILD FAILED + * [THRIFT-3358] - Makefile:1362: *** missing separator. Stop. + * [THRIFT-3600] - Make TTwisted server send exception on unexpected handler error + * [THRIFT-3602] - Make Tornado server send exception on unexpected handler error + * [THRIFT-3657] - D TFileWriterTransport close should use non-priority send + * [THRIFT-3700] - Go Map has wrong default value when optional + * [THRIFT-3703] - Unions Field Count Does Not Consider Map/Set/List Fields + * [THRIFT-3730] - server log error twice + * [THRIFT-3778] - go client can not pass method parameter to server of other language if no field_id is given + * [THRIFT-3784] - thrift-maven-plugin generates invalid include directories for IDL in dependency JARs + * [THRIFT-3801] - Node Thrift client throws exception with multiplexer and responses that are bigger than a single buffer + * [THRIFT-3821] - TMemoryBuffer buffer may overflow when resizing + * [THRIFT-3832] - Thrift version 0.9.3 example on Windows, Visual Studio, linking errors during compiling + * [THRIFT-3847] - thrift/config.h includes a #define for VERSION which will likely conflict with existing user environment or code + * [THRIFT-3873] - Fix various build warnings when using Visual Studio + * [THRIFT-3891] - TNonblockingServer configured with more than one IO threads does not always return from serve() upon stop() + * [THRIFT-3892] - Thrift uses TLS SNI extension provided by OpenSSL library. Older version of OpenSSL(< 0.9.8f) may create problem because they do not support 'SSL_set_tlsext_host_name()'. + * [THRIFT-3895] - Build fails using Java 1.8 with Ant < 1.9 + * [THRIFT-3896] - map data with number string key cannot access that deserialized by php extension + * [THRIFT-3938] - Python TNonblockingServer does not work with SSL + * [THRIFT-3944] - TSSLSocket has dead code in checkHandshake + * [THRIFT-3946] - Java 1.5 compatibility broken for binary fields (java5 option) + * [THRIFT-3960] - Inherited services in Lua generator are not named correctly + * [THRIFT-3962] - Ant build.xml broken on Windows for Java library + * [THRIFT-3963] - Thrift.cabal filename does not match module name + * [THRIFT-3967] - gobject/gparam.h:166:33: warning: enumerator value for ‘G_PARAM_DEPRECATED’ is not an integer constant expression + * [THRIFT-3968] - Deserializing empty string/binary fields + * [THRIFT-3974] - Using clang-3.8 and ThreadSanitizer on the concurrency_test claims bad PThread behavior + * [THRIFT-3984] - PHP7 extension causes segfault + * [THRIFT-4008] - broken ci due to upstream dependency versioning break + * [THRIFT-4009] - Use @implementer instead of implements in TTwisted.py + * [THRIFT-4010] - Q.fcall messing up with *this* pointer inside called function + * [THRIFT-4011] - Sets of Thrift structs generate Go code that can't be serialized to JSON + * [THRIFT-4012] - Python Twisted implementation uses implements, not compatible with Py3 + * [THRIFT-4014] - align C# meta data in AssemblyInfo.cs + * [THRIFT-4015] - Fix wrongly spelled "Thirft"s + * [THRIFT-4016] - testInsanity() impl does not conform to test spec in ThriftTest.thrift + * [THRIFT-4023] - Skip unexpected field types on read/write + * [THRIFT-4024] - Skip() should throw on unknown data types + * [THRIFT-4026] - TSSLSocket doesn't work with Python < 2.7.9 + * [THRIFT-4029] - Accelerated protocols do not build from thrift-py 0.10.0 on PyPI + * [THRIFT-4031] - Go plugin generates invalid code for lists of typedef'ed built-in types + * [THRIFT-4033] - Default build WITH_PLUGIN=ON for all builds results in packaging errors + * [THRIFT-4034] - CMake doesn't work to build compiler on MacOS + * [THRIFT-4036] - Add .NET Core environment/build support to the docker image + * [THRIFT-4038] - socket check: checking an unsigned number against >= 0 never fails + * [THRIFT-4042] - ExtractionError when using accelerated thrift in a multiprocess test + * [THRIFT-4043] - thrift perl debian package is placing files in the wrong place + * [THRIFT-4044] - Build job 17 failing on every pull request; hspec core (haskell) 2.4 issue + * [THRIFT-4046] - MinGW with gcc 6.2 does not compile on Windows + * [THRIFT-4060] - Thrift printTo ostream overload mechanism breaks down when types are nested + * [THRIFT-4062] - Remove debug print from TServiceClient + * [THRIFT-4065] - Document Perl ForkingServer signal restriction imposed by THRIFT-3848 and remove unnecessary code + * [THRIFT-4068] - A code comment in Java ServerSocket is wrong around accept() + * [THRIFT-4073] - enum files are still being generated with unused imports + * [THRIFT-4076] - Appveyor builds failing because ant 1.9.8 was removed from apache servers + * [THRIFT-4077] - AI_ADDRCONFIG redefined after recent change to PlatformSocket header + * [THRIFT-4079] - Generated perl code that returns structures from included thrift files is missing a necessary use clause + * [THRIFT-4087] - Spurious exception destroying TThreadedServer because of incorrect join() call + * [THRIFT-4102] - TBufferedTransport performance issue since 0.10.0 + * [THRIFT-4106] - concurrency_test fails randomly + * [THRIFT-4108] - c_glib thrift ssl has multiple bugs and deprecated functions + * [THRIFT-4109] - Configure Script uses string comparison for versions + * [THRIFT-4129] - C++ TNonblockingServer fd leak when failing to dispatch new connections + * [THRIFT-4131] - Javascript with WebSocket handles oneway methods wrong + * [THRIFT-4134] - Fix remaining undefined behavior invalid vptr casts + * [THRIFT-4140] - Use of non-thread-safe function gmtime() + * [THRIFT-4141] - Installation of haxe in docker files refers to a redirect link and fails + * [THRIFT-4146] - Appveyor builds are being triggered by apache master pushes + * [THRIFT-4147] - Rust: protocol should accept transports with non-static lifetime + * [THRIFT-4148] - [maven-thrift-plugin] compile error while import a thrift in dependency jar file. + * [THRIFT-4149] - System.out pollutes log files + * [THRIFT-4154] - PHP close() of a TSocket needs to close any type of socket + * [THRIFT-4158] - minor issue in README-MSYS2.md + * [THRIFT-4159] - Building tests fails on MSYS2 (MinGW64) due to a (small?) linker error + * [THRIFT-4160] - TNonblocking server fix use of closed/freed connections + * [THRIFT-4161] - TNonBlocking server using uninitialized event in error paths + * [THRIFT-4162] - TNonBlocking handling of TSockets in error state is incorrect after fd is closed + * [THRIFT-4164] - Core in TSSLSocket cleanupOpenSSL when destroying a mutex used by openssl + * [THRIFT-4165] - C++ build has many warnings under c++03 due to recent changes, cmake needs better platform-independent language level control + * [THRIFT-4166] - Recent fix to remove boost::lexical_cast usage broke VS2010 + * [THRIFT-4167] - Missing compile flag + * [THRIFT-4170] - Support lua 5.1 or earlier properly for object length determination + * [THRIFT-4172] - node.js tutorial client does not import assert, connection issues are not handled properly + * [THRIFT-4177] - Java compiler produces deep copy constructor that could make shallow copy instead + * [THRIFT-4184] - Building on Appveyor: invalid escape sequence \L + * [THRIFT-4185] - fb303 counter encoding fix + * [THRIFT-4189] - Framed/buffered transport Dispose() does not dispose the nested transport + * [THRIFT-4193] - Lower the default maxReadBufferBytes for non-blocking servers + * [THRIFT-4195] - Compilation to GO produces broken code + * [THRIFT-4196] - Cannot generate recursive Rust types + * [THRIFT-4204] - typo in compact spec + * [THRIFT-4206] - Strings in container fields are not decoded properly with py:dynamic and py:utf8strings + * [THRIFT-4208] - C# NamedPipesServer not really working in some scenarios + * [THRIFT-4211] - Fix GError glib management under Thrift + * [THRIFT-4212] - c_glib flush tries to close SSL even if socket is invalid + * [THRIFT-4213] - Travis build fails at curl -sSL https://www.npmjs.com/install.sh | sh + * [THRIFT-4215] - Golang TTransportFactory Pattern Squelches Errors + * [THRIFT-4216] - Golang Http Clients Do Not Respect User Options + * [THRIFT-4218] - Set TCP_NODELAY for PHP client socket + * [THRIFT-4219] - Golang HTTP clients created with Nil buffer + * [THRIFT-4231] - TJSONProtocol throws unexpected non-Thrift-exception on null strings + * [THRIFT-4232] - ./configure does bad ant version check + * [THRIFT-4234] - Travis build fails cross language tests with "Unsupported security protocol type" + * [THRIFT-4237] - Go TServerSocket Race Conditions + * [THRIFT-4240] - Go TSimpleServer does not close properly + * [THRIFT-4243] - Go TSimpleServer race on wait in Stop() method + * [THRIFT-4245] - Golang TFramedTransport's writeBuffer increases if writes to transport failed + * [THRIFT-4246] - Sequence number mismatch on multiplexed clients + * [THRIFT-4247] - Compile fails with openssl 1.1 + * [THRIFT-4248] - Compile fails - strncpy, memcmp, memset not declared in src/thrift/transport/TSSLSocket.cpp + * [THRIFT-4251] - Java Epoll Selector Bug + * [THRIFT-4257] - Typescript async callbacks do not provide the correct types + * [THRIFT-4258] - Boost/std thread wrapping faultiness + * [THRIFT-4260] - Go context generation issue. Context is parameter in Interface not in implementation + * [THRIFT-4261] - Go context generation issue: breaking change in generated code regarding thrift.TProcessorFunction interface + * [THRIFT-4262] - Invalid binding to InterlockedCompareExchange64() with 64-bit targets + * [THRIFT-4263] - Fix use after free bug for thrown exceptions + * [THRIFT-4266] - Erlang library throws during skipping fields of composite type (maps, lists, structs, sets) + * [THRIFT-4268] - Erlang library emits debugging output in transport layer + * [THRIFT-4273] - erlang:now/0: Deprecated BIF. + * [THRIFT-4274] - Python feature tests for SSL/TLS failing + * [THRIFT-4279] - Wrong path in include directive in generated Thrift sources + * [THRIFT-4283] - TNamedPipeServer race condition in interrupt + * [THRIFT-4284] - File contains a NBSP: lib/nodejs/lib/thrift/web_server.js + * [THRIFT-4290] - C# nullable option generates invalid code for non-required enum field with default value + * [THRIFT-4292] - TimerManager::remove() is not implemented + * [THRIFT-4307] - Make ssl-open timeout effective in golang client + * [THRIFT-4312] - Erlang client cannot connect to Python server: exception error: econnrefused + * [THRIFT-4313] - Program code of the Erlang tutorial files contain syntax errors + * [THRIFT-4316] - TByteBuffer.java will read too much data if a previous read returns fewer bytes than requested + * [THRIFT-4319] - command line switch for "evhttp" incorrectly resolved to anon pipes + * [THRIFT-4323] - range check errors or NPE in edge cases + * [THRIFT-4324] - field names can conflict with local vars in generated code + * [THRIFT-4328] - Travis CI builds are timing out (job 1) and haxe builds are failing since 9/11 + * [THRIFT-4329] - c_glib Doesn't have a multiplexed processor + * [THRIFT-4331] - C++: TSSLSockets bug in handling huge messages, bug in handling polling + * [THRIFT-4332] - Binary protocol has memory leaks + * [THRIFT-4334] - Perl indentation incorrect when defaulting field attribute to a struct + * [THRIFT-4339] - Thrift Framed Transport in Erlang crashes server when client disconnects + * [THRIFT-4340] - Erlang fix a crash on client close + * [THRIFT-4355] - Javascript indentation incorrect when defaulting field attribute to a struct + * [THRIFT-4356] - thrift_protocol call Transport cause Segmentation fault + * [THRIFT-4359] - Haxe compiler looks like it is producing incorrect code for map or set key that is binary type + * [THRIFT-4362] - Missing size-check can lead to huge memory allocation + * [THRIFT-4364] - Website contributing guide erroneously recommends submitting patches in JIRA + * [THRIFT-4365] - Perl generated code uses indirect object syntax, which occasionally causes compilation errors. + * [THRIFT-4367] - python TProcessor.process is missing "self" + * [THRIFT-4370] - Ubuntu Artful cppcheck and flake8 are more stringent and causing SCA build job failures + * [THRIFT-4372] - Pipe write operations across a network are limited to 65,535 bytes per write. + * [THRIFT-4374] - cannot load thrift_protocol due to undefined symbol: _ZTVN10__cxxabiv120__si_class_type_infoE + * [THRIFT-4376] - Coverity high impact issue resolution + * [THRIFT-4377] - haxe. socket handles leak in TSimpleServer + * [THRIFT-4381] - Wrong isset bitfield value after transmission + * [THRIFT-4384] - Using multiple services simultaneously is not thread-safe. + * [THRIFT-4385] - Go remote client -u flag is broken + * [THRIFT-4392] - compiler/..../plugin.thrift structs mis-ordered blows up ocaml generator + * [THRIFT-4395] - Unable to build in the ubuntu-xenial docker image: clap 2.28 requires Rust 1.20 + * [THRIFT-4396] - inconsistent (or plain wrong) version numbers in master/trunk + +## Documentation + * [THRIFT-4157] - outdated readme about Haxe installation on Linux + +## Improvement + * [THRIFT-105] - make a thrift_spec for a structures with negative tags + * [THRIFT-281] - Cocoa library code needs comments, badly + * [THRIFT-775] - performance improvements for Perl + * [THRIFT-2221] - Generate c++ code with std::shared_ptr instead of boost::shared_ptr. + * [THRIFT-2364] - OCaml: Use Oasis exclusively for build process + * [THRIFT-2504] - TMultiplexedProcessor should allow registering default processor called if no service name is present + * [THRIFT-3207] - Enable build with OpenSSL 1.1.0 series + * [THRIFT-3272] - Perl SSL Authentication Support + * [THRIFT-3357] - Generate EnumSet/EnumMap where elements/keys are enums + * [THRIFT-3369] - Implement SSL/TLS support on C with c_glib + * [THRIFT-3467] - Go Maps for Thrift Sets Should Have Values of Type struct{} + * [THRIFT-3627] - Missing basic code style consistency of JavaScript. + * [THRIFT-3706] - There's no support for Multiplexed protocol on c_glib library + * [THRIFT-3766] - Add getUnderlyingTransport() to TZlibTransport + * [THRIFT-3776] - Go code from multiple thrift files with the same namespace + * [THRIFT-3823] - Escape documentation while generating non escaped documetation + * [THRIFT-3854] - allow users to clear read buffers + * [THRIFT-3859] - Unix Domain Socket Support in Objective-C + * [THRIFT-3921] - C++ code should print enums as strings + * [THRIFT-3926] - There should be an error emitted when http status code is not 200 + * [THRIFT-4000] - Add union test to Test Suite + * [THRIFT-4007] - Micro-optimization of TTransport.py + * [THRIFT-4040] - Add real cause of TNonblockingServerSocket error to exception + * [THRIFT-4064] - Update node library dependencies + * [THRIFT-4069] - All perl packages should have proper namespace, version syntax, and use proper thrift exceptions + * [THRIFT-4071] - Consolidate the Travis CI jobs where possible to put less stress on the Apache Foundation's allocation of CI build slaves + * [THRIFT-4072] - Add the possibility to send custom headers in TCurlClient + * [THRIFT-4075] - Better MinGW support for headers-only boost (without thread library) + * [THRIFT-4081] - Provide a MinGW 64-bit Appveyor CI build for better pull request validation + * [THRIFT-4084] - Improve SSL security in thrift by adding a make cross client that checks to make sure SSLv3 protocol cannot be negotiated + * [THRIFT-4095] - Add multiplexed protocol to Travis CI for make cross + * [THRIFT-4099] - Auto-derive Hash for generated Rust structs + * [THRIFT-4110] - The debian build files do not produce a "-dbg" package for debug symbols of libthrift0 + * [THRIFT-4114] - Space after '///' in doc comments + * [THRIFT-4126] - Validate objects in php extension + * [THRIFT-4130] - Ensure Apache Http connection is released back to pool after use + * [THRIFT-4151] - Thrift Mutex Contention Profiling (pthreads) should be disabled by default + * [THRIFT-4168] - Travis CI builds are being triggered by apache master pushes + * [THRIFT-4176] - Implement a threaded and threadpool server type for Rust + * [THRIFT-4183] - Named pipe client blocks forever on Open() when there is no server at the other end + * [THRIFT-4190] - improve C# TThreadPoolServer defaults + * [THRIFT-4197] - Implement transparent gzip compression for HTTP transport + * [THRIFT-4198] - Ruby should log Thrift internal errors to global logger + * [THRIFT-4203] - thrift server stop gracefully + * [THRIFT-4205] - c_glib is not linking against glib + gobject + * [THRIFT-4209] - warning CS0414 in T[TLS]ServerSocket.cs + * [THRIFT-4210] - include Thrift.45.csproj into CI runs + * [THRIFT-4217] - HttpClient should support gzip and deflate + * [THRIFT-4222] - Support Unix Domain Sockets in Golang TServerSocket + * [THRIFT-4233] - Make THsHaServer.invoker available (get method only) in inherited classes + * [THRIFT-4236] - Support context in go generated code. + * [THRIFT-4238] - JSON generator: make annotation-aware + * [THRIFT-4269] - Don't append '.' to Erlang namespace if it ends in '_'. + * [THRIFT-4270] - Generate Erlang mapping functions for const maps and lists + * [THRIFT-4275] - Add support for zope.interface only, apart from twisted support. + * [THRIFT-4285] - Pull generated send/recv into library to allow behaviour to be customised + * [THRIFT-4287] - Add c++ compiler "no_skeleton" flag option + * [THRIFT-4288] - Implement logging levels properly for node.js + * [THRIFT-4295] - Refresh the Docker image file suite for Ubuntu, Debian, and CentOS + * [THRIFT-4305] - Emit ddoc for generated items + * [THRIFT-4306] - Thrift imports not replicated to D service output + * [THRIFT-4315] - Add default message for TApplicationException + * [THRIFT-4318] - Delphi performance improvements + * [THRIFT-4325] - Simplify automake cross compilation by relying on one global THRIFT compiler path + * [THRIFT-4327] - Improve TimerManager API to allow removing specific task + * [THRIFT-4330] - Allow unused crates in Rust files + * [THRIFT-4333] - Erlang tutorial examples are using a different port (9999) + * [THRIFT-4343] - Change CI builds to use node.js 8.x LTS once available + * [THRIFT-4345] - Create a docker build environment that uses the minimum supported language levels + * [THRIFT-4346] - Allow Zlib transport factory to wrap other transports + * [THRIFT-4348] - Perl HTTP Client custom HTTP headers + * [THRIFT-4350] - Update netcore build for dotnet 2.0 sdk and make cross validation + * [THRIFT-4351] - Use Travis CI Build Stages to optimize the CI build + * [THRIFT-4353] - cannot read via thrift_protocol at server side + * [THRIFT-4378] - add set stopTimeoutUnit method to TThreadPoolServer + +## New Feature + * [THRIFT-750] - C++ Compiler Virtual Function Option + * [THRIFT-2945] - Implement support for Rust language + * [THRIFT-3857] - thrift js:node complier support an object as parameter not an instance of struct + * [THRIFT-3933] - Port official C# .NET library for Thrift to C# .NET Core libary + * [THRIFT-4039] - Update of Apache Thrift .Net Core lib + * [THRIFT-4113] - Provide a buffer transport for reading/writing in memory byte stream + +## Question + * [THRIFT-2956] - autoconf - possibly undefined macro - AC_PROG_BISON + * [THRIFT-4223] - Add support to the isServing() method for the C++ library + +## Task + * [THRIFT-3622] - Fix deprecated uses of std::auto_ptr + * [THRIFT-4028] - Please remove System.out.format from the source code + * [THRIFT-4186] - Build and test rust client in Travis + +## Test + * [THRIFT-4264] - PHP - Support both shared & static linking of sockets library + +## Wish + * [THRIFT-4344] - Define and maintain the minimum language level for all languages in one place + + Thrift 0.10.0 -------------------------------------------------------------------------------- ## Bug diff --git a/LANGUAGES.md b/LANGUAGES.md index 79fcf28df51..2f68a4e6eb5 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -1,7 +1,7 @@ # Apache Thrift Language Support # Last Modified: 2017-10-05
-Version: 0.10.0+ +Version: 0.11.0+ Thrift supports many programming languages and has an impressive test suite that exercises most of the languages, protocols, and transports that represents a matrix of thousands of possible combinations. Each language typically has a minimum required version as well as support libraries - some mandatory and some optional. All of this information is provided below to help you assess whether you can use Apache Thrift with your project. Obviously this is a complex matrix to maintain and may not be correct in all cases - if you spot an error please inform the developers using the mailing list. diff --git a/Thrift.podspec b/Thrift.podspec index 39d378053ac..6f8ebb73f21 100644 --- a/Thrift.podspec +++ b/Thrift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Thrift" - s.version = "1.0.0" + s.version = "0.11.0" s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC." s.description = <<-DESC The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages. @@ -13,6 +13,6 @@ The Apache Thrift software framework, for scalable cross-language services devel s.osx.deployment_target = '10.8' s.ios.framework = 'CFNetwork' s.osx.framework = 'CoreServices' - s.source = { :git => "https://github.com/apache/thrift.git", :tag => "thrift-1.0.0" } + s.source = { :git => "https://github.com/apache/thrift.git", :tag => "thrift-0.11.0" } s.source_files = 'lib/cocoa/src/**/*.{h,m,swift}' end \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index 4c2e36496ca..073ffd49275 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ # build Apache Thrift on AppVeyor - https://ci.appveyor.com -version: '1.0.0-dev.{build}' +version: '0.11.0.{build}' shallow_clone: true diff --git a/build/cmake/DefineCMakeDefaults.cmake b/build/cmake/DefineCMakeDefaults.cmake index 28999379f6c..bb3239980b2 100644 --- a/build/cmake/DefineCMakeDefaults.cmake +++ b/build/cmake/DefineCMakeDefaults.cmake @@ -35,7 +35,7 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) set(CMAKE_COLOR_MAKEFILE ON) # Define the generic version of the libraries here -set(GENERIC_LIB_VERSION "0.1.0") +set(GENERIC_LIB_VERSION "0.11.0") set(GENERIC_LIB_SOVERSION "0") # Set the default build type to release with debug info diff --git a/composer.json b/composer.json index ad71f910c01..9d6454ee12e 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "1.0.0-dev" + "dev-master": "0.11.0" } } } diff --git a/configure.ac b/configure.ac index 073ad8dc59f..6a7a1a58722 100755 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ(2.65) AC_CONFIG_MACRO_DIR([./aclocal]) -AC_INIT([thrift], [1.0.0-dev]) +AC_INIT([thrift], [0.11.0]) AC_CONFIG_AUX_DIR([.]) diff --git a/contrib/Rebus/Properties/AssemblyInfo.cs b/contrib/Rebus/Properties/AssemblyInfo.cs index e476eab7656..9c4d7ccb9ba 100644 --- a/contrib/Rebus/Properties/AssemblyInfo.cs +++ b/contrib/Rebus/Properties/AssemblyInfo.cs @@ -34,5 +34,5 @@ [assembly: Guid("0af10984-40d3-453d-b1e5-421529e8c7e2")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.11.0.0")] +[assembly: AssemblyFileVersion("0.11.0.0")] diff --git a/contrib/fb303/py/setup.py b/contrib/fb303/py/setup.py index 4321ce258d5..9dafa88cfe3 100644 --- a/contrib/fb303/py/setup.py +++ b/contrib/fb303/py/setup.py @@ -26,7 +26,7 @@ from distutils.core import setup, Extension, Command setup(name='thrift_fb303', - version='1.0.0-dev', + version='0.11.0', description='Python bindings for the Apache Thrift FB303', author=['Thrift Developers'], author_email=['dev@thrift.apache.org'], diff --git a/contrib/thrift-maven-plugin/pom.xml b/contrib/thrift-maven-plugin/pom.xml index 0af595764bb..76d0d4f3a90 100644 --- a/contrib/thrift-maven-plugin/pom.xml +++ b/contrib/thrift-maven-plugin/pom.xml @@ -27,7 +27,7 @@ thrift-maven-plugin maven-plugin thrift-maven-plugin - 1.0-SNAPSHOT + 0.11.0 diff --git a/contrib/vagrant/centos-6.5/README.md b/contrib/vagrant/centos-6.5/README.md index 76dca44391e..bd7f022eb82 100644 --- a/contrib/vagrant/centos-6.5/README.md +++ b/contrib/vagrant/centos-6.5/README.md @@ -11,7 +11,7 @@ This will download and launch the base box VM under VirtualBox and run the Apach $ vagrant ssh [vagrant@thrift ~]$ cd /thrift [vagrant@thrift thrift]$ compiler/cpp/thrift --version - Thrift version 1.0.0-dev + Thrift version 0.11.0 The provisioning script (inside the Vagrantfile) runs ./bootstrap.sh, ./configure, make and make check, but does not install thrift. To install thrift run "make install". diff --git a/contrib/zeromq/csharp/ThriftZMQ.csproj b/contrib/zeromq/csharp/ThriftZMQ.csproj index 6b465306554..32a8c498bcd 100755 --- a/contrib/zeromq/csharp/ThriftZMQ.csproj +++ b/contrib/zeromq/csharp/ThriftZMQ.csproj @@ -1,4 +1,22 @@  + Debug @@ -25,7 +43,7 @@ false true 0 - 1.0.0.%2a + 0.11.0.%2a false false true diff --git a/debian/changelog b/debian/changelog index f2da2327e3c..68629d6e10a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,8 @@ -thrift (1.0.0-dev) stable; urgency=low +thrift (0.11.0) stable; urgency=low * update version * fix libthrift0.install + * update to 0.11.0 -- Roger Meier Tue, 08 Jan 2013 22:40:12 +0100 thrift (0.9.0) stable; urgency=low diff --git a/doap.rdf b/doap.rdf index 75274aa7b0d..06447c74417 100755 --- a/doap.rdf +++ b/doap.rdf @@ -58,6 +58,11 @@ + + Apache Thrift + 2017-11-30 + 0.11.0 + Apache Thrift 2017-03-01 diff --git a/lib/cocoa/src/Thrift.h b/lib/cocoa/src/Thrift.h index 6fc594a4b22..89486b2b8b3 100644 --- a/lib/cocoa/src/Thrift.h +++ b/lib/cocoa/src/Thrift.h @@ -17,4 +17,4 @@ * under the License. */ -#define ThriftVersion @"1.0.0-dev" +#define ThriftVersion @"0.11.0" diff --git a/lib/cpp/src/thrift/windows/config.h b/lib/cpp/src/thrift/windows/config.h index bc4aa42f8ad..a361eacb061 100644 --- a/lib/cpp/src/thrift/windows/config.h +++ b/lib/cpp/src/thrift/windows/config.h @@ -70,6 +70,7 @@ #pragma warning(disable : 4996) // Deprecated posix name. #endif +#define VERSION "0.11.0" #define HAVE_GETTIMEOFDAY 1 #define HAVE_SYS_STAT_H 1 diff --git a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj index ae8608159dc..1ee29d16e24 100644 --- a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj +++ b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj @@ -45,7 +45,7 @@ false true 0 - 1.0.0.%2a + 0.11.0.%2a false false true diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs index dcbe74738b8..ab6921e6bf8 100644 --- a/lib/csharp/src/Properties/AssemblyInfo.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.1")] -[assembly: AssemblyFileVersion("1.0.0.1")] +[assembly: AssemblyVersion("0.11.0.1")] +[assembly: AssemblyFileVersion("0.11.0.1")] diff --git a/lib/csharp/src/Thrift.csproj b/lib/csharp/src/Thrift.csproj index 83bc4f7d011..9040ca59055 100644 --- a/lib/csharp/src/Thrift.csproj +++ b/lib/csharp/src/Thrift.csproj @@ -45,7 +45,7 @@ false true 0 - 1.0.0.%2a + 0.11.0.%2a false false true diff --git a/lib/csharp/test/JSON/Properties/AssemblyInfo.cs b/lib/csharp/test/JSON/Properties/AssemblyInfo.cs index fdff4a1a5c4..fe0c46b09f2 100644 --- a/lib/csharp/test/JSON/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/JSON/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern // übernehmen, indem Sie "*" eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.11.0.0")] +[assembly: AssemblyFileVersion("0.11.0.0")] diff --git a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj index 6221e141836..ed9616bb0c2 100644 --- a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj +++ b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj @@ -46,7 +46,7 @@ false true 0 - 1.0.0.%2a + 0.11.0.%2a false true diff --git a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs index f686ded5c20..e2d433e7568 100644 --- a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.11.0.0")] +[assembly: AssemblyFileVersion("0.11.0.0")] diff --git a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj index dc1d123e4fa..e0ca45c9b27 100644 --- a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj +++ b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj @@ -46,7 +46,7 @@ false true 0 - 1.0.0.%2a + 0.11.0.%2a false true
diff --git a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs index 5d405466a1b..8f63d65f2b3 100644 --- a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.11.0.0")] +[assembly: AssemblyFileVersion("0.11.0.0")] diff --git a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs b/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs index 1b1b833d998..8acb1c23c2e 100644 --- a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs @@ -49,5 +49,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.1")] -[assembly: AssemblyFileVersion("1.0.0.1")] +[assembly: AssemblyVersion("0.11.0.1")] +[assembly: AssemblyFileVersion("0.11.0.1")] diff --git a/lib/d/src/thrift/base.d b/lib/d/src/thrift/base.d index 38034a7b87f..8aea53613a9 100644 --- a/lib/d/src/thrift/base.d +++ b/lib/d/src/thrift/base.d @@ -50,7 +50,7 @@ class TCompoundOperationException : TException { /// The Thrift version string, used for informative purposes. // Note: This is currently hardcoded, but will likely be filled in by the build // system in future versions. -enum VERSION = "1.0.0 dev"; +enum VERSION = "0.11.0"; /** * Functions used for logging inside Thrift. diff --git a/lib/dart/pubspec.yaml b/lib/dart/pubspec.yaml index f7aa8768a64..5d04226b446 100644 --- a/lib/dart/pubspec.yaml +++ b/lib/dart/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: thrift -version: 1.0.0-dev +version: 0.11.0 description: > A Dart library for Apache Thrift author: Apache Thrift Developers @@ -33,7 +33,7 @@ dependencies: dev_dependencies: # test - mockito: ^1.0.0 + mockito: ^0.11.0 test: ^0.12.0 # dart_dev - https://github.com/Workiva/dart_dev diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index 6eca3c9cb30..edf20da94eb 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -25,7 +25,7 @@ interface SysUtils, Thrift.Protocol; const - Version = '1.0.0-dev'; + Version = '0.11.0'; type TApplicationExceptionSpecializedClass = class of TApplicationExceptionSpecialized; diff --git a/lib/erl/src/thrift.app.src b/lib/erl/src/thrift.app.src index 1a23f0dd479..02474944253 100644 --- a/lib/erl/src/thrift.app.src +++ b/lib/erl/src/thrift.app.src @@ -22,7 +22,7 @@ {description, "Thrift bindings"}, % The version of the applicaton - {vsn, "1.0.0-dev"}, + {vsn, "0.11.0"}, % All modules used by the application. {modules, [ diff --git a/lib/go/thrift/serializer_types_test.go b/lib/go/thrift/serializer_types_test.go index c8e3b3be466..e6f81808351 100644 --- a/lib/go/thrift/serializer_types_test.go +++ b/lib/go/thrift/serializer_types_test.go @@ -19,7 +19,7 @@ package thrift -// Autogenerated by Thrift Compiler (1.0.0-dev) +// Autogenerated by Thrift Compiler (0.11.0) // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING /* THE FOLLOWING THRIFT FILE WAS USED TO CREATE THIS diff --git a/lib/haxe/README.md b/lib/haxe/README.md index 19bbbaabfd4..ac70f253ad0 100644 --- a/lib/haxe/README.md +++ b/lib/haxe/README.md @@ -69,10 +69,10 @@ Thrift Haxe bindings Thrift Haxe bindings can be set up via the `haxelib` tool either from the official ASF repo, or via the github mirror. -- To set up any **stable version**, choose the appropriate branch (e.g. `0.10.0`): +- To set up any **stable version**, choose the appropriate branch (e.g. `0.11.0`): - - `haxelib git thrift https://git.apache.org/thrift.git 0.10.0 lib/haxe` - - `haxelib git thrift https://github.com/apache/thrift.git 0.10.0 lib/haxe` + - `haxelib git thrift https://git.apache.org/thrift.git 0.11.0 lib/haxe` + - `haxelib git thrift https://github.com/apache/thrift.git 0.11.0 lib/haxe` - To set up the current **development version**, use the `master` branch: diff --git a/lib/haxe/haxelib.json b/lib/haxe/haxelib.json index f76990e8b81..26caa7967ba 100644 --- a/lib/haxe/haxelib.json +++ b/lib/haxe/haxelib.json @@ -4,7 +4,7 @@ "license": "Apache", "tags": ["thrift", "rpc", "serialization", "cross", "framework"], "description": "Haxe bindings for the Apache Thrift RPC and serialization framework", - "version": "1.0.0-dev", + "version": "0.11.0", "releasenote": "Licensed under Apache License, Version 2.0. The Apache Thrift compiler needs to be installed separately.", "contributors": ["Apache Software Foundation (ASF)"], "dependencies": { }, diff --git a/lib/hs/thrift.cabal b/lib/hs/thrift.cabal index fb33d9a414c..9754ab2ee20 100644 --- a/lib/hs/thrift.cabal +++ b/lib/hs/thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 1.0.0-dev +Version: 0.11.0 Cabal-Version: >= 1.8 License: OtherLicense Category: Foreign diff --git a/lib/java/build.properties b/lib/java/build.properties index 96cf8d32c53..fd353518663 100644 --- a/lib/java/build.properties +++ b/lib/java/build.properties @@ -1,4 +1,4 @@ -thrift.version=1.0.0 +thrift.version=0.11.0 thrift.groupid=org.apache.thrift release=false diff --git a/lib/js/package.json b/lib/js/package.json index 526528dd5c6..421de933e6a 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "1.0.0", + "version": "0.11.0", "devDependencies": { "grunt": "^0.4.5", "grunt-cli": "^1.2.0", diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index ab85e9dc6c4..d308c46dcae 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -46,7 +46,7 @@ var Thrift = { * @const {string} Version * @memberof Thrift */ - Version: '1.0.0-dev', + Version: '0.11.0', /** * Thrift IDL type string to Id mapping. diff --git a/lib/lua/THttpTransport.lua b/lib/lua/THttpTransport.lua index 5bbfece2526..041e42188f1 100644 --- a/lib/lua/THttpTransport.lua +++ b/lib/lua/THttpTransport.lua @@ -25,7 +25,7 @@ THttpTransport = TTransportBase:new{ wBuf = '', rBuf = '', CRLF = '\r\n', - VERSION = '1.0.0', + VERSION = '0.11.0', isServer = true } diff --git a/lib/netcore/Thrift/Properties/AssemblyInfo.cs b/lib/netcore/Thrift/Properties/AssemblyInfo.cs index e3118ab23be..61cd3e30b85 100644 --- a/lib/netcore/Thrift/Properties/AssemblyInfo.cs +++ b/lib/netcore/Thrift/Properties/AssemblyInfo.cs @@ -52,5 +52,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.1")] -[assembly: AssemblyFileVersion("1.0.0.1")] \ No newline at end of file +[assembly: AssemblyVersion("0.11.0.1")] +[assembly: AssemblyFileVersion("0.11.0.1")] \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs index bc36bb3b490..1e83f97e92b 100644 --- a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs +++ b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs @@ -151,7 +151,7 @@ private HttpClient CreateClient() } httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); - httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "1.0.0")); + httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "0.11.0")); if (CustomHeaders != null) { diff --git a/lib/ocaml/_oasis b/lib/ocaml/_oasis index 4dd95e5ceb5..19033e61905 100644 --- a/lib/ocaml/_oasis +++ b/lib/ocaml/_oasis @@ -1,5 +1,5 @@ Name: libthrift-ocaml -Version: 1.0 +Version: 0.11.0 OASISFormat: 0.3 Synopsis: OCaml bindings for the Apache Thrift RPC system Authors: Apache Thrift Developers diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm index 592d1ddcdbc..cb623532025 100644 --- a/lib/perl/lib/Thrift.pm +++ b/lib/perl/lib/Thrift.pm @@ -31,6 +31,6 @@ use warnings; # package Thrift; -use version 0.77; our $VERSION = version->declare("v1.0_0"); +use version 0.77; our $VERSION = version->declare("v0.11.0"); 1; diff --git a/lib/py/setup.py b/lib/py/setup.py index 4056b9b9038..e3435c7751a 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -87,7 +87,7 @@ def run_setup(with_binary): twisted_deps = ['twisted'] setup(name='thrift', - version='1.0.0-dev', + version='0.11.0', description='Python bindings for the Apache Thrift RPC system', author='Thrift Developers', author_email='dev@thrift.apache.org', diff --git a/lib/rb/thrift.gemspec b/lib/rb/thrift.gemspec index 166a93f2735..291b81fbc65 100644 --- a/lib/rb/thrift.gemspec +++ b/lib/rb/thrift.gemspec @@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__) Gem::Specification.new do |s| s.name = 'thrift' - s.version = '1.0.0.0' + s.version = '0.11.0.0' s.authors = ['Thrift Developers'] s.email = ['dev@thrift.apache.org'] s.homepage = 'http://thrift.apache.org' diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml index 5f8f5e8cecf..8e68175cfb9 100644 --- a/lib/rs/Cargo.toml +++ b/lib/rs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "thrift" description = "Rust bindings for the Apache Thrift RPC system" -version = "1.0.0" +version = "0.11.0" license = "Apache-2.0" authors = ["Apache Thrift Developers "] homepage = "http://thrift.apache.org" diff --git a/lib/st/package.xml b/lib/st/package.xml index 72194fc9347..5044e2aa489 100644 --- a/lib/st/package.xml +++ b/lib/st/package.xml @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. --> - + libthrift-st thrift.st diff --git a/package.json b/package.json index cd6c7106c3a..24851b28024 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://git-wip-us.apache.org/repos/asf/thrift.git" }, - "version": "1.0.0-dev", + "version": "0.11.0", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", diff --git a/sonar-project.properties b/sonar-project.properties index b465fd12e81..6bc9989aac9 100755 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -16,7 +16,7 @@ development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between all major languages. # Apache Thrift Version -sonar.projectVersion=1.0.0-dev +sonar.projectVersion=0.11.0 # use this to set another version string # $ sonar-runner -D sonar.projectVersion=`git rev-parse HEAD` # set projectDate in combination with projectVersion for imports of old releases @@ -54,7 +54,7 @@ module1.sonar.projectName=Apache Thrift - Java Library module1.sonar.projectBaseDir=lib/java module1.sonar.sources=src module1.sonar.tests=test -module1.sonar.binaries=build/libthrift-1.0.0.jar +module1.sonar.binaries=build/libthrift-0.11.0.jar module1.sonar.libraries=build/lib/*.jar module1.sonar.language=java @@ -62,7 +62,7 @@ module2.sonar.projectName=Apache Thrift - Java Tutorial module2.sonar.projectBaseDir=. module2.sonar.sources=tutorial/java/src, tutorial/java/gen-java module2.sonar.binaries=tutorial/java/tutorial.jar -module2.sonar.libraries=lib/java/build/lib/*.jar,lib/java/build/libthrift-1.0.0.jar +module2.sonar.libraries=lib/java/build/lib/*.jar,lib/java/build/libthrift-0.11.0.jar module2.sonar.language=java module3.sonar.projectName=Apache Thrift - JavaScript Library diff --git a/test/csharp/Properties/AssemblyInfo.cs b/test/csharp/Properties/AssemblyInfo.cs index b1101a15f01..e2def42e333 100644 --- a/test/csharp/Properties/AssemblyInfo.cs +++ b/test/csharp/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.11.0.0")] +[assembly: AssemblyFileVersion("0.11.0.0")] diff --git a/test/csharp/ThriftTest.csproj b/test/csharp/ThriftTest.csproj index 65c0daf7d08..8fe40aaa802 100644 --- a/test/csharp/ThriftTest.csproj +++ b/test/csharp/ThriftTest.csproj @@ -46,7 +46,7 @@ false true 0 - 1.0.0.%2a + 0.11.0.%2a false true
diff --git a/test/dart/test_client/pubspec.yaml b/test/dart/test_client/pubspec.yaml index a91aa455a04..e386c0ec1ff 100644 --- a/test/dart/test_client/pubspec.yaml +++ b/test/dart/test_client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: thrift_test_client -version: 1.0.0-dev +version: 0.11.0 description: A client integration test for the Dart Thrift library author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/test/erl/src/thrift_test.app.src b/test/erl/src/thrift_test.app.src index 7896a9525ab..b55297042bf 100644 --- a/test/erl/src/thrift_test.app.src +++ b/test/erl/src/thrift_test.app.src @@ -22,7 +22,7 @@ {description, "Thrift cross language test"}, % The version of the applicaton - {vsn, "1.0.0-dev"}, + {vsn, "0.11.0"}, % All modules used by the application. {modules, [ diff --git a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs index 1ff658c39bb..2b801c2ca6d 100644 --- a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs +++ b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.11.0.0")] +[assembly: AssemblyFileVersion("0.11.0.0")] diff --git a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs index 74fa476e74d..b11cbdf93cc 100644 --- a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs +++ b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.11.0.0")] +[assembly: AssemblyFileVersion("0.11.0.0")] diff --git a/tutorial/dart/client/pubspec.yaml b/tutorial/dart/client/pubspec.yaml index db64afcfc71..51b7ad2cdb7 100644 --- a/tutorial/dart/client/pubspec.yaml +++ b/tutorial/dart/client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_client -version: 1.0.0-dev +version: 0.11.0 description: A Dart client implementation of the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org @@ -25,7 +25,7 @@ environment: sdk: ">=1.13.0 <2.0.0" dependencies: - browser: ^0.10.0 + browser: ^0.11.0 shared: path: ../gen-dart/shared thrift: diff --git a/tutorial/dart/console_client/pubspec.yaml b/tutorial/dart/console_client/pubspec.yaml index cea13acd55b..dea54494fd9 100644 --- a/tutorial/dart/console_client/pubspec.yaml +++ b/tutorial/dart/console_client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_console_client -version: 1.0.0-dev +version: 0.11.0 description: > A Dart console client to implementation of the Apache Thrift tutorial author: Apache Thrift Developers diff --git a/tutorial/dart/server/pubspec.yaml b/tutorial/dart/server/pubspec.yaml index 4833a4af8f5..b925d2f7c2e 100644 --- a/tutorial/dart/server/pubspec.yaml +++ b/tutorial/dart/server/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_server -version: 1.0.0-dev +version: 0.11.0 description: A Dart server to support the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/tutorial/delphi/DelphiClient/DelphiClient.dproj b/tutorial/delphi/DelphiClient/DelphiClient.dproj index 34aa53388ea..38226b36900 100644 --- a/tutorial/delphi/DelphiClient/DelphiClient.dproj +++ b/tutorial/delphi/DelphiClient/DelphiClient.dproj @@ -97,13 +97,13 @@ Thrift Tutorial - 1.0.0.0 + 0.11.0.0 DelphiClient Copyright © 2012 The Apache Software Foundation DelphiClient.exe Thrift - 1.0.0.0 + 0.11.0.0 diff --git a/tutorial/delphi/DelphiServer/DelphiServer.dproj b/tutorial/delphi/DelphiServer/DelphiServer.dproj index 74811bc10e6..ad47a53a387 100644 --- a/tutorial/delphi/DelphiServer/DelphiServer.dproj +++ b/tutorial/delphi/DelphiServer/DelphiServer.dproj @@ -96,13 +96,13 @@ Thrift Tutorial - 1.0.0.0 + 0.11.0.0 DelphiServer Copyright © 2012 The Apache Software Foundation DelphiServer.exe Thrift - 1.0.0.0 + 0.11.0.0 diff --git a/tutorial/hs/ThriftTutorial.cabal b/tutorial/hs/ThriftTutorial.cabal index 88f1379405d..98fbd7ba584 100755 --- a/tutorial/hs/ThriftTutorial.cabal +++ b/tutorial/hs/ThriftTutorial.cabal @@ -18,7 +18,7 @@ -- Name: ThriftTutorial -Version: 0.1.0 +Version: 0.11.0 Cabal-Version: >= 1.4 License: OtherLicense Category: Foreign diff --git a/tutorial/ocaml/_oasis b/tutorial/ocaml/_oasis index 4cab0806394..898261d81ce 100644 --- a/tutorial/ocaml/_oasis +++ b/tutorial/ocaml/_oasis @@ -1,5 +1,5 @@ Name: tutorial -Version: 1.0 +Version: 0.11.0 OASISFormat: 0.3 Synopsis: OCaml Tutorial example Authors: Apache Thrift Developers From fc0ff81ee7d4aa95a041c826dd5a83239ef98780 Mon Sep 17 00:00:00 2001 From: Nobuaki Sukegawa Date: Sun, 24 Jan 2016 04:01:27 +0900 Subject: [PATCH 067/756] THRIFT-3580 THeader for Haskell Client: hs This closes #820 This closes #1423 --- .../cpp/src/thrift/generate/t_hs_generator.cc | 64 ++-- lib/hs/src/Thrift.hs | 4 +- lib/hs/src/Thrift/Protocol.hs | 41 +- lib/hs/src/Thrift/Protocol/Binary.hs | 59 ++- lib/hs/src/Thrift/Protocol/Compact.hs | 62 +-- lib/hs/src/Thrift/Protocol/Header.hs | 141 +++++++ lib/hs/src/Thrift/Protocol/JSON.hs | 58 +-- lib/hs/src/Thrift/Server.hs | 6 +- lib/hs/src/Thrift/Transport/Handle.hs | 14 +- lib/hs/src/Thrift/Transport/Header.hs | 354 ++++++++++++++++++ lib/hs/thrift.cabal | 2 + test/hs/TestClient.hs | 6 +- test/hs/TestServer.hs | 15 +- test/known_failures_Linux.json | 4 +- test/tests.json | 1 + 15 files changed, 690 insertions(+), 141 deletions(-) create mode 100644 lib/hs/src/Thrift/Protocol/Header.hs create mode 100644 lib/hs/src/Thrift/Transport/Header.hs diff --git a/compiler/cpp/src/thrift/generate/t_hs_generator.cc b/compiler/cpp/src/thrift/generate/t_hs_generator.cc index 30eb8fa9ab3..d0a8cb2d6bf 100644 --- a/compiler/cpp/src/thrift/generate/t_hs_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_hs_generator.cc @@ -711,13 +711,13 @@ void t_hs_generator::generate_hs_struct_reader(ofstream& out, t_struct* tstruct) string tmap = type_name(tstruct, "typemap_"); indent(out) << "to_" << sname << " _ = P.error \"not a struct\"" << endl; - indent(out) << "read_" << sname << " :: (T.Transport t, T.Protocol p) => p t -> P.IO " << sname + indent(out) << "read_" << sname << " :: T.Protocol p => p -> P.IO " << sname << endl; indent(out) << "read_" << sname << " iprot = to_" << sname; out << " <$> T.readVal iprot (T.T_STRUCT " << tmap << ")" << endl; indent(out) << "decode_" << sname - << " :: (T.Protocol p, T.Transport t) => p t -> LBS.ByteString -> " << sname << endl; + << " :: T.StatelessProtocol p => p -> LBS.ByteString -> " << sname << endl; indent(out) << "decode_" << sname << " iprot bs = to_" << sname << " $ "; out << "T.deserializeVal iprot (T.T_STRUCT " << tmap << ") bs" << endl; } @@ -818,13 +818,13 @@ void t_hs_generator::generate_hs_struct_writer(ofstream& out, t_struct* tstruct) indent_down(); // write - indent(out) << "write_" << name << " :: (T.Protocol p, T.Transport t) => p t -> " << name + indent(out) << "write_" << name << " :: T.Protocol p => p -> " << name << " -> P.IO ()" << endl; indent(out) << "write_" << name << " oprot record = T.writeVal oprot $ from_"; out << name << " record" << endl; // encode - indent(out) << "encode_" << name << " :: (T.Protocol p, T.Transport t) => p t -> " << name + indent(out) << "encode_" << name << " :: T.StatelessProtocol p => p -> " << name << " -> LBS.ByteString" << endl; indent(out) << "encode_" << name << " oprot record = T.serializeVal oprot $ "; out << "from_" << name << " record" << endl; @@ -1085,8 +1085,9 @@ void t_hs_generator::generate_service_client(t_service* tservice) { // Serialize the request header string fname = (*f_iter)->get_name(); string msgType = (*f_iter)->is_oneway() ? "T.M_ONEWAY" : "T.M_CALL"; - indent(f_client_) << "T.writeMessageBegin op (\"" << fname << "\", " << msgType << ", seqn)" + indent(f_client_) << "T.writeMessage op (\"" << fname << "\", " << msgType << ", seqn) $" << endl; + indent_up(); indent(f_client_) << "write_" << argsname << " op (" << argsname << "{"; bool first = true; @@ -1102,10 +1103,7 @@ void t_hs_generator::generate_service_client(t_service* tservice) { first = false; } f_client_ << "})" << endl; - indent(f_client_) << "T.writeMessageEnd op" << endl; - - // Write to the stream - indent(f_client_) << "T.tFlush (T.getTransport op)" << endl; + indent_down(); indent_down(); if (!(*f_iter)->is_oneway()) { @@ -1119,12 +1117,12 @@ void t_hs_generator::generate_service_client(t_service* tservice) { indent(f_client_) << funname << " ip = do" << endl; indent_up(); - indent(f_client_) << "(fname, mtype, rseqid) <- T.readMessageBegin ip" << endl; + indent(f_client_) << "T.readMessage ip $ \\(fname, mtype, rseqid) -> do" << endl; + indent_up(); indent(f_client_) << "M.when (mtype == T.M_EXCEPTION) $ do { exn <- T.readAppExn ip ; " - "T.readMessageEnd ip ; X.throw exn }" << endl; + "X.throw exn }" << endl; indent(f_client_) << "res <- read_" << resultname << " ip" << endl; - indent(f_client_) << "T.readMessageEnd ip" << endl; t_struct* xs = (*f_iter)->get_xceptions(); const vector& xceptions = xs->get_members(); @@ -1142,6 +1140,7 @@ void t_hs_generator::generate_service_client(t_service* tservice) { // Close function indent_down(); + indent_down(); } } @@ -1180,11 +1179,11 @@ void t_hs_generator::generate_service_server(t_service* tservice) { f_service_ << "do" << endl; indent_up(); indent(f_service_) << "_ <- T.readVal iprot (T.T_STRUCT Map.empty)" << endl; - indent(f_service_) << "T.writeMessageBegin oprot (name,T.M_EXCEPTION,seqid)" << endl; + indent(f_service_) << "T.writeMessage oprot (name,T.M_EXCEPTION,seqid) $" << endl; + indent_up(); indent(f_service_) << "T.writeAppExn oprot (T.AppExn T.AE_UNKNOWN_METHOD (\"Unknown function " "\" ++ LT.unpack name))" << endl; - indent(f_service_) << "T.writeMessageEnd oprot" << endl; - indent(f_service_) << "T.tFlush (T.getTransport oprot)" << endl; + indent_down(); indent_down(); } @@ -1194,9 +1193,8 @@ void t_hs_generator::generate_service_server(t_service* tservice) { indent(f_service_) << "process handler (iprot, oprot) = do" << endl; indent_up(); - indent(f_service_) << "(name, typ, seqid) <- T.readMessageBegin iprot" << endl; - indent(f_service_) << "proc_ handler (iprot,oprot) (name,typ,seqid)" << endl; - indent(f_service_) << "T.readMessageEnd iprot" << endl; + indent(f_service_) << "T.readMessage iprot (" << endl; + indent(f_service_) << " proc_ handler (iprot,oprot))" << endl; indent(f_service_) << "P.return P.True" << endl; indent_down(); } @@ -1286,11 +1284,11 @@ void t_hs_generator::generate_process_function(t_service* tservice, t_function* if (tfunction->is_oneway()) { indent(f_service_) << "P.return ()"; } else { - indent(f_service_) << "T.writeMessageBegin oprot (\"" << tfunction->get_name() - << "\", T.M_REPLY, seqid)" << endl; - indent(f_service_) << "write_" << resultname << " oprot res" << endl; - indent(f_service_) << "T.writeMessageEnd oprot" << endl; - indent(f_service_) << "T.tFlush (T.getTransport oprot)"; + indent(f_service_) << "T.writeMessage oprot (\"" << tfunction->get_name() + << "\", T.M_REPLY, seqid) $" << endl; + indent_up(); + indent(f_service_) << "write_" << resultname << " oprot res"; + indent_down(); } if (n > 0) { f_service_ << ")"; @@ -1307,11 +1305,11 @@ void t_hs_generator::generate_process_function(t_service* tservice, t_function* indent(f_service_) << "let res = default_" << resultname << "{" << field_name(resultname, (*x_iter)->get_name()) << " = P.Just e}" << endl; - indent(f_service_) << "T.writeMessageBegin oprot (\"" << tfunction->get_name() - << "\", T.M_REPLY, seqid)" << endl; - indent(f_service_) << "write_" << resultname << " oprot res" << endl; - indent(f_service_) << "T.writeMessageEnd oprot" << endl; - indent(f_service_) << "T.tFlush (T.getTransport oprot)"; + indent(f_service_) << "T.writeMessage oprot (\"" << tfunction->get_name() + << "\", T.M_REPLY, seqid) $" << endl; + indent_up(); + indent(f_service_) << "write_" << resultname << " oprot res"; + indent_down(); } else { indent(f_service_) << "P.return ()"; } @@ -1324,11 +1322,11 @@ void t_hs_generator::generate_process_function(t_service* tservice, t_function* indent_up(); if (!tfunction->is_oneway()) { - indent(f_service_) << "T.writeMessageBegin oprot (\"" << tfunction->get_name() - << "\", T.M_EXCEPTION, seqid)" << endl; - indent(f_service_) << "T.writeAppExn oprot (T.AppExn T.AE_UNKNOWN \"\")" << endl; - indent(f_service_) << "T.writeMessageEnd oprot" << endl; - indent(f_service_) << "T.tFlush (T.getTransport oprot)"; + indent(f_service_) << "T.writeMessage oprot (\"" << tfunction->get_name() + << "\", T.M_EXCEPTION, seqid) $" << endl; + indent_up(); + indent(f_service_) << "T.writeAppExn oprot (T.AppExn T.AE_UNKNOWN \"\")"; + indent_down(); } else { indent(f_service_) << "P.return ()"; } diff --git a/lib/hs/src/Thrift.hs b/lib/hs/src/Thrift.hs index 58a304b6e99..658020991bc 100644 --- a/lib/hs/src/Thrift.hs +++ b/lib/hs/src/Thrift.hs @@ -90,13 +90,13 @@ data AppExn = AppExn { ae_type :: AppExnType, ae_message :: String } deriving ( Show, Typeable ) instance Exception AppExn -writeAppExn :: (Protocol p, Transport t) => p t -> AppExn -> IO () +writeAppExn :: Protocol p => p -> AppExn -> IO () writeAppExn pt ae = writeVal pt $ TStruct $ Map.fromList [ (1, ("message", TString $ encodeUtf8 $ pack $ ae_message ae)) , (2, ("type", TI32 $ fromIntegral $ fromEnum (ae_type ae))) ] -readAppExn :: (Protocol p, Transport t) => p t -> IO AppExn +readAppExn :: Protocol p => p -> IO AppExn readAppExn pt = do let typemap = Map.fromList [(1,("message",T_STRING)),(2,("type",T_I32))] TStruct fields <- readVal pt $ T_STRUCT typemap diff --git a/lib/hs/src/Thrift/Protocol.hs b/lib/hs/src/Thrift/Protocol.hs index ed779a27d5f..67a9175cb33 100644 --- a/lib/hs/src/Thrift/Protocol.hs +++ b/lib/hs/src/Thrift/Protocol.hs @@ -22,12 +22,11 @@ module Thrift.Protocol ( Protocol(..) + , StatelessProtocol(..) , ProtocolExn(..) , ProtocolExnType(..) , getTypeOf , runParser - , versionMask - , version1 , bsToDouble , bsToDoubleLE ) where @@ -35,7 +34,6 @@ module Thrift.Protocol import Control.Exception import Data.Attoparsec.ByteString import Data.Bits -import Data.ByteString.Lazy (ByteString, toStrict) import Data.ByteString.Unsafe import Data.Functor ((<$>)) import Data.Int @@ -44,37 +42,26 @@ import Data.Text.Lazy (Text) import Data.Typeable (Typeable) import Data.Word import Foreign.Ptr (castPtr) -import Foreign.Storable (Storable, peek, poke) +import Foreign.Storable (peek, poke) import System.IO.Unsafe import qualified Data.ByteString as BS import qualified Data.HashMap.Strict as Map +import qualified Data.ByteString.Lazy as LBS -import Thrift.Types import Thrift.Transport - -versionMask :: Int32 -versionMask = fromIntegral (0xffff0000 :: Word32) - -version1 :: Int32 -version1 = fromIntegral (0x80010000 :: Word32) +import Thrift.Types class Protocol a where - getTransport :: Transport t => a t -> t - - writeMessageBegin :: Transport t => a t -> (Text, MessageType, Int32) -> IO () - writeMessageEnd :: Transport t => a t -> IO () - writeMessageEnd _ = return () - - readMessageBegin :: Transport t => a t -> IO (Text, MessageType, Int32) - readMessageEnd :: Transport t => a t -> IO () - readMessageEnd _ = return () + readByte :: a -> IO LBS.ByteString + readVal :: a -> ThriftType -> IO ThriftVal + readMessage :: a -> ((Text, MessageType, Int32) -> IO b) -> IO b - serializeVal :: Transport t => a t -> ThriftVal -> ByteString - deserializeVal :: Transport t => a t -> ThriftType -> ByteString -> ThriftVal + writeVal :: a -> ThriftVal -> IO () + writeMessage :: a -> (Text, MessageType, Int32) -> IO () -> IO () - writeVal :: Transport t => a t -> ThriftVal -> IO () - writeVal p = tWrite (getTransport p) . serializeVal p - readVal :: Transport t => a t -> ThriftType -> IO ThriftVal +class Protocol a => StatelessProtocol a where + serializeVal :: a -> ThriftVal -> LBS.ByteString + deserializeVal :: a -> ThriftType -> LBS.ByteString -> ThriftVal data ProtocolExnType = PE_UNKNOWN @@ -105,10 +92,10 @@ getTypeOf v = case v of TBinary{} -> T_BINARY TDouble{} -> T_DOUBLE -runParser :: (Protocol p, Transport t, Show a) => p t -> Parser a -> IO a +runParser :: (Protocol p, Show a) => p -> Parser a -> IO a runParser prot p = refill >>= getResult . parse p where - refill = handle handleEOF $ toStrict <$> tReadAll (getTransport prot) 1 + refill = handle handleEOF $ LBS.toStrict <$> readByte prot getResult (Done _ a) = return a getResult (Partial k) = refill >>= getResult . k getResult f = throw $ ProtocolExn PE_INVALID_DATA (show f) diff --git a/lib/hs/src/Thrift/Protocol/Binary.hs b/lib/hs/src/Thrift/Protocol/Binary.hs index 2d35305dcda..7b0acd9d483 100644 --- a/lib/hs/src/Thrift/Protocol/Binary.hs +++ b/lib/hs/src/Thrift/Protocol/Binary.hs @@ -25,6 +25,8 @@ module Thrift.Protocol.Binary ( module Thrift.Protocol , BinaryProtocol(..) + , versionMask + , version1 ) where import Control.Exception ( throw ) @@ -35,6 +37,7 @@ import Data.Functor import Data.Int import Data.Monoid import Data.Text.Lazy.Encoding ( decodeUtf8, encodeUtf8 ) +import Data.Word import Thrift.Protocol import Thrift.Transport @@ -47,37 +50,55 @@ import qualified Data.ByteString.Lazy as LBS import qualified Data.HashMap.Strict as Map import qualified Data.Text.Lazy as LT -data BinaryProtocol a = BinaryProtocol a +versionMask :: Int32 +versionMask = fromIntegral (0xffff0000 :: Word32) + +version1 :: Int32 +version1 = fromIntegral (0x80010000 :: Word32) + +data BinaryProtocol a = Transport a => BinaryProtocol a + +getTransport :: Transport t => BinaryProtocol t -> t +getTransport (BinaryProtocol t) = t -- NOTE: Reading and Writing functions rely on Builders and Data.Binary to -- encode and decode data. Data.Binary assumes that the binary values it is -- encoding to and decoding from are in BIG ENDIAN format, and converts the -- endianness as necessary to match the local machine. -instance Protocol BinaryProtocol where - getTransport (BinaryProtocol t) = t - - writeMessageBegin p (n, t, s) = tWrite (getTransport p) $ toLazyByteString $ - buildBinaryValue (TI32 (version1 .|. fromIntegral (fromEnum t))) <> - buildBinaryValue (TString $ encodeUtf8 n) <> - buildBinaryValue (TI32 s) - - readMessageBegin p = runParser p $ do - TI32 ver <- parseBinaryValue T_I32 - if ver .&. versionMask /= version1 - then throw $ ProtocolExn PE_BAD_VERSION "Missing version identifier" - else do - TString s <- parseBinaryValue T_STRING - TI32 sz <- parseBinaryValue T_I32 - return (decodeUtf8 s, toEnum $ fromIntegral $ ver .&. 0xFF, sz) +instance Transport t => Protocol (BinaryProtocol t) where + readByte p = tReadAll (getTransport p) 1 + -- flushTransport p = tFlush (getTransport p) + writeMessage p (n, t, s) f = do + tWrite (getTransport p) messageBegin + f + tFlush $ getTransport p + where + messageBegin = toLazyByteString $ + buildBinaryValue (TI32 (version1 .|. fromIntegral (fromEnum t))) <> + buildBinaryValue (TString $ encodeUtf8 n) <> + buildBinaryValue (TI32 s) + + readMessage p = (readMessageBegin p >>=) + where + readMessageBegin p = runParser p $ do + TI32 ver <- parseBinaryValue T_I32 + if ver .&. versionMask /= version1 + then throw $ ProtocolExn PE_BAD_VERSION "Missing version identifier" + else do + TString s <- parseBinaryValue T_STRING + TI32 sz <- parseBinaryValue T_I32 + return (decodeUtf8 s, toEnum $ fromIntegral $ ver .&. 0xFF, sz) + + writeVal p = tWrite (getTransport p) . toLazyByteString . buildBinaryValue + readVal p = runParser p . parseBinaryValue +instance Transport t => StatelessProtocol (BinaryProtocol t) where serializeVal _ = toLazyByteString . buildBinaryValue deserializeVal _ ty bs = case LP.eitherResult $ LP.parse (parseBinaryValue ty) bs of Left s -> error s Right val -> val - readVal p = runParser p . parseBinaryValue - -- | Writing Functions buildBinaryValue :: ThriftVal -> Builder buildBinaryValue (TStruct fields) = buildBinaryStruct fields <> buildType T_STOP diff --git a/lib/hs/src/Thrift/Protocol/Compact.hs b/lib/hs/src/Thrift/Protocol/Compact.hs index 07113df2130..f23970a824b 100644 --- a/lib/hs/src/Thrift/Protocol/Compact.hs +++ b/lib/hs/src/Thrift/Protocol/Compact.hs @@ -25,10 +25,11 @@ module Thrift.Protocol.Compact ( module Thrift.Protocol , CompactProtocol(..) + , parseVarint + , buildVarint ) where import Control.Applicative -import Control.Exception ( throw ) import Control.Monad import Data.Attoparsec.ByteString as P import Data.Attoparsec.ByteString.Lazy as LP @@ -40,7 +41,7 @@ import Data.Monoid import Data.Word import Data.Text.Lazy.Encoding ( decodeUtf8, encodeUtf8 ) -import Thrift.Protocol hiding (versionMask) +import Thrift.Protocol import Thrift.Transport import Thrift.Types @@ -64,38 +65,47 @@ typeBits = 0x07 -- 0000 0111 typeShiftAmount :: Int typeShiftAmount = 5 +getTransport :: Transport t => CompactProtocol t -> t +getTransport (CompactProtocol t) = t -instance Protocol CompactProtocol where - getTransport (CompactProtocol t) = t +instance Transport t => Protocol (CompactProtocol t) where + readByte p = tReadAll (getTransport p) 1 + writeMessage p (n, t, s) f = do + tWrite (getTransport p) messageBegin + f + tFlush $ getTransport p + where + messageBegin = toLazyByteString $ + B.word8 protocolID <> + B.word8 ((version .&. versionMask) .|. + (((fromIntegral $ fromEnum t) `shiftL` + typeShiftAmount) .&. typeMask)) <> + buildVarint (i32ToZigZag s) <> + buildCompactValue (TString $ encodeUtf8 n) - writeMessageBegin p (n, t, s) = tWrite (getTransport p) $ toLazyByteString $ - B.word8 protocolID <> - B.word8 ((version .&. versionMask) .|. - (((fromIntegral $ fromEnum t) `shiftL` - typeShiftAmount) .&. typeMask)) <> - buildVarint (i32ToZigZag s) <> - buildCompactValue (TString $ encodeUtf8 n) - - readMessageBegin p = runParser p $ do - pid <- fromIntegral <$> P.anyWord8 - when (pid /= protocolID) $ error "Bad Protocol ID" - w <- fromIntegral <$> P.anyWord8 - let ver = w .&. versionMask - when (ver /= version) $ error "Bad Protocol version" - let typ = (w `shiftR` typeShiftAmount) .&. typeBits - seqId <- parseVarint zigZagToI32 - TString name <- parseCompactValue T_STRING - return (decodeUtf8 name, toEnum $ fromIntegral $ typ, seqId) + readMessage p f = readMessageBegin >>= f + where + readMessageBegin = runParser p $ do + pid <- fromIntegral <$> P.anyWord8 + when (pid /= protocolID) $ error "Bad Protocol ID" + w <- fromIntegral <$> P.anyWord8 + let ver = w .&. versionMask + when (ver /= version) $ error "Bad Protocol version" + let typ = (w `shiftR` typeShiftAmount) .&. typeBits + seqId <- parseVarint zigZagToI32 + TString name <- parseCompactValue T_STRING + return (decodeUtf8 name, toEnum $ fromIntegral $ typ, seqId) + writeVal p = tWrite (getTransport p) . toLazyByteString . buildCompactValue + readVal p ty = runParser p $ parseCompactValue ty + +instance Transport t => StatelessProtocol (CompactProtocol t) where serializeVal _ = toLazyByteString . buildCompactValue deserializeVal _ ty bs = case LP.eitherResult $ LP.parse (parseCompactValue ty) bs of Left s -> error s Right val -> val - readVal p ty = runParser p $ parseCompactValue ty - - -- | Writing Functions buildCompactValue :: ThriftVal -> Builder buildCompactValue (TStruct fields) = buildCompactStruct fields @@ -283,7 +293,7 @@ typeOf v = case v of TSet{} -> 0x0A TMap{} -> 0x0B TStruct{} -> 0x0C - + typeFrom :: Word8 -> ThriftType typeFrom w = case w of 0x01 -> T_BOOL diff --git a/lib/hs/src/Thrift/Protocol/Header.hs b/lib/hs/src/Thrift/Protocol/Header.hs new file mode 100644 index 00000000000..5f42db45de7 --- /dev/null +++ b/lib/hs/src/Thrift/Protocol/Header.hs @@ -0,0 +1,141 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. +-- + + +module Thrift.Protocol.Header + ( module Thrift.Protocol + , HeaderProtocol(..) + , getProtocolType + , setProtocolType + , getHeaders + , getWriteHeaders + , setHeader + , setHeaders + , createHeaderProtocol + , createHeaderProtocol1 + ) where + +import Thrift.Protocol +import Thrift.Protocol.Binary +import Thrift.Protocol.JSON +import Thrift.Protocol.Compact +import Thrift.Transport +import Thrift.Transport.Header +import Data.IORef +import qualified Data.Map as Map + +data ProtocolWrap = forall a. (Protocol a) => ProtocolWrap(a) + +instance Protocol ProtocolWrap where + readByte (ProtocolWrap p) = readByte p + readVal (ProtocolWrap p) = readVal p + readMessage (ProtocolWrap p) = readMessage p + writeVal (ProtocolWrap p) = writeVal p + writeMessage (ProtocolWrap p) = writeMessage p + +data HeaderProtocol i o = (Transport i, Transport o) => HeaderProtocol { + trans :: HeaderTransport i o, + wrappedProto :: IORef ProtocolWrap + } + +createProtocolWrap :: Transport t => ProtocolType -> t -> ProtocolWrap +createProtocolWrap typ t = + case typ of + TBinary -> ProtocolWrap $ BinaryProtocol t + TCompact -> ProtocolWrap $ CompactProtocol t + TJSON -> ProtocolWrap $ JSONProtocol t + +createHeaderProtocol :: (Transport i, Transport o) => i -> o -> IO(HeaderProtocol i o) +createHeaderProtocol i o = do + t <- openHeaderTransport i o + pid <- readIORef $ protocolType t + proto <- newIORef $ createProtocolWrap pid t + return $ HeaderProtocol { trans = t, wrappedProto = proto } + +createHeaderProtocol1 :: Transport t => t -> IO(HeaderProtocol t t) +createHeaderProtocol1 t = createHeaderProtocol t t + +resetProtocol :: (Transport i, Transport o) => HeaderProtocol i o -> IO () +resetProtocol p = do + pid <- readIORef $ protocolType $ trans p + writeIORef (wrappedProto p) $ createProtocolWrap pid $ trans p + +getWrapped = readIORef . wrappedProto + +setTransport :: (Transport i, Transport o) => HeaderProtocol i o -> HeaderTransport i o -> HeaderProtocol i o +setTransport p t = p { trans = t } + +updateTransport :: (Transport i, Transport o) => HeaderProtocol i o -> (HeaderTransport i o -> HeaderTransport i o)-> HeaderProtocol i o +updateTransport p f = setTransport p (f $ trans p) + +type Headers = Map.Map String String + +-- TODO: we want to set headers without recreating client... +setHeader :: (Transport i, Transport o) => HeaderProtocol i o -> String -> String -> HeaderProtocol i o +setHeader p k v = updateTransport p $ \t -> t { writeHeaders = Map.insert k v $ writeHeaders t } + +setHeaders :: (Transport i, Transport o) => HeaderProtocol i o -> Headers -> HeaderProtocol i o +setHeaders p h = updateTransport p $ \t -> t { writeHeaders = h } + +-- TODO: make it public once we have first transform implementation for Haskell +setTransforms :: (Transport i, Transport o) => HeaderProtocol i o -> [TransformType] -> HeaderProtocol i o +setTransforms p trs = updateTransport p $ \t -> t { writeTransforms = trs } + +setTransform :: (Transport i, Transport o) => HeaderProtocol i o -> TransformType -> HeaderProtocol i o +setTransform p tr = updateTransport p $ \t -> t { writeTransforms = tr:(writeTransforms t) } + +getWriteHeaders :: (Transport i, Transport o) => HeaderProtocol i o -> Headers +getWriteHeaders = writeHeaders . trans + +getHeaders :: (Transport i, Transport o) => HeaderProtocol i o -> IO [(String, String)] +getHeaders = readIORef . headers . trans + +getProtocolType :: (Transport i, Transport o) => HeaderProtocol i o -> IO ProtocolType +getProtocolType p = readIORef $ protocolType $ trans p + +setProtocolType :: (Transport i, Transport o) => HeaderProtocol i o -> ProtocolType -> IO () +setProtocolType p typ = do + typ0 <- getProtocolType p + if typ == typ0 + then return () + else do + tSetProtocol (trans p) typ + resetProtocol p + +instance (Transport i, Transport o) => Protocol (HeaderProtocol i o) where + readByte p = tReadAll (trans p) 1 + + readVal p tp = do + proto <- getWrapped p + readVal proto tp + + readMessage p f = do + tResetProtocol (trans p) + resetProtocol p + proto <- getWrapped p + readMessage proto f + + writeVal p v = do + proto <- getWrapped p + writeVal proto v + + writeMessage p x f = do + proto <- getWrapped p + writeMessage proto x f + diff --git a/lib/hs/src/Thrift/Protocol/JSON.hs b/lib/hs/src/Thrift/Protocol/JSON.hs index 7f619e8cbf1..839eddc8465 100644 --- a/lib/hs/src/Thrift/Protocol/JSON.hs +++ b/lib/hs/src/Thrift/Protocol/JSON.hs @@ -29,12 +29,12 @@ module Thrift.Protocol.JSON ) where import Control.Applicative +import Control.Exception (bracket) import Control.Monad import Data.Attoparsec.ByteString as P import Data.Attoparsec.ByteString.Char8 as PC import Data.Attoparsec.ByteString.Lazy as LP import Data.ByteString.Base64.Lazy as B64C -import Data.ByteString.Base64 as B64 import Data.ByteString.Lazy.Builder as B import Data.ByteString.Internal (c2w, w2c) import Data.Functor @@ -58,38 +58,48 @@ import qualified Data.Text.Lazy as LT -- encoded as a JSON 'ByteString' data JSONProtocol t = JSONProtocol t -- ^ Construct a 'JSONProtocol' with a 'Transport' +getTransport :: Transport t => JSONProtocol t -> t +getTransport (JSONProtocol t) = t -instance Protocol JSONProtocol where - getTransport (JSONProtocol t) = t +instance Transport t => Protocol (JSONProtocol t) where + readByte p = tReadAll (getTransport p) 1 - writeMessageBegin (JSONProtocol t) (s, ty, sq) = tWrite t $ toLazyByteString $ - B.char8 '[' <> buildShowable (1 :: Int32) <> - B.string8 ",\"" <> escape (encodeUtf8 s) <> B.char8 '\"' <> - B.char8 ',' <> buildShowable (fromEnum ty) <> - B.char8 ',' <> buildShowable sq <> - B.char8 ',' - writeMessageEnd (JSONProtocol t) = tWrite t "]" - readMessageBegin p = runParser p $ skipSpace *> do - _ver :: Int32 <- lexeme (PC.char8 '[') *> lexeme (signed decimal) - bs <- lexeme (PC.char8 ',') *> lexeme escapedString - case decodeUtf8' bs of - Left _ -> fail "readMessage: invalid text encoding" - Right str -> do - ty <- toEnum <$> (lexeme (PC.char8 ',') *> lexeme (signed decimal)) - seqNum <- lexeme (PC.char8 ',') *> lexeme (signed decimal) - _ <- PC.char8 ',' - return (str, ty, seqNum) - readMessageEnd p = void $ runParser p (PC.char8 ']') + writeMessage (JSONProtocol t) (s, ty, sq) = bracket readMessageBegin readMessageEnd . const + where + readMessageBegin = tWrite t $ toLazyByteString $ + B.char8 '[' <> buildShowable (1 :: Int32) <> + B.string8 ",\"" <> escape (encodeUtf8 s) <> B.char8 '\"' <> + B.char8 ',' <> buildShowable (fromEnum ty) <> + B.char8 ',' <> buildShowable sq <> + B.char8 ',' + readMessageEnd _ = do + tWrite t "]" + tFlush t + readMessage p = bracket readMessageBegin readMessageEnd + where + readMessageBegin = runParser p $ skipSpace *> do + _ver :: Int32 <- lexeme (PC.char8 '[') *> lexeme (signed decimal) + bs <- lexeme (PC.char8 ',') *> lexeme escapedString + case decodeUtf8' bs of + Left _ -> fail "readMessage: invalid text encoding" + Right str -> do + ty <- toEnum <$> (lexeme (PC.char8 ',') *> lexeme (signed decimal)) + seqNum <- lexeme (PC.char8 ',') *> lexeme (signed decimal) + _ <- PC.char8 ',' + return (str, ty, seqNum) + readMessageEnd _ = void $ runParser p (PC.char8 ']') + + writeVal p = tWrite (getTransport p) . toLazyByteString . buildJSONValue + readVal p ty = runParser p $ skipSpace *> parseJSONValue ty + +instance Transport t => StatelessProtocol (JSONProtocol t) where serializeVal _ = toLazyByteString . buildJSONValue deserializeVal _ ty bs = case LP.eitherResult $ LP.parse (parseJSONValue ty) bs of Left s -> error s Right val -> val - readVal p ty = runParser p $ skipSpace *> parseJSONValue ty - - -- Writing Functions buildJSONValue :: ThriftVal -> Builder diff --git a/lib/hs/src/Thrift/Server.hs b/lib/hs/src/Thrift/Server.hs index ed74ceba615..543f3385012 100644 --- a/lib/hs/src/Thrift/Server.hs +++ b/lib/hs/src/Thrift/Server.hs @@ -38,10 +38,10 @@ import Thrift.Protocol.Binary -- | A threaded sever that is capable of using any Transport or Protocol -- instances. -runThreadedServer :: (Transport t, Protocol i, Protocol o) - => (Socket -> IO (i t, o t)) +runThreadedServer :: (Protocol i, Protocol o) + => (Socket -> IO (i, o)) -> h - -> (h -> (i t, o t) -> IO Bool) + -> (h -> (i, o) -> IO Bool) -> PortID -> IO a runThreadedServer accepter hand proc_ port = do diff --git a/lib/hs/src/Thrift/Transport/Handle.hs b/lib/hs/src/Thrift/Transport/Handle.hs index b7d16e4fbb4..ff6295b6779 100644 --- a/lib/hs/src/Thrift/Transport/Handle.hs +++ b/lib/hs/src/Thrift/Transport/Handle.hs @@ -44,7 +44,13 @@ import Data.Monoid instance Transport Handle where tIsOpen = hIsOpen tClose = hClose - tRead h n = LBS.hGet h n `Control.Exception.catch` handleEOF mempty + tRead h n = read `Control.Exception.catch` handleEOF mempty + where + read = do + hLookAhead h + LBS.hGetNonBlocking h n + tReadAll _ 0 = return mempty + tReadAll h n = LBS.hGet h n `Control.Exception.catch` throwTransportExn tPeek h = (Just . c2w <$> hLookAhead h) `Control.Exception.catch` handleEOF Nothing tWrite = LBS.hPut tFlush = hFlush @@ -61,8 +67,12 @@ instance HandleSource FilePath where instance HandleSource (HostName, PortID) where hOpen = uncurry connectTo +throwTransportExn :: IOError -> IO a +throwTransportExn e = if isEOFError e + then throw $ TransportExn "Cannot read. Remote side has closed." TE_UNKNOWN + else throw $ TransportExn "Handle tReadAll: Could not read" TE_UNKNOWN handleEOF :: a -> IOError -> IO a handleEOF a e = if isEOFError e then return a - else throw $ TransportExn "TChannelTransport: Could not read" TE_UNKNOWN + else throw $ TransportExn "Handle: Could not read" TE_UNKNOWN diff --git a/lib/hs/src/Thrift/Transport/Header.hs b/lib/hs/src/Thrift/Transport/Header.hs new file mode 100644 index 00000000000..2dacad25fd4 --- /dev/null +++ b/lib/hs/src/Thrift/Transport/Header.hs @@ -0,0 +1,354 @@ +-- +-- Licensed to the Apache Software Foundation (ASF) under one +-- or more contributor license agreements. See the NOTICE file +-- distributed with this work for additional information +-- regarding copyright ownership. The ASF licenses this file +-- to you under the Apache License, Version 2.0 (the +-- "License"); you may not use this file except in compliance +-- with the License. You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, +-- software distributed under the License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +-- KIND, either express or implied. See the License for the +-- specific language governing permissions and limitations +-- under the License. +-- + +module Thrift.Transport.Header + ( module Thrift.Transport + , HeaderTransport(..) + , openHeaderTransport + , ProtocolType(..) + , TransformType(..) + , ClientType(..) + , tResetProtocol + , tSetProtocol + ) where + +import Thrift.Transport +import Thrift.Protocol.Compact +import Control.Applicative +import Control.Exception ( throw ) +import Control.Monad +import Data.Bits +import Data.IORef +import Data.Int +import Data.Monoid +import Data.Word + +import qualified Data.Attoparsec.ByteString as P +import qualified Data.Binary as Binary +import qualified Data.ByteString as BS +import qualified Data.ByteString.Char8 as C +import qualified Data.ByteString.Lazy as LBS +import qualified Data.ByteString.Lazy.Builder as B +import qualified Data.Map as Map + +data ProtocolType = TBinary | TCompact | TJSON deriving (Enum, Eq) +data ClientType = HeaderClient | Framed | Unframed deriving (Enum, Eq) + +infoIdKeyValue = 1 + +type Headers = Map.Map String String + +data TransformType = ZlibTransform deriving (Enum, Eq) + +fromTransportType :: TransformType -> Int16 +fromTransportType ZlibTransform = 1 + +toTransportType :: Int16 -> TransformType +toTransportType 1 = ZlibTransform +toTransportType _ = throw $ TransportExn "HeaderTransport: Unknown transform ID" TE_UNKNOWN + +data HeaderTransport i o = (Transport i, Transport o) => HeaderTransport + { readBuffer :: IORef LBS.ByteString + , writeBuffer :: IORef B.Builder + , inTrans :: i + , outTrans :: o + , clientType :: IORef ClientType + , protocolType :: IORef ProtocolType + , headers :: IORef [(String, String)] + , writeHeaders :: Headers + , transforms :: IORef [TransformType] + , writeTransforms :: [TransformType] + } + +openHeaderTransport :: (Transport i, Transport o) => i -> o -> IO (HeaderTransport i o) +openHeaderTransport i o = do + pid <- newIORef TCompact + rBuf <- newIORef LBS.empty + wBuf <- newIORef mempty + cType <- newIORef HeaderClient + h <- newIORef [] + trans <- newIORef [] + return HeaderTransport + { readBuffer = rBuf + , writeBuffer = wBuf + , inTrans = i + , outTrans = o + , clientType = cType + , protocolType = pid + , headers = h + , writeHeaders = Map.empty + , transforms = trans + , writeTransforms = [] + } + +isFramed t = (/= Unframed) <$> readIORef (clientType t) + +readFrame :: (Transport i, Transport o) => HeaderTransport i o -> IO Bool +readFrame t = do + let input = inTrans t + let rBuf = readBuffer t + let cType = clientType t + lsz <- tRead input 4 + let sz = LBS.toStrict lsz + case P.parseOnly P.endOfInput sz of + Right _ -> do return False + Left _ -> do + case parseBinaryMagic sz of + Right _ -> do + writeIORef rBuf $ lsz + writeIORef cType Unframed + writeIORef (protocolType t) TBinary + return True + Left _ -> do + case parseCompactMagic sz of + Right _ -> do + writeIORef rBuf $ lsz + writeIORef cType Unframed + writeIORef (protocolType t) TCompact + return True + Left _ -> do + let len = Binary.decode lsz :: Int32 + lbuf <- tReadAll input $ fromIntegral len + let buf = LBS.toStrict lbuf + case parseBinaryMagic buf of + Right _ -> do + writeIORef cType Framed + writeIORef (protocolType t) TBinary + writeIORef rBuf lbuf + return True + Left _ -> do + case parseCompactMagic buf of + Right _ -> do + writeIORef cType Framed + writeIORef (protocolType t) TCompact + writeIORef rBuf lbuf + return True + Left _ -> do + case parseHeaderMagic buf of + Right flags -> do + let (flags, seqNum, header, body) = extractHeader buf + writeIORef cType HeaderClient + handleHeader t header + payload <- untransform t body + writeIORef rBuf $ LBS.fromStrict $ payload + return True + Left _ -> + throw $ TransportExn "HeaderTransport: unkonwn client type" TE_UNKNOWN + +parseBinaryMagic = P.parseOnly $ P.word8 0x80 *> P.word8 0x01 *> P.word8 0x00 *> P.anyWord8 +parseCompactMagic = P.parseOnly $ P.word8 0x82 *> P.satisfy (\b -> b .&. 0x1f == 0x01) +parseHeaderMagic = P.parseOnly $ P.word8 0x0f *> P.word8 0xff *> (P.count 2 P.anyWord8) + +parseI32 :: P.Parser Int32 +parseI32 = Binary.decode . LBS.fromStrict <$> P.take 4 +parseI16 :: P.Parser Int16 +parseI16 = Binary.decode . LBS.fromStrict <$> P.take 2 + +extractHeader :: BS.ByteString -> (Int16, Int32, BS.ByteString, BS.ByteString) +extractHeader bs = + case P.parse extractHeader_ bs of + P.Done remain (flags, seqNum, header) -> (flags, seqNum, header, remain) + _ -> throw $ TransportExn "HeaderTransport: Invalid header" TE_UNKNOWN + where + extractHeader_ = do + magic <- P.word8 0x0f *> P.word8 0xff + flags <- parseI16 + seqNum <- parseI32 + (headerSize :: Int) <- (* 4) . fromIntegral <$> parseI16 + header <- P.take headerSize + return (flags, seqNum, header) + +handleHeader t header = + case P.parseOnly parseHeader header of + Right (pType, trans, info) -> do + writeIORef (protocolType t) pType + writeIORef (transforms t) trans + writeIORef (headers t) info + _ -> throw $ TransportExn "HeaderTransport: Invalid header" TE_UNKNOWN + + +iw16 :: Int16 -> Word16 +iw16 = fromIntegral +iw32 :: Int32 -> Word32 +iw32 = fromIntegral +wi16 :: Word16 -> Int16 +wi16 = fromIntegral +wi32 :: Word32 -> Int32 +wi32 = fromIntegral + +parseHeader :: P.Parser (ProtocolType, [TransformType], [(String, String)]) +parseHeader = do + protocolType <- toProtocolType <$> parseVarint wi16 + numTrans <- fromIntegral <$> parseVarint wi16 + trans <- replicateM numTrans parseTransform + info <- parseInfo + return (protocolType, trans, info) + +toProtocolType :: Int16 -> ProtocolType +toProtocolType 0 = TBinary +toProtocolType 1 = TJSON +toProtocolType 2 = TCompact + +fromProtocolType :: ProtocolType -> Int16 +fromProtocolType TBinary = 0 +fromProtocolType TJSON = 1 +fromProtocolType TCompact = 2 + +parseTransform :: P.Parser TransformType +parseTransform = toTransportType <$> parseVarint wi16 + +parseInfo :: P.Parser [(String, String)] +parseInfo = do + n <- P.eitherP P.endOfInput (parseVarint wi32) + case n of + Left _ -> return [] + Right n0 -> + replicateM (fromIntegral n0) $ do + klen <- parseVarint wi16 + k <- P.take $ fromIntegral klen + vlen <- parseVarint wi16 + v <- P.take $ fromIntegral vlen + return (C.unpack k, C.unpack v) + +parseString :: P.Parser BS.ByteString +parseString = parseVarint wi32 >>= (P.take . fromIntegral) + +buildHeader :: HeaderTransport i o -> IO B.Builder +buildHeader t = do + pType <- readIORef $ protocolType t + let pId = buildVarint $ iw16 $ fromProtocolType pType + let headerContent = pId <> (buildTransforms t) <> (buildInfo t) + let len = fromIntegral $ LBS.length $ B.toLazyByteString headerContent + -- TODO: length limit check + let padding = mconcat $ replicate (mod len 4) $ B.word8 0 + let codedLen = B.int16BE (fromIntegral $ (quot (len - 1) 4) + 1) + let flags = 0 + let seqNum = 0 + return $ B.int16BE 0x0fff <> B.int16BE flags <> B.int32BE seqNum <> codedLen <> headerContent <> padding + +buildTransforms :: HeaderTransport i o -> B.Builder +-- TODO: check length limit +buildTransforms t = + let trans = writeTransforms t in + (buildVarint $ iw16 $ fromIntegral $ length trans) <> + (mconcat $ map (buildVarint . iw16 . fromTransportType) trans) + +buildInfo :: HeaderTransport i o -> B.Builder +buildInfo t = + let h = Map.assocs $ writeHeaders t in + -- TODO: check length limit + case length h of + 0 -> mempty + len -> (buildVarint $ iw16 $ fromIntegral $ len) <> (mconcat $ map buildInfoEntry h) + where + buildInfoEntry (k, v) = buildVarStr k <> buildVarStr v + -- TODO: check length limit + buildVarStr s = (buildVarint $ iw16 $ fromIntegral $ length s) <> B.string8 s + +tResetProtocol :: (Transport i, Transport o) => HeaderTransport i o -> IO Bool +tResetProtocol t = do + rBuf <- readIORef $ readBuffer t + writeIORef (clientType t) HeaderClient + readFrame t + +tSetProtocol :: (Transport i, Transport o) => HeaderTransport i o -> ProtocolType -> IO () +tSetProtocol t = writeIORef (protocolType t) + +transform :: HeaderTransport i o -> LBS.ByteString -> LBS.ByteString +transform t bs = + foldr applyTransform bs $ writeTransforms t + where + -- applyTransform bs ZlibTransform = + -- throw $ TransportExn "HeaderTransport: not implemented: ZlibTransform " TE_UNKNOWN + applyTransform bs _ = + throw $ TransportExn "HeaderTransport: Unknown transform" TE_UNKNOWN + +untransform :: HeaderTransport i o -> BS.ByteString -> IO BS.ByteString +untransform t bs = do + trans <- readIORef $ transforms t + return $ foldl unapplyTransform bs trans + where + -- unapplyTransform bs ZlibTransform = + -- throw $ TransportExn "HeaderTransport: not implemented: ZlibTransform " TE_UNKNOWN + unapplyTransform bs _ = + throw $ TransportExn "HeaderTransport: Unknown transform" TE_UNKNOWN + +instance (Transport i, Transport o) => Transport (HeaderTransport i o) where + tIsOpen t = do + tIsOpen (inTrans t) + tIsOpen (outTrans t) + + tClose t = do + tClose(outTrans t) + tClose(inTrans t) + + tRead t len = do + rBuf <- readIORef $ readBuffer t + if not $ LBS.null rBuf + then do + let (consumed, remain) = LBS.splitAt (fromIntegral len) rBuf + writeIORef (readBuffer t) remain + return consumed + else do + framed <- isFramed t + if not framed + then tRead (inTrans t) len + else do + ok <- readFrame t + if ok + then tRead t len + else return LBS.empty + + tPeek t = do + rBuf <- readIORef (readBuffer t) + if not $ LBS.null rBuf + then return $ Just $ LBS.head rBuf + else do + framed <- isFramed t + if not framed + then tPeek (inTrans t) + else do + ok <- readFrame t + if ok + then tPeek t + else return Nothing + + tWrite t buf = do + let wBuf = writeBuffer t + framed <- isFramed t + if framed + then modifyIORef wBuf (<> B.lazyByteString buf) + else + -- TODO: what should we do when switched to unframed in the middle ? + tWrite(outTrans t) buf + + tFlush t = do + cType <- readIORef $ clientType t + case cType of + Unframed -> tFlush $ outTrans t + Framed -> flushBuffer t id mempty + HeaderClient -> buildHeader t >>= flushBuffer t (transform t) + where + flushBuffer t f header = do + wBuf <- readIORef $ writeBuffer t + writeIORef (writeBuffer t) mempty + let payload = B.toLazyByteString (header <> wBuf) + tWrite (outTrans t) $ Binary.encode (fromIntegral $ LBS.length payload :: Int32) + tWrite (outTrans t) $ f payload + tFlush (outTrans t) diff --git a/lib/hs/thrift.cabal b/lib/hs/thrift.cabal index 9754ab2ee20..583067953ff 100644 --- a/lib/hs/thrift.cabal +++ b/lib/hs/thrift.cabal @@ -49,6 +49,7 @@ Library Thrift, Thrift.Arbitraries Thrift.Protocol, + Thrift.Protocol.Header, Thrift.Protocol.Binary, Thrift.Protocol.Compact, Thrift.Protocol.JSON, @@ -57,6 +58,7 @@ Library Thrift.Transport.Empty, Thrift.Transport.Framed, Thrift.Transport.Handle, + Thrift.Transport.Header, Thrift.Transport.HttpClient, Thrift.Transport.IOBuffer, Thrift.Transport.Memory, diff --git a/test/hs/TestClient.hs b/test/hs/TestClient.hs index d1ebb3cd076..93fb591b343 100644 --- a/test/hs/TestClient.hs +++ b/test/hs/TestClient.hs @@ -46,6 +46,7 @@ import Thrift.Transport.HttpClient import Thrift.Protocol import Thrift.Protocol.Binary import Thrift.Protocol.Compact +import Thrift.Protocol.Header import Thrift.Protocol.JSON data Options = Options @@ -85,12 +86,14 @@ getTransport t host port = do return (NoTransport $ "Unsupported transport: " ++ data ProtocolType = Binary | Compact | JSON + | Header deriving (Show, Eq) getProtocol :: String -> ProtocolType getProtocol "binary" = Binary getProtocol "compact" = Compact getProtocol "json" = JSON +getProtocol "header" = Header getProtocol p = error $ "Unsupported Protocol: " ++ p defaultOptions :: Options @@ -104,7 +107,7 @@ defaultOptions = Options , testLoops = 1 } -runClient :: (Protocol p, Transport t) => p t -> IO () +runClient :: Protocol p => p -> IO () runClient p = do let prot = (p,p) putStrLn "Starting Tests" @@ -266,6 +269,7 @@ main = do Binary -> runClient $ BinaryProtocol t Compact -> runClient $ CompactProtocol t JSON -> runClient $ JSONProtocol t + Header -> createHeaderProtocol t t >>= runClient runTest loops p t = do let client = makeClient p t replicateM_ loops client diff --git a/test/hs/TestServer.hs b/test/hs/TestServer.hs index 4a88649b81d..b7731ab1c40 100644 --- a/test/hs/TestServer.hs +++ b/test/hs/TestServer.hs @@ -48,6 +48,7 @@ import Thrift.Transport.Framed import Thrift.Transport.Handle import Thrift.Protocol.Binary import Thrift.Protocol.Compact +import Thrift.Protocol.Header import Thrift.Protocol.JSON data Options = Options @@ -90,11 +91,13 @@ getTransport t = NoTransport $ "Unsupported transport: " ++ t data ProtocolType = Binary | Compact | JSON + | Header getProtocol :: String -> ProtocolType getProtocol "binary" = Binary getProtocol "compact" = Compact getProtocol "json" = JSON +getProtocol "header" = Header getProtocol p = error $"Unsupported Protocol: " ++ p defaultOptions :: Options @@ -261,13 +264,19 @@ main = do t <- f socket return (p t, p t) + headerAcceptor f socket = do + t <- f socket + p <- createHeaderProtocol1 t + return (p, p) + doRunServer p f = do runThreadedServer (acceptor p f) TestHandler ThriftTest.process . PortNumber . fromIntegral runServer p f port = case p of - Binary -> do doRunServer BinaryProtocol f port - Compact -> do doRunServer CompactProtocol f port - JSON -> do doRunServer JSONProtocol f port + Binary -> doRunServer BinaryProtocol f port + Compact -> doRunServer CompactProtocol f port + JSON -> doRunServer JSONProtocol f port + Header -> runThreadedServer (headerAcceptor f) TestHandler ThriftTest.process (PortNumber $ fromIntegral port) parseFlags :: [String] -> Options -> Maybe Options parseFlags (flag : flags) opts = do diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index c96198808e5..754535f1213 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -229,6 +229,8 @@ "go-java_json_http-ip", "go-java_json_http-ip-ssl", "go-nodejs_json_framed-ip", + "hs-csharp_binary_framed-ip", + "hs-csharp_compact_framed-ip", "hs-dart_binary_framed-ip", "hs-dart_compact_framed-ip", "hs-dart_json_framed-ip", @@ -331,4 +333,4 @@ "rs-dart_compact_framed-ip", "rs-dart_multi-binary_framed-ip", "rs-dart_multic-compact_framed-ip" -] \ No newline at end of file +] diff --git a/test/tests.json b/test/tests.json index 35d0a6cc120..c4e07eefb1e 100644 --- a/test/tests.json +++ b/test/tests.json @@ -216,6 +216,7 @@ "ip" ], "protocols": [ + "header", "compact", "binary", "json" From 327ebb6c2b6df8bf075da02ef45a2a034e9b79ba Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 3 Dec 2017 18:27:58 +0100 Subject: [PATCH 068/756] Version 0.11.0 --- CHANGES | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index e0a3e0b8cc7..4009f264ce7 100644 --- a/CHANGES +++ b/CHANGES @@ -7,18 +7,8 @@ Thrift 0.11.0 * [THRIFT-2740] - Perl coding standards * [THRIFT-3610] - Streamline exception handling in Python server handler * [THRIFT-3686] - Java processor should report internal error on uncaught exception - * [THRIFT-4047] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4048] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types * [THRIFT-4049] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4050] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4051] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4052] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types * [THRIFT-4053] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4054] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4055] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4056] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4057] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4058] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types * [THRIFT-4136] - Align is_binary() method with is_string() to simplify those checks * [THRIFT-4137] - Fix remaining undefined behavior invalid vptr casts in Thrift Compiler * [THRIFT-4138] - Fix remaining undefined behavior invalid vptr casts in C++ library @@ -107,7 +97,6 @@ Thrift 0.11.0 * [THRIFT-4134] - Fix remaining undefined behavior invalid vptr casts * [THRIFT-4140] - Use of non-thread-safe function gmtime() * [THRIFT-4141] - Installation of haxe in docker files refers to a redirect link and fails - * [THRIFT-4146] - Appveyor builds are being triggered by apache master pushes * [THRIFT-4147] - Rust: protocol should accept transports with non-static lifetime * [THRIFT-4148] - [maven-thrift-plugin] compile error while import a thrift in dependency jar file. * [THRIFT-4149] - System.out pollutes log files @@ -193,7 +182,6 @@ Thrift 0.11.0 * [THRIFT-4376] - Coverity high impact issue resolution * [THRIFT-4377] - haxe. socket handles leak in TSimpleServer * [THRIFT-4381] - Wrong isset bitfield value after transmission - * [THRIFT-4384] - Using multiple services simultaneously is not thread-safe. * [THRIFT-4385] - Go remote client -u flag is broken * [THRIFT-4392] - compiler/..../plugin.thrift structs mis-ordered blows up ocaml generator * [THRIFT-4395] - Unable to build in the ubuntu-xenial docker image: clap 2.28 requires Rust 1.20 @@ -214,6 +202,7 @@ Thrift 0.11.0 * [THRIFT-3357] - Generate EnumSet/EnumMap where elements/keys are enums * [THRIFT-3369] - Implement SSL/TLS support on C with c_glib * [THRIFT-3467] - Go Maps for Thrift Sets Should Have Values of Type struct{} + * [THRIFT-3580] - THeader for Haskell * [THRIFT-3627] - Missing basic code style consistency of JavaScript. * [THRIFT-3706] - There's no support for Multiplexed protocol on c_glib library * [THRIFT-3766] - Add getUnderlyingTransport() to TZlibTransport @@ -223,7 +212,6 @@ Thrift 0.11.0 * [THRIFT-3859] - Unix Domain Socket Support in Objective-C * [THRIFT-3921] - C++ code should print enums as strings * [THRIFT-3926] - There should be an error emitted when http status code is not 200 - * [THRIFT-4000] - Add union test to Test Suite * [THRIFT-4007] - Micro-optimization of TTransport.py * [THRIFT-4040] - Add real cause of TNonblockingServerSocket error to exception * [THRIFT-4064] - Update node library dependencies @@ -240,7 +228,6 @@ Thrift 0.11.0 * [THRIFT-4126] - Validate objects in php extension * [THRIFT-4130] - Ensure Apache Http connection is released back to pool after use * [THRIFT-4151] - Thrift Mutex Contention Profiling (pthreads) should be disabled by default - * [THRIFT-4168] - Travis CI builds are being triggered by apache master pushes * [THRIFT-4176] - Implement a threaded and threadpool server type for Rust * [THRIFT-4183] - Named pipe client blocks forever on Open() when there is no server at the other end * [THRIFT-4190] - improve C# TThreadPoolServer defaults From 0d8da22dba430c379de04ff48e507e7277f4ea21 Mon Sep 17 00:00:00 2001 From: jfarrell Date: Wed, 11 Apr 2018 13:45:08 -0400 Subject: [PATCH 069/756] THRIFT-4546: Fix broken packagist.org Update composer to fix broken packagist.org imports --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9d6454ee12e..0f22b76eabb 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "0.11.0" + "dev-master": "1.0.x-dev" } } } From 858809fad01dba7318c33dc30f6cc92a6e2ac7b1 Mon Sep 17 00:00:00 2001 From: jfarrell Date: Wed, 11 Apr 2018 13:46:21 -0400 Subject: [PATCH 070/756] THRIFT-4546: Fix broken packagist.org Update composer to fix broken packagist.org imports --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d937bc7ac21..0f22b76eabb 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "0.10.0" + "dev-master": "1.0.x-dev" } } } From 7ac9e43ebcc4e65b4150aea83e85af19e22964a1 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Wed, 19 Dec 2018 22:12:32 -0500 Subject: [PATCH 071/756] THRIFT-2333: patch for ruby in rpmbuild --- contrib/thrift.spec | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/contrib/thrift.spec b/contrib/thrift.spec index 034ebc8796c..5cfe88802f2 100644 --- a/contrib/thrift.spec +++ b/contrib/thrift.spec @@ -178,6 +178,19 @@ export RUBYLIB=${PWD}/lib/rb/lib --without-csharp \ --without-erlang \ +%if 0%{!?without_ruby:1} +eval $(grep "^WITH_RUBY_TRUE" config.log) +if [[ "${WITH_RUBY_TRUE}" != "" ]]; then + set +x + echo "" + echo "configure determined that ruby requirements are missing (bundler gem?), either install missing components" >&2 + echo "or disable the ruby sub-packages as follows:" >&2 + echo " rpmbuild -D'%without_ruby 1' ..." >&2 + echo "" + exit 1 +fi +%endif + make %{?_smp_mflags} %if 0%{!?without_java:1} From 087d88108d34e3b08bc24eb555ec2d98b5293c31 Mon Sep 17 00:00:00 2001 From: Shaoyu Zhang Date: Sat, 22 Dec 2018 23:12:01 +0800 Subject: [PATCH 072/756] THRIFT-4684: Fix WCF related C# code generation Client: C# Complete the namespace in System.ServiceModel in WCF related code. Also when generating fields in fault classes, we follow the same behavior in normal struct, to avoid generating unused private fields, when auto properties are also generated. --- .../src/thrift/generate/t_csharp_generator.cc | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc index 37d6f9dd95e..9d1e29e156a 100644 --- a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc @@ -422,7 +422,7 @@ string t_csharp_generator::csharp_type_usings() { + ((async_) ? "using System.Threading.Tasks;\n" : "") + "using Thrift;\n" + "using Thrift.Collections;\n" + ((serialize_ || wcf_) ? "#if !SILVERLIGHT\n" : "") + ((serialize_ || wcf_) ? "using System.Xml.Serialization;\n" : "") - + ((serialize_ || wcf_) ? "#endif\n" : "") + (wcf_ ? "//using System.ServiceModel;\n" : "") + + ((serialize_ || wcf_) ? "#endif\n" : "") + "using System.Runtime.Serialization;\n"; } @@ -903,7 +903,10 @@ void t_csharp_generator::generate_csharp_wcffault(ostream& out, t_struct* tstruc // make private members with public Properties for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - indent(out) << "private " << declare_field(*m_iter, false, "_") << endl; + // if the field is requied, then we use auto-properties + if (!field_is_required((*m_iter)) && (!nullable_ || field_has_default((*m_iter)))) { + indent(out) << "private " << declare_field(*m_iter, false, "_") << endl; + } } out << endl; @@ -1475,7 +1478,7 @@ void t_csharp_generator::generate_sync_service_interface(t_service* tservice) { generate_csharp_doc(f_service_, tservice); if (wcf_) { - indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; + indent(f_service_) << "[System.ServiceModel.ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; } indent(f_service_) << "public interface ISync" << extends_iface << " {" << endl; @@ -1487,12 +1490,12 @@ void t_csharp_generator::generate_sync_service_interface(t_service* tservice) { // if we're using WCF, add the corresponding attributes if (wcf_) { - indent(f_service_) << "[OperationContract]" << endl; + indent(f_service_) << "[System.ServiceModel.OperationContract]" << endl; const std::vector& xceptions = (*f_iter)->get_xceptions()->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - indent(f_service_) << "[FaultContract(typeof(" + indent(f_service_) << "[System.ServiceModel.FaultContract(typeof(" + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl; } } @@ -1514,7 +1517,7 @@ void t_csharp_generator::generate_async_service_interface(t_service* tservice) { generate_csharp_doc(f_service_, tservice); if (wcf_) { - indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; + indent(f_service_) << "[System.ServiceModel.ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; } indent(f_service_) << "public interface IAsync" << extends_iface << " {" << endl; @@ -1526,12 +1529,12 @@ void t_csharp_generator::generate_async_service_interface(t_service* tservice) { // if we're using WCF, add the corresponding attributes if (wcf_) { - indent(f_service_) << "[OperationContract]" << endl; + indent(f_service_) << "[System.ServiceModel.OperationContract]" << endl; const std::vector& xceptions = (*f_iter)->get_xceptions()->get_members(); vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - indent(f_service_) << "[FaultContract(typeof(" + indent(f_service_) << "[System.ServiceModel.FaultContract(typeof(" + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl; } } @@ -1552,7 +1555,7 @@ void t_csharp_generator::generate_combined_service_interface(t_service* tservice generate_csharp_doc(f_service_, tservice); if (wcf_) { - indent(f_service_) << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; + indent(f_service_) << "[System.ServiceModel.ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; } indent(f_service_) << "public interface Iface" << extends_iface << " {" << endl; From a597725bcbfc261caae834fd763dd3734ab1ffce Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 27 Dec 2018 10:53:05 -0500 Subject: [PATCH 073/756] THRIFT-4426: remove a symbolic link that was checked in --- tutorial/erl/server.sh | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) mode change 120000 => 100755 tutorial/erl/server.sh diff --git a/tutorial/erl/server.sh b/tutorial/erl/server.sh deleted file mode 120000 index 26b3c58e44d..00000000000 --- a/tutorial/erl/server.sh +++ /dev/null @@ -1 +0,0 @@ -client.sh \ No newline at end of file diff --git a/tutorial/erl/server.sh b/tutorial/erl/server.sh new file mode 100755 index 00000000000..775afb62d54 --- /dev/null +++ b/tutorial/erl/server.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +ERL_THRIFT=../../lib/erl + +if ! [ -d ${ERL_THRIFT}/ebin ]; then + echo "Please build the Thrift library by running \`make' in ${ERL_THRIFT}" + exit 1 +fi + +if ! [ -d gen-erl ]; then + ../../compiler/cpp/thrift -r --gen erl ../tutorial.thrift +fi + + +erlc -I ${ERL_THRIFT}/include -I ${ERL_THRIFT}/ebin \ + -I gen-erl -o gen-erl gen-erl/*.erl && + erlc -I ${ERL_THRIFT}/include -I gen-erl *.erl && + erl +K true -pa ${ERL_THRIFT}/ebin -pa gen-erl From f9f037bd5a9776ff1f7e28b530418299d102d8d3 Mon Sep 17 00:00:00 2001 From: Allen George Date: Thu, 27 Dec 2018 13:56:21 -0500 Subject: [PATCH 074/756] Update Cargo.toml, release instructions and release script Client: rs --- lib/rs/Cargo.toml | 2 +- lib/rs/RELEASING.md | 57 +++++++++++++++++++++++++++++++++++++++++++++ lib/rs/release.sh | 26 +++++++++++++++++++++ 3 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 lib/rs/RELEASING.md create mode 100755 lib/rs/release.sh diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml index f5844b42a80..ed32179af2b 100644 --- a/lib/rs/Cargo.toml +++ b/lib/rs/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Apache Thrift Developers "] homepage = "http://thrift.apache.org" documentation = "https://thrift.apache.org" readme = "README.md" -exclude = ["Makefile*", "test/**"] +exclude = ["Makefile*", "test/**", "*.iml"] keywords = ["thrift"] [dependencies] diff --git a/lib/rs/RELEASING.md b/lib/rs/RELEASING.md new file mode 100644 index 00000000000..073d7a02a71 --- /dev/null +++ b/lib/rs/RELEASING.md @@ -0,0 +1,57 @@ +# Publishing the thrift crate + +Publishing the Rust thrift crate is straightforward, and involves two major steps: + +1. Setting up your [crates.io](https://www.crates.io) account _(one-time)_ + +2. Packaging/publishing the Rust thrift crate itself + +## Set up your crates.io account (one-time) + +1. Go to [crates.io](https://www.crates.io) and click the `Log In` button at the top right. + + Log in **as the Github user with write permissions to the thrift repo!** + +2. Click your user icon button at the top right and select `Account Settings`. + +3. Click `New Token` next to `API Access`. + + This generates a new API key that cargo uses to publish packages to crates.io. + Store this API key somewhere safe. If you will only use this Github account to + publish crates to crates.io you can follow the instructions to save the + generated key to `~/.cargo/credentials`. + +## Package and Publish + +You can use the automated script or run the release steps manually. + +**Important**: `cargo` expects that version numbers follow the semantic versioning format. +This means that `THRIFT_RELEASE_VERSION` must have a major, minor and patch number, i.e., must +be in the form `#.##.##`. + +#### Automated + +Run `./release.sh [THRIFT_RELEASE_VERSION]`. + +_Requires you to have stored your credentials in `~/.cargo/credentials`._ + +#### Manual + +1. Edit `Cargo.toml` and update the `version = 1.0` key to `version = [THRIFT_RELEASE_VERSION]` + +2. `git add Cargo.toml` + +3. `git commit -m "Update thrift crate version to [THRIFT_RELEASE_VERSION]" -m "Client: rs"` + +4. `cargo login` + + _(not required if you have stored your credentials in `~/.cargo/credentials`)_ + +5. `cargo clean` + +6. `cargo package` + + This step fails if there are any uncommitted or ignored files. Do **not** use the `--allow-dirty` + flag! Instead, add the highlighted files as entries in the `Cargo.toml` `exclude` key. + +7. `cargo publish` diff --git a/lib/rs/release.sh b/lib/rs/release.sh new file mode 100755 index 00000000000..c4e5b48928d --- /dev/null +++ b/lib/rs/release.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +set -o errexit +set -o pipefail +set -o nounset + +if ! [[ $# -eq 1 && $1 =~ ^[0-9](\.[0-9][0-9]*){2}$ ]]; then + (>&2 echo "Usage: ./publish-crate.sh [THRIFT_RELEASE_VERSION] ") + (>&2 echo " THRIFT_RELEASE_VERSION is in semantic versioning format, i.e. #.##.##") + exit 1 +fi + +THRIFT_RELEASE_VERSION=${1:-} + +echo "Updating Cargo.toml to ${THRIFT_RELEASE_VERSION}" +sed -i.old -e "s/^version = .*$/version = \"${THRIFT_RELEASE_VERSION}\"/g" Cargo.toml +rm Cargo.toml.old + +echo "Committing updated Cargo.toml" +git add Cargo.toml +git commit -m "Update thrift crate version to ${THRIFT_RELEASE_VERSION}" -m "Client: rs" + +echo "Packaging and releasing rust thrift crate with version ${THRIFT_RELEASE_VERSION}" +cargo clean +cargo package +cargo publish From a139082755369611ed243376ec3c4161452369fc Mon Sep 17 00:00:00 2001 From: Robert Lu Date: Thu, 27 Dec 2018 23:57:35 +0800 Subject: [PATCH 075/756] THRIFT-4546: replace all git-wip-us.apache.org to github.com --- bower.json | 2 +- contrib/fb303/java/build.xml | 6 +++--- debian/control | 4 ++-- doap.rdf | 4 ++-- doc/committers.md | 2 +- doc/install/centos.md | 2 +- doc/specs/idl.md | 4 ++-- lib/as3/build.xml | 6 +++--- lib/java/gradle/publishing.gradle | 6 +++--- lib/js/test/test-deep-constructor.html | 2 +- lib/js/test/test-es6.html | 2 +- lib/js/test/test-nojq.html | 2 +- lib/js/test/test.html | 2 +- lib/js/test/testws.html | 2 +- package.json | 2 +- sonar-project.properties | 2 +- tutorial/js/tutorial.html | 2 +- 17 files changed, 26 insertions(+), 26 deletions(-) diff --git a/bower.json b/bower.json index 1092c650e98..6f3c126a840 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "thrift", - "homepage": "https://git-wip-us.apache.org/repos/asf/thrift.git", + "homepage": "https://github.com/apache/thrift.git", "authors": [ "Apache Thrift " ], diff --git a/contrib/fb303/java/build.xml b/contrib/fb303/java/build.xml index 591a4cbd0aa..7a1b8f10543 100755 --- a/contrib/fb303/java/build.xml +++ b/contrib/fb303/java/build.xml @@ -136,9 +136,9 @@ - diff --git a/debian/control b/debian/control index cb8a3764f17..9818a37a23a 100644 --- a/debian/control +++ b/debian/control @@ -11,8 +11,8 @@ Build-Depends: debhelper (>= 9), build-essential, mono-mcs, python-dev, ant, php (>= 5), php-dev (>= 5), libglib2.0-dev, qtchooser, qtbase5-dev-tools Maintainer: Thrift Developer's Homepage: http://thrift.apache.org/ -Vcs-Git: https://git-wip-us.apache.org/repos/asf/thrift.git -Vcs-Browser: https://git-wip-us.apache.org/repos/asf?p=thrift.git +Vcs-Git: https://github.com/apache/thrift.git +Vcs-Browser: https://github.com/apache/thrift Standards-Version: 3.9.7 X-Python-Version: >= 2.6 X-Python3-Version: >= 3.3 diff --git a/doap.rdf b/doap.rdf index 75274aa7b0d..91231554a2f 100755 --- a/doap.rdf +++ b/doap.rdf @@ -126,8 +126,8 @@ - - + + diff --git a/doc/committers.md b/doc/committers.md index b02edbe00d2..dcdd7b791c9 100644 --- a/doc/committers.md +++ b/doc/committers.md @@ -4,7 +4,7 @@ 1. Check out the latest version of the source code - * git clone https://git-wip-us.apache.org/repos/asf/thrift.git thrift + * git clone https://github.com/apache/thrift.git thrift 1. Apply the patch diff --git a/doc/install/centos.md b/doc/install/centos.md index 609e118ead0..04932c20a7e 100644 --- a/doc/install/centos.md +++ b/doc/install/centos.md @@ -64,7 +64,7 @@ If you will be developing Apache Thrift clients/servers in C++ you will also nee ## Build and Install the Apache Thrift IDL Compiler - git clone https://git-wip-us.apache.org/repos/asf/thrift.git + git clone https://github.com/apache/thrift.git cd thrift ./bootstrap.sh ./configure --with-lua=no diff --git a/doc/specs/idl.md b/doc/specs/idl.md index dab04c7692b..bf22f5477f2 100644 --- a/doc/specs/idl.md +++ b/doc/specs/idl.md @@ -242,9 +242,9 @@ Here are some examples of Thrift definitions, using the Thrift IDL: * [Apache Cassandra's][] Thrift IDL: [cassandra.thrift][] * [Evernote API][] - [ThriftTest.thrift]: https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob_plain;f=test/ThriftTest.thrift;hb=HEAD + [ThriftTest.thrift]: https://raw.githubusercontent.com/apache/thrift/master/test/ThriftTest.thrift [tutorial]: /tutorial/ - [fb303.thrift]: https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob_plain;f=contrib/fb303/if/fb303.thrift;hb=HEAD + [fb303.thrift]: https://raw.githubusercontent.com/apache/thrift/master/contrib/fb303/if/fb303.thrift [Apache Cassandra's]: http://cassandra.apache.org/ [cassandra.thrift]: http://svn.apache.org/viewvc/cassandra/trunk/interface/cassandra.thrift?view=co [Evernote API]: http://www.evernote.com/about/developer/api/ diff --git a/lib/as3/build.xml b/lib/as3/build.xml index 2b374ddde43..b0c4c858ddf 100755 --- a/lib/as3/build.xml +++ b/lib/as3/build.xml @@ -122,9 +122,9 @@ - diff --git a/lib/java/gradle/publishing.gradle b/lib/java/gradle/publishing.gradle index 961d58f7820..6b0404373d1 100644 --- a/lib/java/gradle/publishing.gradle +++ b/lib/java/gradle/publishing.gradle @@ -61,9 +61,9 @@ def configurePom(pom) { url 'http://thrift.apache.org' scm { - url 'https://git-wip-us.apache.org/repos/asf?p=thrift.git' - connection 'scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git' - developerConnection 'scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git' + url 'https://github.com/apache/thrift.git' + connection 'scm:git:https://github.com/apache/thrift.git' + developerConnection 'scm:git:https://github.com/apache/thrift.git' } licenses { diff --git a/lib/js/test/test-deep-constructor.html b/lib/js/test/test-deep-constructor.html index 4c5fb02e4ef..dfc0da62d1a 100755 --- a/lib/js/test/test-deep-constructor.html +++ b/lib/js/test/test-deep-constructor.html @@ -35,7 +35,7 @@ -

Thrift Javascript Bindings: Deep Constructor Test (JsDeepConstructorTest.thrift)

+

Thrift Javascript Bindings: Deep Constructor Test (JsDeepConstructorTest.thrift)

diff --git a/lib/js/test/test-es6.html b/lib/js/test/test-es6.html index 5f55da78ee7..bf04901e045 100644 --- a/lib/js/test/test-es6.html +++ b/lib/js/test/test-es6.html @@ -46,7 +46,7 @@ -

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

+

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

diff --git a/lib/js/test/test-nojq.html b/lib/js/test/test-nojq.html index 9eec7fcd3f1..408424ed572 100644 --- a/lib/js/test/test-nojq.html +++ b/lib/js/test/test-nojq.html @@ -35,7 +35,7 @@ -

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

+

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

diff --git a/lib/js/test/test.html b/lib/js/test/test.html index af035b6ecca..8b67014bb9f 100755 --- a/lib/js/test/test.html +++ b/lib/js/test/test.html @@ -38,7 +38,7 @@ -

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

+

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

diff --git a/lib/js/test/testws.html b/lib/js/test/testws.html index 1edf0e07a95..184500ff97d 100644 --- a/lib/js/test/testws.html +++ b/lib/js/test/testws.html @@ -46,7 +46,7 @@ -

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

+

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

diff --git a/package.json b/package.json index d641979d829..6d548d7afbf 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "homepage": "http://thrift.apache.org/", "repository": { "type": "git", - "url": "https://git-wip-us.apache.org/repos/asf/thrift.git" + "url": "https://github.com/apache/thrift.git" }, "version": "1.0.0-dev", "author": { diff --git a/sonar-project.properties b/sonar-project.properties index aebeff0c017..06e97ae8ddd 100755 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -31,7 +31,7 @@ sonar.language=java,js,c++,py,c sonar.sourceEncoding=UTF-8 # scm -sonar.scm.url=scm:git:https://git-wip-us.apache.org/repos/asf/thrift +sonar.scm.url=scm:git:https://github.com/apache/thrift.git # cppcheck -q --error-exitcode=0 --xml . 2> cppcheck-result.xml sonar.cxx.cppcheck.reportPath=cppcheck-result.xml diff --git a/tutorial/js/tutorial.html b/tutorial/js/tutorial.html index d7f3945f2ed..d020bed3734 100755 --- a/tutorial/js/tutorial.html +++ b/tutorial/js/tutorial.html @@ -98,7 +98,7 @@

Thrift Javascript Bindings

-

This Java Script example uses tutorial.thrift and a Thrift server using JSON protocol and HTTP transport. +

This Java Script example uses tutorial.thrift and a Thrift server using JSON protocol and HTTP transport.

Date: Sun, 30 Dec 2018 11:09:34 -0500 Subject: [PATCH 076/756] fix top level bower.json file - bad merge from release branch --- bower.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/bower.json b/bower.json index ff70611b78a..436a2cf356b 100644 --- a/bower.json +++ b/bower.json @@ -1,11 +1,7 @@ { "name": "thrift", -<<<<<<< HEAD + "version": "1.0.0", "homepage": "https://github.com/apache/thrift.git", -======= - "version": "0.12.0", - "homepage": "https://git-wip-us.apache.org/repos/asf/thrift.git", ->>>>>>> origin/0.12.0 "authors": [ "Apache Thrift " ], From 3671b8bce9668d680c179db0ba38f7e4df0ff3e6 Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Sun, 30 Dec 2018 20:25:00 -0500 Subject: [PATCH 077/756] Use case-switch Statement Instead of if-else Clauses --- .../thrift/server/AbstractNonblockingServer.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java b/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java index 5c62b991d41..8c206e42741 100644 --- a/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java +++ b/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java @@ -435,17 +435,23 @@ public boolean write() { * has come in. */ public void changeSelectInterests() { - if (state_ == FrameBufferState.AWAITING_REGISTER_WRITE) { + switch (state_) { + case AWAITING_REGISTER_WRITE: // set the OP_WRITE interest selectionKey_.interestOps(SelectionKey.OP_WRITE); state_ = FrameBufferState.WRITING; - } else if (state_ == FrameBufferState.AWAITING_REGISTER_READ) { + break; + case AWAITING_REGISTER_READ: prepareRead(); - } else if (state_ == FrameBufferState.AWAITING_CLOSE) { + break; + case AWAITING_CLOSE: close(); selectionKey_.cancel(); - } else { - LOGGER.error("changeSelectInterest was called, but state is invalid (" + state_ + ")"); + break; + default: + LOGGER.error( + "changeSelectInterest was called, but state is invalid ({})", + state_); } } From 75bac10dbd8d953bb2f556b7dcc3bdf7518e67a6 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sun, 30 Dec 2018 16:20:12 -0500 Subject: [PATCH 078/756] THRIFT-4690: update bionic docker image to use upstream deimos OpenSSL 1.1 tag for dlang --- build/docker/ubuntu-bionic/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index a8c1417ac9f..4f53ca4cdd7 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -113,10 +113,10 @@ RUN \ mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf libevent-master && \ - curl -sSL https://github.com/jeking3/openssl/archive/tls_method.tar.gz| tar xz && \ - mv openssl-tls_method/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ - mv openssl-tls_method/C/* /usr/include/dmd/druntime/import/C/ && \ - rm -rf openssl-tls_method + git clone -b 'v2.0.0+1.1.0h' https://github.com/D-Programming-Deimos/openssl.git deimos-openssl-1.1.0h && \ + mv deimos-openssl-1.1.0h/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ + mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \ + rm -rf deimos-openssl-1.1.0h RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ From bf51a9faf9942571cf1eea64ae260a9ced5c4598 Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Sun, 30 Dec 2018 20:34:13 -0500 Subject: [PATCH 079/756] THRIFT-4695: Pre-Size Java Collections in Union --- lib/java/src/org/apache/thrift/TUnion.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/java/src/org/apache/thrift/TUnion.java b/lib/java/src/org/apache/thrift/TUnion.java index 13f9c6774ef..1ef11df49a9 100644 --- a/lib/java/src/org/apache/thrift/TUnion.java +++ b/lib/java/src/org/apache/thrift/TUnion.java @@ -79,7 +79,7 @@ private static Object deepCopyObject(Object o) { } private static Map deepCopyMap(Map map) { - Map copy = new HashMap(); + Map copy = new HashMap(map.size()); for (Map.Entry entry : map.entrySet()) { copy.put(deepCopyObject(entry.getKey()), deepCopyObject(entry.getValue())); } @@ -87,7 +87,7 @@ private static Map deepCopyMap(Map map) { } private static Set deepCopySet(Set set) { - Set copy = new HashSet(); + Set copy = new HashSet(set.size()); for (Object o : set) { copy.add(deepCopyObject(o)); } From 138a81d5b401b57ee4883879f94b10ba4f935453 Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Mon, 31 Dec 2018 11:38:15 -0500 Subject: [PATCH 080/756] THRIFT-4704: Streamline TDeserializer Implementation --- .../src/org/apache/thrift/TDeserializer.java | 59 +++++++------------ 1 file changed, 20 insertions(+), 39 deletions(-) diff --git a/lib/java/src/org/apache/thrift/TDeserializer.java b/lib/java/src/org/apache/thrift/TDeserializer.java index bf6c97c9d9b..d1d39660926 100644 --- a/lib/java/src/org/apache/thrift/TDeserializer.java +++ b/lib/java/src/org/apache/thrift/TDeserializer.java @@ -251,48 +251,31 @@ private Object partialDeserializeField(byte ttype, byte[] bytes, TFieldIdEnum fi 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){ + if (ttype == field.type) { + // 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; + return protocol_.readBool(); case TType.BYTE: - if (field.type == TType.BYTE) { - return protocol_.readByte(); - } - break; + return protocol_.readByte(); case TType.DOUBLE: - if (field.type == TType.DOUBLE) { - return protocol_.readDouble(); - } - break; + return protocol_.readDouble(); case TType.I16: - if (field.type == TType.I16) { - return protocol_.readI16(); - } - break; + return protocol_.readI16(); case TType.I32: - if (field.type == TType.I32) { - return protocol_.readI32(); - } - break; + return protocol_.readI32(); case TType.I64: - if (field.type == TType.I64) { - return protocol_.readI64(); - } - break; + return protocol_.readI64(); 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 protocol_.readString(); + default: + return null; + } + } + // hack to differentiate between string and binary + if (ttype == 100 && field.type == TType.STRING) { + return protocol_.readBinary(); } } return null; @@ -307,11 +290,9 @@ private Object partialDeserializeField(byte ttype, byte[] bytes, TFieldIdEnum fi private TField locateField(byte[] bytes, TFieldIdEnum fieldIdPathFirst, TFieldIdEnum ... fieldIdPathRest) throws TException { trans_.reset(bytes); - TFieldIdEnum[] fieldIdPath= new TFieldIdEnum[fieldIdPathRest.length + 1]; + TFieldIdEnum[] fieldIdPath = new TFieldIdEnum[fieldIdPathRest.length + 1]; fieldIdPath[0] = fieldIdPathFirst; - for (int i = 0; i < fieldIdPathRest.length; i++){ - fieldIdPath[i + 1] = fieldIdPathRest[i]; - } + System.arraycopy(fieldIdPathRest, 0, fieldIdPath, 1, fieldIdPathRest.length); // index into field ID path being currently searched for int curPathIndex = 0; From 0e99ee31ba25ee0b2b8eecea44b7208318cf3f56 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 31 Dec 2018 17:29:50 -0500 Subject: [PATCH 081/756] remove unused travis build files --- build/travis/installCXXDependencies.sh | 29 ----------- build/travis/installDependencies.sh | 66 -------------------------- 2 files changed, 95 deletions(-) delete mode 100755 build/travis/installCXXDependencies.sh delete mode 100755 build/travis/installDependencies.sh diff --git a/build/travis/installCXXDependencies.sh b/build/travis/installCXXDependencies.sh deleted file mode 100755 index ac3edf381aa..00000000000 --- a/build/travis/installCXXDependencies.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/sh - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - - -# Mainly aiming Travis CI's Ubuntu machines for now -# see what we need: http://thrift.apache.org/docs/install/ubuntu - -# General dependencies -sudo apt-add-repository "deb http://archive.ubuntu.com/ubuntu/ trusty main restricted" -y -sudo apt-get update -qq - -sudo apt-get install -qq libpango-1.0-0 libqt4-dev qtbase5-dev qtbase5-dev-tools qt5-default libboost-dev libboost-test-dev libboost-program-options-dev libboost-system-dev libboost-filesystem-dev libboost-thread-dev libevent-dev automake libtool flex bison pkg-config g++ libssl-dev make cmake git debhelper bc nsis ninja-build -dpkg -S /usr/include/boost/version.hpp diff --git a/build/travis/installDependencies.sh b/build/travis/installDependencies.sh deleted file mode 100755 index eab8c6b6be8..00000000000 --- a/build/travis/installDependencies.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. - -SCRIPTPATH=$( cd $(dirname $0) ; pwd -P ) - -# Mainly aiming Travis CI's Ubuntu machines for now -# see what we need: http://thrift.apache.org/docs/install/ubuntu - -# Java dependencies -sudo apt-get install -qq ant openjdk-7-jdk -sudo update-java-alternatives -s java-1.7.0-openjdk-amd64 - -# Python dependencies -sudo apt-get install -qq python-all python-all-dev python-all-dbg python-setuptools python-support python-twisted python-six python3-six - -# Ruby dependencies -sudo apt-get install -qq ruby ruby-dev -sudo gem install bundler rake - -# Perl dependencies -sudo apt-get install -qq libbit-vector-perl libclass-accessor-class-perl libio-socket-ssl-perl libnet-ssleay-perl libcrypt-ssleay-perl - -# Php dependencies -sudo apt-get install -qq php5 php5-dev php5-cli php-pear re2c - -# GlibC dependencies -sudo apt-get install -qq libglib2.0-dev - -# Erlang dependencies -sudo apt-get install -qq erlang-base erlang-eunit erlang-dev erlang-tools rebar - -# GO dependencies -echo "golang-go golang-go/dashboard boolean false" | debconf-set-selections -sudo apt-get -y install -qq golang golang-go - -# Haskell dependencies -sudo add-apt-repository -y ppa:hvr/ghc -sudo apt-get update -sudo apt-get install cabal-install-1.20 ghc-$GHCVER - -# Lua dependencies -sudo apt-get install -qq lua5.2 lua5.2-dev - -# Node.js dependencies -sudo apt-get install -qq nodejs nodejs-dev npm -sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10 - -# CSharp -sudo apt-get install -qq mono-gmcs mono-devel libmono-system-web2.0-cil -sudo apt-get install -qq mingw32 mingw32-binutils mingw32-runtime nsis From 4c71660dab62f2ac08ab7d81b41053fdaf2cdeb9 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 1 Jan 2019 19:28:23 -0500 Subject: [PATCH 082/756] THRIFT-4705: add nuget configuration file --- ApacheThrift.nuspec | 50 +++++++++++++++++++++++++++++++++ lib/csharp/Makefile.am | 4 +++ lib/csharp/src/Thrift.45.csproj | 4 +-- lib/csharp/src/Thrift.csproj | 11 ++++---- 4 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 ApacheThrift.nuspec diff --git a/ApacheThrift.nuspec b/ApacheThrift.nuspec new file mode 100644 index 00000000000..54ed2c64a94 --- /dev/null +++ b/ApacheThrift.nuspec @@ -0,0 +1,50 @@ + + + + + + + ApacheThrift + 1.0.0 + Apache Thrift 1.0.0 + Apache Thrift Developers + Apache Software Foundation + Apache-2.0 + http://thrift.apache.org/ + true +

Apache Thrift .NET Library + + Contains runtime libraries from lib/csharp for net35 and net45 frameworks, + and from lib/netcore for netstandard2.0 framework development. + + + Apache Thrift RPC + + + + + + + \ No newline at end of file diff --git a/lib/csharp/Makefile.am b/lib/csharp/Makefile.am index be49d5ecd82..56a8b0f54f4 100644 --- a/lib/csharp/Makefile.am +++ b/lib/csharp/Makefile.am @@ -109,3 +109,7 @@ EXTRA_DIST = \ test \ coding_standards.md \ README.md + +MAINTAINERCLEANFILES = \ + Makefile \ + Makefile.in diff --git a/lib/csharp/src/Thrift.45.csproj b/lib/csharp/src/Thrift.45.csproj index 455916f8338..4e28b25110e 100644 --- a/lib/csharp/src/Thrift.45.csproj +++ b/lib/csharp/src/Thrift.45.csproj @@ -31,7 +31,7 @@
true - full + portable false bin\Debug\ TRACE;DEBUG;NET45 @@ -39,7 +39,7 @@ 4 - pdbonly + portable true bin\Release\ TRACE;NET45 diff --git a/lib/csharp/src/Thrift.csproj b/lib/csharp/src/Thrift.csproj index 2a469eddabe..bf65569c908 100644 --- a/lib/csharp/src/Thrift.csproj +++ b/lib/csharp/src/Thrift.csproj @@ -52,19 +52,20 @@ true - full + portable false bin\Debug\ - DEBUG;TRACE + TRACE;DEBUG prompt 4 AllRules.ruleset - pdbonly + portable true bin\Release\ - TRACE + + prompt 4 AllRules.ruleset @@ -153,4 +154,4 @@ -
+
\ No newline at end of file From df9c60d38f0255ea08ea0a5aeba1abc4a0ccf04d Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Tue, 1 Jan 2019 14:43:23 -0500 Subject: [PATCH 083/756] THRIFT-4711: Improve Immutable None Type Instantiation --- lib/java/src/org/apache/thrift/Option.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/java/src/org/apache/thrift/Option.java b/lib/java/src/org/apache/thrift/Option.java index db25ec51314..d5cd309e89a 100644 --- a/lib/java/src/org/apache/thrift/Option.java +++ b/lib/java/src/org/apache/thrift/Option.java @@ -24,6 +24,9 @@ */ public abstract class Option { + @SuppressWarnings("rawtypes") + private static final Option NONE = new None(); + /** * Whether the Option is defined or not * @return @@ -87,7 +90,7 @@ public T get() { } public String toString() { - return "Some("+value.toString()+")"; + return "Some(" + value + ")"; } } @@ -99,9 +102,9 @@ public String toString() { */ public static Option fromNullable(T value) { if (value != null) { - return new Some(value); + return some(value); } else { - return new None(); + return none(); } } @@ -115,7 +118,8 @@ public static Some some(T value) { return new Some(value); } + @SuppressWarnings("unchecked") public static None none() { - return new None(); + return (None) NONE; } } \ No newline at end of file From 1c6914d5c51da5a0a1d92453bfad549831f313d5 Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Tue, 1 Jan 2019 18:32:04 -0500 Subject: [PATCH 084/756] THRIFT-4713: Review of TBaseHelper --- .../src/org/apache/thrift/TBaseHelper.java | 132 ++++++------------ 1 file changed, 46 insertions(+), 86 deletions(-) diff --git a/lib/java/src/org/apache/thrift/TBaseHelper.java b/lib/java/src/org/apache/thrift/TBaseHelper.java index 559df339d93..6f6c6ebf55e 100644 --- a/lib/java/src/org/apache/thrift/TBaseHelper.java +++ b/lib/java/src/org/apache/thrift/TBaseHelper.java @@ -25,10 +25,11 @@ 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.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; public final class TBaseHelper { @@ -53,57 +54,27 @@ public static int compareTo(Object o1, Object o2) { } public static int compareTo(boolean a, boolean b) { - return Boolean.valueOf(a).compareTo(b); + return Boolean.compare(a, b); } public static int compareTo(byte a, byte b) { - if (a < b) { - return -1; - } else if (b < a) { - return 1; - } else { - return 0; - } + return Byte.compare(a, b); } public static int compareTo(short a, short b) { - if (a < b) { - return -1; - } else if (b < a) { - return 1; - } else { - return 0; - } + return Short.compare(a,b); } public static int compareTo(int a, int b) { - if (a < b) { - return -1; - } else if (b < a) { - return 1; - } else { - return 0; - } + return Integer.compare(a, b); } public static int compareTo(long a, long b) { - if (a < b) { - return -1; - } else if (b < a) { - return 1; - } else { - return 0; - } + return Long.compare(a, b); } public static int compareTo(double a, double b) { - if (a < b) { - return -1; - } else if (b < a) { - return 1; - } else { - return 0; - } + return Double.compare(a, b); } public static int compareTo(String a, String b) { @@ -111,17 +82,16 @@ public static int compareTo(String a, String 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; + int compare = compareTo(a.length, b.length); + if (compare == 0) { + for (int i = 0; i < a.length; i++) { + compare = compareTo(a[i], b[i]); + if (compare != 0) { + break; + } } } - return 0; + return compare; } public static int compareTo(Comparable a, Comparable b) { @@ -129,41 +99,39 @@ public static int compareTo(Comparable a, Comparable 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; + int compare = compareTo(a.size(), b.size()); + if (compare == 0) { + for (int i = 0; i < a.size(); i++) { + compare = comparator.compare(a.get(i), b.get(i)); + if (compare != 0) { + break; + } } } - return 0; + return compare; } 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; + int compare = compareTo(a.size(), b.size()); + if (compare == 0) { + ArrayList sortedA = new ArrayList(a); + ArrayList sortedB = new ArrayList(b); + + Collections.sort(sortedA, comparator); + Collections.sort(sortedB, comparator); + + Iterator iterA = sortedA.iterator(); + Iterator iterB = sortedB.iterator(); + + // Compare each item. + while (iterA.hasNext() && iterB.hasNext()) { + compare = comparator.compare(iterA.next(), iterB.next()); + if (compare != 0) { + break; + } } } - - return 0; + return compare; } public static int compareTo(Map a, Map b) { @@ -316,22 +284,14 @@ public static ByteBuffer copyBinary(final ByteBuffer orig) { } 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; + return (orig == null) ? null : Arrays.copyOf(orig, orig.length); } public static int hashCode(long value) { - int low = (int) value; - int high = (int) (value >>> 32); - return high * 127 + low; + return Long.hashCode(value); } public static int hashCode(double value) { - return hashCode(Double.doubleToRawLongBits(value)); + return Double.hashCode(value); } } From a3a7c6c7890b742379db5691f000fb242469af0e Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 31 Dec 2018 17:17:34 -0500 Subject: [PATCH 085/756] THRIFT-4547: add swift to bionic build image and run unit tests --- .gitignore | 1 + build/docker/ubuntu-bionic/Dockerfile | 7 ++++ configure.ac | 21 ++++++++++++ lib/Makefile.am | 4 +++ lib/swift/Makefile.am | 46 +++++++++++++++++++++++++++ lib/swift/README.md | 1 - 6 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 lib/swift/Makefile.am diff --git a/.gitignore b/.gitignore index b7f7b454bb2..b3a5920f2ba 100644 --- a/.gitignore +++ b/.gitignore @@ -285,6 +285,7 @@ project.lock.json /lib/rs/test/src/ultimate.rs /lib/rs/*.iml /lib/rs/**/*.iml +/lib/swift/.build /libtool /ltmain.sh /missing diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index 4f53ca4cdd7..5ad4c845e55 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -250,6 +250,13 @@ RUN apt-get install -y --no-install-recommends \ cargo \ rustc +# Swift on Linux for cross tests +RUN cd / && \ + wget --quiet https://swift.org/builds/swift-4.2.1-release/ubuntu1804/swift-4.2.1-RELEASE/swift-4.2.1-RELEASE-ubuntu18.04.tar.gz && \ + tar xf swift-4.2.1-RELEASE-ubuntu18.04.tar.gz --strip-components=1 && \ + rm swift-4.2.1-RELEASE-ubuntu18.04.tar.gz && \ + swift --version + # cppcheck-1.82 has a nasty cpp parser bug, so we're using something newer RUN apt-get install -y --no-install-recommends \ `# Static Code Analysis dependencies` \ diff --git a/configure.ac b/configure.ac index f53fc3f472d..4a5fb392585 100755 --- a/configure.ac +++ b/configure.ac @@ -141,6 +141,7 @@ if test "$enable_libs" = "no"; then with_nodets="no" with_lua="no" with_rs="no" + with_swift="no" fi AX_THRIFT_LIB(cpp, [C++], yes) @@ -445,6 +446,16 @@ fi AM_CONDITIONAL(WITH_GO, [test "$have_go" = "yes"]) AM_CONDITIONAL([GOVERSION_LT_17], [test "$go_version_lt_17" = "yes"]) +AX_THRIFT_LIB(swift, [Swift], yes) +have_swift="no" +if test "$with_swift" = "yes"; then + AC_PATH_PROG([SWIFT], [swift]) + if test "x$SWIFT" != "x" -a "x$SWIFT" != "x"; then + have_swift="yes" + fi +fi +AM_CONDITIONAL([WITH_SWIFT], [test "$have_swift" = "yes"]) + AX_THRIFT_LIB(rs, [Rust], yes) have_rs="no" if test "$with_rs" = "yes"; then @@ -851,6 +862,7 @@ AC_CONFIG_FILES([ lib/rs/Makefile lib/rs/test/Makefile lib/lua/Makefile + lib/swift/Makefile lib/xml/Makefile lib/xml/test/Makefile test/Makefile @@ -929,6 +941,8 @@ if test "$have_lua" = "yes" ; then MAYBE_LUA="lua" ; else MAYBE_LUA="" ; fi AC_SUBST([MAYBE_LUA]) if test "$have_rs" = "yes" ; then MAYBE_RS="rs" ; else MAYBE_RS="" ; fi AC_SUBST([MAYBE_RS]) +if test "$have_swift" = "yes" ; then MAYBE_SWIFT="swift" ; else MAYBE_SWIFT="" ; fi +AC_SUBST([MAYBE_SWIFT]) if test "$have_dotnetcore" = "yes" ; then MAYBE_DOTNETCORE="netcore" ; else MAYBE_DOTNETCORE="" ; fi AC_SUBST([MAYBE_DOTNETCORE]) if test "$have_cl" = "yes" ; then MAYBE_CL="cl" ; else MAYBE_CL="" ; fi @@ -961,6 +975,7 @@ echo "Building Python Library ...... : $have_python" echo "Building Py3 Library ......... : $have_py3" echo "Building Ruby Library ........ : $have_ruby" echo "Building Rust Library ........ : $have_rs" +echo "Building Swift Library ....... : $have_swift" if test "$have_csharp" = "yes" ; then echo @@ -1090,6 +1105,12 @@ if test "$have_rs" = "yes" ; then echo " Using rustc................ : $RUSTC" echo " Using Rust version......... : $($RUSTC --version)" fi +if test "$have_swift" = "yes" ; then + echo + echo "Swift Library:" + echo " Using Swift ............... : $SWIFT" + echo " Using Swift version ....... : $($SWIFT --version | head -1)" +fi echo echo "If something is missing that you think should be present," echo "please skim the output of configure to find the missing" diff --git a/lib/Makefile.am b/lib/Makefile.am index b31560915e7..b6ce20e3ca0 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -102,6 +102,10 @@ if WITH_CL SUBDIRS += cl endif +if WITH_SWIFT +SUBDIRS += swift +endif + # All of the libs that don't use Automake need to go in here # so they will end up in our release tarballs. EXTRA_DIST = \ diff --git a/lib/swift/Makefile.am b/lib/swift/Makefile.am new file mode 100644 index 00000000000..6b88b06a713 --- /dev/null +++ b/lib/swift/Makefile.am @@ -0,0 +1,46 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +SUBDIRS = . + +all-local: + swift build --configuration release + +install-exec-hook: + swift install + +clean-local: + swift package clean + rm -rf .build + +precross: + swift + +check-local: + swift test + +EXTRA_DIST = \ + Package.swift \ + Sources \ + Tests \ + README.md + +MAINTAINERCLEANFILES = \ + Makefile \ + Makefile.in diff --git a/lib/swift/README.md b/lib/swift/README.md index 4fdeacfa824..6f109618424 100644 --- a/lib/swift/README.md +++ b/lib/swift/README.md @@ -22,7 +22,6 @@ under the License. ## Build - swift build ## Test From 99f673a767104a037e24eb10e1f3341e0ab428f4 Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Sun, 30 Dec 2018 22:10:00 -0500 Subject: [PATCH 086/756] THRIFT-4694: Upgrade Java to Java 1.8 --- contrib/Vagrantfile | 6 +++--- contrib/thrift-maven-plugin/pom.xml | 4 ++-- contrib/vagrant/centos-6.5/Vagrantfile | 2 +- doc/install/README.md | 2 +- doc/install/debian.md | 2 +- doc/install/windows.md | 2 +- lib/java/gradle/codeQualityChecks.gradle | 1 - lib/java/gradle/sourceConfiguration.gradle | 4 ++-- 8 files changed, 11 insertions(+), 12 deletions(-) diff --git a/contrib/Vagrantfile b/contrib/Vagrantfile index 3bcc46a96d7..ff53316bb02 100644 --- a/contrib/Vagrantfile +++ b/contrib/Vagrantfile @@ -43,7 +43,7 @@ sudo apt-get install -qq automake libtool flex bison pkg-config g++ libssl-dev m sudo apt-get install -qq libboost-dev libboost-test-dev libboost-program-options-dev libboost-filesystem-dev libboost-system-dev libevent-dev # Java dependencies -sudo apt-get install -qq ant openjdk-7-jdk maven +sudo apt-get install -qq ant openjdk-8-jdk maven # Python dependencies sudo apt-get install -qq python-all python-all-dev python-all-dbg python-setuptools python-support python-six python3-six @@ -89,8 +89,8 @@ sudo apt-get install -qq xdg-utils dmd-bin # Customize the system # --- -# Default java to latest 1.7 version -update-java-alternatives -s java-1.7.0-openjdk-amd64 +# Default java to latest 1.8 version +update-java-alternatives -s java-1.8.0-openjdk-amd64 # PHPUnit package broken in ubuntu. see https://bugs.launchpad.net/ubuntu/+source/phpunit/+bug/701544 sudo apt-get upgrade pear diff --git a/contrib/thrift-maven-plugin/pom.xml b/contrib/thrift-maven-plugin/pom.xml index d364cfc1f27..1d66bc61976 100644 --- a/contrib/thrift-maven-plugin/pom.xml +++ b/contrib/thrift-maven-plugin/pom.xml @@ -34,8 +34,8 @@ org.apache.maven.plugins maven-compiler-plugin - 1.7 - 1.7 + 1.8 + 1.8 diff --git a/contrib/vagrant/centos-6.5/Vagrantfile b/contrib/vagrant/centos-6.5/Vagrantfile index 6207958b35a..51a2239bc9f 100644 --- a/contrib/vagrant/centos-6.5/Vagrantfile +++ b/contrib/vagrant/centos-6.5/Vagrantfile @@ -87,7 +87,7 @@ sudo ./b2 install # Java LIB Dependencies ##################################### -sudo yum install -y ant junit ant-nodeps ant-junit java-1.7.0-openjdk-devel +sudo yum install -y ant junit ant-nodeps ant-junit java-1.8.0-openjdk-devel # Python LIB Dependencies ##################################### diff --git a/doc/install/README.md b/doc/install/README.md index e37f4ff0fb0..22231cd67fe 100644 --- a/doc/install/README.md +++ b/doc/install/README.md @@ -27,7 +27,7 @@ These are only required if you choose to build the libraries for the given langu * libevent (optional, to build the nonblocking server) * zlib (optional) * Java - * Java 1.7 + * Java 1.8 * Apache Ant * C#: Mono 1.2.4 (and pkg-config to detect it) or Visual Studio 2005+ * Python 2.6 (including header files for extension modules) diff --git a/doc/install/debian.md b/doc/install/debian.md index 83090ab336f..84f696ea2ff 100644 --- a/doc/install/debian.md +++ b/doc/install/debian.md @@ -19,7 +19,7 @@ If you would like to build Apache Thrift libraries for other programming languag * Java * packages: ant - * You will also need Java JDK v1.7 or higher. Type **javac** to see a list of available packages, pick the one you prefer and **apt-get install** it (e.g. default-jdk). + * You will also need Java JDK v1.8 or higher. Type **javac** to see a list of available packages, pick the one you prefer and **apt-get install** it (e.g. default-jdk). * Ruby * ruby-full ruby-dev ruby-rspec rake rubygems bundler * Python diff --git a/doc/install/windows.md b/doc/install/windows.md index 7b09840bef0..8618934f855 100644 --- a/doc/install/windows.md +++ b/doc/install/windows.md @@ -145,7 +145,7 @@ Run bootstrap.sh: Make sure you have java in your $PATH variable, if not do(adjust path if necessary): - export PATH=$PATH:"/cygdrive/c/program files/java/jre1.6.0_05/bin" + export PATH=$PATH:"/cygdrive/c/program files/java/jre1.8.0_191/bin" Run configure - using CXXFLAGS to work around an issue with an old pthreads define (untested on MinGW - works on Cygwin): diff --git a/lib/java/gradle/codeQualityChecks.gradle b/lib/java/gradle/codeQualityChecks.gradle index 9572ca1779f..1ff1c297dea 100644 --- a/lib/java/gradle/codeQualityChecks.gradle +++ b/lib/java/gradle/codeQualityChecks.gradle @@ -28,7 +28,6 @@ pmd { ignoreFailures = true toolVersion = '6.0.0' sourceSets = [ sourceSets.main ] - targetJdk = sourceCompatibility ruleSets = [ 'java-basic' ] } diff --git a/lib/java/gradle/sourceConfiguration.gradle b/lib/java/gradle/sourceConfiguration.gradle index decc6a27597..8dd0331f799 100644 --- a/lib/java/gradle/sourceConfiguration.gradle +++ b/lib/java/gradle/sourceConfiguration.gradle @@ -45,8 +45,8 @@ sourceSets { // ---------------------------------------------------------------------------- // Compiler configuration details -sourceCompatibility = '1.6' -targetCompatibility = '1.6' +sourceCompatibility = '1.8' +targetCompatibility = '1.8' tasks.withType(JavaCompile) { options.encoding = 'UTF-8' From 217e8246ab6fdb6a1fa6016ba0f4979eb1d8a92a Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Wed, 2 Jan 2019 23:09:21 -0500 Subject: [PATCH 087/756] Update CHANGES with issues fixed in 0.12.0 but closed late. --- CHANGES | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index e3e50b6bc85..244f0da2feb 100644 --- a/CHANGES +++ b/CHANGES @@ -43,6 +43,7 @@ Thrift 0.12.0 * [THRIFT-4677] - py3: UnicodeDecideError in Python3 ## Build Process + * [THRIFT-4067] - Windows thrift compiler distributed on the apache web site has runtime dependencies * [THRIFT-4308] - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang * [THRIFT-4579] - Use Ubuntu Bionic (18.04 LTS) for CI builds instead of Artful (17.10) * [THRIFT-4508] - Define CI operating system coverage rules for the project and (hopefully) simplify CI a little more @@ -119,6 +120,8 @@ Thrift 0.12.0 * [THRIFT-4461] - Compiler directive should match Delphi XE4 * [THRIFT-4462] - First line in Console duplicated * [THRIFT-4642] - FPU ctrl word settings may cause an unexpected "denormalized" error + * [THRIFT-4589] - HTTP client timeouts are a) incomplete and b) not used at all + * [THRIFT-4590] - running the test client using HTTP transport leads to "CoInitialize not called" ## erlang * [THRIFT-4497] - Erlang records should use map() for map type @@ -244,6 +247,7 @@ Thrift 0.12.0 * [THRIFT-4658] - Rust's TBinaryInputProtocol fails when strict is false * [THRIFT-4187] - Dart -> Rust Framed cross tests fail * [THRIFT-4664] - Rust cannot create ReadHalf/WriteHalf to implement custom tranports + * [THRIFT-4665] - Keep Rust library up-to-date on crates.io ## swift (new language support in 0.12.0) * [THRIFT-3773] - Swift Library @@ -436,6 +440,7 @@ Thrift 0.11.0 * [THRIFT-4370] - Ubuntu Artful cppcheck and flake8 are more stringent and causing SCA build job failures * [THRIFT-4372] - Pipe write operations across a network are limited to 65,535 bytes per write. * [THRIFT-4374] - cannot load thrift_protocol due to undefined symbol: _ZTVN10__cxxabiv120__si_class_type_infoE + * [THRIFT-4375] - TMemory throw bad_alloc due to counter overflow * [THRIFT-4376] - Coverity high impact issue resolution * [THRIFT-4377] - haxe. socket handles leak in TSimpleServer * [THRIFT-4381] - Wrong isset bitfield value after transmission From 57516213cc3b17a38196b07282feb47144e5232f Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Wed, 2 Jan 2019 08:28:47 -0500 Subject: [PATCH 088/756] THRIFT-4301: fix inability to disable py3 with autoconf build --- configure.ac | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 4a5fb392585..fa507561ffd 100755 --- a/configure.ac +++ b/configure.ac @@ -325,10 +325,13 @@ AM_CONDITIONAL(WITH_TWISTED_TEST, [test "$have_trial" = "yes"]) # It's distro specific and far from ideal but needed to cross test py2-3 at once. # TODO: find "python2" if it's 3.x have_py3="no" -if python --version 2>&1 | grep -q "Python 2"; then - AC_PATH_PROGS([PYTHON3], [python3 python3.5 python35 python3.4 python34]) - if test -n "$PYTHON3"; then - have_py3="yes" +AX_THRIFT_LIB(py3, [Py3], yes) +if test "$with_py3" = "yes"; then + if $PYTHON --version 2>&1 | grep -q "Python 2"; then + AC_PATH_PROGS([PYTHON3], [python3 python3.7 python37 python3.6 python36 python3.5 python35 python3.4 python34]) + if test -n "$PYTHON3"; then + have_py3="yes" + fi fi fi AM_CONDITIONAL(WITH_PY3, [test "$have_py3" = "yes"]) From 9e813aeed2291a25fc965ba58944c3705b9d15c6 Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Mon, 31 Dec 2018 10:58:19 -0500 Subject: [PATCH 089/756] THRIFT-4702: Improve AutoExpandingBuffer --- lib/java/README.md | 9 +++++++ .../thrift/transport/AutoExpandingBuffer.java | 26 +++++++++---------- .../AutoExpandingBufferReadTransport.java | 4 +-- .../AutoExpandingBufferWriteTransport.java | 4 +-- .../transport/TFastFramedTransport.java | 6 ++--- .../transport/TestAutoExpandingBuffer.java | 2 +- .../TestAutoExpandingBufferReadTransport.java | 2 +- ...TestAutoExpandingBufferWriteTransport.java | 2 +- 8 files changed, 31 insertions(+), 24 deletions(-) diff --git a/lib/java/README.md b/lib/java/README.md index 1e4aed22a23..cdd4059f1a4 100644 --- a/lib/java/README.md +++ b/lib/java/README.md @@ -161,3 +161,12 @@ Dependencies Gradle http://gradle.org/ + +# Breaking Changes + +## 0.12.0 + +The access modifier of the AutoExpandingBuffer class has been changed from +public to default (package) and will no longer be accessible by third-party +libraries. + diff --git a/lib/java/src/org/apache/thrift/transport/AutoExpandingBuffer.java b/lib/java/src/org/apache/thrift/transport/AutoExpandingBuffer.java index b02905f3201..fc3aa92dfd9 100644 --- a/lib/java/src/org/apache/thrift/transport/AutoExpandingBuffer.java +++ b/lib/java/src/org/apache/thrift/transport/AutoExpandingBuffer.java @@ -18,6 +18,8 @@ */ package org.apache.thrift.transport; +import java.util.Arrays; + /** * 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, @@ -25,28 +27,24 @@ * rate slightly faster than the requested capacity with the (untested) * objective of avoiding expensive buffer allocations and copies. */ -public class AutoExpandingBuffer { +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 AutoExpandingBuffer(int initialCapacity) { + this.array = new byte[initialCapacity]; } 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; + final int currentCapacity = this.array.length; + if (currentCapacity < size) { + // Increase by a factor of 1.5x + int growCapacity = currentCapacity + (currentCapacity >> 1); + int newCapacity = Math.max(growCapacity, size); + this.array = Arrays.copyOf(array, newCapacity); } } public byte[] array() { - return array; + return this.array; } } diff --git a/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferReadTransport.java b/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferReadTransport.java index 081bc48a5be..a28d254854b 100644 --- a/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferReadTransport.java +++ b/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferReadTransport.java @@ -28,8 +28,8 @@ public class AutoExpandingBufferReadTransport extends TTransport { private int pos = 0; private int limit = 0; - public AutoExpandingBufferReadTransport(int initialCapacity, double overgrowthCoefficient) { - this.buf = new AutoExpandingBuffer(initialCapacity, overgrowthCoefficient); + public AutoExpandingBufferReadTransport(int initialCapacity) { + this.buf = new AutoExpandingBuffer(initialCapacity); } public void fill(TTransport inTrans, int length) throws TTransportException { diff --git a/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java b/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java index 9b35693bac6..ad2ec551bea 100644 --- a/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java +++ b/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java @@ -26,8 +26,8 @@ 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); + public AutoExpandingBufferWriteTransport(int initialCapacity) { + this.buf = new AutoExpandingBuffer(initialCapacity); this.pos = 0; } diff --git a/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java b/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java index d2656008421..891d7984562 100644 --- a/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java @@ -106,8 +106,8 @@ public TFastFramedTransport(TTransport underlying, int initialBufferCapacity, in this.underlying = underlying; this.maxLength = maxLength; this.initialBufferCapacity = initialBufferCapacity; - writeBuffer = new AutoExpandingBufferWriteTransport(initialBufferCapacity, 1.5); - readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity, 1.5); + writeBuffer = new AutoExpandingBufferWriteTransport(initialBufferCapacity); + readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity); } @Override @@ -167,7 +167,7 @@ public void consumeBuffer(int len) { } public void clear() { - readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity, 1.5); + readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity); } @Override diff --git a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBuffer.java b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBuffer.java index 337dcf8cb04..c35348953eb 100644 --- a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBuffer.java +++ b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBuffer.java @@ -23,7 +23,7 @@ public class TestAutoExpandingBuffer extends TestCase { public void testExpands() throws Exception { // has expected initial capacity - AutoExpandingBuffer b = new AutoExpandingBuffer(10, 1.5); + AutoExpandingBuffer b = new AutoExpandingBuffer(10); assertEquals(10, b.array().length); // doesn't shrink diff --git a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferReadTransport.java b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferReadTransport.java index 2e1f9472437..83ebc2d4c3f 100644 --- a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferReadTransport.java +++ b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferReadTransport.java @@ -32,7 +32,7 @@ public class TestAutoExpandingBufferReadTransport extends TestCase { } public void testIt() throws Exception { - AutoExpandingBufferReadTransport t = new AutoExpandingBufferReadTransport(150, 1.5); + AutoExpandingBufferReadTransport t = new AutoExpandingBufferReadTransport(150); TMemoryInputTransport membuf = new TMemoryInputTransport(HUNDRED_BYTES); diff --git a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java index d5f239da4d8..6b04feb2ed6 100644 --- a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java +++ b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java @@ -25,7 +25,7 @@ public class TestAutoExpandingBufferWriteTransport extends TestCase { public void testIt() throws Exception { - AutoExpandingBufferWriteTransport t = new AutoExpandingBufferWriteTransport(1, 1.5); + AutoExpandingBufferWriteTransport t = new AutoExpandingBufferWriteTransport(1); assertEquals(1, t.getBuf().array().length); byte[] b1 = new byte[]{1,2,3}; t.write(b1); From 5abf58cf792466302d3c21d6b93ff50bb42d4c2f Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Mon, 31 Dec 2018 16:47:04 -0500 Subject: [PATCH 090/756] THRIFT-4709: Use StandardCharsets UTF-8 --- .../apache/thrift/TByteArrayOutputStream.java | 5 ++ .../thrift/protocol/TBinaryProtocol.java | 33 +++----- .../thrift/protocol/TCompactProtocol.java | 27 +++--- .../apache/thrift/protocol/TJSONProtocol.java | 82 ++++++------------- .../thrift/protocol/TSimpleJSONProtocol.java | 20 ++--- .../thrift/transport/TMemoryBuffer.java | 10 ++- .../transport/TSaslClientTransport.java | 9 +- .../transport/TSaslServerTransport.java | 10 +-- .../thrift/transport/TSaslTransport.java | 12 +-- lib/java/test/org/apache/thrift/Fixtures.java | 3 +- .../thrift/protocol/TestTJSONProtocol.java | 6 +- .../protocol/TestTSimpleJSONProtocol.java | 8 +- .../thrift/transport/TestTSaslTransports.java | 15 +--- 13 files changed, 83 insertions(+), 157 deletions(-) diff --git a/lib/java/src/org/apache/thrift/TByteArrayOutputStream.java b/lib/java/src/org/apache/thrift/TByteArrayOutputStream.java index 1c37ecd313a..3a2d56c88c2 100644 --- a/lib/java/src/org/apache/thrift/TByteArrayOutputStream.java +++ b/lib/java/src/org/apache/thrift/TByteArrayOutputStream.java @@ -20,6 +20,7 @@ package org.apache.thrift; import java.io.ByteArrayOutputStream; +import java.nio.charset.Charset; /** * Class that allows access to the underlying buf without doing deep @@ -53,4 +54,8 @@ public void reset() { public int len() { return count; } + + public String toString(Charset charset) { + return new String(buf, 0, count, charset); + } } diff --git a/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java b/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java index aaa1fd8c7e4..563128cdb91 100644 --- a/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java +++ b/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java @@ -19,8 +19,8 @@ package org.apache.thrift.protocol; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import org.apache.thrift.TException; import org.apache.thrift.transport.TTransport; @@ -202,13 +202,9 @@ public void writeDouble(double dub) throws TException { } 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"); - } + byte[] dat = str.getBytes(StandardCharsets.UTF_8); + writeI32(dat.length); + trans_.write(dat, 0, dat.length); } public void writeBinary(ByteBuffer bin) throws TException { @@ -360,13 +356,10 @@ public String readString() throws TException { 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"); - } + String s = new String(trans_.getBuffer(), trans_.getBufferPosition(), + size, StandardCharsets.UTF_8); + trans_.consumeBuffer(size); + return s; } return readStringBody(size); @@ -374,13 +367,9 @@ public String readString() throws TException { 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"); - } + byte[] buf = new byte[size]; + trans_.readAll(buf, 0, size); + return new String(buf, StandardCharsets.UTF_8); } public ByteBuffer readBinary() throws TException { diff --git a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java index 56c349a1551..92f186e41e8 100644 --- a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java +++ b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java @@ -22,6 +22,7 @@ import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import org.apache.thrift.ShortStack; import org.apache.thrift.TException; @@ -359,12 +360,8 @@ public void writeDouble(double dub) throws TException { * 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!"); - } + byte[] bytes = str.getBytes(StandardCharsets.UTF_8); + writeBinary(bytes, 0, bytes.length); } /** @@ -680,17 +677,15 @@ public String readString() throws TException { 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!"); + final String str; + if (trans_.getBytesRemainingInBuffer() >= length) { + str = new String(trans_.getBuffer(), trans_.getBufferPosition(), + length, StandardCharsets.UTF_8); + trans_.consumeBuffer(length); + } else { + str = new String(readBinary(length), StandardCharsets.UTF_8); } + return str; } /** diff --git a/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java b/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java index fd54fdf462c..d37c4937f92 100644 --- a/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java +++ b/lib/java/src/org/apache/thrift/protocol/TJSONProtocol.java @@ -20,8 +20,8 @@ package org.apache.thrift.protocol; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Stack; @@ -418,12 +418,8 @@ private void writeJSONInteger(long num) throws TException { 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"); - } + byte[] buf = str.getBytes(StandardCharsets.UTF_8); + trans_.write(buf); if (escapeNum) { trans_.write(QUOTE); } @@ -453,12 +449,8 @@ private void writeJSONDouble(double num) throws TException { 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"); - } + byte[] b = str.getBytes(StandardCharsets.UTF_8); + trans_.write(b, 0, b.length); if (escapeNum) { trans_.write(QUOTE); } @@ -513,12 +505,8 @@ 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"); - } + byte[] b = message.name.getBytes(StandardCharsets.UTF_8); + writeJSONString(b); writeJSONInteger(message.type); writeJSONInteger(message.seqid); } @@ -628,12 +616,8 @@ public void writeDouble(double dub) throws TException { @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"); - } + byte[] b = str.getBytes(StandardCharsets.UTF_8); + writeJSONString(b); } @Override @@ -684,19 +668,17 @@ else if (Character.isLowSurrogate((char)cu)) { } codeunits.add((char)cu); - arr.write((new String(new int[] { codeunits.get(0), codeunits.get(1) }, 0, 2)).getBytes("UTF-8")); + arr.write( + (new String(new int[] { codeunits.get(0), codeunits.get(1) }, + 0, 2)).getBytes(StandardCharsets.UTF_8)); codeunits.clear(); } else { - arr.write((new String(new int[] { cu }, 0, 1)).getBytes("UTF-8")); + arr.write((new String(new int[] { cu }, 0, 1)) + .getBytes(StandardCharsets.UTF_8)); } continue; - } - catch (UnsupportedEncodingException ex) { - throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, - "JVM does not support UTF-8"); - } - catch (IOException ex) { + } catch (IOException ex) { throw new TProtocolException(TProtocolException.INVALID_DATA, "Invalid unicode sequence"); } @@ -777,19 +759,14 @@ 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"); + double dub = Double.valueOf(arr.toString(StandardCharsets.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; } else { if (context_.escapeNum()) { @@ -868,13 +845,7 @@ public TMessage readMessageBegin() throws TException { 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"); - } + String name = readJSONString(false).toString(StandardCharsets.UTF_8); byte type = (byte) readJSONInteger(); int seqid = (int) readJSONInteger(); return new TMessage(name, type, seqid); @@ -991,12 +962,7 @@ public double readDouble() throws TException { @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"); - } + return readJSONString(false).toString(StandardCharsets.UTF_8); } @Override diff --git a/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java b/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java index b24e421a973..e7e8d461558 100644 --- a/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java +++ b/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java @@ -19,8 +19,8 @@ package org.apache.thrift.protocol; -import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.Stack; import org.apache.thrift.TException; @@ -262,12 +262,8 @@ public void writeI32(int i32) throws TException { } 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"); - } + byte[] b = s.getBytes(StandardCharsets.UTF_8); + trans_.write(b); } public void writeI64(long i64) throws TException { @@ -342,12 +338,10 @@ public void writeString(String str) throws TException { } 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"); - } + // TODO(mcslee): Fix this + writeString(new String(bin.array(), bin.position() + bin.arrayOffset(), + bin.limit() - bin.position() - bin.arrayOffset(), + StandardCharsets.UTF_8)); } /** diff --git a/lib/java/src/org/apache/thrift/transport/TMemoryBuffer.java b/lib/java/src/org/apache/thrift/transport/TMemoryBuffer.java index ef5f5c28e04..b19ac86d25a 100644 --- a/lib/java/src/org/apache/thrift/transport/TMemoryBuffer.java +++ b/lib/java/src/org/apache/thrift/transport/TMemoryBuffer.java @@ -20,7 +20,7 @@ package org.apache.thrift.transport; import org.apache.thrift.TByteArrayOutputStream; -import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; /** * Memory buffer-based implementation of the TTransport interface. @@ -30,6 +30,8 @@ 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. + * + * @param size the initial size of the buffer */ public TMemoryBuffer(int size) { arr_ = new TByteArrayOutputStream(size); @@ -69,11 +71,11 @@ public void write(byte[] buf, int off, int len) { /** * Output the contents of the memory buffer as a String, using the supplied * encoding - * @param enc the encoding to use + * @param charset 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 toString(Charset charset) { + return arr_.toString(charset); } public String inspect() { diff --git a/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java index 81222897828..4b1ca0a944f 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java @@ -19,7 +19,7 @@ package org.apache.thrift.transport; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.util.Map; import javax.security.auth.callback.CallbackHandler; @@ -97,12 +97,7 @@ protected void handleSaslStartMessage() throws TTransportException, SaslExceptio 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); - } + byte[] mechanismBytes = mechanism.getBytes(StandardCharsets.UTF_8); sendSaslMessage(NegotiationStatus.START, mechanismBytes); // Send initial response diff --git a/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java index e6c0e3e979a..39b81ca4367 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java @@ -19,8 +19,8 @@ package org.apache.thrift.transport; -import java.io.UnsupportedEncodingException; import java.lang.ref.WeakReference; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -31,7 +31,6 @@ import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; -import org.apache.thrift.TException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -132,12 +131,7 @@ protected void handleSaslStartMessage() throws TTransportException, SaslExceptio } // 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"); - } + String mechanismName = new String(message.payload, StandardCharsets.UTF_8); TSaslServerDefinition serverDefinition = serverDefinitionMap.get(mechanismName); LOGGER.debug("Received mechanism name '{}'", mechanismName); diff --git a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java index bbd3f9a34a6..80f35571057 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java @@ -19,7 +19,7 @@ package org.apache.thrift.transport; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -194,12 +194,8 @@ protected SaslResponse receiveSaslMessage() throws TTransportException { 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); - } + String remoteMessage = new String(payload, StandardCharsets.UTF_8); + throw new TTransportException("Peer indicated failure: " + remoteMessage); } if (LOGGER.isDebugEnabled()) @@ -224,7 +220,7 @@ protected SaslResponse receiveSaslMessage() throws TTransportException { */ protected TTransportException sendAndThrowMessage(NegotiationStatus status, String message) throws TTransportException { try { - sendSaslMessage(status, message.getBytes("UTF-8")); + sendSaslMessage(status, message.getBytes(StandardCharsets.UTF_8)); } catch (Exception e) { LOGGER.warn("Could not send failure response", e); message += "\nAlso, could not send response: " + e.toString(); diff --git a/lib/java/test/org/apache/thrift/Fixtures.java b/lib/java/test/org/apache/thrift/Fixtures.java index 81671d8de56..61f40a590f9 100644 --- a/lib/java/test/org/apache/thrift/Fixtures.java +++ b/lib/java/test/org/apache/thrift/Fixtures.java @@ -20,6 +20,7 @@ package org.apache.thrift; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -267,7 +268,7 @@ public class Fixtures { oneOfEach.setInteger64((long) 6000 * 1000 * 1000); oneOfEach.setDouble_precision(Math.PI); oneOfEach.setSome_characters("JSON THIS! \"\1"); - oneOfEach.setZomg_unicode(new String(kUnicodeBytes, "UTF-8")); + oneOfEach.setZomg_unicode(new String(kUnicodeBytes, StandardCharsets.UTF_8)); oneOfEach.setBase64(ByteBuffer.wrap("base64".getBytes())); // byte, i16, and i64 lists are populated by default constructor diff --git a/lib/java/test/org/apache/thrift/protocol/TestTJSONProtocol.java b/lib/java/test/org/apache/thrift/protocol/TestTJSONProtocol.java index 13207495f7f..c2ca1fa7aaf 100644 --- a/lib/java/test/org/apache/thrift/protocol/TestTJSONProtocol.java +++ b/lib/java/test/org/apache/thrift/protocol/TestTJSONProtocol.java @@ -18,7 +18,7 @@ */ package org.apache.thrift.protocol; -import java.io.IOException; +import java.nio.charset.StandardCharsets; import org.apache.thrift.TException; import org.apache.thrift.protocol.TJSONProtocol; @@ -35,13 +35,13 @@ protected boolean canBeUsedNaked() { return false; } - public void testEscapedUnicode() throws TException, IOException { + public void testEscapedUnicode() throws TException { String jsonString = "\"hello unicode \\u0e01\\ud834\\udd1e world\""; String expectedString = "hello unicode \u0e01\ud834\udd1e world"; TMemoryBuffer buffer = new TMemoryBuffer(1000); TJSONProtocol protocol = new TJSONProtocol(buffer); - buffer.write(jsonString.getBytes("UTF-8")); + buffer.write(jsonString.getBytes(StandardCharsets.UTF_8)); assertEquals(expectedString, protocol.readString()); } diff --git a/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java b/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java index b8c4657489a..9d125b1e58d 100644 --- a/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java +++ b/lib/java/test/org/apache/thrift/protocol/TestTSimpleJSONProtocol.java @@ -18,7 +18,7 @@ */ package org.apache.thrift.protocol; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import junit.framework.TestCase; @@ -40,11 +40,7 @@ protected void setUp() throws Exception { } private String bufToString() { - try { - return buf.toString("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } + return buf.toString(StandardCharsets.UTF_8); } public void testHolyMoley() throws TException { diff --git a/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java b/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java index 788395ff356..36a06e9e5aa 100644 --- a/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java +++ b/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java @@ -20,6 +20,7 @@ package org.apache.thrift.transport; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -332,12 +333,8 @@ public byte[] evaluateChallenge(byte[] challenge) throws SaslException { throw new SaslException("Already complete!"); } - try { - hasProvidedInitialResponse = true; - return username.getBytes("UTF-8"); - } catch (IOException e) { - throw new SaslException(e.toString()); - } + hasProvidedInitialResponse = true; + return username.getBytes(StandardCharsets.UTF_8); } public boolean isComplete() { return hasProvidedInitialResponse; } public byte[] unwrap(byte[] incoming, int offset, int len) { @@ -354,11 +351,7 @@ private static class AnonymousServer implements SaslServer { private String user; public String getMechanismName() { return "ANONYMOUS"; } public byte[] evaluateResponse(byte[] response) throws SaslException { - try { - this.user = new String(response, "UTF-8"); - } catch (IOException e) { - throw new SaslException(e.toString()); - } + this.user = new String(response, StandardCharsets.UTF_8); return null; } public boolean isComplete() { return user != null; } From 36ffe1e8dc5168ea683bb10896377eaffc057667 Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Wed, 2 Jan 2019 19:24:33 -0500 Subject: [PATCH 091/756] THRIFT-4469: Make isServing volatile --- lib/java/src/org/apache/thrift/server/TServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/java/src/org/apache/thrift/server/TServer.java b/lib/java/src/org/apache/thrift/server/TServer.java index 80f4f8629d0..bac06b26bfb 100644 --- a/lib/java/src/org/apache/thrift/server/TServer.java +++ b/lib/java/src/org/apache/thrift/server/TServer.java @@ -123,7 +123,7 @@ public T outputProtocolFactory(TProtocolFactory factory) { */ protected TProtocolFactory outputProtocolFactory_; - private boolean isServing; + private volatile boolean isServing; protected TServerEventHandler eventHandler_; From 882d48da5d5db439c11029f46006c71f6429ae2c Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Thu, 3 Jan 2019 09:20:16 -0500 Subject: [PATCH 092/756] THRIFT-4481: TBinaryProtocol.writeMessageEnd does not allow throwable exception --- .../thrift/protocol/TBinaryProtocol.java | 69 +++++++++++++++---- .../thrift/protocol/TCompactProtocol.java | 2 + .../thrift/protocol/TSimpleJSONProtocol.java | 59 +++++++++++++--- 3 files changed, 107 insertions(+), 23 deletions(-) diff --git a/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java b/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java index 563128cdb91..7924e2fe600 100644 --- a/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java +++ b/lib/java/src/org/apache/thrift/protocol/TBinaryProtocol.java @@ -110,6 +110,7 @@ public TBinaryProtocol(TTransport trans, long stringLengthLimit, long containerL strictWrite_ = strictWrite; } + @Override public void writeMessageBegin(TMessage message) throws TException { if (strictWrite_) { int version = VERSION_1 | message.type; @@ -123,60 +124,76 @@ public void writeMessageBegin(TMessage message) throws TException { } } - public void writeMessageEnd() {} + @Override + public void writeMessageEnd() throws TException {} - public void writeStructBegin(TStruct struct) {} + @Override + public void writeStructBegin(TStruct struct) throws TException {} - public void writeStructEnd() {} + @Override + public void writeStructEnd() throws TException {} + @Override public void writeFieldBegin(TField field) throws TException { writeByte(field.type); writeI16(field.id); } - public void writeFieldEnd() {} + @Override + public void writeFieldEnd() throws TException {} + @Override public void writeFieldStop() throws TException { writeByte(TType.STOP); } + @Override public void writeMapBegin(TMap map) throws TException { writeByte(map.keyType); writeByte(map.valueType); writeI32(map.size); } - public void writeMapEnd() {} + @Override + public void writeMapEnd() throws TException {} + @Override public void writeListBegin(TList list) throws TException { writeByte(list.elemType); writeI32(list.size); } - public void writeListEnd() {} + @Override + public void writeListEnd() throws TException {} + @Override public void writeSetBegin(TSet set) throws TException { writeByte(set.elemType); writeI32(set.size); } - public void writeSetEnd() {} + @Override + public void writeSetEnd() throws TException {} + @Override public void writeBool(boolean b) throws TException { writeByte(b ? (byte)1 : (byte)0); } + @Override public void writeByte(byte b) throws TException { inoutTemp[0] = b; trans_.write(inoutTemp, 0, 1); } + @Override public void writeI16(short i16) throws TException { inoutTemp[0] = (byte)(0xff & (i16 >> 8)); inoutTemp[1] = (byte)(0xff & (i16)); trans_.write(inoutTemp, 0, 2); } + @Override public void writeI32(int i32) throws TException { inoutTemp[0] = (byte)(0xff & (i32 >> 24)); inoutTemp[1] = (byte)(0xff & (i32 >> 16)); @@ -185,6 +202,7 @@ public void writeI32(int i32) throws TException { trans_.write(inoutTemp, 0, 4); } + @Override public void writeI64(long i64) throws TException { inoutTemp[0] = (byte)(0xff & (i64 >> 56)); inoutTemp[1] = (byte)(0xff & (i64 >> 48)); @@ -197,16 +215,19 @@ public void writeI64(long i64) throws TException { trans_.write(inoutTemp, 0, 8); } + @Override public void writeDouble(double dub) throws TException { writeI64(Double.doubleToLongBits(dub)); } + @Override public void writeString(String str) throws TException { byte[] dat = str.getBytes(StandardCharsets.UTF_8); writeI32(dat.length); trans_.write(dat, 0, dat.length); } + @Override public void writeBinary(ByteBuffer bin) throws TException { int length = bin.limit() - bin.position(); writeI32(length); @@ -217,6 +238,7 @@ public void writeBinary(ByteBuffer bin) throws TException { * Reading methods. */ + @Override public TMessage readMessageBegin() throws TException { int size = readI32(); if (size < 0) { @@ -233,50 +255,63 @@ public TMessage readMessageBegin() throws TException { } } - public void readMessageEnd() {} + @Override + public void readMessageEnd() throws TException {} - public TStruct readStructBegin() { + @Override + public TStruct readStructBegin() throws TException { return ANONYMOUS_STRUCT; } - public void readStructEnd() {} + @Override + public void readStructEnd() throws TException {} + @Override public TField readFieldBegin() throws TException { byte type = readByte(); short id = type == TType.STOP ? 0 : readI16(); return new TField("", type, id); } - public void readFieldEnd() {} + @Override + public void readFieldEnd() throws TException {} + @Override public TMap readMapBegin() throws TException { TMap map = new TMap(readByte(), readByte(), readI32()); checkContainerReadLength(map.size); return map; } - public void readMapEnd() {} + @Override + public void readMapEnd() throws TException {} + @Override public TList readListBegin() throws TException { TList list = new TList(readByte(), readI32()); checkContainerReadLength(list.size); return list; } - public void readListEnd() {} + @Override + public void readListEnd() throws TException {} + @Override public TSet readSetBegin() throws TException { TSet set = new TSet(readByte(), readI32()); checkContainerReadLength(set.size); return set; } - public void readSetEnd() {} + @Override + public void readSetEnd() throws TException {} + @Override public boolean readBool() throws TException { return (readByte() == 1); } + @Override public byte readByte() throws TException { if (trans_.getBytesRemainingInBuffer() >= 1) { byte b = trans_.getBuffer()[trans_.getBufferPosition()]; @@ -287,6 +322,7 @@ public byte readByte() throws TException { return inoutTemp[0]; } + @Override public short readI16() throws TException { byte[] buf = inoutTemp; int off = 0; @@ -305,6 +341,7 @@ public short readI16() throws TException { ((buf[off+1] & 0xff))); } + @Override public int readI32() throws TException { byte[] buf = inoutTemp; int off = 0; @@ -323,6 +360,7 @@ public int readI32() throws TException { ((buf[off+3] & 0xff)); } + @Override public long readI64() throws TException { byte[] buf = inoutTemp; int off = 0; @@ -346,10 +384,12 @@ public long readI64() throws TException { ((long)(buf[off+7] & 0xff)); } + @Override public double readDouble() throws TException { return Double.longBitsToDouble(readI64()); } + @Override public String readString() throws TException { int size = readI32(); @@ -372,6 +412,7 @@ public String readStringBody(int size) throws TException { return new String(buf, StandardCharsets.UTF_8); } + @Override public ByteBuffer readBinary() throws TException { int size = readI32(); diff --git a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java index 92f186e41e8..af145ef0a85 100644 --- a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java +++ b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java @@ -203,6 +203,7 @@ public void reset() { * 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. */ + @Override public void writeMessageBegin(TMessage message) throws TException { writeByteDirect(PROTOCOL_ID); writeByteDirect((VERSION & VERSION_MASK) | ((message.type << TYPE_SHIFT_AMOUNT) & TYPE_MASK)); @@ -215,6 +216,7 @@ public void writeMessageBegin(TMessage message) throws TException { * use it as an opportunity to put special placeholder markers on the field * stack so we can get the field id deltas correct. */ + @Override public void writeStructBegin(TStruct struct) throws TException { lastField_.push(lastFieldId_); lastFieldId_ = 0; diff --git a/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java b/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java index e7e8d461558..eb7e23bf9ca 100644 --- a/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java +++ b/lib/java/src/org/apache/thrift/protocol/TSimpleJSONProtocol.java @@ -167,6 +167,7 @@ public TSimpleJSONProtocol(TTransport trans) { super(trans); } + @Override public void writeMessageBegin(TMessage message) throws TException { resetWriteContext(); // THRIFT-3743 trans_.write(LBRACKET); @@ -176,31 +177,38 @@ public void writeMessageBegin(TMessage message) throws TException { writeI32(message.seqid); } + @Override public void writeMessageEnd() throws TException { popWriteContext(); trans_.write(RBRACKET); } + @Override public void writeStructBegin(TStruct struct) throws TException { writeContext_.write(); trans_.write(LBRACE); pushWriteContext(new StructContext()); } + @Override public void writeStructEnd() throws TException { popWriteContext(); trans_.write(RBRACE); } + @Override public void writeFieldBegin(TField field) throws TException { // Note that extra type information is omitted in JSON! writeString(field.name); } - public void writeFieldEnd() {} + @Override + public void writeFieldEnd() throws TException {} - public void writeFieldStop() {} + @Override + public void writeFieldStop() throws TException {} + @Override public void writeMapBegin(TMap map) throws TException { assertContextIsNotMapKey(MAP); writeContext_.write(); @@ -209,11 +217,13 @@ public void writeMapBegin(TMap map) throws TException { // No metadata! } + @Override public void writeMapEnd() throws TException { popWriteContext(); trans_.write(RBRACE); } + @Override public void writeListBegin(TList list) throws TException { assertContextIsNotMapKey(LIST); writeContext_.write(); @@ -222,11 +232,13 @@ public void writeListBegin(TList list) throws TException { // No metadata! } + @Override public void writeListEnd() throws TException { popWriteContext(); trans_.write(RBRACKET); } + @Override public void writeSetBegin(TSet set) throws TException { assertContextIsNotMapKey(SET); writeContext_.write(); @@ -235,23 +247,28 @@ public void writeSetBegin(TSet set) throws TException { // No metadata! } + @Override public void writeSetEnd() throws TException { popWriteContext(); trans_.write(RBRACKET); } + @Override public void writeBool(boolean b) throws TException { writeByte(b ? (byte)1 : (byte)0); } + @Override public void writeByte(byte b) throws TException { writeI32(b); } + @Override public void writeI16(short i16) throws TException { writeI32(i16); } + @Override public void writeI32(int i32) throws TException { if(writeContext_.isMapKey()) { writeString(Integer.toString(i32)); @@ -266,6 +283,7 @@ public void _writeStringData(String s) throws TException { trans_.write(b); } + @Override public void writeI64(long i64) throws TException { if(writeContext_.isMapKey()) { writeString(Long.toString(i64)); @@ -275,6 +293,7 @@ public void writeI64(long i64) throws TException { } } + @Override public void writeDouble(double dub) throws TException { if(writeContext_.isMapKey()) { writeString(Double.toString(dub)); @@ -284,6 +303,7 @@ public void writeDouble(double dub) throws TException { } } + @Override public void writeString(String str) throws TException { writeContext_.write(); int length = str.length(); @@ -337,6 +357,7 @@ public void writeString(String str) throws TException { _writeStringData(escape.toString()); } + @Override public void writeBinary(ByteBuffer bin) throws TException { // TODO(mcslee): Fix this writeString(new String(bin.array(), bin.position() + bin.arrayOffset(), @@ -348,77 +369,96 @@ public void writeBinary(ByteBuffer bin) throws TException { * Reading methods. */ + @Override public TMessage readMessageBegin() throws TException { // TODO(mcslee): implement return EMPTY_MESSAGE; } - public void readMessageEnd() {} + @Override + public void readMessageEnd() throws TException {} - public TStruct readStructBegin() { + @Override + public TStruct readStructBegin() throws TException { // TODO(mcslee): implement return ANONYMOUS_STRUCT; } - public void readStructEnd() {} + @Override + public void readStructEnd() throws TException {} + @Override public TField readFieldBegin() throws TException { // TODO(mcslee): implement return ANONYMOUS_FIELD; } - public void readFieldEnd() {} + @Override + public void readFieldEnd() throws TException {} + @Override public TMap readMapBegin() throws TException { // TODO(mcslee): implement return EMPTY_MAP; } - public void readMapEnd() {} + @Override + public void readMapEnd() throws TException {} + @Override public TList readListBegin() throws TException { // TODO(mcslee): implement return EMPTY_LIST; } - public void readListEnd() {} + @Override + public void readListEnd() throws TException {} + @Override public TSet readSetBegin() throws TException { // TODO(mcslee): implement return EMPTY_SET; } - public void readSetEnd() {} + @Override + public void readSetEnd() throws TException {} + @Override public boolean readBool() throws TException { return (readByte() == 1); } + @Override public byte readByte() throws TException { // TODO(mcslee): implement return 0; } + @Override public short readI16() throws TException { // TODO(mcslee): implement return 0; } + @Override public int readI32() throws TException { // TODO(mcslee): implement return 0; } + @Override public long readI64() throws TException { // TODO(mcslee): implement return 0; } + @Override public double readDouble() throws TException { // TODO(mcslee): implement return 0; } + @Override public String readString() throws TException { // TODO(mcslee): implement return ""; @@ -429,6 +469,7 @@ public String readStringBody(int size) throws TException { return ""; } + @Override public ByteBuffer readBinary() throws TException { // TODO(mcslee): implement return ByteBuffer.wrap(new byte[0]); From 88584f8469a1768f16f8477d0247a27d214a5ebc Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Tue, 1 Jan 2019 16:35:04 -0500 Subject: [PATCH 093/756] THRIFT-4712: Improve Performance and Refactor ShortStack --- lib/java/README.md | 4 + .../thrift/{ => protocol}/ShortStack.java | 43 +++---- .../thrift/protocol/TCompactProtocol.java | 1 - .../org/apache/thrift/TestShortStack.java | 116 ------------------ .../thrift/protocol/TestShortStack.java | 42 +++++++ 5 files changed, 65 insertions(+), 141 deletions(-) rename lib/java/src/org/apache/thrift/{ => protocol}/ShortStack.java (74%) delete mode 100644 lib/java/test/org/apache/thrift/TestShortStack.java create mode 100644 lib/java/test/org/apache/thrift/protocol/TestShortStack.java diff --git a/lib/java/README.md b/lib/java/README.md index cdd4059f1a4..0b5f0d802de 100644 --- a/lib/java/README.md +++ b/lib/java/README.md @@ -170,3 +170,7 @@ The access modifier of the AutoExpandingBuffer class has been changed from public to default (package) and will no longer be accessible by third-party libraries. +The access modifier of the ShortStack class has been changed from +public to default (package) and will no longer be accessible by third-party +libraries. + diff --git a/lib/java/src/org/apache/thrift/ShortStack.java b/lib/java/src/org/apache/thrift/protocol/ShortStack.java similarity index 74% rename from lib/java/src/org/apache/thrift/ShortStack.java rename to lib/java/src/org/apache/thrift/protocol/ShortStack.java index 4957d1c77b5..9e659307459 100644 --- a/lib/java/src/org/apache/thrift/ShortStack.java +++ b/lib/java/src/org/apache/thrift/protocol/ShortStack.java @@ -16,45 +16,43 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.thrift; +package org.apache.thrift.protocol; + +import java.util.Arrays; /** * 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 { +class ShortStack { private short[] vector; - private int top = -1; + + /** Always points to the next location */ + private int top = 0; public ShortStack(int initialCapacity) { vector = new short[initialCapacity]; } public short pop() { - return vector[top--]; + return vector[--top]; } public void push(short pushed) { - if (vector.length == top + 1) { + if (vector.length == top) { grow(); } - vector[++top] = pushed; + 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]; + vector = Arrays.copyOf(vector, vector.length << 1); } public void clear() { - top = -1; + top = 0; } @Override @@ -62,18 +60,15 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append(">"); - } - - sb.append(vector[i]); - - if (i == top) { - sb.append("<<"); + if (isTop) { + sb.append(">>").append(value).append("<<"); + } else { + sb.append(value); } } sb.append("]>"); diff --git a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java index af145ef0a85..ee0586945e0 100644 --- a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java +++ b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java @@ -24,7 +24,6 @@ import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; -import org.apache.thrift.ShortStack; import org.apache.thrift.TException; import org.apache.thrift.transport.TTransport; diff --git a/lib/java/test/org/apache/thrift/TestShortStack.java b/lib/java/test/org/apache/thrift/TestShortStack.java deleted file mode 100644 index 07831e526f0..00000000000 --- a/lib/java/test/org/apache/thrift/TestShortStack.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 org.apache.thrift; - -import java.util.Stack; - -import junit.framework.TestCase; - -public class TestShortStack extends TestCase { - private static final int NUM_TRIALS = 5; - private static final int NUM_REPS = 10000000; - - public void testOps() throws Exception { - ShortStack s = new ShortStack(10); - s.push((short)10); - s.push((short)11); - s.push((short)12); - assertEquals((short)12, s.peek()); - assertEquals((short)12, s.peek()); - assertEquals((short)12, s.pop()); - assertEquals((short)11, s.pop()); - s.push((short)40); - assertEquals((short)40, s.peek()); - assertEquals((short)40, s.pop()); - assertEquals((short)10, s.peek()); - assertEquals((short)10, s.pop()); - try { - s.peek(); - fail("should have thrown an exception!"); - } catch (Exception e) { - // yay - } - - try { - s.pop(); - fail("should have thrown an exception!"); - } catch (Exception e) { - // yay - } - } - - public void testGrow() throws Exception { - ShortStack s = new ShortStack(1); - s.push((short)1); - s.push((short)1); - s.push((short)1); - s.push((short)1); - s.push((short)1); - } - - public static void main(String[] args) throws Exception { - for (int trial = 0; trial < NUM_TRIALS; trial++) { - long start = System.currentTimeMillis(); - ShortStack s = new ShortStack(10); - for (int rep = 0; rep < NUM_REPS; rep++) { - s.push((short)1); - s.push((short)11); - s.push((short)111); - s.pop(); - s.pop(); - s.push((short)12); - s.push((short)121); - s.push((short)1211); - s.push((short)12111); - s.pop(); - s.pop(); - s.pop(); - s.pop(); - s.push((short)5); - s.pop(); - s.pop(); - } - long end = System.currentTimeMillis(); - System.out.println("ShortStack: " + (end-start)); - - start = System.currentTimeMillis(); - Stack stdStack = new Stack(); - for (int rep = 0; rep < NUM_REPS; rep++) { - stdStack.push((short)1); - stdStack.push((short)11); - stdStack.push((short)111); - stdStack.pop(); - stdStack.pop(); - stdStack.push((short)12); - stdStack.push((short)121); - stdStack.push((short)1211); - stdStack.push((short)12111); - stdStack.pop(); - stdStack.pop(); - stdStack.pop(); - stdStack.pop(); - stdStack.push((short)5); - stdStack.pop(); - stdStack.pop(); - } - end = System.currentTimeMillis(); - System.out.println("Built-in stack: " + (end-start)); - } - } -} diff --git a/lib/java/test/org/apache/thrift/protocol/TestShortStack.java b/lib/java/test/org/apache/thrift/protocol/TestShortStack.java new file mode 100644 index 00000000000..c8e78eee6a5 --- /dev/null +++ b/lib/java/test/org/apache/thrift/protocol/TestShortStack.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 org.apache.thrift.protocol; + +import junit.framework.TestCase; + +public class TestShortStack extends TestCase { + + public void testOps() throws Exception { + ShortStack s = new ShortStack(1); + s.push((short)10); + s.push((short)11); + s.push((short)12); + assertEquals((short)12, s.pop()); + assertEquals((short)11, s.pop()); + s.push((short)40); + assertEquals((short)40, s.pop()); + assertEquals((short)10, s.pop()); + try { + s.pop(); + fail("should have thrown an exception!"); + } catch (Exception e) { + // yay + } + } +} From 6503043bc42ab96da14c25f3aee2bb4add719774 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 3 Jan 2019 00:01:18 -0500 Subject: [PATCH 094/756] THRIFT-4714: optimize java TFramedTransport to call write once per flush --- .../AutoExpandingBufferWriteTransport.java | 30 ++++++++++++-- .../transport/TFastFramedTransport.java | 13 ++++--- .../thrift/transport/TFramedTransport.java | 17 ++++++-- ...TestAutoExpandingBufferWriteTransport.java | 39 +++++++++++++++---- .../transport/TestTFramedTransport.java | 4 +- 5 files changed, 81 insertions(+), 22 deletions(-) diff --git a/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java b/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java index ad2ec551bea..ec7e7d45a05 100644 --- a/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java +++ b/lib/java/src/org/apache/thrift/transport/AutoExpandingBufferWriteTransport.java @@ -25,10 +25,29 @@ public final class AutoExpandingBufferWriteTransport extends TTransport { private final AutoExpandingBuffer buf; private int pos; + private int res; - public AutoExpandingBufferWriteTransport(int initialCapacity) { + /** + * Constructor. + * @param initialCapacity the initial capacity of the buffer + * @param frontReserve space, if any, to reserve at the beginning such + * that the first write is after this reserve. + * This allows framed transport to reserve space + * for the frame buffer length. + * @throws IllegalArgumentException if initialCapacity is less than one + * @throws IllegalArgumentException if frontReserve is less than zero + * @throws IllegalArgumentException if frontReserve is greater than initialCapacity + */ + public AutoExpandingBufferWriteTransport(int initialCapacity, int frontReserve) { + if (initialCapacity < 1) { + throw new IllegalArgumentException("initialCapacity"); + } + if (frontReserve < 0 || initialCapacity < frontReserve) { + throw new IllegalArgumentException("frontReserve"); + } this.buf = new AutoExpandingBuffer(initialCapacity); - this.pos = 0; + this.pos = frontReserve; + this.res = frontReserve; } @Override @@ -56,11 +75,14 @@ public AutoExpandingBuffer getBuf() { return buf; } - public int getPos() { + /** + * @return length of the buffer, including any front reserve + */ + public int getLength() { return pos; } public void reset() { - pos = 0; + pos = res; } } diff --git a/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java b/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java index 891d7984562..a1fd2490aa9 100644 --- a/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TFastFramedTransport.java @@ -106,8 +106,8 @@ public TFastFramedTransport(TTransport underlying, int initialBufferCapacity, in this.underlying = underlying; this.maxLength = maxLength; this.initialBufferCapacity = initialBufferCapacity; - writeBuffer = new AutoExpandingBufferWriteTransport(initialBufferCapacity); readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity); + writeBuffer = new AutoExpandingBufferWriteTransport(initialBufferCapacity, 4); } @Override @@ -166,16 +166,19 @@ public void consumeBuffer(int len) { readBuffer.consumeBuffer(len); } + /** + * Only clears the read buffer! + */ public void clear() { readBuffer = new AutoExpandingBufferReadTransport(initialBufferCapacity); } @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); + int payloadLength = writeBuffer.getLength() - 4; + byte[] data = writeBuffer.getBuf().array(); + TFramedTransport.encodeFrameSize(payloadLength, data); + underlying.write(data, 0, payloadLength + 4); writeBuffer.reset(); underlying.flush(); } diff --git a/lib/java/src/org/apache/thrift/transport/TFramedTransport.java b/lib/java/src/org/apache/thrift/transport/TFramedTransport.java index fa531ef35e3..a006c3a6ac7 100644 --- a/lib/java/src/org/apache/thrift/transport/TFramedTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TFramedTransport.java @@ -65,17 +65,26 @@ public TTransport getTransport(TTransport base) { } } + /** + * Something to fill in the first four bytes of the buffer + * to make room for the frame size. This allows the + * implementation to write once instead of twice. + */ + private static final byte[] sizeFiller_ = new byte[] { 0x00, 0x00, 0x00, 0x00 }; + /** * Constructor wraps around another transport */ public TFramedTransport(TTransport transport, int maxLength) { transport_ = transport; maxLength_ = maxLength; + writeBuffer_.write(sizeFiller_, 0, 4); } public TFramedTransport(TTransport transport) { transport_ = transport; maxLength_ = TFramedTransport.DEFAULT_MAX_LENGTH; + writeBuffer_.write(sizeFiller_, 0, 4); } public void open() throws TTransportException { @@ -155,12 +164,12 @@ public void write(byte[] buf, int off, int len) throws TTransportException { @Override public void flush() throws TTransportException { byte[] buf = writeBuffer_.get(); - int len = writeBuffer_.len(); + int len = writeBuffer_.len() - 4; // account for the prepended frame size writeBuffer_.reset(); + writeBuffer_.write(sizeFiller_, 0, 4); // make room for the next frame's size data - encodeFrameSize(len, i32buf); - transport_.write(i32buf, 0, 4); - transport_.write(buf, 0, len); + encodeFrameSize(len, buf); // this is the frame length without the filler + transport_.write(buf, 0, len + 4); // we have to write the frame size and frame data transport_.flush(); } diff --git a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java index 6b04feb2ed6..86b5b0d0f45 100644 --- a/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java +++ b/lib/java/test/org/apache/thrift/transport/TestAutoExpandingBufferWriteTransport.java @@ -19,26 +19,51 @@ package org.apache.thrift.transport; import java.nio.ByteBuffer; +import org.junit.Test; +import static org.junit.Assert.*; -import junit.framework.TestCase; - -public class TestAutoExpandingBufferWriteTransport extends TestCase { +public class TestAutoExpandingBufferWriteTransport { + @Test public void testIt() throws Exception { - AutoExpandingBufferWriteTransport t = new AutoExpandingBufferWriteTransport(1); + AutoExpandingBufferWriteTransport t = new AutoExpandingBufferWriteTransport(1, 0); + assertEquals(0, t.getLength()); assertEquals(1, t.getBuf().array().length); byte[] b1 = new byte[]{1,2,3}; t.write(b1); - assertEquals(3, t.getPos()); + assertEquals(3, t.getLength()); assertTrue(t.getBuf().array().length >= 3); assertEquals(ByteBuffer.wrap(b1), ByteBuffer.wrap(t.getBuf().array(), 0, 3)); t.reset(); + assertEquals(0, t.getLength()); assertTrue(t.getBuf().array().length >= 3); - assertEquals(0, t.getPos()); byte[] b2 = new byte[]{4,5}; t.write(b2); - assertEquals(2, t.getPos()); + assertEquals(2, t.getLength()); assertEquals(ByteBuffer.wrap(b2), ByteBuffer.wrap(t.getBuf().array(), 0, 2)); + + AutoExpandingBufferWriteTransport uut = new AutoExpandingBufferWriteTransport(8, 4); + assertEquals(4, uut.getLength()); + assertEquals(8, uut.getBuf().array().length); + uut.write(b1); + assertEquals(7, uut.getLength()); + assertEquals(8, uut.getBuf().array().length); + assertEquals(ByteBuffer.wrap(b1), ByteBuffer.wrap(uut.getBuf().array(), 4, 3)); + } + + @Test(expected = IllegalArgumentException.class) + public void testBadInitialSize() throws IllegalArgumentException { + new AutoExpandingBufferWriteTransport(0, 0); + } + + @Test(expected = IllegalArgumentException.class) + public void testBadFrontReserveSize() throws IllegalArgumentException { + new AutoExpandingBufferWriteTransport(4, -1); + } + + @Test(expected = IllegalArgumentException.class) + public void testTooSmallFrontReserveSize() throws IllegalArgumentException { + new AutoExpandingBufferWriteTransport(4, 5); } } diff --git a/lib/java/test/org/apache/thrift/transport/TestTFramedTransport.java b/lib/java/test/org/apache/thrift/transport/TestTFramedTransport.java index 7e889d68d56..e30d74b0758 100644 --- a/lib/java/test/org/apache/thrift/transport/TestTFramedTransport.java +++ b/lib/java/test/org/apache/thrift/transport/TestTFramedTransport.java @@ -125,11 +125,11 @@ public void testWrite() throws TTransportException, IOException { assertEquals(0, countingTrans.writeCount); trans.flush(); - assertEquals(2, countingTrans.writeCount); + assertEquals(1, countingTrans.writeCount); trans.write(byteSequence(0, 245)); trans.flush(); - assertEquals(4, countingTrans.writeCount); + assertEquals(2, countingTrans.writeCount); DataInputStream din = new DataInputStream(new ByteArrayInputStream(baos.toByteArray())); assertEquals(256, din.readInt()); From d5324413664a44da1cbdf671e0fe00b8571c2b4b Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Fri, 4 Jan 2019 10:30:32 -0500 Subject: [PATCH 095/756] THRIFT-4368: Fix guaranteed NPE in TBaseAsyncProcessor.java wq# Please enter the commit message for your changes. Lines starting --- .../org/apache/thrift/TBaseAsyncProcessor.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java b/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java index 9459c1ae418..0ab1827dc20 100644 --- a/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java +++ b/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java @@ -54,8 +54,13 @@ public boolean process(final AsyncFrameBuffer fb) throws TException { 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+"'"); + + TApplicationException x = new TApplicationException(TApplicationException.UNKNOWN_METHOD, + "Invalid method name: '" + msg.name + "'"); + LOGGER.debug("Invalid method name", x); + + // this means it is a two-way request, so we can send a reply + if (msg.type == TMessageType.CALL) { out.writeMessageBegin(new TMessage(msg.name, TMessageType.EXCEPTION, msg.seqid)); x.write(out); out.writeMessageEnd(); @@ -72,8 +77,12 @@ public boolean process(final AsyncFrameBuffer fb) throws TException { args.read(in); } catch (TProtocolException e) { in.readMessageEnd(); + + TApplicationException x = new TApplicationException(TApplicationException.PROTOCOL_ERROR, + e.getMessage()); + LOGGER.debug("Could not retrieve function arguments", x); + 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(); @@ -93,6 +102,7 @@ public boolean process(final AsyncFrameBuffer fb) throws TException { try { fn.start(iface, args, resultHandler); } catch (Exception e) { + LOGGER.debug("Exception handling function", e); resultHandler.onError(e); } return true; From ecebd77c4a19919471345c21e797d55c5f83c22b Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 28 Dec 2018 08:50:58 -0500 Subject: [PATCH 096/756] THRIFT-4716: add veralign.sh tool to set versions for releases --- bower.json | 3 +- configure.ac | 2 +- .../Transports/Client/THttpClientTransport.cs | 2 +- test/csharp/ThriftTest.csproj | 2 +- veralign.sh | 313 ++++++++++++++++++ 5 files changed, 317 insertions(+), 5 deletions(-) create mode 100755 veralign.sh diff --git a/bower.json b/bower.json index 436a2cf356b..853b8cbbf19 100644 --- a/bower.json +++ b/bower.json @@ -11,6 +11,5 @@ "thrift" ], "license": "Apache v2", - "ignore": [ - ] + "ignore": [] } diff --git a/configure.ac b/configure.ac index fa507561ffd..e04891f368c 100755 --- a/configure.ac +++ b/configure.ac @@ -158,7 +158,7 @@ if test "$with_cpp" = "yes"; then have_cpp="yes" fi - AX_LIB_EVENT([1.0]) + AX_LIB_EVENT([2.0]) have_libevent=$success AX_LIB_ZLIB([1.2.3]) diff --git a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs index 60671414e9a..797d3803e5d 100644 --- a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs +++ b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs @@ -149,7 +149,7 @@ private HttpClient CreateClient() } httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); - httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "0.12.0")); + httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "1.0.0")); if (CustomHeaders != null) { diff --git a/test/csharp/ThriftTest.csproj b/test/csharp/ThriftTest.csproj index 363627fdfe2..63629eb7ca5 100644 --- a/test/csharp/ThriftTest.csproj +++ b/test/csharp/ThriftTest.csproj @@ -46,7 +46,7 @@ false true 0 - 0.12.0.%2a + 1.0.0.0 false true
diff --git a/veralign.sh b/veralign.sh new file mode 100755 index 00000000000..380aa48311e --- /dev/null +++ b/veralign.sh @@ -0,0 +1,313 @@ +#!/usr/bin/env bash +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# +# The veralign script sets the appropriate versions in all of +# the package configuration files for all of the supported +# languages. It is used to prepare a release or move master +# forward to the next anticipated version. +# +# USAGE +# ----------------------------------------------------------- +# usage: veralign.sh +# +# EXAMPLE +# ----------------------------------------------------------- +# $ ./veralign.sh 0.12.0 1.0.0 +# $ ./veralign.sh 1.0.0 1.1.0 +# +# IMPORTANT USAGE NOTE +# ----------------------------------------------------------- +# Define the environment variable DRYRUN to have the script +# print out all matches to the oldVersion hilighted so that +# you can verify it will change the right things. +# + +declare -A FILES + +# These files require a manual touch: +FILES[CHANGES]=manual +FILES[debian/changelog]=manual +FILES[doap.rdf]=manual + +# These files can be updated automatically: +FILES[ApacheThrift.nuspec]=simpleReplace +FILES[Thrift-swift3.podspec]=simpleReplace +FILES[Thrift.podspec]=simpleReplace +FILES[appveyor.yml]=simpleReplace +FILES[bower.json]=jsonReplace +FILES[build/cmake/DefineCMakeDefaults.cmake]=simpleReplace +FILES[configure.ac]=configureReplace +FILES[contrib/thrift.spec]=simpleReplace +FILES[lib/cocoa/src/Thrift.h]=simpleReplace +FILES[lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs]=simpleReplace +FILES[lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj]=simpleReplace +FILES[lib/csharp/src/Properties/AssemblyInfo.cs]=simpleReplace +FILES[lib/csharp/src/Thrift.csproj]=simpleReplace +FILES[lib/csharp/test/Multiplex/Client/MultiplexClient.csproj]=simpleReplace +FILES[lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs]=simpleReplace +FILES[lib/csharp/test/Multiplex/Server/MultiplexServer.csproj]=simpleReplace +FILES[lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs]=simpleReplace +FILES[lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs]=simpleReplace +FILES[lib/d/src/thrift/base.d]=simpleReplace +FILES[lib/dart/pubspec.yaml]=pubspecReplace +FILES[lib/delphi/src/Thrift.pas]=simpleReplace +FILES[lib/erl/src/thrift.app.src]=simpleReplace +FILES[lib/haxe/haxelib.json]=simpleReplace +FILES[lib/hs/thrift.cabal]=simpleReplace +FILES[lib/java/gradle.properties]=simpleReplace +FILES[lib/js/package.json]=jsonReplace +FILES[lib/js/src/thrift.js]=simpleReplace +FILES[lib/lua/Thrift.lua]=simpleReplace +FILES[lib/netcore/Thrift/Properties/AssemblyInfo.cs]=simpleReplace +FILES[lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs]=simpleReplace +FILES[lib/ocaml/_oasis]=simpleReplace +FILES[lib/perl/lib/Thrift.pm]=simpleReplace +FILES[lib/py/setup.py]=simpleReplace +FILES[lib/rb/thrift.gemspec]=simpleReplace +FILES[lib/rs/Cargo.toml]=simpleReplace +FILES[lib/st/package.xml]=simpleReplace +FILES[package.json]=jsonReplace +FILES[sonar-project.properties]=simpleReplace +FILES[test/csharp/Properties/AssemblyInfo.cs]=simpleReplace +FILES[test/csharp/ThriftTest.csproj]=simpleReplace +FILES[test/dart/test_client/pubspec.yaml]=pubspecReplace +FILES[test/erl/src/thrift_test.app.src]=simpleReplace +FILES[tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs]=simpleReplace +FILES[tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs]=simpleReplace +FILES[tutorial/dart/client/pubspec.yaml]=pubspecReplace +FILES[tutorial/dart/console_client/pubspec.yaml]=pubspecReplace +FILES[tutorial/dart/server/pubspec.yaml]=pubspecReplace +FILES[tutorial/delphi/DelphiClient/DelphiClient.dproj]=simpleReplace +FILES[tutorial/delphi/DelphiServer/DelphiServer.dproj]=simpleReplace +FILES[tutorial/hs/ThriftTutorial.cabal]=simpleReplace +FILES[tutorial/ocaml/_oasis]=simpleReplace + +if [ ! -f "CHANGES" ]; then + >&2 echo "error: run veralign.sh while in the thrift root directory" + exit 1 +fi + +if [ $# -ne 2 ]; then + >&2 echo "usage: veralign.sh " + exit 1 +fi + +jq --version 1>/dev/null 2>/dev/null +if [ $? -ne 0 ]; then + >&2 echo "error: the 'jq' package is not installed" + exit 1 +fi + +# +# validateVersion: check that a version matches the major.minor.patch +# format which is the lowest common denominator supported by all +# project systems. +# \param $1 the version +# \returns 0 if the version is compliant +# +function validateVersion +{ + local result + local valid + valid=$(echo "$1" | sed '/^[[:digit:]]\+\.[[:digit:]]\+\.[[:digit:]]\+$/!{q22}') + result=$? + if [ $result -eq 22 ]; then + >&2 echo "error: version '$1' does not conform to the required major.minor.patch format" + return ${result} + fi +} + +OLDVERSION=$1 +NEWVERSION=$2 +validateVersion "${OLDVERSION}" || exit $? +validateVersion "${NEWVERSION}" || exit $? + +# +# escapeVersion: escape the version for use as a sed search +# \param $1 the version to escape +# \output the escaped string +# \returns 0 +# \example VERSEARCH=$(escapeVersion "[1.0.0]"); echo $VERSEARCH; => "\[1\.0\.0\]" +# +function escapeVersion +{ + echo "$(echo $1 | sed 's/\./\\./g' | sed 's/\[/\\\[/g' | sed 's/\]/\\\]/g')" +} + +# Set up verbose hilighting if running interactive +if [ "$(tput colors)" -ne 0 ]; then + reverse=$(tput rev) + red=$(tput setaf 1) + green=$(tput setaf 2) + yellow=$(tput setaf 3) + normal=$(tput sgr0) +fi + +declare -A MANUAL + +# +# manual: note that update of said file is manual +# \param $1 filename to do replacements on +# \returns 0 +# +function manual +{ + MANUAL["$1"]="" + return 0 +} + +# +# configureReplace: replace the AC_INIT field in configure.ac +# \param $1 filename to do replacements on +# \returns 0 on success +# + +function configureReplace +{ + replace "$1" "[thrift], [${OLDVERSION}]" "[thrift], [${NEWVERSION}]" +} + +# +# jsonReplace: replace a specific version field in a JSON file +# must be a top level "version" field in the json structure +# \param $1 filename to do replacements on +# \returns 0 on success +# + +function jsonReplace +{ + local result + local output + if [ ! -z "$DRYRUN" ]; then + output=$(jq -e ".version" "$1") + else + output=$(jq -e ".version = \"${NEWVERSION}\"" "$1" > tmp.$$.json && mv tmp.$$.json "$1") + fi + result=$? + if [ $? -ne 0 ]; then + printf "%-60s | %5d | ${red}ERROR${normal}: version tag not found" "$1" "$count" + echo + return 1 + elif [ ! -z "$DRYRUN" ]; then + output=${output%\"} + output=${output#\"} + printf "%-60s | %5d | MATCHES: version: \"${reverse}${green}${output}${normal}\"" "$1" 1 + echo + return 0 + fi + printf "%-60s | %5d | ${green}OK${normal}" "$1" 1 + echo + return 0 +} + +# +# pubspecReplace: replace a specific version field in a YAML file +# must be a top level "version" field in the yaml structure +# did not find a package that preserves comments so this is +# somewhat brain-dead, but it gets the job done +# \param $1 filename to do replacements on +# \returns 0 on success +# + +function pubspecReplace +{ + replace "$1" "version: ${OLDVERSION}" "version: ${NEWVERSION}" +} + +# +# replace: replace occurrences of one string with another +# the file specified must contain the old string at least once +# in order to be successful. +# \param $1 filename to do replacements on +# \param $2 the "old" string to be replaced +# \param $3 the "new" striing to replace it with +# \returns 0 on success +# +function replace +{ + local result + local output + local oldString="$2" + local newString="$3" + local oldRegex=$(escapeVersion "${oldString}") + local count=$(grep -Ec "${oldRegex}" "$1") + local verbose + if [ $count -eq 0 ]; then + printf "%-60s | %5d | ${red}NOT FOUND${normal}: ${oldString}" "$1" 0 + echo + return 1 + elif [ ! -z "$DRYRUN" ]; then + printf "%-60s | %5d | MATCHES:" "$1" "$count" + echo + while read -r line; do + echo " > $(echo "$line" | sed "s/${oldRegex}/${reverse}${green}${oldString}${normal}/g")" + done < <(grep -E "${oldRegex}" "$1") + return 0 + fi + output=$(sed -i "s/${oldRegex}/${newString}/g" "$1") + result=$? + if [ $result -ne 0 ]; then + printf "%-60s | %5d | ${red}ERROR${normal}: %s" "$1" "$count" "$output" + echo + return 1 + fi + printf "%-60s | %5d | ${green}OK${normal}" "$1" "$count" + echo + return 0 +} + +# +# simpleReplace: replace occurrences of ${OLDVERSION} with ${NEWVERSION} +# the file specified must contain OLDVERSION at least once +# in order to be successful. +# \param $1 filename to do replacements on +# \param $2 the "old" string to be replaced +# \param $3 the "new" striing to replace it with +# \returns 0 on success +# +function simpleReplace +{ + replace "$1" "${OLDVERSION}" "${NEWVERSION}" +} + +echo "" +echo "Apache Thrift Version Alignment Tool" +echo "------------------------------------" +echo "" +echo "Previous Version: ${OLDVERSION}" +echo " New Version: ${NEWVERSION}" +echo "" +echo "-------------------------------------------------------------+-------+----------------------" +echo "Filename | Count | Status " +echo "-------------------------------------------------------------+-------+----------------------" + +for file in $(echo "${!FILES[@]}" | sort); do + ${FILES[$file]} $file || exit $? +done + +echo +echo "Files that must be modified manually:" +echo +for manu in $(echo "${!MANUAL[@]}" | sort); do + echo " > ${yellow}${manu}${normal}" +done + +exit 0 From abf3aa5810bc641f566b95b9748dabe2284baafb Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 4 Jan 2019 17:21:02 -0500 Subject: [PATCH 097/756] update language levels in docker build image (bionic) and readmes --- LANGUAGES.md | 24 ++++++++++++------------ build/docker/README.md | 22 +++++++++++----------- build/docker/ubuntu-bionic/Dockerfile | 22 +++++++++++----------- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/LANGUAGES.md b/LANGUAGES.md index acf908343fb..24a3cf5cebc 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -48,7 +48,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u C (glib) 0.6.0 YesYes -2.48.22.54.0 +2.48.22.56.0 YesYesYesYes Yes YesYesYes @@ -92,7 +92,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Common Lisp 0.12.0 Yes -SBCL 1.4.5SBCL 1.4.9 +SBCL 1.4.5SBCL 1.4.15 YesYes Yes YesYesYes @@ -103,7 +103,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Dlang 0.9.0 Yes -2.075.12.081.0 +2.075.12.083.2 YesYesYesYesYes YesYesYes YesYesYes @@ -136,7 +136,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u .NET Core 0.11.0 Yes -2.1.4 +2.1.42.2.101 YesYesYesYes YesYes YesYesYesYes @@ -158,7 +158,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Go 0.7.0 Yes -1.7.61.10.3 +1.7.61.11.4 YesYesYes YesYesYes YesYesYesYes @@ -191,7 +191,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Java (SE) 0.2.0 YesYes -1.8.0_151 +1.8.0_1511.8.0_191 YesYesYesYes YesYesYes YesYesYesYes @@ -235,7 +235,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u node.js 0.6.0 Yes -6.x8.11.3 +6.x8.x YesYesYes YesYes YesYesYesYes @@ -268,7 +268,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Perl 0.2.0 Yes -5.22.15.26.0 +5.22.15.26.1 YesYesYesYes YesYes YesYesYes @@ -279,7 +279,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u PHP 0.2.0 Yes -7.0.227.1.8 +7.0.227.2.10 YesYesYes YesYes YesYesYesYes @@ -290,7 +290,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Python 0.2.0 YesYes -2.7.12, 3.5.22.7.14, 3.6.3 +2.7.12, 3.5.22.7.15rc1, 3.6.7 YesYes YesYes YesYesYesYes @@ -301,7 +301,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Ruby 0.2.0 Yes -2.3.1p1122.3.3p222 +2.3.1p1122.5.1p57 YesYesYesYes YesYes YesYesYesYes @@ -312,7 +312,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Rust 0.11.0 Yes -1.17.01.21.0 +1.17.01.30.0 YesYes Yes YesYesYes diff --git a/build/docker/README.md b/build/docker/README.md index d0a83886f88..966d690c9de 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -167,32 +167,32 @@ Last updated: October 1, 2017 | Language | ubuntu-xenial | ubuntu-bionic | Notes | | :-------- | :------------ | :------------ | :---- | -| as of | Mar 06, 2018 | Jul 6, 2018 | | +| as of | Mar 06, 2018 | Jan 4, 2019 | | | as3 | | | Not in CI | | C++ gcc | 5.4.0 | 7.3.0 | | | C++ clang | 3.8 | 6.0 | | | C# (mono) | 4.2.1.0 | 4.6.2.7 | | | c_glib | 2.48.2 | 2.56.0 | | -| cl (sbcl) | | 1.4.9 | | +| cl (sbcl) | | 1.4.15 | | | cocoa | | | Not in CI | -| d | 2.075.1 | 2.081.0 | | +| d | 2.075.1 | 2.083.1 | | | dart | 1.22.1 | 1.24.3 | | | delphi | | | Not in CI | -| dotnet | 2.1.4 | 2.1.301 | | +| dotnet | 2.1.4 | 2.2.101 | | | erlang | 18.3 | 20.2.2 | | -| go | 1.7.6 | 1.10.3 | | +| go | 1.7.6 | 1.11.4 | | | haskell | 7.10.3 | 8.0.2 | | | haxe | 3.2.1 | 3.4.4 | THRIFT-4352: avoid 3.4.2 | -| java | 1.8.0_151 | 1.8.0_171 | | +| java | 1.8.0_151 | 1.8.0_191 | | | js | | | Unsure how to look for version info? | | lua | 5.2.4 | 5.2.4 | Lua 5.3: see THRIFT-4386 | -| nodejs | 6.13.0 | 8.11.3 | | +| nodejs | 6.13.0 | 8.15.0 | | | ocaml | | 4.05.0 | THRIFT-4517: ocaml 4.02.3 on xenial appears broken | | perl | 5.22.1 | 5.26.1 | | -| php | 7.0.22 | 7.2.5 | | +| php | 7.0.22 | 7.2.10 | | | python | 2.7.12 | 2.7.15rc1 | | -| python3 | 3.5.2 | 3.6.5 | | +| python3 | 3.5.2 | 3.6.7 | | | ruby | 2.3.1p112 | 2.5.1p57 | | -| rust | 1.17.0 | 1.24.1 | | +| rust | 1.17.0 | 1.30.0 | | | smalltalk | | | Not in CI | -| swift | | | Not in CI | +| swift | | 4.2.1 | | diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index 5ad4c845e55..43c99a95174 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -89,11 +89,11 @@ RUN apt-get install -y --no-install-recommends \ `# csharp (mono) dependencies` \ mono-devel -ENV SBCL_VERSION 1.4.12 +ENV SBCL_VERSION 1.4.15 RUN \ `# Common Lisp (sbcl) dependencies` \ curl --version && \ - curl -O -J -L https://kent.dl.sourceforge.net/project/sbcl/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \ + curl -o sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 -J -L https://sourceforge.net/projects/sbcl/files/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2/download?use_mirror=managedway# && \ tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \ cd sbcl-${SBCL_VERSION}-x86-64-linux && \ ./install.sh && \ @@ -101,18 +101,18 @@ RUN \ cd .. && \ rm -rf sbcl* -ENV D_VERSION 2.082.1 -ENV DMD_DEB dmd_2.082.1-0_amd64.deb +ENV D_VERSION 2.083.1 +ENV DMD_DEB dmd_2.083.1-0_amd64.deb RUN \ `# D dependencies` \ wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \ dpkg --install ${DMD_DEB} && \ rm -f ${DMD_DEB} && \ mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ - curl -sSL https://github.com/D-Programming-Deimos/libevent/archive/master.tar.gz| tar xz && \ - mv libevent-master/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ - mv libevent-master/C/* /usr/include/dmd/druntime/import/C/ && \ - rm -rf libevent-master && \ + git clone -b 'v2.0.2+2.0.16' https://github.com/D-Programming-Deimos/libevent.git deimos-libevent-2.0 && \ + mv deimos-libevent-2.0/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ + mv deimos-libevent-2.0/C/* /usr/include/dmd/druntime/import/C/ && \ + rm -rf deimos-libevent-2.0 && \ git clone -b 'v2.0.0+1.1.0h' https://github.com/D-Programming-Deimos/openssl.git deimos-openssl-1.1.0h && \ mv deimos-openssl-1.1.0h/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \ @@ -125,7 +125,7 @@ ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ - dotnet-sdk-2.1 + dotnet-sdk-2.2 RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ @@ -140,9 +140,9 @@ RUN apt-get install -y --no-install-recommends \ libglib2.0-dev # golang -ENV GOLANG_VERSION 1.11.1 +ENV GOLANG_VERSION 1.11.4 ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz -ENV GOLANG_DOWNLOAD_SHA256 2871270d8ff0c8c69f161aaae42f9f28739855ff5c5204752a8d92a1c9f63993 +ENV GOLANG_DOWNLOAD_SHA256 fb26c30e6a04ad937bbc657a1b5bba92f80096af1e8ee6da6430c045a8db3a5b RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ From 414f9a5bf6372844274b0adee7263f4d03ed8e70 Mon Sep 17 00:00:00 2001 From: Nephi Allred Date: Wed, 2 Jan 2019 16:34:51 -0700 Subject: [PATCH 098/756] Skip native extension for jruby --- lib/rb/Rakefile | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/rb/Rakefile b/lib/rb/Rakefile index cdecaa68c1d..5e5e5acaa99 100644 --- a/lib/rb/Rakefile +++ b/lib/rb/Rakefile @@ -71,6 +71,7 @@ end desc "Build the native library" task :build_ext => :'gen-rb' do + next if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/ Dir::chdir(File::dirname('ext/extconf.rb')) do unless sh "ruby #{File::basename('ext/extconf.rb')}" $stderr.puts "Failed to run extconf" From 41d5d3a9ef5f6c90b0bff1a6e5f785841c11c15b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E5=BC=82=E9=9B=84?= Date: Fri, 4 Jan 2019 20:30:14 +0800 Subject: [PATCH 099/756] Fix: do not reconnect if connection.destroyed, prevent connection leak --- lib/nodejs/lib/thrift/connection.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/nodejs/lib/thrift/connection.js b/lib/nodejs/lib/thrift/connection.js index b54545436d3..06481db783f 100644 --- a/lib/nodejs/lib/thrift/connection.js +++ b/lib/nodejs/lib/thrift/connection.js @@ -221,6 +221,10 @@ Connection.prototype.connection_gone = function () { }); this.retry_timer = setTimeout(function () { + if (self.connection.destroyed) { + return; + } + log.debug("Retrying connection..."); self.retry_totaltime += self.retry_delay; From b239b0a53b016ea55939b6fd667955762bd56909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E5=BC=82=E9=9B=84?= Date: Fri, 4 Jan 2019 20:31:32 +0800 Subject: [PATCH 100/756] Style: fix style --- lib/nodejs/lib/thrift/connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/nodejs/lib/thrift/connection.js b/lib/nodejs/lib/thrift/connection.js index 06481db783f..15d955b95bd 100644 --- a/lib/nodejs/lib/thrift/connection.js +++ b/lib/nodejs/lib/thrift/connection.js @@ -222,7 +222,7 @@ Connection.prototype.connection_gone = function () { this.retry_timer = setTimeout(function () { if (self.connection.destroyed) { - return; + return; } log.debug("Retrying connection..."); From 0f7904562771ba2c04e0836dfa6eb7771bf3a6a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E5=BC=82=E9=9B=84?= Date: Sat, 5 Jan 2019 11:05:38 +0800 Subject: [PATCH 101/756] Fix: free useless timer --- lib/nodejs/lib/thrift/connection.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/nodejs/lib/thrift/connection.js b/lib/nodejs/lib/thrift/connection.js index 15d955b95bd..9e5c063cffd 100644 --- a/lib/nodejs/lib/thrift/connection.js +++ b/lib/nodejs/lib/thrift/connection.js @@ -222,6 +222,7 @@ Connection.prototype.connection_gone = function () { this.retry_timer = setTimeout(function () { if (self.connection.destroyed) { + self.retry_timer = null; return; } From d2c6dc8e44e40a2b439a8aaadd224e2960a08f9e Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 5 Jan 2019 09:33:02 -0500 Subject: [PATCH 102/756] THRIFT-4724: fix dub.json dependencies limit on openssl deimos --- dub.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dub.json b/dub.json index 1e268600e56..af76afc0c9e 100644 --- a/dub.json +++ b/dub.json @@ -11,10 +11,10 @@ "version": "~>2.0.2" }, "openssl": { - "version": "~>1.1.6" + "version": ">=1.1.6" } }, - "systemDependencies": "requires openssl 1.0 until deimos module is updated", + "systemDependencies": "On systems with native openssl 1.0.x use dub package openssl~>1.1, on systems with native openssl 1.1.x use dub package openssl~>2.0", "targetType": "library", "sourcePaths": [ "lib/d/src" From 93e8ec2d6a372cd6f68b7c11508ff7f8ea043f08 Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Sun, 6 Jan 2019 15:20:02 -0500 Subject: [PATCH 103/756] THRIFT-4726: Remove SLF4J Logging Guards --- .../org/apache/thrift/server/TThreadPoolServer.java | 8 +++----- .../org/apache/thrift/transport/TSaslTransport.java | 12 +++++------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java index 3b5f21e84c5..1697ad6ae4b 100644 --- a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java +++ b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java @@ -320,11 +320,9 @@ public void run() { // Ignore err-logging all transport-level/type exceptions if ((realCause != null && realCause instanceof TTransportException) || (x instanceof TTransportException)) { - if (LOGGER.isDebugEnabled()) { - // Write to debug, just in case the exception gets required - LOGGER - .debug("Received TTransportException during processing of message, ignoring: ", x); - } + LOGGER.debug( + "Received TTransportException during processing of message. Ignoring.", + x); } else { // Log the exception at error level and continue LOGGER.error("Error occurred during processing of message.", x); diff --git a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java index 80f35571057..bed3b395ede 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java @@ -158,9 +158,9 @@ protected void sendSaslMessage(NegotiationStatus status, byte[] payload) throws 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); + LOGGER.debug("{}: Writing message with status {} and payload length {}", + getRole(), status, payload.length); + underlyingTransport.write(messageHeader); underlyingTransport.write(payload); underlyingTransport.flush(); @@ -197,10 +197,8 @@ protected SaslResponse receiveSaslMessage() throws TTransportException { String remoteMessage = new String(payload, StandardCharsets.UTF_8); throw new TTransportException("Peer indicated failure: " + remoteMessage); } - - if (LOGGER.isDebugEnabled()) - LOGGER.debug(getRole() + ": Received message with status {} and payload length {}", - status, payload.length); + LOGGER.debug("{}: Received message with status {} and payload length {}", + getRole(), status, payload.length); return new SaslResponse(status, payload); } From 3cf066708e29e8cef76102c82cb51e74dfdd0426 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 5 Jan 2019 10:03:19 +0800 Subject: [PATCH 104/756] force c++11 in cmake --- build/cmake/DefinePlatformSpecifc.cmake | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index a809c0723ff..e324f59d82d 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -97,21 +97,14 @@ elseif(WITH_STDTHREADS) endif() # C++ Language Level -set(CXX_LANGUAGE_LEVEL "C++${CMAKE_CXX_STANDARD}") -if (CMAKE_CXX_STANDARD_REQUIRED) - string(CONCAT CXX_LANGUAGE_LEVEL "${CXX_LANGUAGE_LEVEL} [compiler must support it]") -else() - string(CONCAT CXX_LANGUAGE_LEVEL "${CXX_LANGUAGE_LEVEL} [fallback to earlier if compiler does not support it]") +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) +if ((CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND NOT MINGW) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-variadic-macros -Wno-long-long") endif() -if (CMAKE_CXX_EXTENSIONS) - string(CONCAT CXX_LANGUAGE_LEVEL "${CXX_LANGUAGE_LEVEL} [with compiler-specific extensions]") -else() - if ((CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND NOT MINGW) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-variadic-macros -Wno-long-long") - endif() - if ((CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND NOT MINGW) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++11-long-long") - endif() +if ((CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND NOT MINGW) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++11-long-long") endif() if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") From 7b935597bac2336c7f4d282069ab4d78ca473543 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 10:04:25 +0800 Subject: [PATCH 105/756] use noexcept instead of throw() in library --- lib/cpp/src/thrift/TApplicationException.h | 4 ++-- lib/cpp/src/thrift/Thrift.h | 4 ++-- lib/cpp/src/thrift/protocol/TProtocolException.h | 4 ++-- lib/cpp/src/thrift/transport/TSSLSocket.cpp | 6 +++--- lib/cpp/src/thrift/transport/TSSLSocket.h | 14 +++++++------- .../src/thrift/transport/TTransportException.cpp | 2 +- lib/cpp/src/thrift/transport/TTransportException.h | 6 +++--- lib/cpp/src/thrift/transport/TZlibTransport.h | 2 +- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/cpp/src/thrift/TApplicationException.h b/lib/cpp/src/thrift/TApplicationException.h index 81d94249d67..60618fbe83c 100644 --- a/lib/cpp/src/thrift/TApplicationException.h +++ b/lib/cpp/src/thrift/TApplicationException.h @@ -57,7 +57,7 @@ class TApplicationException : public TException { TApplicationException(TApplicationExceptionType type, const std::string& message) : TException(message), type_(type) {} - virtual ~TApplicationException() throw() {} + virtual ~TApplicationException() noexcept {} /** * Returns an error code that provides information about the type of error @@ -67,7 +67,7 @@ class TApplicationException : public TException { */ TApplicationExceptionType getType() const { return type_; } - virtual const char* what() const throw() { + virtual const char* what() const noexcept { if (message_.empty()) { switch (type_) { case UNKNOWN: diff --git a/lib/cpp/src/thrift/Thrift.h b/lib/cpp/src/thrift/Thrift.h index e8e70eba044..b41d5d2a06f 100644 --- a/lib/cpp/src/thrift/Thrift.h +++ b/lib/cpp/src/thrift/Thrift.h @@ -82,9 +82,9 @@ class TException : public std::exception { TException(const std::string& message) : message_(message) {} - virtual ~TException() throw() {} + virtual ~TException() noexcept {} - virtual const char* what() const throw() { + virtual const char* what() const noexcept { if (message_.empty()) { return "Default TException."; } else { diff --git a/lib/cpp/src/thrift/protocol/TProtocolException.h b/lib/cpp/src/thrift/protocol/TProtocolException.h index 6e536b42956..10178e11a71 100644 --- a/lib/cpp/src/thrift/protocol/TProtocolException.h +++ b/lib/cpp/src/thrift/protocol/TProtocolException.h @@ -59,7 +59,7 @@ class TProtocolException : public apache::thrift::TException { TProtocolException(TProtocolExceptionType type, const std::string& message) : apache::thrift::TException(message), type_(type) {} - virtual ~TProtocolException() throw() {} + virtual ~TProtocolException() noexcept {} /** * Returns an error code that provides information about the type of error @@ -69,7 +69,7 @@ class TProtocolException : public apache::thrift::TException { */ TProtocolExceptionType getType() const { return type_; } - virtual const char* what() const throw() { + virtual const char* what() const noexcept { if (message_.empty()) { switch (type_) { case UNKNOWN: diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp index 251ef2f5bdc..5f8a2c0f8ac 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp @@ -1046,14 +1046,14 @@ void buildErrors(string& errors, int errno_copy, int sslerrno) { /** * Default implementation of AccessManager */ -Decision DefaultClientAccessManager::verify(const sockaddr_storage& sa) throw() { +Decision DefaultClientAccessManager::verify(const sockaddr_storage& sa) noexcept { (void)sa; return SKIP; } Decision DefaultClientAccessManager::verify(const string& host, const char* name, - int size) throw() { + int size) noexcept { if (host.empty() || name == NULL || size <= 0) { return SKIP; } @@ -1062,7 +1062,7 @@ Decision DefaultClientAccessManager::verify(const string& host, Decision DefaultClientAccessManager::verify(const sockaddr_storage& sa, const char* data, - int size) throw() { + int size) noexcept { bool match = false; if (sa.ss_family == AF_INET && size == sizeof(in_addr)) { match = (memcmp(&((sockaddr_in*)&sa)->sin_addr, data, size) == 0); diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.h b/lib/cpp/src/thrift/transport/TSSLSocket.h index ec30cc1491f..d8fd77e94f8 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.h +++ b/lib/cpp/src/thrift/transport/TSSLSocket.h @@ -335,7 +335,7 @@ class TSSLException : public TTransportException { TSSLException(const std::string& message) : TTransportException(TTransportException::INTERNAL_ERROR, message) {} - virtual const char* what() const throw() { + virtual const char* what() const noexcept { if (message_.empty()) { return "TSSLException"; } else { @@ -386,7 +386,7 @@ class AccessManager { * @param sa Peer IP address * @return True if the peer is trusted, false otherwise */ - virtual Decision verify(const sockaddr_storage& /* sa */) throw() { return DENY; } + virtual Decision verify(const sockaddr_storage& /* sa */) noexcept { return DENY; } /** * Determine whether the peer should be granted access or not. It's called * every time a DNS subjectAltName/common name is extracted from peer's @@ -402,7 +402,7 @@ class AccessManager { */ virtual Decision verify(const std::string& /* host */, const char* /* name */, - int /* size */) throw() { + int /* size */) noexcept { return DENY; } /** @@ -416,7 +416,7 @@ class AccessManager { */ virtual Decision verify(const sockaddr_storage& /* sa */, const char* /* data */, - int /* size */) throw() { + int /* size */) noexcept { return DENY; } }; @@ -426,9 +426,9 @@ typedef AccessManager::Decision Decision; class DefaultClientAccessManager : public AccessManager { public: // AccessManager interface - Decision verify(const sockaddr_storage& sa) throw(); - Decision verify(const std::string& host, const char* name, int size) throw(); - Decision verify(const sockaddr_storage& sa, const char* data, int size) throw(); + Decision verify(const sockaddr_storage& sa) noexcept; + Decision verify(const std::string& host, const char* name, int size) noexcept; + Decision verify(const sockaddr_storage& sa, const char* data, int size) noexcept; }; } } diff --git a/lib/cpp/src/thrift/transport/TTransportException.cpp b/lib/cpp/src/thrift/transport/TTransportException.cpp index 9e15dbd2875..a527317e08b 100644 --- a/lib/cpp/src/thrift/transport/TTransportException.cpp +++ b/lib/cpp/src/thrift/transport/TTransportException.cpp @@ -28,7 +28,7 @@ namespace apache { namespace thrift { namespace transport { -const char* TTransportException::what() const throw() { +const char* TTransportException::what() const noexcept { if (message_.empty()) { switch (type_) { case UNKNOWN: diff --git a/lib/cpp/src/thrift/transport/TTransportException.h b/lib/cpp/src/thrift/transport/TTransportException.h index dbbb9711c5c..fb5f00cd359 100644 --- a/lib/cpp/src/thrift/transport/TTransportException.h +++ b/lib/cpp/src/thrift/transport/TTransportException.h @@ -65,7 +65,7 @@ class TTransportException : public apache::thrift::TException { TTransportException(TTransportExceptionType type, const std::string& message, int errno_copy) : apache::thrift::TException(message + ": " + TOutput::strerror_s(errno_copy)), type_(type) {} - virtual ~TTransportException() throw() {} + virtual ~TTransportException() noexcept {} /** * Returns an error code that provides information about the type of error @@ -73,9 +73,9 @@ class TTransportException : public apache::thrift::TException { * * @return Error code */ - TTransportExceptionType getType() const throw() { return type_; } + TTransportExceptionType getType() const noexcept { return type_; } - virtual const char* what() const throw(); + virtual const char* what() const noexcept; protected: /** Just like strerror_r but returns a C++ string object. */ diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.h b/lib/cpp/src/thrift/transport/TZlibTransport.h index a0fb464d377..59acd69d011 100644 --- a/lib/cpp/src/thrift/transport/TZlibTransport.h +++ b/lib/cpp/src/thrift/transport/TZlibTransport.h @@ -38,7 +38,7 @@ class TZlibTransportException : public TTransportException { zlib_status_(status), zlib_msg_(msg == NULL ? "(null)" : msg) {} - virtual ~TZlibTransportException() throw() {} + virtual ~TZlibTransportException() noexcept {} int getZlibStatus() { return zlib_status_; } std::string getZlibMessage() { return zlib_msg_; } From e42cf5023e3fc7fddf7e6f897aa1fb7d4a090afc Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 10:05:48 +0800 Subject: [PATCH 106/756] use noexcept instead of throw() in compiler generated code --- compiler/cpp/src/thrift/generate/t_cpp_generator.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc index 3e8f728d244..08393028d97 100644 --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc @@ -1097,7 +1097,7 @@ void t_cpp_generator::generate_struct_declaration(ostream& out, } if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) { - out << endl << indent() << "virtual ~" << tstruct->get_name() << "() throw();" << endl; + out << endl << indent() << "virtual ~" << tstruct->get_name() << "() noexcept;" << endl; } // Declare all fields @@ -1226,7 +1226,7 @@ void t_cpp_generator::generate_struct_definition(ostream& out, // Destructor if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) { force_cpp_out << endl << indent() << tstruct->get_name() << "::~" << tstruct->get_name() - << "() throw() {" << endl; + << "() noexcept {" << endl; indent_up(); indent_down(); @@ -1598,7 +1598,7 @@ void t_cpp_generator::generate_exception_what_method_decl(std::ostream& out, if (external) { out << tstruct->get_name() << "::"; } - out << "what() const throw()"; + out << "what() const noexcept"; } namespace struct_ostream_operator_generator { From 0705d9956750b9d61d763c8d8e38bb98e86870eb Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 10:52:48 +0800 Subject: [PATCH 107/756] force c++11 in GNU autotools --- configure.ac | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index e04891f368c..9885e1b6498 100755 --- a/configure.ac +++ b/configure.ac @@ -102,10 +102,7 @@ AC_PROG_AWK AC_PROG_RANLIB AC_LANG([C++]) -AX_CXX_COMPILE_STDCXX_11([noext], [optional]) -if test "$ac_success" = "no"; then - CXXFLAGS="$CXXFLAGS -Wno-variadic-macros -Wno-long-long -Wno-c++11-long-long" -fi +AX_CXX_COMPILE_STDCXX_11([noext], [mandatory]) AM_EXTRA_RECURSIVE_TARGETS([style]) AC_SUBST(CPPSTYLE_CMD, 'find . -type f \( -iname "*.h" -or -iname "*.cpp" -or -iname "*.cc" -or -iname "*.tcc" \) -printf "Reformatting: %h/%f\n" -exec clang-format -i {} \;') From 83b65f06fa380ed94669bdb461344f4f6b591191 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 11:06:50 +0800 Subject: [PATCH 108/756] allow specifing CMAKE_CXX_STANDARD above c++11 --- build/cmake/DefinePlatformSpecifc.cmake | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index e324f59d82d..626f5e581b0 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -97,14 +97,25 @@ elseif(WITH_STDTHREADS) endif() # C++ Language Level -set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) -if ((CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND NOT MINGW) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-variadic-macros -Wno-long-long") +if (NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 11) +elseif (CMAKE_CXX_STANDARD EQUAL 98) + message(FATAL_ERROR "only C++11 or above C++ standard is supported") endif() -if ((CMAKE_CXX_COMPILER_ID MATCHES "Clang") AND NOT MINGW) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++11-long-long") + +if (CMAKE_CXX_STANDARD EQUAL 11) + # should not fallback to C++98 + set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif() + +set(CXX_LANGUAGE_LEVEL "C++${CMAKE_CXX_STANDARD}") +if (CMAKE_CXX_STANDARD_REQUIRED) + string(CONCAT CXX_LANGUAGE_LEVEL "${CXX_LANGUAGE_LEVEL} [compiler must support it]") +else() + string(CONCAT CXX_LANGUAGE_LEVEL "${CXX_LANGUAGE_LEVEL} [fallback to earlier if compiler does not support it]") +endif() +if (CMAKE_CXX_EXTENSIONS) + string(CONCAT CXX_LANGUAGE_LEVEL "${CXX_LANGUAGE_LEVEL} [with compiler-specific extensions]") endif() if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") From c109e019790a87ef1f874dfac3482ac45a57d3ab Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 13:45:07 +0800 Subject: [PATCH 109/756] remove boost::thread and boost::mutex code --- .travis.yml | 2 +- build/cmake/DefineOptions.cmake | 7 +- build/cmake/DefinePlatformSpecifc.cmake | 4 +- build/cmake/README-MSYS2.md | 2 +- build/cmake/README.md | 2 +- build/cmake/config.h.in | 3 - build/wincpp/build-thrift.bat | 1 - configure.ac | 18 -- contrib/transport-sample/ThriftCommon.h | 2 - lib/cpp/CMakeLists.txt | 9 +- lib/cpp/Makefile.am | 7 - .../src/thrift/concurrency/BoostMonitor.cpp | 214 ------------------ lib/cpp/src/thrift/concurrency/BoostMutex.cpp | 73 ------ .../thrift/concurrency/BoostThreadFactory.cpp | 162 ------------- .../thrift/concurrency/BoostThreadFactory.h | 63 ------ .../concurrency/PlatformThreadFactory.h | 8 +- lib/cpp/src/thrift/concurrency/Thread.h | 11 +- .../src/thrift/server/TNonblockingServer.cpp | 2 +- .../src/thrift/windows/TWinsockSingleton.cpp | 10 - .../src/thrift/windows/TWinsockSingleton.h | 12 - lib/cpp/src/thrift/windows/config.h | 3 - lib/cpp/test/CMakeLists.txt | 2 +- lib/cpp/test/Makefile.am | 2 - lib/cpp/test/TNonblockingSSLServerTest.cpp | 2 +- lib/cpp/test/TNonblockingServerTest.cpp | 2 +- lib/cpp/test/concurrency/ThreadManagerTests.h | 8 +- 26 files changed, 19 insertions(+), 612 deletions(-) delete mode 100644 lib/cpp/src/thrift/concurrency/BoostMonitor.cpp delete mode 100644 lib/cpp/src/thrift/concurrency/BoostMutex.cpp delete mode 100644 lib/cpp/src/thrift/concurrency/BoostThreadFactory.cpp delete mode 100644 lib/cpp/src/thrift/concurrency/BoostThreadFactory.h diff --git a/.travis.yml b/.travis.yml index e09b8a4a3be..96e0b5178ae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -142,7 +142,7 @@ jobs: - JOB="C++98 (Boost Thread)" - SCRIPT="cmake.sh" - BUILD_LIBS="CPP TESTING TUTORIALS" - - BUILD_ARG="-DCMAKE_CXX_STANDARD=98 -DCMAKE_CXX_STANDARD_REQUIRED=ON -DCMAKE_CXX_EXTENSIONS=OFF --DWITH_BOOSTTHREADS=ON -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF" + - BUILD_ARG="-DCMAKE_CXX_STANDARD=98 -DCMAKE_CXX_STANDARD_REQUIRED=ON -DCMAKE_CXX_EXTENSIONS=OFF -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF" - BUILD_ENV="-e CC=clang -e CXX=clang++" - script: build/docker/run.sh diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index f419229a0aa..43b73e498be 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -88,9 +88,7 @@ if(WITH_CPP) find_package(OpenSSL QUIET) CMAKE_DEPENDENT_OPTION(WITH_OPENSSL "Build with OpenSSL support" ON "OPENSSL_FOUND" OFF) - option(WITH_STDTHREADS "Build with C++ std::thread support" OFF) - CMAKE_DEPENDENT_OPTION(WITH_BOOSTTHREADS "Build with Boost threads support" OFF - "NOT WITH_STDTHREADS;Boost_FOUND" OFF) + option(WITH_STDTHREADS "Build with C++ std::thread support" ON) endif() CMAKE_DEPENDENT_OPTION(BUILD_CPP "Build C++ library" ON "BUILD_LIBRARIES;WITH_CPP;Boost_FOUND" OFF) @@ -107,7 +105,7 @@ CMAKE_DEPENDENT_OPTION(BUILD_C_GLIB "Build C (GLib) library" ON if(BUILD_CPP) set(boost_components) - if(WITH_BOOSTTHREADS OR BUILD_TESTING) + if(BUILD_TESTING) list(APPEND boost_components system thread) endif() if(BUILD_TESTING) @@ -206,7 +204,6 @@ message(STATUS " Library features:") message(STATUS " Build shared libraries: ${WITH_SHARED_LIB}") message(STATUS " Build static libraries: ${WITH_STATIC_LIB}") message(STATUS " Build with Boost static link library: ${WITH_BOOST_STATIC}") -message(STATUS " Build with Boost thread support: ${WITH_BOOSTTHREADS}") message(STATUS " Build with boost/tr1/functional (forced) ${WITH_BOOST_FUNCTIONAL}") message(STATUS " Build with boost/smart_ptr (forced) ${WITH_BOOST_SMART_PTR}") message(STATUS " Build with C++ std::thread support: ${WITH_STDTHREADS}") diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index 626f5e581b0..cbd5ca86704 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -90,9 +90,7 @@ add_definitions("-D__STDC_FORMAT_MACROS") add_definitions("-D__STDC_LIMIT_MACROS") # WITH_*THREADS selects which threading library to use -if(WITH_BOOSTTHREADS) - add_definitions("-DUSE_BOOST_THREAD=1") -elseif(WITH_STDTHREADS) +if(WITH_STDTHREADS) add_definitions("-DUSE_STD_THREAD=1") endif() diff --git a/build/cmake/README-MSYS2.md b/build/cmake/README-MSYS2.md index 02679e615a7..07cad92baa3 100644 --- a/build/cmake/README-MSYS2.md +++ b/build/cmake/README-MSYS2.md @@ -43,7 +43,7 @@ Use cmake to create a MinGW makefile, out of tree (assumes you are in the top le cmake -G"MinGW Makefiles" -DCMAKE_MAKE_PROGRAM=/mingw64/bin/mingw32-make \ -DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc.exe \ -DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++.exe \ - -DWITH_BOOSTTHREADS=ON -DWITH_LIBEVENT=OFF \ + -DWITH_LIBEVENT=OFF \ -DWITH_SHARED_LIB=OFF -DWITH_STATIC_LIB=ON \ -DWITH_JAVA=OFF -DWITH_PYTHON=OFF -DWITH_PERL=OFF \ ../thrift diff --git a/build/cmake/README.md b/build/cmake/README.md index ebc4f7da133..e5c128bc36c 100644 --- a/build/cmake/README.md +++ b/build/cmake/README.md @@ -30,7 +30,7 @@ or on Windows cmake -G "Visual Studio 12 2013 Win64" \ -DBOOST_ROOT=C:/3rdparty/boost_1_58_0 \ -DZLIB_ROOT=C:/3rdparty/zlib128-dll \ - -DWITH_SHARED_LIB=off -DWITH_BOOSTTHREADS=ON .. + -DWITH_SHARED_LIB=off .. and open the development environment you like with the solution or do this: diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index 39d8270aa3c..5f0ae4681c3 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -64,9 +64,6 @@ see: aclocal/ac_prog_bison.m4 */ #cmakedefine BISON_USE_PARSER_H_EXTENSION 1 -/* replaces POSIX pthread by boost::thread */ -#cmakedefine USE_BOOST_THREAD 1 - /* replaces POSIX pthread by std::thread */ #cmakedefine USE_STD_THREAD 1 diff --git a/build/wincpp/build-thrift.bat b/build/wincpp/build-thrift.bat index ba3e47675e2..b867acf2456 100644 --- a/build/wincpp/build-thrift.bat +++ b/build/wincpp/build-thrift.bat @@ -134,7 +134,6 @@ IF %OPT_GENERATE% == 1 ( -DOPENSSL_USE_STATIC_LIBS=OFF ^ -DZLIB_LIBRARY=%WIN3P_ROOT%\dist\zlib-%TP_ZLIB_VERSION%\%COMPILER%\%ARCH%\lib\zlib%ZLIB_LIB_SUFFIX%.lib ^ -DZLIB_ROOT=%WIN3P_ROOT%\dist\zlib-%TP_ZLIB_VERSION%\%COMPILER%\%ARCH% ^ - -DWITH_BOOSTTHREADS=ON ^ -DWITH_SHARED_LIB=OFF ^ -DWITH_STATIC_LIB=ON || EXIT /B diff --git a/configure.ac b/configure.ac index 9885e1b6498..21746292b27 100755 --- a/configure.ac +++ b/configure.ac @@ -785,24 +785,6 @@ AC_SUBST(GCOV_CFLAGS) AC_SUBST(GCOV_CXXFLAGS) AC_SUBST(GCOV_LDFLAGS) -AC_ARG_ENABLE(boostthreads, - [ --enable-boostthreads use boost threads, instead of POSIX pthread (experimental) ], - [case "${enableval}" in - yes) ENABLE_BOOSTTHREADS=1 ;; - no) ENABLE_BOOSTTHREADS=0 ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-cov) ;; - esac], - [ENABLE_BOOSTTHREADS=2]) - - -if test "x[$]ENABLE_BOOSTTHREADS" = "x1"; then - AC_MSG_WARN(enable boostthreads) - AC_DEFINE([USE_BOOST_THREAD], [1], [experimental --enable-boostthreads that replaces POSIX pthread by boost::thread]) - LIBS="-lboost_thread $LIBS" -fi - -AM_CONDITIONAL([WITH_BOOSTTHREADS], [test "x[$]ENABLE_BOOSTTHREADS" = "x1"]) - AC_CONFIG_HEADERS(config.h:config.hin) AC_CONFIG_HEADERS(lib/cpp/src/thrift/config.h:config.hin) AC_CONFIG_HEADERS(lib/c_glib/src/thrift/config.h:config.hin) diff --git a/contrib/transport-sample/ThriftCommon.h b/contrib/transport-sample/ThriftCommon.h index d24d1a7a749..e16d87dddf3 100644 --- a/contrib/transport-sample/ThriftCommon.h +++ b/contrib/transport-sample/ThriftCommon.h @@ -16,8 +16,6 @@ // #ifdef _WIN32 //thrift is crashing when using boost threads on Mac OSX -# define USE_BOOST_THREAD 1 -# include #else # include # include diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index 1ed0bfadfeb..9ea82c3dffc 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -103,14 +103,7 @@ if(OPENSSL_FOUND AND WITH_OPENSSL) endif() # WITH_*THREADS selects which threading library to use -if(WITH_BOOSTTHREADS) - set( thriftcpp_threads_SOURCES - src/thrift/concurrency/BoostThreadFactory.cpp - src/thrift/concurrency/BoostMonitor.cpp - src/thrift/concurrency/BoostMutex.cpp - ) - list(APPEND SYSLIBS "${Boost_LIBRARIES}") -elseif(UNIX AND NOT WITH_STDTHREADS) +if(UNIX AND NOT WITH_STDTHREADS) if(ANDROID) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") else() diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index 83ccd9b6f0f..11d6b051c2b 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -106,15 +106,9 @@ libthrift_la_SOURCES = src/thrift/TApplicationException.cpp \ src/thrift/server/TThreadPoolServer.cpp \ src/thrift/server/TThreadedServer.cpp -if WITH_BOOSTTHREADS -libthrift_la_SOURCES += src/thrift/concurrency/BoostThreadFactory.cpp \ - src/thrift/concurrency/BoostMonitor.cpp \ - src/thrift/concurrency/BoostMutex.cpp -else libthrift_la_SOURCES += src/thrift/concurrency/Mutex.cpp \ src/thrift/concurrency/Monitor.cpp \ src/thrift/concurrency/PosixThreadFactory.cpp -endif libthriftnb_la_SOURCES = src/thrift/server/TNonblockingServer.cpp \ src/thrift/async/TEvhttpServer.cpp \ @@ -170,7 +164,6 @@ include_thrift_HEADERS = \ include_concurrencydir = $(include_thriftdir)/concurrency include_concurrency_HEADERS = \ - src/thrift/concurrency/BoostThreadFactory.h \ src/thrift/concurrency/Exception.h \ src/thrift/concurrency/Mutex.h \ src/thrift/concurrency/Monitor.h \ diff --git a/lib/cpp/src/thrift/concurrency/BoostMonitor.cpp b/lib/cpp/src/thrift/concurrency/BoostMonitor.cpp deleted file mode 100644 index ebfa0b9dd9a..00000000000 --- a/lib/cpp/src/thrift/concurrency/BoostMonitor.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace apache { -namespace thrift { -namespace concurrency { - -/** - * Monitor implementation using the boost thread library - * - * @version $Id:$ - */ -class Monitor::Impl : public boost::condition_variable_any { - -public: - Impl() : ownedMutex_(new Mutex()), mutex_(NULL) { init(ownedMutex_.get()); } - - Impl(Mutex* mutex) : mutex_(NULL) { init(mutex); } - - Impl(Monitor* monitor) : mutex_(NULL) { init(&(monitor->mutex())); } - - Mutex& mutex() { return *mutex_; } - void lock() { mutex().lock(); } - void unlock() { mutex().unlock(); } - - /** - * Exception-throwing version of waitForTimeRelative(), called simply - * wait(int64) for historical reasons. Timeout is in milliseconds. - * - * If the condition occurs, this function returns cleanly; on timeout or - * error an exception is thrown. - */ - void wait(int64_t timeout_ms) { - int result = waitForTimeRelative(timeout_ms); - if (result == THRIFT_ETIMEDOUT) { - throw TimedOutException(); - } else if (result != 0) { - throw TException("Monitor::wait() failed"); - } - } - - /** - * Waits until the specified timeout in milliseconds for the condition to - * occur, or waits forever if timeout_ms == 0. - * - * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. - */ - int waitForTimeRelative(int64_t timeout_ms) { - if (timeout_ms == 0LL) { - return waitForever(); - } - - assert(mutex_); - boost::timed_mutex* mutexImpl - = reinterpret_cast(mutex_->getUnderlyingImpl()); - assert(mutexImpl); - - boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock); - int res - = timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(timeout_ms)) - ? 0 - : THRIFT_ETIMEDOUT; - lock.release(); - return res; - } - - /** - * Waits until the absolute time specified using struct THRIFT_TIMESPEC. - * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. - */ - int waitForTime(const THRIFT_TIMESPEC* abstime) { - struct timeval temp; - temp.tv_sec = static_cast(abstime->tv_sec); - temp.tv_usec = static_cast(abstime->tv_nsec) / 1000; - return waitForTime(&temp); - } - - /** - * Waits until the absolute time specified using struct timeval. - * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. - */ - int waitForTime(const struct timeval* abstime) { - assert(mutex_); - boost::timed_mutex* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); - assert(mutexImpl); - - struct timeval currenttime; - Util::toTimeval(currenttime, Util::currentTime()); - - long tv_sec = static_cast(abstime->tv_sec - currenttime.tv_sec); - long tv_usec = static_cast(abstime->tv_usec - currenttime.tv_usec); - if (tv_sec < 0) - tv_sec = 0; - if (tv_usec < 0) - tv_usec = 0; - - boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock); - int res = timed_wait(lock, - boost::get_system_time() + boost::posix_time::seconds(tv_sec) - + boost::posix_time::microseconds(tv_usec)) - ? 0 - : THRIFT_ETIMEDOUT; - lock.release(); - return res; - } - - /** - * Waits forever until the condition occurs. - * Returns 0 if condition occurs, or an error code otherwise. - */ - int waitForever() { - assert(mutex_); - boost::timed_mutex* mutexImpl - = reinterpret_cast(mutex_->getUnderlyingImpl()); - assert(mutexImpl); - - boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock); - ((boost::condition_variable_any*)this)->wait(lock); - lock.release(); - return 0; - } - - void notify() { notify_one(); } - - void notifyAll() { notify_all(); } - -private: - void init(Mutex* mutex) { mutex_ = mutex; } - - stdcxx::scoped_ptr ownedMutex_; - Mutex* mutex_; -}; - -Monitor::Monitor() : impl_(new Monitor::Impl()) { -} -Monitor::Monitor(Mutex* mutex) : impl_(new Monitor::Impl(mutex)) { -} -Monitor::Monitor(Monitor* monitor) : impl_(new Monitor::Impl(monitor)) { -} - -Monitor::~Monitor() { - delete impl_; -} - -Mutex& Monitor::mutex() const { - return const_cast(impl_)->mutex(); -} - -void Monitor::lock() const { - const_cast(impl_)->lock(); -} - -void Monitor::unlock() const { - const_cast(impl_)->unlock(); -} - -void Monitor::wait(int64_t timeout) const { - const_cast(impl_)->wait(timeout); -} - -int Monitor::waitForTime(const THRIFT_TIMESPEC* abstime) const { - return const_cast(impl_)->waitForTime(abstime); -} - -int Monitor::waitForTime(const timeval* abstime) const { - return const_cast(impl_)->waitForTime(abstime); -} - -int Monitor::waitForTimeRelative(int64_t timeout_ms) const { - return const_cast(impl_)->waitForTimeRelative(timeout_ms); -} - -int Monitor::waitForever() const { - return const_cast(impl_)->waitForever(); -} - -void Monitor::notify() const { - const_cast(impl_)->notify(); -} - -void Monitor::notifyAll() const { - const_cast(impl_)->notifyAll(); -} -} -} -} // apache::thrift::concurrency diff --git a/lib/cpp/src/thrift/concurrency/BoostMutex.cpp b/lib/cpp/src/thrift/concurrency/BoostMutex.cpp deleted file mode 100644 index 4e556df1702..00000000000 --- a/lib/cpp/src/thrift/concurrency/BoostMutex.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include - -#include -#include -#include - -#include -#include -#include -#include - -namespace apache { -namespace thrift { -namespace concurrency { - -/** - * Implementation of Mutex class using boost::timed_mutex - * - * Methods throw boost::lock_error on error. - * - * @version $Id:$ - */ -class Mutex::impl : public boost::timed_mutex {}; - -Mutex::Mutex(Initializer init) : impl_(new Mutex::impl()) { - THRIFT_UNUSED_VARIABLE(init); -} - -void* Mutex::getUnderlyingImpl() const { - return impl_.get(); -} - -void Mutex::lock() const { - impl_->lock(); -} - -bool Mutex::trylock() const { - return impl_->try_lock(); -} - -bool Mutex::timedlock(int64_t ms) const { - return impl_->timed_lock(boost::get_system_time() + boost::posix_time::milliseconds(ms)); -} - -void Mutex::unlock() const { - impl_->unlock(); -} - -void Mutex::DEFAULT_INITIALIZER(void* arg) { - THRIFT_UNUSED_VARIABLE(arg); -} -} -} -} // apache::thrift::concurrency diff --git a/lib/cpp/src/thrift/concurrency/BoostThreadFactory.cpp b/lib/cpp/src/thrift/concurrency/BoostThreadFactory.cpp deleted file mode 100644 index d7d8d54e902..00000000000 --- a/lib/cpp/src/thrift/concurrency/BoostThreadFactory.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include - -#if USE_BOOST_THREAD - -#include -#include -#include -#include - -#include - -namespace apache { -namespace thrift { - -using stdcxx::bind; -using stdcxx::scoped_ptr; -using stdcxx::shared_ptr; -using stdcxx::weak_ptr; - -namespace concurrency { - -/** - * The boost thread class. - * - * @version $Id:$ - */ -class BoostThread : public Thread { -public: - enum STATE { uninitialized, starting, started, stopping, stopped }; - - static void* threadMain(void* arg); - -private: - scoped_ptr thread_; - Monitor monitor_; - STATE state_; - weak_ptr self_; - bool detached_; - -public: - BoostThread(bool detached, shared_ptr runnable) - : state_(uninitialized), detached_(detached) { - this->Thread::runnable(runnable); - } - - ~BoostThread() { - if (!detached_ && thread_->joinable()) { - try { - join(); - } catch (...) { - // We're really hosed. - } - } - } - - STATE getState() const - { - Synchronized sync(monitor_); - return state_; - } - - void setState(STATE newState) - { - Synchronized sync(monitor_); - state_ = newState; - - // unblock start() with the knowledge that the thread has actually - // started running, which avoids a race in detached threads. - if (newState == started) { - monitor_.notify(); - } - } - - void start() { - // Create reference - shared_ptr* selfRef = new shared_ptr(); - *selfRef = self_.lock(); - - setState(starting); - - Synchronized sync(monitor_); - - thread_.reset(new boost::thread(bind(threadMain, (void*)selfRef))); - - if (detached_) - thread_->detach(); - - // Wait for the thread to start and get far enough to grab everything - // that it needs from the calling context, thus absolving the caller - // from being required to hold on to runnable indefinitely. - monitor_.wait(); - } - - void join() { - if (!detached_ && getState() != uninitialized) { - thread_->join(); - } - } - - Thread::id_t getId() { return thread_.get() ? thread_->get_id() : boost::thread::id(); } - - shared_ptr runnable() const { return Thread::runnable(); } - - void runnable(shared_ptr value) { Thread::runnable(value); } - - void weakRef(shared_ptr self) { - assert(self.get() == this); - self_ = weak_ptr(self); - } -}; - -void* BoostThread::threadMain(void* arg) { - shared_ptr thread = *(shared_ptr*)arg; - delete reinterpret_cast*>(arg); - - thread->setState(started); - thread->runnable()->run(); - - if (thread->getState() != stopping && thread->getState() != stopped) { - thread->setState(stopping); - } - return (void*)0; -} - -BoostThreadFactory::BoostThreadFactory(bool detached) - : ThreadFactory(detached) { -} - -shared_ptr BoostThreadFactory::newThread(shared_ptr runnable) const { - shared_ptr result = shared_ptr(new BoostThread(isDetached(), runnable)); - result->weakRef(result); - runnable->thread(result); - return result; -} - -Thread::id_t BoostThreadFactory::getCurrentThreadId() const { - return boost::this_thread::get_id(); -} -} -} -} // apache::thrift::concurrency - -#endif // USE_BOOST_THREAD diff --git a/lib/cpp/src/thrift/concurrency/BoostThreadFactory.h b/lib/cpp/src/thrift/concurrency/BoostThreadFactory.h deleted file mode 100644 index bf11a708bf8..00000000000 --- a/lib/cpp/src/thrift/concurrency/BoostThreadFactory.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_ -#define _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_ 1 - -#include -#include -#include - -namespace apache { -namespace thrift { -namespace concurrency { - -/** - * A thread factory to create posix threads - * - * @version $Id:$ - */ -class BoostThreadFactory : public ThreadFactory { - -public: - /** - * Boost thread factory. All threads created by a factory are reference-counted - * via stdcxx::shared_ptr. The factory guarantees that threads and the Runnable tasks they - * host will be properly cleaned up once the last strong reference to both is given up. - * - * Threads are created with the specified boost policy, priority, stack-size. A detachable thread - * is not joinable. - * - * By default threads are not joinable. - */ - - BoostThreadFactory(bool detached = true); - - // From ThreadFactory; - stdcxx::shared_ptr newThread(stdcxx::shared_ptr runnable) const; - - // From ThreadFactory; - Thread::id_t getCurrentThreadId() const; -}; - -} -} -} // apache::thrift::concurrency - -#endif // #ifndef _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_ diff --git a/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h b/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h index 545b5727060..99b44033b3c 100644 --- a/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h +++ b/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h @@ -22,9 +22,7 @@ // clang-format off #include -#if USE_BOOST_THREAD -# include -#elif USE_STD_THREAD +#if USE_STD_THREAD # include #else # include @@ -36,9 +34,7 @@ namespace thrift { namespace concurrency { // clang-format off -#if USE_BOOST_THREAD - typedef BoostThreadFactory PlatformThreadFactory; -#elif USE_STD_THREAD +#if USE_STD_THREAD typedef StdThreadFactory PlatformThreadFactory; #else typedef PosixThreadFactory PlatformThreadFactory; diff --git a/lib/cpp/src/thrift/concurrency/Thread.h b/lib/cpp/src/thrift/concurrency/Thread.h index 788623bdad7..7e2d251e057 100644 --- a/lib/cpp/src/thrift/concurrency/Thread.h +++ b/lib/cpp/src/thrift/concurrency/Thread.h @@ -25,9 +25,7 @@ #include -#if USE_BOOST_THREAD -#include -#elif USE_STD_THREAD +#if USE_STD_THREAD #include #else #ifdef HAVE_PTHREAD_H @@ -80,12 +78,7 @@ class Runnable { class Thread { public: -#if USE_BOOST_THREAD - typedef boost::thread::id id_t; - - static inline bool is_current(id_t t) { return t == boost::this_thread::get_id(); } - static inline id_t get_current() { return boost::this_thread::get_id(); } -#elif USE_STD_THREAD +#if USE_STD_THREAD typedef std::thread::id id_t; static inline bool is_current(id_t t) { return t == std::this_thread::get_id(); } diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.cpp b/lib/cpp/src/thrift/server/TNonblockingServer.cpp index 194d59fa085..1031ec0074f 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.cpp +++ b/lib/cpp/src/thrift/server/TNonblockingServer.cpp @@ -1119,7 +1119,7 @@ void TNonblockingServer::registerEvents(event_base* user_event_base) { // Launch all the secondary IO threads in separate threads if (ioThreads_.size() > 1) { ioThreadFactory_.reset(new PlatformThreadFactory( -#if !USE_BOOST_THREAD && !USE_STD_THREAD +#if !USE_STD_THREAD PlatformThreadFactory::OTHER, // scheduler PlatformThreadFactory::NORMAL, // priority 1, // stack size (MB) diff --git a/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp b/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp index 2e0ccf53a81..d2683b08abb 100644 --- a/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp +++ b/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp @@ -28,13 +28,7 @@ namespace thrift { namespace transport { TWinsockSingleton::instance_ptr TWinsockSingleton::instance_ptr_(NULL); -#if USE_BOOST_THREAD -boost::once_flag TWinsockSingleton::flags_ = BOOST_ONCE_INIT; -#elif USE_STD_THREAD std::once_flag TWinsockSingleton::flags_; -#else -#error For windows you must choose USE_BOOST_THREAD or USE_STD_THREAD -#endif //------------------------------------------------------------------------------ TWinsockSingleton::TWinsockSingleton(void) { @@ -55,11 +49,7 @@ TWinsockSingleton::~TWinsockSingleton(void) { //------------------------------------------------------------------------------ void TWinsockSingleton::create(void) { -#if USE_BOOST_THREAD - boost::call_once(init, flags_); -#elif USE_STD_THREAD std::call_once(flags_, init); -#endif } //------------------------------------------------------------------------------ diff --git a/lib/cpp/src/thrift/windows/TWinsockSingleton.h b/lib/cpp/src/thrift/windows/TWinsockSingleton.h index 0eab6d4ec8a..50458a93791 100644 --- a/lib/cpp/src/thrift/windows/TWinsockSingleton.h +++ b/lib/cpp/src/thrift/windows/TWinsockSingleton.h @@ -33,13 +33,7 @@ // boost #include -#if USE_BOOST_THREAD -#include -#elif USE_STD_THREAD #include -#else -#error For windows you must choose USE_BOOST_THREAD or USE_STD_THREAD -#endif #include @@ -70,13 +64,7 @@ class TWinsockSingleton : private boost::noncopyable { private: static instance_ptr instance_ptr_; -#if USE_BOOST_THREAD - static boost::once_flag flags_; -#elif USE_STD_THREAD static std::once_flag flags_; -#else -#error Need a non-Boost non-C++11 way to track single initialization here. -#endif }; } } diff --git a/lib/cpp/src/thrift/windows/config.h b/lib/cpp/src/thrift/windows/config.h index bc4aa42f8ad..a5f44577d8a 100644 --- a/lib/cpp/src/thrift/windows/config.h +++ b/lib/cpp/src/thrift/windows/config.h @@ -31,9 +31,6 @@ // use std::thread in MSVC11 (2012) or newer and in MinGW #if (_MSC_VER >= 1700) || defined(__MINGW32__) #define USE_STD_THREAD 1 -#else -// otherwise use boost threads -#define USE_BOOST_THREAD 1 #endif // Something that defines PRId64 is required to build diff --git a/lib/cpp/test/CMakeLists.txt b/lib/cpp/test/CMakeLists.txt index 261382f6584..82d47a6b6e8 100644 --- a/lib/cpp/test/CMakeLists.txt +++ b/lib/cpp/test/CMakeLists.txt @@ -82,7 +82,7 @@ set(UnitTest_SOURCES TServerTransportTest.cpp ) -if(NOT WITH_BOOSTTHREADS AND NOT WITH_STDTHREADS AND NOT MSVC AND NOT MINGW) +if(NOT WITH_STDTHREADS AND NOT MSVC AND NOT MINGW) list(APPEND UnitTest_SOURCES concurrency/MutexTest.cpp) list(APPEND UnitTest_SOURCES concurrency/RWMutexStarveTest.cpp) endif() diff --git a/lib/cpp/test/Makefile.am b/lib/cpp/test/Makefile.am index 4b9f77d2142..d645a6501ab 100755 --- a/lib/cpp/test/Makefile.am +++ b/lib/cpp/test/Makefile.am @@ -135,11 +135,9 @@ UnitTests_SOURCES = \ TServerTransportTest.cpp \ TTransportCheckThrow.h -if !WITH_BOOSTTHREADS UnitTests_SOURCES += \ concurrency/MutexTest.cpp \ concurrency/RWMutexStarveTest.cpp -endif UnitTests_LDADD = \ libtestgencpp.la \ diff --git a/lib/cpp/test/TNonblockingSSLServerTest.cpp b/lib/cpp/test/TNonblockingSSLServerTest.cpp index 3e9700f1f19..2efb1409b2a 100644 --- a/lib/cpp/test/TNonblockingSSLServerTest.cpp +++ b/lib/cpp/test/TNonblockingSSLServerTest.cpp @@ -221,7 +221,7 @@ class Fixture { apache::thrift::stdcxx::scoped_ptr threadFactory( new apache::thrift::concurrency::PlatformThreadFactory( -#if !USE_BOOST_THREAD && !USE_STD_THREAD +#if !USE_STD_THREAD concurrency::PlatformThreadFactory::OTHER, concurrency::PlatformThreadFactory::NORMAL, 1, #endif diff --git a/lib/cpp/test/TNonblockingServerTest.cpp b/lib/cpp/test/TNonblockingServerTest.cpp index 63d8a046133..5e10907b057 100644 --- a/lib/cpp/test/TNonblockingServerTest.cpp +++ b/lib/cpp/test/TNonblockingServerTest.cpp @@ -148,7 +148,7 @@ class Fixture { shared_ptr threadFactory( new PlatformThreadFactory( -#if !USE_BOOST_THREAD && !USE_STD_THREAD +#if !USE_STD_THREAD PlatformThreadFactory::OTHER, PlatformThreadFactory::NORMAL, 1, #endif diff --git a/lib/cpp/test/concurrency/ThreadManagerTests.h b/lib/cpp/test/concurrency/ThreadManagerTests.h index 9ecd6bad5a2..15a43ffae00 100644 --- a/lib/cpp/test/concurrency/ThreadManagerTests.h +++ b/lib/cpp/test/concurrency/ThreadManagerTests.h @@ -111,7 +111,7 @@ class ThreadManagerTests { shared_ptr threadFactory = shared_ptr(new PlatformThreadFactory(false)); -#if !USE_BOOST_THREAD && !USE_STD_THREAD +#if !USE_STD_THREAD threadFactory->setPriority(PosixThreadFactory::HIGHEST); #endif threadManager->threadFactory(threadFactory); @@ -260,7 +260,7 @@ class ThreadManagerTests { shared_ptr threadFactory = shared_ptr(new PlatformThreadFactory()); -#if !USE_BOOST_THREAD && !USE_STD_THREAD +#if !USE_STD_THREAD threadFactory->setPriority(PosixThreadFactory::HIGHEST); #endif threadManager->threadFactory(threadFactory); @@ -401,7 +401,7 @@ class ThreadManagerTests { return false; } -#if !USE_BOOST_THREAD && !USE_STD_THREAD +#if !USE_STD_THREAD // test once with a detached thread factory and once with a joinable thread factory shared_ptr threadFactory @@ -426,7 +426,7 @@ class ThreadManagerTests { shared_ptr threadManager = ThreadManager::newSimpleThreadManager(1); threadManager->threadFactory(threadFactory); -#if !USE_BOOST_THREAD && !USE_STD_THREAD +#if !USE_STD_THREAD threadFactory->setPriority(PosixThreadFactory::HIGHEST); // verify we cannot change the thread factory to one with the opposite detached setting From 2150a3451bd110ed528df6f3e6a805dc5b3fd147 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 13:51:01 +0800 Subject: [PATCH 110/756] remove boost::thread in CI --- .travis.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 96e0b5178ae..637b5d534a0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -137,14 +137,6 @@ jobs: - JOB="CMake" # C++ specific options: compiler plug-in, threading model - - script: build/docker/run.sh - env: - - JOB="C++98 (Boost Thread)" - - SCRIPT="cmake.sh" - - BUILD_LIBS="CPP TESTING TUTORIALS" - - BUILD_ARG="-DCMAKE_CXX_STANDARD=98 -DCMAKE_CXX_STANDARD_REQUIRED=ON -DCMAKE_CXX_EXTENSIONS=OFF -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF" - - BUILD_ENV="-e CC=clang -e CXX=clang++" - - script: build/docker/run.sh env: - JOB="C++ (Std Thread) and Plugin" From f23e6a5e23c8ad1feaaa6913314c7836246a2925 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 14:00:03 +0800 Subject: [PATCH 111/756] remove boost::thread in CI --- build/appveyor/cl_setenv.bat | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/build/appveyor/cl_setenv.bat b/build/appveyor/cl_setenv.bat index 62856cba0c1..c33366d6943 100644 --- a/build/appveyor/cl_setenv.bat +++ b/build/appveyor/cl_setenv.bat @@ -14,9 +14,7 @@ @ECHO OFF - IF "%PROFILE%" == "MSVC2010" ( - CALL "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" %PLATFORM% -) ELSE IF "%PROFILE%" == "MSVC2012" ( +IF "%PROFILE%" == "MSVC2012" ( CALL "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" %PLATFORM% ) ELSE IF "%PROFILE%" == "MSVC2013" ( CALL "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" %PLATFORM% @@ -54,12 +52,7 @@ IF "%PROFILE:~0,4%" == "MSVC" ( SET OPENSSL_ROOT=C:\OpenSSL-Win%NORM_PLATFORM% SET WIN3P=%APPVEYOR_BUILD_FOLDER%\thirdparty - :: MSVC2010 doesn't "do" std::thread - IF "%COMPILER%" == "vc100" ( - SET THREADMODEL=BOOST - ) ELSE ( - SET THREADMODEL=STD - ) + SET THREADMODEL=STD IF "%PYTHON_VERSION%" == "" ( SET WITH_PYTHON=OFF From 9f837bbfb4c61ad8afe80950b6ce677a5cd39aeb Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 14:49:24 +0800 Subject: [PATCH 112/756] remove boost smart ptr --- build/cmake/DefineOptions.cmake | 6 ---- build/cmake/DefinePlatformSpecifc.cmake | 2 -- lib/cpp/src/thrift/stdcxx.h | 39 +++++-------------------- 3 files changed, 8 insertions(+), 39 deletions(-) diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 43b73e498be..7465c803785 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -45,11 +45,6 @@ if (WITH_BOOST_FUNCTIONAL) add_definitions(-DFORCE_BOOST_FUNCTIONAL) endif() -option(WITH_BOOST_SMART_PTR "Use boost/smart_ptr.hpp even under C++11 or later" OFF) -if (WITH_BOOST_SMART_PTR) - add_definitions(-DFORCE_BOOST_SMART_PTR) -endif() - option(WITH_BOOST_STATIC "Build with Boost static link library" OFF) set(Boost_USE_STATIC_LIBS ${WITH_BOOST_STATIC}) if (NOT WITH_BOOST_STATIC) @@ -205,7 +200,6 @@ message(STATUS " Build shared libraries: ${WITH_SHARED_LIB} message(STATUS " Build static libraries: ${WITH_STATIC_LIB}") message(STATUS " Build with Boost static link library: ${WITH_BOOST_STATIC}") message(STATUS " Build with boost/tr1/functional (forced) ${WITH_BOOST_FUNCTIONAL}") -message(STATUS " Build with boost/smart_ptr (forced) ${WITH_BOOST_SMART_PTR}") message(STATUS " Build with C++ std::thread support: ${WITH_STDTHREADS}") message(STATUS " Build with libevent support: ${WITH_LIBEVENT}") message(STATUS " Build with OpenSSL support: ${WITH_OPENSSL}") diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index cbd5ca86704..98fb589583e 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -125,7 +125,5 @@ if (WITH_PLUGIN) if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8") message(SEND_ERROR "Thrift compiler plug-in support is not possible with older gcc ( < 4.8 ) compiler") endif() - message(STATUS "Forcing use of boost::smart_ptr to build WITH_PLUGIN") - add_definitions("-DFORCE_BOOST_SMART_PTR=1") endif() diff --git a/lib/cpp/src/thrift/stdcxx.h b/lib/cpp/src/thrift/stdcxx.h index c8cabf52035..1a65f87b9f9 100644 --- a/lib/cpp/src/thrift/stdcxx.h +++ b/lib/cpp/src/thrift/stdcxx.h @@ -87,42 +87,19 @@ // /////////////////////////////////////////////////////////////////// -// We can use std for memory functions only if the compiler supports template aliasing -// The macro BOOST_NO_CXX11_SMART_PTR is defined as 1 under Visual Studio 2010 and 2012 -// which do not support the feature, so we must continue to use C++98 and boost on them. -// We cannot use __cplusplus to detect this either, since Microsoft advertises an older one. - -#if defined(BOOST_NO_CXX11_SMART_PTR) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_SMART_PTR) -#include -#else #include -#endif namespace apache { namespace thrift { namespace stdcxx { -#if defined(BOOST_NO_CXX11_SMART_PTR) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_SMART_PTR) - - using ::boost::const_pointer_cast; - using ::boost::dynamic_pointer_cast; - using ::boost::enable_shared_from_this; - using ::boost::make_shared; - using ::boost::scoped_ptr; - using ::boost::shared_ptr; - using ::boost::static_pointer_cast; - using ::boost::weak_ptr; +using ::std::const_pointer_cast; +using ::std::dynamic_pointer_cast; +using ::std::enable_shared_from_this; +using ::std::make_shared; +template using scoped_ptr = std::unique_ptr; // compiler must support template aliasing +using ::std::shared_ptr; +using ::std::static_pointer_cast; +using ::std::weak_ptr; -#else - - using ::std::const_pointer_cast; - using ::std::dynamic_pointer_cast; - using ::std::enable_shared_from_this; - using ::std::make_shared; - template using scoped_ptr = std::unique_ptr; // compiler must support template aliasing - using ::std::shared_ptr; - using ::std::static_pointer_cast; - using ::std::weak_ptr; - -#endif }}} // apache::thrift::stdcxx From 52637b33aba090851436b2031476529423ea3281 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 15:11:17 +0800 Subject: [PATCH 113/756] remove std tr1 --- lib/cpp/src/thrift/stdcxx.h | 66 ++++++++++--------------------------- 1 file changed, 17 insertions(+), 49 deletions(-) diff --git a/lib/cpp/src/thrift/stdcxx.h b/lib/cpp/src/thrift/stdcxx.h index 1a65f87b9f9..20910de5308 100644 --- a/lib/cpp/src/thrift/stdcxx.h +++ b/lib/cpp/src/thrift/stdcxx.h @@ -29,57 +29,25 @@ // /////////////////////////////////////////////////////////////////// -#if defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) || (defined(_MSC_VER) && _MSC_VER < 1800) || defined(FORCE_BOOST_FUNCTIONAL) -#if (BOOST_VERSION <= 106500) -#include -#else -#include -#endif -#define _THRIFT_FUNCTIONAL_TR1_ 1 -#endif +#include -#if _THRIFT_FUNCTIONAL_TR1_ - - namespace apache { namespace thrift { namespace stdcxx { - - using ::std::tr1::bind; - using ::std::tr1::function; - - namespace placeholders { - using ::std::tr1::placeholders::_1; - using ::std::tr1::placeholders::_2; - using ::std::tr1::placeholders::_3; - using ::std::tr1::placeholders::_4; - using ::std::tr1::placeholders::_5; - using ::std::tr1::placeholders::_6; - using ::std::tr1::placeholders::_7; - using ::std::tr1::placeholders::_8; - using ::std::tr1::placeholders::_9; - } // apache::thrift::stdcxx::placeholders - }}} // apache::thrift::stdcxx - -#else - - #include - - namespace apache { namespace thrift { namespace stdcxx { - using ::std::bind; - using ::std::function; - - namespace placeholders { - using ::std::placeholders::_1; - using ::std::placeholders::_2; - using ::std::placeholders::_3; - using ::std::placeholders::_4; - using ::std::placeholders::_5; - using ::std::placeholders::_6; - using ::std::placeholders::_7; - using ::std::placeholders::_8; - using ::std::placeholders::_9; - } // apache::thrift::stdcxx::placeholders - }}} // apache::thrift::stdcxx +namespace apache { namespace thrift { namespace stdcxx { + using ::std::bind; + using ::std::function; + + namespace placeholders { + using ::std::placeholders::_1; + using ::std::placeholders::_2; + using ::std::placeholders::_3; + using ::std::placeholders::_4; + using ::std::placeholders::_5; + using ::std::placeholders::_6; + using ::std::placeholders::_7; + using ::std::placeholders::_8; + using ::std::placeholders::_9; + } // apache::thrift::stdcxx::placeholders +}}} // apache::thrift::stdcxx -#endif /////////////////////////////////////////////////////////////////// // From 316723add4c368ffd144dd5beb55245832e073fa Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 16:35:14 +0800 Subject: [PATCH 114/756] remove stdcxx namespace and use std directly --- .../src/thrift/generate/t_cpp_generator.cc | 112 +++++++------ compiler/cpp/src/thrift/plugin/plugin.cc | 29 ++-- .../cpp/src/thrift/plugin/plugin_output.cc | 7 +- contrib/zeromq/TZmqServer.cpp | 2 +- contrib/zeromq/test-client.cpp | 2 +- contrib/zeromq/test-receiver.cpp | 2 +- contrib/zeromq/test-sender.cpp | 2 +- contrib/zeromq/test-server.cpp | 2 +- lib/c_glib/test/testthrifttestclient.cpp | 12 +- lib/cpp/src/thrift/TDispatchProcessor.h | 8 +- lib/cpp/src/thrift/TProcessor.h | 33 ++-- .../src/thrift/async/TAsyncBufferProcessor.h | 8 +- lib/cpp/src/thrift/async/TAsyncChannel.cpp | 5 +- lib/cpp/src/thrift/async/TAsyncChannel.h | 5 +- .../thrift/async/TAsyncDispatchProcessor.h | 20 +-- lib/cpp/src/thrift/async/TAsyncProcessor.h | 20 +-- .../thrift/async/TAsyncProtocolProcessor.cpp | 18 +- .../thrift/async/TAsyncProtocolProcessor.h | 18 +- .../thrift/async/TConcurrentClientSyncInfo.h | 4 +- .../src/thrift/async/TEvhttpClientChannel.h | 2 +- lib/cpp/src/thrift/async/TEvhttpServer.cpp | 19 +-- lib/cpp/src/thrift/async/TEvhttpServer.h | 8 +- .../src/thrift/concurrency/FunctionRunner.h | 18 +- lib/cpp/src/thrift/concurrency/Monitor.cpp | 6 +- lib/cpp/src/thrift/concurrency/Mutex.h | 6 +- .../thrift/concurrency/PosixThreadFactory.cpp | 26 +-- .../thrift/concurrency/PosixThreadFactory.h | 6 +- .../thrift/concurrency/StdThreadFactory.cpp | 20 +-- .../src/thrift/concurrency/StdThreadFactory.h | 6 +- lib/cpp/src/thrift/concurrency/Thread.h | 16 +- .../src/thrift/concurrency/ThreadManager.cpp | 10 +- .../src/thrift/concurrency/ThreadManager.h | 19 ++- .../src/thrift/concurrency/TimerManager.cpp | 4 +- lib/cpp/src/thrift/concurrency/TimerManager.h | 26 +-- .../src/thrift/processor/PeekProcessor.cpp | 26 +-- lib/cpp/src/thrift/processor/PeekProcessor.h | 30 ++-- lib/cpp/src/thrift/processor/StatsProcessor.h | 8 +- .../thrift/processor/TMultiplexedProcessor.h | 36 ++-- lib/cpp/src/thrift/protocol/TBinaryProtocol.h | 12 +- .../src/thrift/protocol/TCompactProtocol.h | 12 +- lib/cpp/src/thrift/protocol/TDebugProtocol.h | 12 +- .../src/thrift/protocol/THeaderProtocol.cpp | 6 +- lib/cpp/src/thrift/protocol/THeaderProtocol.h | 32 ++-- lib/cpp/src/thrift/protocol/TJSONProtocol.cpp | 12 +- lib/cpp/src/thrift/protocol/TJSONProtocol.h | 14 +- .../thrift/protocol/TMultiplexedProtocol.h | 2 +- lib/cpp/src/thrift/protocol/TProtocol.h | 18 +- .../src/thrift/protocol/TProtocolDecorator.h | 4 +- lib/cpp/src/thrift/protocol/TProtocolTap.h | 6 +- .../src/thrift/protocol/TVirtualProtocol.h | 4 +- lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp | 4 +- lib/cpp/src/thrift/qt/TQIODeviceTransport.h | 6 +- lib/cpp/src/thrift/qt/TQTcpServer.cpp | 13 +- lib/cpp/src/thrift/qt/TQTcpServer.h | 18 +- .../src/thrift/server/TConnectedClient.cpp | 2 +- lib/cpp/src/thrift/server/TConnectedClient.h | 22 +-- .../src/thrift/server/TNonblockingServer.cpp | 64 +++---- .../src/thrift/server/TNonblockingServer.h | 86 +++++----- lib/cpp/src/thrift/server/TServer.h | 140 ++++++++-------- .../src/thrift/server/TServerFramework.cpp | 6 +- lib/cpp/src/thrift/server/TServerFramework.h | 46 ++--- lib/cpp/src/thrift/server/TSimpleServer.cpp | 2 +- lib/cpp/src/thrift/server/TSimpleServer.h | 42 ++--- .../src/thrift/server/TThreadPoolServer.cpp | 4 +- lib/cpp/src/thrift/server/TThreadPoolServer.h | 54 +++--- lib/cpp/src/thrift/server/TThreadedServer.cpp | 6 +- lib/cpp/src/thrift/server/TThreadedServer.h | 66 ++++---- lib/cpp/src/thrift/stdcxx.h | 74 -------- .../src/thrift/transport/TBufferTransports.h | 26 +-- .../src/thrift/transport/TFileTransport.cpp | 2 +- lib/cpp/src/thrift/transport/TFileTransport.h | 35 ++-- .../src/thrift/transport/THeaderTransport.cpp | 3 +- .../src/thrift/transport/THeaderTransport.h | 13 +- lib/cpp/src/thrift/transport/THttpClient.cpp | 4 +- lib/cpp/src/thrift/transport/THttpClient.h | 2 +- lib/cpp/src/thrift/transport/THttpServer.cpp | 2 +- lib/cpp/src/thrift/transport/THttpServer.h | 6 +- .../src/thrift/transport/THttpTransport.cpp | 2 +- lib/cpp/src/thrift/transport/THttpTransport.h | 4 +- .../transport/TNonblockingSSLServerSocket.cpp | 10 +- .../transport/TNonblockingSSLServerSocket.h | 11 +- .../transport/TNonblockingServerSocket.cpp | 2 +- .../transport/TNonblockingServerSocket.h | 7 +- .../transport/TNonblockingServerTransport.h | 7 +- lib/cpp/src/thrift/transport/TPipe.h | 2 +- lib/cpp/src/thrift/transport/TPipeServer.cpp | 11 +- lib/cpp/src/thrift/transport/TPipeServer.h | 6 +- .../src/thrift/transport/TSSLServerSocket.cpp | 8 +- .../src/thrift/transport/TSSLServerSocket.h | 11 +- lib/cpp/src/thrift/transport/TSSLSocket.cpp | 42 ++--- lib/cpp/src/thrift/transport/TSSLSocket.h | 39 +++-- .../src/thrift/transport/TServerSocket.cpp | 5 +- lib/cpp/src/thrift/transport/TServerSocket.h | 9 +- .../src/thrift/transport/TServerTransport.h | 7 +- .../thrift/transport/TShortReadTransport.h | 6 +- lib/cpp/src/thrift/transport/TSocket.cpp | 2 +- lib/cpp/src/thrift/transport/TSocket.h | 4 +- lib/cpp/src/thrift/transport/TSocketPool.cpp | 2 +- lib/cpp/src/thrift/transport/TSocketPool.h | 14 +- lib/cpp/src/thrift/transport/TTransport.h | 4 +- .../src/thrift/transport/TTransportUtils.cpp | 4 +- .../src/thrift/transport/TTransportUtils.h | 44 ++--- lib/cpp/src/thrift/transport/TZlibTransport.h | 10 +- .../src/thrift/windows/TWinsockSingleton.h | 4 +- lib/cpp/test/AllProtocolTests.tcc | 2 +- lib/cpp/test/Benchmark.cpp | 16 +- lib/cpp/test/DebugProtoTest.cpp | 8 +- lib/cpp/test/GenericHelpers.h | 26 +-- lib/cpp/test/JSONProtoTest.cpp | 36 ++-- lib/cpp/test/OneWayHTTPTest.cpp | 24 +-- lib/cpp/test/OptionalRequiredTest.cpp | 6 +- lib/cpp/test/RecursiveTest.cpp | 4 +- lib/cpp/test/SecurityTest.cpp | 6 +- lib/cpp/test/SpecializationTest.cpp | 4 +- lib/cpp/test/TBufferBaseTest.cpp | 4 +- lib/cpp/test/TMemoryBufferTest.cpp | 4 +- lib/cpp/test/TNonblockingSSLServerTest.cpp | 44 +++-- lib/cpp/test/TNonblockingServerTest.cpp | 6 +- lib/cpp/test/TPipeInterruptTest.cpp | 8 +- lib/cpp/test/TPipedTransportTest.cpp | 8 +- lib/cpp/test/TSSLSocketInterruptTest.cpp | 16 +- lib/cpp/test/TServerIntegrationTest.cpp | 20 +-- lib/cpp/test/TServerSocketTest.cpp | 4 +- lib/cpp/test/TServerTransportTest.cpp | 4 +- lib/cpp/test/TSocketInterruptTest.cpp | 24 +-- lib/cpp/test/TransportTest.cpp | 23 ++- lib/cpp/test/ZlibTest.cpp | 10 +- .../test/concurrency/RWMutexStarveTest.cpp | 4 +- lib/cpp/test/concurrency/ThreadFactoryTests.h | 2 +- lib/cpp/test/concurrency/ThreadManagerTests.h | 6 +- lib/cpp/test/processor/Handlers.h | 32 ++-- lib/cpp/test/processor/ProcessorTest.cpp | 158 +++++++++--------- lib/cpp/test/processor/ServerThread.cpp | 2 +- lib/cpp/test/processor/ServerThread.h | 16 +- lib/cpp/test/qt/TQTcpServerTest.cpp | 39 +++-- .../thrift_protocol/php_thrift_protocol.cpp | 10 +- lib/py/src/ext/types.h | 8 +- test/cpp/src/StressTest.cpp | 75 ++++----- test/cpp/src/StressTestNonBlocking.cpp | 71 ++++---- test/cpp/src/TestClient.cpp | 51 +++--- test/cpp/src/TestServer.cpp | 119 +++++++------ tutorial/cpp/CppClient.cpp | 7 +- tutorial/cpp/CppServer.cpp | 39 +++-- 143 files changed, 1307 insertions(+), 1399 deletions(-) delete mode 100644 lib/cpp/src/thrift/stdcxx.h diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc index 08393028d97..cf3036390ff 100644 --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc @@ -419,7 +419,8 @@ void t_cpp_generator::init_generator() { << "#include " << endl << endl; // Include C++xx compatibility header - f_types_ << "#include " << endl; + f_types_ << "#include " << endl; + f_types_ << "#include " << endl; // Include other Thrift includes const vector& includes = program_->get_includes(); @@ -1119,7 +1120,7 @@ void t_cpp_generator::generate_struct_declaration(ostream& out, continue; } if (is_reference((*m_iter))) { - out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "(::apache::thrift::stdcxx::shared_ptr<" + out << endl << indent() << "void __set_" << (*m_iter)->get_name() << "(::std::shared_ptr<" << type_name((*m_iter)->get_type(), false, false) << ">"; out << " val);" << endl; } else { @@ -1239,7 +1240,7 @@ void t_cpp_generator::generate_struct_definition(ostream& out, if (is_reference((*m_iter))) { std::string type = type_name((*m_iter)->get_type()); out << endl << indent() << "void " << tstruct->get_name() << "::__set_" - << (*m_iter)->get_name() << "(::apache::thrift::stdcxx::shared_ptr<" + << (*m_iter)->get_name() << "(::std::shared_ptr<" << type_name((*m_iter)->get_type(), false, false) << ">"; out << " val) {" << endl; } else { @@ -1717,8 +1718,9 @@ void t_cpp_generator::generate_service(t_service* tservice) { f_header_ << "#ifndef " << svcname << "_H" << endl << "#define " << svcname << "_H" << endl << endl; if (gen_cob_style_) { - f_header_ << "#include " << endl << // TMemoryBuffer - "#include " << endl + f_header_ << "#include " << endl // TMemoryBuffer + << "#include " << endl + << "#include " << endl << "namespace apache { namespace thrift { namespace async {" << endl << "class TAsyncChannel;" << endl << "}}}" << endl; } @@ -1968,7 +1970,7 @@ void t_cpp_generator::generate_service_interface_factory(t_service* tservice, st f_header_ << "class " << singleton_factory_name << " : virtual public " << factory_name << " {" << endl << " public:" << endl; indent_up(); - f_header_ << indent() << singleton_factory_name << "(const ::apache::thrift::stdcxx::shared_ptr<" << service_if_name + f_header_ << indent() << singleton_factory_name << "(const ::std::shared_ptr<" << service_if_name << ">& iface) : iface_(iface) {}" << endl << indent() << "virtual ~" << singleton_factory_name << "() {}" << endl << endl << indent() << "virtual " << service_if_name << "* getHandler(" @@ -1976,7 +1978,7 @@ void t_cpp_generator::generate_service_interface_factory(t_service* tservice, st << " return iface_.get();" << endl << indent() << "}" << endl << indent() << "virtual void releaseHandler(" << base_if_name << "* /* handler */) {}" << endl; - f_header_ << endl << " protected:" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr<" << service_if_name + f_header_ << endl << " protected:" << endl << indent() << "::std::shared_ptr<" << service_if_name << "> iface_;" << endl; indent_down(); @@ -2146,7 +2148,7 @@ void t_cpp_generator::generate_service_multiface(t_service* tservice) { extends_multiface = ", public " + extends + "Multiface"; } - string list_type = string("std::vector >"; + string list_type = string("std::vector >"; // Generate the header portion f_header_ << "class " << service_name_ << "Multiface : " @@ -2157,7 +2159,7 @@ void t_cpp_generator::generate_service_multiface(t_service* tservice) { << "& ifaces) : ifaces_(ifaces) {" << endl; if (!extends.empty()) { f_header_ << indent() - << " std::vector >::iterator iter;" + << " std::vector >::iterator iter;" << endl << indent() << " for (iter = ifaces.begin(); iter != ifaces.end(); ++iter) {" << endl << indent() << " " << extends << "Multiface::add(*iter);" << endl << indent() << " }" << endl; @@ -2170,7 +2172,7 @@ void t_cpp_generator::generate_service_multiface(t_service* tservice) { f_header_ << " protected:" << endl; indent_up(); f_header_ << indent() << list_type << " ifaces_;" << endl << indent() << service_name_ - << "Multiface() {}" << endl << indent() << "void add(::apache::thrift::stdcxx::shared_ptr<" + << "Multiface() {}" << endl << indent() << "void add(::std::shared_ptr<" << service_name_ << "If> iface) {" << endl; if (!extends.empty()) { f_header_ << indent() << " " << extends << "Multiface::add(iface);" << endl; @@ -2252,7 +2254,7 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) } else { protocol_type = "::apache::thrift::protocol::TProtocol"; } - string prot_ptr = "apache::thrift::stdcxx::shared_ptr< " + protocol_type + ">"; + string prot_ptr = "std::shared_ptr< " + protocol_type + ">"; string client_suffix = "Client" + template_suffix; string if_suffix = "If"; if (style == "Cob") { @@ -2329,18 +2331,18 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) // Note that these are not currently templated for simplicity. // TODO(simpkins): should they be templated? f_header_ << indent() - << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() {" + << "std::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() {" << endl << indent() << " return " << _this << "piprot_;" << endl << indent() << "}" << endl; f_header_ << indent() - << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() {" + << "std::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() {" << endl << indent() << " return " << _this << "poprot_;" << endl << indent() << "}" << endl; } else /* if (style == "Cob") */ { f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" - << "apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel, " + << "std::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel, " << "::apache::thrift::protocol::TProtocolFactory* protocolFactory) :" << endl; if (extends.empty()) { f_header_ << indent() << " channel_(channel)," << endl << indent() @@ -2350,9 +2352,9 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) if (gen_templates_) { // TProtocolFactory classes return generic TProtocol pointers. // We have to dynamic cast to the Protocol_ type we are expecting. - f_header_ << indent() << " piprot_(::apache::thrift::stdcxx::dynamic_pointer_cast(" + f_header_ << indent() << " piprot_(::std::dynamic_pointer_cast(" << "protocolFactory->getProtocol(itrans_)))," << endl << indent() - << " poprot_(::apache::thrift::stdcxx::dynamic_pointer_cast(" + << " poprot_(::std::dynamic_pointer_cast(" << "protocolFactory->getProtocol(otrans_))) {" << endl; // Throw a TException if either dynamic cast failed. f_header_ << indent() << " if (!piprot_ || !poprot_) {" << endl << indent() @@ -2374,7 +2376,7 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) if (style == "Cob") { f_header_ << indent() - << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() {" << endl + << "::std::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() {" << endl << indent() << " return " << _this << "channel_;" << endl << indent() << "}" << endl; if (!gen_no_client_completion_) { f_header_ << indent() << "virtual void completed__(bool /* success */) {}" << endl; @@ -2426,11 +2428,11 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) if (style == "Cob") { f_header_ << indent() - << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel_;" << endl + << "::std::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel_;" << endl << indent() - << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> itrans_;" << endl + << "::std::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> itrans_;" << endl << indent() - << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> otrans_;" + << "::std::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> otrans_;" << endl; } f_header_ << @@ -2512,11 +2514,11 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) } else { if (!(*f_iter)->is_oneway()) { out << indent() << _this << "channel_->sendAndRecvMessage(" - << "::apache::thrift::stdcxx::bind(cob, this), " << _this << "otrans_.get(), " << _this << "itrans_.get());" + << "::std::bind(cob, this), " << _this << "otrans_.get(), " << _this << "itrans_.get());" << endl; } else { out << indent() << _this << "channel_->sendMessage(" - << "::apache::thrift::stdcxx::bind(cob, this), " << _this << "otrans_.get());" << endl; + << "::std::bind(cob, this), " << _this << "otrans_.get());" << endl; } } scope_down(out); @@ -2867,8 +2869,8 @@ ProcessorGenerator::ProcessorGenerator(t_cpp_generator* generator, class_name_ = service_name_ + pstyle_ + "Processor"; if_name_ = service_name_ + "CobSvIf"; - finish_cob_ = "::apache::thrift::stdcxx::function cob, "; - finish_cob_decl_ = "::apache::thrift::stdcxx::function, "; + finish_cob_ = "::std::function cob, "; + finish_cob_decl_ = "::std::function, "; cob_arg_ = "cob, "; ret_type_ = "void "; } else { @@ -2929,7 +2931,7 @@ void ProcessorGenerator::generate_class_definition() { // Protected data members f_header_ << " protected:" << endl; indent_up(); - f_header_ << indent() << "::apache::thrift::stdcxx::shared_ptr<" << if_name_ << "> iface_;" << endl; + f_header_ << indent() << "::std::shared_ptr<" << if_name_ << "> iface_;" << endl; f_header_ << indent() << "virtual " << ret_type_ << "dispatchCall(" << finish_cob_ << "::apache::thrift::protocol::TProtocol* iprot, " << "::apache::thrift::protocol::TProtocol* oprot, " @@ -2985,29 +2987,29 @@ void ProcessorGenerator::generate_class_definition() { ? "" : ", const " + type_name((*f_iter)->get_returntype()) + "& _return"); f_header_ << indent() << "void return_" << (*f_iter)->get_name() - << "(::apache::thrift::stdcxx::function cob, int32_t seqid, " + << "(::std::function cob, int32_t seqid, " << "::apache::thrift::protocol::TProtocol* oprot, " << "void* ctx" << ret_arg << ");" << endl; if (generator_->gen_templates_) { f_header_ << indent() << "void return_" << (*f_iter)->get_name() - << "(::apache::thrift::stdcxx::function cob, int32_t seqid, " + << "(::std::function cob, int32_t seqid, " << "Protocol_* oprot, void* ctx" << ret_arg << ");" << endl; } // XXX Don't declare throw if it doesn't exist f_header_ << indent() << "void throw_" << (*f_iter)->get_name() - << "(::apache::thrift::stdcxx::function cob, int32_t seqid, " + << "(::std::function cob, int32_t seqid, " << "::apache::thrift::protocol::TProtocol* oprot, void* ctx, " << "::apache::thrift::TDelayedException* _throw);" << endl; if (generator_->gen_templates_) { f_header_ << indent() << "void throw_" << (*f_iter)->get_name() - << "(::apache::thrift::stdcxx::function cob, int32_t seqid, " + << "(::std::function cob, int32_t seqid, " << "Protocol_* oprot, void* ctx, " << "::apache::thrift::TDelayedException* _throw);" << endl; } } } - f_header_ << " public:" << endl << indent() << class_name_ << "(::apache::thrift::stdcxx::shared_ptr<" << if_name_ + f_header_ << " public:" << endl << indent() << class_name_ << "(::std::shared_ptr<" << if_name_ << "> iface) :" << endl; if (!extends_.empty()) { f_header_ << indent() << " " << extends_ << "(iface)," << endl; @@ -3145,14 +3147,14 @@ void ProcessorGenerator::generate_factory() { << endl << " public:" << endl; indent_up(); - f_header_ << indent() << factory_class_name_ << "(const ::apache::thrift::stdcxx::shared_ptr< " << if_factory_name + f_header_ << indent() << factory_class_name_ << "(const ::std::shared_ptr< " << if_factory_name << " >& handlerFactory) :" << endl << indent() << " handlerFactory_(handlerFactory) {}" << endl << endl << indent() - << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::" + << "::std::shared_ptr< ::apache::thrift::" << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " << "getProcessor(const ::apache::thrift::TConnectionInfo& connInfo);" << endl; - f_header_ << endl << " protected:" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr< " + f_header_ << endl << " protected:" << endl << indent() << "::std::shared_ptr< " << if_factory_name << " > handlerFactory_;" << endl; indent_down(); @@ -3167,17 +3169,17 @@ void ProcessorGenerator::generate_factory() { } // Generate the getProcessor() method - f_out_ << template_header_ << indent() << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::" + f_out_ << template_header_ << indent() << "::std::shared_ptr< ::apache::thrift::" << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " << factory_class_name_ << template_suffix_ << "::getProcessor(" << "const ::apache::thrift::TConnectionInfo& connInfo) {" << endl; indent_up(); f_out_ << indent() << "::apache::thrift::ReleaseHandler< " << if_factory_name - << " > cleanup(handlerFactory_);" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr< " + << " > cleanup(handlerFactory_);" << endl << indent() << "::std::shared_ptr< " << if_name_ << " > handler(" << "handlerFactory_->getHandler(connInfo), cleanup);" << endl << indent() - << "::apache::thrift::stdcxx::shared_ptr< ::apache::thrift::" + << "::std::shared_ptr< ::apache::thrift::" << (style_ == "Cob" ? "async::TAsyncProcessor" : "TProcessor") << " > " << "processor(new " << class_name_ << template_suffix_ << "(handler));" << endl << indent() << "return processor;" << endl; @@ -3412,7 +3414,7 @@ void t_cpp_generator::generate_process_function(t_service* tservice, out << indent() << "template " << endl; } out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::process_" - << tfunction->get_name() << "(::apache::thrift::stdcxx::function cob, int32_t seqid, " + << tfunction->get_name() << "(::std::function cob, int32_t seqid, " << prot_type << "* iprot, " << prot_type << "* oprot)" << endl; scope_up(out); @@ -3469,28 +3471,28 @@ void t_cpp_generator::generate_process_function(t_service* tservice, // No return. Just hand off our cob. // TODO(dreiss): Call the cob immediately? out << indent() << "iface_->" << tfunction->get_name() << "(" - << "::apache::thrift::stdcxx::bind(cob, true)" << endl; + << "::std::bind(cob, true)" << endl; indent_up(); indent_up(); } else { string ret_arg, ret_placeholder; if (!tfunction->get_returntype()->is_void()) { ret_arg = ", const " + type_name(tfunction->get_returntype()) + "& _return"; - ret_placeholder = ", ::apache::thrift::stdcxx::placeholders::_1"; + ret_placeholder = ", ::std::placeholders::_1"; } // When gen_templates_ is true, the return_ and throw_ functions are // overloaded. We have to declare pointers to them so that the compiler // can resolve the correct overloaded version. out << indent() << "void (" << tservice->get_name() << "AsyncProcessor" << class_suffix - << "::*return_fn)(::apache::thrift::stdcxx::function " + << "::*return_fn)(::std::function " << "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx" << ret_arg << ") =" << endl; out << indent() << " &" << tservice->get_name() << "AsyncProcessor" << class_suffix << "::return_" << tfunction->get_name() << ";" << endl; if (!xceptions.empty()) { out << indent() << "void (" << tservice->get_name() << "AsyncProcessor" << class_suffix - << "::*throw_fn)(::apache::thrift::stdcxx::function " + << "::*throw_fn)(::std::function " << "cob, int32_t seqid, " << prot_type << "* oprot, void* ctx, " << "::apache::thrift::TDelayedException* _throw) =" << endl; out << indent() << " &" << tservice->get_name() << "AsyncProcessor" << class_suffix @@ -3500,11 +3502,11 @@ void t_cpp_generator::generate_process_function(t_service* tservice, out << indent() << "iface_->" << tfunction->get_name() << "(" << endl; indent_up(); indent_up(); - out << indent() << "::apache::thrift::stdcxx::bind(return_fn, this, cob, seqid, oprot, ctx" << ret_placeholder + out << indent() << "::std::bind(return_fn, this, cob, seqid, oprot, ctx" << ret_placeholder << ")"; if (!xceptions.empty()) { - out << ',' << endl << indent() << "::apache::thrift::stdcxx::bind(throw_fn, this, cob, seqid, oprot, " - << "ctx, ::apache::thrift::stdcxx::placeholders::_1)"; + out << ',' << endl << indent() << "::std::bind(throw_fn, this, cob, seqid, oprot, " + << "ctx, ::std::placeholders::_1)"; } } @@ -3529,7 +3531,7 @@ void t_cpp_generator::generate_process_function(t_service* tservice, out << indent() << "template " << endl; } out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::return_" - << tfunction->get_name() << "(::apache::thrift::stdcxx::function cob, int32_t seqid, " + << tfunction->get_name() << "(::std::function cob, int32_t seqid, " << prot_type << "* oprot, void* ctx" << ret_arg_decl << ')' << endl; scope_up(out); @@ -3577,7 +3579,7 @@ void t_cpp_generator::generate_process_function(t_service* tservice, out << indent() << "template " << endl; } out << "void " << tservice->get_name() << "AsyncProcessor" << class_suffix << "::throw_" - << tfunction->get_name() << "(::apache::thrift::stdcxx::function cob, int32_t seqid, " + << tfunction->get_name() << "(::std::function cob, int32_t seqid, " << prot_type << "* oprot, void* ctx, " << "::apache::thrift::TDelayedException* _throw)" << endl; scope_up(out); @@ -3707,13 +3709,13 @@ void t_cpp_generator::generate_service_skeleton(t_service* tservice) { f_skeleton << indent() << "int main(int argc, char **argv) {" << endl; indent_up(); f_skeleton - << indent() << "int port = 9090;" << endl << indent() << "::apache::thrift::stdcxx::shared_ptr<" << svcname + << indent() << "int port = 9090;" << endl << indent() << "::std::shared_ptr<" << svcname << "Handler> handler(new " << svcname << "Handler());" << endl << indent() - << "::apache::thrift::stdcxx::shared_ptr processor(new " << svcname << "Processor(handler));" << endl - << indent() << "::apache::thrift::stdcxx::shared_ptr serverTransport(new TServerSocket(port));" + << "::std::shared_ptr processor(new " << svcname << "Processor(handler));" << endl + << indent() << "::std::shared_ptr serverTransport(new TServerSocket(port));" << endl << indent() - << "::apache::thrift::stdcxx::shared_ptr transportFactory(new TBufferedTransportFactory());" << endl - << indent() << "::apache::thrift::stdcxx::shared_ptr protocolFactory(new TBinaryProtocolFactory());" + << "::std::shared_ptr transportFactory(new TBufferedTransportFactory());" << endl + << indent() << "::std::shared_ptr protocolFactory(new TBinaryProtocolFactory());" << endl << endl << indent() << "TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);" << endl << indent() << "server.serve();" << endl << indent() << "return 0;" << endl; @@ -3802,7 +3804,7 @@ void t_cpp_generator::generate_deserialize_struct(ostream& out, bool pointer) { if (pointer) { indent(out) << "if (!" << prefix << ") { " << endl; - indent(out) << " " << prefix << " = ::apache::thrift::stdcxx::shared_ptr<" << type_name(tstruct) << ">(new " + indent(out) << " " << prefix << " = ::std::shared_ptr<" << type_name(tstruct) << ">(new " << type_name(tstruct) << ");" << endl; indent(out) << "}" << endl; indent(out) << "xfer += " << prefix << "->read(iprot);" << endl; @@ -4294,7 +4296,7 @@ string t_cpp_generator::declare_field(t_field* tfield, } result += type_name(tfield->get_type()); if (is_reference(tfield)) { - result = "::apache::thrift::stdcxx::shared_ptr<" + result + ">"; + result = "::std::shared_ptr<" + result + ">"; } if (pointer) { result += "*"; @@ -4373,13 +4375,13 @@ string t_cpp_generator::function_signature(t_function* tfunction, cob_type = (ttype->is_void() ? "()" : ("(" + type_name(ttype) + " const& _return)")); if (has_xceptions) { exn_cob - = ", ::apache::thrift::stdcxx::function /* exn_cob */"; + = ", ::std::function /* exn_cob */"; } } else { throw "UNKNOWN STYLE"; } - return "void " + prefix + tfunction->get_name() + "(::apache::thrift::stdcxx::function cob" + return "void " + prefix + tfunction->get_name() + "(::std::function cob" + exn_cob + argument_list(arglist, name_params, true) + ")"; } else { throw "UNKNOWN STYLE"; diff --git a/compiler/cpp/src/thrift/plugin/plugin.cc b/compiler/cpp/src/thrift/plugin/plugin.cc index ca5d28771f1..7c4c432b099 100644 --- a/compiler/cpp/src/thrift/plugin/plugin.cc +++ b/compiler/cpp/src/thrift/plugin/plugin.cc @@ -25,7 +25,9 @@ #endif #include +#include #include +#include #include #include @@ -35,7 +37,6 @@ #include "thrift/protocol/TBinaryProtocol.h" #include "thrift/transport/TBufferTransports.h" #include "thrift/transport/TFDTransport.h" -#include "thrift/stdcxx.h" #include "thrift/plugin/plugin_types.h" namespace apache { @@ -119,7 +120,7 @@ struct TypeCache { void compileAll() { boost::for_each(*source | boost::adaptors::map_keys, - stdcxx::bind(&TypeCache::compile, this, stdcxx::placeholders::_1)); + std::bind(&TypeCache::compile, this, std::placeholders::_1)); } std::map const* source; @@ -227,7 +228,7 @@ THRIFT_CONVERSION(t_enum, g_program_cache[from.metadata.program_id]) { assert(to); THRIFT_ASSIGN_METADATA(); boost::for_each(from.constants | boost::adaptors::transformed(convert), - stdcxx::bind(&::t_enum::append, to, stdcxx::placeholders::_1)); + std::bind(&::t_enum::append, to, std::placeholders::_1)); } THRIFT_CONVERSION(t_list, resolve_type< ::t_type>(from.elem_type)) { assert(to); @@ -264,7 +265,7 @@ THRIFT_CONVERSION(t_const_value, ) { } else if (from.__isset.list_val) { to->set_list(); boost::for_each(from.list_val | boost::adaptors::transformed(&convert), - stdcxx::bind(&::t_const_value::add_list, to, stdcxx::placeholders::_1)); + std::bind(&::t_const_value::add_list, to, std::placeholders::_1)); } else T_CONST_VALUE_CASE(string); else T_CONST_VALUE_CASE(integer); @@ -291,7 +292,7 @@ THRIFT_CONVERSION(t_struct, g_program_cache[from.metadata.program_id]) { to->set_union(from.is_union); to->set_xception(from.is_xception); boost::for_each(from.members | boost::adaptors::transformed(convert), - stdcxx::bind(&::t_struct::append, to, stdcxx::placeholders::_1)); + std::bind(&::t_struct::append, to, std::placeholders::_1)); } THRIFT_CONVERSION(t_const, resolve_type< ::t_type>(from.type), @@ -318,7 +319,7 @@ THRIFT_CONVERSION(t_service, g_program_cache[from.metadata.program_id]) { THRIFT_ASSIGN_METADATA(); boost::for_each(from.functions | boost::adaptors::transformed(convert), - stdcxx::bind(&::t_service::add_function, to, stdcxx::placeholders::_1)); + std::bind(&::t_service::add_function, to, std::placeholders::_1)); if (from.__isset.extends_) to->set_extends(resolve_service(from.extends_)); @@ -399,9 +400,9 @@ THRIFT_CONVERT_COMPLETE(t_program) { to->set_out_path(from.out_path, from.out_path_is_absolute); boost::for_each(from.typedefs | boost::adaptors::transformed(&resolve_type< ::t_typedef>), - stdcxx::bind(&::t_program::add_typedef, to, stdcxx::placeholders::_1)); + std::bind(&::t_program::add_typedef, to, std::placeholders::_1)); boost::for_each(from.enums | boost::adaptors::transformed(&resolve_type< ::t_enum>), - stdcxx::bind(&::t_program::add_enum, to, stdcxx::placeholders::_1)); + std::bind(&::t_program::add_enum, to, std::placeholders::_1)); for (std::vector::const_iterator it = from.objects.begin(); it != from.objects.end(); it++) { ::t_struct* t2 = resolve_type< ::t_struct>(*it); @@ -412,18 +413,18 @@ THRIFT_CONVERT_COMPLETE(t_program) { } } boost::for_each(from.consts | boost::adaptors::transformed(&resolve_const), - stdcxx::bind(&::t_program::add_const, to, stdcxx::placeholders::_1)); + std::bind(&::t_program::add_const, to, std::placeholders::_1)); boost::for_each(from.services | boost::adaptors::transformed(&resolve_service), - stdcxx::bind(&::t_program::add_service, to, stdcxx::placeholders::_1)); + std::bind(&::t_program::add_service, to, std::placeholders::_1)); for (std::vector::const_iterator it = from.includes.begin(); it != from.includes.end(); it++) { convert(*it, g_program_cache[it->program_id]); } std::for_each(from.c_includes.begin(), from.c_includes.end(), - stdcxx::bind(&::t_program::add_c_include, to, stdcxx::placeholders::_1)); + std::bind(&::t_program::add_c_include, to, std::placeholders::_1)); std::for_each(from.cpp_includes.begin(), from.cpp_includes.end(), - stdcxx::bind(&::t_program::add_cpp_include, to, stdcxx::placeholders::_1)); + std::bind(&::t_program::add_cpp_include, to, std::placeholders::_1)); for (std::map::const_iterator it = from.namespaces.begin(); it != from.namespaces.end(); it++) { to->set_namespace(it->first, it->second); @@ -437,8 +438,8 @@ int GeneratorPlugin::exec(int, char* []) { #ifdef _WIN32 _setmode(fileno(stdin), _O_BINARY); #endif - stdcxx::shared_ptr transport( - new TFramedTransport(stdcxx::make_shared(fileno(stdin)))); + std::shared_ptr transport( + new TFramedTransport(std::make_shared(fileno(stdin)))); TBinaryProtocol proto(transport); GeneratorInput input; try { diff --git a/compiler/cpp/src/thrift/plugin/plugin_output.cc b/compiler/cpp/src/thrift/plugin/plugin_output.cc index 81b9a2aa688..f8223dedc2a 100644 --- a/compiler/cpp/src/thrift/plugin/plugin_output.cc +++ b/compiler/cpp/src/thrift/plugin/plugin_output.cc @@ -39,12 +39,13 @@ #include "thrift/plugin/plugin.h" #include "thrift/plugin/type_util.h" #include "thrift/protocol/TBinaryProtocol.h" -#include "thrift/stdcxx.h" #include "thrift/transport/TBufferTransports.h" #include "thrift/transport/TFDTransport.h" #include "thrift/plugin/plugin_types.h" +#include + namespace plugin_output { template @@ -55,8 +56,8 @@ typename apache::thrift::plugin::ToType::type convert(From* from) { } using apache::thrift::protocol::TBinaryProtocol; -using apache::thrift::stdcxx::make_shared; -using apache::thrift::stdcxx::shared_ptr; +using std::make_shared; +using std::shared_ptr; using apache::thrift::transport::TFDTransport; using apache::thrift::transport::TFramedTransport; diff --git a/contrib/zeromq/TZmqServer.cpp b/contrib/zeromq/TZmqServer.cpp index 4df6c923708..88660a3305c 100644 --- a/contrib/zeromq/TZmqServer.cpp +++ b/contrib/zeromq/TZmqServer.cpp @@ -21,7 +21,7 @@ #include #include -using apache::thrift::stdcxx::shared_ptr; +using apache::thrift::std::shared_ptr; using apache::thrift::transport::TMemoryBuffer; using apache::thrift::protocol::TProtocol; diff --git a/contrib/zeromq/test-client.cpp b/contrib/zeromq/test-client.cpp index 70a331ed57f..159c25030d5 100644 --- a/contrib/zeromq/test-client.cpp +++ b/contrib/zeromq/test-client.cpp @@ -6,7 +6,7 @@ #include "TZmqClient.h" #include "Storage.h" -using apache::thrift::stdcxx::shared_ptr; +using apache::thrift::std::shared_ptr; using apache::thrift::transport::TZmqClient; using apache::thrift::protocol::TBinaryProtocol; diff --git a/contrib/zeromq/test-receiver.cpp b/contrib/zeromq/test-receiver.cpp index 60791ac72fe..d465bff6343 100644 --- a/contrib/zeromq/test-receiver.cpp +++ b/contrib/zeromq/test-receiver.cpp @@ -2,7 +2,7 @@ #include "TZmqServer.h" #include "Storage.h" -using apache::thrift::stdcxx::shared_ptr; +using apache::thrift::std::shared_ptr; using apache::thrift::TProcessor; using apache::thrift::server::TZmqServer; using apache::thrift::server::TZmqMultiServer; diff --git a/contrib/zeromq/test-sender.cpp b/contrib/zeromq/test-sender.cpp index 8928db390a3..5c086a11ff8 100644 --- a/contrib/zeromq/test-sender.cpp +++ b/contrib/zeromq/test-sender.cpp @@ -6,7 +6,7 @@ #include "TZmqClient.h" #include "Storage.h" -using apache::thrift::stdcxx::shared_ptr; +using apache::thrift::std::shared_ptr; using apache::thrift::transport::TZmqClient; using apache::thrift::protocol::TBinaryProtocol; diff --git a/contrib/zeromq/test-server.cpp b/contrib/zeromq/test-server.cpp index baa1451dd27..e6f1b208370 100644 --- a/contrib/zeromq/test-server.cpp +++ b/contrib/zeromq/test-server.cpp @@ -2,7 +2,7 @@ #include "TZmqServer.h" #include "Storage.h" -using apache::thrift::stdcxx::shared_ptr; +using apache::thrift::std::shared_ptr; using apache::thrift::TProcessor; using apache::thrift::server::TZmqServer; using apache::thrift::server::TZmqMultiServer; diff --git a/lib/c_glib/test/testthrifttestclient.cpp b/lib/c_glib/test/testthrifttestclient.cpp index 5b06883ebcf..1910c8a40b0 100755 --- a/lib/c_glib/test/testthrifttestclient.cpp +++ b/lib/c_glib/test/testthrifttestclient.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include "ThriftTest.h" #include "ThriftTest_types.h" @@ -618,11 +618,11 @@ main (void) if (pid == 0) /* child */ { - stdcxx::shared_ptr protocolFactory(new TBinaryProtocolFactory()); - stdcxx::shared_ptr testHandler(new TestHandler()); - stdcxx::shared_ptr testProcessor(new ThriftTestProcessor(testHandler)); - stdcxx::shared_ptr serverSocket(new TServerSocket(TEST_PORT)); - stdcxx::shared_ptr transportFactory(new TBufferedTransportFactory()); + std::shared_ptr protocolFactory(new TBinaryProtocolFactory()); + std::shared_ptr testHandler(new TestHandler()); + std::shared_ptr testProcessor(new ThriftTestProcessor(testHandler)); + std::shared_ptr serverSocket(new TServerSocket(TEST_PORT)); + std::shared_ptr transportFactory(new TBufferedTransportFactory()); TSimpleServer simpleServer(testProcessor, serverSocket, transportFactory, protocolFactory); signal (SIGALRM, bailout); alarm (60); diff --git a/lib/cpp/src/thrift/TDispatchProcessor.h b/lib/cpp/src/thrift/TDispatchProcessor.h index dadc87b5c05..28d347dbbd2 100644 --- a/lib/cpp/src/thrift/TDispatchProcessor.h +++ b/lib/cpp/src/thrift/TDispatchProcessor.h @@ -33,8 +33,8 @@ namespace thrift { template class TDispatchProcessorT : public TProcessor { public: - virtual bool process(stdcxx::shared_ptr in, - stdcxx::shared_ptr out, + virtual bool process(std::shared_ptr in, + std::shared_ptr out, void* connectionContext) { protocol::TProtocol* inRaw = in.get(); protocol::TProtocol* outRaw = out.get(); @@ -105,8 +105,8 @@ class TDispatchProcessorT : public TProcessor { */ class TDispatchProcessor : public TProcessor { public: - virtual bool process(stdcxx::shared_ptr in, - stdcxx::shared_ptr out, + virtual bool process(std::shared_ptr in, + std::shared_ptr out, void* connectionContext) { std::string fname; protocol::TMessageType mtype; diff --git a/lib/cpp/src/thrift/TProcessor.h b/lib/cpp/src/thrift/TProcessor.h index 27294d3ec0c..6a464668fe5 100644 --- a/lib/cpp/src/thrift/TProcessor.h +++ b/lib/cpp/src/thrift/TProcessor.h @@ -22,7 +22,6 @@ #include #include -#include namespace apache { namespace thrift { @@ -142,28 +141,28 @@ class TProcessor { public: virtual ~TProcessor() {} - virtual bool process(stdcxx::shared_ptr in, - stdcxx::shared_ptr out, + virtual bool process(std::shared_ptr in, + std::shared_ptr out, void* connectionContext) = 0; - bool process(stdcxx::shared_ptr io, void* connectionContext) { + bool process(std::shared_ptr io, void* connectionContext) { return process(io, io, connectionContext); } - stdcxx::shared_ptr getEventHandler() const { return eventHandler_; } + std::shared_ptr getEventHandler() const { return eventHandler_; } - void setEventHandler(stdcxx::shared_ptr eventHandler) { + void setEventHandler(std::shared_ptr eventHandler) { eventHandler_ = eventHandler; } protected: TProcessor() {} - stdcxx::shared_ptr eventHandler_; + std::shared_ptr eventHandler_; }; /** - * This is a helper class to allow stdcxx::shared_ptr to be used with handler + * This is a helper class to allow std::shared_ptr to be used with handler * pointers returned by the generated handler factories. * * The handler factory classes generated by the thrift compiler return raw @@ -177,7 +176,7 @@ class TProcessor { template class ReleaseHandler { public: - ReleaseHandler(const stdcxx::shared_ptr& handlerFactory) + ReleaseHandler(const std::shared_ptr& handlerFactory) : handlerFactory_(handlerFactory) {} void operator()(typename HandlerFactory_::Handler* handler) { @@ -187,18 +186,18 @@ class ReleaseHandler { } private: - stdcxx::shared_ptr handlerFactory_; + std::shared_ptr handlerFactory_; }; struct TConnectionInfo { // The input and output protocols - stdcxx::shared_ptr input; - stdcxx::shared_ptr output; + std::shared_ptr input; + std::shared_ptr output; // The underlying transport used for the connection // This is the transport that was returned by TServerTransport::accept(), // and it may be different than the transport pointed to by the input and // output protocols. - stdcxx::shared_ptr transport; + std::shared_ptr transport; }; class TProcessorFactory { @@ -212,17 +211,17 @@ class TProcessorFactory { * accepted on. This generally means that this call does not need to be * thread safe, as it will always be invoked from a single thread. */ - virtual stdcxx::shared_ptr getProcessor(const TConnectionInfo& connInfo) = 0; + virtual std::shared_ptr getProcessor(const TConnectionInfo& connInfo) = 0; }; class TSingletonProcessorFactory : public TProcessorFactory { public: - TSingletonProcessorFactory(stdcxx::shared_ptr processor) : processor_(processor) {} + TSingletonProcessorFactory(std::shared_ptr processor) : processor_(processor) {} - stdcxx::shared_ptr getProcessor(const TConnectionInfo&) { return processor_; } + std::shared_ptr getProcessor(const TConnectionInfo&) { return processor_; } private: - stdcxx::shared_ptr processor_; + std::shared_ptr processor_; }; } } // apache::thrift diff --git a/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h b/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h index 0d56c78d0b3..9c96b14a6e4 100644 --- a/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h +++ b/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h @@ -20,7 +20,7 @@ #ifndef _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ #define _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ 1 -#include +#include #include namespace apache { @@ -34,9 +34,9 @@ class TAsyncBufferProcessor { // forcefully close the connection (if applicable). // "in" and "out" should be TMemoryBuffer or similar, // not a wrapper around a socket. - virtual void process(stdcxx::function _return, - stdcxx::shared_ptr ibuf, - stdcxx::shared_ptr obuf) = 0; + virtual void process(std::function _return, + std::shared_ptr ibuf, + std::shared_ptr obuf) = 0; virtual ~TAsyncBufferProcessor() {} }; } diff --git a/lib/cpp/src/thrift/async/TAsyncChannel.cpp b/lib/cpp/src/thrift/async/TAsyncChannel.cpp index c87659fcaf5..01b91131f44 100644 --- a/lib/cpp/src/thrift/async/TAsyncChannel.cpp +++ b/lib/cpp/src/thrift/async/TAsyncChannel.cpp @@ -18,7 +18,6 @@ */ #include -#include namespace apache { namespace thrift { @@ -27,8 +26,8 @@ namespace async { void TAsyncChannel::sendAndRecvMessage(const VoidCallback& cob, TMemoryBuffer* sendBuf, TMemoryBuffer* recvBuf) { - apache::thrift::stdcxx::function send_done - = apache::thrift::stdcxx::bind(&TAsyncChannel::recvMessage, this, cob, recvBuf); + std::function send_done + = std::bind(&TAsyncChannel::recvMessage, this, cob, recvBuf); sendMessage(send_done, sendBuf); } diff --git a/lib/cpp/src/thrift/async/TAsyncChannel.h b/lib/cpp/src/thrift/async/TAsyncChannel.h index f8d2b036aeb..d7ace96c29c 100644 --- a/lib/cpp/src/thrift/async/TAsyncChannel.h +++ b/lib/cpp/src/thrift/async/TAsyncChannel.h @@ -20,7 +20,8 @@ #ifndef _THRIFT_ASYNC_TASYNCCHANNEL_H_ #define _THRIFT_ASYNC_TASYNCCHANNEL_H_ 1 -#include +#include +#include #include namespace apache { @@ -38,7 +39,7 @@ using apache::thrift::transport::TMemoryBuffer; class TAsyncChannel { public: - typedef apache::thrift::stdcxx::function VoidCallback; + typedef std::function VoidCallback; virtual ~TAsyncChannel() {} diff --git a/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h b/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h index a1450f0154c..59db5977d3c 100644 --- a/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h +++ b/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h @@ -34,9 +34,9 @@ namespace async { template class TAsyncDispatchProcessorT : public TAsyncProcessor { public: - virtual void process(apache::thrift::stdcxx::function _return, - stdcxx::shared_ptr in, - stdcxx::shared_ptr out) { + virtual void process(std::function _return, + std::shared_ptr in, + std::shared_ptr out) { protocol::TProtocol* inRaw = in.get(); protocol::TProtocol* outRaw = out.get(); @@ -70,7 +70,7 @@ class TAsyncDispatchProcessorT : public TAsyncProcessor { return this->dispatchCall(_return, inRaw, outRaw, fname, seqid); } - void processFast(apache::thrift::stdcxx::function _return, + void processFast(std::function _return, Protocol_* in, Protocol_* out) { std::string fname; @@ -87,13 +87,13 @@ class TAsyncDispatchProcessorT : public TAsyncProcessor { return this->dispatchCallTemplated(_return, in, out, fname, seqid); } - virtual void dispatchCall(apache::thrift::stdcxx::function _return, + virtual void dispatchCall(std::function _return, apache::thrift::protocol::TProtocol* in, apache::thrift::protocol::TProtocol* out, const std::string& fname, int32_t seqid) = 0; - virtual void dispatchCallTemplated(apache::thrift::stdcxx::function _return, + virtual void dispatchCallTemplated(std::function _return, Protocol_* in, Protocol_* out, const std::string& fname, @@ -106,9 +106,9 @@ class TAsyncDispatchProcessorT : public TAsyncProcessor { */ class TAsyncDispatchProcessor : public TAsyncProcessor { public: - virtual void process(apache::thrift::stdcxx::function _return, - stdcxx::shared_ptr in, - stdcxx::shared_ptr out) { + virtual void process(std::function _return, + std::shared_ptr in, + std::shared_ptr out) { protocol::TProtocol* inRaw = in.get(); protocol::TProtocol* outRaw = out.get(); @@ -131,7 +131,7 @@ class TAsyncDispatchProcessor : public TAsyncProcessor { return dispatchCall(_return, inRaw, outRaw, fname, seqid); } - virtual void dispatchCall(apache::thrift::stdcxx::function _return, + virtual void dispatchCall(std::function _return, apache::thrift::protocol::TProtocol* in, apache::thrift::protocol::TProtocol* out, const std::string& fname, diff --git a/lib/cpp/src/thrift/async/TAsyncProcessor.h b/lib/cpp/src/thrift/async/TAsyncProcessor.h index afc4ffaa43f..fdb976dd3cf 100644 --- a/lib/cpp/src/thrift/async/TAsyncProcessor.h +++ b/lib/cpp/src/thrift/async/TAsyncProcessor.h @@ -21,7 +21,7 @@ #define _THRIFT_TASYNCPROCESSOR_H_ 1 #include -#include +#include #include namespace apache { @@ -37,25 +37,25 @@ class TAsyncProcessor { public: virtual ~TAsyncProcessor() {} - virtual void process(stdcxx::function _return, - stdcxx::shared_ptr in, - stdcxx::shared_ptr out) = 0; + virtual void process(std::function _return, + std::shared_ptr in, + std::shared_ptr out) = 0; - void process(stdcxx::function _return, - stdcxx::shared_ptr io) { + void process(std::function _return, + std::shared_ptr io) { return process(_return, io, io); } - stdcxx::shared_ptr getEventHandler() const { return eventHandler_; } + std::shared_ptr getEventHandler() const { return eventHandler_; } - void setEventHandler(stdcxx::shared_ptr eventHandler) { + void setEventHandler(std::shared_ptr eventHandler) { eventHandler_ = eventHandler; } protected: TAsyncProcessor() {} - stdcxx::shared_ptr eventHandler_; + std::shared_ptr eventHandler_; }; class TAsyncProcessorFactory { @@ -69,7 +69,7 @@ class TAsyncProcessorFactory { * accepted on. This generally means that this call does not need to be * thread safe, as it will always be invoked from a single thread. */ - virtual stdcxx::shared_ptr getProcessor(const TConnectionInfo& connInfo) = 0; + virtual std::shared_ptr getProcessor(const TConnectionInfo& connInfo) = 0; }; } } diff --git a/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.cpp b/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.cpp index b9ffb044802..cb5201bf65b 100644 --- a/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.cpp +++ b/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.cpp @@ -26,23 +26,23 @@ namespace apache { namespace thrift { namespace async { -void TAsyncProtocolProcessor::process(apache::thrift::stdcxx::function _return, - stdcxx::shared_ptr ibuf, - stdcxx::shared_ptr obuf) { - stdcxx::shared_ptr iprot(pfact_->getProtocol(ibuf)); - stdcxx::shared_ptr oprot(pfact_->getProtocol(obuf)); +void TAsyncProtocolProcessor::process(std::function _return, + std::shared_ptr ibuf, + std::shared_ptr obuf) { + std::shared_ptr iprot(pfact_->getProtocol(ibuf)); + std::shared_ptr oprot(pfact_->getProtocol(obuf)); return underlying_ - ->process(apache::thrift::stdcxx::bind(&TAsyncProtocolProcessor::finish, + ->process(std::bind(&TAsyncProtocolProcessor::finish, _return, oprot, - apache::thrift::stdcxx::placeholders::_1), + std::placeholders::_1), iprot, oprot); } /* static */ void TAsyncProtocolProcessor::finish( - apache::thrift::stdcxx::function _return, - stdcxx::shared_ptr oprot, + std::function _return, + std::shared_ptr oprot, bool healthy) { (void)oprot; // This is a stub function to hold a reference to oprot. diff --git a/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h b/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h index ce3883c2f23..8052cf36487 100644 --- a/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h +++ b/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h @@ -30,23 +30,23 @@ namespace async { class TAsyncProtocolProcessor : public TAsyncBufferProcessor { public: - TAsyncProtocolProcessor(stdcxx::shared_ptr underlying, - stdcxx::shared_ptr pfact) + TAsyncProtocolProcessor(std::shared_ptr underlying, + std::shared_ptr pfact) : underlying_(underlying), pfact_(pfact) {} - virtual void process(apache::thrift::stdcxx::function _return, - stdcxx::shared_ptr ibuf, - stdcxx::shared_ptr obuf); + virtual void process(std::function _return, + std::shared_ptr ibuf, + std::shared_ptr obuf); virtual ~TAsyncProtocolProcessor() {} private: - static void finish(apache::thrift::stdcxx::function _return, - stdcxx::shared_ptr oprot, + static void finish(std::function _return, + std::shared_ptr oprot, bool healthy); - stdcxx::shared_ptr underlying_; - stdcxx::shared_ptr pfact_; + std::shared_ptr underlying_; + std::shared_ptr pfact_; }; } } diff --git a/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.h b/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.h index 9ec77b962ca..0bc5eb565f5 100644 --- a/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.h +++ b/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.h @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -60,7 +60,7 @@ class TConcurrentRecvSentry { class TConcurrentClientSyncInfo { private: // typedefs - typedef stdcxx::shared_ptr< ::apache::thrift::concurrency::Monitor> MonitorPtr; + typedef std::shared_ptr< ::apache::thrift::concurrency::Monitor> MonitorPtr; typedef std::map MonitorMap; public: diff --git a/lib/cpp/src/thrift/async/TEvhttpClientChannel.h b/lib/cpp/src/thrift/async/TEvhttpClientChannel.h index 3515ca22f12..a321f417b42 100644 --- a/lib/cpp/src/thrift/async/TEvhttpClientChannel.h +++ b/lib/cpp/src/thrift/async/TEvhttpClientChannel.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include struct event_base; diff --git a/lib/cpp/src/thrift/async/TEvhttpServer.cpp b/lib/cpp/src/thrift/async/TEvhttpServer.cpp index d87e507d82c..bdc32661fad 100644 --- a/lib/cpp/src/thrift/async/TEvhttpServer.cpp +++ b/lib/cpp/src/thrift/async/TEvhttpServer.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -31,8 +31,7 @@ #endif using apache::thrift::transport::TMemoryBuffer; -using apache::thrift::stdcxx::scoped_ptr; -using apache::thrift::stdcxx::shared_ptr; +using std::shared_ptr; namespace apache { namespace thrift { @@ -40,17 +39,17 @@ namespace async { struct TEvhttpServer::RequestContext { struct evhttp_request* req; - stdcxx::shared_ptr ibuf; - stdcxx::shared_ptr obuf; + std::shared_ptr ibuf; + std::shared_ptr obuf; RequestContext(struct evhttp_request* req); }; -TEvhttpServer::TEvhttpServer(stdcxx::shared_ptr processor) +TEvhttpServer::TEvhttpServer(std::shared_ptr processor) : processor_(processor), eb_(NULL), eh_(NULL) { } -TEvhttpServer::TEvhttpServer(stdcxx::shared_ptr processor, int port) +TEvhttpServer::TEvhttpServer(std::shared_ptr processor, int port) : processor_(processor), eb_(NULL), eh_(NULL) { // Create event_base and evhttp. eb_ = event_base_new(); @@ -110,17 +109,17 @@ void TEvhttpServer::request(struct evhttp_request* req, void* self) { void TEvhttpServer::process(struct evhttp_request* req) { RequestContext* ctx = new RequestContext(req); - return processor_->process(apache::thrift::stdcxx::bind(&TEvhttpServer::complete, + return processor_->process(std::bind(&TEvhttpServer::complete, this, ctx, - apache::thrift::stdcxx::placeholders::_1), + std::placeholders::_1), ctx->ibuf, ctx->obuf); } void TEvhttpServer::complete(RequestContext* ctx, bool success) { (void)success; - scoped_ptr ptr(ctx); + std::unique_ptr ptr(ctx); int code = success ? 200 : 400; const char* reason = success ? "OK" : "Bad Request"; diff --git a/lib/cpp/src/thrift/async/TEvhttpServer.h b/lib/cpp/src/thrift/async/TEvhttpServer.h index afc679ccfc6..c5bf3b6eef4 100644 --- a/lib/cpp/src/thrift/async/TEvhttpServer.h +++ b/lib/cpp/src/thrift/async/TEvhttpServer.h @@ -20,7 +20,7 @@ #ifndef _THRIFT_TEVHTTP_SERVER_H_ #define _THRIFT_TEVHTTP_SERVER_H_ 1 -#include +#include struct event_base; struct evhttp; @@ -41,14 +41,14 @@ class TEvhttpServer { * address of the server as the extra arg. * Do not call "serve" on this server. */ - TEvhttpServer(stdcxx::shared_ptr processor); + TEvhttpServer(std::shared_ptr processor); /** * Create a TEvhttpServer with an embedded event_base and evhttp, * listening on port and responding on the endpoint "/". * Call "serve" on this server to serve forever. */ - TEvhttpServer(stdcxx::shared_ptr processor, int port); + TEvhttpServer(std::shared_ptr processor, int port); ~TEvhttpServer(); @@ -63,7 +63,7 @@ class TEvhttpServer { void process(struct evhttp_request* req); void complete(RequestContext* ctx, bool success); - stdcxx::shared_ptr processor_; + std::shared_ptr processor_; struct event_base* eb_; struct evhttp* eh_; }; diff --git a/lib/cpp/src/thrift/concurrency/FunctionRunner.h b/lib/cpp/src/thrift/concurrency/FunctionRunner.h index eabf019b759..8ad176eb4c8 100644 --- a/lib/cpp/src/thrift/concurrency/FunctionRunner.h +++ b/lib/cpp/src/thrift/concurrency/FunctionRunner.h @@ -21,7 +21,7 @@ #define _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H 1 #include -#include +#include namespace apache { namespace thrift { @@ -44,7 +44,7 @@ namespace concurrency { * A* a = new A(); * // To create a thread that executes a.foo() every 100 milliseconds: * factory->newThread(FunctionRunner::create( - * apache::thrift::stdcxx::bind(&A::foo, a), 100))->start(); + * std::bind(&A::foo, a), 100))->start(); * */ @@ -53,20 +53,20 @@ class FunctionRunner : public Runnable { // This is the type of callback 'pthread_create()' expects. typedef void* (*PthreadFuncPtr)(void* arg); // This a fully-generic void(void) callback for custom bindings. - typedef stdcxx::function VoidFunc; + typedef std::function VoidFunc; - typedef stdcxx::function BoolFunc; + typedef std::function BoolFunc; /** * Syntactic sugar to make it easier to create new FunctionRunner * objects wrapped in shared_ptr. */ - static stdcxx::shared_ptr create(const VoidFunc& cob) { - return stdcxx::shared_ptr(new FunctionRunner(cob)); + static std::shared_ptr create(const VoidFunc& cob) { + return std::shared_ptr(new FunctionRunner(cob)); } - static stdcxx::shared_ptr create(PthreadFuncPtr func, void* arg) { - return stdcxx::shared_ptr(new FunctionRunner(func, arg)); + static std::shared_ptr create(PthreadFuncPtr func, void* arg) { + return std::shared_ptr(new FunctionRunner(func, arg)); } private: @@ -81,7 +81,7 @@ class FunctionRunner : public Runnable { * execute the given callback. Note that the 'void*' return value is ignored. */ FunctionRunner(PthreadFuncPtr func, void* arg) - : func_(stdcxx::bind(pthread_func_wrapper, func, arg)), intervalMs_(-1) {} + : func_(std::bind(pthread_func_wrapper, func, arg)), intervalMs_(-1) {} /** * Given a generic callback, this FunctionRunner will execute it. diff --git a/lib/cpp/src/thrift/concurrency/Monitor.cpp b/lib/cpp/src/thrift/concurrency/Monitor.cpp index af4fcd09c50..8e4ac79a71c 100644 --- a/lib/cpp/src/thrift/concurrency/Monitor.cpp +++ b/lib/cpp/src/thrift/concurrency/Monitor.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include @@ -34,8 +34,8 @@ namespace apache { namespace thrift { -using stdcxx::scoped_ptr; -using stdcxx::shared_ptr; +using std::scoped_ptr; +using std::shared_ptr; namespace concurrency { diff --git a/lib/cpp/src/thrift/concurrency/Mutex.h b/lib/cpp/src/thrift/concurrency/Mutex.h index 09b938e5b1b..a1f539685c2 100644 --- a/lib/cpp/src/thrift/concurrency/Mutex.h +++ b/lib/cpp/src/thrift/concurrency/Mutex.h @@ -20,7 +20,7 @@ #ifndef _THRIFT_CONCURRENCY_MUTEX_H_ #define _THRIFT_CONCURRENCY_MUTEX_H_ 1 -#include +#include #include #include @@ -86,7 +86,7 @@ class Mutex { private: class impl; - stdcxx::shared_ptr impl_; + std::shared_ptr impl_; }; class ReadWriteMutex { @@ -107,7 +107,7 @@ class ReadWriteMutex { private: class impl; - stdcxx::shared_ptr impl_; + std::shared_ptr impl_; }; /** diff --git a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp index 2e35446b5c8..5c592697776 100644 --- a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp +++ b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp @@ -32,7 +32,7 @@ #include -#include +#include namespace apache { namespace thrift { @@ -58,7 +58,7 @@ class PthreadThread : public Thread { int policy_; int priority_; int stackSize_; - stdcxx::weak_ptr self_; + std::weak_ptr self_; bool detached_; public: @@ -66,7 +66,7 @@ class PthreadThread : public Thread { int priority, int stackSize, bool detached, - stdcxx::shared_ptr runnable) + std::shared_ptr runnable) : #ifndef _WIN32 @@ -155,7 +155,7 @@ class PthreadThread : public Thread { } // Create reference - stdcxx::shared_ptr* selfRef = new stdcxx::shared_ptr(); + std::shared_ptr* selfRef = new std::shared_ptr(); *selfRef = self_.lock(); setState(starting); @@ -201,19 +201,19 @@ class PthreadThread : public Thread { #endif // _WIN32 } - stdcxx::shared_ptr runnable() const { return Thread::runnable(); } + std::shared_ptr runnable() const { return Thread::runnable(); } - void runnable(stdcxx::shared_ptr value) { Thread::runnable(value); } + void runnable(std::shared_ptr value) { Thread::runnable(value); } - void weakRef(stdcxx::shared_ptr self) { + void weakRef(std::shared_ptr self) { assert(self.get() == this); - self_ = stdcxx::weak_ptr(self); + self_ = std::weak_ptr(self); } }; void* PthreadThread::threadMain(void* arg) { - stdcxx::shared_ptr thread = *(stdcxx::shared_ptr*)arg; - delete reinterpret_cast*>(arg); + std::shared_ptr thread = *(std::shared_ptr*)arg; + delete reinterpret_cast*>(arg); #if GOOGLE_PERFTOOLS_REGISTER_THREAD ProfilerRegisterThread(); @@ -294,9 +294,9 @@ PosixThreadFactory::PosixThreadFactory(bool detached) stackSize_(1) { } -stdcxx::shared_ptr PosixThreadFactory::newThread(stdcxx::shared_ptr runnable) const { - stdcxx::shared_ptr result - = stdcxx::shared_ptr(new PthreadThread(toPthreadPolicy(policy_), +std::shared_ptr PosixThreadFactory::newThread(std::shared_ptr runnable) const { + std::shared_ptr result + = std::shared_ptr(new PthreadThread(toPthreadPolicy(policy_), toPthreadPriority(policy_, priority_), stackSize_, isDetached(), diff --git a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h index 5e04d01d33f..cb3b17c9c9c 100644 --- a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h +++ b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h @@ -22,7 +22,7 @@ #include -#include +#include namespace apache { namespace thrift { @@ -63,7 +63,7 @@ class PosixThreadFactory : public ThreadFactory { /** * Posix thread (pthread) factory. All threads created by a factory are reference-counted - * via stdcxx::shared_ptr. The factory guarantees that threads and the Runnable tasks + * via std::shared_ptr. The factory guarantees that threads and the Runnable tasks * they host will be properly cleaned up once the last strong reference to both is * given up. * @@ -88,7 +88,7 @@ class PosixThreadFactory : public ThreadFactory { PosixThreadFactory(bool detached); // From ThreadFactory; - stdcxx::shared_ptr newThread(stdcxx::shared_ptr runnable) const; + std::shared_ptr newThread(std::shared_ptr runnable) const; // From ThreadFactory; Thread::id_t getCurrentThreadId() const; diff --git a/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp b/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp index da0c5e373bc..c885f3acab4 100644 --- a/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp +++ b/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -42,11 +42,11 @@ namespace concurrency { * * @version $Id:$ */ -class StdThread : public Thread, public stdcxx::enable_shared_from_this { +class StdThread : public Thread, public std::enable_shared_from_this { public: enum STATE { uninitialized, starting, started, stopping, stopped }; - static void threadMain(stdcxx::shared_ptr thread); + static void threadMain(std::shared_ptr thread); private: std::unique_ptr thread_; @@ -55,7 +55,7 @@ class StdThread : public Thread, public stdcxx::enable_shared_from_this runnable) + StdThread(bool detached, std::shared_ptr runnable) : state_(uninitialized), detached_(detached) { this->Thread::runnable(runnable); } @@ -93,7 +93,7 @@ class StdThread : public Thread, public stdcxx::enable_shared_from_this selfRef = shared_from_this(); + std::shared_ptr selfRef = shared_from_this(); setState(starting); Synchronized sync(monitor_); @@ -116,12 +116,12 @@ class StdThread : public Thread, public stdcxx::enable_shared_from_thisget_id() : std::thread::id(); } - stdcxx::shared_ptr runnable() const { return Thread::runnable(); } + std::shared_ptr runnable() const { return Thread::runnable(); } - void runnable(stdcxx::shared_ptr value) { Thread::runnable(value); } + void runnable(std::shared_ptr value) { Thread::runnable(value); } }; -void StdThread::threadMain(stdcxx::shared_ptr thread) { +void StdThread::threadMain(std::shared_ptr thread) { #if GOOGLE_PERFTOOLS_REGISTER_THREAD ProfilerRegisterThread(); #endif @@ -137,8 +137,8 @@ void StdThread::threadMain(stdcxx::shared_ptr thread) { StdThreadFactory::StdThreadFactory(bool detached) : ThreadFactory(detached) { } -stdcxx::shared_ptr StdThreadFactory::newThread(stdcxx::shared_ptr runnable) const { - stdcxx::shared_ptr result = stdcxx::shared_ptr(new StdThread(isDetached(), runnable)); +std::shared_ptr StdThreadFactory::newThread(std::shared_ptr runnable) const { + std::shared_ptr result = std::shared_ptr(new StdThread(isDetached(), runnable)); runnable->thread(result); return result; } diff --git a/lib/cpp/src/thrift/concurrency/StdThreadFactory.h b/lib/cpp/src/thrift/concurrency/StdThreadFactory.h index 8e116b64aa0..e74046b7b30 100644 --- a/lib/cpp/src/thrift/concurrency/StdThreadFactory.h +++ b/lib/cpp/src/thrift/concurrency/StdThreadFactory.h @@ -22,7 +22,7 @@ #include -#include +#include namespace apache { namespace thrift { @@ -38,7 +38,7 @@ class StdThreadFactory : public ThreadFactory { public: /** * Std thread factory. All threads created by a factory are reference-counted - * via stdcxx::shared_ptr. The factory guarantees that threads and the Runnable tasks + * via std::shared_ptr. The factory guarantees that threads and the Runnable tasks * they host will be properly cleaned up once the last strong reference * to both is given up. * @@ -48,7 +48,7 @@ class StdThreadFactory : public ThreadFactory { StdThreadFactory(bool detached = true); // From ThreadFactory; - stdcxx::shared_ptr newThread(stdcxx::shared_ptr runnable) const; + std::shared_ptr newThread(std::shared_ptr runnable) const; // From ThreadFactory; Thread::id_t getCurrentThreadId() const; diff --git a/lib/cpp/src/thrift/concurrency/Thread.h b/lib/cpp/src/thrift/concurrency/Thread.h index 7e2d251e057..b2ea4e2975b 100644 --- a/lib/cpp/src/thrift/concurrency/Thread.h +++ b/lib/cpp/src/thrift/concurrency/Thread.h @@ -21,7 +21,7 @@ #define _THRIFT_CONCURRENCY_THREAD_H_ 1 #include -#include +#include #include @@ -54,16 +54,16 @@ class Runnable { * Gets the thread object that is hosting this runnable object - can return * an empty boost::shared pointer if no references remain on that thread object */ - virtual stdcxx::shared_ptr thread() { return thread_.lock(); } + virtual std::shared_ptr thread() { return thread_.lock(); } /** * Sets the thread that is executing this object. This is only meant for * use by concrete implementations of Thread. */ - virtual void thread(stdcxx::shared_ptr value) { thread_ = value; } + virtual void thread(std::shared_ptr value) { thread_ = value; } private: - stdcxx::weak_ptr thread_; + std::weak_ptr thread_; }; /** @@ -114,13 +114,13 @@ class Thread { /** * Gets the runnable object this thread is hosting */ - virtual stdcxx::shared_ptr runnable() const { return _runnable; } + virtual std::shared_ptr runnable() const { return _runnable; } protected: - virtual void runnable(stdcxx::shared_ptr value) { _runnable = value; } + virtual void runnable(std::shared_ptr value) { _runnable = value; } private: - stdcxx::shared_ptr _runnable; + std::shared_ptr _runnable; }; /** @@ -147,7 +147,7 @@ class ThreadFactory { /** * Create a new thread. */ - virtual stdcxx::shared_ptr newThread(stdcxx::shared_ptr runnable) const = 0; + virtual std::shared_ptr newThread(std::shared_ptr runnable) const = 0; /** * Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp index 2e27b7f42df..58025f9d519 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp +++ b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include @@ -34,8 +34,8 @@ namespace apache { namespace thrift { namespace concurrency { -using stdcxx::shared_ptr; -using stdcxx::dynamic_pointer_cast; +using std::shared_ptr; +using std::dynamic_pointer_cast; /** * ThreadManager class @@ -504,7 +504,7 @@ void ThreadManager::Impl::remove(shared_ptr task) { } } -stdcxx::shared_ptr ThreadManager::Impl::removeNextPending() { +std::shared_ptr ThreadManager::Impl::removeNextPending() { Guard g(mutex_); if (state_ != ThreadManager::STARTED) { throw IllegalStateException( @@ -513,7 +513,7 @@ stdcxx::shared_ptr ThreadManager::Impl::removeNextPending() { } if (tasks_.empty()) { - return stdcxx::shared_ptr(); + return std::shared_ptr(); } shared_ptr task = tasks_.front(); diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.h b/lib/cpp/src/thrift/concurrency/ThreadManager.h index b3b75421d9a..470fc0aaea3 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadManager.h +++ b/lib/cpp/src/thrift/concurrency/ThreadManager.h @@ -20,9 +20,10 @@ #ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_ #define _THRIFT_CONCURRENCY_THREADMANAGER_H_ 1 +#include +#include #include #include -#include namespace apache { namespace thrift { @@ -58,7 +59,7 @@ class ThreadManager { ThreadManager() {} public: - typedef apache::thrift::stdcxx::function)> ExpireCallback; + typedef std::function)> ExpireCallback; virtual ~ThreadManager() {} @@ -87,14 +88,14 @@ class ThreadManager { /** * \returns the current thread factory */ - virtual stdcxx::shared_ptr threadFactory() const = 0; + virtual std::shared_ptr threadFactory() const = 0; /** * Set the thread factory. * \throws InvalidArgumentException if the new thread factory has a different * detached disposition than the one replacing it */ - virtual void threadFactory(stdcxx::shared_ptr value) = 0; + virtual void threadFactory(std::shared_ptr value) = 0; /** * Adds worker thread(s). @@ -161,21 +162,21 @@ class ThreadManager { * * @throws TooManyPendingTasksException Pending task count exceeds max pending task count */ - virtual void add(stdcxx::shared_ptr task, + virtual void add(std::shared_ptr task, int64_t timeout = 0LL, int64_t expiration = 0LL) = 0; /** * Removes a pending task */ - virtual void remove(stdcxx::shared_ptr task) = 0; + virtual void remove(std::shared_ptr task) = 0; /** * Remove the next pending task which would be run. * * @return the task removed. */ - virtual stdcxx::shared_ptr removeNextPending() = 0; + virtual std::shared_ptr removeNextPending() = 0; /** * Remove tasks from front of task queue that have expired. @@ -190,14 +191,14 @@ class ThreadManager { */ virtual void setExpireCallback(ExpireCallback expireCallback) = 0; - static stdcxx::shared_ptr newThreadManager(); + static std::shared_ptr newThreadManager(); /** * Creates a simple thread manager the uses count number of worker threads and has * a pendingTaskCountMax maximum pending tasks. The default, 0, specified no limit * on pending tasks */ - static stdcxx::shared_ptr newSimpleThreadManager(size_t count = 4, + static std::shared_ptr newSimpleThreadManager(size_t count = 4, size_t pendingTaskCountMax = 0); class Task; diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.cpp b/lib/cpp/src/thrift/concurrency/TimerManager.cpp index 20171467e73..61a34ff694f 100644 --- a/lib/cpp/src/thrift/concurrency/TimerManager.cpp +++ b/lib/cpp/src/thrift/concurrency/TimerManager.cpp @@ -29,8 +29,8 @@ namespace apache { namespace thrift { namespace concurrency { -using stdcxx::shared_ptr; -using stdcxx::weak_ptr; +using std::shared_ptr; +using std::weak_ptr; /** * TimerManager class diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.h b/lib/cpp/src/thrift/concurrency/TimerManager.h index 2bfc6a755bc..ba792264c53 100644 --- a/lib/cpp/src/thrift/concurrency/TimerManager.h +++ b/lib/cpp/src/thrift/concurrency/TimerManager.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include @@ -43,15 +43,15 @@ class TimerManager { public: class Task; - typedef stdcxx::weak_ptr Timer; + typedef std::weak_ptr Timer; TimerManager(); virtual ~TimerManager(); - virtual stdcxx::shared_ptr threadFactory() const; + virtual std::shared_ptr threadFactory() const; - virtual void threadFactory(stdcxx::shared_ptr value); + virtual void threadFactory(std::shared_ptr value); /** * Starts the timer manager service @@ -74,7 +74,7 @@ class TimerManager { * @param timeout Time in milliseconds to delay before executing task * @return Handle of the timer, which can be used to remove the timer. */ - virtual Timer add(stdcxx::shared_ptr task, int64_t timeout); + virtual Timer add(std::shared_ptr task, int64_t timeout); /** * Adds a task to be executed at some time in the future by a worker thread. @@ -83,7 +83,7 @@ class TimerManager { * @param timeout Absolute time in the future to execute task. * @return Handle of the timer, which can be used to remove the timer. */ - virtual Timer add(stdcxx::shared_ptr task, const struct THRIFT_TIMESPEC& timeout); + virtual Timer add(std::shared_ptr task, const struct THRIFT_TIMESPEC& timeout); /** * Adds a task to be executed at some time in the future by a worker thread. @@ -92,7 +92,7 @@ class TimerManager { * @param timeout Absolute time in the future to execute task. * @return Handle of the timer, which can be used to remove the timer. */ - virtual Timer add(stdcxx::shared_ptr task, const struct timeval& timeout); + virtual Timer add(std::shared_ptr task, const struct timeval& timeout); /** * Removes a pending task @@ -106,7 +106,7 @@ class TimerManager { * @throws UncancellableTaskException Specified task is already being * executed or has completed execution. */ - virtual void remove(stdcxx::shared_ptr task); + virtual void remove(std::shared_ptr task); /** * Removes a single pending task @@ -127,17 +127,17 @@ class TimerManager { virtual STATE state() const; private: - stdcxx::shared_ptr threadFactory_; + std::shared_ptr threadFactory_; friend class Task; - std::multimap > taskMap_; + std::multimap > taskMap_; size_t taskCount_; Monitor monitor_; STATE state_; class Dispatcher; friend class Dispatcher; - stdcxx::shared_ptr dispatcher_; - stdcxx::shared_ptr dispatcherThread_; - typedef std::multimap >::iterator task_iterator; + std::shared_ptr dispatcher_; + std::shared_ptr dispatcherThread_; + typedef std::multimap >::iterator task_iterator; typedef std::pair task_range; }; } diff --git a/lib/cpp/src/thrift/processor/PeekProcessor.cpp b/lib/cpp/src/thrift/processor/PeekProcessor.cpp index fa11a721c6b..07f6ba58bfd 100644 --- a/lib/cpp/src/thrift/processor/PeekProcessor.cpp +++ b/lib/cpp/src/thrift/processor/PeekProcessor.cpp @@ -34,26 +34,26 @@ PeekProcessor::PeekProcessor() { PeekProcessor::~PeekProcessor() { } -void PeekProcessor::initialize(stdcxx::shared_ptr actualProcessor, - stdcxx::shared_ptr protocolFactory, - stdcxx::shared_ptr transportFactory) { +void PeekProcessor::initialize(std::shared_ptr actualProcessor, + std::shared_ptr protocolFactory, + std::shared_ptr transportFactory) { actualProcessor_ = actualProcessor; pipedProtocol_ = protocolFactory->getProtocol(targetTransport_); transportFactory_ = transportFactory; transportFactory_->initializeTargetTransport(targetTransport_); } -stdcxx::shared_ptr PeekProcessor::getPipedTransport(stdcxx::shared_ptr in) { +std::shared_ptr PeekProcessor::getPipedTransport(std::shared_ptr in) { return transportFactory_->getTransport(in); } -void PeekProcessor::setTargetTransport(stdcxx::shared_ptr targetTransport) { +void PeekProcessor::setTargetTransport(std::shared_ptr targetTransport) { targetTransport_ = targetTransport; - if (stdcxx::dynamic_pointer_cast(targetTransport_)) { - memoryBuffer_ = stdcxx::dynamic_pointer_cast(targetTransport); - } else if (stdcxx::dynamic_pointer_cast(targetTransport_)) { - memoryBuffer_ = stdcxx::dynamic_pointer_cast( - stdcxx::dynamic_pointer_cast(targetTransport_)->getTargetTransport()); + if (std::dynamic_pointer_cast(targetTransport_)) { + memoryBuffer_ = std::dynamic_pointer_cast(targetTransport); + } else if (std::dynamic_pointer_cast(targetTransport_)) { + memoryBuffer_ = std::dynamic_pointer_cast( + std::dynamic_pointer_cast(targetTransport_)->getTargetTransport()); } if (!memoryBuffer_) { @@ -62,8 +62,8 @@ void PeekProcessor::setTargetTransport(stdcxx::shared_ptr targetTran } } -bool PeekProcessor::process(stdcxx::shared_ptr in, - stdcxx::shared_ptr out, +bool PeekProcessor::process(std::shared_ptr in, + std::shared_ptr out, void* connectionContext) { std::string fname; @@ -120,7 +120,7 @@ void PeekProcessor::peekBuffer(uint8_t* buffer, uint32_t size) { (void)size; } -void PeekProcessor::peek(stdcxx::shared_ptr in, TType ftype, int16_t fid) { +void PeekProcessor::peek(std::shared_ptr in, TType ftype, int16_t fid) { (void)fid; in->skip(ftype); } diff --git a/lib/cpp/src/thrift/processor/PeekProcessor.h b/lib/cpp/src/thrift/processor/PeekProcessor.h index f5c10da682b..efac2b96130 100644 --- a/lib/cpp/src/thrift/processor/PeekProcessor.h +++ b/lib/cpp/src/thrift/processor/PeekProcessor.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include namespace apache { namespace thrift { @@ -47,34 +47,34 @@ class PeekProcessor : public apache::thrift::TProcessor { // transportFactory - this TPipedTransportFactory is used to wrap the source transport // via a call to getPipedTransport void initialize( - stdcxx::shared_ptr actualProcessor, - stdcxx::shared_ptr protocolFactory, - stdcxx::shared_ptr transportFactory); + std::shared_ptr actualProcessor, + std::shared_ptr protocolFactory, + std::shared_ptr transportFactory); - stdcxx::shared_ptr getPipedTransport( - stdcxx::shared_ptr in); + std::shared_ptr getPipedTransport( + std::shared_ptr in); - void setTargetTransport(stdcxx::shared_ptr targetTransport); + void setTargetTransport(std::shared_ptr targetTransport); - virtual bool process(stdcxx::shared_ptr in, - stdcxx::shared_ptr out, + virtual bool process(std::shared_ptr in, + std::shared_ptr out, void* connectionContext); // The following three functions can be overloaded by child classes to // achieve desired peeking behavior virtual void peekName(const std::string& fname); virtual void peekBuffer(uint8_t* buffer, uint32_t size); - virtual void peek(stdcxx::shared_ptr in, + virtual void peek(std::shared_ptr in, apache::thrift::protocol::TType ftype, int16_t fid); virtual void peekEnd(); private: - stdcxx::shared_ptr actualProcessor_; - stdcxx::shared_ptr pipedProtocol_; - stdcxx::shared_ptr transportFactory_; - stdcxx::shared_ptr memoryBuffer_; - stdcxx::shared_ptr targetTransport_; + std::shared_ptr actualProcessor_; + std::shared_ptr pipedProtocol_; + std::shared_ptr transportFactory_; + std::shared_ptr memoryBuffer_; + std::shared_ptr targetTransport_; }; } } diff --git a/lib/cpp/src/thrift/processor/StatsProcessor.h b/lib/cpp/src/thrift/processor/StatsProcessor.h index 8f6725f000c..e98efb82c81 100644 --- a/lib/cpp/src/thrift/processor/StatsProcessor.h +++ b/lib/cpp/src/thrift/processor/StatsProcessor.h @@ -20,7 +20,7 @@ #ifndef STATSPROCESSOR_H #define STATSPROCESSOR_H -#include +#include #include #include #include @@ -38,8 +38,8 @@ class StatsProcessor : public apache::thrift::TProcessor { StatsProcessor(bool print, bool frequency) : print_(print), frequency_(frequency) {} virtual ~StatsProcessor(){}; - virtual bool process(stdcxx::shared_ptr piprot, - stdcxx::shared_ptr poprot, + virtual bool process(std::shared_ptr piprot, + std::shared_ptr poprot, void* serverContext) { piprot_ = piprot; @@ -229,7 +229,7 @@ class StatsProcessor : public apache::thrift::TProcessor { } } - stdcxx::shared_ptr piprot_; + std::shared_ptr piprot_; std::map frequency_map_; bool print_; diff --git a/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h b/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h index aa3d49f8111..2aa7f751109 100644 --- a/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h +++ b/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h @@ -36,7 +36,7 @@ namespace protocol { */ class StoredMessageProtocol : public TProtocolDecorator { public: - StoredMessageProtocol(stdcxx::shared_ptr _protocol, + StoredMessageProtocol(std::shared_ptr _protocol, const std::string& _name, const TMessageType _type, const int32_t _seqid) @@ -65,19 +65,19 @@ class StoredMessageProtocol : public TProtocolDecorator { * processors with it, as shown in the following example:

* *
- * stdcxx::shared_ptr processor(new TMultiplexedProcessor()); + * std::shared_ptr processor(new TMultiplexedProcessor()); * * processor->registerProcessor( * "Calculator", - * stdcxx::shared_ptr( new CalculatorProcessor( - * stdcxx::shared_ptr( new CalculatorHandler())))); + * std::shared_ptr( new CalculatorProcessor( + * std::shared_ptr( new CalculatorHandler())))); * * processor->registerProcessor( * "WeatherReport", - * stdcxx::shared_ptr( new WeatherReportProcessor( - * stdcxx::shared_ptr( new WeatherReportHandler())))); + * std::shared_ptr( new WeatherReportProcessor( + * std::shared_ptr( new WeatherReportHandler())))); * - * stdcxx::shared_ptr transport(new TServerSocket(9090)); + * std::shared_ptr transport(new TServerSocket(9090)); * TSimpleServer server(processor, transport); * * server.serve(); @@ -85,7 +85,7 @@ class StoredMessageProtocol : public TProtocolDecorator { */ class TMultiplexedProcessor : public TProcessor { public: - typedef std::map > services_t; + typedef std::map > services_t; /** * 'Register' a service with this TMultiplexedProcessor. This @@ -98,7 +98,7 @@ class TMultiplexedProcessor : public TProcessor { * as "handlers", e.g. WeatherReportHandler, * implementing WeatherReportIf interface. */ - void registerProcessor(const std::string& serviceName, stdcxx::shared_ptr processor) { + void registerProcessor(const std::string& serviceName, std::shared_ptr processor) { services[serviceName] = processor; } @@ -106,15 +106,15 @@ class TMultiplexedProcessor : public TProcessor { * Register a service to be called to process queries without service name * \param [in] processor Implementation of a service. */ - void registerDefault(const stdcxx::shared_ptr& processor) { + void registerDefault(const std::shared_ptr& processor) { defaultProcessor = processor; } /** * Chew up invalid input and return an exception to throw. */ - TException protocol_error(stdcxx::shared_ptr in, - stdcxx::shared_ptr out, + TException protocol_error(std::shared_ptr in, + std::shared_ptr out, const std::string& name, int32_t seqid, const std::string& msg) const { @@ -147,8 +147,8 @@ class TMultiplexedProcessor : public TProcessor { * the service name was not found in the message, or if the service * name was not found in the service map. */ - bool process(stdcxx::shared_ptr in, - stdcxx::shared_ptr out, + bool process(std::shared_ptr in, + std::shared_ptr out, void* connectionContext) { std::string name; protocol::TMessageType type; @@ -177,11 +177,11 @@ class TMultiplexedProcessor : public TProcessor { services_t::iterator it = services.find(tokens[0]); if (it != services.end()) { - stdcxx::shared_ptr processor = it->second; + std::shared_ptr processor = it->second; // Let the processor registered for this service name // process the message. return processor - ->process(stdcxx::shared_ptr( + ->process(std::shared_ptr( new protocol::StoredMessageProtocol(in, tokens[1], type, seqid)), out, connectionContext); @@ -195,7 +195,7 @@ class TMultiplexedProcessor : public TProcessor { if (defaultProcessor) { // non-multiplexed client forwards to default processor return defaultProcessor - ->process(stdcxx::shared_ptr( + ->process(std::shared_ptr( new protocol::StoredMessageProtocol(in, tokens[0], type, seqid)), out, connectionContext); @@ -216,7 +216,7 @@ class TMultiplexedProcessor : public TProcessor { //! If a non-multi client requests something, it goes to the //! default processor (if one is defined) for backwards compatibility. - stdcxx::shared_ptr defaultProcessor; + std::shared_ptr defaultProcessor; }; } } diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h index f28d27872b9..906775831b4 100644 --- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h +++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h @@ -23,7 +23,7 @@ #include #include -#include +#include namespace apache { namespace thrift { @@ -41,7 +41,7 @@ class TBinaryProtocolT : public TVirtualProtocol trans) + TBinaryProtocolT(std::shared_ptr trans) : TVirtualProtocol >(trans), trans_(trans.get()), string_limit_(0), @@ -49,7 +49,7 @@ class TBinaryProtocolT : public TVirtualProtocol trans, + TBinaryProtocolT(std::shared_ptr trans, int32_t string_limit, int32_t container_limit, bool strict_read, @@ -212,8 +212,8 @@ class TBinaryProtocolFactoryT : public TProtocolFactory { strict_write_ = strict_write; } - stdcxx::shared_ptr getProtocol(stdcxx::shared_ptr trans) { - stdcxx::shared_ptr specific_trans = stdcxx::dynamic_pointer_cast(trans); + std::shared_ptr getProtocol(std::shared_ptr trans) { + std::shared_ptr specific_trans = std::dynamic_pointer_cast(trans); TProtocol* prot; if (specific_trans) { prot = new TBinaryProtocolT(specific_trans, @@ -229,7 +229,7 @@ class TBinaryProtocolFactoryT : public TProtocolFactory { strict_write_); } - return stdcxx::shared_ptr(prot); + return std::shared_ptr(prot); } private: diff --git a/lib/cpp/src/thrift/protocol/TCompactProtocol.h b/lib/cpp/src/thrift/protocol/TCompactProtocol.h index e6024a9d309..5cfb47d2058 100644 --- a/lib/cpp/src/thrift/protocol/TCompactProtocol.h +++ b/lib/cpp/src/thrift/protocol/TCompactProtocol.h @@ -23,7 +23,7 @@ #include #include -#include +#include namespace apache { namespace thrift { @@ -74,7 +74,7 @@ class TCompactProtocolT : public TVirtualProtocol int16_t lastFieldId_; public: - TCompactProtocolT(stdcxx::shared_ptr trans) + TCompactProtocolT(std::shared_ptr trans) : TVirtualProtocol >(trans), trans_(trans.get()), lastFieldId_(0), @@ -86,7 +86,7 @@ class TCompactProtocolT : public TVirtualProtocol boolValue_.hasBoolValue = false; } - TCompactProtocolT(stdcxx::shared_ptr trans, + TCompactProtocolT(std::shared_ptr trans, int32_t string_limit, int32_t container_limit) : TVirtualProtocol >(trans), @@ -239,8 +239,8 @@ class TCompactProtocolFactoryT : public TProtocolFactory { void setContainerSizeLimit(int32_t container_limit) { container_limit_ = container_limit; } - stdcxx::shared_ptr getProtocol(stdcxx::shared_ptr trans) { - stdcxx::shared_ptr specific_trans = stdcxx::dynamic_pointer_cast(trans); + std::shared_ptr getProtocol(std::shared_ptr trans) { + std::shared_ptr specific_trans = std::dynamic_pointer_cast(trans); TProtocol* prot; if (specific_trans) { prot = new TCompactProtocolT(specific_trans, string_limit_, container_limit_); @@ -248,7 +248,7 @@ class TCompactProtocolFactoryT : public TProtocolFactory { prot = new TCompactProtocol(trans, string_limit_, container_limit_); } - return stdcxx::shared_ptr(prot); + return std::shared_ptr(prot); } private: diff --git a/lib/cpp/src/thrift/protocol/TDebugProtocol.h b/lib/cpp/src/thrift/protocol/TDebugProtocol.h index 301d05aa4c1..c07962475a2 100644 --- a/lib/cpp/src/thrift/protocol/TDebugProtocol.h +++ b/lib/cpp/src/thrift/protocol/TDebugProtocol.h @@ -22,7 +22,7 @@ #include -#include +#include namespace apache { namespace thrift { @@ -51,7 +51,7 @@ class TDebugProtocol : public TVirtualProtocol { enum write_state_t { UNINIT, STRUCT, LIST, SET, MAP_KEY, MAP_VALUE }; public: - TDebugProtocol(stdcxx::shared_ptr trans) + TDebugProtocol(std::shared_ptr trans) : TVirtualProtocol(trans), trans_(trans.get()), string_limit_(DEFAULT_STRING_LIMIT), @@ -141,8 +141,8 @@ class TDebugProtocolFactory : public TProtocolFactory { TDebugProtocolFactory() {} virtual ~TDebugProtocolFactory() {} - stdcxx::shared_ptr getProtocol(stdcxx::shared_ptr trans) { - return stdcxx::shared_ptr(new TDebugProtocol(trans)); + std::shared_ptr getProtocol(std::shared_ptr trans) { + return std::shared_ptr(new TDebugProtocol(trans)); } }; } @@ -160,7 +160,7 @@ std::string ThriftDebugString(const ThriftStruct& ts) { using namespace apache::thrift::transport; using namespace apache::thrift::protocol; TMemoryBuffer* buffer = new TMemoryBuffer; - stdcxx::shared_ptr trans(buffer); + std::shared_ptr trans(buffer); TDebugProtocol protocol(trans); ts.write(&protocol); @@ -178,7 +178,7 @@ std::string DebugString(const std::vector& vec) { using namespace apache::thrift::transport; using namespace apache::thrift::protocol; TMemoryBuffer* buffer = new TMemoryBuffer; - stdcxx::shared_ptr trans(buffer); + std::shared_ptr trans(buffer); TDebugProtocol protocol(trans); // I am gross! diff --git a/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp b/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp index 26676172f35..a19d545059a 100644 --- a/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp @@ -27,7 +27,7 @@ #include #include -#include +#include namespace apache { namespace thrift { @@ -42,11 +42,11 @@ void THeaderProtocol::resetProtocol() { switch (protoId_) { case T_BINARY_PROTOCOL: - proto_ = stdcxx::make_shared >(trans_); + proto_ = std::make_shared >(trans_); break; case T_COMPACT_PROTOCOL: - proto_ = stdcxx::make_shared >(trans_); + proto_ = std::make_shared >(trans_); break; default: diff --git a/lib/cpp/src/thrift/protocol/THeaderProtocol.h b/lib/cpp/src/thrift/protocol/THeaderProtocol.h index 8cd501736e3..e5e2b657420 100644 --- a/lib/cpp/src/thrift/protocol/THeaderProtocol.h +++ b/lib/cpp/src/thrift/protocol/THeaderProtocol.h @@ -25,7 +25,7 @@ #include #include -#include +#include using apache::thrift::transport::THeaderTransport; @@ -43,21 +43,21 @@ class THeaderProtocol : public TVirtualProtocol { public: void resetProtocol(); - explicit THeaderProtocol(const stdcxx::shared_ptr& trans, + explicit THeaderProtocol(const std::shared_ptr& trans, uint16_t protoId = T_COMPACT_PROTOCOL) - : TVirtualProtocol(stdcxx::shared_ptr(new THeaderTransport(trans))), - trans_(stdcxx::dynamic_pointer_cast(getTransport())), + : TVirtualProtocol(std::shared_ptr(new THeaderTransport(trans))), + trans_(std::dynamic_pointer_cast(getTransport())), protoId_(protoId) { trans_->setProtocolId(protoId); resetProtocol(); } - THeaderProtocol(const stdcxx::shared_ptr& inTrans, - const stdcxx::shared_ptr& outTrans, + THeaderProtocol(const std::shared_ptr& inTrans, + const std::shared_ptr& outTrans, uint16_t protoId = T_COMPACT_PROTOCOL) : TVirtualProtocol( - stdcxx::shared_ptr(new THeaderTransport(inTrans, outTrans))), - trans_(stdcxx::dynamic_pointer_cast(getTransport())), + std::shared_ptr(new THeaderTransport(inTrans, outTrans))), + trans_(std::dynamic_pointer_cast(getTransport())), protoId_(protoId) { trans_->setProtocolId(protoId); resetProtocol(); @@ -182,25 +182,25 @@ class THeaderProtocol : public TVirtualProtocol { uint32_t readBinary(std::string& binary); protected: - stdcxx::shared_ptr trans_; + std::shared_ptr trans_; - stdcxx::shared_ptr proto_; + std::shared_ptr proto_; uint32_t protoId_; }; class THeaderProtocolFactory : public TProtocolFactory { public: - virtual stdcxx::shared_ptr getProtocol(stdcxx::shared_ptr trans) { + virtual std::shared_ptr getProtocol(std::shared_ptr trans) { THeaderProtocol* headerProtocol = new THeaderProtocol(trans, trans, T_BINARY_PROTOCOL); - return stdcxx::shared_ptr(headerProtocol); + return std::shared_ptr(headerProtocol); } - virtual stdcxx::shared_ptr getProtocol( - stdcxx::shared_ptr inTrans, - stdcxx::shared_ptr outTrans) { + virtual std::shared_ptr getProtocol( + std::shared_ptr inTrans, + std::shared_ptr outTrans) { THeaderProtocol* headerProtocol = new THeaderProtocol(inTrans, outTrans, T_BINARY_PROTOCOL); - return stdcxx::shared_ptr(headerProtocol); + return std::shared_ptr(headerProtocol); } }; } diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp index 80def7ff704..40eb7ad9ae0 100644 --- a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp @@ -398,7 +398,7 @@ class JSONListContext : public TJSONContext { bool first_; }; -TJSONProtocol::TJSONProtocol(stdcxx::shared_ptr ptrans) +TJSONProtocol::TJSONProtocol(std::shared_ptr ptrans) : TVirtualProtocol(ptrans), trans_(ptrans.get()), context_(new TJSONContext()), @@ -408,7 +408,7 @@ TJSONProtocol::TJSONProtocol(stdcxx::shared_ptr ptrans) TJSONProtocol::~TJSONProtocol() { } -void TJSONProtocol::pushContext(stdcxx::shared_ptr c) { +void TJSONProtocol::pushContext(std::shared_ptr c) { contexts_.push(context_); context_ = c; } @@ -576,7 +576,7 @@ uint32_t TJSONProtocol::writeJSONDouble(double num) { uint32_t TJSONProtocol::writeJSONObjectStart() { uint32_t result = context_->write(*trans_); trans_->write(&kJSONObjectStart, 1); - pushContext(stdcxx::shared_ptr(new JSONPairContext())); + pushContext(std::shared_ptr(new JSONPairContext())); return result + 1; } @@ -589,7 +589,7 @@ uint32_t TJSONProtocol::writeJSONObjectEnd() { uint32_t TJSONProtocol::writeJSONArrayStart() { uint32_t result = context_->write(*trans_); trans_->write(&kJSONArrayStart, 1); - pushContext(stdcxx::shared_ptr(new JSONListContext())); + pushContext(std::shared_ptr(new JSONListContext())); return result + 1; } @@ -923,7 +923,7 @@ uint32_t TJSONProtocol::readJSONDouble(double& num) { uint32_t TJSONProtocol::readJSONObjectStart() { uint32_t result = context_->read(reader_); result += readJSONSyntaxChar(kJSONObjectStart); - pushContext(stdcxx::shared_ptr(new JSONPairContext())); + pushContext(std::shared_ptr(new JSONPairContext())); return result; } @@ -936,7 +936,7 @@ uint32_t TJSONProtocol::readJSONObjectEnd() { uint32_t TJSONProtocol::readJSONArrayStart() { uint32_t result = context_->read(reader_); result += readJSONSyntaxChar(kJSONArrayStart); - pushContext(stdcxx::shared_ptr(new JSONListContext())); + pushContext(std::shared_ptr(new JSONListContext())); return result; } diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.h b/lib/cpp/src/thrift/protocol/TJSONProtocol.h index 16dff561c4e..9c2f8726978 100644 --- a/lib/cpp/src/thrift/protocol/TJSONProtocol.h +++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.h @@ -96,12 +96,12 @@ class TJSONContext; */ class TJSONProtocol : public TVirtualProtocol { public: - TJSONProtocol(stdcxx::shared_ptr ptrans); + TJSONProtocol(std::shared_ptr ptrans); ~TJSONProtocol(); private: - void pushContext(stdcxx::shared_ptr c); + void pushContext(std::shared_ptr c); void popContext(); @@ -276,8 +276,8 @@ class TJSONProtocol : public TVirtualProtocol { private: TTransport* trans_; - std::stack > contexts_; - stdcxx::shared_ptr context_; + std::stack > contexts_; + std::shared_ptr context_; LookaheadReader reader_; }; @@ -290,8 +290,8 @@ class TJSONProtocolFactory : public TProtocolFactory { virtual ~TJSONProtocolFactory() {} - stdcxx::shared_ptr getProtocol(stdcxx::shared_ptr trans) { - return stdcxx::shared_ptr(new TJSONProtocol(trans)); + std::shared_ptr getProtocol(std::shared_ptr trans) { + return std::shared_ptr(new TJSONProtocol(trans)); } }; } @@ -309,7 +309,7 @@ std::string ThriftJSONString(const ThriftStruct& ts) { using namespace apache::thrift::transport; using namespace apache::thrift::protocol; TMemoryBuffer* buffer = new TMemoryBuffer; - stdcxx::shared_ptr trans(buffer); + std::shared_ptr trans(buffer); TJSONProtocol protocol(trans); ts.write(&protocol); diff --git a/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h b/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h index dd7e88ffc80..94bd82eaed2 100644 --- a/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h +++ b/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h @@ -25,7 +25,7 @@ namespace apache { namespace thrift { namespace protocol { -using stdcxx::shared_ptr; +using std::shared_ptr; /** * TMultiplexedProtocol is a protocol-independent concrete decorator diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h index aa5beea92e9..28e1bb734b5 100644 --- a/lib/cpp/src/thrift/protocol/TProtocol.h +++ b/lib/cpp/src/thrift/protocol/TProtocol.h @@ -28,7 +28,7 @@ #include #include -#include +#include #include #ifdef HAVE_NETINET_IN_H @@ -550,12 +550,12 @@ class TProtocol { } virtual uint32_t skip_virt(TType type); - inline stdcxx::shared_ptr getTransport() { return ptrans_; } + inline std::shared_ptr getTransport() { return ptrans_; } // TODO: remove these two calls, they are for backwards // compatibility - inline stdcxx::shared_ptr getInputTransport() { return ptrans_; } - inline stdcxx::shared_ptr getOutputTransport() { return ptrans_; } + inline std::shared_ptr getInputTransport() { return ptrans_; } + inline std::shared_ptr getOutputTransport() { return ptrans_; } // input and output recursion depth are kept separate so that one protocol // can be used concurrently for both input and output. @@ -577,11 +577,11 @@ class TProtocol { void setRecurisionLimit(uint32_t depth) {recursion_limit_ = depth;} protected: - TProtocol(stdcxx::shared_ptr ptrans) + TProtocol(std::shared_ptr ptrans) : ptrans_(ptrans), input_recursion_depth_(0), output_recursion_depth_(0), recursion_limit_(DEFAULT_RECURSION_LIMIT) {} - stdcxx::shared_ptr ptrans_; + std::shared_ptr ptrans_; private: TProtocol() {} @@ -599,9 +599,9 @@ class TProtocolFactory { virtual ~TProtocolFactory(); - virtual stdcxx::shared_ptr getProtocol(stdcxx::shared_ptr trans) = 0; - virtual stdcxx::shared_ptr getProtocol(stdcxx::shared_ptr inTrans, - stdcxx::shared_ptr outTrans) { + virtual std::shared_ptr getProtocol(std::shared_ptr trans) = 0; + virtual std::shared_ptr getProtocol(std::shared_ptr inTrans, + std::shared_ptr outTrans) { (void)outTrans; return getProtocol(inTrans); } diff --git a/lib/cpp/src/thrift/protocol/TProtocolDecorator.h b/lib/cpp/src/thrift/protocol/TProtocolDecorator.h index a353b796886..743a0f472d0 100644 --- a/lib/cpp/src/thrift/protocol/TProtocolDecorator.h +++ b/lib/cpp/src/thrift/protocol/TProtocolDecorator.h @@ -21,12 +21,12 @@ #define THRIFT_TPROTOCOLDECORATOR_H_ 1 #include -#include +#include namespace apache { namespace thrift { namespace protocol { -using stdcxx::shared_ptr; +using std::shared_ptr; /** * TProtocolDecorator forwards all requests to an enclosed diff --git a/lib/cpp/src/thrift/protocol/TProtocolTap.h b/lib/cpp/src/thrift/protocol/TProtocolTap.h index 176d4fdc041..d000ba61a3b 100644 --- a/lib/cpp/src/thrift/protocol/TProtocolTap.h +++ b/lib/cpp/src/thrift/protocol/TProtocolTap.h @@ -36,7 +36,7 @@ using apache::thrift::transport::TTransport; */ class TProtocolTap : public TVirtualProtocol { public: - TProtocolTap(stdcxx::shared_ptr source, stdcxx::shared_ptr sink) + TProtocolTap(std::shared_ptr source, std::shared_ptr sink) : TVirtualProtocol(source->getTransport()), source_(source), sink_(sink) {} uint32_t readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) { @@ -167,8 +167,8 @@ class TProtocolTap : public TVirtualProtocol { } private: - stdcxx::shared_ptr source_; - stdcxx::shared_ptr sink_; + std::shared_ptr source_; + std::shared_ptr sink_; }; } } diff --git a/lib/cpp/src/thrift/protocol/TVirtualProtocol.h b/lib/cpp/src/thrift/protocol/TVirtualProtocol.h index 628b494a485..4eea5791614 100644 --- a/lib/cpp/src/thrift/protocol/TVirtualProtocol.h +++ b/lib/cpp/src/thrift/protocol/TVirtualProtocol.h @@ -301,7 +301,7 @@ class TProtocolDefaults : public TProtocol { uint32_t skip(TType type) { return ::apache::thrift::protocol::skip(*this, type); } protected: - TProtocolDefaults(stdcxx::shared_ptr ptrans) : TProtocol(ptrans) {} + TProtocolDefaults(std::shared_ptr ptrans) : TProtocol(ptrans) {} }; /** @@ -504,7 +504,7 @@ class TVirtualProtocol : public Super_ { using Super_::readBool; // so we don't hide readBool(bool&) protected: - TVirtualProtocol(stdcxx::shared_ptr ptrans) : Super_(ptrans) {} + TVirtualProtocol(std::shared_ptr ptrans) : Super_(ptrans) {} }; } } diff --git a/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp b/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp index 0e46f11fa53..f77c993f4dc 100644 --- a/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp +++ b/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp @@ -23,12 +23,12 @@ #include #include -#include +#include namespace apache { namespace thrift { -using stdcxx::shared_ptr; +using std::shared_ptr; namespace transport { diff --git a/lib/cpp/src/thrift/qt/TQIODeviceTransport.h b/lib/cpp/src/thrift/qt/TQIODeviceTransport.h index 9087f2c41c5..91ce8d5f680 100644 --- a/lib/cpp/src/thrift/qt/TQIODeviceTransport.h +++ b/lib/cpp/src/thrift/qt/TQIODeviceTransport.h @@ -20,7 +20,7 @@ #ifndef _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_ #define _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_ 1 -#include +#include #include @@ -36,7 +36,7 @@ namespace transport { class TQIODeviceTransport : public apache::thrift::transport::TVirtualTransport { public: - explicit TQIODeviceTransport(stdcxx::shared_ptr dev); + explicit TQIODeviceTransport(std::shared_ptr dev); virtual ~TQIODeviceTransport(); void open(); @@ -59,7 +59,7 @@ class TQIODeviceTransport TQIODeviceTransport(const TQIODeviceTransport&); TQIODeviceTransport& operator=(const TQIODeviceTransport&); - stdcxx::shared_ptr dev_; + std::shared_ptr dev_; }; } } diff --git a/lib/cpp/src/thrift/qt/TQTcpServer.cpp b/lib/cpp/src/thrift/qt/TQTcpServer.cpp index c4669d78265..99aad071a2c 100644 --- a/lib/cpp/src/thrift/qt/TQTcpServer.cpp +++ b/lib/cpp/src/thrift/qt/TQTcpServer.cpp @@ -17,14 +17,15 @@ * under the License. */ +#include +#include + #include #include #include #include -#include - #include #include @@ -33,10 +34,10 @@ using apache::thrift::protocol::TProtocolFactory; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TQIODeviceTransport; -using apache::thrift::stdcxx::bind; -using apache::thrift::stdcxx::function; -using apache::thrift::stdcxx::placeholders::_1; -using apache::thrift::stdcxx::shared_ptr; +using std::bind; +using std::function; +using std::placeholders::_1; +using std::shared_ptr; QT_USE_NAMESPACE diff --git a/lib/cpp/src/thrift/qt/TQTcpServer.h b/lib/cpp/src/thrift/qt/TQTcpServer.h index 0d32afa0a77..8e3fe3a83d2 100644 --- a/lib/cpp/src/thrift/qt/TQTcpServer.h +++ b/lib/cpp/src/thrift/qt/TQTcpServer.h @@ -23,7 +23,7 @@ #include #include -#include +#include namespace apache { namespace thrift { @@ -47,9 +47,9 @@ class TAsyncProcessor; class TQTcpServer : public QObject { Q_OBJECT public: - TQTcpServer(stdcxx::shared_ptr server, - stdcxx::shared_ptr processor, - stdcxx::shared_ptr protocolFactory, + TQTcpServer(std::shared_ptr server, + std::shared_ptr processor, + std::shared_ptr protocolFactory, QObject* parent = NULL); virtual ~TQTcpServer(); @@ -65,13 +65,13 @@ private Q_SLOTS: struct ConnectionContext; void scheduleDeleteConnectionContext(QTcpSocket* connection); - void finish(stdcxx::shared_ptr ctx, bool healthy); + void finish(std::shared_ptr ctx, bool healthy); - stdcxx::shared_ptr server_; - stdcxx::shared_ptr processor_; - stdcxx::shared_ptr pfact_; + std::shared_ptr server_; + std::shared_ptr processor_; + std::shared_ptr pfact_; - typedef std::map > ConnectionContextMap; + typedef std::map > ConnectionContextMap; ConnectionContextMap ctxMap_; }; } diff --git a/lib/cpp/src/thrift/server/TConnectedClient.cpp b/lib/cpp/src/thrift/server/TConnectedClient.cpp index 33ec3a980ee..acdaa77cb71 100644 --- a/lib/cpp/src/thrift/server/TConnectedClient.cpp +++ b/lib/cpp/src/thrift/server/TConnectedClient.cpp @@ -28,7 +28,7 @@ using apache::thrift::protocol::TProtocol; using apache::thrift::server::TServerEventHandler; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; -using stdcxx::shared_ptr; +using std::shared_ptr; using std::string; TConnectedClient::TConnectedClient(const shared_ptr& processor, diff --git a/lib/cpp/src/thrift/server/TConnectedClient.h b/lib/cpp/src/thrift/server/TConnectedClient.h index 2f9d4c9de94..19e70c1801d 100644 --- a/lib/cpp/src/thrift/server/TConnectedClient.h +++ b/lib/cpp/src/thrift/server/TConnectedClient.h @@ -20,7 +20,7 @@ #ifndef _THRIFT_SERVER_TCONNECTEDCLIENT_H_ #define _THRIFT_SERVER_TCONNECTEDCLIENT_H_ 1 -#include +#include #include #include #include @@ -49,11 +49,11 @@ class TConnectedClient : public apache::thrift::concurrency::Runnable { * @param[in] client the TTransport representing the client */ TConnectedClient( - const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& inputProtocol, - const stdcxx::shared_ptr& outputProtocol, - const stdcxx::shared_ptr& eventHandler, - const stdcxx::shared_ptr& client); + const std::shared_ptr& processor, + const std::shared_ptr& inputProtocol, + const std::shared_ptr& outputProtocol, + const std::shared_ptr& eventHandler, + const std::shared_ptr& client); /** * Destructor. @@ -92,11 +92,11 @@ class TConnectedClient : public apache::thrift::concurrency::Runnable { virtual void cleanup(); private: - stdcxx::shared_ptr processor_; - stdcxx::shared_ptr inputProtocol_; - stdcxx::shared_ptr outputProtocol_; - stdcxx::shared_ptr eventHandler_; - stdcxx::shared_ptr client_; + std::shared_ptr processor_; + std::shared_ptr inputProtocol_; + std::shared_ptr outputProtocol_; + std::shared_ptr eventHandler_; + std::shared_ptr client_; /** * Context acquired from the eventHandler_ if one exists. diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.cpp b/lib/cpp/src/thrift/server/TNonblockingServer.cpp index 1031ec0074f..f16fce78986 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.cpp +++ b/lib/cpp/src/thrift/server/TNonblockingServer.cpp @@ -84,7 +84,7 @@ using namespace apache::thrift::transport; using namespace apache::thrift::concurrency; using apache::thrift::transport::TSocket; using apache::thrift::transport::TTransportException; -using stdcxx::shared_ptr; +using std::shared_ptr; /// Three states for sockets: recv frame size, recv data, and send mode enum TSocketState { SOCKET_RECV_FRAMING, SOCKET_RECV, SOCKET_SEND }; @@ -119,10 +119,10 @@ class TNonblockingServer::TConnection { TNonblockingServer* server_; /// TProcessor - stdcxx::shared_ptr processor_; + std::shared_ptr processor_; /// Object wrapping network socket - stdcxx::shared_ptr tSocket_; + std::shared_ptr tSocket_; /// Libevent object struct event event_; @@ -164,23 +164,23 @@ class TNonblockingServer::TConnection { int32_t callsForResize_; /// Transport to read from - stdcxx::shared_ptr inputTransport_; + std::shared_ptr inputTransport_; /// Transport that processor writes to - stdcxx::shared_ptr outputTransport_; + std::shared_ptr outputTransport_; /// extra transport generated by transport factory (e.g. BufferedRouterTransport) - stdcxx::shared_ptr factoryInputTransport_; - stdcxx::shared_ptr factoryOutputTransport_; + std::shared_ptr factoryInputTransport_; + std::shared_ptr factoryOutputTransport_; /// Protocol decoder - stdcxx::shared_ptr inputProtocol_; + std::shared_ptr inputProtocol_; /// Protocol encoder - stdcxx::shared_ptr outputProtocol_; + std::shared_ptr outputProtocol_; /// Server event handler, if any - stdcxx::shared_ptr serverEventHandler_; + std::shared_ptr serverEventHandler_; /// Thrift call context, if any void* connectionContext_; @@ -213,7 +213,7 @@ class TNonblockingServer::TConnection { class Task; /// Constructor - TConnection(stdcxx::shared_ptr socket, + TConnection(std::shared_ptr socket, TNonblockingIOThread* ioThread) { readBuffer_ = NULL; readBufferSize_ = 0; @@ -249,7 +249,7 @@ class TNonblockingServer::TConnection { void init(TNonblockingIOThread* ioThread); /// set socket for connection - void setSocket(stdcxx::shared_ptr socket); + void setSocket(std::shared_ptr socket); /** * This is called when the application transitions from one state into @@ -305,10 +305,10 @@ class TNonblockingServer::TConnection { TAppState getState() const { return appState_; } /// return the TSocket transport wrapping this network connection - stdcxx::shared_ptr getTSocket() const { return tSocket_; } + std::shared_ptr getTSocket() const { return tSocket_; } /// return the server event handler if any - stdcxx::shared_ptr getServerEventHandler() { return serverEventHandler_; } + std::shared_ptr getServerEventHandler() { return serverEventHandler_; } /// return the Thrift connection context if any void* getConnectionContext() { return connectionContext_; } @@ -316,9 +316,9 @@ class TNonblockingServer::TConnection { class TNonblockingServer::TConnection::Task : public Runnable { public: - Task(stdcxx::shared_ptr processor, - stdcxx::shared_ptr input, - stdcxx::shared_ptr output, + Task(std::shared_ptr processor, + std::shared_ptr input, + std::shared_ptr output, TConnection* connection) : processor_(processor), input_(input), @@ -363,11 +363,11 @@ class TNonblockingServer::TConnection::Task : public Runnable { TConnection* getTConnection() { return connection_; } private: - stdcxx::shared_ptr processor_; - stdcxx::shared_ptr input_; - stdcxx::shared_ptr output_; + std::shared_ptr processor_; + std::shared_ptr input_; + std::shared_ptr output_; TConnection* connection_; - stdcxx::shared_ptr serverEventHandler_; + std::shared_ptr serverEventHandler_; void* connectionContext_; }; @@ -414,7 +414,7 @@ void TNonblockingServer::TConnection::init(TNonblockingIOThread* ioThread) { processor_ = server_->getProcessor(inputProtocol_, outputProtocol_, tSocket_); } -void TNonblockingServer::TConnection::setSocket(stdcxx::shared_ptr socket) { +void TNonblockingServer::TConnection::setSocket(std::shared_ptr socket) { tSocket_ = socket; } @@ -610,7 +610,7 @@ void TNonblockingServer::TConnection::transition() { // We are setting up a Task to do this work and we will wait on it // Create task and dispatch to the thread manager - stdcxx::shared_ptr task = stdcxx::shared_ptr( + std::shared_ptr task = std::shared_ptr( new Task(processor_, inputProtocol_, outputProtocol_, this)); // The application is now waiting on the task to finish appState_ = APP_WAIT_TASK; @@ -888,9 +888,9 @@ TNonblockingServer::~TNonblockingServer() { // objects and the Thread objects have shared_ptrs to the TNonblockingIOThread // objects (as runnable) so these objects will never deallocate without help. while (!ioThreads_.empty()) { - stdcxx::shared_ptr iot = ioThreads_.back(); + std::shared_ptr iot = ioThreads_.back(); ioThreads_.pop_back(); - iot->setThread(stdcxx::shared_ptr()); + iot->setThread(std::shared_ptr()); } } @@ -898,7 +898,7 @@ TNonblockingServer::~TNonblockingServer() { * Creates a new connection either by reusing an object off the stack or * by allocating a new one entirely */ -TNonblockingServer::TConnection* TNonblockingServer::createConnection(stdcxx::shared_ptr socket) { +TNonblockingServer::TConnection* TNonblockingServer::createConnection(std::shared_ptr socket) { // Check the stack Guard g(connMutex_); @@ -954,7 +954,7 @@ void TNonblockingServer::handleEvent(THRIFT_SOCKET fd, short which) { assert(fd == serverSocket_); // Going to accept a new client socket - stdcxx::shared_ptr clientSocket; + std::shared_ptr clientSocket; clientSocket = serverTransport_->accept(); if (clientSocket) { @@ -1017,13 +1017,13 @@ void TNonblockingServer::createAndListenOnSocket() { } -void TNonblockingServer::setThreadManager(stdcxx::shared_ptr threadManager) { +void TNonblockingServer::setThreadManager(std::shared_ptr threadManager) { threadManager_ = threadManager; if (threadManager) { threadManager->setExpireCallback( - apache::thrift::stdcxx::bind(&TNonblockingServer::expireClose, + std::bind(&TNonblockingServer::expireClose, this, - apache::thrift::stdcxx::placeholders::_1)); + std::placeholders::_1)); threadPoolProcessing_ = true; } else { threadPoolProcessing_ = false; @@ -1055,7 +1055,7 @@ bool TNonblockingServer::serverOverloaded() { bool TNonblockingServer::drainPendingTask() { if (threadManager_) { - stdcxx::shared_ptr task = threadManager_->removeNextPending(); + std::shared_ptr task = threadManager_->removeNextPending(); if (task) { TConnection* connection = static_cast(task.get())->getTConnection(); assert(connection && connection->getServer() && connection->getState() == APP_WAIT_TASK); @@ -1066,7 +1066,7 @@ bool TNonblockingServer::drainPendingTask() { return false; } -void TNonblockingServer::expireClose(stdcxx::shared_ptr task) { +void TNonblockingServer::expireClose(std::shared_ptr task) { TConnection* connection = static_cast(task.get())->getTConnection(); assert(connection && connection->getServer() && connection->getState() == APP_WAIT_TASK); connection->forceClose(); diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.h b/lib/cpp/src/thrift/server/TNonblockingServer.h index f95a7290115..e79c24f6236 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.h +++ b/lib/cpp/src/thrift/server/TNonblockingServer.h @@ -21,7 +21,7 @@ #define _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ 1 #include -#include +#include #include #include #include @@ -160,16 +160,16 @@ class TNonblockingServer : public TServer { event_base* userEventBase_; /// For processing via thread pool, may be NULL - stdcxx::shared_ptr threadManager_; + std::shared_ptr threadManager_; /// Is thread pool processing? bool threadPoolProcessing_; // Factory to create the IO threads - stdcxx::shared_ptr ioThreadFactory_; + std::shared_ptr ioThreadFactory_; // Vector of IOThread objects that will handle our IO - std::vector > ioThreads_; + std::vector > ioThreads_; // Index of next IO Thread to be used (for round-robin) uint32_t nextIOThread_; @@ -264,7 +264,7 @@ class TNonblockingServer : public TServer { /* */ - stdcxx::shared_ptr serverTransport_; + std::shared_ptr serverTransport_; /** * Called when server socket had something happen. We accept all waiting @@ -301,24 +301,24 @@ class TNonblockingServer : public TServer { } public: - TNonblockingServer(const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport) + TNonblockingServer(const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport) : TServer(processorFactory), serverTransport_(serverTransport) { init(); } - TNonblockingServer(const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport) + TNonblockingServer(const std::shared_ptr& processor, + const std::shared_ptr& serverTransport) : TServer(processor), serverTransport_(serverTransport) { init(); } - TNonblockingServer(const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& protocolFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& threadManager - = stdcxx::shared_ptr()) + TNonblockingServer(const std::shared_ptr& processorFactory, + const std::shared_ptr& protocolFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& threadManager + = std::shared_ptr()) : TServer(processorFactory), serverTransport_(serverTransport) { init(); @@ -327,11 +327,11 @@ class TNonblockingServer : public TServer { setThreadManager(threadManager); } - TNonblockingServer(const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& protocolFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& threadManager - = stdcxx::shared_ptr()) + TNonblockingServer(const std::shared_ptr& processor, + const std::shared_ptr& protocolFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& threadManager + = std::shared_ptr()) : TServer(processor), serverTransport_(serverTransport) { init(); @@ -340,14 +340,14 @@ class TNonblockingServer : public TServer { setThreadManager(threadManager); } - TNonblockingServer(const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& threadManager - = stdcxx::shared_ptr()) + TNonblockingServer(const std::shared_ptr& processorFactory, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& threadManager + = std::shared_ptr()) : TServer(processorFactory), serverTransport_(serverTransport) { init(); @@ -358,14 +358,14 @@ class TNonblockingServer : public TServer { setThreadManager(threadManager); } - TNonblockingServer(const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& threadManager - = stdcxx::shared_ptr()) + TNonblockingServer(const std::shared_ptr& processor, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& threadManager + = std::shared_ptr()) : TServer(processor), serverTransport_(serverTransport) { init(); @@ -378,11 +378,11 @@ class TNonblockingServer : public TServer { ~TNonblockingServer(); - void setThreadManager(stdcxx::shared_ptr threadManager); + void setThreadManager(std::shared_ptr threadManager); int getListenPort() { return serverTransport_->getListenPort(); } - stdcxx::shared_ptr getThreadManager() { return threadManager_; } + std::shared_ptr getThreadManager() { return threadManager_; } /** * Sets the number of IO threads used by this server. Can only be used before @@ -421,7 +421,7 @@ class TNonblockingServer : public TServer { bool isThreadPoolProcessing() const { return threadPoolProcessing_; } - void addTask(stdcxx::shared_ptr task) { + void addTask(std::shared_ptr task) { threadManager_->add(task, 0LL, taskExpireTime_); } @@ -709,7 +709,7 @@ class TNonblockingServer : public TServer { * * @param task the runnable associated with the expired task. */ - void expireClose(stdcxx::shared_ptr task); + void expireClose(std::shared_ptr task); /** * Return an initialized connection object. Creates or recovers from @@ -721,7 +721,7 @@ class TNonblockingServer : public TServer { * @param addrLen the length of addr * @return pointer to initialized TConnection object. */ - TConnection* createConnection(stdcxx::shared_ptr socket); + TConnection* createConnection(std::shared_ptr socket); /** * Returns a connection to pool or deletion. If the connection pool @@ -765,10 +765,10 @@ class TNonblockingIOThread : public Runnable { evutil_socket_t getNotificationRecvFD() const { return notificationPipeFDs_[0]; } // Returns the actual thread object associated with this IO thread. - stdcxx::shared_ptr getThread() const { return thread_; } + std::shared_ptr getThread() const { return thread_; } // Sets the actual thread object associated with this IO thread. - void setThread(const stdcxx::shared_ptr& t) { thread_ = t; } + void setThread(const std::shared_ptr& t) { thread_ = t; } // Used by TConnection objects to indicate processing has finished. bool notify(TNonblockingServer::TConnection* conn); @@ -853,7 +853,7 @@ class TNonblockingIOThread : public Runnable { evutil_socket_t notificationPipeFDs_[2]; /// Actual IO Thread - stdcxx::shared_ptr thread_; + std::shared_ptr thread_; }; } } diff --git a/lib/cpp/src/thrift/server/TServer.h b/lib/cpp/src/thrift/server/TServer.h index f4cd7bc1408..3c6d8185082 100644 --- a/lib/cpp/src/thrift/server/TServer.h +++ b/lib/cpp/src/thrift/server/TServer.h @@ -25,7 +25,7 @@ #include #include -#include +#include namespace apache { namespace thrift { @@ -58,8 +58,8 @@ class TServerEventHandler { /** * Called when a new client has connected and is about to being processing. */ - virtual void* createContext(stdcxx::shared_ptr input, - stdcxx::shared_ptr output) { + virtual void* createContext(std::shared_ptr input, + std::shared_ptr output) { (void)input; (void)output; return NULL; @@ -70,8 +70,8 @@ class TServerEventHandler { * context. */ virtual void deleteContext(void* serverContext, - stdcxx::shared_ptr input, - stdcxx::shared_ptr output) { + std::shared_ptr input, + std::shared_ptr output) { (void)serverContext; (void)input; (void)output; @@ -80,7 +80,7 @@ class TServerEventHandler { /** * Called when a client is about to call the processor. */ - virtual void processContext(void* serverContext, stdcxx::shared_ptr transport) { + virtual void processContext(void* serverContext, std::shared_ptr transport) { (void)serverContext; (void)transport; } @@ -107,62 +107,62 @@ class TServer : public concurrency::Runnable { // Allows running the server as a Runnable thread virtual void run() { serve(); } - stdcxx::shared_ptr getProcessorFactory() { return processorFactory_; } + std::shared_ptr getProcessorFactory() { return processorFactory_; } - stdcxx::shared_ptr getServerTransport() { return serverTransport_; } + std::shared_ptr getServerTransport() { return serverTransport_; } - stdcxx::shared_ptr getInputTransportFactory() { return inputTransportFactory_; } + std::shared_ptr getInputTransportFactory() { return inputTransportFactory_; } - stdcxx::shared_ptr getOutputTransportFactory() { + std::shared_ptr getOutputTransportFactory() { return outputTransportFactory_; } - stdcxx::shared_ptr getInputProtocolFactory() { return inputProtocolFactory_; } + std::shared_ptr getInputProtocolFactory() { return inputProtocolFactory_; } - stdcxx::shared_ptr getOutputProtocolFactory() { return outputProtocolFactory_; } + std::shared_ptr getOutputProtocolFactory() { return outputProtocolFactory_; } - stdcxx::shared_ptr getEventHandler() { return eventHandler_; } + std::shared_ptr getEventHandler() { return eventHandler_; } protected: - TServer(const stdcxx::shared_ptr& processorFactory) + TServer(const std::shared_ptr& processorFactory) : processorFactory_(processorFactory) { - setInputTransportFactory(stdcxx::shared_ptr(new TTransportFactory())); - setOutputTransportFactory(stdcxx::shared_ptr(new TTransportFactory())); - setInputProtocolFactory(stdcxx::shared_ptr(new TBinaryProtocolFactory())); - setOutputProtocolFactory(stdcxx::shared_ptr(new TBinaryProtocolFactory())); + setInputTransportFactory(std::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(std::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); + setOutputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); } - TServer(const stdcxx::shared_ptr& processor) + TServer(const std::shared_ptr& processor) : processorFactory_(new TSingletonProcessorFactory(processor)) { - setInputTransportFactory(stdcxx::shared_ptr(new TTransportFactory())); - setOutputTransportFactory(stdcxx::shared_ptr(new TTransportFactory())); - setInputProtocolFactory(stdcxx::shared_ptr(new TBinaryProtocolFactory())); - setOutputProtocolFactory(stdcxx::shared_ptr(new TBinaryProtocolFactory())); + setInputTransportFactory(std::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(std::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); + setOutputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); } - TServer(const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport) + TServer(const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport) : processorFactory_(processorFactory), serverTransport_(serverTransport) { - setInputTransportFactory(stdcxx::shared_ptr(new TTransportFactory())); - setOutputTransportFactory(stdcxx::shared_ptr(new TTransportFactory())); - setInputProtocolFactory(stdcxx::shared_ptr(new TBinaryProtocolFactory())); - setOutputProtocolFactory(stdcxx::shared_ptr(new TBinaryProtocolFactory())); + setInputTransportFactory(std::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(std::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); + setOutputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); } - TServer(const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport) + TServer(const std::shared_ptr& processor, + const std::shared_ptr& serverTransport) : processorFactory_(new TSingletonProcessorFactory(processor)), serverTransport_(serverTransport) { - setInputTransportFactory(stdcxx::shared_ptr(new TTransportFactory())); - setOutputTransportFactory(stdcxx::shared_ptr(new TTransportFactory())); - setInputProtocolFactory(stdcxx::shared_ptr(new TBinaryProtocolFactory())); - setOutputProtocolFactory(stdcxx::shared_ptr(new TBinaryProtocolFactory())); + setInputTransportFactory(std::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(std::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); + setOutputProtocolFactory(std::shared_ptr(new TBinaryProtocolFactory())); } - TServer(const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory) + TServer(const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory) : processorFactory_(processorFactory), serverTransport_(serverTransport), inputTransportFactory_(transportFactory), @@ -170,10 +170,10 @@ class TServer : public concurrency::Runnable { inputProtocolFactory_(protocolFactory), outputProtocolFactory_(protocolFactory) {} - TServer(const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory) + TServer(const std::shared_ptr& processor, + const std::shared_ptr& serverTransport, + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory) : processorFactory_(new TSingletonProcessorFactory(processor)), serverTransport_(serverTransport), inputTransportFactory_(transportFactory), @@ -181,12 +181,12 @@ class TServer : public concurrency::Runnable { inputProtocolFactory_(protocolFactory), outputProtocolFactory_(protocolFactory) {} - TServer(const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory) + TServer(const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory) : processorFactory_(processorFactory), serverTransport_(serverTransport), inputTransportFactory_(inputTransportFactory), @@ -194,12 +194,12 @@ class TServer : public concurrency::Runnable { inputProtocolFactory_(inputProtocolFactory), outputProtocolFactory_(outputProtocolFactory) {} - TServer(const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory) + TServer(const std::shared_ptr& processor, + const std::shared_ptr& serverTransport, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory) : processorFactory_(new TSingletonProcessorFactory(processor)), serverTransport_(serverTransport), inputTransportFactory_(inputTransportFactory), @@ -214,9 +214,9 @@ class TServer : public concurrency::Runnable { * call). This allows the TProcessorFactory to return a different processor * for each connection if it desires. */ - stdcxx::shared_ptr getProcessor(stdcxx::shared_ptr inputProtocol, - stdcxx::shared_ptr outputProtocol, - stdcxx::shared_ptr transport) { + std::shared_ptr getProcessor(std::shared_ptr inputProtocol, + std::shared_ptr outputProtocol, + std::shared_ptr transport) { TConnectionInfo connInfo; connInfo.input = inputProtocol; connInfo.output = outputProtocol; @@ -225,35 +225,35 @@ class TServer : public concurrency::Runnable { } // Class variables - stdcxx::shared_ptr processorFactory_; - stdcxx::shared_ptr serverTransport_; + std::shared_ptr processorFactory_; + std::shared_ptr serverTransport_; - stdcxx::shared_ptr inputTransportFactory_; - stdcxx::shared_ptr outputTransportFactory_; + std::shared_ptr inputTransportFactory_; + std::shared_ptr outputTransportFactory_; - stdcxx::shared_ptr inputProtocolFactory_; - stdcxx::shared_ptr outputProtocolFactory_; + std::shared_ptr inputProtocolFactory_; + std::shared_ptr outputProtocolFactory_; - stdcxx::shared_ptr eventHandler_; + std::shared_ptr eventHandler_; public: - void setInputTransportFactory(stdcxx::shared_ptr inputTransportFactory) { + void setInputTransportFactory(std::shared_ptr inputTransportFactory) { inputTransportFactory_ = inputTransportFactory; } - void setOutputTransportFactory(stdcxx::shared_ptr outputTransportFactory) { + void setOutputTransportFactory(std::shared_ptr outputTransportFactory) { outputTransportFactory_ = outputTransportFactory; } - void setInputProtocolFactory(stdcxx::shared_ptr inputProtocolFactory) { + void setInputProtocolFactory(std::shared_ptr inputProtocolFactory) { inputProtocolFactory_ = inputProtocolFactory; } - void setOutputProtocolFactory(stdcxx::shared_ptr outputProtocolFactory) { + void setOutputProtocolFactory(std::shared_ptr outputProtocolFactory) { outputProtocolFactory_ = outputProtocolFactory; } - void setServerEventHandler(stdcxx::shared_ptr eventHandler) { + void setServerEventHandler(std::shared_ptr eventHandler) { eventHandler_ = eventHandler; } }; diff --git a/lib/cpp/src/thrift/server/TServerFramework.cpp b/lib/cpp/src/thrift/server/TServerFramework.cpp index ae38336d49e..cbeaa24ff5c 100644 --- a/lib/cpp/src/thrift/server/TServerFramework.cpp +++ b/lib/cpp/src/thrift/server/TServerFramework.cpp @@ -29,8 +29,8 @@ namespace server { using apache::thrift::concurrency::Synchronized; using apache::thrift::protocol::TProtocol; using apache::thrift::protocol::TProtocolFactory; -using apache::thrift::stdcxx::bind; -using apache::thrift::stdcxx::shared_ptr; +using std::bind; +using std::shared_ptr; using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; @@ -161,7 +161,7 @@ void TServerFramework::serve() { outputProtocol, eventHandler_, client), - bind(&TServerFramework::disposeConnectedClient, this, stdcxx::placeholders::_1))); + bind(&TServerFramework::disposeConnectedClient, this, std::placeholders::_1))); } catch (TTransportException& ttx) { releaseOneDescriptor("inputTransport", inputTransport); diff --git a/lib/cpp/src/thrift/server/TServerFramework.h b/lib/cpp/src/thrift/server/TServerFramework.h index 706fd490a0c..eaacce5f263 100644 --- a/lib/cpp/src/thrift/server/TServerFramework.h +++ b/lib/cpp/src/thrift/server/TServerFramework.h @@ -20,7 +20,7 @@ #ifndef _THRIFT_SERVER_TSERVERFRAMEWORK_H_ #define _THRIFT_SERVER_TSERVERFRAMEWORK_H_ 1 -#include +#include #include #include #include @@ -48,32 +48,32 @@ namespace server { class TServerFramework : public TServer { public: TServerFramework( - const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory); + const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory); TServerFramework( - const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory); + const std::shared_ptr& processor, + const std::shared_ptr& serverTransport, + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory); TServerFramework( - const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory); + const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory); TServerFramework( - const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory); + const std::shared_ptr& processor, + const std::shared_ptr& serverTransport, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory); virtual ~TServerFramework(); @@ -130,7 +130,7 @@ class TServerFramework : public TServer { * * \param[in] pClient the newly connected client */ - virtual void onClientConnected(const stdcxx::shared_ptr& pClient) = 0; + virtual void onClientConnected(const std::shared_ptr& pClient) = 0; /** * A client has disconnected. @@ -149,7 +149,7 @@ class TServerFramework : public TServer { * client rate limiting after onClientConnected returns by blocking the * serve() thread if the limit has been reached. */ - void newlyConnectedClient(const stdcxx::shared_ptr& pClient); + void newlyConnectedClient(const std::shared_ptr& pClient); /** * Smart pointer client deletion. diff --git a/lib/cpp/src/thrift/server/TSimpleServer.cpp b/lib/cpp/src/thrift/server/TSimpleServer.cpp index a0afbbe7360..716234d0e12 100644 --- a/lib/cpp/src/thrift/server/TSimpleServer.cpp +++ b/lib/cpp/src/thrift/server/TSimpleServer.cpp @@ -29,7 +29,7 @@ using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TTransportFactory; -using stdcxx::shared_ptr; +using std::shared_ptr; using std::string; TSimpleServer::TSimpleServer(const shared_ptr& processorFactory, diff --git a/lib/cpp/src/thrift/server/TSimpleServer.h b/lib/cpp/src/thrift/server/TSimpleServer.h index ac4ed34ea2c..454922591c4 100644 --- a/lib/cpp/src/thrift/server/TSimpleServer.h +++ b/lib/cpp/src/thrift/server/TSimpleServer.h @@ -34,37 +34,37 @@ namespace server { class TSimpleServer : public TServerFramework { public: TSimpleServer( - const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory); + const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory); TSimpleServer( - const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory); + const std::shared_ptr& processor, + const std::shared_ptr& serverTransport, + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory); TSimpleServer( - const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory); + const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory); TSimpleServer( - const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory); + const std::shared_ptr& processor, + const std::shared_ptr& serverTransport, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory); virtual ~TSimpleServer(); protected: - virtual void onClientConnected(const stdcxx::shared_ptr& pClient) /* override */; + virtual void onClientConnected(const std::shared_ptr& pClient) /* override */; virtual void onClientDisconnected(TConnectedClient* pClient) /* override */; private: diff --git a/lib/cpp/src/thrift/server/TThreadPoolServer.cpp b/lib/cpp/src/thrift/server/TThreadPoolServer.cpp index f07ff849d22..ee345a98966 100644 --- a/lib/cpp/src/thrift/server/TThreadPoolServer.cpp +++ b/lib/cpp/src/thrift/server/TThreadPoolServer.cpp @@ -30,7 +30,7 @@ using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TTransportFactory; -using stdcxx::shared_ptr; +using std::shared_ptr; using std::string; TThreadPoolServer::TThreadPoolServer(const shared_ptr& processorFactory, @@ -115,7 +115,7 @@ void TThreadPoolServer::setTaskExpiration(int64_t value) { taskExpiration_ = value; } -stdcxx::shared_ptr +std::shared_ptr TThreadPoolServer::getThreadManager() const { return threadManager_; } diff --git a/lib/cpp/src/thrift/server/TThreadPoolServer.h b/lib/cpp/src/thrift/server/TThreadPoolServer.h index 94088d5d04a..a957b473dbf 100644 --- a/lib/cpp/src/thrift/server/TThreadPoolServer.h +++ b/lib/cpp/src/thrift/server/TThreadPoolServer.h @@ -34,39 +34,39 @@ namespace server { class TThreadPoolServer : public TServerFramework { public: TThreadPoolServer( - const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory, - const stdcxx::shared_ptr& threadManager + const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory, + const std::shared_ptr& threadManager = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager()); TThreadPoolServer( - const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory, - const stdcxx::shared_ptr& threadManager + const std::shared_ptr& processor, + const std::shared_ptr& serverTransport, + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory, + const std::shared_ptr& threadManager = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager()); TThreadPoolServer( - const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory, - const stdcxx::shared_ptr& threadManager + const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory, + const std::shared_ptr& threadManager = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager()); TThreadPoolServer( - const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory, - const stdcxx::shared_ptr& threadManager + const std::shared_ptr& processor, + const std::shared_ptr& serverTransport, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory, + const std::shared_ptr& threadManager = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager()); virtual ~TThreadPoolServer(); @@ -83,13 +83,13 @@ class TThreadPoolServer : public TServerFramework { virtual int64_t getTaskExpiration() const; virtual void setTaskExpiration(int64_t value); - virtual stdcxx::shared_ptr getThreadManager() const; + virtual std::shared_ptr getThreadManager() const; protected: - virtual void onClientConnected(const stdcxx::shared_ptr& pClient) /* override */; + virtual void onClientConnected(const std::shared_ptr& pClient) /* override */; virtual void onClientDisconnected(TConnectedClient* pClient) /* override */; - stdcxx::shared_ptr threadManager_; + std::shared_ptr threadManager_; boost::atomic timeout_; boost::atomic taskExpiration_; }; diff --git a/lib/cpp/src/thrift/server/TThreadedServer.cpp b/lib/cpp/src/thrift/server/TThreadedServer.cpp index 3fe5aa6fc91..2264df79b33 100644 --- a/lib/cpp/src/thrift/server/TThreadedServer.cpp +++ b/lib/cpp/src/thrift/server/TThreadedServer.cpp @@ -18,7 +18,7 @@ */ #include -#include +#include #include #include @@ -32,8 +32,8 @@ using apache::thrift::concurrency::Thread; using apache::thrift::concurrency::ThreadFactory; using apache::thrift::protocol::TProtocol; using apache::thrift::protocol::TProtocolFactory; -using apache::thrift::stdcxx::make_shared; -using apache::thrift::stdcxx::shared_ptr; +using std::make_shared; +using std::shared_ptr; using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; diff --git a/lib/cpp/src/thrift/server/TThreadedServer.h b/lib/cpp/src/thrift/server/TThreadedServer.h index 1e0a824d395..c5ccd03c8d2 100644 --- a/lib/cpp/src/thrift/server/TThreadedServer.h +++ b/lib/cpp/src/thrift/server/TThreadedServer.h @@ -38,43 +38,43 @@ namespace server { class TThreadedServer : public TServerFramework { public: TThreadedServer( - const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory, - const stdcxx::shared_ptr& threadFactory - = stdcxx::shared_ptr( + const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory, + const std::shared_ptr& threadFactory + = std::shared_ptr( new apache::thrift::concurrency::PlatformThreadFactory(false))); TThreadedServer( - const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory, - const stdcxx::shared_ptr& threadFactory - = stdcxx::shared_ptr( + const std::shared_ptr& processor, + const std::shared_ptr& serverTransport, + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory, + const std::shared_ptr& threadFactory + = std::shared_ptr( new apache::thrift::concurrency::PlatformThreadFactory(false))); TThreadedServer( - const stdcxx::shared_ptr& processorFactory, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory, - const stdcxx::shared_ptr& threadFactory - = stdcxx::shared_ptr( + const std::shared_ptr& processorFactory, + const std::shared_ptr& serverTransport, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory, + const std::shared_ptr& threadFactory + = std::shared_ptr( new apache::thrift::concurrency::PlatformThreadFactory(false))); TThreadedServer( - const stdcxx::shared_ptr& processor, - const stdcxx::shared_ptr& serverTransport, - const stdcxx::shared_ptr& inputTransportFactory, - const stdcxx::shared_ptr& outputTransportFactory, - const stdcxx::shared_ptr& inputProtocolFactory, - const stdcxx::shared_ptr& outputProtocolFactory, - const stdcxx::shared_ptr& threadFactory - = stdcxx::shared_ptr( + const std::shared_ptr& processor, + const std::shared_ptr& serverTransport, + const std::shared_ptr& inputTransportFactory, + const std::shared_ptr& outputTransportFactory, + const std::shared_ptr& inputProtocolFactory, + const std::shared_ptr& outputProtocolFactory, + const std::shared_ptr& threadFactory + = std::shared_ptr( new apache::thrift::concurrency::PlatformThreadFactory(false))); virtual ~TThreadedServer(); @@ -95,14 +95,14 @@ class TThreadedServer : public TServerFramework { /** * Implementation of TServerFramework::onClientConnected */ - virtual void onClientConnected(const stdcxx::shared_ptr& pClient) /* override */; + virtual void onClientConnected(const std::shared_ptr& pClient) /* override */; /** * Implementation of TServerFramework::onClientDisconnected */ virtual void onClientDisconnected(TConnectedClient *pClient) /* override */; - stdcxx::shared_ptr threadFactory_; + std::shared_ptr threadFactory_; /** * A helper wrapper used to wrap the client in something we can use to maintain @@ -114,16 +114,16 @@ class TThreadedServer : public TServerFramework { class TConnectedClientRunner : public apache::thrift::concurrency::Runnable { public: - TConnectedClientRunner(const stdcxx::shared_ptr& pClient); + TConnectedClientRunner(const std::shared_ptr& pClient); virtual ~TConnectedClientRunner(); void run() /* override */; private: - stdcxx::shared_ptr pClient_; + std::shared_ptr pClient_; }; apache::thrift::concurrency::Monitor clientMonitor_; - typedef std::map > ClientMap; + typedef std::map > ClientMap; /** * A map of active clients diff --git a/lib/cpp/src/thrift/stdcxx.h b/lib/cpp/src/thrift/stdcxx.h deleted file mode 100644 index 20910de5308..00000000000 --- a/lib/cpp/src/thrift/stdcxx.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef _THRIFT_STDCXX_H_ -#define _THRIFT_STDCXX_H_ 1 - -#include -#include - -/////////////////////////////////////////////////////////////////// -// -// functional (function, bind) -// -/////////////////////////////////////////////////////////////////// - -#include - -namespace apache { namespace thrift { namespace stdcxx { - using ::std::bind; - using ::std::function; - - namespace placeholders { - using ::std::placeholders::_1; - using ::std::placeholders::_2; - using ::std::placeholders::_3; - using ::std::placeholders::_4; - using ::std::placeholders::_5; - using ::std::placeholders::_6; - using ::std::placeholders::_7; - using ::std::placeholders::_8; - using ::std::placeholders::_9; - } // apache::thrift::stdcxx::placeholders -}}} // apache::thrift::stdcxx - - -/////////////////////////////////////////////////////////////////// -// -// Smart Pointers -// -/////////////////////////////////////////////////////////////////// - -#include - -namespace apache { namespace thrift { namespace stdcxx { - -using ::std::const_pointer_cast; -using ::std::dynamic_pointer_cast; -using ::std::enable_shared_from_this; -using ::std::make_shared; -template using scoped_ptr = std::unique_ptr; // compiler must support template aliasing -using ::std::shared_ptr; -using ::std::static_pointer_cast; -using ::std::weak_ptr; - - -}}} // apache::thrift::stdcxx - -#endif // #ifndef _THRIFT_STDCXX_H_ diff --git a/lib/cpp/src/thrift/transport/TBufferTransports.h b/lib/cpp/src/thrift/transport/TBufferTransports.h index 79aace625f8..c423f9cf467 100644 --- a/lib/cpp/src/thrift/transport/TBufferTransports.h +++ b/lib/cpp/src/thrift/transport/TBufferTransports.h @@ -186,7 +186,7 @@ class TBufferedTransport : public TVirtualTransport transport) + TBufferedTransport(std::shared_ptr transport) : transport_(transport), rBufSize_(DEFAULT_BUFFER_SIZE), wBufSize_(DEFAULT_BUFFER_SIZE), @@ -196,7 +196,7 @@ class TBufferedTransport : public TVirtualTransport transport, uint32_t sz) + TBufferedTransport(std::shared_ptr transport, uint32_t sz) : transport_(transport), rBufSize_(sz), wBufSize_(sz), @@ -206,7 +206,7 @@ class TBufferedTransport : public TVirtualTransport transport, uint32_t rsz, uint32_t wsz) + TBufferedTransport(std::shared_ptr transport, uint32_t rsz, uint32_t wsz) : transport_(transport), rBufSize_(rsz), wBufSize_(wsz), @@ -255,7 +255,7 @@ class TBufferedTransport : public TVirtualTransport getUnderlyingTransport() { return transport_; } + std::shared_ptr getUnderlyingTransport() { return transport_; } /* * TVirtualTransport provides a default implementation of readAll(). @@ -270,7 +270,7 @@ class TBufferedTransport : public TVirtualTransport transport_; + std::shared_ptr transport_; uint32_t rBufSize_; uint32_t wBufSize_; @@ -291,8 +291,8 @@ class TBufferedTransportFactory : public TTransportFactory { /** * Wraps the transport into a buffered one. */ - virtual stdcxx::shared_ptr getTransport(stdcxx::shared_ptr trans) { - return stdcxx::shared_ptr(new TBufferedTransport(trans)); + virtual std::shared_ptr getTransport(std::shared_ptr trans) { + return std::shared_ptr(new TBufferedTransport(trans)); } }; @@ -319,7 +319,7 @@ class TFramedTransport : public TVirtualTransport initPointers(); } - TFramedTransport(stdcxx::shared_ptr transport) + TFramedTransport(std::shared_ptr transport) : transport_(transport), rBufSize_(0), wBufSize_(DEFAULT_BUFFER_SIZE), @@ -330,7 +330,7 @@ class TFramedTransport : public TVirtualTransport initPointers(); } - TFramedTransport(stdcxx::shared_ptr transport, + TFramedTransport(std::shared_ptr transport, uint32_t sz, uint32_t bufReclaimThresh = (std::numeric_limits::max)()) : transport_(transport), @@ -366,7 +366,7 @@ class TFramedTransport : public TVirtualTransport const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len); - stdcxx::shared_ptr getUnderlyingTransport() { return transport_; } + std::shared_ptr getUnderlyingTransport() { return transport_; } /* * TVirtualTransport provides a default implementation of readAll(). @@ -407,7 +407,7 @@ class TFramedTransport : public TVirtualTransport this->write((uint8_t*)&pad, sizeof(pad)); } - stdcxx::shared_ptr transport_; + std::shared_ptr transport_; uint32_t rBufSize_; uint32_t wBufSize_; @@ -430,8 +430,8 @@ class TFramedTransportFactory : public TTransportFactory { /** * Wraps the transport into a framed one. */ - virtual stdcxx::shared_ptr getTransport(stdcxx::shared_ptr trans) { - return stdcxx::shared_ptr(new TFramedTransport(trans)); + virtual std::shared_ptr getTransport(std::shared_ptr trans) { + return std::shared_ptr(new TFramedTransport(trans)); } }; diff --git a/lib/cpp/src/thrift/transport/TFileTransport.cpp b/lib/cpp/src/thrift/transport/TFileTransport.cpp index b08a5f16f2f..c9f65b8b5ea 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.cpp +++ b/lib/cpp/src/thrift/transport/TFileTransport.cpp @@ -61,7 +61,7 @@ namespace apache { namespace thrift { namespace transport { -using stdcxx::shared_ptr; +using std::shared_ptr; using std::cerr; using std::cout; using std::endl; diff --git a/lib/cpp/src/thrift/transport/TFileTransport.h b/lib/cpp/src/thrift/transport/TFileTransport.h index d6da4363e1b..4fbdd9ec643 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.h +++ b/lib/cpp/src/thrift/transport/TFileTransport.h @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -339,7 +338,7 @@ class TFileTransport : public TFileReaderTransport, public TFileWriterTransport // writer thread apache::thrift::concurrency::PlatformThreadFactory threadFactory_; - stdcxx::shared_ptr writerThread_; + std::shared_ptr writerThread_; // buffers to hold data before it is flushed. Each element of the buffer stores a msg that // needs to be written to the file. The buffers are swapped by the writer thread. @@ -390,14 +389,14 @@ class TFileProcessor { * @param protocolFactory protocol factory * @param inputTransport file transport */ - TFileProcessor(stdcxx::shared_ptr processor, - stdcxx::shared_ptr protocolFactory, - stdcxx::shared_ptr inputTransport); + TFileProcessor(std::shared_ptr processor, + std::shared_ptr protocolFactory, + std::shared_ptr inputTransport); - TFileProcessor(stdcxx::shared_ptr processor, - stdcxx::shared_ptr inputProtocolFactory, - stdcxx::shared_ptr outputProtocolFactory, - stdcxx::shared_ptr inputTransport); + TFileProcessor(std::shared_ptr processor, + std::shared_ptr inputProtocolFactory, + std::shared_ptr outputProtocolFactory, + std::shared_ptr inputTransport); /** * Constructor @@ -407,10 +406,10 @@ class TFileProcessor { * @param inputTransport input file transport * @param output output transport */ - TFileProcessor(stdcxx::shared_ptr processor, - stdcxx::shared_ptr protocolFactory, - stdcxx::shared_ptr inputTransport, - stdcxx::shared_ptr outputTransport); + TFileProcessor(std::shared_ptr processor, + std::shared_ptr protocolFactory, + std::shared_ptr inputTransport, + std::shared_ptr outputTransport); /** * processes events from the file @@ -427,11 +426,11 @@ class TFileProcessor { void processChunk(); private: - stdcxx::shared_ptr processor_; - stdcxx::shared_ptr inputProtocolFactory_; - stdcxx::shared_ptr outputProtocolFactory_; - stdcxx::shared_ptr inputTransport_; - stdcxx::shared_ptr outputTransport_; + std::shared_ptr processor_; + std::shared_ptr inputProtocolFactory_; + std::shared_ptr outputProtocolFactory_; + std::shared_ptr inputTransport_; + std::shared_ptr outputTransport_; }; } } diff --git a/lib/cpp/src/thrift/transport/THeaderTransport.cpp b/lib/cpp/src/thrift/transport/THeaderTransport.cpp index ea16591a9c7..25084ec59cb 100644 --- a/lib/cpp/src/thrift/transport/THeaderTransport.cpp +++ b/lib/cpp/src/thrift/transport/THeaderTransport.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -37,7 +36,7 @@ using std::vector; namespace apache { namespace thrift { -using stdcxx::shared_ptr; +using std::shared_ptr; namespace transport { diff --git a/lib/cpp/src/thrift/transport/THeaderTransport.h b/lib/cpp/src/thrift/transport/THeaderTransport.h index 1a2c8e04900..e6c57e67f6a 100644 --- a/lib/cpp/src/thrift/transport/THeaderTransport.h +++ b/lib/cpp/src/thrift/transport/THeaderTransport.h @@ -34,7 +34,6 @@ #endif #include -#include #include #include @@ -75,7 +74,7 @@ class THeaderTransport : public TVirtualTransport& transport) + explicit THeaderTransport(const std::shared_ptr& transport) : TVirtualTransport(transport), outTransport_(transport), protoId(T_COMPACT_PROTOCOL), @@ -88,8 +87,8 @@ class THeaderTransport : public TVirtualTransport inTransport, - const stdcxx::shared_ptr outTransport) + THeaderTransport(const std::shared_ptr inTransport, + const std::shared_ptr outTransport) : TVirtualTransport(inTransport), outTransport_(outTransport), protoId(T_COMPACT_PROTOCOL), @@ -186,7 +185,7 @@ class THeaderTransport : public TVirtualTransport outTransport_; + std::shared_ptr outTransport_; // 0 and 16th bits must be 0 to differentiate from framed & unframed static const uint32_t HEADER_MAGIC = 0x0FFF0000; @@ -265,8 +264,8 @@ class THeaderTransportFactory : public TTransportFactory { /** * Wraps the transport into a header one. */ - virtual stdcxx::shared_ptr getTransport(stdcxx::shared_ptr trans) { - return stdcxx::shared_ptr(new THeaderTransport(trans)); + virtual std::shared_ptr getTransport(std::shared_ptr trans) { + return std::shared_ptr(new THeaderTransport(trans)); } }; } diff --git a/lib/cpp/src/thrift/transport/THttpClient.cpp b/lib/cpp/src/thrift/transport/THttpClient.cpp index afd02a83dc0..d1521978a9d 100644 --- a/lib/cpp/src/thrift/transport/THttpClient.cpp +++ b/lib/cpp/src/thrift/transport/THttpClient.cpp @@ -32,14 +32,14 @@ namespace apache { namespace thrift { namespace transport { -THttpClient::THttpClient(stdcxx::shared_ptr transport, +THttpClient::THttpClient(std::shared_ptr transport, std::string host, std::string path) : THttpTransport(transport), host_(host), path_(path) { } THttpClient::THttpClient(string host, int port, string path) - : THttpTransport(stdcxx::shared_ptr(new TSocket(host, port))), + : THttpTransport(std::shared_ptr(new TSocket(host, port))), host_(host), path_(path) { } diff --git a/lib/cpp/src/thrift/transport/THttpClient.h b/lib/cpp/src/thrift/transport/THttpClient.h index 96fd5b8460b..f4fb12a11eb 100644 --- a/lib/cpp/src/thrift/transport/THttpClient.h +++ b/lib/cpp/src/thrift/transport/THttpClient.h @@ -28,7 +28,7 @@ namespace transport { class THttpClient : public THttpTransport { public: - THttpClient(stdcxx::shared_ptr transport, std::string host, std::string path = ""); + THttpClient(std::shared_ptr transport, std::string host, std::string path = ""); THttpClient(std::string host, int port, std::string path = ""); diff --git a/lib/cpp/src/thrift/transport/THttpServer.cpp b/lib/cpp/src/thrift/transport/THttpServer.cpp index 2f48cf6dd93..96b248097fb 100644 --- a/lib/cpp/src/thrift/transport/THttpServer.cpp +++ b/lib/cpp/src/thrift/transport/THttpServer.cpp @@ -34,7 +34,7 @@ namespace apache { namespace thrift { namespace transport { -THttpServer::THttpServer(stdcxx::shared_ptr transport) : THttpTransport(transport) { +THttpServer::THttpServer(std::shared_ptr transport) : THttpTransport(transport) { } THttpServer::~THttpServer() { diff --git a/lib/cpp/src/thrift/transport/THttpServer.h b/lib/cpp/src/thrift/transport/THttpServer.h index 086dd6f5ff9..c38606f497e 100644 --- a/lib/cpp/src/thrift/transport/THttpServer.h +++ b/lib/cpp/src/thrift/transport/THttpServer.h @@ -28,7 +28,7 @@ namespace transport { class THttpServer : public THttpTransport { public: - THttpServer(stdcxx::shared_ptr transport); + THttpServer(std::shared_ptr transport); virtual ~THttpServer(); @@ -53,8 +53,8 @@ class THttpServerTransportFactory : public TTransportFactory { /** * Wraps the transport into a buffered one. */ - virtual stdcxx::shared_ptr getTransport(stdcxx::shared_ptr trans) { - return stdcxx::shared_ptr(new THttpServer(trans)); + virtual std::shared_ptr getTransport(std::shared_ptr trans) { + return std::shared_ptr(new THttpServer(trans)); } }; } diff --git a/lib/cpp/src/thrift/transport/THttpTransport.cpp b/lib/cpp/src/thrift/transport/THttpTransport.cpp index 4ccb4d35b03..6ccc03427a3 100644 --- a/lib/cpp/src/thrift/transport/THttpTransport.cpp +++ b/lib/cpp/src/thrift/transport/THttpTransport.cpp @@ -31,7 +31,7 @@ namespace transport { const char* THttpTransport::CRLF = "\r\n"; const int THttpTransport::CRLF_LEN = 2; -THttpTransport::THttpTransport(stdcxx::shared_ptr transport) +THttpTransport::THttpTransport(std::shared_ptr transport) : transport_(transport), origin_(""), readHeaders_(true), diff --git a/lib/cpp/src/thrift/transport/THttpTransport.h b/lib/cpp/src/thrift/transport/THttpTransport.h index 3fa80f81dae..e46ab7f66b4 100644 --- a/lib/cpp/src/thrift/transport/THttpTransport.h +++ b/lib/cpp/src/thrift/transport/THttpTransport.h @@ -36,7 +36,7 @@ namespace transport { */ class THttpTransport : public TVirtualTransport { public: - THttpTransport(stdcxx::shared_ptr transport); + THttpTransport(std::shared_ptr transport); virtual ~THttpTransport(); @@ -59,7 +59,7 @@ class THttpTransport : public TVirtualTransport { virtual const std::string getOrigin(); protected: - stdcxx::shared_ptr transport_; + std::shared_ptr transport_; std::string origin_; TMemoryBuffer writeBuffer_; diff --git a/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.cpp b/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.cpp index da83bea144e..adec5d0f96f 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.cpp @@ -27,14 +27,14 @@ namespace transport { /** * Nonblocking SSL server socket implementation. */ -TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(int port, stdcxx::shared_ptr factory) +TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(int port, std::shared_ptr factory) : TNonblockingServerSocket(port), factory_(factory) { factory_->server(true); } TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(const std::string& address, int port, - stdcxx::shared_ptr factory) + std::shared_ptr factory) : TNonblockingServerSocket(address, port), factory_(factory) { factory_->server(true); } @@ -42,13 +42,13 @@ TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(const std::string& addr TNonblockingSSLServerSocket::TNonblockingSSLServerSocket(int port, int sendTimeout, int recvTimeout, - stdcxx::shared_ptr factory) + std::shared_ptr factory) : TNonblockingServerSocket(port, sendTimeout, recvTimeout), factory_(factory) { factory_->server(true); } -stdcxx::shared_ptr TNonblockingSSLServerSocket::createSocket(THRIFT_SOCKET client) { - stdcxx::shared_ptr tSSLSocket; +std::shared_ptr TNonblockingSSLServerSocket::createSocket(THRIFT_SOCKET client) { + std::shared_ptr tSSLSocket; tSSLSocket = factory_->createSocket(client); tSSLSocket->setLibeventSafe(); return tSSLSocket; diff --git a/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h b/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h index 7aaff53df48..215c405e3b0 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h +++ b/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h @@ -21,7 +21,6 @@ #define _THRIFT_TRANSPORT_TNONBLOCKINGSSLSERVERSOCKET_H_ 1 #include -#include namespace apache { namespace thrift { @@ -40,7 +39,7 @@ class TNonblockingSSLServerSocket : public TNonblockingServerSocket { * @param port Listening port * @param factory SSL socket factory implementation */ - TNonblockingSSLServerSocket(int port, stdcxx::shared_ptr factory); + TNonblockingSSLServerSocket(int port, std::shared_ptr factory); /** * Constructor. Binds to the specified address. @@ -51,7 +50,7 @@ class TNonblockingSSLServerSocket : public TNonblockingServerSocket { */ TNonblockingSSLServerSocket(const std::string& address, int port, - stdcxx::shared_ptr factory); + std::shared_ptr factory); /** * Constructor. Binds to all interfaces. @@ -64,11 +63,11 @@ class TNonblockingSSLServerSocket : public TNonblockingServerSocket { TNonblockingSSLServerSocket(int port, int sendTimeout, int recvTimeout, - stdcxx::shared_ptr factory); + std::shared_ptr factory); protected: - stdcxx::shared_ptr createSocket(THRIFT_SOCKET socket); - stdcxx::shared_ptr factory_; + std::shared_ptr createSocket(THRIFT_SOCKET socket); + std::shared_ptr factory_; }; } } diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp index cca52a4ec3f..3d34ccac526 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp @@ -74,7 +74,7 @@ namespace thrift { namespace transport { using std::string; -using stdcxx::shared_ptr; +using std::shared_ptr; TNonblockingServerSocket::TNonblockingServerSocket(int port) : port_(port), diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h index 1d33239ffae..1586ff0bc9b 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h +++ b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h @@ -22,7 +22,6 @@ #include #include -#include namespace apache { namespace thrift { @@ -37,7 +36,7 @@ class TSocket; */ class TNonblockingServerSocket : public TNonblockingServerTransport { public: - typedef apache::thrift::stdcxx::function socket_func_t; + typedef std::function socket_func_t; const static int DEFAULT_BACKLOG = 1024; @@ -108,8 +107,8 @@ class TNonblockingServerSocket : public TNonblockingServerTransport { void close(); protected: - apache::thrift::stdcxx::shared_ptr acceptImpl(); - virtual apache::thrift::stdcxx::shared_ptr createSocket(THRIFT_SOCKET client); + std::shared_ptr acceptImpl(); + virtual std::shared_ptr createSocket(THRIFT_SOCKET client); private: int port_; diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h b/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h index c32a051d90c..3142e19dbac 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h +++ b/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h @@ -22,7 +22,6 @@ #include #include -#include namespace apache { namespace thrift { @@ -56,8 +55,8 @@ class TNonblockingServerTransport { * @return A new TTransport object * @throws TTransportException if there is an error */ - stdcxx::shared_ptr accept() { - stdcxx::shared_ptr result = acceptImpl(); + std::shared_ptr accept() { + std::shared_ptr result = acceptImpl(); if (!result) { throw TTransportException("accept() may not return NULL"); } @@ -91,7 +90,7 @@ class TNonblockingServerTransport { * @return A newly allocated TTransport object * @throw TTransportException If an error occurs */ - virtual stdcxx::shared_ptr acceptImpl() = 0; + virtual std::shared_ptr acceptImpl() = 0; }; } diff --git a/lib/cpp/src/thrift/transport/TPipe.h b/lib/cpp/src/thrift/transport/TPipe.h index dfc5f2c2fab..aa14f95588c 100644 --- a/lib/cpp/src/thrift/transport/TPipe.h +++ b/lib/cpp/src/thrift/transport/TPipe.h @@ -95,7 +95,7 @@ class TPipe : public TVirtualTransport { HANDLE getNativeWaitHandle(); private: - stdcxx::shared_ptr impl_; + std::shared_ptr impl_; std::string pipename_; diff --git a/lib/cpp/src/thrift/transport/TPipeServer.cpp b/lib/cpp/src/thrift/transport/TPipeServer.cpp index 5923a6236a8..55c35800458 100644 --- a/lib/cpp/src/thrift/transport/TPipeServer.cpp +++ b/lib/cpp/src/thrift/transport/TPipeServer.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #ifdef _WIN32 @@ -37,14 +36,14 @@ namespace transport { #ifdef _WIN32 -using stdcxx::shared_ptr; +using std::shared_ptr; class TPipeServerImpl : boost::noncopyable { public: TPipeServerImpl() {} virtual ~TPipeServerImpl() {} virtual void interrupt() = 0; - virtual stdcxx::shared_ptr acceptImpl() = 0; + virtual std::shared_ptr acceptImpl() = 0; virtual HANDLE getPipeHandle() = 0; virtual HANDLE getWrtPipeHandle() = 0; @@ -75,7 +74,7 @@ class TAnonPipeServer : public TPipeServerImpl { virtual void interrupt() {} // not currently implemented - virtual stdcxx::shared_ptr acceptImpl(); + virtual std::shared_ptr acceptImpl(); virtual HANDLE getPipeHandle() { return PipeR_.h; } virtual HANDLE getWrtPipeHandle() { return PipeW_.h; } @@ -117,7 +116,7 @@ class TNamedPipeServer : public TPipeServerImpl { } } - virtual stdcxx::shared_ptr acceptImpl(); + virtual std::shared_ptr acceptImpl(); virtual HANDLE getPipeHandle() { return Pipe_.h; } virtual HANDLE getWrtPipeHandle() { return INVALID_HANDLE_VALUE; } @@ -141,7 +140,7 @@ class TNamedPipeServer : public TPipeServerImpl { TCriticalSection pipe_protect_; // only read or write these variables underneath a locked pipe_protect_ - stdcxx::shared_ptr cached_client_; + std::shared_ptr cached_client_; TAutoHandle Pipe_; }; diff --git a/lib/cpp/src/thrift/transport/TPipeServer.h b/lib/cpp/src/thrift/transport/TPipeServer.h index 117773c2266..c9b13e5a6d0 100644 --- a/lib/cpp/src/thrift/transport/TPipeServer.h +++ b/lib/cpp/src/thrift/transport/TPipeServer.h @@ -20,8 +20,8 @@ #ifndef _THRIFT_TRANSPORT_TSERVERWINPIPES_H_ #define _THRIFT_TRANSPORT_TSERVERWINPIPES_H_ 1 +#include #include -#include #ifndef _WIN32 #include #endif @@ -82,10 +82,10 @@ class TPipeServer : public TServerTransport { HANDLE getNativeWaitHandle(); protected: - virtual stdcxx::shared_ptr acceptImpl(); + virtual std::shared_ptr acceptImpl(); private: - stdcxx::shared_ptr impl_; + std::shared_ptr impl_; std::string pipename_; uint32_t bufsize_; diff --git a/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp b/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp index 8e81ad7431e..34605c09f68 100644 --- a/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp @@ -27,14 +27,14 @@ namespace transport { /** * SSL server socket implementation. */ -TSSLServerSocket::TSSLServerSocket(int port, stdcxx::shared_ptr factory) +TSSLServerSocket::TSSLServerSocket(int port, std::shared_ptr factory) : TServerSocket(port), factory_(factory) { factory_->server(true); } TSSLServerSocket::TSSLServerSocket(const std::string& address, int port, - stdcxx::shared_ptr factory) + std::shared_ptr factory) : TServerSocket(address, port), factory_(factory) { factory_->server(true); } @@ -42,12 +42,12 @@ TSSLServerSocket::TSSLServerSocket(const std::string& address, TSSLServerSocket::TSSLServerSocket(int port, int sendTimeout, int recvTimeout, - stdcxx::shared_ptr factory) + std::shared_ptr factory) : TServerSocket(port, sendTimeout, recvTimeout), factory_(factory) { factory_->server(true); } -stdcxx::shared_ptr TSSLServerSocket::createSocket(THRIFT_SOCKET client) { +std::shared_ptr TSSLServerSocket::createSocket(THRIFT_SOCKET client) { if (interruptableChildren_) { return factory_->createSocket(client, pChildInterruptSockReader_); diff --git a/lib/cpp/src/thrift/transport/TSSLServerSocket.h b/lib/cpp/src/thrift/transport/TSSLServerSocket.h index dda9af41767..8b75de84d40 100644 --- a/lib/cpp/src/thrift/transport/TSSLServerSocket.h +++ b/lib/cpp/src/thrift/transport/TSSLServerSocket.h @@ -20,7 +20,6 @@ #ifndef _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_ #define _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_ 1 -#include #include namespace apache { @@ -40,7 +39,7 @@ class TSSLServerSocket : public TServerSocket { * @param port Listening port * @param factory SSL socket factory implementation */ - TSSLServerSocket(int port, stdcxx::shared_ptr factory); + TSSLServerSocket(int port, std::shared_ptr factory); /** * Constructor. Binds to the specified address. @@ -51,7 +50,7 @@ class TSSLServerSocket : public TServerSocket { */ TSSLServerSocket(const std::string& address, int port, - stdcxx::shared_ptr factory); + std::shared_ptr factory); /** * Constructor. Binds to all interfaces. @@ -64,11 +63,11 @@ class TSSLServerSocket : public TServerSocket { TSSLServerSocket(int port, int sendTimeout, int recvTimeout, - stdcxx::shared_ptr factory); + std::shared_ptr factory); protected: - stdcxx::shared_ptr createSocket(THRIFT_SOCKET socket); - stdcxx::shared_ptr factory_; + std::shared_ptr createSocket(THRIFT_SOCKET socket); + std::shared_ptr factory_; }; } } diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp index 5f8a2c0f8ac..718e9b1533d 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp @@ -213,33 +213,33 @@ SSL* SSLContext::createSSL() { } // TSSLSocket implementation -TSSLSocket::TSSLSocket(stdcxx::shared_ptr ctx) +TSSLSocket::TSSLSocket(std::shared_ptr ctx) : TSocket(), server_(false), ssl_(NULL), ctx_(ctx) { init(); } -TSSLSocket::TSSLSocket(stdcxx::shared_ptr ctx, stdcxx::shared_ptr interruptListener) +TSSLSocket::TSSLSocket(std::shared_ptr ctx, std::shared_ptr interruptListener) : TSocket(), server_(false), ssl_(NULL), ctx_(ctx) { init(); interruptListener_ = interruptListener; } -TSSLSocket::TSSLSocket(stdcxx::shared_ptr ctx, THRIFT_SOCKET socket) +TSSLSocket::TSSLSocket(std::shared_ptr ctx, THRIFT_SOCKET socket) : TSocket(socket), server_(false), ssl_(NULL), ctx_(ctx) { init(); } -TSSLSocket::TSSLSocket(stdcxx::shared_ptr ctx, THRIFT_SOCKET socket, stdcxx::shared_ptr interruptListener) +TSSLSocket::TSSLSocket(std::shared_ptr ctx, THRIFT_SOCKET socket, std::shared_ptr interruptListener) : TSocket(socket, interruptListener), server_(false), ssl_(NULL), ctx_(ctx) { init(); } -TSSLSocket::TSSLSocket(stdcxx::shared_ptr ctx, string host, int port) +TSSLSocket::TSSLSocket(std::shared_ptr ctx, string host, int port) : TSocket(host, port), server_(false), ssl_(NULL), ctx_(ctx) { init(); } -TSSLSocket::TSSLSocket(stdcxx::shared_ptr ctx, string host, int port, stdcxx::shared_ptr interruptListener) +TSSLSocket::TSSLSocket(std::shared_ptr ctx, string host, int port, std::shared_ptr interruptListener) : TSocket(host, port), server_(false), ssl_(NULL), ctx_(ctx) { init(); interruptListener_ = interruptListener; @@ -857,7 +857,7 @@ TSSLSocketFactory::TSSLSocketFactory(SSLProtocol protocol) : server_(false) { randomize(); } count_++; - ctx_ = stdcxx::shared_ptr(new SSLContext(protocol)); + ctx_ = std::shared_ptr(new SSLContext(protocol)); } TSSLSocketFactory::~TSSLSocketFactory() { @@ -869,47 +869,47 @@ TSSLSocketFactory::~TSSLSocketFactory() { } } -stdcxx::shared_ptr TSSLSocketFactory::createSocket() { - stdcxx::shared_ptr ssl(new TSSLSocket(ctx_)); +std::shared_ptr TSSLSocketFactory::createSocket() { + std::shared_ptr ssl(new TSSLSocket(ctx_)); setup(ssl); return ssl; } -stdcxx::shared_ptr TSSLSocketFactory::createSocket(stdcxx::shared_ptr interruptListener) { - stdcxx::shared_ptr ssl(new TSSLSocket(ctx_, interruptListener)); +std::shared_ptr TSSLSocketFactory::createSocket(std::shared_ptr interruptListener) { + std::shared_ptr ssl(new TSSLSocket(ctx_, interruptListener)); setup(ssl); return ssl; } -stdcxx::shared_ptr TSSLSocketFactory::createSocket(THRIFT_SOCKET socket) { - stdcxx::shared_ptr ssl(new TSSLSocket(ctx_, socket)); +std::shared_ptr TSSLSocketFactory::createSocket(THRIFT_SOCKET socket) { + std::shared_ptr ssl(new TSSLSocket(ctx_, socket)); setup(ssl); return ssl; } -stdcxx::shared_ptr TSSLSocketFactory::createSocket(THRIFT_SOCKET socket, stdcxx::shared_ptr interruptListener) { - stdcxx::shared_ptr ssl(new TSSLSocket(ctx_, socket, interruptListener)); +std::shared_ptr TSSLSocketFactory::createSocket(THRIFT_SOCKET socket, std::shared_ptr interruptListener) { + std::shared_ptr ssl(new TSSLSocket(ctx_, socket, interruptListener)); setup(ssl); return ssl; } -stdcxx::shared_ptr TSSLSocketFactory::createSocket(const string& host, int port) { - stdcxx::shared_ptr ssl(new TSSLSocket(ctx_, host, port)); +std::shared_ptr TSSLSocketFactory::createSocket(const string& host, int port) { + std::shared_ptr ssl(new TSSLSocket(ctx_, host, port)); setup(ssl); return ssl; } -stdcxx::shared_ptr TSSLSocketFactory::createSocket(const string& host, int port, stdcxx::shared_ptr interruptListener) { - stdcxx::shared_ptr ssl(new TSSLSocket(ctx_, host, port, interruptListener)); +std::shared_ptr TSSLSocketFactory::createSocket(const string& host, int port, std::shared_ptr interruptListener) { + std::shared_ptr ssl(new TSSLSocket(ctx_, host, port, interruptListener)); setup(ssl); return ssl; } -void TSSLSocketFactory::setup(stdcxx::shared_ptr ssl) { +void TSSLSocketFactory::setup(std::shared_ptr ssl) { ssl->server(server()); if (access_ == NULL && !server()) { - access_ = stdcxx::shared_ptr(new DefaultClientAccessManager); + access_ = std::shared_ptr(new DefaultClientAccessManager); } if (access_ != NULL) { ssl->access(access_); diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.h b/lib/cpp/src/thrift/transport/TSSLSocket.h index d8fd77e94f8..5a87d1e360c 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.h +++ b/lib/cpp/src/thrift/transport/TSSLSocket.h @@ -26,7 +26,6 @@ #include #include #include -#include namespace apache { namespace thrift { @@ -98,7 +97,7 @@ class TSSLSocket : public TSocket { * * @param manager Instance of AccessManager */ - virtual void access(stdcxx::shared_ptr manager) { access_ = manager; } + virtual void access(std::shared_ptr manager) { access_ = manager; } /** * Set eventSafe flag if libevent is used. */ @@ -112,37 +111,37 @@ class TSSLSocket : public TSocket { /** * Constructor. */ - TSSLSocket(stdcxx::shared_ptr ctx); + TSSLSocket(std::shared_ptr ctx); /** * Constructor with an interrupt signal. */ - TSSLSocket(stdcxx::shared_ptr ctx, stdcxx::shared_ptr interruptListener); + TSSLSocket(std::shared_ptr ctx, std::shared_ptr interruptListener); /** * Constructor, create an instance of TSSLSocket given an existing socket. * * @param socket An existing socket */ - TSSLSocket(stdcxx::shared_ptr ctx, THRIFT_SOCKET socket); + TSSLSocket(std::shared_ptr ctx, THRIFT_SOCKET socket); /** * Constructor, create an instance of TSSLSocket given an existing socket that can be interrupted. * * @param socket An existing socket */ - TSSLSocket(stdcxx::shared_ptr ctx, THRIFT_SOCKET socket, stdcxx::shared_ptr interruptListener); + TSSLSocket(std::shared_ptr ctx, THRIFT_SOCKET socket, std::shared_ptr interruptListener); /** * Constructor. * * @param host Remote host name * @param port Remote port number */ - TSSLSocket(stdcxx::shared_ptr ctx, std::string host, int port); + TSSLSocket(std::shared_ptr ctx, std::string host, int port); /** * Constructor with an interrupt signal. * * @param host Remote host name * @param port Remote port number */ - TSSLSocket(stdcxx::shared_ptr ctx, std::string host, int port, stdcxx::shared_ptr interruptListener); + TSSLSocket(std::shared_ptr ctx, std::string host, int port, std::shared_ptr interruptListener); /** * Authorize peer access after SSL handshake completes. */ @@ -171,8 +170,8 @@ class TSSLSocket : public TSocket { bool server_; SSL* ssl_; - stdcxx::shared_ptr ctx_; - stdcxx::shared_ptr access_; + std::shared_ptr ctx_; + std::shared_ptr access_; friend class TSSLSocketFactory; private: @@ -212,37 +211,37 @@ class TSSLSocketFactory { /** * Create an instance of TSSLSocket with a fresh new socket. */ - virtual stdcxx::shared_ptr createSocket(); + virtual std::shared_ptr createSocket(); /** * Create an instance of TSSLSocket with a fresh new socket, which is interruptable. */ - virtual stdcxx::shared_ptr createSocket(stdcxx::shared_ptr interruptListener); + virtual std::shared_ptr createSocket(std::shared_ptr interruptListener); /** * Create an instance of TSSLSocket with the given socket. * * @param socket An existing socket. */ - virtual stdcxx::shared_ptr createSocket(THRIFT_SOCKET socket); + virtual std::shared_ptr createSocket(THRIFT_SOCKET socket); /** * Create an instance of TSSLSocket with the given socket which is interruptable. * * @param socket An existing socket. */ - virtual stdcxx::shared_ptr createSocket(THRIFT_SOCKET socket, stdcxx::shared_ptr interruptListener); + virtual std::shared_ptr createSocket(THRIFT_SOCKET socket, std::shared_ptr interruptListener); /** * Create an instance of TSSLSocket. * * @param host Remote host to be connected to * @param port Remote port to be connected to */ - virtual stdcxx::shared_ptr createSocket(const std::string& host, int port); + virtual std::shared_ptr createSocket(const std::string& host, int port); /** * Create an instance of TSSLSocket. * * @param host Remote host to be connected to * @param port Remote port to be connected to */ - virtual stdcxx::shared_ptr createSocket(const std::string& host, int port, stdcxx::shared_ptr interruptListener); + virtual std::shared_ptr createSocket(const std::string& host, int port, std::shared_ptr interruptListener); /** * Set ciphers to be used in SSL handshake process. * @@ -300,13 +299,13 @@ class TSSLSocketFactory { * * @param manager The AccessManager instance */ - virtual void access(stdcxx::shared_ptr manager) { access_ = manager; } + virtual void access(std::shared_ptr manager) { access_ = manager; } static void setManualOpenSSLInitialization(bool manualOpenSSLInitialization) { manualOpenSSLInitialization_ = manualOpenSSLInitialization; } protected: - stdcxx::shared_ptr ctx_; + std::shared_ptr ctx_; /** * Override this method for custom password callback. It may be called @@ -319,11 +318,11 @@ class TSSLSocketFactory { private: bool server_; - stdcxx::shared_ptr access_; + std::shared_ptr access_; static concurrency::Mutex mutex_; static uint64_t count_; static bool manualOpenSSLInitialization_; - void setup(stdcxx::shared_ptr ssl); + void setup(std::shared_ptr ssl); static int passwordCallback(char* password, int size, int, void* data); }; diff --git a/lib/cpp/src/thrift/transport/TServerSocket.cpp b/lib/cpp/src/thrift/transport/TServerSocket.cpp index 3f11a59e39e..118b9936d9c 100644 --- a/lib/cpp/src/thrift/transport/TServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TServerSocket.cpp @@ -46,7 +46,6 @@ #include #include #include -#include #ifndef AF_LOCAL #define AF_LOCAL AF_UNIX @@ -81,7 +80,7 @@ namespace apache { namespace thrift { namespace transport { -using stdcxx::shared_ptr; +using std::shared_ptr; TGetAddrInfoWrapper::TGetAddrInfoWrapper(const char* node, const char* service, @@ -249,7 +248,7 @@ void TServerSocket::listen() { } else { childInterruptSockWriter_ = sv[1]; pChildInterruptSockReader_ - = stdcxx::shared_ptr(new THRIFT_SOCKET(sv[0]), destroyer_of_fine_sockets); + = std::shared_ptr(new THRIFT_SOCKET(sv[0]), destroyer_of_fine_sockets); } // Validate port number diff --git a/lib/cpp/src/thrift/transport/TServerSocket.h b/lib/cpp/src/thrift/transport/TServerSocket.h index 1daaa8299b1..b23d2c19dfd 100644 --- a/lib/cpp/src/thrift/transport/TServerSocket.h +++ b/lib/cpp/src/thrift/transport/TServerSocket.h @@ -21,7 +21,6 @@ #define _THRIFT_TRANSPORT_TSERVERSOCKET_H_ 1 #include -#include #include #include @@ -62,7 +61,7 @@ class TGetAddrInfoWrapper { */ class TServerSocket : public TServerTransport { public: - typedef apache::thrift::stdcxx::function socket_func_t; + typedef std::function socket_func_t; const static int DEFAULT_BACKLOG = 1024; @@ -147,10 +146,10 @@ class TServerSocket : public TServerTransport { void close(); protected: - stdcxx::shared_ptr acceptImpl(); - virtual stdcxx::shared_ptr createSocket(THRIFT_SOCKET client); + std::shared_ptr acceptImpl(); + virtual std::shared_ptr createSocket(THRIFT_SOCKET client); bool interruptableChildren_; - stdcxx::shared_ptr pChildInterruptSockReader_; // if interruptableChildren_ this is shared with child TSockets + std::shared_ptr pChildInterruptSockReader_; // if interruptableChildren_ this is shared with child TSockets private: void notify(THRIFT_SOCKET notifySock); diff --git a/lib/cpp/src/thrift/transport/TServerTransport.h b/lib/cpp/src/thrift/transport/TServerTransport.h index 9d5a3d556e7..db7632a03a9 100644 --- a/lib/cpp/src/thrift/transport/TServerTransport.h +++ b/lib/cpp/src/thrift/transport/TServerTransport.h @@ -22,7 +22,6 @@ #include #include -#include namespace apache { namespace thrift { @@ -56,8 +55,8 @@ class TServerTransport { * @return A new TTransport object * @throws TTransportException if there is an error */ - stdcxx::shared_ptr accept() { - stdcxx::shared_ptr result = acceptImpl(); + std::shared_ptr accept() { + std::shared_ptr result = acceptImpl(); if (!result) { throw TTransportException("accept() may not return NULL"); } @@ -105,7 +104,7 @@ class TServerTransport { * @return A newly allocated TTransport object * @throw TTransportException If an error occurs */ - virtual stdcxx::shared_ptr acceptImpl() = 0; + virtual std::shared_ptr acceptImpl() = 0; }; } } diff --git a/lib/cpp/src/thrift/transport/TShortReadTransport.h b/lib/cpp/src/thrift/transport/TShortReadTransport.h index 550b6ba4b01..118252d75d5 100644 --- a/lib/cpp/src/thrift/transport/TShortReadTransport.h +++ b/lib/cpp/src/thrift/transport/TShortReadTransport.h @@ -38,7 +38,7 @@ namespace test { */ class TShortReadTransport : public TVirtualTransport { public: - TShortReadTransport(stdcxx::shared_ptr transport, double full_prob) + TShortReadTransport(std::shared_ptr transport, double full_prob) : transport_(transport), fullProb_(full_prob) {} bool isOpen() { return transport_->isOpen(); } @@ -68,10 +68,10 @@ class TShortReadTransport : public TVirtualTransport { void consume(uint32_t len) { return transport_->consume(len); } - stdcxx::shared_ptr getUnderlyingTransport() { return transport_; } + std::shared_ptr getUnderlyingTransport() { return transport_; } protected: - stdcxx::shared_ptr transport_; + std::shared_ptr transport_; double fullProb_; }; } diff --git a/lib/cpp/src/thrift/transport/TSocket.cpp b/lib/cpp/src/thrift/transport/TSocket.cpp index 18cadbc0611..c6c2bfa0074 100644 --- a/lib/cpp/src/thrift/transport/TSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSocket.cpp @@ -144,7 +144,7 @@ TSocket::TSocket(THRIFT_SOCKET socket) #endif } -TSocket::TSocket(THRIFT_SOCKET socket, stdcxx::shared_ptr interruptListener) +TSocket::TSocket(THRIFT_SOCKET socket, std::shared_ptr interruptListener) : port_(0), socket_(socket), peerPort_(0), diff --git a/lib/cpp/src/thrift/transport/TSocket.h b/lib/cpp/src/thrift/transport/TSocket.h index 66d9e6cd37d..4030d4646de 100644 --- a/lib/cpp/src/thrift/transport/TSocket.h +++ b/lib/cpp/src/thrift/transport/TSocket.h @@ -270,7 +270,7 @@ class TSocket : public TVirtualTransport { * Constructor to create socket from file descriptor that * can be interrupted safely. */ - TSocket(THRIFT_SOCKET socket, stdcxx::shared_ptr interruptListener); + TSocket(THRIFT_SOCKET socket, std::shared_ptr interruptListener); /** * Set a cache of the peer address (used when trivially available: e.g. @@ -307,7 +307,7 @@ class TSocket : public TVirtualTransport { * A shared socket pointer that will interrupt a blocking read if data * becomes available on it */ - stdcxx::shared_ptr interruptListener_; + std::shared_ptr interruptListener_; /** Connect timeout in ms */ int connTimeout_; diff --git a/lib/cpp/src/thrift/transport/TSocketPool.cpp b/lib/cpp/src/thrift/transport/TSocketPool.cpp index a34d1359914..5477bbb8e68 100644 --- a/lib/cpp/src/thrift/transport/TSocketPool.cpp +++ b/lib/cpp/src/thrift/transport/TSocketPool.cpp @@ -35,7 +35,7 @@ namespace apache { namespace thrift { namespace transport { -using stdcxx::shared_ptr; +using std::shared_ptr; /** * TSocketPoolServer implementation diff --git a/lib/cpp/src/thrift/transport/TSocketPool.h b/lib/cpp/src/thrift/transport/TSocketPool.h index bd49e5574b1..18f101c1cff 100644 --- a/lib/cpp/src/thrift/transport/TSocketPool.h +++ b/lib/cpp/src/thrift/transport/TSocketPool.h @@ -92,7 +92,7 @@ class TSocketPool : public TSocket { * * @param servers list of TSocketPoolServers */ - TSocketPool(const std::vector >& servers); + TSocketPool(const std::vector >& servers); /** * Socket pool constructor @@ -115,17 +115,17 @@ class TSocketPool : public TSocket { /** * Add a server to the pool */ - void addServer(stdcxx::shared_ptr& server); + void addServer(std::shared_ptr& server); /** * Set list of servers in this pool */ - void setServers(const std::vector >& servers); + void setServers(const std::vector >& servers); /** * Get list of servers in this pool */ - void getServers(std::vector >& servers); + void getServers(std::vector >& servers); /** * Sets how many times to keep retrying a host in the connect function. @@ -163,13 +163,13 @@ class TSocketPool : public TSocket { void close(); protected: - void setCurrentServer(const stdcxx::shared_ptr& server); + void setCurrentServer(const std::shared_ptr& server); /** List of servers to connect to */ - std::vector > servers_; + std::vector > servers_; /** Current server */ - stdcxx::shared_ptr currentServer_; + std::shared_ptr currentServer_; /** How many times to retry each host in connect */ int numRetries_; diff --git a/lib/cpp/src/thrift/transport/TTransport.h b/lib/cpp/src/thrift/transport/TTransport.h index de032909d23..d844239a8c2 100644 --- a/lib/cpp/src/thrift/transport/TTransport.h +++ b/lib/cpp/src/thrift/transport/TTransport.h @@ -21,8 +21,8 @@ #define _THRIFT_TRANSPORT_TTRANSPORT_H_ 1 #include -#include #include +#include #include namespace apache { @@ -260,7 +260,7 @@ class TTransportFactory { /** * Default implementation does nothing, just returns the transport given. */ - virtual stdcxx::shared_ptr getTransport(stdcxx::shared_ptr trans) { + virtual std::shared_ptr getTransport(std::shared_ptr trans) { return trans; } }; diff --git a/lib/cpp/src/thrift/transport/TTransportUtils.cpp b/lib/cpp/src/thrift/transport/TTransportUtils.cpp index 5a236dc308c..6f47c797295 100644 --- a/lib/cpp/src/thrift/transport/TTransportUtils.cpp +++ b/lib/cpp/src/thrift/transport/TTransportUtils.cpp @@ -103,8 +103,8 @@ void TPipedTransport::flush() { } TPipedFileReaderTransport::TPipedFileReaderTransport( - stdcxx::shared_ptr srcTrans, - stdcxx::shared_ptr dstTrans) + std::shared_ptr srcTrans, + std::shared_ptr dstTrans) : TPipedTransport(srcTrans, dstTrans), srcTrans_(srcTrans) { } diff --git a/lib/cpp/src/thrift/transport/TTransportUtils.h b/lib/cpp/src/thrift/transport/TTransportUtils.h index f3b4c5acbf7..4c82dd3befb 100644 --- a/lib/cpp/src/thrift/transport/TTransportUtils.h +++ b/lib/cpp/src/thrift/transport/TTransportUtils.h @@ -63,7 +63,7 @@ class TNullTransport : public TVirtualTransport { */ class TPipedTransport : virtual public TTransport { public: - TPipedTransport(stdcxx::shared_ptr srcTrans, stdcxx::shared_ptr dstTrans) + TPipedTransport(std::shared_ptr srcTrans, std::shared_ptr dstTrans) : srcTrans_(srcTrans), dstTrans_(dstTrans), rBufSize_(512), @@ -86,8 +86,8 @@ class TPipedTransport : virtual public TTransport { } } - TPipedTransport(stdcxx::shared_ptr srcTrans, - stdcxx::shared_ptr dstTrans, + TPipedTransport(std::shared_ptr srcTrans, + std::shared_ptr dstTrans, uint32_t sz) : srcTrans_(srcTrans), dstTrans_(dstTrans), @@ -174,7 +174,7 @@ class TPipedTransport : virtual public TTransport { void flush(); - stdcxx::shared_ptr getTargetTransport() { return dstTrans_; } + std::shared_ptr getTargetTransport() { return dstTrans_; } /* * Override TTransport *_virt() functions to invoke our implementations. @@ -185,8 +185,8 @@ class TPipedTransport : virtual public TTransport { virtual void write_virt(const uint8_t* buf, uint32_t len) { this->write(buf, len); } protected: - stdcxx::shared_ptr srcTrans_; - stdcxx::shared_ptr dstTrans_; + std::shared_ptr srcTrans_; + std::shared_ptr dstTrans_; uint8_t* rBuf_; uint32_t rBufSize_; @@ -208,7 +208,7 @@ class TPipedTransport : virtual public TTransport { class TPipedTransportFactory : public TTransportFactory { public: TPipedTransportFactory() {} - TPipedTransportFactory(stdcxx::shared_ptr dstTrans) { + TPipedTransportFactory(std::shared_ptr dstTrans) { initializeTargetTransport(dstTrans); } virtual ~TPipedTransportFactory() {} @@ -216,11 +216,11 @@ class TPipedTransportFactory : public TTransportFactory { /** * Wraps the base transport into a piped transport. */ - virtual stdcxx::shared_ptr getTransport(stdcxx::shared_ptr srcTrans) { - return stdcxx::shared_ptr(new TPipedTransport(srcTrans, dstTrans_)); + virtual std::shared_ptr getTransport(std::shared_ptr srcTrans) { + return std::shared_ptr(new TPipedTransport(srcTrans, dstTrans_)); } - virtual void initializeTargetTransport(stdcxx::shared_ptr dstTrans) { + virtual void initializeTargetTransport(std::shared_ptr dstTrans) { if (dstTrans_.get() == NULL) { dstTrans_ = dstTrans; } else { @@ -229,7 +229,7 @@ class TPipedTransportFactory : public TTransportFactory { } protected: - stdcxx::shared_ptr dstTrans_; + std::shared_ptr dstTrans_; }; /** @@ -240,8 +240,8 @@ class TPipedTransportFactory : public TTransportFactory { */ class TPipedFileReaderTransport : public TPipedTransport, public TFileReaderTransport { public: - TPipedFileReaderTransport(stdcxx::shared_ptr srcTrans, - stdcxx::shared_ptr dstTrans); + TPipedFileReaderTransport(std::shared_ptr srcTrans, + std::shared_ptr dstTrans); ~TPipedFileReaderTransport(); @@ -277,7 +277,7 @@ class TPipedFileReaderTransport : public TPipedTransport, public TFileReaderTran protected: // shouldn't be used TPipedFileReaderTransport(); - stdcxx::shared_ptr srcTrans_; + std::shared_ptr srcTrans_; }; /** @@ -287,23 +287,23 @@ class TPipedFileReaderTransport : public TPipedTransport, public TFileReaderTran class TPipedFileReaderTransportFactory : public TPipedTransportFactory { public: TPipedFileReaderTransportFactory() {} - TPipedFileReaderTransportFactory(stdcxx::shared_ptr dstTrans) + TPipedFileReaderTransportFactory(std::shared_ptr dstTrans) : TPipedTransportFactory(dstTrans) {} virtual ~TPipedFileReaderTransportFactory() {} - stdcxx::shared_ptr getTransport(stdcxx::shared_ptr srcTrans) { - stdcxx::shared_ptr pFileReaderTransport - = stdcxx::dynamic_pointer_cast(srcTrans); + std::shared_ptr getTransport(std::shared_ptr srcTrans) { + std::shared_ptr pFileReaderTransport + = std::dynamic_pointer_cast(srcTrans); if (pFileReaderTransport.get() != NULL) { return getFileReaderTransport(pFileReaderTransport); } else { - return stdcxx::shared_ptr(); + return std::shared_ptr(); } } - stdcxx::shared_ptr getFileReaderTransport( - stdcxx::shared_ptr srcTrans) { - return stdcxx::shared_ptr( + std::shared_ptr getFileReaderTransport( + std::shared_ptr srcTrans) { + return std::shared_ptr( new TPipedFileReaderTransport(srcTrans, dstTrans_)); } }; diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.h b/lib/cpp/src/thrift/transport/TZlibTransport.h index 59acd69d011..b45ec4356da 100644 --- a/lib/cpp/src/thrift/transport/TZlibTransport.h +++ b/lib/cpp/src/thrift/transport/TZlibTransport.h @@ -78,7 +78,7 @@ class TZlibTransport : public TVirtualTransport { * @param cwbuf_size Compressed buffer size for writing. * @param comp_level Compression level (0=none[fast], 6=default, 9=max[slow]). */ - TZlibTransport(stdcxx::shared_ptr transport, + TZlibTransport(std::shared_ptr transport, int urbuf_size = DEFAULT_URBUF_SIZE, int crbuf_size = DEFAULT_CRBUF_SIZE, int uwbuf_size = DEFAULT_UWBUF_SIZE, @@ -180,7 +180,7 @@ class TZlibTransport : public TVirtualTransport { static const int DEFAULT_UWBUF_SIZE = 128; static const int DEFAULT_CWBUF_SIZE = 1024; - stdcxx::shared_ptr getUnderlyingTransport() const { return transport_; } + std::shared_ptr getUnderlyingTransport() const { return transport_; } protected: inline void checkZlibRv(int status, const char* msg); @@ -195,7 +195,7 @@ class TZlibTransport : public TVirtualTransport { // Larger (or equal) writes are dumped straight to zlib. static const uint32_t MIN_DIRECT_DEFLATE_SIZE = 32; - stdcxx::shared_ptr transport_; + std::shared_ptr transport_; int urpos_; int uwpos_; @@ -231,8 +231,8 @@ class TZlibTransportFactory : public TTransportFactory { virtual ~TZlibTransportFactory() {} - virtual stdcxx::shared_ptr getTransport(stdcxx::shared_ptr trans) { - return stdcxx::shared_ptr(new TZlibTransport(trans)); + virtual std::shared_ptr getTransport(std::shared_ptr trans) { + return std::shared_ptr(new TZlibTransport(trans)); } }; } diff --git a/lib/cpp/src/thrift/windows/TWinsockSingleton.h b/lib/cpp/src/thrift/windows/TWinsockSingleton.h index 50458a93791..a30806b98ce 100644 --- a/lib/cpp/src/thrift/windows/TWinsockSingleton.h +++ b/lib/cpp/src/thrift/windows/TWinsockSingleton.h @@ -33,9 +33,9 @@ // boost #include +#include #include -#include namespace apache { namespace thrift { @@ -48,7 +48,7 @@ namespace transport { class TWinsockSingleton : private boost::noncopyable { public: - typedef stdcxx::shared_ptr instance_ptr; + typedef std::shared_ptr instance_ptr; private: TWinsockSingleton(void); diff --git a/lib/cpp/test/AllProtocolTests.tcc b/lib/cpp/test/AllProtocolTests.tcc index b6df6563a8a..a7eab07ca27 100644 --- a/lib/cpp/test/AllProtocolTests.tcc +++ b/lib/cpp/test/AllProtocolTests.tcc @@ -28,7 +28,7 @@ #include "GenericHelpers.h" -using apache::thrift::stdcxx::shared_ptr; +using std::shared_ptr; using namespace apache::thrift; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; diff --git a/lib/cpp/test/Benchmark.cpp b/lib/cpp/test/Benchmark.cpp index afde7d40278..5ff77aab95f 100644 --- a/lib/cpp/test/Benchmark.cpp +++ b/lib/cpp/test/Benchmark.cpp @@ -23,8 +23,8 @@ #include #define _USE_MATH_DEFINES #include +#include #include "thrift/protocol/TBinaryProtocol.h" -#include "thrift/stdcxx.h" #include "thrift/transport/TBufferTransports.h" #include "gen-cpp/DebugProtoTest_types.h" @@ -68,7 +68,7 @@ int main() { ooe.base64 = "\1\2\3\255"; int num = 100000; - apache::thrift::stdcxx::shared_ptr buf(new TMemoryBuffer(num*1000)); + std::shared_ptr buf(new TMemoryBuffer(num*1000)); uint8_t* data = NULL; uint32_t datasize = 0; @@ -89,7 +89,7 @@ int main() { buf->getBuffer(&data, &datasize); { - apache::thrift::stdcxx::shared_ptr buf2(new TMemoryBuffer(data, datasize)); + std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); OneOfEach ooe2; double elapsed = 0.0; @@ -117,7 +117,7 @@ int main() { { OneOfEach ooe2; - apache::thrift::stdcxx::shared_ptr buf2(new TMemoryBuffer(data, datasize)); + std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); double elapsed = 0.0; Timer timer; @@ -143,7 +143,7 @@ int main() { } { - apache::thrift::stdcxx::shared_ptr buf2(new TMemoryBuffer(data, datasize)); + std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); OneOfEach ooe2; double elapsed = 0.0; @@ -182,7 +182,7 @@ int main() { buf->getBuffer(&data, &datasize); { - apache::thrift::stdcxx::shared_ptr buf2(new TMemoryBuffer(data, datasize)); + std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); ListDoublePerf listDoublePerf2; double elapsed = 0.0; @@ -206,7 +206,7 @@ int main() { { ListDoublePerf listDoublePerf2; - apache::thrift::stdcxx::shared_ptr buf2(new TMemoryBuffer(data, datasize)); + std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); double elapsed = 0.0; Timer timer; @@ -228,7 +228,7 @@ int main() { } { - apache::thrift::stdcxx::shared_ptr buf2(new TMemoryBuffer(data, datasize)); + std::shared_ptr buf2(new TMemoryBuffer(data, datasize)); TBinaryProtocolT prot(buf2); ListDoublePerf listDoublePerf2; double elapsed = 0.0; diff --git a/lib/cpp/test/DebugProtoTest.cpp b/lib/cpp/test/DebugProtoTest.cpp index e04600a32c2..060f3547dd7 100644 --- a/lib/cpp/test/DebugProtoTest.cpp +++ b/lib/cpp/test/DebugProtoTest.cpp @@ -21,14 +21,14 @@ #include #include "gen-cpp/DebugProtoTest_types.h" #include -#include +#include #define BOOST_TEST_MODULE DebugProtoTest #include using namespace thrift::test::debug; -static ::apache::thrift::stdcxx::shared_ptr ooe; +static ::std::shared_ptr ooe; void testCaseSetup_1() { ooe.reset(new OneOfEach); @@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE(test_debug_proto_1) { "Expected:\n" << expected_result << "\nGotten:\n" << result); } -static ::apache::thrift::stdcxx::shared_ptr n; +static ::std::shared_ptr n; void testCaseSetup_2() { testCaseSetup_1(); @@ -149,7 +149,7 @@ BOOST_AUTO_TEST_CASE(test_debug_proto_2) { "Expected:\n" << expected_result << "\nGotten:\n" << result); } -static ::apache::thrift::stdcxx::shared_ptr hm; +static ::std::shared_ptr hm; void testCaseSetup_3() { testCaseSetup_2(); diff --git a/lib/cpp/test/GenericHelpers.h b/lib/cpp/test/GenericHelpers.h index e131c42ff5c..bcef9f24252 100644 --- a/lib/cpp/test/GenericHelpers.h +++ b/lib/cpp/test/GenericHelpers.h @@ -21,7 +21,7 @@ #define _THRIFT_TEST_GENERICHELPERS_H_ 1 #include -#include +#include #include /* ClassName Helper for cleaner exceptions */ @@ -63,43 +63,43 @@ class GenericIO { public: /* Write functions */ - static uint32_t write(apache::thrift::stdcxx::shared_ptr proto, const int8_t& val) { + static uint32_t write(std::shared_ptr proto, const int8_t& val) { return proto->writeByte(val); } - static uint32_t write(apache::thrift::stdcxx::shared_ptr proto, const int16_t& val) { + static uint32_t write(std::shared_ptr proto, const int16_t& val) { return proto->writeI16(val); } - static uint32_t write(apache::thrift::stdcxx::shared_ptr proto, const int32_t& val) { + static uint32_t write(std::shared_ptr proto, const int32_t& val) { return proto->writeI32(val); } - static uint32_t write(apache::thrift::stdcxx::shared_ptr proto, const double& val) { + static uint32_t write(std::shared_ptr proto, const double& val) { return proto->writeDouble(val); } - static uint32_t write(apache::thrift::stdcxx::shared_ptr proto, const int64_t& val) { + static uint32_t write(std::shared_ptr proto, const int64_t& val) { return proto->writeI64(val); } - static uint32_t write(apache::thrift::stdcxx::shared_ptr proto, const std::string& val) { + static uint32_t write(std::shared_ptr proto, const std::string& val) { return proto->writeString(val); } /* Read functions */ - static uint32_t read(apache::thrift::stdcxx::shared_ptr proto, int8_t& val) { return proto->readByte(val); } + static uint32_t read(std::shared_ptr proto, int8_t& val) { return proto->readByte(val); } - static uint32_t read(apache::thrift::stdcxx::shared_ptr proto, int16_t& val) { return proto->readI16(val); } + static uint32_t read(std::shared_ptr proto, int16_t& val) { return proto->readI16(val); } - static uint32_t read(apache::thrift::stdcxx::shared_ptr proto, int32_t& val) { return proto->readI32(val); } + static uint32_t read(std::shared_ptr proto, int32_t& val) { return proto->readI32(val); } - static uint32_t read(apache::thrift::stdcxx::shared_ptr proto, int64_t& val) { return proto->readI64(val); } + static uint32_t read(std::shared_ptr proto, int64_t& val) { return proto->readI64(val); } - static uint32_t read(apache::thrift::stdcxx::shared_ptr proto, double& val) { return proto->readDouble(val); } + static uint32_t read(std::shared_ptr proto, double& val) { return proto->readDouble(val); } - static uint32_t read(apache::thrift::stdcxx::shared_ptr proto, std::string& val) { + static uint32_t read(std::shared_ptr proto, std::string& val) { return proto->readString(val); } }; diff --git a/lib/cpp/test/JSONProtoTest.cpp b/lib/cpp/test/JSONProtoTest.cpp index 77bc2500c87..c2ad73e71db 100644 --- a/lib/cpp/test/JSONProtoTest.cpp +++ b/lib/cpp/test/JSONProtoTest.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include "gen-cpp/DebugProtoTest_types.h" @@ -34,7 +34,7 @@ using namespace apache::thrift; using apache::thrift::transport::TMemoryBuffer; using apache::thrift::protocol::TJSONProtocol; -static stdcxx::shared_ptr ooe; +static std::shared_ptr ooe; void testCaseSetup_1() { ooe.reset(new OneOfEach); @@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE(test_json_proto_1) { "Expected:\n" << expected_result << "\nGotten:\n" << result); } -static stdcxx::shared_ptr n; +static std::shared_ptr n; void testCaseSetup_2() { testCaseSetup_1(); @@ -107,7 +107,7 @@ BOOST_AUTO_TEST_CASE(test_json_proto_2) { "Expected:\n" << expected_result << "\nGotten:\n" << result); } -static stdcxx::shared_ptr hm; +static std::shared_ptr hm; void testCaseSetup_3() { testCaseSetup_2(); @@ -185,8 +185,8 @@ BOOST_AUTO_TEST_CASE(test_json_proto_3) { BOOST_AUTO_TEST_CASE(test_json_proto_4) { testCaseSetup_1(); - stdcxx::shared_ptr buffer(new TMemoryBuffer()); - stdcxx::shared_ptr proto(new TJSONProtocol(buffer)); + std::shared_ptr buffer(new TMemoryBuffer()); + std::shared_ptr proto(new TJSONProtocol(buffer)); ooe->write(proto.get()); OneOfEach ooe2; @@ -198,8 +198,8 @@ BOOST_AUTO_TEST_CASE(test_json_proto_4) { BOOST_AUTO_TEST_CASE(test_json_proto_5) { testCaseSetup_3(); - stdcxx::shared_ptr buffer(new TMemoryBuffer()); - stdcxx::shared_ptr proto(new TJSONProtocol(buffer)); + std::shared_ptr buffer(new TMemoryBuffer()); + std::shared_ptr proto(new TJSONProtocol(buffer)); hm->write(proto.get()); HolyMoley hm2; @@ -236,8 +236,8 @@ BOOST_AUTO_TEST_CASE(test_json_proto_6) { } BOOST_AUTO_TEST_CASE(test_json_proto_7) { - stdcxx::shared_ptr buffer(new TMemoryBuffer()); - stdcxx::shared_ptr proto(new TJSONProtocol(buffer)); + std::shared_ptr buffer(new TMemoryBuffer()); + std::shared_ptr proto(new TJSONProtocol(buffer)); Base64 base; base.a = 123; @@ -265,9 +265,9 @@ BOOST_AUTO_TEST_CASE(test_json_proto_8) { "\",3,1,2,3]}}"; const std::size_t bufSiz = strlen(json_string) * sizeof(char); - stdcxx::shared_ptr buffer(new TMemoryBuffer( + std::shared_ptr buffer(new TMemoryBuffer( (uint8_t*)(json_string), static_cast(bufSiz))); - stdcxx::shared_ptr proto(new TJSONProtocol(buffer)); + std::shared_ptr proto(new TJSONProtocol(buffer)); OneOfEach ooe2; @@ -294,9 +294,9 @@ BOOST_AUTO_TEST_CASE(test_json_unicode_escaped) { "\",3,1,2,3]}}"; const char* expected_zomg_unicode = "\xe0\xb8\x81 \xf0\x9d\x94\xbe"; - stdcxx::shared_ptr buffer(new TMemoryBuffer( + std::shared_ptr buffer(new TMemoryBuffer( (uint8_t*)(json_string), sizeof(json_string))); - stdcxx::shared_ptr proto(new TJSONProtocol(buffer)); + std::shared_ptr proto(new TJSONProtocol(buffer)); OneOfEach ooe2; ooe2.read(proto.get()); @@ -315,9 +315,9 @@ BOOST_AUTO_TEST_CASE(test_json_unicode_escaped_missing_low_surrogate) { ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64" "\",3,1,2,3]}}"; - stdcxx::shared_ptr buffer(new TMemoryBuffer( + std::shared_ptr buffer(new TMemoryBuffer( (uint8_t*)(json_string), sizeof(json_string))); - stdcxx::shared_ptr proto(new TJSONProtocol(buffer)); + std::shared_ptr proto(new TJSONProtocol(buffer)); OneOfEach ooe2; BOOST_CHECK_THROW(ooe2.read(proto.get()), @@ -333,9 +333,9 @@ BOOST_AUTO_TEST_CASE(test_json_unicode_escaped_missing_hi_surrogate) { ":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64" "\",3,1,2,3]}}"; - stdcxx::shared_ptr buffer(new TMemoryBuffer( + std::shared_ptr buffer(new TMemoryBuffer( (uint8_t*)(json_string), sizeof(json_string))); - stdcxx::shared_ptr proto(new TJSONProtocol(buffer)); + std::shared_ptr proto(new TJSONProtocol(buffer)); OneOfEach ooe2; BOOST_CHECK_THROW(ooe2.read(proto.get()), diff --git a/lib/cpp/test/OneWayHTTPTest.cpp b/lib/cpp/test/OneWayHTTPTest.cpp index 3fe63b612a4..89fa1643106 100644 --- a/lib/cpp/test/OneWayHTTPTest.cpp +++ b/lib/cpp/test/OneWayHTTPTest.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include "gen-cpp/OneWayService.h" @@ -54,7 +54,7 @@ using apache::thrift::transport::TMemoryBuffer; using apache::thrift::transport::TServerSocket; using apache::thrift::transport::TSocket; using apache::thrift::transport::TTransportException; -using apache::thrift::stdcxx::shared_ptr; +using std::shared_ptr; using std::cout; using std::cerr; using std::endl; @@ -138,7 +138,7 @@ class TServerReadyEventHandler : public TServerEventHandler, public Monitor { class TBlockableBufferedTransport : public TBufferedTransport { public: - TBlockableBufferedTransport(stdcxx::shared_ptr transport) + TBlockableBufferedTransport(std::shared_ptr transport) : TBufferedTransport(transport, 10240), blocked_(false) { } @@ -176,14 +176,14 @@ class TBlockableBufferedTransport : public TBufferedTransport { BOOST_AUTO_TEST_CASE( JSON_BufferedHTTP ) { - stdcxx::shared_ptr ss = stdcxx::make_shared(0) ; + std::shared_ptr ss = std::make_shared(0) ; TThreadedServer server( - stdcxx::make_shared(stdcxx::make_shared()), + std::make_shared(std::make_shared()), ss, //port - stdcxx::make_shared(), - stdcxx::make_shared()); + std::make_shared(), + std::make_shared()); - stdcxx::shared_ptr pEventHandler(new TServerReadyEventHandler) ; + std::shared_ptr pEventHandler(new TServerReadyEventHandler) ; server.setServerEventHandler(pEventHandler); #ifdef ENABLE_STDERR_LOGGING @@ -205,11 +205,11 @@ BOOST_AUTO_TEST_CASE( JSON_BufferedHTTP ) #endif { - stdcxx::shared_ptr socket(new TSocket("localhost", port)); + std::shared_ptr socket(new TSocket("localhost", port)); socket->setRecvTimeout(10000) ; // 1000msec should be enough - stdcxx::shared_ptr blockable_transport(new TBlockableBufferedTransport(socket)); - stdcxx::shared_ptr transport(new THttpClient(blockable_transport, "localhost", "/service")); - stdcxx::shared_ptr protocol(new TJSONProtocol(transport)); + std::shared_ptr blockable_transport(new TBlockableBufferedTransport(socket)); + std::shared_ptr transport(new THttpClient(blockable_transport, "localhost", "/service")); + std::shared_ptr protocol(new TJSONProtocol(transport)); onewaytest::OneWayServiceClient client(protocol); diff --git a/lib/cpp/test/OptionalRequiredTest.cpp b/lib/cpp/test/OptionalRequiredTest.cpp index 55fe249ecda..4c435469e92 100644 --- a/lib/cpp/test/OptionalRequiredTest.cpp +++ b/lib/cpp/test/OptionalRequiredTest.cpp @@ -40,7 +40,7 @@ template void trywrite(const Struct& s, bool should_work) { bool worked; try { - TBinaryProtocol protocol(stdcxx::shared_ptr(new TMemoryBuffer)); + TBinaryProtocol protocol(std::shared_ptr(new TMemoryBuffer)); s.write(&protocol); worked = true; } catch (TProtocolException & ex) { @@ -52,7 +52,7 @@ void trywrite(const Struct& s, bool should_work) { template void write_to_read(const Struct1& w, Struct2& r) { - TBinaryProtocol protocol(stdcxx::shared_ptr(new TMemoryBuffer)); + TBinaryProtocol protocol(std::shared_ptr(new TMemoryBuffer)); w.write(&protocol); r.read(&protocol); } @@ -303,7 +303,7 @@ BOOST_AUTO_TEST_CASE(test_optional_required_11) { o1.im_big.push_back(mymap); BOOST_CHECK(o1 == o2); - TBinaryProtocol protocol(stdcxx::shared_ptr(new TMemoryBuffer)); + TBinaryProtocol protocol(std::shared_ptr(new TMemoryBuffer)); o1.write(&protocol); o1.im_big.push_back(mymap); diff --git a/lib/cpp/test/RecursiveTest.cpp b/lib/cpp/test/RecursiveTest.cpp index ce5569bf7f5..15f234cfa1c 100644 --- a/lib/cpp/test/RecursiveTest.cpp +++ b/lib/cpp/test/RecursiveTest.cpp @@ -23,7 +23,7 @@ #include "gen-cpp/Recursive_types.h" #include -#include +#include #include #define BOOST_TEST_MODULE RecursiveTest @@ -31,7 +31,7 @@ using apache::thrift::transport::TMemoryBuffer; using apache::thrift::protocol::TBinaryProtocol; -using apache::thrift::stdcxx::shared_ptr; +using std::shared_ptr; BOOST_AUTO_TEST_CASE(test_recursive_1) { shared_ptr buf(new TMemoryBuffer()); diff --git a/lib/cpp/test/SecurityTest.cpp b/lib/cpp/test/SecurityTest.cpp index 51ee4272716..982a4f30c1e 100644 --- a/lib/cpp/test/SecurityTest.cpp +++ b/lib/cpp/test/SecurityTest.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -40,8 +40,8 @@ using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TTransportFactory; -using apache::thrift::stdcxx::bind; -using apache::thrift::stdcxx::shared_ptr; +using std::bind; +using std::shared_ptr; boost::filesystem::path keyDir; boost::filesystem::path certFile(const std::string& filename) diff --git a/lib/cpp/test/SpecializationTest.cpp b/lib/cpp/test/SpecializationTest.cpp index a060b4fcb59..008837d319c 100644 --- a/lib/cpp/test/SpecializationTest.cpp +++ b/lib/cpp/test/SpecializationTest.cpp @@ -82,8 +82,8 @@ BOOST_AUTO_TEST_CASE(test_specialization_1) { stage2.back().message = "nevermore"; hm.bonks["poe"] = stage2; - apache::thrift::stdcxx::shared_ptr buffer(new TMemoryBuffer()); - apache::thrift::stdcxx::shared_ptr proto(new MyProtocol(buffer)); + std::shared_ptr buffer(new TMemoryBuffer()); + std::shared_ptr proto(new MyProtocol(buffer)); ooe.write(proto.get()); OneOfEach ooe2; diff --git a/lib/cpp/test/TBufferBaseTest.cpp b/lib/cpp/test/TBufferBaseTest.cpp index 4201ddb7149..430302cc2ad 100644 --- a/lib/cpp/test/TBufferBaseTest.cpp +++ b/lib/cpp/test/TBufferBaseTest.cpp @@ -21,9 +21,9 @@ #include #include #include -#include +#include -using apache::thrift::stdcxx::shared_ptr; +using std::shared_ptr; using apache::thrift::transport::TMemoryBuffer; using apache::thrift::transport::TBufferedTransport; using apache::thrift::transport::TFramedTransport; diff --git a/lib/cpp/test/TMemoryBufferTest.cpp b/lib/cpp/test/TMemoryBufferTest.cpp index d81b1d80425..92068729517 100644 --- a/lib/cpp/test/TMemoryBufferTest.cpp +++ b/lib/cpp/test/TMemoryBufferTest.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include "gen-cpp/ThriftTest_types.h" @@ -31,7 +31,7 @@ BOOST_AUTO_TEST_SUITE(TMemoryBufferTest) using apache::thrift::protocol::TBinaryProtocol; using apache::thrift::transport::TMemoryBuffer; using apache::thrift::transport::TTransportException; -using apache::thrift::stdcxx::shared_ptr; +using std::shared_ptr; using std::cout; using std::endl; using std::string; diff --git a/lib/cpp/test/TNonblockingSSLServerTest.cpp b/lib/cpp/test/TNonblockingSSLServerTest.cpp index 2efb1409b2a..330380b3486 100644 --- a/lib/cpp/test/TNonblockingSSLServerTest.cpp +++ b/lib/cpp/test/TNonblockingSSLServerTest.cpp @@ -19,8 +19,6 @@ #define BOOST_TEST_MODULE TNonblockingSSLServerTest #include -#include -#include #include #include @@ -105,8 +103,8 @@ BOOST_GLOBAL_FIXTURE(GlobalFixtureSSL); BOOST_GLOBAL_FIXTURE(GlobalFixtureSSL) #endif -stdcxx::shared_ptr createServerSocketFactory() { - stdcxx::shared_ptr pServerSocketFactory; +std::shared_ptr createServerSocketFactory() { + std::shared_ptr pServerSocketFactory; pServerSocketFactory.reset(new TSSLSocketFactory()); pServerSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); @@ -116,8 +114,8 @@ stdcxx::shared_ptr createServerSocketFactory() { return pServerSocketFactory; } -stdcxx::shared_ptr createClientSocketFactory() { - stdcxx::shared_ptr pClientSocketFactory; +std::shared_ptr createClientSocketFactory() { + std::shared_ptr pClientSocketFactory; pClientSocketFactory.reset(new TSSLSocketFactory()); pClientSocketFactory->authenticate(true); @@ -145,12 +143,12 @@ class Fixture { struct Runner : public apache::thrift::concurrency::Runnable { int port; - stdcxx::shared_ptr userEventBase; - stdcxx::shared_ptr processor; - stdcxx::shared_ptr server; - stdcxx::shared_ptr listenHandler; - stdcxx::shared_ptr pServerSocketFactory; - stdcxx::shared_ptr socket; + std::shared_ptr userEventBase; + std::shared_ptr processor; + std::shared_ptr server; + std::shared_ptr listenHandler; + std::shared_ptr pServerSocketFactory; + std::shared_ptr socket; Mutex mutex_; Runner() { @@ -198,7 +196,7 @@ class Fixture { }; protected: - Fixture() : processor(new test::ParentServiceProcessor(stdcxx::make_shared())) {} + Fixture() : processor(new test::ParentServiceProcessor(std::make_shared())) {} ~Fixture() { if (server) { @@ -214,12 +212,12 @@ class Fixture { } int startServer(int port) { - stdcxx::shared_ptr runner(new Runner); + std::shared_ptr runner(new Runner); runner->port = port; runner->processor = processor; runner->userEventBase = userEventBase_; - apache::thrift::stdcxx::scoped_ptr threadFactory( + std::unique_ptr threadFactory( new apache::thrift::concurrency::PlatformThreadFactory( #if !USE_STD_THREAD concurrency::PlatformThreadFactory::OTHER, concurrency::PlatformThreadFactory::NORMAL, @@ -235,11 +233,11 @@ class Fixture { } bool canCommunicate(int serverPort) { - stdcxx::shared_ptr pClientSocketFactory = createClientSocketFactory(); - stdcxx::shared_ptr socket = pClientSocketFactory->createSocket("localhost", serverPort); + std::shared_ptr pClientSocketFactory = createClientSocketFactory(); + std::shared_ptr socket = pClientSocketFactory->createSocket("localhost", serverPort); socket->open(); - test::ParentServiceClient client(stdcxx::make_shared( - stdcxx::make_shared(socket))); + test::ParentServiceClient client(std::make_shared( + std::make_shared(socket))); client.addString("foo"); std::vector strings; client.getStrings(strings); @@ -247,12 +245,12 @@ class Fixture { } private: - stdcxx::shared_ptr userEventBase_; - stdcxx::shared_ptr processor; + std::shared_ptr userEventBase_; + std::shared_ptr processor; protected: - stdcxx::shared_ptr server; + std::shared_ptr server; private: - stdcxx::shared_ptr thread; + std::shared_ptr thread; }; diff --git a/lib/cpp/test/TNonblockingServerTest.cpp b/lib/cpp/test/TNonblockingServerTest.cpp index 5e10907b057..f0bb283ff7b 100644 --- a/lib/cpp/test/TNonblockingServerTest.cpp +++ b/lib/cpp/test/TNonblockingServerTest.cpp @@ -19,12 +19,12 @@ #define BOOST_TEST_MODULE TNonblockingServerTest #include +#include #include "thrift/concurrency/Monitor.h" #include "thrift/concurrency/Thread.h" #include "thrift/server/TNonblockingServer.h" #include "thrift/transport/TNonblockingServerSocket.h" -#include "thrift/stdcxx.h" #include "gen-cpp/ParentService.h" @@ -38,8 +38,8 @@ using apache::thrift::concurrency::Runnable; using apache::thrift::concurrency::Thread; using apache::thrift::concurrency::ThreadFactory; using apache::thrift::server::TServerEventHandler; -using apache::thrift::stdcxx::make_shared; -using apache::thrift::stdcxx::shared_ptr; +using std::make_shared; +using std::shared_ptr; using namespace apache::thrift; diff --git a/lib/cpp/test/TPipeInterruptTest.cpp b/lib/cpp/test/TPipeInterruptTest.cpp index 232e4bb73e8..2423f5646ec 100644 --- a/lib/cpp/test/TPipeInterruptTest.cpp +++ b/lib/cpp/test/TPipeInterruptTest.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include using apache::thrift::transport::TPipeServer; using apache::thrift::transport::TPipe; @@ -52,7 +52,7 @@ static void acceptWorker(TPipeServer *pipe) { { for (;;) { - stdcxx::shared_ptr temp = pipe->accept(); + std::shared_ptr temp = pipe->accept(); } } catch (...) {/*just want to make sure nothing crashes*/ } @@ -70,8 +70,8 @@ BOOST_AUTO_TEST_CASE(stress_pipe_accept_interruption) { { TPipeServer pipeServer("TPipeInterruptTest"); pipeServer.listen(); - boost::thread acceptThread(stdcxx::bind(acceptWorker, &pipeServer)); - boost::thread interruptThread(stdcxx::bind(interruptWorker, &pipeServer)); + boost::thread acceptThread(std::bind(acceptWorker, &pipeServer)); + boost::thread interruptThread(std::bind(interruptWorker, &pipeServer)); try { for (;;) diff --git a/lib/cpp/test/TPipedTransportTest.cpp b/lib/cpp/test/TPipedTransportTest.cpp index a3ce662a3ae..f3091a48779 100644 --- a/lib/cpp/test/TPipedTransportTest.cpp +++ b/lib/cpp/test/TPipedTransportTest.cpp @@ -18,7 +18,7 @@ */ #include -#include +#include #include #include @@ -31,9 +31,9 @@ using apache::thrift::transport::TMemoryBuffer; using namespace apache::thrift; BOOST_AUTO_TEST_CASE(test_read_write) { - stdcxx::shared_ptr underlying(new TMemoryBuffer); - stdcxx::shared_ptr pipe(new TMemoryBuffer); - stdcxx::shared_ptr trans(new TPipedTransport(underlying, pipe)); + std::shared_ptr underlying(new TMemoryBuffer); + std::shared_ptr pipe(new TMemoryBuffer); + std::shared_ptr trans(new TPipedTransport(underlying, pipe)); uint8_t buffer[4]; diff --git a/lib/cpp/test/TSSLSocketInterruptTest.cpp b/lib/cpp/test/TSSLSocketInterruptTest.cpp index 85f6c398dd1..33f686cefdd 100644 --- a/lib/cpp/test/TSSLSocketInterruptTest.cpp +++ b/lib/cpp/test/TSSLSocketInterruptTest.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #ifdef __linux__ @@ -37,8 +37,8 @@ using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; using apache::thrift::transport::TSSLSocketFactory; -using apache::thrift::stdcxx::static_pointer_cast; -using apache::thrift::stdcxx::shared_ptr; +using std::static_pointer_cast; +using std::shared_ptr; BOOST_AUTO_TEST_SUITE(TSSLSocketInterruptTest) @@ -146,7 +146,7 @@ BOOST_AUTO_TEST_CASE(test_ssl_interruptable_child_read_while_handshaking) { shared_ptr clientSock = pClientSocketFactory->createSocket("localhost", port); clientSock->open(); shared_ptr accepted = sock1.accept(); - boost::thread readThread(apache::thrift::stdcxx::bind(readerWorkerMustThrow, accepted)); + boost::thread readThread(std::bind(readerWorkerMustThrow, accepted)); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // readThread is practically guaranteed to be blocking now sock1.interruptChildren(); @@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE(test_ssl_interruptable_child_read) { shared_ptr clientSock = pClientSocketFactory->createSocket("localhost", port); clientSock->open(); shared_ptr accepted = sock1.accept(); - boost::thread readThread(apache::thrift::stdcxx::bind(readerWorkerMustThrow, accepted)); + boost::thread readThread(std::bind(readerWorkerMustThrow, accepted)); clientSock->write((const uint8_t*)"0", 1); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // readThread is practically guaranteed to be blocking now @@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE(test_ssl_non_interruptable_child_read) { clientSock->open(); shared_ptr accepted = sock1.accept(); static_pointer_cast(accepted)->setRecvTimeout(1000); - boost::thread readThread(apache::thrift::stdcxx::bind(readerWorker, accepted, 0)); + boost::thread readThread(std::bind(readerWorker, accepted, 0)); clientSock->write((const uint8_t*)"0", 1); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // readThread is practically guaranteed to be blocking here @@ -241,7 +241,7 @@ BOOST_AUTO_TEST_CASE(test_ssl_interruptable_child_peek) { shared_ptr clientSock = pClientSocketFactory->createSocket("localhost", port); clientSock->open(); shared_ptr accepted = sock1.accept(); - boost::thread peekThread(apache::thrift::stdcxx::bind(peekerWorkerInterrupt, accepted)); + boost::thread peekThread(std::bind(peekerWorkerInterrupt, accepted)); clientSock->write((const uint8_t*)"0", 1); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // peekThread is practically guaranteed to be blocking now @@ -264,7 +264,7 @@ BOOST_AUTO_TEST_CASE(test_ssl_non_interruptable_child_peek) { clientSock->open(); shared_ptr accepted = sock1.accept(); static_pointer_cast(accepted)->setRecvTimeout(1000); - boost::thread peekThread(apache::thrift::stdcxx::bind(peekerWorker, accepted, false)); + boost::thread peekThread(std::bind(peekerWorker, accepted, false)); clientSock->write((const uint8_t*)"0", 1); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // peekThread is practically guaranteed to be blocking now diff --git a/lib/cpp/test/TServerIntegrationTest.cpp b/lib/cpp/test/TServerIntegrationTest.cpp index 5f7b2e88b88..3723679123c 100644 --- a/lib/cpp/test/TServerIntegrationTest.cpp +++ b/lib/cpp/test/TServerIntegrationTest.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include #include @@ -55,9 +55,9 @@ using apache::thrift::server::TServerEventHandler; using apache::thrift::server::TSimpleServer; using apache::thrift::server::TThreadPoolServer; using apache::thrift::server::TThreadedServer; -using apache::thrift::stdcxx::dynamic_pointer_cast; -using apache::thrift::stdcxx::make_shared; -using apache::thrift::stdcxx::shared_ptr; +using std::dynamic_pointer_cast; +using std::make_shared; +using std::shared_ptr; using apache::thrift::test::ParentServiceClient; using apache::thrift::test::ParentServiceIf; using apache::thrift::test::ParentServiceIfFactory; @@ -177,7 +177,7 @@ class TServerIntegrationTestFixture { } void startServer() { - pServerThread.reset(new boost::thread(apache::thrift::stdcxx::bind(&TServerType::serve, pServer.get()))); + pServerThread.reset(new boost::thread(std::bind(&TServerType::serve, pServer.get()))); // block until listen() completes so clients will be able to connect Synchronized sync(*(pEventHandler.get())); @@ -235,7 +235,7 @@ class TServerIntegrationTestFixture { pClientSock->open(); client.incrementGeneration(); holdThreads.push_back(shared_ptr( - new boost::thread(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose, + new boost::thread(std::bind(&TServerIntegrationTestFixture::delayClose, this, pClientSock, milliseconds(10 * numToMake))))); @@ -284,7 +284,7 @@ class TServerIntegrationTestFixture { std::vector > holdThreads; for (int64_t i = 0; i < numToMake; ++i) { holdThreads.push_back(shared_ptr( - new boost::thread(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::stressor, this)))); + new boost::thread(std::bind(&TServerIntegrationTestFixture::stressor, this)))); } boost::this_thread::sleep(duration); @@ -479,11 +479,11 @@ BOOST_AUTO_TEST_CASE(test_stop_with_uninterruptable_clients_connected) { // Ensure they have been accepted blockUntilAccepted(2); - boost::thread t1(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose, + boost::thread t1(std::bind(&TServerIntegrationTestFixture::delayClose, this, pClientSock1, milliseconds(250))); - boost::thread t2(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose, + boost::thread t2(std::bind(&TServerIntegrationTestFixture::delayClose, this, pClientSock2, milliseconds(250))); @@ -517,7 +517,7 @@ BOOST_AUTO_TEST_CASE(test_concurrent_client_limit) { BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount()); // a third client cannot connect until one of the other two closes - boost::thread t2(apache::thrift::stdcxx::bind(&TServerIntegrationTestFixture::delayClose, + boost::thread t2(std::bind(&TServerIntegrationTestFixture::delayClose, this, pClientSock2, milliseconds(250))); diff --git a/lib/cpp/test/TServerSocketTest.cpp b/lib/cpp/test/TServerSocketTest.cpp index a191147eb17..bec6d475626 100644 --- a/lib/cpp/test/TServerSocketTest.cpp +++ b/lib/cpp/test/TServerSocketTest.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include "TTransportCheckThrow.h" #include @@ -28,7 +28,7 @@ using apache::thrift::transport::TServerSocket; using apache::thrift::transport::TSocket; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; -using apache::thrift::stdcxx::shared_ptr; +using std::shared_ptr; BOOST_AUTO_TEST_SUITE(TServerSocketTest) diff --git a/lib/cpp/test/TServerTransportTest.cpp b/lib/cpp/test/TServerTransportTest.cpp index dc6aede87ca..539bd28cdc0 100644 --- a/lib/cpp/test/TServerTransportTest.cpp +++ b/lib/cpp/test/TServerTransportTest.cpp @@ -20,12 +20,12 @@ #include #include #include -#include +#include using apache::thrift::transport::TServerTransport; using apache::thrift::transport::TTransport; using apache::thrift::transport::TTransportException; -using apache::thrift::stdcxx::shared_ptr; +using std::shared_ptr; BOOST_AUTO_TEST_SUITE(TServerTransportTest) diff --git a/lib/cpp/test/TSocketInterruptTest.cpp b/lib/cpp/test/TSocketInterruptTest.cpp index 3a189cce52a..366242f7cd7 100644 --- a/lib/cpp/test/TSocketInterruptTest.cpp +++ b/lib/cpp/test/TSocketInterruptTest.cpp @@ -25,7 +25,7 @@ #include #include #include -#include +#include using apache::thrift::transport::TServerSocket; using apache::thrift::transport::TSocket; @@ -35,12 +35,12 @@ using namespace apache::thrift; BOOST_AUTO_TEST_SUITE(TSocketInterruptTest) -void readerWorker(stdcxx::shared_ptr tt, uint32_t expectedResult) { +void readerWorker(std::shared_ptr tt, uint32_t expectedResult) { uint8_t buf[4]; BOOST_CHECK_EQUAL(expectedResult, tt->read(buf, 4)); } -void readerWorkerMustThrow(stdcxx::shared_ptr tt) { +void readerWorkerMustThrow(std::shared_ptr tt) { try { uint8_t buf[4]; tt->read(buf, 4); @@ -56,8 +56,8 @@ BOOST_AUTO_TEST_CASE(test_interruptable_child_read) { int port = sock1.getPort(); TSocket clientSock("localhost", port); clientSock.open(); - stdcxx::shared_ptr accepted = sock1.accept(); - boost::thread readThread(stdcxx::bind(readerWorkerMustThrow, accepted)); + std::shared_ptr accepted = sock1.accept(); + boost::thread readThread(std::bind(readerWorkerMustThrow, accepted)); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // readThread is practically guaranteed to be blocking now sock1.interruptChildren(); @@ -75,8 +75,8 @@ BOOST_AUTO_TEST_CASE(test_non_interruptable_child_read) { int port = sock1.getPort(); TSocket clientSock("localhost", port); clientSock.open(); - stdcxx::shared_ptr accepted = sock1.accept(); - boost::thread readThread(stdcxx::bind(readerWorker, accepted, 0)); + std::shared_ptr accepted = sock1.accept(); + boost::thread readThread(std::bind(readerWorker, accepted, 0)); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // readThread is practically guaranteed to be blocking here sock1.interruptChildren(); @@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE(test_cannot_change_after_listen) { sock1.close(); } -void peekerWorker(stdcxx::shared_ptr tt, bool expectedResult) { +void peekerWorker(std::shared_ptr tt, bool expectedResult) { BOOST_CHECK_EQUAL(expectedResult, tt->peek()); } @@ -107,9 +107,9 @@ BOOST_AUTO_TEST_CASE(test_interruptable_child_peek) { int port = sock1.getPort(); TSocket clientSock("localhost", port); clientSock.open(); - stdcxx::shared_ptr accepted = sock1.accept(); + std::shared_ptr accepted = sock1.accept(); // peek() will return false if child is interrupted - boost::thread peekThread(stdcxx::bind(peekerWorker, accepted, false)); + boost::thread peekThread(std::bind(peekerWorker, accepted, false)); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // peekThread is practically guaranteed to be blocking now sock1.interruptChildren(); @@ -127,9 +127,9 @@ BOOST_AUTO_TEST_CASE(test_non_interruptable_child_peek) { int port = sock1.getPort(); TSocket clientSock("localhost", port); clientSock.open(); - stdcxx::shared_ptr accepted = sock1.accept(); + std::shared_ptr accepted = sock1.accept(); // peek() will return false when remote side is closed - boost::thread peekThread(stdcxx::bind(peekerWorker, accepted, false)); + boost::thread peekThread(std::bind(peekerWorker, accepted, false)); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); // peekThread is practically guaranteed to be blocking now sock1.interruptChildren(); diff --git a/lib/cpp/test/TransportTest.cpp b/lib/cpp/test/TransportTest.cpp index d6ab457e2f7..ce1954469c6 100644 --- a/lib/cpp/test/TransportTest.cpp +++ b/lib/cpp/test/TransportTest.cpp @@ -26,7 +26,6 @@ #endif #include #include -#include #include #include @@ -114,7 +113,7 @@ class GenericSizeGenerator : public SizeGenerator { std::string describe() const { return generator_->describe(); } private: - stdcxx::shared_ptr generator_; + std::shared_ptr generator_; }; /************************************************************************** @@ -137,8 +136,8 @@ class CoupledTransports { CoupledTransports() : in(), out() {} - stdcxx::shared_ptr in; - stdcxx::shared_ptr out; + std::shared_ptr in; + std::shared_ptr out; private: CoupledTransports(const CoupledTransports&); @@ -155,7 +154,7 @@ class CoupledMemoryBuffers : public CoupledTransports { out = buf; } - stdcxx::shared_ptr buf; + std::shared_ptr buf; }; /** @@ -341,11 +340,11 @@ class CoupledBufferBases : public CoupledTransports { **************************************************************************/ struct TriggerInfo { - TriggerInfo(int seconds, const stdcxx::shared_ptr& transport, uint32_t writeLength) + TriggerInfo(int seconds, const std::shared_ptr& transport, uint32_t writeLength) : timeoutSeconds(seconds), transport(transport), writeLength(writeLength), next(NULL) {} int timeoutSeconds; - stdcxx::shared_ptr transport; + std::shared_ptr transport; uint32_t writeLength; TriggerInfo* next; }; @@ -420,7 +419,7 @@ void alarm_handler_wrapper() { * to the end.) */ void add_trigger(unsigned int seconds, - const stdcxx::shared_ptr& transport, + const std::shared_ptr& transport, uint32_t write_len) { TriggerInfo* info = new TriggerInfo(seconds, transport, write_len); { @@ -460,7 +459,7 @@ void clear_triggers() { } void set_trigger(unsigned int seconds, - const stdcxx::shared_ptr& transport, + const std::shared_ptr& transport, uint32_t write_len) { clear_triggers(); add_trigger(seconds, transport, write_len); @@ -976,11 +975,11 @@ class TransportTestGen { << rChunkSizeGen.describe() << ", " << maxOutstanding << ")"; #if (BOOST_VERSION >= 105900) - stdcxx::function test_func + std::function test_func #else boost::unit_test::callback0<> test_func #endif - = stdcxx::bind(test_rw, + = std::bind(test_rw, totalSize, wSizeGen, rSizeGen, @@ -1026,7 +1025,7 @@ class TransportTestGen { **************************************************************************/ struct global_fixture { - stdcxx::shared_ptr alarmThread_; + std::shared_ptr alarmThread_; global_fixture() { #if _WIN32 apache::thrift::transport::TWinsockSingleton::create(); diff --git a/lib/cpp/test/ZlibTest.cpp b/lib/cpp/test/ZlibTest.cpp index ea54487ebe6..c8268149e3b 100644 --- a/lib/cpp/test/ZlibTest.cpp +++ b/lib/cpp/test/ZlibTest.cpp @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include #include @@ -47,7 +47,7 @@ #include using namespace apache::thrift::transport; -using apache::thrift::stdcxx::shared_ptr; +using std::shared_ptr; using std::string; boost::mt19937 rng; @@ -347,8 +347,8 @@ void test_get_underlying_transport() { do { \ ::std::ostringstream name_ss; \ name_ss << name << "-" << BOOST_STRINGIZE(_FUNC); \ - ::apache::thrift::stdcxx::function test_func = \ - ::apache::thrift::stdcxx::bind(_FUNC, ##__VA_ARGS__); \ + ::std::function test_func = \ + ::std::bind(_FUNC, ##__VA_ARGS__); \ ::boost::unit_test::test_case* tc \ = ::boost::unit_test::make_test_case(test_func, name_ss.str(), __FILE__, __LINE__); \ (suite)->add(tc); \ @@ -359,7 +359,7 @@ void test_get_underlying_transport() { ::std::ostringstream name_ss; \ name_ss << name << "-" << BOOST_STRINGIZE(_FUNC); \ ::boost::unit_test::test_case* tc \ - = ::boost::unit_test::make_test_case(::apache::thrift::stdcxx::bind(_FUNC, \ + = ::boost::unit_test::make_test_case(::std::bind(_FUNC, \ ##__VA_ARGS__), \ name_ss.str()); \ (suite)->add(tc); \ diff --git a/lib/cpp/test/concurrency/RWMutexStarveTest.cpp b/lib/cpp/test/concurrency/RWMutexStarveTest.cpp index 849e078bd2a..985a230a05f 100644 --- a/lib/cpp/test/concurrency/RWMutexStarveTest.cpp +++ b/lib/cpp/test/concurrency/RWMutexStarveTest.cpp @@ -23,9 +23,9 @@ #include "thrift/concurrency/Mutex.h" #include "thrift/concurrency/PosixThreadFactory.h" -#include +#include -using apache::thrift::stdcxx::shared_ptr; +using std::shared_ptr; using boost::unit_test::test_suite; using boost::unit_test::framework::master_test_suite; diff --git a/lib/cpp/test/concurrency/ThreadFactoryTests.h b/lib/cpp/test/concurrency/ThreadFactoryTests.h index 48330f374c0..ba9850286cb 100644 --- a/lib/cpp/test/concurrency/ThreadFactoryTests.h +++ b/lib/cpp/test/concurrency/ThreadFactoryTests.h @@ -33,7 +33,7 @@ namespace thrift { namespace concurrency { namespace test { -using stdcxx::shared_ptr; +using std::shared_ptr; using namespace apache::thrift::concurrency; /** diff --git a/lib/cpp/test/concurrency/ThreadManagerTests.h b/lib/cpp/test/concurrency/ThreadManagerTests.h index 15a43ffae00..d6c092d6cc5 100644 --- a/lib/cpp/test/concurrency/ThreadManagerTests.h +++ b/lib/cpp/test/concurrency/ThreadManagerTests.h @@ -36,8 +36,8 @@ namespace test { using namespace apache::thrift::concurrency; -static std::deque > m_expired; -static void expiredNotifier(stdcxx::shared_ptr runnable) +static std::deque > m_expired; +static void expiredNotifier(std::shared_ptr runnable) { m_expired.push_back(runnable); } @@ -452,7 +452,7 @@ class ThreadManagerTests { std::cout << "\t\t\t\tstarting.. " << std::endl; threadManager->start(); - threadManager->setExpireCallback(expiredNotifier); // apache::thrift::stdcxx::bind(&ThreadManagerTests::expiredNotifier, this)); + threadManager->setExpireCallback(expiredNotifier); // std::bind(&ThreadManagerTests::expiredNotifier, this)); #define EXPECT(FUNC, COUNT) { size_t c = FUNC; if (c != COUNT) { std::cerr << "expected " #FUNC" to be " #COUNT ", but was " << c << std::endl; return false; } } diff --git a/lib/cpp/test/processor/Handlers.h b/lib/cpp/test/processor/Handlers.h index ad47229ad05..29784d84591 100644 --- a/lib/cpp/test/processor/Handlers.h +++ b/lib/cpp/test/processor/Handlers.h @@ -29,7 +29,7 @@ namespace test { class ParentHandler : virtual public ParentServiceIf { public: - ParentHandler(const stdcxx::shared_ptr& log) + ParentHandler(const std::shared_ptr& log) : triggerMonitor(&mutex_), generation_(0), wait_(false), log_(log) {} int32_t incrementGeneration() { @@ -136,7 +136,7 @@ class ParentHandler : virtual public ParentServiceIf { int32_t generation_; bool wait_; std::vector strings_; - stdcxx::shared_ptr log_; + std::shared_ptr log_; }; #ifdef _WIN32 @@ -146,7 +146,7 @@ class ParentHandler : virtual public ParentServiceIf { class ChildHandler : public ParentHandler, virtual public ChildServiceIf { public: - ChildHandler(const stdcxx::shared_ptr& log) : ParentHandler(log), value_(0) {} + ChildHandler(const std::shared_ptr& log) : ParentHandler(log), value_(0) {} int32_t setValue(const int32_t value) { concurrency::Guard g(mutex_); @@ -174,13 +174,13 @@ class ChildHandler : public ParentHandler, virtual public ChildServiceIf { struct ConnContext { public: - ConnContext(stdcxx::shared_ptr in, - stdcxx::shared_ptr out, + ConnContext(std::shared_ptr in, + std::shared_ptr out, uint32_t id) : input(in), output(out), id(id) {} - stdcxx::shared_ptr input; - stdcxx::shared_ptr output; + std::shared_ptr input; + std::shared_ptr output; uint32_t id; }; @@ -196,12 +196,12 @@ struct CallContext { class ServerEventHandler : public server::TServerEventHandler { public: - ServerEventHandler(const stdcxx::shared_ptr& log) : nextId_(1), log_(log) {} + ServerEventHandler(const std::shared_ptr& log) : nextId_(1), log_(log) {} virtual void preServe() {} - virtual void* createContext(stdcxx::shared_ptr input, - stdcxx::shared_ptr output) { + virtual void* createContext(std::shared_ptr input, + std::shared_ptr output) { ConnContext* context = new ConnContext(input, output, nextId_); ++nextId_; log_->append(EventLog::ET_CONN_CREATED, context->id, 0); @@ -209,8 +209,8 @@ class ServerEventHandler : public server::TServerEventHandler { } virtual void deleteContext(void* serverContext, - stdcxx::shared_ptr input, - stdcxx::shared_ptr output) { + std::shared_ptr input, + std::shared_ptr output) { ConnContext* context = reinterpret_cast(serverContext); if (input != context->input) { @@ -226,7 +226,7 @@ class ServerEventHandler : public server::TServerEventHandler { } virtual void processContext(void* serverContext, - stdcxx::shared_ptr transport) { + std::shared_ptr transport) { // TODO: We currently don't test the behavior of the processContext() // calls. The various server implementations call processContext() at // slightly different times, and it is too annoying to try and account for @@ -251,12 +251,12 @@ class ServerEventHandler : public server::TServerEventHandler { protected: uint32_t nextId_; - stdcxx::shared_ptr log_; + std::shared_ptr log_; }; class ProcessorEventHandler : public TProcessorEventHandler { public: - ProcessorEventHandler(const stdcxx::shared_ptr& log) : nextId_(1), log_(log) {} + ProcessorEventHandler(const std::shared_ptr& log) : nextId_(1), log_(log) {} void* getContext(const char* fnName, void* serverContext) { ConnContext* connContext = reinterpret_cast(serverContext); @@ -329,7 +329,7 @@ class ProcessorEventHandler : public TProcessorEventHandler { } uint32_t nextId_; - stdcxx::shared_ptr log_; + std::shared_ptr log_; }; } } diff --git a/lib/cpp/test/processor/ProcessorTest.cpp b/lib/cpp/test/processor/ProcessorTest.cpp index c9e186face9..36ce0131190 100644 --- a/lib/cpp/test/processor/ProcessorTest.cpp +++ b/lib/cpp/test/processor/ProcessorTest.cpp @@ -57,13 +57,13 @@ class TSimpleServerTraits { public: typedef TSimpleServer ServerType; - stdcxx::shared_ptr createServer( - const stdcxx::shared_ptr& processor, + std::shared_ptr createServer( + const std::shared_ptr& processor, uint16_t port, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory) { - stdcxx::shared_ptr socket(new TServerSocket(port)); - return stdcxx::shared_ptr( + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory) { + std::shared_ptr socket(new TServerSocket(port)); + return std::shared_ptr( new TSimpleServer(processor, socket, transportFactory, protocolFactory)); } }; @@ -72,13 +72,13 @@ class TThreadedServerTraits { public: typedef TThreadedServer ServerType; - stdcxx::shared_ptr createServer( - const stdcxx::shared_ptr& processor, + std::shared_ptr createServer( + const std::shared_ptr& processor, uint16_t port, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory) { - stdcxx::shared_ptr socket(new TServerSocket(port)); - return stdcxx::shared_ptr( + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory) { + std::shared_ptr socket(new TServerSocket(port)); + return std::shared_ptr( new TThreadedServer(processor, socket, transportFactory, protocolFactory)); } }; @@ -87,19 +87,19 @@ class TThreadPoolServerTraits { public: typedef TThreadPoolServer ServerType; - stdcxx::shared_ptr createServer( - const stdcxx::shared_ptr& processor, + std::shared_ptr createServer( + const std::shared_ptr& processor, uint16_t port, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory) { - stdcxx::shared_ptr socket(new TServerSocket(port)); + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory) { + std::shared_ptr socket(new TServerSocket(port)); - stdcxx::shared_ptr threadFactory(new PlatformThreadFactory); - stdcxx::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(8); + std::shared_ptr threadFactory(new PlatformThreadFactory); + std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(8); threadManager->threadFactory(threadFactory); threadManager->start(); - return stdcxx::shared_ptr( + return std::shared_ptr( new TThreadPoolServer(processor, socket, transportFactory, protocolFactory, threadManager)); } }; @@ -108,11 +108,11 @@ class TNonblockingServerTraits { public: typedef TNonblockingServer ServerType; - stdcxx::shared_ptr createServer( - const stdcxx::shared_ptr& processor, + std::shared_ptr createServer( + const std::shared_ptr& processor, uint16_t port, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory) { + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory) { // TNonblockingServer automatically uses TFramedTransport. // Raise an exception if the supplied transport factory is not a // TFramedTransportFactory @@ -122,13 +122,13 @@ class TNonblockingServerTraits { throw TException("TNonblockingServer must use TFramedTransport"); } - stdcxx::shared_ptr socket(new TNonblockingServerSocket(port)); - stdcxx::shared_ptr threadFactory(new PlatformThreadFactory); - stdcxx::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(8); + std::shared_ptr socket(new TNonblockingServerSocket(port)); + std::shared_ptr threadFactory(new PlatformThreadFactory); + std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(8); threadManager->threadFactory(threadFactory); threadManager->start(); - return stdcxx::shared_ptr( + return std::shared_ptr( new TNonblockingServer(processor, protocolFactory, socket, threadManager)); } }; @@ -137,11 +137,11 @@ class TNonblockingServerNoThreadsTraits { public: typedef TNonblockingServer ServerType; - stdcxx::shared_ptr createServer( - const stdcxx::shared_ptr& processor, + std::shared_ptr createServer( + const std::shared_ptr& processor, uint16_t port, - const stdcxx::shared_ptr& transportFactory, - const stdcxx::shared_ptr& protocolFactory) { + const std::shared_ptr& transportFactory, + const std::shared_ptr& protocolFactory) { // TNonblockingServer automatically uses TFramedTransport. // Raise an exception if the supplied transport factory is not a // TFramedTransportFactory @@ -151,10 +151,10 @@ class TNonblockingServerNoThreadsTraits { throw TException("TNonblockingServer must use TFramedTransport"); } - stdcxx::shared_ptr socket(new TNonblockingServerSocket(port)); + std::shared_ptr socket(new TNonblockingServerSocket(port)); // Use a NULL ThreadManager - stdcxx::shared_ptr threadManager; - return stdcxx::shared_ptr( + std::shared_ptr threadManager; + return std::shared_ptr( new TNonblockingServer(processor, protocolFactory, socket, threadManager)); } }; @@ -244,48 +244,48 @@ class ServiceState : public ServerState { processor_->setEventHandler(processorEventHandler_); } - stdcxx::shared_ptr createServer(uint16_t port) { + std::shared_ptr createServer(uint16_t port) { ServerTraits_ serverTraits; return serverTraits.createServer(processor_, port, transportFactory_, protocolFactory_); } - stdcxx::shared_ptr getServerEventHandler() { return serverEventHandler_; } + std::shared_ptr getServerEventHandler() { return serverEventHandler_; } void bindSuccessful(uint16_t port) { port_ = port; } uint16_t getPort() const { return port_; } - const stdcxx::shared_ptr& getLog() const { return log_; } + const std::shared_ptr& getLog() const { return log_; } - const stdcxx::shared_ptr& getHandler() const { return handler_; } + const std::shared_ptr& getHandler() const { return handler_; } - stdcxx::shared_ptr createClient() { + std::shared_ptr createClient() { typedef typename ServiceTraits_::Protocol Protocol; - stdcxx::shared_ptr socket(new TSocket("127.0.0.1", port_)); - stdcxx::shared_ptr transport(new Transport_(socket)); - stdcxx::shared_ptr protocol(new Protocol(transport)); + std::shared_ptr socket(new TSocket("127.0.0.1", port_)); + std::shared_ptr transport(new Transport_(socket)); + std::shared_ptr protocol(new Protocol(transport)); transport->open(); - stdcxx::shared_ptr client(new Client(protocol)); + std::shared_ptr client(new Client(protocol)); return client; } private: uint16_t port_; - stdcxx::shared_ptr log_; - stdcxx::shared_ptr handler_; - stdcxx::shared_ptr processor_; - stdcxx::shared_ptr transportFactory_; - stdcxx::shared_ptr protocolFactory_; - stdcxx::shared_ptr serverEventHandler_; - stdcxx::shared_ptr processorEventHandler_; + std::shared_ptr log_; + std::shared_ptr handler_; + std::shared_ptr processor_; + std::shared_ptr transportFactory_; + std::shared_ptr protocolFactory_; + std::shared_ptr serverEventHandler_; + std::shared_ptr processorEventHandler_; }; /** * Check that there are no more events in the log */ -void checkNoEvents(const stdcxx::shared_ptr& log) { +void checkNoEvents(const std::shared_ptr& log) { // Wait for an event with a very short timeout period. We don't expect // anything to be present, so we will normally wait for the full timeout. // On the other hand, a non-zero timeout is nice since it does give a short @@ -299,7 +299,7 @@ void checkNoEvents(const stdcxx::shared_ptr& log) { * * Returns the connection ID allocated by the server. */ -uint32_t checkNewConnEvents(const stdcxx::shared_ptr& log) { +uint32_t checkNewConnEvents(const std::shared_ptr& log) { // Check for an ET_CONN_CREATED event Event event = log->waitForEvent(2500); BOOST_CHECK_EQUAL(EventLog::ET_CONN_CREATED, event.type); @@ -314,7 +314,7 @@ uint32_t checkNewConnEvents(const stdcxx::shared_ptr& log) { /** * Check for the events that should be logged when a connection is closed. */ -void checkCloseEvents(const stdcxx::shared_ptr& log, uint32_t connId) { +void checkCloseEvents(const std::shared_ptr& log, uint32_t connId) { // Check for an ET_CONN_DESTROYED event Event event = log->waitForEvent(); BOOST_CHECK_EQUAL(EventLog::ET_CONN_DESTROYED, event.type); @@ -332,7 +332,7 @@ void checkCloseEvents(const stdcxx::shared_ptr& log, uint32_t connId) * * Returns the call ID allocated by the server. */ -uint32_t checkCallHandlerEvents(const stdcxx::shared_ptr& log, +uint32_t checkCallHandlerEvents(const std::shared_ptr& log, uint32_t connId, EventType callType, const string& callName) { @@ -369,7 +369,7 @@ uint32_t checkCallHandlerEvents(const stdcxx::shared_ptr& log, /** * Check for the events that should be after a handler returns. */ -void checkCallPostHandlerEvents(const stdcxx::shared_ptr& log, +void checkCallPostHandlerEvents(const std::shared_ptr& log, uint32_t connId, uint32_t callId, const string& callName) { @@ -409,7 +409,7 @@ void checkCallPostHandlerEvents(const stdcxx::shared_ptr& log, * * Returns the call ID allocated by the server. */ -uint32_t checkCallEvents(const stdcxx::shared_ptr& log, +uint32_t checkCallEvents(const std::shared_ptr& log, uint32_t connId, EventType callType, const string& callName) { @@ -424,8 +424,8 @@ uint32_t checkCallEvents(const stdcxx::shared_ptr& log, */ template -void testParentService(const stdcxx::shared_ptr& state) { - stdcxx::shared_ptr client = state->createClient(); +void testParentService(const std::shared_ptr& state) { + std::shared_ptr client = state->createClient(); int32_t gen = client->getGeneration(); int32_t newGen = client->incrementGeneration(); @@ -446,8 +446,8 @@ void testParentService(const stdcxx::shared_ptr& state) { } template -void testChildService(const stdcxx::shared_ptr& state) { - stdcxx::shared_ptr client = state->createClient(); +void testChildService(const std::shared_ptr& state) { + std::shared_ptr client = state->createClient(); // Test calling some of the parent methids via the a child client int32_t gen = client->getGeneration(); @@ -468,7 +468,7 @@ void testBasicService() { typedef ServiceState > State; // Start the server - stdcxx::shared_ptr state(new State); + std::shared_ptr state(new State); ServerThread serverThread(state, true); testParentService(state); @@ -479,7 +479,7 @@ void testInheritedService() { typedef ServiceState > State; // Start the server - stdcxx::shared_ptr state(new State); + std::shared_ptr state(new State); ServerThread serverThread(state, true); testParentService(state); @@ -502,10 +502,10 @@ void testEventSequencing() { TBufferedTransport> State; // Start the server - stdcxx::shared_ptr state(new State); + std::shared_ptr state(new State); ServerThread serverThread(state, true); - const stdcxx::shared_ptr& log = state->getLog(); + const std::shared_ptr& log = state->getLog(); // Make sure we're at the end of the log checkNoEvents(log); @@ -514,7 +514,7 @@ void testEventSequencing() { // Make sure createContext() is called after a connection has been // established. We open a plain socket instead of creating a client. - stdcxx::shared_ptr socket(new TSocket("127.0.0.1", state->getPort())); + std::shared_ptr socket(new TSocket("127.0.0.1", state->getPort())); socket->open(); // Make sure the proper events occurred after a new connection @@ -635,19 +635,19 @@ void testSeparateConnections() { typedef ServiceState > State; // Start the server - stdcxx::shared_ptr state(new State); + std::shared_ptr state(new State); ServerThread serverThread(state, true); - const stdcxx::shared_ptr& log = state->getLog(); + const std::shared_ptr& log = state->getLog(); // Create a client - stdcxx::shared_ptr client1 = state->createClient(); + std::shared_ptr client1 = state->createClient(); // Make sure the expected events were logged uint32_t client1Id = checkNewConnEvents(log); // Create a second client - stdcxx::shared_ptr client2 = state->createClient(); + std::shared_ptr client2 = state->createClient(); // Make sure the expected events were logged uint32_t client2Id = checkNewConnEvents(log); @@ -683,13 +683,13 @@ void testOnewayCall() { typedef ServiceState > State; // Start the server - stdcxx::shared_ptr state(new State); + std::shared_ptr state(new State); ServerThread serverThread(state, true); - const stdcxx::shared_ptr& log = state->getLog(); + const std::shared_ptr& log = state->getLog(); // Create a client - stdcxx::shared_ptr client = state->createClient(); + std::shared_ptr client = state->createClient(); uint32_t connId = checkNewConnEvents(log); // Make a oneway call @@ -735,13 +735,13 @@ void testExpectedError() { typedef ServiceState > State; // Start the server - stdcxx::shared_ptr state(new State); + std::shared_ptr state(new State); ServerThread serverThread(state, true); - const stdcxx::shared_ptr& log = state->getLog(); + const std::shared_ptr& log = state->getLog(); // Create a client - stdcxx::shared_ptr client = state->createClient(); + std::shared_ptr client = state->createClient(); uint32_t connId = checkNewConnEvents(log); // Send the exceptionWait() call @@ -790,13 +790,13 @@ void testUnexpectedError() { typedef ServiceState > State; // Start the server - stdcxx::shared_ptr state(new State); + std::shared_ptr state(new State); ServerThread serverThread(state, true); - const stdcxx::shared_ptr& log = state->getLog(); + const std::shared_ptr& log = state->getLog(); // Create a client - stdcxx::shared_ptr client = state->createClient(); + std::shared_ptr client = state->createClient(); uint32_t connId = checkNewConnEvents(log); // Send the unexpectedExceptionWait() call diff --git a/lib/cpp/test/processor/ServerThread.cpp b/lib/cpp/test/processor/ServerThread.cpp index e752d5e1dc8..4d1ec4c1dbc 100644 --- a/lib/cpp/test/processor/ServerThread.cpp +++ b/lib/cpp/test/processor/ServerThread.cpp @@ -130,7 +130,7 @@ void ServerThread::preServe() { serverState_->bindSuccessful(port_); // Set the real server event handler (replacing ourself) - stdcxx::shared_ptr serverEventHandler + std::shared_ptr serverEventHandler = serverState_->getServerEventHandler(); server_->setServerEventHandler(serverEventHandler); diff --git a/lib/cpp/test/processor/ServerThread.h b/lib/cpp/test/processor/ServerThread.h index 21c3b60e086..61e31a35e9f 100644 --- a/lib/cpp/test/processor/ServerThread.h +++ b/lib/cpp/test/processor/ServerThread.h @@ -43,7 +43,7 @@ class ServerState { * If the server returned fails to bind to the specified port when serve() is * called on it, createServer() may be called again on a different port. */ - virtual stdcxx::shared_ptr createServer(uint16_t port) = 0; + virtual std::shared_ptr createServer(uint16_t port) = 0; /** * Get the TServerEventHandler to set on the server. @@ -52,8 +52,8 @@ class ServerState { * start serving traffic. It is invoked from the server thread, rather than * the main thread. */ - virtual stdcxx::shared_ptr getServerEventHandler() { - return stdcxx::shared_ptr(); + virtual std::shared_ptr getServerEventHandler() { + return std::shared_ptr(); } /** @@ -70,7 +70,7 @@ class ServerState { */ class ServerThread { public: - ServerThread(const stdcxx::shared_ptr& state, bool autoStart) + ServerThread(const std::shared_ptr& state, bool autoStart) : port_(0), running_(false), serving_(false), @@ -116,7 +116,7 @@ class ServerThread { void run(); void preServe(); - stdcxx::shared_ptr helper_; + std::shared_ptr helper_; uint16_t port_; bool running_; @@ -124,9 +124,9 @@ class ServerThread { bool error_; concurrency::Monitor serverMonitor_; - stdcxx::shared_ptr serverState_; - stdcxx::shared_ptr server_; - stdcxx::shared_ptr thread_; + std::shared_ptr serverState_; + std::shared_ptr server_; + std::shared_ptr thread_; }; } } diff --git a/lib/cpp/test/qt/TQTcpServerTest.cpp b/lib/cpp/test/qt/TQTcpServerTest.cpp index 8a327aa24ca..58d0c6dbf60 100644 --- a/lib/cpp/test/qt/TQTcpServerTest.cpp +++ b/lib/cpp/test/qt/TQTcpServerTest.cpp @@ -8,7 +8,6 @@ #include #ifndef Q_MOC_RUN - #include "thrift/stdcxx.h" #include "thrift/protocol/TBinaryProtocol.h" #include "thrift/async/TAsyncProcessor.h" #include "thrift/qt/TQTcpServer.h" @@ -21,25 +20,25 @@ using namespace apache::thrift; struct AsyncHandler : public test::ParentServiceCobSvIf { std::vector strings; - virtual void addString(stdcxx::function cob, const std::string& s) { + virtual void addString(std::function cob, const std::string& s) { strings.push_back(s); cob(); } - virtual void getStrings(stdcxx::function const& _return)> cob) { + virtual void getStrings(std::function const& _return)> cob) { cob(strings); } // Overrides not used in this test - virtual void incrementGeneration(stdcxx::function cob) {} - virtual void getGeneration(stdcxx::function cob) {} - virtual void getDataWait(stdcxx::function cob, + virtual void incrementGeneration(std::function cob) {} + virtual void getGeneration(std::function cob) {} + virtual void getDataWait(std::function cob, const int32_t length) {} - virtual void onewayWait(stdcxx::function cob) {} + virtual void onewayWait(std::function cob) {} virtual void exceptionWait( - stdcxx::function cob, - stdcxx::function /* exn_cob */, + std::function cob, + std::function /* exn_cob */, const std::string& message) {} - virtual void unexpectedExceptionWait(stdcxx::function cob, const std::string& message) {} + virtual void unexpectedExceptionWait(std::function cob, const std::string& message) {} }; class TQTcpServerTest : public QObject { @@ -51,18 +50,18 @@ private slots: void test_communicate(); private: - stdcxx::shared_ptr serverThread; - stdcxx::shared_ptr server; - stdcxx::shared_ptr client; + std::shared_ptr serverThread; + std::shared_ptr server; + std::shared_ptr client; }; void TQTcpServerTest::initTestCase() { // setup server - stdcxx::shared_ptr serverSocket = stdcxx::make_shared(); + std::shared_ptr serverSocket = std::make_shared(); server.reset(new async::TQTcpServer(serverSocket, - stdcxx::make_shared( - stdcxx::make_shared()), - stdcxx::make_shared())); + std::make_shared( + std::make_shared()), + std::make_shared())); QVERIFY(serverSocket->listen(QHostAddress::LocalHost)); int port = serverSocket->serverPort(); QVERIFY(port > 0); @@ -74,9 +73,9 @@ void TQTcpServerTest::initTestCase() { serverThread->start(); // setup client - stdcxx::shared_ptr socket = stdcxx::make_shared(); - client.reset(new test::ParentServiceClient(stdcxx::make_shared( - stdcxx::make_shared(socket)))); + std::shared_ptr socket = std::make_shared(); + client.reset(new test::ParentServiceClient(std::make_shared( + std::make_shared(socket)))); socket->connectToHost(QHostAddress::LocalHost, port); QVERIFY(socket->waitForConnected()); } diff --git a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp index 63c8905a53d..019e2a74e28 100644 --- a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp +++ b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp @@ -111,23 +111,23 @@ ZEND_GET_MODULE(thrift_protocol) class PHPExceptionWrapper : public std::exception { public: - PHPExceptionWrapper(zval* _ex) throw() { + PHPExceptionWrapper(zval* _ex) noexcept { ZVAL_COPY(&ex, _ex); snprintf(_what, 40, "PHP exception zval=%p", _ex); } - PHPExceptionWrapper(zend_object* _exobj) throw() { + PHPExceptionWrapper(zend_object* _exobj) noexcept { ZVAL_OBJ(&ex, _exobj); snprintf(_what, 40, "PHP exception zval=%p", _exobj); } - ~PHPExceptionWrapper() throw() { + ~PHPExceptionWrapper() noexcept { zval_dtor(&ex); } - const char* what() const throw() { + const char* what() const noexcept { return _what; } - operator zval*() const throw() { + operator zval*() const noexcept { return const_cast(&ex); } // Zend API doesn't do 'const'... protected: diff --git a/lib/py/src/ext/types.h b/lib/py/src/ext/types.h index 5cd8dda9e01..84933f4fc24 100644 --- a/lib/py/src/ext/types.h +++ b/lib/py/src/ext/types.h @@ -89,19 +89,19 @@ class ScopedPyObject { if (obj_) Py_DECREF(obj_); } - PyObject* get() throw() { return obj_; } + PyObject* get() noexcept { return obj_; } operator bool() { return obj_; } - void reset(PyObject* py_object) throw() { + void reset(PyObject* py_object) noexcept { if (obj_) Py_DECREF(obj_); obj_ = py_object; } - PyObject* release() throw() { + PyObject* release() noexcept { PyObject* tmp = obj_; obj_ = NULL; return tmp; } - void swap(ScopedPyObject& other) throw() { + void swap(ScopedPyObject& other) noexcept { ScopedPyObject tmp(other.release()); other.reset(release()); reset(tmp.release()); diff --git a/test/cpp/src/StressTest.cpp b/test/cpp/src/StressTest.cpp index 5ff5e44f95d..585f89a9e27 100644 --- a/test/cpp/src/StressTest.cpp +++ b/test/cpp/src/StressTest.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include "Service.h" #include @@ -108,8 +107,8 @@ enum TransportOpenCloseBehavior { }; class ClientThread : public Runnable { public: - ClientThread(stdcxx::shared_ptr transport, - stdcxx::shared_ptr client, + ClientThread(std::shared_ptr transport, + std::shared_ptr client, Monitor& monitor, size_t& workerCount, size_t loopCount, @@ -225,8 +224,8 @@ class ClientThread : public Runnable { } } - stdcxx::shared_ptr _transport; - stdcxx::shared_ptr _client; + std::shared_ptr _transport; + std::shared_ptr _client; Monitor& _monitor; size_t& _workerCount; size_t _loopCount; @@ -391,24 +390,24 @@ int main(int argc, char** argv) { cerr << usage.str(); } - stdcxx::shared_ptr threadFactory - = stdcxx::shared_ptr(new PlatformThreadFactory()); + std::shared_ptr threadFactory + = std::shared_ptr(new PlatformThreadFactory()); // Dispatcher - stdcxx::shared_ptr serviceHandler(new Server()); + std::shared_ptr serviceHandler(new Server()); if (replayRequests) { - stdcxx::shared_ptr serviceHandler(new Server()); - stdcxx::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler)); + std::shared_ptr serviceHandler(new Server()); + std::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler)); // Transports - stdcxx::shared_ptr fileTransport(new TFileTransport(requestLogPath)); + std::shared_ptr fileTransport(new TFileTransport(requestLogPath)); fileTransport->setChunkSize(2 * 1024 * 1024); fileTransport->setMaxEventSize(1024 * 16); fileTransport->seekToEnd(); // Protocol Factory - stdcxx::shared_ptr protocolFactory(new TBinaryProtocolFactory()); + std::shared_ptr protocolFactory(new TBinaryProtocolFactory()); TFileProcessor fileProcessor(serviceProcessor, protocolFactory, fileTransport); @@ -418,28 +417,28 @@ int main(int argc, char** argv) { if (runServer) { - stdcxx::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler)); + std::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler)); // Transport - stdcxx::shared_ptr serverSocket(new TServerSocket(port)); + std::shared_ptr serverSocket(new TServerSocket(port)); // Transport Factory - stdcxx::shared_ptr transportFactory(new TBufferedTransportFactory()); + std::shared_ptr transportFactory(new TBufferedTransportFactory()); // Protocol Factory - stdcxx::shared_ptr protocolFactory(new TBinaryProtocolFactory()); + std::shared_ptr protocolFactory(new TBinaryProtocolFactory()); if (logRequests) { // initialize the log file - stdcxx::shared_ptr fileTransport(new TFileTransport(requestLogPath)); + std::shared_ptr fileTransport(new TFileTransport(requestLogPath)); fileTransport->setChunkSize(2 * 1024 * 1024); fileTransport->setMaxEventSize(1024 * 16); transportFactory - = stdcxx::shared_ptr(new TPipedTransportFactory(fileTransport)); + = std::shared_ptr(new TPipedTransportFactory(fileTransport)); } - stdcxx::shared_ptr server; + std::shared_ptr server; if (serverType == "simple") { @@ -453,7 +452,7 @@ int main(int argc, char** argv) { } else if (serverType == "thread-pool") { - stdcxx::shared_ptr threadManager + std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workerCount); threadManager->threadFactory(threadFactory); @@ -465,9 +464,9 @@ int main(int argc, char** argv) { threadManager)); } - stdcxx::shared_ptr observer(new TStartObserver); + std::shared_ptr observer(new TStartObserver); server->setServerEventHandler(observer); - stdcxx::shared_ptr serverThread = threadFactory->newThread(server); + std::shared_ptr serverThread = threadFactory->newThread(server); cerr << "Starting the server on port " << port << endl; @@ -486,7 +485,7 @@ int main(int argc, char** argv) { size_t threadCount = 0; - set > clientThreads; + set > clientThreads; if (callName == "echoVoid") { loopType = T_VOID; @@ -505,28 +504,28 @@ int main(int argc, char** argv) { if(clientType == "regular") { for (size_t ix = 0; ix < clientCount; ix++) { - stdcxx::shared_ptr socket(new TSocket("127.0.0.1", port)); - stdcxx::shared_ptr bufferedSocket(new TBufferedTransport(socket, 2048)); - stdcxx::shared_ptr protocol(new TBinaryProtocol(bufferedSocket)); - stdcxx::shared_ptr serviceClient(new ServiceClient(protocol)); + std::shared_ptr socket(new TSocket("127.0.0.1", port)); + std::shared_ptr bufferedSocket(new TBufferedTransport(socket, 2048)); + std::shared_ptr protocol(new TBinaryProtocol(bufferedSocket)); + std::shared_ptr serviceClient(new ServiceClient(protocol)); - clientThreads.insert(threadFactory->newThread(stdcxx::shared_ptr( + clientThreads.insert(threadFactory->newThread(std::shared_ptr( new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, OpenAndCloseTransportInThread)))); } } else if(clientType == "concurrent") { - stdcxx::shared_ptr socket(new TSocket("127.0.0.1", port)); - stdcxx::shared_ptr bufferedSocket(new TBufferedTransport(socket, 2048)); - stdcxx::shared_ptr protocol(new TBinaryProtocol(bufferedSocket)); - //stdcxx::shared_ptr serviceClient(new ServiceClient(protocol)); - stdcxx::shared_ptr serviceClient(new ServiceConcurrentClient(protocol)); + std::shared_ptr socket(new TSocket("127.0.0.1", port)); + std::shared_ptr bufferedSocket(new TBufferedTransport(socket, 2048)); + std::shared_ptr protocol(new TBinaryProtocol(bufferedSocket)); + //std::shared_ptr serviceClient(new ServiceClient(protocol)); + std::shared_ptr serviceClient(new ServiceConcurrentClient(protocol)); socket->open(); for (size_t ix = 0; ix < clientCount; ix++) { - clientThreads.insert(threadFactory->newThread(stdcxx::shared_ptr( + clientThreads.insert(threadFactory->newThread(std::shared_ptr( new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType, DontOpenAndCloseTransportInThread)))); } } - for (std::set >::const_iterator thread = clientThreads.begin(); + for (std::set >::const_iterator thread = clientThreads.begin(); thread != clientThreads.end(); thread++) { (*thread)->start(); @@ -559,12 +558,12 @@ int main(int argc, char** argv) { int64_t minTime = 9223372036854775807LL; int64_t maxTime = 0; - for (set >::iterator ix = clientThreads.begin(); + for (set >::iterator ix = clientThreads.begin(); ix != clientThreads.end(); ix++) { - stdcxx::shared_ptr client - = stdcxx::dynamic_pointer_cast((*ix)->runnable()); + std::shared_ptr client + = std::dynamic_pointer_cast((*ix)->runnable()); int64_t delta = client->_endTime - client->_startTime; diff --git a/test/cpp/src/StressTestNonBlocking.cpp b/test/cpp/src/StressTestNonBlocking.cpp index e68988f41b3..1d3ed732bca 100644 --- a/test/cpp/src/StressTestNonBlocking.cpp +++ b/test/cpp/src/StressTestNonBlocking.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include "Service.h" @@ -109,8 +108,8 @@ class Server : public ServiceIf { class ClientThread : public Runnable { public: - ClientThread(stdcxx::shared_ptr transport, - stdcxx::shared_ptr client, + ClientThread(std::shared_ptr transport, + std::shared_ptr client, Monitor& monitor, size_t& workerCount, size_t loopCount, @@ -221,8 +220,8 @@ class ClientThread : public Runnable { } } - stdcxx::shared_ptr _transport; - stdcxx::shared_ptr _client; + std::shared_ptr _transport; + std::shared_ptr _client; Monitor& _monitor; size_t& _workerCount; size_t _loopCount; @@ -344,24 +343,24 @@ int main(int argc, char** argv) { cerr << usage.str(); } - stdcxx::shared_ptr threadFactory - = stdcxx::shared_ptr(new PlatformThreadFactory()); + std::shared_ptr threadFactory + = std::shared_ptr(new PlatformThreadFactory()); // Dispatcher - stdcxx::shared_ptr serviceHandler(new Server()); + std::shared_ptr serviceHandler(new Server()); if (replayRequests) { - stdcxx::shared_ptr serviceHandler(new Server()); - stdcxx::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler)); + std::shared_ptr serviceHandler(new Server()); + std::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler)); // Transports - stdcxx::shared_ptr fileTransport(new TFileTransport(requestLogPath)); + std::shared_ptr fileTransport(new TFileTransport(requestLogPath)); fileTransport->setChunkSize(2 * 1024 * 1024); fileTransport->setMaxEventSize(1024 * 16); fileTransport->seekToEnd(); // Protocol Factory - stdcxx::shared_ptr protocolFactory(new TBinaryProtocolFactory()); + std::shared_ptr protocolFactory(new TBinaryProtocolFactory()); TFileProcessor fileProcessor(serviceProcessor, protocolFactory, fileTransport); @@ -371,50 +370,50 @@ int main(int argc, char** argv) { if (runServer) { - stdcxx::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler)); + std::shared_ptr serviceProcessor(new ServiceProcessor(serviceHandler)); // Protocol Factory - stdcxx::shared_ptr protocolFactory(new TBinaryProtocolFactory()); + std::shared_ptr protocolFactory(new TBinaryProtocolFactory()); // Transport Factory - stdcxx::shared_ptr transportFactory; + std::shared_ptr transportFactory; if (logRequests) { // initialize the log file - stdcxx::shared_ptr fileTransport(new TFileTransport(requestLogPath)); + std::shared_ptr fileTransport(new TFileTransport(requestLogPath)); fileTransport->setChunkSize(2 * 1024 * 1024); fileTransport->setMaxEventSize(1024 * 16); transportFactory - = stdcxx::shared_ptr(new TPipedTransportFactory(fileTransport)); + = std::shared_ptr(new TPipedTransportFactory(fileTransport)); } - stdcxx::shared_ptr serverThread; - stdcxx::shared_ptr serverThread2; - stdcxx::shared_ptr nbSocket1; - stdcxx::shared_ptr nbSocket2; + std::shared_ptr serverThread; + std::shared_ptr serverThread2; + std::shared_ptr nbSocket1; + std::shared_ptr nbSocket2; if (serverType == "simple") { nbSocket1.reset(new transport::TNonblockingServerSocket(port)); - serverThread = threadFactory->newThread(stdcxx::shared_ptr( + serverThread = threadFactory->newThread(std::shared_ptr( new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket1))); nbSocket2.reset(new transport::TNonblockingServerSocket(port + 1)); - serverThread2 = threadFactory->newThread(stdcxx::shared_ptr( + serverThread2 = threadFactory->newThread(std::shared_ptr( new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket2))); } else if (serverType == "thread-pool") { - stdcxx::shared_ptr threadManager + std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workerCount); threadManager->threadFactory(threadFactory); threadManager->start(); nbSocket1.reset(new transport::TNonblockingServerSocket(port)); - serverThread = threadFactory->newThread(stdcxx::shared_ptr( + serverThread = threadFactory->newThread(std::shared_ptr( new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket1, threadManager))); nbSocket2.reset(new transport::TNonblockingServerSocket(port + 1)); - serverThread2 = threadFactory->newThread(stdcxx::shared_ptr( + serverThread2 = threadFactory->newThread(std::shared_ptr( new TNonblockingServer(serviceProcessor, protocolFactory, nbSocket2, threadManager))); } @@ -437,7 +436,7 @@ int main(int argc, char** argv) { size_t threadCount = 0; - set > clientThreads; + set > clientThreads; if (callName == "echoVoid") { loopType = T_VOID; @@ -455,16 +454,16 @@ int main(int argc, char** argv) { for (uint32_t ix = 0; ix < clientCount; ix++) { - stdcxx::shared_ptr socket(new TSocket("127.0.0.1", port + (ix % 2))); - stdcxx::shared_ptr framedSocket(new TFramedTransport(socket)); - stdcxx::shared_ptr protocol(new TBinaryProtocol(framedSocket)); - stdcxx::shared_ptr serviceClient(new ServiceClient(protocol)); + std::shared_ptr socket(new TSocket("127.0.0.1", port + (ix % 2))); + std::shared_ptr framedSocket(new TFramedTransport(socket)); + std::shared_ptr protocol(new TBinaryProtocol(framedSocket)); + std::shared_ptr serviceClient(new ServiceClient(protocol)); - clientThreads.insert(threadFactory->newThread(stdcxx::shared_ptr( + clientThreads.insert(threadFactory->newThread(std::shared_ptr( new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType)))); } - for (std::set >::const_iterator thread = clientThreads.begin(); + for (std::set >::const_iterator thread = clientThreads.begin(); thread != clientThreads.end(); thread++) { (*thread)->start(); @@ -497,12 +496,12 @@ int main(int argc, char** argv) { int64_t minTime = 9223372036854775807LL; int64_t maxTime = 0; - for (set >::iterator ix = clientThreads.begin(); + for (set >::iterator ix = clientThreads.begin(); ix != clientThreads.end(); ix++) { - stdcxx::shared_ptr client - = stdcxx::dynamic_pointer_cast((*ix)->runnable()); + std::shared_ptr client + = std::dynamic_pointer_cast((*ix)->runnable()); int64_t delta = client->_endTime - client->_startTime; diff --git a/test/cpp/src/TestClient.cpp b/test/cpp/src/TestClient.cpp index ca213260e55..89f3fd13c35 100644 --- a/test/cpp/src/TestClient.cpp +++ b/test/cpp/src/TestClient.cpp @@ -46,7 +46,6 @@ #include #include #include -#include #if _WIN32 #include #endif @@ -98,10 +97,10 @@ static void testVoid_clientReturn(event_base* base, ThriftTestCobClient* client) for (int testNr = 0; testNr < 10; ++testNr) { std::ostringstream os; os << "test" << testNr; - client->testString(stdcxx::bind(testString_clientReturn, + client->testString(std::bind(testString_clientReturn, base, testNr, - stdcxx::placeholders::_1), + std::placeholders::_1), os.str()); } } catch (TException& exn) { @@ -254,18 +253,18 @@ int main(int argc, char** argv) { } // THRIFT-4164: The factory MUST outlive any sockets it creates for correct behavior! - stdcxx::shared_ptr factory; - stdcxx::shared_ptr socket; - stdcxx::shared_ptr transport; - stdcxx::shared_ptr protocol; - stdcxx::shared_ptr protocol2; // SecondService for multiplexed + std::shared_ptr factory; + std::shared_ptr socket; + std::shared_ptr transport; + std::shared_ptr protocol; + std::shared_ptr protocol2; // SecondService for multiplexed if (ssl) { cout << "Client Certificate File: " << certPath << endl; cout << "Client Key File: " << keyPath << endl; cout << "CA File: " << caPath << endl; - factory = stdcxx::shared_ptr(new TSSLSocketFactory()); + factory = std::shared_ptr(new TSSLSocketFactory()); factory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); factory->loadTrustedCertificates(caPath.c_str()); factory->loadCertificate(certPath.c_str()); @@ -277,42 +276,42 @@ int main(int argc, char** argv) { if (abstract_namespace) { std::string abstract_socket("\0", 1); abstract_socket += domain_socket; - socket = stdcxx::shared_ptr(new TSocket(abstract_socket)); + socket = std::shared_ptr(new TSocket(abstract_socket)); } else { - socket = stdcxx::shared_ptr(new TSocket(domain_socket)); + socket = std::shared_ptr(new TSocket(domain_socket)); } port = 0; } else { - socket = stdcxx::shared_ptr(new TSocket(host, port)); + socket = std::shared_ptr(new TSocket(host, port)); } } if (transport_type.compare("http") == 0) { - transport = stdcxx::make_shared(socket, host, "/service"); + transport = std::make_shared(socket, host, "/service"); } else if (transport_type.compare("framed") == 0) { - transport = stdcxx::make_shared(socket); + transport = std::make_shared(socket); } else { - transport = stdcxx::make_shared(socket); + transport = std::make_shared(socket); } if (zlib) { - transport = stdcxx::make_shared(transport); + transport = std::make_shared(transport); } if (protocol_type == "json" || protocol_type == "multij") { - protocol = stdcxx::make_shared(transport); + protocol = std::make_shared(transport); } else if (protocol_type == "compact" || protocol_type == "multic") { - protocol = stdcxx::make_shared(transport); + protocol = std::make_shared(transport); } else if (protocol_type == "header" || protocol_type == "multih") { - protocol = stdcxx::make_shared(transport); + protocol = std::make_shared(transport); } else { - protocol = stdcxx::make_shared(transport); + protocol = std::make_shared(transport); } if (boost::starts_with(protocol_type, "multi")) { - protocol2 = stdcxx::make_shared(protocol, "SecondService"); + protocol2 = std::make_shared(protocol, "SecondService"); // we don't need access to the original protocol any more, so... - protocol = stdcxx::make_shared(protocol, "ThriftTest"); + protocol = std::make_shared(protocol, "ThriftTest"); } // Connection info @@ -334,14 +333,14 @@ int main(int argc, char** argv) { cout << "Libevent Features: 0x" << hex << event_base_get_features(base) << endl; #endif - stdcxx::shared_ptr protocolFactory(new TBinaryProtocolFactory()); + std::shared_ptr protocolFactory(new TBinaryProtocolFactory()); - stdcxx::shared_ptr channel( + std::shared_ptr channel( new TEvhttpClientChannel(host.c_str(), "/", host.c_str(), port, base)); ThriftTestCobClient* client = new ThriftTestCobClient(channel, protocolFactory.get()); - client->testVoid(stdcxx::bind(testVoid_clientReturn, + client->testVoid(std::bind(testVoid_clientReturn, base, - stdcxx::placeholders::_1)); + std::placeholders::_1)); event_base_loop(base, 0); return 0; diff --git a/test/cpp/src/TestServer.cpp b/test/cpp/src/TestServer.cpp index 323f873547a..622201766f6 100644 --- a/test/cpp/src/TestServer.cpp +++ b/test/cpp/src/TestServer.cpp @@ -61,7 +61,6 @@ #include #include #include -#include #if _WIN32 #include @@ -395,66 +394,66 @@ class TestProcessorEventHandler : public TProcessorEventHandler { class TestHandlerAsync : public ThriftTestCobSvIf { public: - TestHandlerAsync(stdcxx::shared_ptr& handler) : _delegate(handler) {} + TestHandlerAsync(std::shared_ptr& handler) : _delegate(handler) {} virtual ~TestHandlerAsync() {} - virtual void testVoid(stdcxx::function cob) { + virtual void testVoid(std::function cob) { _delegate->testVoid(); cob(); } - virtual void testString(stdcxx::function cob, + virtual void testString(std::function cob, const std::string& thing) { std::string res; _delegate->testString(res, thing); cob(res); } - virtual void testBool(stdcxx::function cob, const bool thing) { + virtual void testBool(std::function cob, const bool thing) { bool res = _delegate->testBool(thing); cob(res); } - virtual void testByte(stdcxx::function cob, const int8_t thing) { + virtual void testByte(std::function cob, const int8_t thing) { int8_t res = _delegate->testByte(thing); cob(res); } - virtual void testI32(stdcxx::function cob, const int32_t thing) { + virtual void testI32(std::function cob, const int32_t thing) { int32_t res = _delegate->testI32(thing); cob(res); } - virtual void testI64(stdcxx::function cob, const int64_t thing) { + virtual void testI64(std::function cob, const int64_t thing) { int64_t res = _delegate->testI64(thing); cob(res); } - virtual void testDouble(stdcxx::function cob, const double thing) { + virtual void testDouble(std::function cob, const double thing) { double res = _delegate->testDouble(thing); cob(res); } - virtual void testBinary(stdcxx::function cob, + virtual void testBinary(std::function cob, const std::string& thing) { std::string res; _delegate->testBinary(res, thing); cob(res); } - virtual void testStruct(stdcxx::function cob, const Xtruct& thing) { + virtual void testStruct(std::function cob, const Xtruct& thing) { Xtruct res; _delegate->testStruct(res, thing); cob(res); } - virtual void testNest(stdcxx::function cob, const Xtruct2& thing) { + virtual void testNest(std::function cob, const Xtruct2& thing) { Xtruct2 res; _delegate->testNest(res, thing); cob(res); } - virtual void testMap(stdcxx::function const& _return)> cob, + virtual void testMap(std::function const& _return)> cob, const std::map& thing) { std::map res; _delegate->testMap(res, thing); @@ -462,40 +461,40 @@ class TestHandlerAsync : public ThriftTestCobSvIf { } virtual void testStringMap( - stdcxx::function const& _return)> cob, + std::function const& _return)> cob, const std::map& thing) { std::map res; _delegate->testStringMap(res, thing); cob(res); } - virtual void testSet(stdcxx::function const& _return)> cob, + virtual void testSet(std::function const& _return)> cob, const std::set& thing) { std::set res; _delegate->testSet(res, thing); cob(res); } - virtual void testList(stdcxx::function const& _return)> cob, + virtual void testList(std::function const& _return)> cob, const std::vector& thing) { std::vector res; _delegate->testList(res, thing); cob(res); } - virtual void testEnum(stdcxx::function cob, + virtual void testEnum(std::function cob, const Numberz::type thing) { Numberz::type res = _delegate->testEnum(thing); cob(res); } - virtual void testTypedef(stdcxx::function cob, const UserId thing) { + virtual void testTypedef(std::function cob, const UserId thing) { UserId res = _delegate->testTypedef(thing); cob(res); } virtual void testMapMap( - stdcxx::function > const& _return)> cob, + std::function > const& _return)> cob, const int32_t hello) { std::map > res; _delegate->testMapMap(res, hello); @@ -503,14 +502,14 @@ class TestHandlerAsync : public ThriftTestCobSvIf { } virtual void testInsanity( - stdcxx::function > const& _return)> cob, + std::function > const& _return)> cob, const Insanity& argument) { std::map > res; _delegate->testInsanity(res, argument); cob(res); } - virtual void testMulti(stdcxx::function cob, + virtual void testMulti(std::function cob, const int8_t arg0, const int32_t arg1, const int64_t arg2, @@ -523,8 +522,8 @@ class TestHandlerAsync : public ThriftTestCobSvIf { } virtual void testException( - stdcxx::function cob, - stdcxx::function exn_cob, + std::function cob, + std::function exn_cob, const std::string& arg) { try { _delegate->testException(arg); @@ -536,8 +535,8 @@ class TestHandlerAsync : public ThriftTestCobSvIf { } virtual void testMultiException( - stdcxx::function cob, - stdcxx::function exn_cob, + std::function cob, + std::function exn_cob, const std::string& arg0, const std::string& arg1) { Xtruct res; @@ -550,13 +549,13 @@ class TestHandlerAsync : public ThriftTestCobSvIf { cob(res); } - virtual void testOneway(stdcxx::function cob, const int32_t secondsToSleep) { + virtual void testOneway(std::function cob, const int32_t secondsToSleep) { _delegate->testOneway(secondsToSleep); cob(); } protected: - stdcxx::shared_ptr _delegate; + std::shared_ptr _delegate; }; namespace po = boost::program_options; @@ -668,9 +667,9 @@ int main(int argc, char** argv) { } // Dispatcher - stdcxx::shared_ptr protocolFactory; + std::shared_ptr protocolFactory; if (protocol_type == "json" || protocol_type == "multij") { - stdcxx::shared_ptr jsonProtocolFactory(new TJSONProtocolFactory()); + std::shared_ptr jsonProtocolFactory(new TJSONProtocolFactory()); protocolFactory = jsonProtocolFactory; } else if (protocol_type == "compact" || protocol_type == "multic") { TCompactProtocolFactoryT *compactProtocolFactory = new TCompactProtocolFactoryT(); @@ -678,7 +677,7 @@ int main(int argc, char** argv) { compactProtocolFactory->setStringSizeLimit(string_limit); protocolFactory.reset(compactProtocolFactory); } else if (protocol_type == "header" || protocol_type == "multih") { - stdcxx::shared_ptr headerProtocolFactory(new THeaderProtocolFactory()); + std::shared_ptr headerProtocolFactory(new THeaderProtocolFactory()); protocolFactory = headerProtocolFactory; } else { TBinaryProtocolFactoryT* binaryProtocolFactory = new TBinaryProtocolFactoryT(); @@ -688,56 +687,56 @@ int main(int argc, char** argv) { } // Processors - stdcxx::shared_ptr testHandler(new TestHandler()); - stdcxx::shared_ptr testProcessor(new ThriftTestProcessor(testHandler)); + std::shared_ptr testHandler(new TestHandler()); + std::shared_ptr testProcessor(new ThriftTestProcessor(testHandler)); if (vm.count("processor-events")) { testProcessor->setEventHandler( - stdcxx::shared_ptr(new TestProcessorEventHandler())); + std::shared_ptr(new TestProcessorEventHandler())); } // Transport - stdcxx::shared_ptr sslSocketFactory; - stdcxx::shared_ptr serverSocket; + std::shared_ptr sslSocketFactory; + std::shared_ptr serverSocket; if (ssl) { - sslSocketFactory = stdcxx::shared_ptr(new TSSLSocketFactory()); + sslSocketFactory = std::shared_ptr(new TSSLSocketFactory()); sslSocketFactory->loadCertificate(certPath.c_str()); sslSocketFactory->loadPrivateKey(keyPath.c_str()); sslSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); if (server_type != "nonblocking") { - serverSocket = stdcxx::shared_ptr(new TSSLServerSocket(port, sslSocketFactory)); + serverSocket = std::shared_ptr(new TSSLServerSocket(port, sslSocketFactory)); } } else { if (domain_socket != "") { if (abstract_namespace) { std::string abstract_socket("\0", 1); abstract_socket += domain_socket; - serverSocket = stdcxx::shared_ptr(new TServerSocket(abstract_socket)); + serverSocket = std::shared_ptr(new TServerSocket(abstract_socket)); } else { unlink(domain_socket.c_str()); - serverSocket = stdcxx::shared_ptr(new TServerSocket(domain_socket)); + serverSocket = std::shared_ptr(new TServerSocket(domain_socket)); } port = 0; } else { - serverSocket = stdcxx::shared_ptr(new TServerSocket(port)); + serverSocket = std::shared_ptr(new TServerSocket(port)); } } // Factory - stdcxx::shared_ptr transportFactory; + std::shared_ptr transportFactory; if (transport_type == "http" && server_type != "nonblocking") { - transportFactory = stdcxx::make_shared(); + transportFactory = std::make_shared(); } else if (transport_type == "framed") { - transportFactory = stdcxx::make_shared(); + transportFactory = std::make_shared(); } else { - transportFactory = stdcxx::make_shared(); + transportFactory = std::make_shared(); } if (zlib) { // hmm.. doesn't seem to be a way to make it wrap the others... - transportFactory = stdcxx::make_shared(); + transportFactory = std::make_shared(); } // Server Info @@ -754,27 +753,27 @@ int main(int argc, char** argv) { // Multiplexed Processor if needed if (boost::starts_with(protocol_type, "multi")) { - stdcxx::shared_ptr secondHandler(new SecondHandler()); - stdcxx::shared_ptr secondProcessor(new SecondServiceProcessor(secondHandler)); + std::shared_ptr secondHandler(new SecondHandler()); + std::shared_ptr secondProcessor(new SecondServiceProcessor(secondHandler)); - stdcxx::shared_ptr multiplexedProcessor(new TMultiplexedProcessor()); + std::shared_ptr multiplexedProcessor(new TMultiplexedProcessor()); multiplexedProcessor->registerDefault(testProcessor); // non-multi clients go to the default processor (multi:binary, multic:compact, ...) multiplexedProcessor->registerProcessor("ThriftTest", testProcessor); multiplexedProcessor->registerProcessor("SecondService", secondProcessor); - testProcessor = stdcxx::dynamic_pointer_cast(multiplexedProcessor); + testProcessor = std::dynamic_pointer_cast(multiplexedProcessor); } // Server - stdcxx::shared_ptr server; + std::shared_ptr server; if (server_type == "simple") { server.reset(new TSimpleServer(testProcessor, serverSocket, transportFactory, protocolFactory)); } else if (server_type == "thread-pool") { - stdcxx::shared_ptr threadFactory - = stdcxx::shared_ptr(new PlatformThreadFactory()); + std::shared_ptr threadFactory + = std::shared_ptr(new PlatformThreadFactory()); - stdcxx::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workers); + std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workers); threadManager->threadFactory(threadFactory); threadManager->start(); @@ -788,10 +787,10 @@ int main(int argc, char** argv) { new TThreadedServer(testProcessor, serverSocket, transportFactory, protocolFactory)); } else if (server_type == "nonblocking") { if (transport_type == "http") { - stdcxx::shared_ptr testHandlerAsync(new TestHandlerAsync(testHandler)); - stdcxx::shared_ptr testProcessorAsync( + std::shared_ptr testHandlerAsync(new TestHandlerAsync(testHandler)); + std::shared_ptr testProcessorAsync( new ThriftTestAsyncProcessor(testHandlerAsync)); - stdcxx::shared_ptr testBufferProcessor( + std::shared_ptr testBufferProcessor( new TAsyncProtocolProcessor(testProcessorAsync, protocolFactory)); // not loading nonblockingServer into "server" because @@ -800,7 +799,7 @@ int main(int argc, char** argv) { TEvhttpServer nonblockingServer(testBufferProcessor, port); nonblockingServer.serve(); } else if (transport_type == "framed") { - stdcxx::shared_ptr nbSocket; + std::shared_ptr nbSocket; nbSocket.reset( ssl ? new transport::TNonblockingSSLServerSocket(port, sslSocketFactory) : new transport::TNonblockingServerSocket(port)); @@ -815,13 +814,13 @@ int main(int argc, char** argv) { if (protocol_type == "header") { // Tell the server to use the same protocol for input / output // if using header - server->setOutputProtocolFactory(stdcxx::shared_ptr()); + server->setOutputProtocolFactory(std::shared_ptr()); } apache::thrift::concurrency::PlatformThreadFactory factory; factory.setDetached(false); - stdcxx::shared_ptr serverThreadRunner(server); - stdcxx::shared_ptr thread + std::shared_ptr serverThreadRunner(server); + std::shared_ptr thread = factory.newThread(serverThreadRunner); #ifdef HAVE_SIGNAL_H diff --git a/tutorial/cpp/CppClient.cpp b/tutorial/cpp/CppClient.cpp index f10c72557e2..520841143b4 100644 --- a/tutorial/cpp/CppClient.cpp +++ b/tutorial/cpp/CppClient.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include "../gen-cpp/Calculator.h" @@ -35,9 +34,9 @@ using namespace tutorial; using namespace shared; int main() { - stdcxx::shared_ptr socket(new TSocket("localhost", 9090)); - stdcxx::shared_ptr transport(new TBufferedTransport(socket)); - stdcxx::shared_ptr protocol(new TBinaryProtocol(transport)); + std::shared_ptr socket(new TSocket("localhost", 9090)); + std::shared_ptr transport(new TBufferedTransport(socket)); + std::shared_ptr protocol(new TBinaryProtocol(transport)); CalculatorClient client(protocol); try { diff --git a/tutorial/cpp/CppServer.cpp b/tutorial/cpp/CppServer.cpp index 80b100e59a9..f7379d5368b 100644 --- a/tutorial/cpp/CppServer.cpp +++ b/tutorial/cpp/CppServer.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -117,7 +116,7 @@ class CalculatorCloneFactory : virtual public CalculatorIfFactory { virtual ~CalculatorCloneFactory() {} virtual CalculatorIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) { - stdcxx::shared_ptr sock = stdcxx::dynamic_pointer_cast(connInfo.transport); + std::shared_ptr sock = std::dynamic_pointer_cast(connInfo.transport); cout << "Incoming connection\n"; cout << "\tSocketInfo: " << sock->getSocketInfo() << "\n"; cout << "\tPeerHost: " << sock->getPeerHost() << "\n"; @@ -132,18 +131,18 @@ class CalculatorCloneFactory : virtual public CalculatorIfFactory { int main() { TThreadedServer server( - stdcxx::make_shared(stdcxx::make_shared()), - stdcxx::make_shared(9090), //port - stdcxx::make_shared(), - stdcxx::make_shared()); + std::make_shared(std::make_shared()), + std::make_shared(9090), //port + std::make_shared(), + std::make_shared()); /* // if you don't need per-connection state, do the following instead TThreadedServer server( - stdcxx::make_shared(stdcxx::make_shared()), - stdcxx::make_shared(9090), //port - stdcxx::make_shared(), - stdcxx::make_shared()); + std::make_shared(std::make_shared()), + std::make_shared(9090), //port + std::make_shared(), + std::make_shared()); */ /** @@ -151,25 +150,25 @@ int main() { // This server only allows one connection at a time, but spawns no threads TSimpleServer server( - stdcxx::make_shared(stdcxx::make_shared()), - stdcxx::make_shared(9090), - stdcxx::make_shared(), - stdcxx::make_shared()); + std::make_shared(std::make_shared()), + std::make_shared(9090), + std::make_shared(), + std::make_shared()); const int workerCount = 4; - stdcxx::shared_ptr threadManager = + std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workerCount); threadManager->threadFactory( - stdcxx::make_shared()); + std::make_shared()); threadManager->start(); // This server allows "workerCount" connection at a time, and reuses threads TThreadPoolServer server( - stdcxx::make_shared(stdcxx::make_shared()), - stdcxx::make_shared(9090), - stdcxx::make_shared(), - stdcxx::make_shared(), + std::make_shared(std::make_shared()), + std::make_shared(9090), + std::make_shared(), + std::make_shared(), threadManager); */ From d65e91c47613e54eb0c2bf521ae2cd4242d58ed9 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 16:43:55 +0800 Subject: [PATCH 115/756] remove stdcxx namespace and use std directly --- contrib/zeromq/TZmqServer.h | 5 +++-- lib/cpp/Makefile.am | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/zeromq/TZmqServer.h b/contrib/zeromq/TZmqServer.h index 43f86c084fc..ecd13b4243f 100644 --- a/contrib/zeromq/TZmqServer.h +++ b/contrib/zeromq/TZmqServer.h @@ -20,6 +20,7 @@ #ifndef _THRIFT_SERVER_TZMQSERVER_H_ #define _THRIFT_SERVER_TZMQSERVER_H_ 1 +#include #include #include @@ -28,7 +29,7 @@ namespace apache { namespace thrift { namespace server { class TZmqServer : public TServer { public: TZmqServer( - apache::thrift::stdcxx::shared_ptr processor, + std::shared_ptr processor, zmq::context_t& ctx, const std::string& endpoint, int type) : TServer(processor) , processor_(processor) @@ -56,7 +57,7 @@ class TZmqServer : public TServer { } private: - apache::thrift::stdcxx::shared_ptr processor_; + std::shared_ptr processor_; int zmq_type_; zmq::socket_t sock_; }; diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index 11d6b051c2b..85bb9abf82c 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -159,7 +159,6 @@ include_thrift_HEADERS = \ src/thrift/TApplicationException.h \ src/thrift/TLogging.h \ src/thrift/TToString.h \ - src/thrift/stdcxx.h \ src/thrift/TBase.h include_concurrencydir = $(include_thriftdir)/concurrency From 8cb3b6854818bf63d3208afaf4dc9e70c6137500 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 17:09:34 +0800 Subject: [PATCH 116/756] remove stdcxx namespace and use std directly --- lib/cpp/src/thrift/concurrency/Monitor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cpp/src/thrift/concurrency/Monitor.cpp b/lib/cpp/src/thrift/concurrency/Monitor.cpp index 8e4ac79a71c..9570cc691c7 100644 --- a/lib/cpp/src/thrift/concurrency/Monitor.cpp +++ b/lib/cpp/src/thrift/concurrency/Monitor.cpp @@ -34,7 +34,7 @@ namespace apache { namespace thrift { -using std::scoped_ptr; +using std::unique_ptr; using std::shared_ptr; namespace concurrency { @@ -163,7 +163,7 @@ class Monitor::Impl { } } - scoped_ptr ownedMutex_; + unique_ptr ownedMutex_; Mutex* mutex_; mutable pthread_cond_t pthread_cond_; From 0f43f95b89db01a8c68225824f8aa7fd4522007e Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 19:27:00 +0800 Subject: [PATCH 117/756] revert noexcept changings --- .../src/ext/thrift_protocol/php_thrift_protocol.cpp | 10 +++++----- lib/py/src/ext/types.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp index 019e2a74e28..63c8905a53d 100644 --- a/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp +++ b/lib/php/src/ext/thrift_protocol/php_thrift_protocol.cpp @@ -111,23 +111,23 @@ ZEND_GET_MODULE(thrift_protocol) class PHPExceptionWrapper : public std::exception { public: - PHPExceptionWrapper(zval* _ex) noexcept { + PHPExceptionWrapper(zval* _ex) throw() { ZVAL_COPY(&ex, _ex); snprintf(_what, 40, "PHP exception zval=%p", _ex); } - PHPExceptionWrapper(zend_object* _exobj) noexcept { + PHPExceptionWrapper(zend_object* _exobj) throw() { ZVAL_OBJ(&ex, _exobj); snprintf(_what, 40, "PHP exception zval=%p", _exobj); } - ~PHPExceptionWrapper() noexcept { + ~PHPExceptionWrapper() throw() { zval_dtor(&ex); } - const char* what() const noexcept { + const char* what() const throw() { return _what; } - operator zval*() const noexcept { + operator zval*() const throw() { return const_cast(&ex); } // Zend API doesn't do 'const'... protected: diff --git a/lib/py/src/ext/types.h b/lib/py/src/ext/types.h index 84933f4fc24..5cd8dda9e01 100644 --- a/lib/py/src/ext/types.h +++ b/lib/py/src/ext/types.h @@ -89,19 +89,19 @@ class ScopedPyObject { if (obj_) Py_DECREF(obj_); } - PyObject* get() noexcept { return obj_; } + PyObject* get() throw() { return obj_; } operator bool() { return obj_; } - void reset(PyObject* py_object) noexcept { + void reset(PyObject* py_object) throw() { if (obj_) Py_DECREF(obj_); obj_ = py_object; } - PyObject* release() noexcept { + PyObject* release() throw() { PyObject* tmp = obj_; obj_ = NULL; return tmp; } - void swap(ScopedPyObject& other) noexcept { + void swap(ScopedPyObject& other) throw() { ScopedPyObject tmp(other.release()); other.reset(release()); reset(tmp.release()); From e9421b826f3db5491b583db5202394e8e3861226 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 5 Jan 2019 19:28:55 +0800 Subject: [PATCH 118/756] remove std tr1 --- build/cmake/DefineOptions.cmake | 6 ------ 1 file changed, 6 deletions(-) diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 7465c803785..9aff53c16bb 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -40,11 +40,6 @@ option(BUILD_LIBRARIES "Build Thrift libraries" ON) # and enables the library if all are found. This means the default is to build as # much as possible but leaving out libraries if their dependencies are not met. -option(WITH_BOOST_FUNCTIONAL "Use boost/tr1/functional.hpp even under C++11 or later" OFF) -if (WITH_BOOST_FUNCTIONAL) - add_definitions(-DFORCE_BOOST_FUNCTIONAL) -endif() - option(WITH_BOOST_STATIC "Build with Boost static link library" OFF) set(Boost_USE_STATIC_LIBS ${WITH_BOOST_STATIC}) if (NOT WITH_BOOST_STATIC) @@ -199,7 +194,6 @@ message(STATUS " Library features:") message(STATUS " Build shared libraries: ${WITH_SHARED_LIB}") message(STATUS " Build static libraries: ${WITH_STATIC_LIB}") message(STATUS " Build with Boost static link library: ${WITH_BOOST_STATIC}") -message(STATUS " Build with boost/tr1/functional (forced) ${WITH_BOOST_FUNCTIONAL}") message(STATUS " Build with C++ std::thread support: ${WITH_STDTHREADS}") message(STATUS " Build with libevent support: ${WITH_LIBEVENT}") message(STATUS " Build with OpenSSL support: ${WITH_OPENSSL}") From 7f8aef709937fb0a033ba89eade671a989d16f96 Mon Sep 17 00:00:00 2001 From: cyy Date: Sun, 6 Jan 2019 10:05:50 +0800 Subject: [PATCH 119/756] replace boost::atomic with std::atomic --- lib/cpp/src/thrift/server/TThreadPoolServer.h | 6 +++--- lib/cpp/src/thrift/transport/TFileTransport.h | 7 +++---- lib/cpp/test/TServerIntegrationTest.cpp | 12 ++++++------ 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/lib/cpp/src/thrift/server/TThreadPoolServer.h b/lib/cpp/src/thrift/server/TThreadPoolServer.h index a957b473dbf..121998c4d2f 100644 --- a/lib/cpp/src/thrift/server/TThreadPoolServer.h +++ b/lib/cpp/src/thrift/server/TThreadPoolServer.h @@ -20,7 +20,7 @@ #ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_ #define _THRIFT_SERVER_TTHREADPOOLSERVER_H_ 1 -#include +#include #include #include @@ -90,8 +90,8 @@ class TThreadPoolServer : public TServerFramework { virtual void onClientDisconnected(TConnectedClient* pClient) /* override */; std::shared_ptr threadManager_; - boost::atomic timeout_; - boost::atomic taskExpiration_; + std::atomic timeout_; + std::atomic taskExpiration_; }; } diff --git a/lib/cpp/src/thrift/transport/TFileTransport.h b/lib/cpp/src/thrift/transport/TFileTransport.h index 4fbdd9ec643..6cc7bd24b01 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.h +++ b/lib/cpp/src/thrift/transport/TFileTransport.h @@ -24,11 +24,10 @@ #include #include +#include #include #include -#include - #include #include #include @@ -347,11 +346,11 @@ class TFileTransport : public TFileReaderTransport, public TFileWriterTransport // conditions used to block when the buffer is full or empty Monitor notFull_, notEmpty_; - boost::atomic closing_; + std::atomic closing_; // To keep track of whether the buffer has been flushed Monitor flushed_; - boost::atomic forceFlush_; + std::atomic forceFlush_; // Mutex that is grabbed when enqueueing and swapping the read/write buffers Mutex mutex_; diff --git a/lib/cpp/test/TServerIntegrationTest.cpp b/lib/cpp/test/TServerIntegrationTest.cpp index 3723679123c..7976c8bcf60 100644 --- a/lib/cpp/test/TServerIntegrationTest.cpp +++ b/lib/cpp/test/TServerIntegrationTest.cpp @@ -18,8 +18,8 @@ */ #define BOOST_TEST_MODULE TServerIntegrationTest +#include #include -#include #include #include #include @@ -310,10 +310,10 @@ class TServerIntegrationTestFixture { shared_ptr pProtocol(new TBinaryProtocol(pSocket)); ParentServiceClient client(pProtocol); pSocket->open(); - bStressConnectionCount.fetch_add(1, boost::memory_order_relaxed); + bStressConnectionCount.fetch_add(1, std::memory_order_relaxed); for (int i = 0; i < rand() % 1000; ++i) { client.incrementGeneration(); - bStressRequestCount.fetch_add(1, boost::memory_order_relaxed); + bStressRequestCount.fetch_add(1, std::memory_order_relaxed); } } } @@ -321,9 +321,9 @@ class TServerIntegrationTestFixture { shared_ptr pServer; shared_ptr pEventHandler; shared_ptr pServerThread; - boost::atomic bStressDone; - boost::atomic_int64_t bStressConnectionCount; - boost::atomic_int64_t bStressRequestCount; + std::atomic bStressDone; + std::atomic bStressConnectionCount; + std::atomic bStressRequestCount; }; template From 7007506960437a51fad46a2426ebadee50b7817f Mon Sep 17 00:00:00 2001 From: cyy Date: Sun, 6 Jan 2019 10:12:45 +0800 Subject: [PATCH 120/756] replace boost static_assert with static_assert --- lib/cpp/src/thrift/protocol/TBase64Utils.cpp | 2 -- lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc | 8 ++++---- lib/cpp/src/thrift/protocol/TCompactProtocol.tcc | 8 ++++---- lib/cpp/src/thrift/protocol/TDebugProtocol.cpp | 1 - lib/cpp/src/thrift/protocol/THeaderProtocol.cpp | 1 - lib/cpp/src/thrift/protocol/TProtocol.h | 3 +-- 6 files changed, 9 insertions(+), 14 deletions(-) diff --git a/lib/cpp/src/thrift/protocol/TBase64Utils.cpp b/lib/cpp/src/thrift/protocol/TBase64Utils.cpp index beb76ebdff5..7474f5af8ce 100644 --- a/lib/cpp/src/thrift/protocol/TBase64Utils.cpp +++ b/lib/cpp/src/thrift/protocol/TBase64Utils.cpp @@ -19,8 +19,6 @@ #include -#include - using std::string; namespace apache { diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc index d6f6dbb3d88..902ef9853f1 100644 --- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc +++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc @@ -165,8 +165,8 @@ uint32_t TBinaryProtocolT::writeI64(const int64_t i64) { template uint32_t TBinaryProtocolT::writeDouble(const double dub) { - BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); - BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + static_assert(sizeof(double) == sizeof(uint64_t)); + static_assert(std::numeric_limits::is_iec559); uint64_t bits = bitwise_cast(dub); bits = ByteOrder_::toWire64(bits); @@ -388,8 +388,8 @@ uint32_t TBinaryProtocolT::readI64(int64_t& i64) { template uint32_t TBinaryProtocolT::readDouble(double& dub) { - BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); - BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + static_assert(sizeof(double) == sizeof(uint64_t)); + static_assert(std::numeric_limits::is_iec559); union bytes { uint8_t b[8]; diff --git a/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc b/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc index d40c3313431..2b8207aa575 100644 --- a/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc +++ b/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc @@ -253,8 +253,8 @@ uint32_t TCompactProtocolT::writeI64(const int64_t i64) { */ template uint32_t TCompactProtocolT::writeDouble(const double dub) { - BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); - BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + static_assert(sizeof(double) == sizeof(uint64_t)); + static_assert(std::numeric_limits::is_iec559); uint64_t bits = bitwise_cast(dub); bits = THRIFT_htolell(bits); @@ -653,8 +653,8 @@ uint32_t TCompactProtocolT::readI64(int64_t& i64) { */ template uint32_t TCompactProtocolT::readDouble(double& dub) { - BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); - BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + static_assert(sizeof(double) == sizeof(uint64_t)); + static_assert(std::numeric_limits::is_iec559); union { uint64_t bits; diff --git a/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp b/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp index d3c6bebf3a1..0e6d4a2aac3 100644 --- a/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/TDebugProtocol.cpp @@ -24,7 +24,6 @@ #include #include #include -#include using std::string; diff --git a/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp b/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp index a19d545059a..6242e30b854 100644 --- a/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/THeaderProtocol.cpp @@ -26,7 +26,6 @@ #include -#include #include namespace apache { diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h index 28e1bb734b5..746973db9f7 100644 --- a/lib/cpp/src/thrift/protocol/TProtocol.h +++ b/lib/cpp/src/thrift/protocol/TProtocol.h @@ -29,7 +29,6 @@ #include #include -#include #ifdef HAVE_NETINET_IN_H #include @@ -48,7 +47,7 @@ // http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html template static inline To bitwise_cast(From from) { - BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To)); + static_assert(sizeof(From) == sizeof(To)); // BAD!!! These are all broken with -O2. //return *reinterpret_cast(&from); // BAD!!! From 77d26e2e5c2f9624f6d4b5f20819448164a7ae1b Mon Sep 17 00:00:00 2001 From: cyy Date: Sun, 6 Jan 2019 10:17:35 +0800 Subject: [PATCH 121/756] replace boost unique_ptr with std::unique_ptr --- lib/cpp/src/thrift/transport/TFileTransport.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/cpp/src/thrift/transport/TFileTransport.cpp b/lib/cpp/src/thrift/transport/TFileTransport.cpp index c9f65b8b5ea..afb441198f6 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.cpp +++ b/lib/cpp/src/thrift/transport/TFileTransport.cpp @@ -25,13 +25,6 @@ #include #include -#if (BOOST_VERSION >= 105700) -#include -using boost::movelib::unique_ptr; -#else -#include -using boost::interprocess::unique_ptr; -#endif #ifdef HAVE_SYS_TIME_H #include @@ -49,6 +42,7 @@ using boost::interprocess::unique_ptr; #include #include #include +#include #ifdef HAVE_SYS_STAT_H #include #endif @@ -203,8 +197,6 @@ void TFileTransport::write(const uint8_t* buf, uint32_t len) { enqueueEvent(buf, len); } -// this is needed until boost 1.57 as the older unique_ptr implementation -// has no default deleter in interprocess template struct uniqueDeleter { @@ -228,7 +220,7 @@ void TFileTransport::enqueueEvent(const uint8_t* buf, uint32_t eventLen) { return; } - unique_ptr > toEnqueue(new eventInfo()); + std::unique_ptr > toEnqueue(new eventInfo()); toEnqueue->eventBuff_ = new uint8_t[(sizeof(uint8_t) * eventLen) + 4]; // first 4 bytes is the event length From 863262dad7ee2719a6699d564a249dfea7480032 Mon Sep 17 00:00:00 2001 From: cyy Date: Sun, 6 Jan 2019 10:40:58 +0800 Subject: [PATCH 122/756] add static_assert message --- lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc | 8 ++++---- lib/cpp/src/thrift/protocol/TCompactProtocol.tcc | 8 ++++---- lib/cpp/src/thrift/protocol/TProtocol.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc index 902ef9853f1..fe739928212 100644 --- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc +++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc @@ -165,8 +165,8 @@ uint32_t TBinaryProtocolT::writeI64(const int64_t i64) { template uint32_t TBinaryProtocolT::writeDouble(const double dub) { - static_assert(sizeof(double) == sizeof(uint64_t)); - static_assert(std::numeric_limits::is_iec559); + static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); + static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); uint64_t bits = bitwise_cast(dub); bits = ByteOrder_::toWire64(bits); @@ -388,8 +388,8 @@ uint32_t TBinaryProtocolT::readI64(int64_t& i64) { template uint32_t TBinaryProtocolT::readDouble(double& dub) { - static_assert(sizeof(double) == sizeof(uint64_t)); - static_assert(std::numeric_limits::is_iec559); + static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); + static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); union bytes { uint8_t b[8]; diff --git a/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc b/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc index 2b8207aa575..8efec6edc29 100644 --- a/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc +++ b/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc @@ -253,8 +253,8 @@ uint32_t TCompactProtocolT::writeI64(const int64_t i64) { */ template uint32_t TCompactProtocolT::writeDouble(const double dub) { - static_assert(sizeof(double) == sizeof(uint64_t)); - static_assert(std::numeric_limits::is_iec559); + static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); + static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); uint64_t bits = bitwise_cast(dub); bits = THRIFT_htolell(bits); @@ -653,8 +653,8 @@ uint32_t TCompactProtocolT::readI64(int64_t& i64) { */ template uint32_t TCompactProtocolT::readDouble(double& dub) { - static_assert(sizeof(double) == sizeof(uint64_t)); - static_assert(std::numeric_limits::is_iec559); + static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); + static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); union { uint64_t bits; diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h index 746973db9f7..bbc6816cedf 100644 --- a/lib/cpp/src/thrift/protocol/TProtocol.h +++ b/lib/cpp/src/thrift/protocol/TProtocol.h @@ -47,7 +47,7 @@ // http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html template static inline To bitwise_cast(From from) { - static_assert(sizeof(From) == sizeof(To)); + static_assert(sizeof(From) == sizeof(To), "sizeof(From) == sizeof(To)"); // BAD!!! These are all broken with -O2. //return *reinterpret_cast(&from); // BAD!!! From 5e16f8b9086ce9bf4fa74993ecc51a7b9354f51e Mon Sep 17 00:00:00 2001 From: cyy Date: Sun, 6 Jan 2019 10:49:20 +0800 Subject: [PATCH 123/756] set c++11 in proper place --- build/cmake/DefineCMakeDefaults.cmake | 17 +++++++---------- build/cmake/DefinePlatformSpecifc.cmake | 11 ----------- 2 files changed, 7 insertions(+), 21 deletions(-) diff --git a/build/cmake/DefineCMakeDefaults.cmake b/build/cmake/DefineCMakeDefaults.cmake index 65ccc69a121..93255e05cdb 100644 --- a/build/cmake/DefineCMakeDefaults.cmake +++ b/build/cmake/DefineCMakeDefaults.cmake @@ -73,19 +73,16 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # C++ Language Level Defaults - this depends on the compiler capabilities # if (NOT DEFINED CMAKE_CXX_STANDARD) - if (MSVC AND MSVC_VERSION LESS 1800) - # MSVC 2012 and earlier don't support template aliases so you have to use C++98 - set(CMAKE_CXX_STANDARD 98) - message(STATUS "Setting C++98 as the default language level (for an older MSVC compiler).") - else() - set(CMAKE_CXX_STANDARD 11) # C++11 - message(STATUS "Setting C++11 as the default language level.") - endif() + set(CMAKE_CXX_STANDARD 11) # C++11 + message(STATUS "Setting C++11 as the default language level.") message(STATUS "To specify a different C++ language level, set CMAKE_CXX_STANDARD") endif() -if (NOT DEFINED CMAKE_CXX_STANDARD_REQUIRED) - set(CMAKE_CXX_STANDARD_REQUIRED OFF) # can degrade to C++98 if compiler does not support C++11 +if (CMAKE_CXX_STANDARD EQUAL 98) + message(FATAL_ERROR "only C++11 or above C++ standard is supported") +elseif (CMAKE_CXX_STANDARD EQUAL 11) + # should not fallback to C++98 + set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() if (NOT DEFINED CMAKE_CXX_EXTENSIONS) diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index 98fb589583e..3f112b625fc 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -95,17 +95,6 @@ if(WITH_STDTHREADS) endif() # C++ Language Level -if (NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 11) -elseif (CMAKE_CXX_STANDARD EQUAL 98) - message(FATAL_ERROR "only C++11 or above C++ standard is supported") -endif() - -if (CMAKE_CXX_STANDARD EQUAL 11) - # should not fallback to C++98 - set(CMAKE_CXX_STANDARD_REQUIRED ON) -endif() - set(CXX_LANGUAGE_LEVEL "C++${CMAKE_CXX_STANDARD}") if (CMAKE_CXX_STANDARD_REQUIRED) string(CONCAT CXX_LANGUAGE_LEVEL "${CXX_LANGUAGE_LEVEL} [compiler must support it]") From 1f34504f43a7a409364d4114f180762bf2679e57 Mon Sep 17 00:00:00 2001 From: cyy Date: Sun, 6 Jan 2019 11:19:38 +0800 Subject: [PATCH 124/756] remove unused boost headers --- lib/cpp/src/thrift/Thrift.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/cpp/src/thrift/Thrift.h b/lib/cpp/src/thrift/Thrift.h index b41d5d2a06f..63227426d97 100644 --- a/lib/cpp/src/thrift/Thrift.h +++ b/lib/cpp/src/thrift/Thrift.h @@ -42,9 +42,6 @@ #include #include -#include -#include - #include #include From 0140cbf5674c5573d142c95c182f4ba98de99769 Mon Sep 17 00:00:00 2001 From: cyy Date: Sun, 6 Jan 2019 11:21:10 +0800 Subject: [PATCH 125/756] remove unused variables --- compiler/cpp/src/thrift/generate/t_erl_generator.cc | 2 -- compiler/cpp/src/thrift/generate/t_go_generator.cc | 3 --- compiler/cpp/src/thrift/generate/t_hs_generator.cc | 4 ---- compiler/cpp/src/thrift/generate/t_py_generator.cc | 2 -- lib/c_glib/test/testbufferedtransport.c | 3 --- lib/c_glib/test/testframedtransport.c | 3 --- lib/c_glib/test/testtransportsocket.c | 3 --- lib/cpp/src/thrift/protocol/TJSONProtocol.cpp | 1 - 8 files changed, 21 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_erl_generator.cc b/compiler/cpp/src/thrift/generate/t_erl_generator.cc index 587133f8cb2..12d91a70649 100644 --- a/compiler/cpp/src/thrift/generate/t_erl_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_erl_generator.cc @@ -415,7 +415,6 @@ const std::string emit_double_as_string(const double value) { } void t_erl_generator::generate_type_metadata(std::string function_name, vector names) { - vector::iterator s_iter; size_t num_structs = names.size(); indent(f_types_file_) << function_name << "() ->\n"; @@ -947,7 +946,6 @@ void t_erl_generator::generate_service(t_service* tservice) { void t_erl_generator::generate_service_metadata(t_service* tservice) { export_string("function_names", 0); vector functions = tservice->get_functions(); - vector::iterator f_iter; size_t num_functions = functions.size(); indent(f_service_) << "function_names() -> " << endl; diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index 5ada4fa813f..ec16b87b87b 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -2153,7 +2153,6 @@ void t_go_generator::generate_service_remote(t_service* tservice) { << (*f_iter)->get_name() << "("; t_struct* arg_struct = (*f_iter)->get_arglist(); const std::vector& args = arg_struct->get_members(); - vector::const_iterator a_iter; std::vector::size_type num_args = args.size(); bool first = true; @@ -2308,7 +2307,6 @@ void t_go_generator::generate_service_remote(t_service* tservice) { for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* arg_struct = (*f_iter)->get_arglist(); const std::vector& args = arg_struct->get_members(); - vector::const_iterator a_iter; std::vector::size_type num_args = args.size(); string funcName((*f_iter)->get_name()); string pubName(publicize(funcName)); @@ -2693,7 +2691,6 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function* // t_struct* xs = tfunction->get_xceptions(); // const std::vector& xceptions = xs->get_members(); - vector::const_iterator x_iter; f_types_ << indent() << "type " << processorName << " struct {" << endl; f_types_ << indent() << " handler " << publicize(tservice->get_name()) << endl; f_types_ << indent() << "}" << endl << endl; diff --git a/compiler/cpp/src/thrift/generate/t_hs_generator.cc b/compiler/cpp/src/thrift/generate/t_hs_generator.cc index ce7cd0c76c9..8f6d4b0c731 100644 --- a/compiler/cpp/src/thrift/generate/t_hs_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_hs_generator.cc @@ -590,7 +590,6 @@ void t_hs_generator::generate_hs_struct_arbitrary(ostream& out, t_struct* tstruc string tname = type_name(tstruct); string name = tstruct->get_name(); const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; indent(out) << "instance QC.Arbitrary " << tname << " where " << endl; indent_up(); @@ -654,7 +653,6 @@ void t_hs_generator::generate_hs_struct_arbitrary(ostream& out, t_struct* tstruc */ void t_hs_generator::generate_hs_struct_reader(ostream& out, t_struct* tstruct) { const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; string sname = type_name(tstruct); string id = tmp("_id"); @@ -725,7 +723,6 @@ void t_hs_generator::generate_hs_struct_reader(ostream& out, t_struct* tstruct) void t_hs_generator::generate_hs_struct_writer(ostream& out, t_struct* tstruct) { string name = type_name(tstruct); const vector& fields = tstruct->get_sorted_members(); - vector::const_iterator f_iter; string str = tmp("_str"); string f = tmp("_f"); string v = tmp("_v"); @@ -909,7 +906,6 @@ void t_hs_generator::generate_hs_function_helpers(t_function* tfunction) { void t_hs_generator::generate_hs_typemap(ostream& out, t_struct* tstruct) { string name = type_name(tstruct); const vector& fields = tstruct->get_sorted_members(); - vector::const_iterator f_iter; indent(out) << "typemap_" << name << " :: T.TypeMap" << endl; indent(out) << "typemap_" << name << " = Map.fromList ["; diff --git a/compiler/cpp/src/thrift/generate/t_py_generator.cc b/compiler/cpp/src/thrift/generate/t_py_generator.cc index f0a153ca8b9..e46207a7c7a 100644 --- a/compiler/cpp/src/thrift/generate/t_py_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_py_generator.cc @@ -1624,7 +1624,6 @@ void t_py_generator::generate_service_remote(t_service* tservice) { << (*f_iter)->get_name() << "("; t_struct* arg_struct = (*f_iter)->get_arglist(); const std::vector& args = arg_struct->get_members(); - vector::const_iterator a_iter; std::vector::size_type num_args = args.size(); bool first = true; for (std::vector::size_type i = 0; i < num_args; ++i) { @@ -1730,7 +1729,6 @@ void t_py_generator::generate_service_remote(t_service* tservice) { t_struct* arg_struct = (*f_iter)->get_arglist(); const std::vector& args = arg_struct->get_members(); - vector::const_iterator a_iter; std::vector::size_type num_args = args.size(); f_remote << "if cmd == '" << (*f_iter)->get_name() << "':" << endl; diff --git a/lib/c_glib/test/testbufferedtransport.c b/lib/c_glib/test/testbufferedtransport.c index c6e6b581d33..d01806d6132 100755 --- a/lib/c_glib/test/testbufferedtransport.c +++ b/lib/c_glib/test/testbufferedtransport.c @@ -175,11 +175,8 @@ test_read_and_write(void) static void thrift_socket_server_open (const int port, int times) { - int bytes = 0; ThriftServerTransport *transport = NULL; ThriftTransport *client = NULL; - guchar buf[10]; /* a buffer */ - guchar match[10] = TEST_DATA; int i; ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port, NULL); diff --git a/lib/c_glib/test/testframedtransport.c b/lib/c_glib/test/testframedtransport.c index 45397cef487..008e61e40cb 100755 --- a/lib/c_glib/test/testframedtransport.c +++ b/lib/c_glib/test/testframedtransport.c @@ -249,11 +249,8 @@ test_read_after_peer_close(void) static void thrift_socket_server_open (const int port, int times) { - int bytes = 0; ThriftServerTransport *transport = NULL; ThriftTransport *client = NULL; - guchar buf[10]; /* a buffer */ - guchar match[10] = TEST_DATA; int i; ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, diff --git a/lib/c_glib/test/testtransportsocket.c b/lib/c_glib/test/testtransportsocket.c index fedbad6b69a..89c61b91019 100755 --- a/lib/c_glib/test/testtransportsocket.c +++ b/lib/c_glib/test/testtransportsocket.c @@ -291,11 +291,8 @@ test_peek(void) static void thrift_socket_server_open (const int port, int times) { - int bytes = 0; ThriftServerTransport *transport = NULL; ThriftTransport *client = NULL; - guchar buf[10]; /* a buffer */ - guchar match[10] = TEST_DATA; int i; ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port, NULL); diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp index 40eb7ad9ae0..4576fa16672 100644 --- a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp @@ -49,7 +49,6 @@ static const uint8_t kJSONPairSeparator = ':'; static const uint8_t kJSONElemSeparator = ','; static const uint8_t kJSONBackslash = '\\'; static const uint8_t kJSONStringDelimiter = '"'; -static const uint8_t kJSONZeroChar = '0'; static const uint8_t kJSONEscapeChar = 'u'; static const std::string kJSONEscapePrefix("\\u00"); From caf7da976755694ee2a905cc8b85e36852f87558 Mon Sep 17 00:00:00 2001 From: Ozan Can Altiok Date: Mon, 7 Jan 2019 14:14:11 +0300 Subject: [PATCH 126/756] automatize the double rendering test --- lib/js/Gruntfile.js | 3 ++- lib/js/test/test-double-rendering.html | 6 +++--- lib/js/test/test-double-rendering.js | 22 ++-------------------- 3 files changed, 7 insertions(+), 24 deletions(-) diff --git a/lib/js/Gruntfile.js b/lib/js/Gruntfile.js index bb7691a0a02..b32a016b8e0 100644 --- a/lib/js/Gruntfile.js +++ b/lib/js/Gruntfile.js @@ -270,7 +270,7 @@ module.exports = function(grunt) { grunt.registerTask('installAndGenerate', [ 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen', - 'shell:ThriftGenDeepConstructor', + 'shell:ThriftGenDeepConstructor', 'shell:ThriftGenDoubleConstants', 'shell:InstallTestLibs', ]); @@ -282,6 +282,7 @@ module.exports = function(grunt) { 'wait', 'qunit:ThriftDeepConstructor', 'qunit:ThriftJS', 'qunit:ThriftJS_TLS', + 'qunit:ThriftJS_DoubleRendering', 'qunit:ThriftWS', 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS', 'qunit:ThriftWSES6', diff --git a/lib/js/test/test-double-rendering.html b/lib/js/test/test-double-rendering.html index 240cb3946c3..7a430a50796 100644 --- a/lib/js/test/test-double-rendering.html +++ b/lib/js/test/test-double-rendering.html @@ -29,11 +29,11 @@ - + - - + + diff --git a/lib/js/test/test-double-rendering.js b/lib/js/test/test-double-rendering.js index b4b79b8dfe5..1790c1b80d0 100644 --- a/lib/js/test/test-double-rendering.js +++ b/lib/js/test/test-double-rendering.js @@ -20,29 +20,11 @@ /* * JavaScript test suite for double constants inside - * DebugProtoTest.thrift. These tests will run against Normal (-gen js) + * DoubleConstantsTest.thrift. These tests will run against Normal (-gen js) * Apache Thrift interfaces. * - * Synchronous blocking calls should be identical in both - * Normal and jQuery interfaces. All synchronous tests belong - * here. - * - * Asynchronous success callbacks passed as the last parameter - * of an RPC call should be identical in both Normal and jQuery - * interfaces. Async success tests belong here. - * - * Asynchronous exception processing is different in Normal - * and jQuery interfaces. Such tests belong in the test-nojq.js - * or test-jq.js files respectively. jQuery specific XHR object - * tests also belong in test-jq.js. Do not create any jQuery - * dependencies in this file or in test-nojq.js - * * To compile client code for this test use: - * $ thrift -gen js ThriftTest.thrift - * $ thrift -gen js DebugProtoTest.thrift - * - * See also: - * ++ test-nojq.js for "-gen js" only tests + * $ thrift -gen js DoubleConstantsTest.thrift */ // double assertion threshold From e824efcb7935e019998264b8982ad5e51858879e Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 7 Jan 2019 16:50:54 -0500 Subject: [PATCH 127/756] add/move a couple build related tools around --- build/fixchanges.sh | 39 ++++++++++++++++++++++++++++++++ veralign.sh => build/veralign.sh | 2 +- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100755 build/fixchanges.sh rename veralign.sh => build/veralign.sh (99%) diff --git a/build/fixchanges.sh b/build/fixchanges.sh new file mode 100755 index 00000000000..6c57b5497ba --- /dev/null +++ b/build/fixchanges.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# +# fixchanges will take a file as input and look for text matching +# the pattern [THRIFT-nnnn] (the number of digits is not important) +# which is not a markdown link, and change it to be a markdown link. +# The tool writes to stdout so you can redirect it to a temporary +# file and then compare against the original file before replacing +# it. +# +# This tool was developed after the 0.12.0 release to assist with +# generation of CHANGES.md content. +# + +while IFS='' read -r line || [[ -n "$line" ]]; do + if [[ "$line" =~ ^(.*)\[(THRIFT-[[:digit:]]+)\][^\(](.*)$ ]]; then + echo "${BASH_REMATCH[1]}[${BASH_REMATCH[2]}](https://issues.apache.org/jira/browse/${BASH_REMATCH[2]}) ${BASH_REMATCH[3]}" + else + echo "$line" + fi +done < "$1" diff --git a/veralign.sh b/build/veralign.sh similarity index 99% rename from veralign.sh rename to build/veralign.sh index 380aa48311e..61744b43261 100755 --- a/veralign.sh +++ b/build/veralign.sh @@ -43,7 +43,7 @@ declare -A FILES # These files require a manual touch: -FILES[CHANGES]=manual +FILES[CHANGES.md]=manual FILES[debian/changelog]=manual FILES[doap.rdf]=manual From c9ac8d2953a4806cc93aa4ff2e700623ecad980c Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 7 Jan 2019 16:46:45 -0500 Subject: [PATCH 128/756] THRIFT-4720: documenting breaking changes, minor cleanup --- CHANGES | 2918 ----------------- CHANGES.md | 2916 ++++++++++++++++ CMakeLists.txt | 43 +- LANGUAGES.md | 2 +- Makefile.am | 2 +- appveyor.yml | 10 +- build/appveyor/MSVC-appveyor-build.bat | 15 + build/cmake/BoostMacros.cmake | 41 + build/cmake/DefineCMakeDefaults.cmake | 4 - build/cmake/DefineOptions.cmake | 22 +- build/docker/scripts/cmake.sh | 3 +- build/veralign.sh | 4 +- .../src/thrift/generate/t_c_glib_generator.cc | 6 +- .../cpp/src/thrift/generate/t_cl_generator.cc | 2 +- compiler/cpp/src/thrift/windows/config.h | 21 +- compiler/cpp/test/CMakeLists.txt | 7 +- lib/c_glib/test/CMakeLists.txt | 2 +- lib/cpp/CMakeLists.txt | 5 +- lib/cpp/README.md | 103 +- lib/cpp/test/CMakeLists.txt | 10 +- test/cpp/CMakeLists.txt | 8 +- tutorial/cpp/CMakeLists.txt | 3 +- 22 files changed, 3069 insertions(+), 3078 deletions(-) delete mode 100644 CHANGES create mode 100644 CHANGES.md create mode 100644 build/cmake/BoostMacros.cmake diff --git a/CHANGES b/CHANGES deleted file mode 100644 index 244f0da2feb..00000000000 --- a/CHANGES +++ /dev/null @@ -1,2918 +0,0 @@ -Apache Thrift Changelog - -================================================================================ -Thrift 0.12.0 --------------------------------------------------------------------------------- -## New Languages - * Common LISP (cl) - * Swift - * Typescript (nodets) - -## Deprecated Languages - * Cocoa - -## Breaking Changes (since 0.11.0) - * [THRIFT-4529] - Rust enum variants are now camel-cased instead of uppercased to conform to Rust naming conventions - * [THRIFT-4448] - Support for golang 1.6 and earlier has been dropped. - * [THRIFT-4474] - PHP now uses the PSR-4 loader by default instead of class maps. - * [THRIFT-4532] - method signatures changed in the compiler's t_oop_generator. - * [THRIFT-4648] - The C (GLib) compiler's handling of namespaces has been improved. - -## Known Issues (Blocker or Critical) - * [THRIFT-4037] - build: use a single build system for thrift - * [THRIFT-4119] - build: bootstrap.sh is missing from source tarball - * [THRIFT-3289] - csharp: socket exhaustion in csharp implementation - * [THRIFT-3029] - cocoa: Getters for fields defined with uppercase names do not work - * [THRIFT-3325] - cocoa: Extended services aren't subclasses in generated Cocoa - * [THRIFT-4116] - cocoa: Thrift de-capitalizes the name of IsSet property in Cocoa - * [THRIFT-3877] - cpp: the http implementation is not standard; interop with other languages is spotty at best - * [THRIFT-4180] - cpp: Impossible to build Thrift C++ library for Android (NDK) - * [THRIFT-4384] - cpp: Using multiple async services simultaneously is not thread-safe - * [THRIFT-3108] - haskell: Defaulted struct parameters on a service generates invalid Haskell - * [THRIFT-3990] - nodejs: Exception swallowed by deserialization function - * [THRIFT-4214] - nodejs: map key treated as hex value in JavaScript - * [THRIFT-4602] - nodejs: ERROR in ./node_modules/thrift/lib/nodejs/lib/thrift/connection.js Module not found: Error: Can't resolve 'child_process' - * [THRIFT-4639] - nodejs: Sequence numbering for multiplexed protocol broken - * [THRIFT-1310] - php: sequence and reconnection management issues - * [THRIFT-1538] - php: Error during deserialization int64 on 32-bit architecture - * [THRIFT-1580] - php: thrift type i64 java to php serialize/deserealize not working - * [THRIFT-1950] - php: PHP gets stuck in infinite loop - * [THRIFT-2954] - python: sending int or float in a double field breaks the connection - * [THRIFT-4080] - python: unix sockets can get stuck forever - * [THRIFT-4281] - python: generated code is out of order and causes load issues - * [THRIFT-4677] - py3: UnicodeDecideError in Python3 - -## Build Process - * [THRIFT-4067] - Windows thrift compiler distributed on the apache web site has runtime dependencies - * [THRIFT-4308] - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang - * [THRIFT-4579] - Use Ubuntu Bionic (18.04 LTS) for CI builds instead of Artful (17.10) - * [THRIFT-4508] - Define CI operating system coverage rules for the project and (hopefully) simplify CI a little more - * [THRIFT-4397] - ubuntu install instructions broken on 16.04 - * [THRIFT-4545] - Appveyor builds are failing due to a haskell / cabal update in chocolatey - * [THRIFT-4452] - optimize Dockerfile (only onetime apt-get update) - * [THRIFT-4440] - rm `build/docker/ubuntu-trusty/Dockerfile.orig` - * [THRIFT-4352] - Ubuntu Artful doesn't appear to be compatible with Thrift and Haxe 3.4.2 - * [THRIFT-4666] - DLang Client Pool Test fails sporadically - * [THRIFT-4676] - CL tutorial build fails sporadically - * [THRIFT-4456] - Make haxelib download quiet so it doesn't blow up the build log - * [THRIFT-4605] - bootstrap.sh fails if automake=1.16.1 - -## c_glib - * [THRIFT-4648] - The C (GLib) compiler's handling of namespaces has been improved. - * [THRIFT-4622] - glibC compilation issue - * [THRIFT-4671] - c glib is unable to handle client close unexpectedly - -## cl (new language support in 0.12.0) - * [THRIFT-82] - Common Lisp support - -## csharp - * [THRIFT-4558] - reserved Csharp keywords are not escaped in some cases - * [THRIFT-4637] - C# async mode generates incorrect code with inherited services - * [THRIFT-4672] - IAsyncResult style methods not being supported by certain transports leads to issues in mixed ISync/IAsync use cases - * [THRIFT-4539] - Allow TBufferedTransport to be used as base class - * [THRIFT-4535] - XML docs; code cleanup (tabs->spaces; String->string) - * [THRIFT-4492] - protected ExceptionType type member of TApplicationException cannot be accessed - * [THRIFT-4446] - JSONProtocol Base64 Encoding Trims Padding - * [THRIFT-4455] - Missing dispose calls in ThreadedServer & ThreadpoolServer - * [THRIFT-4609] - keep InnerException wherever appropriate - * [THRIFT-4673] - IAsyncResult not supported by layered transports (buffered/framed) - -## cpp - * [THRIFT-4476] - Typecasting problem on list items - * [THRIFT-4465] - TNonblockingServer throwing THRIFT LOGGER: TConnection::workSocket(): THRIFT_EAGAIN (unavailable resources) - * [THRIFT-4680] - TBufferTransports.h does not compile under Visual Studio 2017 - * [THRIFT-4618] - TNonblockingServer crash because of limitation of select() - * [THRIFT-4620] - TZlibTransport.cpp doesn't ensure that there is enough space for the zlib flush marker in the buffer. - * [THRIFT-4571] - ZeroMQ contrib library needs a refresh - * [THRIFT-4559] - TSSLServerSocket incorrectly prints errors - * [THRIFT-4578] - Move `TAsyncProtocolProcessor` into main thrift library - * [THRIFT-4418] - evhttp_connection_new is deprecated; use evhttp_connection_base_new - -## compiler - * [THRIFT-4644] - Compiler cannot be compiled on macOS(maybe also on other platforms with clang) - * [THRIFT-4531] - Thrift generates wrong Python code for immutable structures with optional members - * [THRIFT-4513] - thrift generated code is not stable for constants - * [THRIFT-4532] - Avoid updating Thrift compiler generated code if the output has not changed - * [THRIFT-4400] - Visual Studio Compiler project should link runtime statically in release builds - * [THRIFT-4399] - plugin.thrift t_const_value is not used as a union in C++ code -- fix this - * [THRIFT-4496] - Dealing with language keywords in Thrift (e.g. service method names) - * [THRIFT-4393] - repeated runs of compiler produce different binary output at plugin interface - -## dlang - * [THRIFT-4478] - Thrift will not build with dlang 2.078 or later - * [THRIFT-4503] - dlang servers logError on normal client disconnection - * [THRIFT-4308] - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang - -## dart - * [THRIFT-4646] - Effective Dart and Exceptions - * [THRIFT-4439] - Shouldn't download dart.deb directly. - -## delphi - * [THRIFT-4562] - Calling wrong exception CTOR leads to "call failed: unknown result" instead of the real exception being thrown - * [THRIFT-4554] - uncompileable code with member names that are also types under specific conditions - * [THRIFT-4422] - Add Async implementation via IFuture - * [THRIFT-4485] - Possible invalid ptr AV with overlapped read/write on pipes - * [THRIFT-4549] - Thrift exceptions should derive from TException - * [THRIFT-4540] - buffered transport broken when trying to re-open a formerly closed transport - * [THRIFT-4473] - Move Thrift.Console.pas out of the Library - * [THRIFT-4490] - Allow a default service as fallback for multiplex processors connected by old clients - * [THRIFT-4454] - Large writes/reads may cause range check errors in debug mode - * [THRIFT-4461] - Compiler directive should match Delphi XE4 - * [THRIFT-4462] - First line in Console duplicated - * [THRIFT-4642] - FPU ctrl word settings may cause an unexpected "denormalized" error - * [THRIFT-4589] - HTTP client timeouts are a) incomplete and b) not used at all - * [THRIFT-4590] - running the test client using HTTP transport leads to "CoInitialize not called" - -## erlang - * [THRIFT-4497] - Erlang records should use map() for map type - * [THRIFT-4495] - Erlang records should allow 'undefined' for non-required fields - * [THRIFT-4580] - Fix erlang tutorial unpack on Windows - * [THRIFT-4582] - Ubuntu Xenial erlang 18.3 "make check" fails - -## golang - * [THRIFT-4448] - Support for golang 1.6 and earlier has been dropped. - * [THRIFT-4253] - Go generator assigns strings to field in const instead of pointers. - * [THRIFT-4573] - Unions Field Count Does Not Consider Binary - * [THRIFT-4447] - Golang: Panic on p.c.Call when using deprecated initializers - * [THRIFT-4650] - Required field incorrectly marked as set when fieldType does not match - * [THRIFT-4486] - Golang: -remote.go client cleanup - * [THRIFT-4537] - TSimpleServer can exit Accept loop with lock still acquired - * [THRIFT-4516] - Add support for go 1.10 - * [THRIFT-4421] - golang tests rely on gomock, which has change behaviour, causing tests to fail - * [THRIFT-4626] - Communication crash when using binary/compact protocol and zlib transport - * [THRIFT-4659] - golang race detected when closing listener socket - -## haskell - * [THRIFT-4634] - Haskell builds with older cabal cannot reconcile complex version requirements - -## java - * [THRIFT-4259] - Thrift does not compile due to Ant Maven task errors - * [THRIFT-1418] - Compiling Thrift from source: Class org.apache.tools.ant.taskdefs.ConditionTask doesn't support the nested "typefound" element - * [THRIFT-4530] - proposal: add nullability annotations to generated Java code - * [THRIFT-4614] - Generate missing @Nullable annotations for Java iterator getters - * [THRIFT-4555] - Getter of binary field in Java creates unnecessary copy - * [THRIFT-3983] - libthrift is deployed on central with pom packaging instead of jar - * [THRIFT-4294] - Java Configure Fails for Ant >= 1.10 - * [THRIFT-4178] - Java libraries missing from package when using cmake - * [THRIFT-4120] - pom files are not generated or provided in the build - * [THRIFT-1507] - Maven can't download resource from central when behind a proxy and won't use local repository - * [THRIFT-4556] - Optional rethrow of unhandled exceptions in java processor - * [THRIFT-4337] - Able to set keyStore and trustStore as InputStream in the TSSLTransportFactory.TSSLTransportParameters - * [THRIFT-4566] - Pass message of unhandled exception to optional rethrow. - * [THRIFT-4506] - Remove assertion in Java SASL code that would be ignored in release builds - * [THRIFT-4470] - Include popular IDE file templates to gitignore - * [THRIFT-4429] - Make TThreadPoolServer.executorService_ available in inherited classes and refactor methods to be able customization - * [THRIFT-3769] - Fix logic of THRIFT-2268 - * [THRIFT-4494] - Increase Java Socket Buffer Size - * [THRIFT-4499] - Remove Magic Number In TFIleTransport - -## js - * [THRIFT-4406] - JavaScript: Use modern Promise implementations - * [THRIFT-4625] - let / const variable decorators for es6 compiler - * [THRIFT-4653] - ES6 Classes - * [THRIFT-4592] - JS: readI32 performance on large arrays is very poor in Chrome - * [THRIFT-4509] - js and nodejs libraries need to be refreshed with current libraries - * [THRIFT-4403] - thrift.js: Incorrect usage of 'this' in TWebSocketTransport.__onOpen - * [THRIFT-4436] - Deserialization of nested list discards content - * [THRIFT-4437] - JS WebSocket client callbacks invoked twice on parallel requests - * [THRIFT-4679] - Duplicate declaration of InputBufferUnderrunError in lib/nodejs/lib/thrift/json_protocol.js - * [THRIFT-4551] - Add prettier for consistent JS code formatting - -## lua - * [THRIFT-4591] - lua client uses two write() calls per framed message send - * [THRIFT-3863] - Can't "make install" Lua Library - -## netcore - * [THRIFT-4524] - .NET Core Server doesn't close properly when cancelled - * [THRIFT-4434] - Update .NET Core components, add tests for .Net Core library and .Net Core compiler, fix bugs and build process - * [THRIFT-4446] - JSONProtocol Base64 Encoding Trims Padding - -## node.js - * [THRIFT-4225] - Error handling malformed arguments leaks memory, corrupts transport buffers causing next RPC to fail - * [THRIFT-3950] - Memory leak while calling oneway method - * [THRIFT-3143] - add typescript directory support - * [THRIFT-4564] - TBufferedTransport can leave corrupt data in the buffer - * [THRIFT-4647] - Node.js Fileserver webroot path - * [THRIFT-4489] - Unix domain socket support for NodeJS client - * [THRIFT-4443] - node.js json_protocol throws error in skip function - * [THRIFT-4604] - NodeJS: Expose Int64 from browser.js for consumption by browser - * [THRIFT-4480] - NodeJS warning on binary_protocol writeMessageEnd when seqid = 0 - -## perl - * [THRIFT-4382] - Replace the use of Perl Indirect Object Syntax calls to new() - * [THRIFT-4471] - Thrift CPAN release is missing Makefile.PL and the clients are unable to build the module - * [THRIFT-4416] - Perl CPAN Packaging Improvements - -## php - * [THRIFT-4474] - PHP generator use PSR-4 default - * [THRIFT-4463] - PHP generated code match PSR-2 - * [THRIFT-4373] - Extending Thrift class results in "Attempt serialize from non-Thrift object" - * [THRIFT-4354] - TSocket block on read - * [THRIFT-4423] - migrate php library to psr-4 - * [THRIFT-4656] - infinite loop in latest PHP library - * [THRIFT-4477] - TBufferedTransport must have underlying transport - * [THRIFT-4475] - lib/php/test should be checked for PSR-2 - * [THRIFT-4498] - add phpcs back - * [THRIFT-4460] - php library use PSR-2 - * [THRIFT-4641] - TCurlClient doesn't check for HTTP status code - * [THRIFT-4645] - TCurlClient: show actual error message when throwing TTransportException - * [THRIFT-4674] - Add stream context support into PHP/THttpClient - * [THRIFT-4459] - reduce php library directory depth - -## python - * [THRIFT-4670] - Twisted, slots, and void method fails with "object has no attribute 'success'" - * [THRIFT-4464] - Potentially server-crashing typo in Python TNonblockingServer - * [THRIFT-4548] - Supporting TBinaryProtocolAccelerated protocol when using TMultiplexedProcessor in Python - * [THRIFT-4577] - Outdated cipher string in python unit test - * [THRIFT-4505] - python build on Vagrant Windows boxes fails - * [THRIFT-4621] - THeader for Python - * [THRIFT-4668] - make socket backlog configurable for python - * [THRIFT-4561] - Python: cleanup socket timeout settings - -## ruby - * [THRIFT-4289] - Thrift RSpec test suite fails with Ruby 2.4.x due to Fixnum deprecation - * [THRIFT-4342] - Support ruby rspec 3 - * [THRIFT-4525] - Add ssl socket option to ruby cross tests - * [THRIFT-4450] - Add seek support to TCompactInputProtocol in Rust - * [THRIFT-4631] - Codegen Creates Invalid Ruby for Recursive Structs - * [THRIFT-4472] - Fix the genspec for ruby so it does not complain about an invalid license - -## rust - * [THRIFT-4662] - Rust const string calls function at compile time - * [THRIFT-4661] - Rust enum name wrong case in generated structs - * [THRIFT-4617] - Avoid generating conflicting struct names in Rust code - * [THRIFT-4529] - Rust generation should include #![allow(non_snake_case)] or force conform to Rust style guidelines - * [THRIFT-4390] - Rust binary protocol and buffered transport cannot handle writes above 4096 bytes - * [THRIFT-4419] - Rust framed transport cannot handle writes above 4096 bytes - * [THRIFT-4658] - Rust's TBinaryInputProtocol fails when strict is false - * [THRIFT-4187] - Dart -> Rust Framed cross tests fail - * [THRIFT-4664] - Rust cannot create ReadHalf/WriteHalf to implement custom tranports - * [THRIFT-4665] - Keep Rust library up-to-date on crates.io - -## swift (new language support in 0.12.0) - * [THRIFT-3773] - Swift Library - -## test suite - * [THRIFT-4515] - Gracefully shutdown cross-test servers to fully test teardown - * [THRIFT-4085] - Add .NET Core to the make cross standard test suite - * [THRIFT-4358] - Add unix domain sockets in ruby to cross test - code exists - -## typescript (new language support in 0.12.0) - * [THRIFT-3143] - add typescript directory support - -================================================================================ -Thrift 0.11.0 --------------------------------------------------------------------------------- -## Sub-task - * [THRIFT-2733] - Erlang coding standards - * [THRIFT-2740] - Perl coding standards - * [THRIFT-3610] - Streamline exception handling in Python server handler - * [THRIFT-3686] - Java processor should report internal error on uncaught exception - * [THRIFT-4049] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4053] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4136] - Align is_binary() method with is_string() to simplify those checks - * [THRIFT-4137] - Fix remaining undefined behavior invalid vptr casts in Thrift Compiler - * [THRIFT-4138] - Fix remaining undefined behavior invalid vptr casts in C++ library - * [THRIFT-4296] - Fix Ubuntu Xenial build environment for the python language - * [THRIFT-4298] - Fix Ubuntu Xenial build environment for the go 1.6 language - * [THRIFT-4299] - Fix Ubuntu Xenial build environment for the D language - * [THRIFT-4300] - Fix make cross in Ubuntu Xenial docker environment, once all language support issues are fixed - * [THRIFT-4302] - Fix Ubuntu Xenial make cross testing for lua and php7 - * [THRIFT-4398] - Update EXTRA_DIST for "make dist" - -## Bug - * [THRIFT-381] - Fail fast if configure detects C++ problems - * [THRIFT-1677] - MinGW support broken - * [THRIFT-1805] - Thrift should not swallow ALL exceptions - * [THRIFT-2026] - Fix TCompactProtocol 64 bit builds - * [THRIFT-2642] - Recursive structs don't work in python - * [THRIFT-2889] - stable release 0.9.2, erlang tutorial broken - * [THRIFT-2913] - Ruby Server Thrift::ThreadPoolServer should serve inside a thread - * [THRIFT-2998] - Node.js: Missing header from http request - * [THRIFT-3000] - .NET implementation has trouble with mixed IP modes - * [THRIFT-3281] - Travis CI build passed but the log says BUILD FAILED - * [THRIFT-3358] - Makefile:1362: *** missing separator. Stop. - * [THRIFT-3600] - Make TTwisted server send exception on unexpected handler error - * [THRIFT-3602] - Make Tornado server send exception on unexpected handler error - * [THRIFT-3657] - D TFileWriterTransport close should use non-priority send - * [THRIFT-3700] - Go Map has wrong default value when optional - * [THRIFT-3703] - Unions Field Count Does Not Consider Map/Set/List Fields - * [THRIFT-3730] - server log error twice - * [THRIFT-3778] - go client can not pass method parameter to server of other language if no field_id is given - * [THRIFT-3784] - thrift-maven-plugin generates invalid include directories for IDL in dependency JARs - * [THRIFT-3801] - Node Thrift client throws exception with multiplexer and responses that are bigger than a single buffer - * [THRIFT-3821] - TMemoryBuffer buffer may overflow when resizing - * [THRIFT-3832] - Thrift version 0.9.3 example on Windows, Visual Studio, linking errors during compiling - * [THRIFT-3847] - thrift/config.h includes a #define for VERSION which will likely conflict with existing user environment or code - * [THRIFT-3873] - Fix various build warnings when using Visual Studio - * [THRIFT-3891] - TNonblockingServer configured with more than one IO threads does not always return from serve() upon stop() - * [THRIFT-3892] - Thrift uses TLS SNI extension provided by OpenSSL library. Older version of OpenSSL(< 0.9.8f) may create problem because they do not support 'SSL_set_tlsext_host_name()'. - * [THRIFT-3895] - Build fails using Java 1.8 with Ant < 1.9 - * [THRIFT-3896] - map data with number string key cannot access that deserialized by php extension - * [THRIFT-3938] - Python TNonblockingServer does not work with SSL - * [THRIFT-3944] - TSSLSocket has dead code in checkHandshake - * [THRIFT-3946] - Java 1.5 compatibility broken for binary fields (java5 option) - * [THRIFT-3960] - Inherited services in Lua generator are not named correctly - * [THRIFT-3962] - Ant build.xml broken on Windows for Java library - * [THRIFT-3963] - Thrift.cabal filename does not match module name - * [THRIFT-3967] - gobject/gparam.h:166:33: warning: enumerator value for ‘G_PARAM_DEPRECATED’ is not an integer constant expression - * [THRIFT-3968] - Deserializing empty string/binary fields - * [THRIFT-3974] - Using clang-3.8 and ThreadSanitizer on the concurrency_test claims bad PThread behavior - * [THRIFT-3984] - PHP7 extension causes segfault - * [THRIFT-4008] - broken ci due to upstream dependency versioning break - * [THRIFT-4009] - Use @implementer instead of implements in TTwisted.py - * [THRIFT-4010] - Q.fcall messing up with *this* pointer inside called function - * [THRIFT-4011] - Sets of Thrift structs generate Go code that can't be serialized to JSON - * [THRIFT-4012] - Python Twisted implementation uses implements, not compatible with Py3 - * [THRIFT-4014] - align C# meta data in AssemblyInfo.cs - * [THRIFT-4015] - Fix wrongly spelled "Thirft"s - * [THRIFT-4016] - testInsanity() impl does not conform to test spec in ThriftTest.thrift - * [THRIFT-4023] - Skip unexpected field types on read/write - * [THRIFT-4024] - Skip() should throw on unknown data types - * [THRIFT-4026] - TSSLSocket doesn't work with Python < 2.7.9 - * [THRIFT-4029] - Accelerated protocols do not build from thrift-py 0.10.0 on PyPI - * [THRIFT-4031] - Go plugin generates invalid code for lists of typedef'ed built-in types - * [THRIFT-4033] - Default build WITH_PLUGIN=ON for all builds results in packaging errors - * [THRIFT-4034] - CMake doesn't work to build compiler on MacOS - * [THRIFT-4036] - Add .NET Core environment/build support to the docker image - * [THRIFT-4038] - socket check: checking an unsigned number against >= 0 never fails - * [THRIFT-4042] - ExtractionError when using accelerated thrift in a multiprocess test - * [THRIFT-4043] - thrift perl debian package is placing files in the wrong place - * [THRIFT-4044] - Build job 17 failing on every pull request; hspec core (haskell) 2.4 issue - * [THRIFT-4046] - MinGW with gcc 6.2 does not compile on Windows - * [THRIFT-4060] - Thrift printTo ostream overload mechanism breaks down when types are nested - * [THRIFT-4062] - Remove debug print from TServiceClient - * [THRIFT-4065] - Document Perl ForkingServer signal restriction imposed by THRIFT-3848 and remove unnecessary code - * [THRIFT-4068] - A code comment in Java ServerSocket is wrong around accept() - * [THRIFT-4073] - enum files are still being generated with unused imports - * [THRIFT-4076] - Appveyor builds failing because ant 1.9.8 was removed from apache servers - * [THRIFT-4077] - AI_ADDRCONFIG redefined after recent change to PlatformSocket header - * [THRIFT-4079] - Generated perl code that returns structures from included thrift files is missing a necessary use clause - * [THRIFT-4087] - Spurious exception destroying TThreadedServer because of incorrect join() call - * [THRIFT-4102] - TBufferedTransport performance issue since 0.10.0 - * [THRIFT-4106] - concurrency_test fails randomly - * [THRIFT-4108] - c_glib thrift ssl has multiple bugs and deprecated functions - * [THRIFT-4109] - Configure Script uses string comparison for versions - * [THRIFT-4129] - C++ TNonblockingServer fd leak when failing to dispatch new connections - * [THRIFT-4131] - Javascript with WebSocket handles oneway methods wrong - * [THRIFT-4134] - Fix remaining undefined behavior invalid vptr casts - * [THRIFT-4140] - Use of non-thread-safe function gmtime() - * [THRIFT-4141] - Installation of haxe in docker files refers to a redirect link and fails - * [THRIFT-4147] - Rust: protocol should accept transports with non-static lifetime - * [THRIFT-4148] - [maven-thrift-plugin] compile error while import a thrift in dependency jar file. - * [THRIFT-4149] - System.out pollutes log files - * [THRIFT-4154] - PHP close() of a TSocket needs to close any type of socket - * [THRIFT-4158] - minor issue in README-MSYS2.md - * [THRIFT-4159] - Building tests fails on MSYS2 (MinGW64) due to a (small?) linker error - * [THRIFT-4160] - TNonblocking server fix use of closed/freed connections - * [THRIFT-4161] - TNonBlocking server using uninitialized event in error paths - * [THRIFT-4162] - TNonBlocking handling of TSockets in error state is incorrect after fd is closed - * [THRIFT-4164] - Core in TSSLSocket cleanupOpenSSL when destroying a mutex used by openssl - * [THRIFT-4165] - C++ build has many warnings under c++03 due to recent changes, cmake needs better platform-independent language level control - * [THRIFT-4166] - Recent fix to remove boost::lexical_cast usage broke VS2010 - * [THRIFT-4167] - Missing compile flag - * [THRIFT-4170] - Support lua 5.1 or earlier properly for object length determination - * [THRIFT-4172] - node.js tutorial client does not import assert, connection issues are not handled properly - * [THRIFT-4177] - Java compiler produces deep copy constructor that could make shallow copy instead - * [THRIFT-4184] - Building on Appveyor: invalid escape sequence \L - * [THRIFT-4185] - fb303 counter encoding fix - * [THRIFT-4189] - Framed/buffered transport Dispose() does not dispose the nested transport - * [THRIFT-4193] - Lower the default maxReadBufferBytes for non-blocking servers - * [THRIFT-4195] - Compilation to GO produces broken code - * [THRIFT-4196] - Cannot generate recursive Rust types - * [THRIFT-4204] - typo in compact spec - * [THRIFT-4206] - Strings in container fields are not decoded properly with py:dynamic and py:utf8strings - * [THRIFT-4208] - C# NamedPipesServer not really working in some scenarios - * [THRIFT-4211] - Fix GError glib management under Thrift - * [THRIFT-4212] - c_glib flush tries to close SSL even if socket is invalid - * [THRIFT-4213] - Travis build fails at curl -sSL https://www.npmjs.com/install.sh | sh - * [THRIFT-4215] - Golang TTransportFactory Pattern Squelches Errors - * [THRIFT-4216] - Golang Http Clients Do Not Respect User Options - * [THRIFT-4218] - Set TCP_NODELAY for PHP client socket - * [THRIFT-4219] - Golang HTTP clients created with Nil buffer - * [THRIFT-4231] - TJSONProtocol throws unexpected non-Thrift-exception on null strings - * [THRIFT-4232] - ./configure does bad ant version check - * [THRIFT-4234] - Travis build fails cross language tests with "Unsupported security protocol type" - * [THRIFT-4237] - Go TServerSocket Race Conditions - * [THRIFT-4240] - Go TSimpleServer does not close properly - * [THRIFT-4243] - Go TSimpleServer race on wait in Stop() method - * [THRIFT-4245] - Golang TFramedTransport's writeBuffer increases if writes to transport failed - * [THRIFT-4246] - Sequence number mismatch on multiplexed clients - * [THRIFT-4247] - Compile fails with openssl 1.1 - * [THRIFT-4248] - Compile fails - strncpy, memcmp, memset not declared in src/thrift/transport/TSSLSocket.cpp - * [THRIFT-4251] - Java Epoll Selector Bug - * [THRIFT-4257] - Typescript async callbacks do not provide the correct types - * [THRIFT-4258] - Boost/std thread wrapping faultiness - * [THRIFT-4260] - Go context generation issue. Context is parameter in Interface not in implementation - * [THRIFT-4261] - Go context generation issue: breaking change in generated code regarding thrift.TProcessorFunction interface - * [THRIFT-4262] - Invalid binding to InterlockedCompareExchange64() with 64-bit targets - * [THRIFT-4263] - Fix use after free bug for thrown exceptions - * [THRIFT-4266] - Erlang library throws during skipping fields of composite type (maps, lists, structs, sets) - * [THRIFT-4268] - Erlang library emits debugging output in transport layer - * [THRIFT-4273] - erlang:now/0: Deprecated BIF. - * [THRIFT-4274] - Python feature tests for SSL/TLS failing - * [THRIFT-4279] - Wrong path in include directive in generated Thrift sources - * [THRIFT-4283] - TNamedPipeServer race condition in interrupt - * [THRIFT-4284] - File contains a NBSP: lib/nodejs/lib/thrift/web_server.js - * [THRIFT-4290] - C# nullable option generates invalid code for non-required enum field with default value - * [THRIFT-4292] - TimerManager::remove() is not implemented - * [THRIFT-4307] - Make ssl-open timeout effective in golang client - * [THRIFT-4312] - Erlang client cannot connect to Python server: exception error: econnrefused - * [THRIFT-4313] - Program code of the Erlang tutorial files contain syntax errors - * [THRIFT-4316] - TByteBuffer.java will read too much data if a previous read returns fewer bytes than requested - * [THRIFT-4319] - command line switch for "evhttp" incorrectly resolved to anon pipes - * [THRIFT-4323] - range check errors or NPE in edge cases - * [THRIFT-4324] - field names can conflict with local vars in generated code - * [THRIFT-4328] - Travis CI builds are timing out (job 1) and haxe builds are failing since 9/11 - * [THRIFT-4329] - c_glib Doesn't have a multiplexed processor - * [THRIFT-4331] - C++: TSSLSockets bug in handling huge messages, bug in handling polling - * [THRIFT-4332] - Binary protocol has memory leaks - * [THRIFT-4334] - Perl indentation incorrect when defaulting field attribute to a struct - * [THRIFT-4339] - Thrift Framed Transport in Erlang crashes server when client disconnects - * [THRIFT-4340] - Erlang fix a crash on client close - * [THRIFT-4355] - Javascript indentation incorrect when defaulting field attribute to a struct - * [THRIFT-4356] - thrift_protocol call Transport cause Segmentation fault - * [THRIFT-4359] - Haxe compiler looks like it is producing incorrect code for map or set key that is binary type - * [THRIFT-4362] - Missing size-check can lead to huge memory allocation - * [THRIFT-4364] - Website contributing guide erroneously recommends submitting patches in JIRA - * [THRIFT-4365] - Perl generated code uses indirect object syntax, which occasionally causes compilation errors. - * [THRIFT-4367] - python TProcessor.process is missing "self" - * [THRIFT-4370] - Ubuntu Artful cppcheck and flake8 are more stringent and causing SCA build job failures - * [THRIFT-4372] - Pipe write operations across a network are limited to 65,535 bytes per write. - * [THRIFT-4374] - cannot load thrift_protocol due to undefined symbol: _ZTVN10__cxxabiv120__si_class_type_infoE - * [THRIFT-4375] - TMemory throw bad_alloc due to counter overflow - * [THRIFT-4376] - Coverity high impact issue resolution - * [THRIFT-4377] - haxe. socket handles leak in TSimpleServer - * [THRIFT-4381] - Wrong isset bitfield value after transmission - * [THRIFT-4385] - Go remote client -u flag is broken - * [THRIFT-4392] - compiler/..../plugin.thrift structs mis-ordered blows up ocaml generator - * [THRIFT-4395] - Unable to build in the ubuntu-xenial docker image: clap 2.28 requires Rust 1.20 - * [THRIFT-4396] - inconsistent (or plain wrong) version numbers in master/trunk - -## Documentation - * [THRIFT-4157] - outdated readme about Haxe installation on Linux - -## Improvement - * [THRIFT-105] - make a thrift_spec for a structures with negative tags - * [THRIFT-281] - Cocoa library code needs comments, badly - * [THRIFT-775] - performance improvements for Perl - * [THRIFT-2221] - Generate c++ code with std::shared_ptr instead of boost::shared_ptr. - * [THRIFT-2364] - OCaml: Use Oasis exclusively for build process - * [THRIFT-2504] - TMultiplexedProcessor should allow registering default processor called if no service name is present - * [THRIFT-3207] - Enable build with OpenSSL 1.1.0 series - * [THRIFT-3272] - Perl SSL Authentication Support - * [THRIFT-3357] - Generate EnumSet/EnumMap where elements/keys are enums - * [THRIFT-3369] - Implement SSL/TLS support on C with c_glib - * [THRIFT-3467] - Go Maps for Thrift Sets Should Have Values of Type struct{} - * [THRIFT-3580] - THeader for Haskell - * [THRIFT-3627] - Missing basic code style consistency of JavaScript. - * [THRIFT-3706] - There's no support for Multiplexed protocol on c_glib library - * [THRIFT-3766] - Add getUnderlyingTransport() to TZlibTransport - * [THRIFT-3776] - Go code from multiple thrift files with the same namespace - * [THRIFT-3823] - Escape documentation while generating non escaped documetation - * [THRIFT-3854] - allow users to clear read buffers - * [THRIFT-3859] - Unix Domain Socket Support in Objective-C - * [THRIFT-3921] - C++ code should print enums as strings - * [THRIFT-3926] - There should be an error emitted when http status code is not 200 - * [THRIFT-4007] - Micro-optimization of TTransport.py - * [THRIFT-4040] - Add real cause of TNonblockingServerSocket error to exception - * [THRIFT-4064] - Update node library dependencies - * [THRIFT-4069] - All perl packages should have proper namespace, version syntax, and use proper thrift exceptions - * [THRIFT-4071] - Consolidate the Travis CI jobs where possible to put less stress on the Apache Foundation's allocation of CI build slaves - * [THRIFT-4072] - Add the possibility to send custom headers in TCurlClient - * [THRIFT-4075] - Better MinGW support for headers-only boost (without thread library) - * [THRIFT-4081] - Provide a MinGW 64-bit Appveyor CI build for better pull request validation - * [THRIFT-4084] - Improve SSL security in thrift by adding a make cross client that checks to make sure SSLv3 protocol cannot be negotiated - * [THRIFT-4095] - Add multiplexed protocol to Travis CI for make cross - * [THRIFT-4099] - Auto-derive Hash for generated Rust structs - * [THRIFT-4110] - The debian build files do not produce a "-dbg" package for debug symbols of libthrift0 - * [THRIFT-4114] - Space after '///' in doc comments - * [THRIFT-4126] - Validate objects in php extension - * [THRIFT-4130] - Ensure Apache Http connection is released back to pool after use - * [THRIFT-4151] - Thrift Mutex Contention Profiling (pthreads) should be disabled by default - * [THRIFT-4176] - Implement a threaded and threadpool server type for Rust - * [THRIFT-4183] - Named pipe client blocks forever on Open() when there is no server at the other end - * [THRIFT-4190] - improve C# TThreadPoolServer defaults - * [THRIFT-4197] - Implement transparent gzip compression for HTTP transport - * [THRIFT-4198] - Ruby should log Thrift internal errors to global logger - * [THRIFT-4203] - thrift server stop gracefully - * [THRIFT-4205] - c_glib is not linking against glib + gobject - * [THRIFT-4209] - warning CS0414 in T[TLS]ServerSocket.cs - * [THRIFT-4210] - include Thrift.45.csproj into CI runs - * [THRIFT-4217] - HttpClient should support gzip and deflate - * [THRIFT-4222] - Support Unix Domain Sockets in Golang TServerSocket - * [THRIFT-4233] - Make THsHaServer.invoker available (get method only) in inherited classes - * [THRIFT-4236] - Support context in go generated code. - * [THRIFT-4238] - JSON generator: make annotation-aware - * [THRIFT-4269] - Don't append '.' to Erlang namespace if it ends in '_'. - * [THRIFT-4270] - Generate Erlang mapping functions for const maps and lists - * [THRIFT-4275] - Add support for zope.interface only, apart from twisted support. - * [THRIFT-4285] - Pull generated send/recv into library to allow behaviour to be customised - * [THRIFT-4287] - Add c++ compiler "no_skeleton" flag option - * [THRIFT-4288] - Implement logging levels properly for node.js - * [THRIFT-4295] - Refresh the Docker image file suite for Ubuntu, Debian, and CentOS - * [THRIFT-4305] - Emit ddoc for generated items - * [THRIFT-4306] - Thrift imports not replicated to D service output - * [THRIFT-4315] - Add default message for TApplicationException - * [THRIFT-4318] - Delphi performance improvements - * [THRIFT-4325] - Simplify automake cross compilation by relying on one global THRIFT compiler path - * [THRIFT-4327] - Improve TimerManager API to allow removing specific task - * [THRIFT-4330] - Allow unused crates in Rust files - * [THRIFT-4333] - Erlang tutorial examples are using a different port (9999) - * [THRIFT-4343] - Change CI builds to use node.js 8.x LTS once available - * [THRIFT-4345] - Create a docker build environment that uses the minimum supported language levels - * [THRIFT-4346] - Allow Zlib transport factory to wrap other transports - * [THRIFT-4348] - Perl HTTP Client custom HTTP headers - * [THRIFT-4350] - Update netcore build for dotnet 2.0 sdk and make cross validation - * [THRIFT-4351] - Use Travis CI Build Stages to optimize the CI build - * [THRIFT-4353] - cannot read via thrift_protocol at server side - * [THRIFT-4378] - add set stopTimeoutUnit method to TThreadPoolServer - -## New Feature - * [THRIFT-750] - C++ Compiler Virtual Function Option - * [THRIFT-2945] - Implement support for Rust language - * [THRIFT-3857] - thrift js:node complier support an object as parameter not an instance of struct - * [THRIFT-3933] - Port official C# .NET library for Thrift to C# .NET Core libary - * [THRIFT-4039] - Update of Apache Thrift .Net Core lib - * [THRIFT-4113] - Provide a buffer transport for reading/writing in memory byte stream - -## Question - * [THRIFT-2956] - autoconf - possibly undefined macro - AC_PROG_BISON - * [THRIFT-4223] - Add support to the isServing() method for the C++ library - -## Task - * [THRIFT-3622] - Fix deprecated uses of std::auto_ptr - * [THRIFT-4028] - Please remove System.out.format from the source code - * [THRIFT-4186] - Build and test rust client in Travis - -## Test - * [THRIFT-4264] - PHP - Support both shared & static linking of sockets library - -## Wish - * [THRIFT-4344] - Define and maintain the minimum language level for all languages in one place - - -Thrift 0.10.0 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1840] - Thrift Generated Code Causes Global Variable Leaks - * [THRIFT-1828] - moc_TQTcpServer.cpp was removed from source tree but is in thrift-0.9.0.tar.gz - * [THRIFT-1790] - cocoa: Duplicate interface definition error - * [THRIFT-1776] - TPipeServer should implement "listen", so that TServerEventHandler preServe will work right - * [THRIFT-1351] - Compiler does not care about binary strings - * [THRIFT-1229] - Python fastbinary.c can not handle unicode as generated python code - * [THRIFT-749] - C++ TBufferedTransports do not flush their buffers on delete - * [THRIFT-747] - C++ TSocket->close calls shutdown breaking forked parent process - * [THRIFT-732] - server exits abnormally when client calls send_xxx function without calling recv_xxx function - * [THRIFT-3942] - TSSLSocket does not honor send and receive timeouts - * [THRIFT-3941] - WinXP version of thrift_poll() relies on undefined behavior by passing a destructed variable to select() - * [THRIFT-3940] - Visual Studio project file for compiler is broken - * [THRIFT-3943] - Coverity Scan identified some high severity defects - * [THRIFT-3929] - PHP "nsglobal" Option Results in Syntax Error in Generated Code (Trailing Backslash) - * [THRIFT-3936] - Cannot compile 0.10.0 development tip with VS2013 and earlier (snprintf, uint32_t) - * [THRIFT-3935] - Incorrect skipping of map and set - * [THRIFT-3920] - Ruby: Ensuring that HTTP failures will clear the http transport outbuf var - * [THRIFT-3919] - C# TTLSServerSocket does not use clientTimeout - * [THRIFT-3917] - Check backports.ssl_match_hostname module version - * [THRIFT-3909] - Fix c_glib static lib CMake build - * [THRIFT-3904] - Typo in node tutorial leads to wrong transport being used - * [THRIFT-3848] - As an implementer of a perl socket server, I do not want to have to remember to ignore SIGCHLD for it to work properly - * [THRIFT-3844] - thrift_protocol cannot compile in 7.0.7 - * [THRIFT-3843] - integer issues with Haxe PHP targets cause ZigZag encoding to fail - * [THRIFT-3842] - Dart generates incorrect code for a const struct - * [THRIFT-3841] - dart compact protocol incorrectly serializes/deserialized doubles - * [THRIFT-3708] - NameError: global name 'TProtocol' is not defined - * [THRIFT-3704] - "TConnectedClient died: Could not refill buffer" message shown when using HTTP Server - * [THRIFT-3678] - Fix javadoc errors on JDK 8 - * [THRIFT-3014] - AppVeyor support - * [THRIFT-2994] - Node.js TJSONProtocol cannot be used for object serialization. - * [THRIFT-2974] - writeToParcel throws NPE for optional enum fields - * [THRIFT-2948] - Python TJSONProtocol doesn't handle structs with binary fields containing invalid unicode. - * [THRIFT-2845] - ChildService.Plo: No such file or directory - * [THRIFT-3276] - Binary data does not decode correctly using the TJSONProtocol when the base64 encoded data is padded. - * [THRIFT-3253] - Using latest version of D gives deprecation notices - * [THRIFT-2883] - TTwisted.py, during ConnectionLost processing: exceptions.RuntimeError: dictionary changed size during iteration - * [THRIFT-2019] - Writing on a disconnected socket on Mac causes SIG PIPE - * [THRIFT-2020] - Thrift library has some empty files that haven't really been deleted - * [THRIFT-2049] - Go compiler doesn't build on native Windows - * [THRIFT-2024] - TServer.cpp warns on 64-bit platforms about truncating an rlim_t into an int - * [THRIFT-2023] - gettimeofday implementation on Windows errors when no time zone is passed in. - * [THRIFT-2022] - CoB and dense code generation still uses TR1 bind, even though that doesn't work with clang - * [THRIFT-2027] - Minor 64-bit and NOMINMAX issues in C++ library - * [THRIFT-2156] - TServerSocket::listen() is throwing exceptions with misleading information - * [THRIFT-2154] - Missing #deepCopy should return T - * [THRIFT-3157] - TBase signature should be TBase, F extends TFieldIdEnum> - * [THRIFT-3156] - Node TLS: server executes processing logic two full times - * [THRIFT-3154] - tutorial/py.tornado throw EOF exception - * [THRIFT-3063] - C++ build -Wunused-parameter warnings on processor_test, TransportTest - * [THRIFT-3056] - Add string/collection length limits for Python protocol readers - * [THRIFT-3237] - Fix TNamedPipeServer::createNamedPipe memory leak - * [THRIFT-3233] - Fix C++ ThreadManager::Impl::removeWorker worker join - * [THRIFT-3232] - Cannot deserialize json messages created with fieldNamesAsString - * [THRIFT-3206] - Fix Visual Studio build failure due 'pthread_self': identifier not found - * [THRIFT-3200] - JS and nodejs do not encode JSON protocol binary fields as base64 - * [THRIFT-3199] - Exception field has basic metadata - * [THRIFT-3182] - TFramedTransport is in an invalid state after frame size exception - * [THRIFT-2536] - new TSocket, uninitialised value reported by valgrind - * [THRIFT-2527] - Apache Thrift IDL Compiler code generated for Node.js should be jshint clean - * [THRIFT-2519] - "processor" class is not being generated - * [THRIFT-2431] - TFileTransportTest fails with "check delta < XXX failed" - * [THRIFT-2708] - Erlang library does not support "oneway" message type - * [THRIFT-3377] - Deep copy is actually shallow when using typedef members - * [THRIFT-3376] - C# and Python JSON protocol double values lose precision - * [THRIFT-3373] - Various fixes for cross test servers and clients - * [THRIFT-3370] - errno extern variable redefined. Not compiling for Android - * [THRIFT-3379] - Potential out of range panic in Go JSON protocols - * [THRIFT-3371] - Abstract namespace Unix domain sockets broken in C++ - * [THRIFT-3380] - nodejs: 0.9.2 -> 0.9.3 upgrade breaks Protocol and Transport requires - * [THRIFT-3367] - Fix bad links to coding_standards.md #634 - * [THRIFT-3401] - Nested collections emit Objective-C code that cannot compile - * [THRIFT-3403] - JSON String reader doesn't recognize UTF-16 surrogate pairs - * [THRIFT-3362] - make check fails for C++ at the SecurityTest - * [THRIFT-3395] - Cocoa compiler produces corrupt code when boxing enums inside map. - * [THRIFT-3394] - compiler generates uncompilable code - * [THRIFT-3388] - hash doesn't work on set/list - * [THRIFT-3391] - Wrong bool formatting in test server - * [THRIFT-3390] - TTornado server doesn't handle closed connections properly - * [THRIFT-3382] - TBase class for C++ Library - * [THRIFT-3392] - Java TZlibTransport does not close its wrapper streams upon close() - * [THRIFT-3383] - i64 related warnings - * [THRIFT-3386] - misc. warnings with make check - * [THRIFT-3385] - warning: format ‘%lu’ expects ‘long unsigned int’, but has type ‘std::basic_string::size_type {aka unsigned int} - * [THRIFT-3355] - npm WARN package.json thrift@1.0.0-dev No license field. - * [THRIFT-3360] - Improve cross test servers and clients further - * [THRIFT-3359] - Binary field incompatibilities - * [THRIFT-3354] - Fix word-extraction substr bug in initialism code - * [THRIFT-3350] - Python JSON protocol does not encode binary as Base64 - * [THRIFT-3577] - assertion failed at line 512 of testcontainertest.c - * [THRIFT-3576] - Boost test --log_format arg does not accept lowercase - * [THRIFT-3575] - Go compiler tries to use unexported library methods when using read_write_private - * [THRIFT-3574] - Cocoa generator makes uncompilable imports - * [THRIFT-3570] - Remove duplicate instances that are added by upstream - * [THRIFT-3571] - Make feature test result browsable - * [THRIFT-3569] - c_glib protocols do not check number of bytes read by transport - * [THRIFT-3568] - THeader server crashes on readSlow - * [THRIFT-3567] - GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed - * [THRIFT-3566] - C++/Qt: TQTcpServerTest::test_communicate() is never executed - * [THRIFT-3564] - C++/Qt: potential core dump in TQTcpServer in case an exception occurs in TAsyncProcessor::process() - * [THRIFT-3558] - typos in c_glib tests - * [THRIFT-3559] - Fix awkward extra semi-colons with Cocoa container literals - * [THRIFT-3555] - 'configure' script does not honor --with-openssl= for libcrypto for BN_init - * [THRIFT-3554] - Constant decls may lead to "Error: internal error: prepare_member_name_mapping() already active for different struct" - * [THRIFT-3552] - glib_c Memory Leak - * [THRIFT-3551] - Thrift perl library missing package declaration - * [THRIFT-3549] - Exceptions are not properly stringified in Perl library - * [THRIFT-3546] - NodeJS code should not be namespaced (and is currently not strict-mode compliant) - * [THRIFT-3545] - Container type literals do not compile - * [THRIFT-3538] - Remove UnboundMethodType in TProtocolDecorator - * [THRIFT-3536] - Error 'char' does not contain a definition for 'IsLowSurrogate' for WP7 target - * [THRIFT-3534] - Link error when building with Qt5 - * [THRIFT-3533] - Can not send nil pointer as service method argument - * [THRIFT-3507] - THttpClient does not use proxy from http_proxy, https_proxy environment variables - * [THRIFT-3502] - C++ TServerSocket passes small buffer to getsockname - * [THRIFT-3501] - Forward slash in comment causes compiler error - * [THRIFT-3498] - C++ library assumes optional function pthread_attr_setschedpolicy is available - * [THRIFT-3497] - Build fails with "invalid use of incomplete type" - * [THRIFT-3496] - C++: Cob style client fails when sending a consecutive request - * [THRIFT-3493] - libthrift does not compile on windows using visual studio - * [THRIFT-3488] - warning: unused variable 'program' - * [THRIFT-3489] - warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings] - * [THRIFT-3487] - Full support for newer Delphi versions - * [THRIFT-3528] - Fix warnings in thrift.ll - * [THRIFT-3527] - -gen py:dynamic,utf8strings ignores utf8strings option - * [THRIFT-3526] - Code generated by py:utf8strings does not work for Python3 - * [THRIFT-3524] - dcc32 warning "W1000 Symbol 'IsLowSurrogate' is deprecated: 'Use TCharHelper'" in Thrift.Protocol.JSON.pas - * [THRIFT-3525] - py:dynamic fails to handle binary list/set/map element - * [THRIFT-3521] - TSimpleJSONProtocolTest is not deterministic (fails when run on JDK 8) - * [THRIFT-3520] - Dart TSocket onError stream should be typed as Object - * [THRIFT-3519] - fastbinary does not work with -gen py:utf8strings - * [THRIFT-3518] - TConcurrentClientSyncInfo files were missing for Visual Studio - * [THRIFT-3512] - c_glib: Build fails due to missing features.h - * [THRIFT-3483] - Incorrect empty binary handling introduced by THRIFT-3359 - * [THRIFT-3479] - Oneway calls should not return exceptions to clients - * [THRIFT-3478] - Restore dropped method to THsHaServer.java - * [THRIFT-3477] - Parser fails on enum item that starts with 'E' letter and continues with number - * [THRIFT-3476] - Missing include in ./src/thrift/protocol/TJSONProtocol.cpp - * [THRIFT-3474] - Docker: thrift-compiler - * [THRIFT-3473] - When "optional' is used with a struct member, C++ server seems to not return it correctly - * [THRIFT-3468] - Dart TSocketTransport onError handler is too restrictive - * [THRIFT-3451] - thrift_protocol PHP extension missing config.m4 file - * [THRIFT-3456] - rounding issue in static assert - * [THRIFT-3455] - struct write method's return value is incorrect - * [THRIFT-3454] - Python Tornado tutorial is broken - * [THRIFT-3463] - Java can't be disabled in CMake build - * [THRIFT-3450] - NPE when using SSL - * [THRIFT-3449] - TBaseAsyncProcessor fb.responseReady() never called for oneway functions - * [THRIFT-3471] - Dart generator does not handle uppercase argument names - * [THRIFT-3470] - Sporadic timeouts with pipes - * [THRIFT-3465] - Go Code With Complex Const Initializer Compilation Depends On Struct Order - * [THRIFT-3464] - Fix several defects in c_glib code generator - * [THRIFT-3462] - Cocoa generates Incorrect #import header names - * [THRIFT-3453] - remove rat_exclude - * [THRIFT-3418] - Use of ciphers in ssl.wrap_socket() breaks python 2.6 compatibility - * [THRIFT-3417] - "namespace xsd" is not really working - * [THRIFT-3413] - Thrift code generation bug in Go when extending service - * [THRIFT-3420] - C++: TSSLSockets are not interruptable - * [THRIFT-3415] - include unistd.h conditionally - * [THRIFT-3414] - #include in THeaderTransport.h breaks windows build - * [THRIFT-3411] - Go generates remotes with wrong package qualifiers when including - * [THRIFT-3430] - Go THttpClient does not read HTTP response body to completion when closing - * [THRIFT-3423] - First call to thrift_transport:read_exact fails to dispatch correct function - * [THRIFT-3422] - Go TServerSocket doesn't close on Interrupt - * [THRIFT-3421] - rebar as dependency instead of bundling (was: rebar fails if PWD contains Unicode) - * [THRIFT-3428] - Go test fails when running make check - * [THRIFT-3445] - Throwable messages are hidden from JVM stack trace output - * [THRIFT-3443] - Thrift include can generate uncompilable code - * [THRIFT-3444] - Large 64 bit Integer does not preserve value through Node.js JSONProtocol - * [THRIFT-3436] - misc. cross test issues with UTF-8 path names - * [THRIFT-3435] - Put generated Java code for fullcamel tests in a separate package/namespace - * [THRIFT-3433] - Doubles aren't interpreted correctly - * [THRIFT-3437] - Mingw-w64 build fail - * [THRIFT-3434] - Dart generator produces empty name in pubspec.yaml for includes without namespaces - * [THRIFT-3408] - JSON generator emits incorrect types - * [THRIFT-3406] - Cocoa client should not schedule streams on main runloop - * [THRIFT-3404] - JSON String reader doesn't recognize UTF-16 surrogate pair - * [THRIFT-3636] - Double precision is not fully preserved in C++ TJSONProtocol - * [THRIFT-3632] - c_glib testserialization fails with glib assertion - * [THRIFT-3619] - Using Thrift 0.9.3 with googletest on Linux gcc 4.9 / C++11 - * [THRIFT-3617] - CMake does not build gv/xml generators - * [THRIFT-3615] - Fix Python SSL client resource leak on connection failure - * [THRIFT-3616] - lib/py/test/test_sslsocket.py is flaky - * [THRIFT-3643] - Perl SSL server crushes if a client disconnect without handshake - * [THRIFT-3639] - C# Thrift library forces TLS 1.0, thwarting TLS 1.2 usage - * [THRIFT-3633] - Travis "C C++ - GCC" build was using clang - * [THRIFT-3634] - Fix Python TSocket resource leak on connection failure - * [THRIFT-3630] - Debian/Ubuntu install docs need an update - * [THRIFT-3629] - Parser sets exitcode on errors, but generator does not - * [THRIFT-3608] - lib/cpp/test/SecurityTest is flaky in jenkins Thrift-precommit build. - * [THRIFT-3601] - Better conformance to PEP8 for generated code - * [THRIFT-3599] - Validate client IP address against cert's SubjectAltName - * [THRIFT-3598] - TBufferedTransport doesn't instantiate client connection - * [THRIFT-3597] - `make check` hangs in go tests - * [THRIFT-3589] - Dart generator uses wrong name in constructor for uppercase arguments with defaults - * [THRIFT-3588] - Using TypeScript with --noImplicitAny fails - * [THRIFT-3584] - boolean false value cannot be transferred - * [THRIFT-3578] - Make THeaderTransport detect TCompact framed and unframed - * [THRIFT-3323] - Python library does not handle escaped forward slash ("/") in JSON - * [THRIFT-3322] - CMake generated "make check" failes on python_test - * [THRIFT-3321] - Thrift can't be added as a subdirectory of another CMake-based project - * [THRIFT-3314] - Dots in file names of includes causes dots in javascript variable names - * [THRIFT-3307] - Segfault in Ruby serializer - * [THRIFT-3309] - Missing TConstant.php in /lib/php/Makefile.am - * [THRIFT-3810] - unresolved external symbol public: virtual void __cdecl apache::thrift::server::TServerFramework::serve(void) - * [THRIFT-3736] - C++ library build fails if OpenSSL does not surrpot SSLv3 - * [THRIFT-3878] - Compile error in TSSLSocket.cpp with new OpenSSL [CRYPTO_num_locks] - * [THRIFT-3949] - missing make dist entry for compiler/cpp/test - * [THRIFT-449] - The wire format of the JSON Protocol may not always be valid JSON if it contains non-UTF8 encoded strings - * [THRIFT-162] - Thrift structures are unhashable, preventing them from being used as set elements - * [THRIFT-3961] - TConnectedClient does not terminate the connection to the client if an exception while processing the received message occures. - * [THRIFT-3881] - Travis CI builds are failing due to docker failures (three retries, and gives up) - * [THRIFT-3937] - Cannot compile 0.10.0 development tip with gcc-4.6.x - * [THRIFT-3964] - Unsupported mechanism type ????? due to dependency on default OS-dependent charset - * [THRIFT-3038] - Use of volatile in cpp library - * [THRIFT-3301] - Java generated code uses imports that can lead to class name collisions with IDL defined types - * [THRIFT-3348] - PHP TCompactProtocol bool&int64 readvalue bug - * [THRIFT-3955] - TThreadedServer Memory Leak - * [THRIFT-3829] - Thrift does not install Python Libraries if Twisted is not installed - * [THRIFT-3932] - C++ ThreadManager has a rare termination race - * [THRIFT-3828] - cmake fails when Boost_INCLUDE_DIRS (and other variables passed to include_directories()) is empty - * [THRIFT-3958] - CMake WITH_MT option for windows static runtime linking does not support the cmake build type RelWithDebInfo - * [THRIFT-3957] - TConnectedClient does not disconnect from clients when their timeout is reached. - * [THRIFT-3953] - TSSLSocket::close should handle exceptions from waitForEvent because it is called by the destructor. - * [THRIFT-3977] - PHP extension creates undefined values when deserializing sets - * [THRIFT-3947] - sockaddr type isn't always large enough for the return of getsockname - * [THRIFT-2755] - ThreadSanitizer reports data race in ThreadManager::Impl::addWorker - * [THRIFT-3948] - errno is not the correct method of getting the error in windows - * [THRIFT-4008] - broken ci due to upstream dependency versioning break - * [THRIFT-3999] - Fix Debian & Ubuntu package dependencies - * [THRIFT-3886] - PHP cross test client returns 0 even when failing - * [THRIFT-3997] - building thrift libs does not support new openssl - -## Documentation - * [THRIFT-3867] - Specify BinaryProtocol and CompactProtocol - -## Epic - * [THRIFT-3049] - As an iOS developer, I want a generator and library that produces Swift code - * [THRIFT-2336] - UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - -## Improvement - * [THRIFT-1867] - Python client/server should support client-side certificates. - * [THRIFT-1313] - c_glib compact support - * [THRIFT-1385] - make install doesn't install java library in the setted folder - * [THRIFT-1437] - Update RPM spec - * [THRIFT-847] - Test Framework harmonization across all languages - * [THRIFT-819] - add Enumeration for protocol, transport and server types - * [THRIFT-3927] - Emit an error instead of throw an error in the async callback - * [THRIFT-3931] - TSimpleServer: If process request encounter UNKNOWN_METHOD, don't close transport. - * [THRIFT-3934] - Automatically resolve OpenSSL binary version on Windows CI - * [THRIFT-3918] - Run subset of make cross - * [THRIFT-3908] - Remove redundant dependencies from Dockerfile - * [THRIFT-3907] - Skip Docker image build on CI when unchanged - * [THRIFT-3868] - Java struct equals should do identity check before field comparison - * [THRIFT-3849] - Port Go serializer and deserializer to dart - * [THRIFT-2989] - Complete CMake build for Apache Thrift - * [THRIFT-2980] - ThriftMemoryBuffer doesn't have a constructor option to take an existing buffer - * [THRIFT-2856] - refactor erlang basic transports and unify interfaces - * [THRIFT-2877] - Optimize generated hashCode - * [THRIFT-2869] - JSON: run schema validation from tests - * [THRIFT-3112] - [Java] AsyncMethodCallback should be typed in generated AsyncIface - * [THRIFT-3263] - PHP jsonSerialize() should cast scalar types - * [THRIFT-2905] - Cocoa compiler should have option to produce "modern" Objective-C - * [THRIFT-2821] - Enable the use of custom HTTP-Header in the Transport - * [THRIFT-2093] - added the ability to set compression level in C++ zlib transport - * [THRIFT-2089] - Compiler ignores duplicate typenames - * [THRIFT-2056] - Moved all #include config.h statements to #include - * [THRIFT-2031] - Make SO_KEEPALIVE configurable for C++ lib - * [THRIFT-2021] - Improve large binary protocol string performance - * [THRIFT-2028] - Cleanup threading headers / libraries - * [THRIFT-2014] - Change C++ lib includes to use style throughout - * [THRIFT-2312] - travis.yml: build everything - * [THRIFT-1915] - Multiplexing Services - * [THRIFT-1736] - Visual Studio top level project files within msvc - * [THRIFT-1735] - integrate tutorial into regular build - * [THRIFT-1533] - Make TTransport should be Closeable - * [THRIFT-35] - Move language tests into their appropriate library directory - * [THRIFT-1079] - Support i64 in AS3 - * [THRIFT-1108] - SSL support for the Ruby library - * [THRIFT-3856] - update debian package deependencies - * [THRIFT-3833] - haxe http server implementation (by embeding into php web server) - * [THRIFT-3839] - Performance issue with big message deserialization using php extension - * [THRIFT-3820] - Erlang: Detect OTP >= 18 to use new time correction - * [THRIFT-3816] - Reduce docker build duration on Travis-CI - * [THRIFT-3815] - Put appveyor dependency versions to one place - * [THRIFT-3788] - Compatibility improvements and Win64 support - * [THRIFT-3792] - Timeouts for anonymous pipes should be configurable - * [THRIFT-3794] - Split Delphi application, protocol and transport exception subtypes into separate exceptions - * [THRIFT-3774] - The generated code should have exception_names meta info - * [THRIFT-3762] - Fix build warnings for deprecated Thrift "byte" fields - * [THRIFT-3756] - Improve requiredness documentation - * [THRIFT-3761] - Add debian package for Python3 - * [THRIFT-3742] - haxe php cli support - * [THRIFT-3733] - Socket timeout improvements - * [THRIFT-3728] - http transport for thrift-lua - * [THRIFT-3905] - Dart compiler does not initialize bool, int, and double properties - * [THRIFT-3911] - Loosen Ruby dev dependency version requirements - * [THRIFT-3906] - Run C# tests with make check - * [THRIFT-3900] - Add Python SSL flags - * [THRIFT-3897] - Provide meaningful exception type based on WebExceptionStatus in case of timeout - * [THRIFT-3808] - Missing `DOUBLE` in thrift type enumeration - * [THRIFT-3803] - Remove "file" attribute from XML generator - * [THRIFT-3660] - Add V4 mapped address to test client cert's altname - * [THRIFT-3661] - Use https to download meck in erlang test build - * [THRIFT-3659] - Check configure result of CMake on CI - * [THRIFT-3667] - Add TLS SNI support to clients - * [THRIFT-3651] - Make backports.match_hostname and ipaddress optional - * [THRIFT-3666] - Build D tutorial as part of Autotools build - * [THRIFT-3665] - Add D libevent and OpenSSL to docker images - * [THRIFT-3664] - Remove md5.c - * [THRIFT-3662] - Add Haskell to debian docker image - * [THRIFT-3711] - Add D to cross language test - * [THRIFT-3691] - Run flake8 Python style check on Travis-CI - * [THRIFT-3692] - (Re)enable Appveyor C++ and Python build - * [THRIFT-3677] - Improve CMake Java build - * [THRIFT-3679] - Add stdout log to testBinary in Java test server - * [THRIFT-3718] - Reduce size of docker image for build environment - * [THRIFT-3698] - [Travis-CI] Introduce retry to apt commands - * [THRIFT-3127] - switch -recurse to --recurse and reserve -r - * [THRIFT-3087] - Pass on errors like "connection closed" - * [THRIFT-3240] - Thrift Python client should support subjectAltName and wildcard certs in TSSLSocket - * [THRIFT-3213] - make cross should indicate when it skips a known failing test - * [THRIFT-3208] - Fix Visual Studio solution build failure due to missing source - * [THRIFT-3186] - Add TServerHTTP to Go library - * [THRIFT-2342] - Add __FILE__ and __LINE__ to Thrift C++ excpetions - * [THRIFT-3372] - Add dart generator to Visual Studio project - * [THRIFT-3366] - ThriftTest to implement standard return values - * [THRIFT-3402] - Provide a perl Unix Socket implementation - * [THRIFT-3361] - Improve C# library - * [THRIFT-3393] - Introduce i8 to provide consistent set of Thrift IDL integer types - * [THRIFT-3339] - Support for database/sql - * [THRIFT-3565] - C++: T[Async]Processor::getEventHandler() should be declared as const member functions - * [THRIFT-3563] - C++/Qt: removed usage of macro QT_PREPEND_NAMESPACE as it isn't consequently used for all references to Qt types. - * [THRIFT-3562] - Removed unused TAsyncProcessor::getAsyncServer() - * [THRIFT-3561] - C++/Qt: make use of Q_DISABLE_COPY() to get rid of copy ctor and assignment operator - * [THRIFT-3556] - c_glib file descriptor transport - * [THRIFT-3544] - Make cross test fail when server process died unexpectedly - * [THRIFT-3540] - Make python tutorial more in line with PEP8 - * [THRIFT-3535] - Dart generator argument to produce a file structure usable in parent library - * [THRIFT-3505] - Enhance Python TSSLSocket - * [THRIFT-3506] - Eliminate old style classes from library code - * [THRIFT-3503] - Enable py:utf8string by default - * [THRIFT-3499] - Add package_prefix to python generator - * [THRIFT-3495] - Minor enhancements and fixes for cross test - * [THRIFT-3486] - Java generated `getFieldValue` is incompatible with `setFieldValue` for binary values. - * [THRIFT-3484] - Consolidate temporary buffers in Java's TCompactProtocol - * [THRIFT-3516] - Add feature test for THeader TBinaryProtocol interop - * [THRIFT-3515] - Python 2.6 compatibility and test on CI - * [THRIFT-3514] - PHP 7 compatible version of binary protocol - * [THRIFT-3469] - Docker: Debian support - * [THRIFT-3416] - Retire old "xxx_namespace" declarations from the IDL - * [THRIFT-3426] - Align autogen comment in XSD - * [THRIFT-3424] - Add CMake android build option - * [THRIFT-3439] - Run make cross using Python3 when available - * [THRIFT-3440] - Python make check takes too much time - * [THRIFT-3441] - Stabilize Travis-CI builds - * [THRIFT-3431] - Avoid "schemes" HashMap lookups during struct reads/writes - * [THRIFT-3432] - Add a TByteBuffer transport to the Java library - * [THRIFT-3438] - Enable py:new_style by default - * [THRIFT-3405] - Go THttpClient misuses http.Client objects - * [THRIFT-3614] - Improve logging of test_sslsocket.py - * [THRIFT-3647] - Fix php extension build warnings - * [THRIFT-3642] - Speed up cross test runner - * [THRIFT-3637] - Implement compact protocol for dart - * [THRIFT-3613] - Port Python C extension to Python 3 - * [THRIFT-3612] - Add Python C extension for compact protocol - * [THRIFT-3611] - Add --regex filter to cross test runner - * [THRIFT-3631] - JSON protocol implementation for Lua - * [THRIFT-3609] - Remove or replace TestPortFixture.h - * [THRIFT-3605] - Have the compiler complain about invalid arguments and options - * [THRIFT-3596] - Better conformance to PEP8 - * [THRIFT-3585] - Compact protocol implementation for Lua - * [THRIFT-3582] - Erlang libraries should have service metadata - * [THRIFT-3579] - Introduce retry to make cross - * [THRIFT-3306] - Java: TBinaryProtocol: Use 1 temp buffer instead of allocating 8 - * [THRIFT-3910] - Do not invoke pip as part of build process - * [THRIFT-1857] - Python 3.X Support - * [THRIFT-1944] - Binding to zero port - * [THRIFT-3954] - Enable the usage of structs called "Object" in Java - * [THRIFT-3981] - Enable analyzer strong mode in Dart library - * [THRIFT-3998] - Document ability to add custom tags to thrift structs - * [THRIFT-4006] - Add a removeEventListener method on TSocket - -## New Feature - * [THRIFT-640] - Support deprecation - * [THRIFT-948] - SSL socket support for PHP - * [THRIFT-764] - add Support for Vala language - * [THRIFT-3046] - Allow PSR4 class loading for generated classes (PHP) - * [THRIFT-2113] - Erlang SSL Socket Support - * [THRIFT-1482] - Unix domain socket support under PHP - * [THRIFT-519] - Support collections of types without having to explicitly define it - * [THRIFT-468] - Rack Middleware Application for Rails - * [THRIFT-1708] - Add event handlers for processor events - * [THRIFT-3834] - Erlang namespacing and exception metadata - * [THRIFT-2510] - Implement TNonblockingServer's ability to listen on unix domain sockets - * [THRIFT-3397] - Implement TProcessorFactory in C# to enable per-client processors - * [THRIFT-3523] - XML Generator - * [THRIFT-3510] - Add HttpTaskAsyncHandler implementation - * [THRIFT-3318] - PHP: SimpleJSONProtocol Implementation - * [THRIFT-3299] - Dart language bindings in Thrift - * [THRIFT-2835] - Add possibility to distribute generators separately from thrift core, and load them dynamically - * [THRIFT-184] - Add OSGi Manifest headers to the libthrift java library to be able to use Thrift in the OSGi runtime - * [THRIFT-141] - If a required field is not present on serialization, throw an exception - * [THRIFT-1891] - Add Windows ALPC transport which is right counterpart of Unix domain sockets - -## Question - * [THRIFT-1808] - The Thrift struct should be considered self-contained? - * [THRIFT-2895] - Tutorial cpp - * [THRIFT-3860] - Elephant-bird application Test fails for Thrift - * [THRIFT-3811] - HTTPS Support for C++ applications - * [THRIFT-3509] - "make check" error - -## Story - * [THRIFT-3452] - .travis.yml: Migrating from legacy to container-based infrastructure - -## Sub-task - * [THRIFT-1811] - ruby tutorial as part of the regular build - * [THRIFT-2779] - PHP TJSONProtocol encode unicode into UCS-4LE which can't be parsed by other language bindings - * [THRIFT-2110] - Erlang: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-3852] - A Travis-CI job fails with "write error" - * [THRIFT-3740] - Fix haxelib.json classpath - * [THRIFT-3653] - incorrect union serialization - * [THRIFT-3652] - incorrect serialization of optionals - * [THRIFT-3655] - incorrect union serialization - * [THRIFT-3654] - incorrect serialization of optionals - * [THRIFT-3656] - incorrect serialization of optionals - * [THRIFT-3699] - Fix integer limit symbol includes in Python C extension - * [THRIFT-3693] - Fix include issue in C++ TSSLSocketInterruptTest on Windows - * [THRIFT-3694] - [Windows] Disable tests of a few servers that are not supported - * [THRIFT-3696] - Install pip to CentOS Docker images to fix Python builds - * [THRIFT-3638] - Fix haxelib.json - * [THRIFT-3251] - Add http transport for server to Go lib - * [THRIFT-2424] - Recursive Types - * [THRIFT-2423] - THeader - * [THRIFT-2413] - Python: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2409] - Java: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2412] - D: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2411] - C++: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2410] - JavaMe: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2668] - TestSuite: detailed result on passed tests by feature - * [THRIFT-2659] - python Test Server fails when throwing TException - * [THRIFT-3398] - Add CMake build for Haskell library and tests - * [THRIFT-3396] - DART: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-3364] - Fix ruby binary field encoding in TJSONProtocol - * [THRIFT-3381] - Fix for misc. codegen issues with THRIFT-2905 - * [THRIFT-3573] - No rule to make target `../../../test/c_glib/src/.deps/testthrifttest-thrift_test_handler.Po'. - * [THRIFT-3572] - "Unable to determine the behavior of a signed right shift" - * [THRIFT-3542] - Add length limit support to Java test server - * [THRIFT-3537] - Remove the (now obsolete) csharp:asyncctp flag - * [THRIFT-3532] - Add configurable string and container read size limit to Python protocols - * [THRIFT-3531] - Create cross lang feature test for string and container read length limit - * [THRIFT-3482] - Haskell JSON protocol does not encode binary field as Base64 - * [THRIFT-3425] - Minor fixes + simplification for CentOS Dockerfile - * [THRIFT-3442] - Run CMake tests on Appveyor - * [THRIFT-3409] - NodeJS binary field issues - * [THRIFT-3621] - Fix lib/cpp/test/SecurityTest.cpp to use ephemeral ports - * [THRIFT-3628] - Fix lib/cpp/test/TServerIntegrationTest.cpp to use ephemeral ports - * [THRIFT-3625] - Kill unused #include "TestPortFixture.h" in lib/cpp/test/TServerTransportTest.cpp. - * [THRIFT-3646] - Fix Python extension build warnings - * [THRIFT-3626] - Fix lib/cpp/test/TSocketInterruptTest.cpp to use ephemeral ports. - * [THRIFT-3624] - Fix lib/cpp/test/TServerSocketTest.cpp to use ephemeral ports - * [THRIFT-3623] - Fix Fix cpp/lib/test/TSSLSocketInterruptTest.cpp to use ephemeral ports - * [THRIFT-3592] - Add basic test client - * [THRIFT-3980] - add TExtendedBinaryProtocol.java - -## Task - * [THRIFT-1801] - Sync up TApplicationException codes across languages and thrift implementations - * [THRIFT-1259] - Automate versioning - -## Test - * [THRIFT-3400] - Add Erlang to cross test - * [THRIFT-3504] - Fix FastbinaryTest.py - -## Wish - * [THRIFT-3923] - Maybe remove Aereo from the "Powered by" list - * [THRIFT-2149] - Add an option to disable the generation of default operators - - - -Thrift 0.9.3 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-2441] - Cannot shutdown TThreadedServer when clients are still connected - * [THRIFT-2465] - TBinaryProtocolT breaks if copied/moved - * [THRIFT-2474] - thrift.h causes a compile failure - * [THRIFT-2540] - Running configure from outside the source directory fails - * [THRIFT-2598] - Add check for minimum Go version to configure.ac - * [THRIFT-2647] - compiler-hs: don't decapitalize field names, do decapitalize argument bindings - * [THRIFT-2773] - Generated Java code for 'oneway' methods is incorrect. - * [THRIFT-2789] - TNonblockingServer leaks socket FD's under load - * [THRIFT-2682] - TThreadedServer leaks per-thread memory - * [THRIFT-2674] - JavaScript: declare Accept: and Content-Type: in request - * [THRIFT-3078] - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket - * [THRIFT-3077] - C++ TFileTransport ignores return code from ftruncate - * [THRIFT-3067] - C++ cppcheck performance related warnings - * [THRIFT-3066] - C++ TDenseProtocol assert modifies instead of checks - * [THRIFT-3071] - bootstrap.sh on Ubuntu 12.04 (Precise) automake error - * [THRIFT-3069] - C++ TServerSocket leaks socket on fcntl get or set flags error - * [THRIFT-3079] - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket - * [THRIFT-3080] - C++ TNonblockingServer connection leak while accept huge number connections. - * [THRIFT-3086] - C++ Valgrind Error Cleanup - * [THRIFT-3085] - thrift_reconnecting_client never try to reconnect - * [THRIFT-3123] - Missing include in compiler/cpp/src/main.h breaks build in some environments - * [THRIFT-3125] - Fix the list of exported headers in automake input - * [THRIFT-3126] - PHP JSON serializer converts empty or int-indexed maps to lists - * [THRIFT-3132] - Properly format date in Java @Generated annotations - * [THRIFT-3137] - Travis build hangs after failure - * [THRIFT-3138] - "make check" parallel execution is underministic - * [THRIFT-3139] - JS library test is flaky - * [THRIFT-3140] - ConcurrentModificationException is thrown by JavaScript test server - * [THRIFT-3124] - Some signed/unsigned warnings while building compiler - * [THRIFT-3128] - Go generated code produces name collisions between services - * [THRIFT-3146] - Graphviz generates function name collisions between services - * [THRIFT-3147] - Segfault while receiving data - * [THRIFT-3148] - Markdown links to coding_standards are dead - * [THRIFT-3090] - cmake build is broken on MacOSX - * [THRIFT-3097] - cmake targets unconditionally depend on optional libraries - * [THRIFT-3094] - master as of 2015-APR-13 fails -DBOOST_THREADS cmake build - * [THRIFT-3099] - cmake build is broken on FreeBSD - * [THRIFT-3089] - Assigning default ENUM values results in non-compilable java code if java namespace is not defined - * [THRIFT-3093] - mingw compile fixes for c++ library 0.9.2 - * [THRIFT-3098] - Thrift does not pretty print binary typedefs the way it does binary fields - * [THRIFT-3091] - c_glib service method should return result from handler method - * [THRIFT-3088] - TThreadPoolServer with Sasl auth may leak CLOSE_WAIT socket - * [THRIFT-3109] - Cross test log file cannot be browsed when served in HTTP server - * [THRIFT-3113] - m4 C++11 macro issue - * [THRIFT-3105] - C++ libthriftnb library on Windows build failure - * [THRIFT-3115] - Uncompileable code due to name collision with predefined used types - * [THRIFT-3117] - Java TSSLTransportFactory can't load certificates within JAR archive - * [THRIFT-3102] - could not make check for Go Library - * [THRIFT-3120] - Minor spelling errors and an outdated URL - * [THRIFT-3121] - Librt does not exist on OS X - * [THRIFT-3152] - Compiler error on Mac OSX (missing #include ) - * [THRIFT-3162] - make fails for dmd 2.067 - * [THRIFT-3164] - Thrift C++ library SSL socket by default allows for unsecure SSLv3 negotiation - * [THRIFT-3168] - Fix Maven POM - * [THRIFT-3170] - Initialism code in the Go compiler causes chaos - * [THRIFT-3169] - Do not export thrift.TestStruct and thrift.TestEnum in thrift Go library - * [THRIFT-3191] - Perl compiler does not add support for unexpected exception handling - * [THRIFT-3178] - glib C does not compile - * [THRIFT-3189] - Perl ServerSocket should allow a specific interface to be listened to - * [THRIFT-3252] - Missing TConcurrentClientSyncInfo.h in cpp Makefile, so doesn't install - * [THRIFT-3255] - Thrift generator doesn't exclude 'package' keyword for thrift property names breaking java builds - * [THRIFT-3260] - multiple warnings in c_glib tutorial - * [THRIFT-3256] - Some D test timings are too aggressive for slow machines - * [THRIFT-3257] - warning: extra tokens at end of #endif directive - * [THRIFT-3184] - Thrift Go leaves file descriptors open - * [THRIFT-3203] - DOAP - please fix "Ocaml" => "OCaml" - * [THRIFT-3210] - (uncompileable) code generated for server events while are events not enabled - * [THRIFT-3215] - TJSONProtocol '(c++) uses "throw new" to throw exceptions instead of "throw" - * [THRIFT-3202] - Allow HSHAServer to configure min and max worker threads separately. - * [THRIFT-3205] - TCompactProtocol return a wrong error when the io.EOF happens - * [THRIFT-3209] - LGPL mentioned in license file - * [THRIFT-3197] - keepAliveTime is hard coded as 60 sec in TThreadPoolServer - * [THRIFT-3196] - Misspelling in lua TBinaryProtocol (stirctWrite => strictWrite) - * [THRIFT-3198] - Allow construction of TTransportFactory with a specified maxLength - * [THRIFT-3192] - Go import paths changed in 1.4, and expired June 1 - * [THRIFT-3271] - Could not find or load main class configtest_ax_javac_and_java on some non-english systems - * [THRIFT-3273] - c_glib: Generated code tries to convert between function and void pointers - * [THRIFT-3264] - Fix Erlang 16 namespaced types - * [THRIFT-3270] - reusing TNonblockingServer::TConnection cause dirty TSocket - * [THRIFT-3267] - c_glib: "Critical" failure during unit tests - * [THRIFT-3277] - THttpClient leaks connections if it's used for multiple requests - * [THRIFT-3278] - NodeJS: Fix exception stack traces and names - * [THRIFT-3279] - Fix a bug in retry_max_delay (NodeJS) - * [THRIFT-3280] - Initialize retry variables on construction - * [THRIFT-3283] - c_glib: Tutorial server always exits with warning - * [THRIFT-3284] - c_glib: Empty service produces unused-variable warning - * [THRIFT-1925] - c_glib generated code does not compile - * [THRIFT-1849] - after transport->open() opens isOpen returns true and next open() goes thru when it shall not - * [THRIFT-1866] - java compiler generates non-compiling code with const's defined in a thrift when name includes non-identifier chars - * [THRIFT-1938] - FunctionRunner.h -- uses wrong path for Thread.h when installed - * [THRIFT-1844] - Password string not cleared - * [THRIFT-2004] - Thrift::Union violates :== method contract and crashes - * [THRIFT-2073] - Thrift C++ THttpClient error: cannot refill buffer - * [THRIFT-2127] - Autoconf scripting does not properly account for cross-compile - * [THRIFT-2180] - Integer types issues in Cocoa lib on ARM64 - * [THRIFT-2189] - Go needs "isset" to fully support "union" type (and optionals) - * [THRIFT-2192] - autotools on Redhat based systems - * [THRIFT-2546] - cross language tests fails at 'TestMultiException' when using nodejs server - * [THRIFT-2547] - nodejs servers and clients fails to connect with cpp using compact protocol - * [THRIFT-2548] - Nodejs servers and clients does not work properly with -ssl - * [THRIFT-1471] - toString() does not print ByteBuffer values when nested in a List - * [THRIFT-1201] - getaddrinfo resource leak - * [THRIFT-615] - TThreadPoolServer doesn't call task_done after pulling tasks from it's clients queue - * [THRIFT-162] - Thrift structures are unhashable, preventing them from being used as set elements - * [THRIFT-810] - Crashed client on TSocket::close under loads - * [THRIFT-557] - charset problem with file Autogenerated by Thrift - * [THRIFT-233] - IDL doesn't support negative hex literals - * [THRIFT-1649] - contrib/zeromq does not build in 0.8.0 - * [THRIFT-1642] - Miscalculation lead to throw unexpected "TTransportException::TIMED_OUT"(or called "EAGAIN (timed out)") exception - * [THRIFT-1587] - TSocket::setRecvTimeout error - * [THRIFT-1248] - pointer subtraction in TMemoryBuffer relies on undefined behavior - * [THRIFT-1774] - Sasl Transport client would hang when trying to connect non-sasl transport server - * [THRIFT-1754] - RangeError in buffer handling - * [THRIFT-1618] - static structMap in FieldMetaData is not thread safe and can lead to deadlocks - * [THRIFT-2335] - thrift incompatibility with py:tornado as server, java as client - * [THRIFT-2803] - TCP_DEFER_ACCEPT not supported with domain sockets - * [THRIFT-2799] - Build Problem(s): ld: library not found for -l:libboost_unit_test_framework.a - * [THRIFT-2801] - C++ test suite compilation warnings - * [THRIFT-2802] - C++ tutorial compilation warnings - * [THRIFT-2795] - thrift_binary_protocol.c: 'dereferencing type-punned pointer will break strict-aliasing rules' - * [THRIFT-2817] - TSimpleJSONProtocol reads beyond end of message - * [THRIFT-2826] - html:standalone sometimes ignored - * [THRIFT-2829] - Support haxelib installation via github - * [THRIFT-2828] - slightly wrong help screen indent - * [THRIFT-2831] - Removes dead code in web_server.js introduced in THRIFT-2819 - * [THRIFT-2823] - All JS-tests are failing when run with grunt test - * [THRIFT-2827] - Thrift 0.9.2 fails to compile on Yosemite due to tr1/functional include in ProcessorTest.cpp - * [THRIFT-2843] - Automake configure.ac has possible typo related to Java - * [THRIFT-2813] - multiple haxe library fixes/improvements - * [THRIFT-2825] - Supplying unicode to python Thrift client can cause next request arguments to get overwritten - * [THRIFT-2840] - Cabal file points to LICENSE file outside the path of the Haskell project. - * [THRIFT-2818] - Trailing commas in array - * [THRIFT-2830] - Clean up ant warnings in tutorial dir - * [THRIFT-2842] - Erlang thrift client has infinite timeout - * [THRIFT-2810] - Do not leave the underlying ServerSocket open if construction of TServerSocket fails - * [THRIFT-2812] - Go server adding redundant buffering layer - * [THRIFT-2839] - TFramedTransport read bug - * [THRIFT-2844] - Nodejs support broken when running under Browserify - * [THRIFT-2814] - args/result classes not found when no namespace is set - * [THRIFT-2847] - function IfValue() is a duplicate of System.StrUtils.IfThen - * [THRIFT-2848] - certain Delphi tests do not build if TypeRegistry is used - * [THRIFT-2854] - Go Struct writer and reader looses important error information - * [THRIFT-2858] - Enable header field case insensitive match in THttpServer - * [THRIFT-2857] - C# generator creates uncompilable code for struct constants - * [THRIFT-2860] - Delphi server closes connection on unexpected exceptions - * [THRIFT-2868] - Enhance error handling in the Go client - * [THRIFT-2879] - TMemoryBuffer: using lua string in wrong way - * [THRIFT-2851] - Remove strange public Peek() from Go transports - * [THRIFT-2852] - Better Open/IsOpen/Close behavior for StreamTransport. - * [THRIFT-2871] - Missing semicolon in thrift.js - * [THRIFT-2872] - ThreadManager deadlock for task expiration - * [THRIFT-2881] - Handle errors from Accept() correctly - * [THRIFT-2849] - Spell errors reported by codespell tool - * [THRIFT-2870] - C++ TJSONProtocol using locale dependent formatting - * [THRIFT-2882] - Lua Generator: using string.len funtion to get struct(map,list,set) size - * [THRIFT-2864] - JSON generator missing from Visual Studio build project - * [THRIFT-2878] - Go validation support of required fields - * [THRIFT-2873] - TPipe and TPipeServer don't compile on Windows with UNICODE enabled - * [THRIFT-2888] - import of is missing in JSON generator - * [THRIFT-2900] - Python THttpClient does not reset socket timeout on exception - * [THRIFT-2907] - 'ntohll' macro redefined - * [THRIFT-2884] - Map does not serialize correctly for JSON protocol in Go library - * [THRIFT-2887] - --with-openssl configure flag is ignored - * [THRIFT-2894] - PHP json serializer skips maps with int/bool keys - * [THRIFT-2904] - json_protocol_test.go fails - * [THRIFT-2906] - library not found for -l:libboost_unit_test_framework.a - * [THRIFT-2890] - binary data may lose bytes with JSON transport under specific circumstances - * [THRIFT-2891] - binary data may cause a failure with JSON transport under specific circumstances - * [THRIFT-2901] - Fix for generated TypeScript functions + indentation of JavaScript maps - * [THRIFT-2916] - make check fails for D language - * [THRIFT-2918] - Race condition in Python TProcessPoolServer test - * [THRIFT-2920] - Erlang Thrift test uses wrong IDL file - * [THRIFT-2922] - $TRIAL is used with Python tests but not tested accordingly - * [THRIFT-2912] - Autotool build for C++ Qt library is invalid - * [THRIFT-2914] - explicit dependency to Lua5.2 fails on some systems - * [THRIFT-2910] - libevent is not really optional - * [THRIFT-2911] - fix c++ version zeromq transport, the old version cannot work - * [THRIFT-2915] - Lua generator missing from Visual Studio build project - * [THRIFT-2917] - "make clean" breaks test/c_glib - * [THRIFT-2919] - Haxe test server timeout too large - * [THRIFT-2923] - JavaScript client assumes a message being written - * [THRIFT-2924] - TNonblockingServer crashes when user-provided event_base is used - * [THRIFT-2925] - CMake build does not work with OpenSSL nor anything installed in non-system location - * [THRIFT-2931] - Access to undeclared static property: Thrift\Protocol\TProtocol::$TBINARYPROTOCOLACCELERATED - * [THRIFT-2893] - CMake build fails with boost thread or std thread - * [THRIFT-2902] - Generated c_glib code does not compile with clang - * [THRIFT-2903] - Qt4 library built with CMake does not work - * [THRIFT-2942] - CSharp generate invalid code for property named read or write - * [THRIFT-2932] - Node.js Thrift connection libraries throw Exceptions into event emitter - * [THRIFT-2933] - v0.9.2: doubles encoded in node with compact protocol cannot be decoded by python - * [THRIFT-2934] - createServer signature mismatch - * [THRIFT-2981] - IDL with no namespace produces unparsable PHP - * [THRIFT-2999] - Addition of .gitattributes text auto in THRIFT-2724 causes modified files on checkout - * [THRIFT-2949] - typo in compiler/cpp/README.md - * [THRIFT-2957] - warning: source file %s is in a subdirectory, but option 'subdir-objects' is disabled - * [THRIFT-2953] - TNamedPipeServerTransport is not Stop()able - * [THRIFT-2962] - Docker Thrift env for development and testing - * [THRIFT-2971] - C++ test and tutorial parallel build is unstable - * [THRIFT-2972] - Missing backslash in lib/cpp/test/Makefile.am - * [THRIFT-2951] - Fix Erlang name conflict test - * [THRIFT-2955] - Using list of typedefs does not compile on Go - * [THRIFT-2960] - namespace regression for Ruby - * [THRIFT-2959] - nodejs: fix binary unit tests - * [THRIFT-2966] - nodejs: Fix bad references to TProtocolException and TProtocolExceptionType - * [THRIFT-2970] - grunt-jsdoc fails due to dependency issues - * [THRIFT-3001] - C# Equals fails for binary fields (byte[]) - * [THRIFT-3003] - Missing LICENSE file prevents package from being installed - * [THRIFT-3008] - Node.js server does not fully support exception - * [THRIFT-3007] - Travis build is broken because of directory conflict - * [THRIFT-3009] - TSSLSocket does not use the correct hostname (breaks certificate checks) - * [THRIFT-3011] - C# test server testException() not implemented according to specs - * [THRIFT-3012] - Timing problems in NamedPipe implementation due to unnecessary open/close - * [THRIFT-3019] - Golang generator missing docstring for structs - * [THRIFT-3021] - Service remote tool does not import stub package with package prefix - * [THRIFT-3026] - TMultiplexedProcessor does not have a constructor - * [THRIFT-3028] - Regression caused by THRIFT-2180 - * [THRIFT-3017] - order of map key/value types incorrect for one CTOR - * [THRIFT-3020] - Cannot compile thrift as C++03 - * [THRIFT-3024] - User-Agent "BattleNet" used in some Thrift library files - * [THRIFT-3047] - Uneven calls to indent_up and indent_down in Cocoa generator - * [THRIFT-3048] - NodeJS decoding of I64 is inconsistent across protocols - * [THRIFT-3043] - go compiler generator uses non C++98 code - * [THRIFT-3044] - Docker README.md paths to Dockerfiles are incorrect - * [THRIFT-3040] - bower.json wrong "main" path - * [THRIFT-3051] - Go Thrift generator creates bad go code - * [THRIFT-3057] - Java compiler build is broken - * [THRIFT-3061] - C++ TSSLSocket shutdown delay/vulnerability - * [THRIFT-3062] - C++ TServerSocket invalid port number (over 999999) causes stack corruption - * [THRIFT-3065] - Update libthrift dependencies (slf4j, httpcore, httpclient) - * [THRIFT-3244] - TypeScript: fix namespace of included types - * [THRIFT-3246] - Reduce the number of trivial warnings in Windows C++ CMake builds - * [THRIFT-3224] - Fix TNamedPipeServer unpredictable behavior on accept - * [THRIFT-3230] - Python compiler generates wrong code if there is function throwing a typedef of exception with another namespace - * [THRIFT-3236] - MaxSkipDepth never checked - * [THRIFT-3239] - Limit recursion depth - * [THRIFT-3241] - fatal error: runtime: cannot map pages in arena address space - * [THRIFT-3242] - OSGi Import-Package directive is missing the Apache HTTP packages - * [THRIFT-3234] - Limit recursion depth - * [THRIFT-3222] - TypeScript: Generated Enums are quoted - * [THRIFT-3229] - unexpected Timeout exception when desired bytes are only partially available - * [THRIFT-3231] - CPP: Limit recursion depth to 64 - * [THRIFT-3235] - Limit recursion depth - * [THRIFT-3175] - fastbinary.c python deserialize can cause huge allocations from garbage - * [THRIFT-3176] - Union incorrectly implements == - * [THRIFT-3177] - Fails to run rake test - * [THRIFT-3180] - lua plugin: framed transport do not work - * [THRIFT-3179] - lua plugin cant connect to remote server because function l_socket_create_and_connect always bind socket to localhost - * [THRIFT-3248] - TypeScript: additional comma in method signature without parameters - * [THRIFT-3302] - Go JSON protocol should encode Thrift byte type as signed integer string - * [THRIFT-3297] - c_glib: an abstract base class is not generated - * [THRIFT-3294] - TZlibTransport for Java does not write data correctly - * [THRIFT-3296] - Go cross test does not conform to spec - * [THRIFT-3295] - C# library does not build on Mono 4.0.2.5 or later - * [THRIFT-3293] - JavaScript: null values turn into empty structs in constructor - * [THRIFT-3310] - lib/erl/README.md has incorrect formatting - * [THRIFT-3319] - CSharp tutorial will not build using the *.sln - * [THRIFT-3335] - Ruby server does not handle processor exception - * [THRIFT-3338] - Stray underscore in generated go when service name starts with "New" - * [THRIFT-3324] - Update Go Docs for pulling all packages - * [THRIFT-3345] - Clients blocked indefinitely when a java.lang.Error is thrown - * [THRIFT-3332] - make dist fails on clean build - * [THRIFT-3326] - Tests do not compile under *BSD - * [THRIFT-3334] - Markdown notation of protocol spec is malformed - * [THRIFT-3331] - warning: ‘etype’ may be used uninitialized in this function - * [THRIFT-3349] - Python server does not handle processor exception - * [THRIFT-3343] - Fix haskell README - * [THRIFT-3340] - Python: enable json tests again - * [THRIFT-3311] - Top level README.md has incorrect formmating - * [THRIFT-2936] - Minor memory leak in SSL - * [THRIFT-3290] - Using from in variable names causes the generated Python code to have errors - * [THRIFT-3225] - Fix TPipeServer unpredictable behavior on interrupt() - * [THRIFT-3354] - Fix word-extraction substr bug in initialism code - * [THRIFT-2006] - TBinaryProtocol message header call name length is not validated and can be used to core the server - * [THRIFT-3329] - C++ library unit tests don't compile against the new boost-1.59 unit test framework - * [THRIFT-2630] - windows7 64bit pc. ipv4 and ipv6 pc.can't use - * [THRIFT-3336] - Thrift generated streaming operators added in 0.9.2 cannot be overridden - * [THRIFT-2681] - Core of unwind_cleanup - * [THRIFT-3317] - cpp namespace org.apache issue appears in 0.9 - -## Documentation - * [THRIFT-3286] - Apache Ant is a necessary dependency - -## Improvement - * [THRIFT-227] - Byte[] in collections aren't pretty printed like regular binary fields - * [THRIFT-2744] - Vagrantfile for Centos 6.5 - * [THRIFT-2644] - Haxe support - * [THRIFT-2756] - register Media Type @ IANA - * [THRIFT-3076] - Compatibility with Haxe 3.2.0 - * [THRIFT-3081] - C++ Consolidate client processing loops in TServers - * [THRIFT-3083] - C++ Consolidate server processing loops in TSimpleServer, TThreadedServer, TThreadPoolServer - * [THRIFT-3084] - C++ add concurrent client limit to threaded servers - * [THRIFT-3074] - Add compiler/cpp/lex.yythriftl.cc to gitignore. - * [THRIFT-3134] - Remove use of deprecated "phantom.args" - * [THRIFT-3133] - Allow "make cross" and "make precross" to run without building all languages - * [THRIFT-3142] - Make JavaScript use downloaded libraries - * [THRIFT-3141] - Improve logging of JavaScript test - * [THRIFT-3144] - Proposal: make String representation of enums in generated go code less verbose - * [THRIFT-3130] - Remove the last vestiges of THRIFT_OVERLOAD_IF from THRIFT-1316 - * [THRIFT-3131] - Consolidate suggested import path for go thrift library to git.apache.org in docs and code - * [THRIFT-3092] - Generated Haskell types should derive Generic - * [THRIFT-3110] - Print error log after cross test failures on Travis - * [THRIFT-3114] - Using local temp variables to not pollute the global table - * [THRIFT-3106] - CMake summary should give more information why a library is set to off - * [THRIFT-3119] - Java's TThreadedSelectorServer has indistinguishable log messages in run() - * [THRIFT-3122] - Javascript struct constructor should properly initialize struct and container members from plain js arguments - * [THRIFT-3151] - Fix links to git-wip* - should be git.apache.org - * [THRIFT-3167] - Windows build from source instructions need to be revised - * [THRIFT-3155] - move contrib/mingw32-toolchain.cmake to build/cmake/ - * [THRIFT-3160] - Make generated go enums implement TextMarshaller and TextUnmarshaller interfaces - * [THRIFT-3150] - Add an option to thrift go generator to make Read and Write methods private - * [THRIFT-3149] - Make ReadFieldN methods in generated Go code private - * [THRIFT-3172] - Add tutorial to Thrift web site - * [THRIFT-3214] - Add Erlang option for using maps instead of dicts - * [THRIFT-3201] - Capture github test artifacts for failed builds - * [THRIFT-3266] - c_glib: Multiple compiler warnings building unit tests - * [THRIFT-3285] - c_glib: Build library with all warnings enabled, no warnings generated - * [THRIFT-1954] - Allow for a separate connection timeout value - * [THRIFT-2098] - Add support for Qt5+ - * [THRIFT-2199] - Remove Dense protocol (was: move to Contrib) - * [THRIFT-406] - C++ Test suite cleanup - * [THRIFT-902] - socket and connect timeout in TSocket should be distinguished - * [THRIFT-388] - Use a separate wire format for async calls - * [THRIFT-727] - support native C++ language specific exception message - * [THRIFT-1784] - pep-3110 compliance for exception handling - * [THRIFT-1025] - C++ ServerSocket should inherit from Socket with the necessary Ctor to listen on connections from a specific host - * [THRIFT-2269] - Can deploy libthrift-source.jar to maven center repository - * [THRIFT-2804] - Pull an interface out of TBaseAsyncProcessor - * [THRIFT-2806] - more whitespace fixups - * [THRIFT-2811] - Make remote socket address accessible - * [THRIFT-2809] - .gitignore update for compiler's visual project - * [THRIFT-2846] - Expose ciphers parameter from ssl.wrap_socket() - * [THRIFT-2859] - JSON generator: output complete descriptors - * [THRIFT-2861] - add buffered transport - * [THRIFT-2865] - Test case for Go: SeqId out of sequence - * [THRIFT-2866] - Go generator source code is hard to read and maintain - * [THRIFT-2880] - Read the network address from the listener if available. - * [THRIFT-2875] - Typo in TDenseProtocol.h comment - * [THRIFT-2874] - TBinaryProtocol member variable "string_buf_" is never used. - * [THRIFT-2855] - Move contributing.md to the root of the repository - * [THRIFT-2862] - Enable RTTI and/or build macros for generated code - * [THRIFT-2876] - Add test for THRIFT-2526 Assignment operators and copy constructors in c++ don't copy the __isset struct - * [THRIFT-2897] - Generate -isEqual: and -hash methods - * [THRIFT-2909] - Improve travis build - * [THRIFT-2921] - Make Erlang impl ready for OTP 18 release (dict/0 and set/0 are deprecated) - * [THRIFT-2928] - Rename the erlang test_server module - * [THRIFT-2940] - Allow installing Thrift from git as NPM module by providing package.json in top level directory - * [THRIFT-2937] - Allow setting a maximum frame size in TFramedTransport - * [THRIFT-2976] - nodejs: xhr and websocket support for browserify - * [THRIFT-2996] - Test for Haxe 3.1.3 or better - * [THRIFT-2969] - nodejs: DRY up library tests - * [THRIFT-2973] - Update Haxe lib readme regarding Haxe 3.1.3 - * [THRIFT-2952] - Improve handling of Server.Stop() - * [THRIFT-2964] - nodejs: move protocols and transports into separate files - * [THRIFT-2963] - nodejs - add test coverage - * [THRIFT-3006] - Attach 'omitempty' json tag for optional fields in Go - * [THRIFT-3027] - Go compiler does not ensure common initialisms have consistent case - * [THRIFT-3030] - TThreadedServer: Property for number of clientThreads - * [THRIFT-3023] - Go compiler is a little overly conservative with names of attributes - * [THRIFT-3018] - Compact protocol for Delphi - * [THRIFT-3025] - Change pure Int constants into @enums (where possible) - * [THRIFT-3031] - migrate "shouldStop" flag to TServer - * [THRIFT-3022] - Compact protocol for Haxe - * [THRIFT-3041] - Generate asynchronous clients for Cocoa - * [THRIFT-3053] - Perl SSL Socket Support (Encryption) - * [THRIFT-3247] - Generate a C++ thread-safe client - * [THRIFT-3217] - Provide a little endian variant of the binary protocol in C++ - * [THRIFT-3223] - TypeScript: Add initial support for Enum Maps - * [THRIFT-3220] - Option to suppress @Generated Annotation entirely - * [THRIFT-3300] - Reimplement TZlibTransport in Java using streams - * [THRIFT-3288] - c_glib: Build unit tests with all warnings enabled, no warnings generated - * [THRIFT-3347] - Improve cross test servers and clients - * [THRIFT-3342] - Improve ruby cross test client and server compatibility - * [THRIFT-2296] - Add C++ Base class for service - * [THRIFT-3337] - Add testBool method to cross tests - * [THRIFT-3303] - Disable concurrent cabal jobs on Travis to avoid GHC crash - * [THRIFT-2623] - Docker container for Thrift - * [THRIFT-3298] - thrift endian converters may conflict with other libraries - * [THRIFT-1559] - Provide memory pool for TBinaryProtocol to eliminate memory fragmentation - * [THRIFT-424] - Steal ProtocolBuffers' VarInt implementation for C++ - -## New Feature - * [THRIFT-3070] - Add ability to set the LocalCertificateSelectionCallback - * [THRIFT-1909] - Java: Add compiler flag to use the "option pattern" for optional fields - * [THRIFT-2099] - Stop TThreadPoolServer with alive connections. - * [THRIFT-123] - implement TZlibTransport in Java - * [THRIFT-2368] - New option: reuse-objects for Java generator - * [THRIFT-2836] - Optionally generate C++11 MoveConstructible types - * [THRIFT-2824] - Flag to disable html escaping doctext - * [THRIFT-2819] - Add WebsSocket client to node.js - * [THRIFT-3050] - Client certificate authentication for non-http TLS in C# - * [THRIFT-3292] - Implement TZlibTransport in Go - -## Question - * [THRIFT-2583] - Thrift on xPC target (SpeedGoat) - * [THRIFT-2592] - thrift server using c_glib - * [THRIFT-2832] - c_glib: Handle string lists correctly - * [THRIFT-3136] - thrift installation problem on mac - * [THRIFT-3346] - c_glib: Tutorials example crashes saying Calculator.ping implementation returned FALSE but did not set an error - -## Sub-task - * [THRIFT-2578] - Moving 'make cross' from test.sh to test.py - * [THRIFT-2734] - Go coding standards - * [THRIFT-2748] - Add Vagrantfile for Centos 6.5 - * [THRIFT-2753] - Misc. Haxe improvements - * [THRIFT-2640] - Compact Protocol in Cocoa - * [THRIFT-3262] - warning: overflow in implicit constant conversion in DenseProtoTest.cpp - * [THRIFT-3194] - Can't build with go enabled. gomock SCC path incorrect. - * [THRIFT-3275] - c_glib tutorial warnings in generated code - * [THRIFT-1125] - Multiplexing support for the Ruby Library - * [THRIFT-2807] - PHP Code Style - * [THRIFT-2841] - Add comprehensive integration tests for the whole Go stack - * [THRIFT-2815] - Haxe: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-2886] - Integrate binary type in standard Thrift cross test - * [THRIFT-2946] - Enhance usability of cross test framework - * [THRIFT-2967] - Add .editorconfig to root - * [THRIFT-3033] - Perl: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-3174] - Initialism code in the Go compiler doesn't check first word - * [THRIFT-3193] - Option to supress date value in @Generated annotation - * [THRIFT-3305] - Missing dist files for 0.9.3 release candidate - * [THRIFT-3341] - Add testBool methods - * [THRIFT-3308] - Fix broken test cases for 0.9.3 release candidate - -## Task - * [THRIFT-2834] - Remove semi-colons from python code generator - * [THRIFT-2853] - Adjust comments not applying anymore after THRIFT-2852 - -## Test - * [THRIFT-3211] - Add make cross support for php TCompactProtocol - -## Wish - * [THRIFT-2838] - TNonblockingServer can bind to port 0 (i.e., get an OS-assigned port) but there is no way to get the port number - - - -Thrift 0.9.2 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-2793] - Go compiler produces uncompilable code - * [THRIFT-1481] - Unix domain sockets in C++ do not support the abstract namespace - * [THRIFT-1455] - TBinaryProtocolT::writeString casts from size_t to uint32_t, which is not safe on 64-bit platforms - * [THRIFT-1579] - PHP Extention - function thrift_protocol_read_binary not working from TBinarySerializer::deserialize - * [THRIFT-1584] - Error: could not SetMinThreads in ThreadPool on single-core machines - * [THRIFT-1614] - Thrift build from svn repo sources fails with automake-1.12 - * [THRIFT-1047] - rb_thrift_memory_buffer_write treats arg as string without check, segfaults if you pass non-string - * [THRIFT-1639] - Java/Python: Serialization/Deserialization of double type using CompactProtocol - * [THRIFT-1647] - NodeJS BufferedTransport does not work beyond the hello-world example - * [THRIFT-2130] - Thrift's D library/test: parts of "make check" code do not compile with recent dmd-2.062 through dmd-2.064alpha - * [THRIFT-2140] - Error compiling cpp tutorials - * [THRIFT-2139] - MSVC 2012 Error - Cannot compile due to BoostThreadFactory - * [THRIFT-2138] - pkgconfig file created with wrong include path - * [THRIFT-2160] - Warning in thrift.h when compiling with -Wunused and NDEBUG - * [THRIFT-2158] - Compact, JSON, and SimpleJSON protocols are not working correctly - * [THRIFT-2167] - nodejs lib throws error if options argument isn't passed - * [THRIFT-2288] - Go impl of Thrift JSON protocol wrongly writes/expects true/false for bools - * [THRIFT-2147] - Thrift IDL grammar allows for dotted identifier names - * [THRIFT-2145] - Rack and Thin are not just development dependencies - * [THRIFT-2267] - Should be able to choose socket family in Python TSocket - * [THRIFT-2276] - java path in spec file needs updating - * [THRIFT-2281] - Generated send/recv code ignores errors returned by the underlying protocol - * [THRIFT-2280] - TJSONProtocol.Flush() does not really flush the transport - * [THRIFT-2274] - TNonblockingServer and TThreadedSelectorServer do not close their channel selectors on exit and leak file descriptors - * [THRIFT-2265] - php library doesn't build - * [THRIFT-2232] - IsSet* broken in Go - * [THRIFT-2246] - Unset enum value is printed by ToString() - * [THRIFT-2240] - thrift.vim (contrib) does not correctly handle 'union' - * [THRIFT-2243] - TNonblockingServer in thrift crashes when TFramedTransport opens - * [THRIFT-2230] - Cannot Build on RHEL/Centos/Amazon Linux 6.x - * [THRIFT-2247] - Go generator doesn't deal well with map keys of type binary - * [THRIFT-2253] - Python Tornado TTornadoServer base class change - * [THRIFT-2261] - java: error: unmappable character for encoding ASCII - * [THRIFT-2259] - C#: unexpected null logDelegate() pointer causes AV in TServer.serve() - * [THRIFT-2225] - SSLContext destroy before cleanupOpenSSL - * [THRIFT-2224] - TSSLSocket.h and TSSLServerSocket.h should use the platfromsocket too - * [THRIFT-2229] - thrift failed to build on OSX 10.9 GM - * [THRIFT-2227] - Thrift compiler generates spurious warnings with Xlint - * [THRIFT-2219] - Thrift gem fails to build on OS X Mavericks with 1.9.3 rubies - * [THRIFT-2226] - TServerSocket - keepAlive wrong initialization order - * [THRIFT-2285] - TJsonProtocol implementation for Java doesn't allow a slash (/) to be escaped (\/) - * [THRIFT-2216] - Extraneous semicolon in TProtocolUtil.h makes clang mad - * [THRIFT-2215] - Generated HTML/Graphviz lists referenced enum identifiers as UNKNOWN. - * [THRIFT-2211] - Exception constructor does not contain namespace prefix. - * [THRIFT-2210] - lib/java TSimpleJSONProtocol can emit invalid JSON - * [THRIFT-2209] - Ruby generator -- please namespace classes - * [THRIFT-2202] - Delphi TServerImpl.DefaultLogDelegate may stop the server with I/O-Error 105 - * [THRIFT-2201] - Ternary operator returns different types (build error for some compilers) - * [THRIFT-2200] - nested structs cause generate_fingerprint() to slow down at excessive CPU load - * [THRIFT-2197] - fix jar output directory in rpm spec file - * [THRIFT-2196] - Fix invalid dependency in Makefile.am - * [THRIFT-2194] - Node: Not actually prepending residual data in TFramedTransport.receiver - * [THRIFT-2193] - Java code generator emits spurious semicolon when deep copying binary data - * [THRIFT-2191] - Fix charp JSONProtocol.ReadJSONDouble (specify InvariantCulture) - * [THRIFT-2214] - System header sys/param.h is included inside the Thrift namespace - * [THRIFT-2178] - Thrift generator returns error exit code on --version - * [THRIFT-2171] - NodeJS implementation has extremely low test coverage - * [THRIFT-2183] - gem install fails on zsh - * [THRIFT-2182] - segfault in regression tests (GC bug in rb_thrift_memory_buffer_write) - * [THRIFT-2181] - oneway calls don't work in NodeJS - * [THRIFT-2169] - JavaME Thrift Library causes "java.io.IOException: No Response Entries Available" after using the Thrift client for some time - * [THRIFT-2168] - Node.js appears broken (at least, examples don't work as intended) - * [THRIFT-2293] - TSSLTransportFactory.createSSLContext() leaves files open - * [THRIFT-2279] - TSerializer only returns the first 1024 bytes serialized - * [THRIFT-2278] - Buffered transport doesn't support writes > buffer size - * [THRIFT-2275] - Fix memory leak in golang compact_protocol. - * [THRIFT-2282] - Incorect code generated for some typedefs - * [THRIFT-2009] - Go redeclaration error - * [THRIFT-1964] - 'Isset' causes problems with C#/.NET serializers - * [THRIFT-2026] - Fix TCompactProtocol 64 bit builds - * [THRIFT-2108] - Fix TAsyncClientManager timeout race - * [THRIFT-2068] - Multiple calls from same connection are not processed in node - * [THRIFT-1750] - Make compiler build cleanly under visual studio 10 - * [THRIFT-1755] - Comment parsing bug - * [THRIFT-1771] - "make check" fails on x64 for libboost_unit_test_framework.a - * [THRIFT-1841] - NodeJS Thrift incorrectly parses non-UTF8-string types - * [THRIFT-1908] - Using php thrift_protocol accelerated transfer causes core dump - * [THRIFT-1892] - Socket timeouts are declared in milli-seconds, but are actually set in micro-seconds - * [THRIFT-2303] - TBufferredTransport not properly closing underlying transport - * [THRIFT-2313] - nodejs server crash after processing the first request when using MultiplexedProcessor/FramedBuffer/BinaryProtocol - * [THRIFT-2311] - Go: invalid code generated when exception name is a go keyword - * [THRIFT-2308] - node: TJSONProtocol parse error when reading from buffered message - * [THRIFT-2316] - ccp: TFileTransportTest - * [THRIFT-2352] - msvc failed to compile thrift tests - * [THRIFT-2337] - Golang does not report TIMED_OUT exceptions - * [THRIFT-2340] - Generated server implementation does not send response type EXCEPTION on the Thrift.TApplicationExceptionType.UNKNOWN_METHOD exception - * [THRIFT-2354] - Connection errors can lead to case_clause exceptions - * [THRIFT-2339] - Uncaught exception in thrift c# driver - * [THRIFT-2356] - c++ thrift client not working with ssl (SSL_connect hangs) - * [THRIFT-2331] - Missing call to ReadStructBegin() in TApplicationException.Read() - * [THRIFT-2323] - Uncompileable Delphi code generated for typedef'd structs - * [THRIFT-2322] - Correctly show the number of times ExecutorService (java) has rejected the client. - * [THRIFT-2389] - namespaces handled wrongly in acrionscript 3.0 implementation - * [THRIFT-2388] - GoLang - Fix data races in simple_server and server_socket - * [THRIFT-2386] - Thrift refuses to link yylex - * [THRIFT-2375] - Excessive
's in generated HTML - * [THRIFT-2373] - warning CS0414 in THttpClient.cs: private field 'Thrift.Transport.THttpClient.connection' assigned but never used - * [THRIFT-2372] - thrift/json_protocol.go:160: function ends without a return statement - * [THRIFT-2371] - ruby bundler version fails on ~1.3.1, remove and take latest avail - * [THRIFT-2370] - Compiler SEGFAULTs generating HTML documentation for complex strucre - * [THRIFT-2384] - Binary map keys produce uncompilable code in go - * [THRIFT-2380] - unreachable code (CID 1174546, CID 1174679) - * [THRIFT-2378] - service method arguments of binary type lead to uncompileable Go code - * [THRIFT-2363] - Issue with character encoding of Success returned from Login using Thrift Proxy and NodeJS - * [THRIFT-2359] - TBufferedTransport doesn't clear it's buffer on a failed flush call - * [THRIFT-2428] - Python 3 setup.py support - * [THRIFT-2367] - Build failure: stdlib and boost both define uint64_t - * [THRIFT-2365] - C# decodes too many binary bytes from JSON - * [THRIFT-2402] - byte count of FrameBuffer in AWAITING_CLOSE state is not subtracted from readBufferBytesAllocated - * [THRIFT-2396] - Build Error on MacOSX - * [THRIFT-2395] - thrift Ruby gem requires development dependency 'thin' regardless of environment - * [THRIFT-2414] - c_glib fix several bug. - * [THRIFT-2420] - Go argument parser for methods without arguments does not skip fields - * [THRIFT-2439] - Bug in TProtocolDecorator Class causes parsing errors - * [THRIFT-2419] - golang - Fix fmt.Errorf in generated code - * [THRIFT-2418] - Go handler function panics on internal error - * [THRIFT-2405] - Node.js Multiplexer tests fail (silently) - * [THRIFT-2581] - TFDTransport destructor should not throw - * [THRIFT-2575] - Thrift includes siginfo_t within apache::thrift::protocol namespace - * [THRIFT-2577] - TFileTransport missuse of closesocket on windows platform - * [THRIFT-2576] - Implement Thrift.Protocol.prototype.skip method in JavaScript library - * [THRIFT-2588] - Thrift compiler is not buildable in Visual Studio 2010 - * [THRIFT-2594] - JS Compiler: Single quotes are not being escaped in constants. - * [THRIFT-2591] - TFramedTransport does not handle payloads split across packets correctly - * [THRIFT-2599] - Uncompileable Delphi code due to naming conflicts with IDL - * [THRIFT-2590] - C++ Visual Studio solution doesn't include Multiplexing support - * [THRIFT-2595] - Node.js: Fix global leaks and copy-paste errors - * [THRIFT-2565] - autoconf fails to find mingw-g++ cross compiler on travis CI - * [THRIFT-2555] - excessive "unused field" comments - * [THRIFT-2554] - double initialization in generated Read() method - * [THRIFT-2551] - OutOfMemoryError "unable to create new native thread" kills serve thread - * [THRIFT-2543] - Generated enum type in haskell should be qualified - * [THRIFT-2560] - Thrift compiler generator tries to concat ints with strings using + - * [THRIFT-2559] - Centos 6.5 unable to "make" with Thrift 0.9.1 - * [THRIFT-2526] - Assignment operators and copy constructors in c++ don't copy the __isset struct - * [THRIFT-2454] - c_glib: There is no gethostbyname_r() in some OS. - * [THRIFT-2451] - Do not use pointers for optional fields with defaults. Do not write such fields if its value set to default. Also, do not use pointers for any optional fields mapped to go map or slice. generate Get accessors - * [THRIFT-2450] - include HowToContribute in the src repo - * [THRIFT-2448] - thrift/test/test.sh has incorrect Node.js test path - * [THRIFT-2460] - unopened socket fd must be less than zero. - * [THRIFT-2459] - --version should not exit 1 - * [THRIFT-2468] - Timestamp handling - * [THRIFT-2467] - Unable to build contrib/fb303 on OSX 10.9.2 - * [THRIFT-2466] - Improper error handling for SSL/TLS connections that don't complete a handshake - * [THRIFT-2463] - test/py/RunClientServer.py fails sometimes - * [THRIFT-2458] - Generated golang server code for "oneway" methods is incorrect - * [THRIFT-2456] - THttpClient fails when using async support outside Silverlight - * [THRIFT-2524] - Visual Studio project is missing TThreadedServer files - * [THRIFT-2523] - Visual Studio project is missing OverlappedSubmissionThread files - * [THRIFT-2520] - cpp:cob_style generates incorrect .tcc file - * [THRIFT-2508] - Uncompileable C# code due to language keywords in IDL - * [THRIFT-2506] - Update TProtocolException error codes to be used consistently throughout the library - * [THRIFT-2505] - go: struct should always be a pointer to avoid copying of potentially size-unbounded structs - * [THRIFT-2515] - TLS Method error during make - * [THRIFT-2503] - C++: Fix name collision when a struct has a member named "val" - * [THRIFT-2477] - thrift --help text with misplaced comma - * [THRIFT-2492] - test/cpp does not compile on mac - * [THRIFT-2500] - sending random data crashes thrift(golang) service - * [THRIFT-2475] - c_glib: buffered_transport_write function return always TRUE. - * [THRIFT-2495] - JavaScript/Node string constants lack proper escaping - * [THRIFT-2491] - unable to import generated ThriftTest service - * [THRIFT-2490] - c_glib: if fail to read a exception from server, client may be occurred double free - * [THRIFT-2470] - THttpHandler swallows exceptions from processor - * [THRIFT-2533] - Boost version in requirements should be updated - * [THRIFT-2532] - Java version in installation requirements should be updated - * [THRIFT-2529] - TBufferedTransport split Tcp data bug in nodeJs - * [THRIFT-2537] - Path for "go get" does not work (pull request 115) - * [THRIFT-2443] - Node fails cross lang tests - * [THRIFT-2437] - Author fields in Python setup.py must be strings not lists. - * [THRIFT-2435] - Java compiler doesn't like struct member names that are identical to an existing enum or struct type - * [THRIFT-2434] - Missing namespace import for php TMultiplexedProcessor implementation - * [THRIFT-2432] - Flaky parallel build - * [THRIFT-2430] - Crash during TThreadPoolServer shutdown - * [THRIFT-667] - Period should not be allowed in identifier names - * [THRIFT-1212] - Members capital case conflict - * [THRIFT-2584] - Error handler not listened on javascript client - * [THRIFT-2294] - Incorrect Makefile generation - * [THRIFT-2601] - Fix vagrant to work again for builds again - * [THRIFT-2092] - TNonblocking server should release handler as soon as connection closes - * [THRIFT-2557] - CS0542 member names cannot be the same as their enclosing type - * [THRIFT-2605] - TSocket warning on gcc 4.8.3 - * [THRIFT-2607] - ThreadManager.cpp warning on clang++ 3.4 - * [THRIFT-1998] - TCompactProtocol.tcc - one more warning on Visual 2010 - * [THRIFT-2610] - MSVC warning in TSocket.cpp - * [THRIFT-2614] - TNonblockingServer.cpp warnings on MSVC - * [THRIFT-2608] - TNonblockingServer.cpp warnings on clang 3.4 - * [THRIFT-2606] - ThreadManager.h warning in clang++ 3.4 - * [THRIFT-2609] - TFileTransport.h unused field warning (clang 3.4) - * [THRIFT-2416] - Cannot use TCompactProtocol with MSVC - * [THRIFT-1803] - Ruby Thrift 0.9.0 tries to encode UUID to UTF8 and crashes - * [THRIFT-2385] - Problem with gethostbyname2 during make check - * [THRIFT-2262] - thrift server 'MutateRow' operation gives no indication of success / failure - * [THRIFT-2048] - Prefer boolean context to nullptr_t conversion - * [THRIFT-2528] - Thrift Erlang Library: Multiple thrift applications in one bundle - * [THRIFT-1999] - warning on gcc 4.7 while compiling BoostMutex.cpp - * [THRIFT-2104] - Structs lose binary data when transferred from server to client in Java - * [THRIFT-2184] - undefined method rspec_verify for Thrift::MemoryBufferTransport - * [THRIFT-2351] - PHP TCompactProtocol has fails to decode messages - * [THRIFT-2016] - Resource Leak in thrift struct under compiler/cpp/src/parse/t_function.h - * [THRIFT-2273] - Please delete old releases from mirroring system - * [THRIFT-2270] - Faulty library version numbering at build or documentation - * [THRIFT-2203] - Tests keeping failing on Jenkins and Travis CI - * [THRIFT-2399] - thrift.el: recognize "//"-style comments in emacs thrift-mode - * [THRIFT-2582] - "FileTransport error" exception is raised when trying to use Java's TFileTransport - * [THRIFT-1682] - Multiple thread calling a Service function unsafely causes message corruption and terminates with Broken Pipe - * [THRIFT-2357] - recurse option has no effect when generating php - * [THRIFT-2248] - Go generator doesn't deal well with map keys of type binary - * [THRIFT-2426] - clarify IP rights and contributions from fbthrift - * [THRIFT-2041] - TNonblocking server compilation on windows (ARITHMETIC_RIGHT_SHIFT) - * [THRIFT-2400] - thrift.el: recognize "//"-style comments in emacs thrift-mode - * [THRIFT-1717] - Fix deb build in jenkins - * [THRIFT-2266] - ThreadManager.h:24:10: fatal error: 'tr1/functional' file not found on Mac 10.9 (Mavericks) - * [THRIFT-1300] - Test failures with parallel builds (make -j) - * [THRIFT-2487] - Tutorial requires two IDL files but only one is linked from the Thrift web site - * [THRIFT-2329] - missing release tags within git - * [THRIFT-2306] - concurent client calls with nodejs - * [THRIFT-2222] - ruby gem cannot be compiled on OS X mavericks - * [THRIFT-2381] - code which generated by thrift2/hbase.thrift compile error - * [THRIFT-2390] - no close event when connection lost - * [THRIFT-2146] - Unable to pass multiple "--gen" options to the thrift compiler - * [THRIFT-2438] - Unexpected readFieldEnd call causes JSON Parsing errors - * [THRIFT-2498] - Error message "Invalid method name" while trying to call HBase Thrift API - * [THRIFT-841] - Build cruft - * [THRIFT-2570] - Wrong URL given in http://thrift.apache.org/developers - * [THRIFT-2604] - Fix debian packaging - * [THRIFT-2618] - Unignore /aclocal files required for build - * [THRIFT-2562] - ./configure create MakeFile in lib/d with errors - * [THRIFT-2593] - Unable to build thrift on ubuntu-12.04 (Precise) - * [THRIFT-2461] - Can't install thrift-0.8.0 on OS X 10.9.2 - * [THRIFT-2602] - Fix missing dist files - * [THRIFT-2620] - Fix python packaging - * [THRIFT-2545] - Test CPP fails to build (possibly typo) - -## Documentation - * [THRIFT-2155] - Adding one liner guide to rename the version.h.in and rename thrifty.cc.h - * [THRIFT-1991] - Add exceptions to examples - * [THRIFT-2334] - add a tutorial for node JS - * [THRIFT-2392] - Actionscript tutorial - * [THRIFT-2383] - contrib: sample for connecting Thrift with Rebus - * [THRIFT-2382] - contrib: sample for connecting Thrift with STOMP - -## Improvement - * [THRIFT-1457] - Capacity of TframedTransport write buffer is never reset - * [THRIFT-1135] - Node.js tutorial - * [THRIFT-1371] - Socket timeouts (SO_RCVTIMEO and SO_SNDTIMEO) not supported on Solaris - * [THRIFT-2142] - Minor tweaks to thrift.el for better emacs package compatibility - * [THRIFT-2268] - Modify TSaslTransport to ignore TCP health checks from loadbalancers - * [THRIFT-2264] - GitHub page incorrectly states that Thrift is still incubating - * [THRIFT-2263] - Always generate good hashCode for Java - * [THRIFT-2233] - Java compiler should defensively copy its binary inputs - * [THRIFT-2239] - Address FindBugs errors - * [THRIFT-2249] - Add SMP Build option to thrift.spec (and three config defines) - * [THRIFT-2254] - Exceptions generated by Go compiler should implement error interface - * [THRIFT-2260] - Thrift imposes unneeded dependency on commons-lang3 - * [THRIFT-2258] - Add TLS v1.1/1.2 support to TSSLSocket.cpp - * [THRIFT-2205] - Node.js Test Server to support test.js JavaScript Browser test and sundry fixes - * [THRIFT-2204] - SSL client for the cocoa client - * [THRIFT-2172] - Java compiler allocates optionals array for every struct with an optional field - * [THRIFT-2185] - use cabal instead of runhaskell in haskell library - * [THRIFT-1926] - PHP Constant Generation Refactoring - * [THRIFT-2029] - Port C++ tests to Windows - * [THRIFT-2054] - TSimpleFileTransport - Java Lib has no straight forward TTransport based file transport - * [THRIFT-2040] - "uninitialized variable" warnings on MSVC/windows - * [THRIFT-2034] - Give developers' C++ code direct access to socket FDs on server side - * [THRIFT-2095] - Use print function for Python 3 compatiblity - * [THRIFT-1868] - Make the TPC backlog configurable in the Java servers - * [THRIFT-1813] - Add @Generated annotation to generated classes - * [THRIFT-1815] - Code generators line buffer output - * [THRIFT-2305] - TFramedTransport empty constructor should probably be private - * [THRIFT-2304] - Move client assignments from construtor in method - * [THRIFT-2309] - Ruby (gem) & PHP RPM subpackages - * [THRIFT-2318] - perl: dependency Class::Accessor not checked - * [THRIFT-2317] - exclude tutorial from build - * [THRIFT-2320] - Program level doctext does not get attached by parser - * [THRIFT-2349] - Golang - improve tutorial - * [THRIFT-2348] - PHP Generator: add array typehint to functions - * [THRIFT-2344] - configure.ac: compiler-only option - * [THRIFT-2343] - Golang - Return a single error for all exceptions instead of multiple return values - * [THRIFT-2341] - Enable generation of Delphi XMLDoc comments (a.k.a. "Help Insight") - * [THRIFT-2355] - Add SSL and Web Socket Support to Node and JavaScript - * [THRIFT-2350] - Add async calls to normal JavaScript - * [THRIFT-2330] - Generate PHPDoc comments - * [THRIFT-2332] - RPMBUILD: run bootstrap (if needed) - * [THRIFT-2391] - simple socket transport for actionscript 3.0 - * [THRIFT-2376] - nodejs: allow Promise style calls for client and server - * [THRIFT-2369] - Add ssl support for nodejs implementation - * [THRIFT-2401] - Haskell tutorial compiles - * [THRIFT-2417] - C# Union classes are not partial - * [THRIFT-2415] - Named pipes server performance & message mode - * [THRIFT-2404] - emit warning on (typically inefficient) list - * [THRIFT-2398] - Improve Node Server Library - * [THRIFT-2397] - Add CORS and CSP support for JavaScript and Node.js libraries - * [THRIFT-2407] - use markdown (rename README => README.md) - * [THRIFT-2300] - D configure info output should follow same format as other languages - * [THRIFT-2579] - Windows CE support - * [THRIFT-2574] - Compiler option to generate namespace directories for Ruby - * [THRIFT-2571] - Simplify cross compilation using CMake - * [THRIFT-2569] - Introduce file to specify third party library locations on Windows - * [THRIFT-2568] - Implement own certificate handler - * [THRIFT-2552] - eliminate warning from configure.ac - * [THRIFT-2549] - Generate json tag for struct members. use go.tag annotation to override the default generated tag. - * [THRIFT-2544] - Add support for socket transport for c# library when using Windows Phone projects - * [THRIFT-2453] - haskell tutorial: fix up division by 0 example - * [THRIFT-2449] - Enhance typedef structure to distinguish between forwards and real typedefs - * [THRIFT-2446] - There is no way to handle server stream errors - * [THRIFT-2455] - Allow client certificates to be used with THttpClient - * [THRIFT-2511] - Node.js needs the compact protocol - * [THRIFT-2493] - Node.js lib needs HTTP client - * [THRIFT-2502] - Optimize go implementations of binary and compact protocols for speed - * [THRIFT-2494] - Add enum toString helper function in c_glib - * [THRIFT-2471] - Make cpp.ref annotation language agnostic - * [THRIFT-2497] - server and client for test/go, also several fixes and improvements - * [THRIFT-2535] - TJSONProtocol when serialized yields TField ids rather than names - * [THRIFT-2220] - Add a new struct structv? - * [THRIFT-1352] - Thrift server - * [THRIFT-989] - Push boost m4 macros upstream - * [THRIFT-1349] - Remove unnecessary print outs - * [THRIFT-2496] - server and client for test/go, also several fixes and improvements - * [THRIFT-1114] - Maven publish shouldn't require passwords hardcoded in settings.xml - * [THRIFT-2043] - visual 2010 warnings - unreachable code - * [THRIFT-1683] - Implement alternatives to Javascript Client side Transport protocol, just as NPAPI and WebSocket. - * [THRIFT-1746] - provide a SPDX file - * [THRIFT-1772] - Serialization does not check types of embedded structures. - * [THRIFT-2387] - nodejs: external imports should be centralized in index.js - * [THRIFT-2037] - More general macro THRIFT_UNUSED_VARIABLE - -## New Feature - * [THRIFT-1012] - Transport for DataInput DataOutput interface - * [THRIFT-2256] - Using c++11/c++0x std library replace boost library - * [THRIFT-2250] - JSON and MemoryBuffer for JavaME - * [THRIFT-2114] - Python Service Remote SSL Option - * [THRIFT-1719] - SASL client support for Python - * [THRIFT-1894] - Thrift multi-threaded async Java Server using Java 7 AsynchronousChannelGroup - * [THRIFT-1893] - HTTP/JSON server/client for node js - * [THRIFT-2347] - C# TLS Transport based on THRIFT-181 - * [THRIFT-2377] - Allow addition of custom HTTP Headers to an HTTP Transport - * [THRIFT-2408] - Named Pipe Transport Option for C# - * [THRIFT-2572] - Add string/collection length limit checks (from C++) to java protocol readers - * [THRIFT-2469] - "java:fullcamel" option to automatically camel-case underscored attribute names - * [THRIFT-795] - Importing service functions (simulation multiple inheritance) - * [THRIFT-2164] - Add a Get/Post Http Server to Node along with examples - * [THRIFT-2255] - add Parent Class for generated Struct class - -## Question - * [THRIFT-2539] - Tsocket.cpp addrinfo ai_flags = AI_ADDRCONFIG - * [THRIFT-2440] - how to connect as3 to java by thrift , - * [THRIFT-2379] - Memmory leaking while using multithreading in C++ server. - * [THRIFT-2277] - Thrift: installing fb303 error - * [THRIFT-2567] - Csharp slow ? - * [THRIFT-2573] - thrift 0.9.2 release - -## Sub-task - * [THRIFT-981] - cocoa: add version Info to the library - * [THRIFT-2132] - Go: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-2299] - TJsonProtocol implementation for Ruby does not allow for both possible slash (solidus) encodings - * [THRIFT-2298] - TJsonProtocol implementation for C# does not allow for both possible slash (solidus) encodings - * [THRIFT-2297] - TJsonProtocol implementation for Delphi does not allow for both possible slash (solidus) encodings - * [THRIFT-2271] - JavaScript: Support for Multiplexing Services - * [THRIFT-2251] - go test for compact protocol is not running - * [THRIFT-2195] - Delphi: Add event handlers for server and processing events - * [THRIFT-2176] - TSimpleJSONProtocol.ReadFieldBegin() does not return field type and ID - * [THRIFT-2175] - Wrong field type set for binary - * [THRIFT-2174] - Deserializing JSON fails in specific cases - * [THRIFT-2053] - NodeJS: Support for Multiplexing Services - * [THRIFT-1914] - Python: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-1810] - add ruby to test/test.sh - * [THRIFT-2310] - PHP: Client-side support for Multiplexing Services - * [THRIFT-2346] - C#: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2345] - Delphi: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2338] - First doctext wrongly interpreted as program doctext in some cases - * [THRIFT-2325] - SSL test certificates - * [THRIFT-2358] - C++: add compact protocol to cross language test suite - * [THRIFT-2425] - PHP: Server-side support for Multiplexing Services - * [THRIFT-2421] - Tree/Recursive struct support in thrift - * [THRIFT-2290] - Update Go tutorial to align with THRIFT-2232 - * [THRIFT-2558] - CSharp compiler generator tries to concat ints with strings using + - * [THRIFT-2507] - Additional LUA TProtocolException error code needed? - * [THRIFT-2499] - Compiler: allow annotations without "= value" - * [THRIFT-2534] - Cross language test results should recorded to a status.md or status.html file automatically - * [THRIFT-66] - Java: Allow multiplexing multiple services over a single TCP connection - * [THRIFT-1681] - Add Lua Support - * [THRIFT-1727] - Ruby-1.9: data loss: "binary" fields are re-encoded - * [THRIFT-1726] - Ruby-1.9: "binary" fields are represented by string whose encoding is "UTF-8" - * [THRIFT-988] - perl: add version Info to the library via configure - * [THRIFT-334] - Compact Protocol for PHP - * [THRIFT-2444] - pull request 88: thrift: clean up enum value assignment - -## Task - * [THRIFT-2223] - Spam links on wiki - * [THRIFT-2566] - Please create a DOAP file for your TLP - * [THRIFT-2237] - Update archive to contain all versions - * [THRIFT-962] - Tutorial page on our website is really unhelpful - -## Test - * [THRIFT-2327] - nodejs: nodejs test suite should be bundled with the library - * [THRIFT-2445] - THRIFT-2384 (code generation for go maps with binary keys) should be tested - * [THRIFT-2501] - C# The test parameters from the TestServer and TestClient are different from the http://thrift.apache.org/test/ - -## Wish - * [THRIFT-2190] - Add the JavaScript thrift.js lib to the Bower registry - * [THRIFT-2076] - boost::optional instead of __isset - - - -Thrift 0.9.1 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1440] - debian packaging: minor-ish policy problems - * [THRIFT-1402] - Generated Y_types.js does not require() X_types.js when an include in the IDL file was used - * [THRIFT-1551] - 2 thrift file define only struct (no service), one include another, the gen nodejs file didn't have "requires" at the top - * [THRIFT-1264] - TSocketClient is queried by run loop after deallocation in Cocoa - * [THRIFT-1600] - Thrift Go Compiler and Library out of date with Go 1 Release. - * [THRIFT-1603] - Thrift IDL allows for multiple exceptions, args or struct member names to be the same - * [THRIFT-1062] - Problems with python tutorials - * [THRIFT-864] - default value fails if identifier is a struct - * [THRIFT-930] - Ruby and Haskell bindings don't properly support DESTDIR (makes packaging painful) - * [THRIFT-820] - The readLength attribute of TBinaryProtocol is used as an instance variable and is decremented on each call of checkReadLength - * [THRIFT-1640] - None of the tutorials linked on the website contain content - * [THRIFT-1637] - NPM registry does not include version 0.8 - * [THRIFT-1648] - NodeJS clients always receive 0 for 'double' values. - * [THRIFT-1660] - Python Thrift library can be installed with pip but not easy_install - * [THRIFT-1657] - Chrome browser sending OPTIONS method before POST in xmlHttpRequest - * [THRIFT-2118] - Certificate error handling still incorrect - * [THRIFT-2137] - Ruby test lib fails jenkins build #864 - * [THRIFT-2136] - Vagrant build not compiling java, ruby, php, go libs due to missing dependencies - * [THRIFT-2135] - GO lib leaves behind test files that are auto generated - * [THRIFT-2134] - mingw-cross-compile script failing with strip errors - * [THRIFT-2133] - java TestTBinaryProtocol.java test failing - * [THRIFT-2126] - lib/cpp/src/thrift/concurrency/STD* files missing from DIST - * [THRIFT-2125] - debian missing from DIST - * [THRIFT-2124] - .o, .so, .la, .deps, .libs, gen-* files left tutorials, test and lib/cpp when making DIST - * [THRIFT-2123] - GO lib missing files in DIST build - * [THRIFT-2121] - Compilation bug for Node.js - * [THRIFT-2129] - php ext missing from dist - * [THRIFT-2128] - lib GO tests fail with funct ends without a return statement - * [THRIFT-2286] - Failed to compile Thrift0.9.1 with boost1.55 by VS2010 if select Debug-mt&x64 mode. - * [THRIFT-1973] - TCompactProtocol in C# lib does not serialize and deserialize negative int32 and int64 number correctly - * [THRIFT-1992] - casts in TCompactProtocol.tcc causing "dereferencing type-punned pointer will break strict-aliasing rules" warnings from gcc - * [THRIFT-1930] - C# generates unsigned byte for Thrift "byte" type - * [THRIFT-1929] - Update website to use Mirrors for downloads - * [THRIFT-1928] - Race may still exist in TFileTransport::flush() - * [THRIFT-1934] - Tabs in Example section on main page are not working - * [THRIFT-1933] - Delphi generator crashes when a typedef references another typedef from an included file - * [THRIFT-1942] - Binary accelerated cpp extension does not use Thrift namespaces for Exceptions - * [THRIFT-1959] - C#: Add Union TMemoryBuffer support - * [THRIFT-1958] - C#: Use static Object.Equals instead of .Equals() calls in equals - * [THRIFT-1957] - NodeJS TFramedTransport and TBufferedTransport read bytes as unsigned - * [THRIFT-1955] - Union Type writer generated in C# does not WriteStructBegin - * [THRIFT-1952] - Travis CI - * [THRIFT-1949] - WP7 build broken - * [THRIFT-1943] - docstrings for enum values are ignored - * [THRIFT-2070] - Improper `HexChar' and 'HexVal' implementation in TJSONProtocol.cs - * [THRIFT-2017] - Resource Leak in thrift struct under compiler/cpp/src/parse/t_program.h - * [THRIFT-2032] - C# client leaks sockets/handles - * [THRIFT-1996] - JavaME Constants generation is broken / inconsistent with regular Java generation - * [THRIFT-2002] - Haskell: Test use Data.Maybe instead of Maybe - * [THRIFT-2051] - Vagrant fails to build erlang - * [THRIFT-2050] - Vagrant C# lib compile fails with TException missing - * [THRIFT-1978] - Ruby: Thrift should allow for the SSL verify mode to be set - * [THRIFT-1984] - namespace collision in python bindings - * [THRIFT-1988] - When trying to build a debian package it fails as the file NEWS doesn't exist - * [THRIFT-1975] - TBinaryProtocol CheckLength can't be used for a client - * [THRIFT-1995] - '.' allowed at end of identifier generates non-compilable code - * [THRIFT-2112] - Error in Go generator when using typedefs in map keys - * [THRIFT-2088] - Typos in Thrift compiler help text - * [THRIFT-2080] - C# multiplex processor does not catch IOException - * [THRIFT-2082] - Executing "gmake clean" is broken - * [THRIFT-2102] - constants are not referencing to correct type when included from another thrift file - * [THRIFT-2100] - typedefs are not correctly referenced when including from other thrift files - * [THRIFT-2066] - 'make install' does not install two headers required for C++ bindings - * [THRIFT-2065] - Not valid constants filename in Java - * [THRIFT-2047] - Thrift.Protocol.TCompactProtocol, intToZigZag data lost (TCompactProtocol.cs) - * [THRIFT-2036] - Thrift gem warns about class variable access from top level - * [THRIFT-2057] - Vagrant fails on php tests - * [THRIFT-2105] - Generated code for default values of collections ignores t_field::T_REQUIRED - * [THRIFT-2091] - Unnecessary 'friend' declaration causes warning in TWinsockSingleton - * [THRIFT-2090] - Go generator, fix including of other thrift files - * [THRIFT-2106] - Fix support for namespaces in GO generator - * [THRIFT-1783] - C# doesn't handle required fields correctly - * [THRIFT-1782] - async only defined in silverlight - * [THRIFT-1779] - Missing process_XXXX method in generated TProcessor implementation for all 'oneway' service functions - * [THRIFT-1692] - SO_REUSEADDR allows for socket hijacking on Windows - * [THRIFT-1720] - JRuby times out on successful connection - * [THRIFT-1713] - Named and Anonymous Pipe transport (Delphi) - * [THRIFT-1699] - Native Union#read has extra read_field_end call - * [THRIFT-1749] - Python TSSLSocket error handling obscures actual error - * [THRIFT-1748] - Guard and RWGuard macros defined in global namespace - * [THRIFT-1734] - Front webpage is still advertising v0.8 as current release - * [THRIFT-1729] - C glib refactor left empty folders in svn - * [THRIFT-1767] - unions can't have required fields (Delphi) - * [THRIFT-1765] - Incorrect error message printed for null or negative keys - * [THRIFT-1778] - Configure requires manual intervention due to tar failure - * [THRIFT-1777] - TPipeServer is UNSTOPPABLE - * [THRIFT-1753] - Multiple C++ Windows, OSX, and iOS portability issues - * [THRIFT-1756] - 'make -j 8' fails with "unterminated #ifdef" error - * [THRIFT-1773] - Python library should run on python 2.4 - * [THRIFT-1769] - unions can't have required fields (C++) - * [THRIFT-1768] - unions can't have required fields (Compiler) - * [THRIFT-1666] - htonll usage in TBinaryProtocol.tcc generates warning with MSVC2010 - * [THRIFT-1919] - libthrift depends on httpcore-4.1.3 (directly) and httpcore-4.1.4 (transitively) - * [THRIFT-1864] - implement event handler for non-blocking server - * [THRIFT-1859] - Generated error c++ code with -out and include_prefix param - * [THRIFT-1869] - TThreadPoolServer (java) dies when threadpool is consumed - * [THRIFT-1842] - Memory leak with Pipes - * [THRIFT-1838] - Can't build compiler on OS X because of missing thrifty.h - * [THRIFT-1846] - Restore socket.h header to support builds with Android NDK - * [THRIFT-1850] - make check hangs on TSocket tests in TransportTest.cpp - * [THRIFT-1873] - Binary protocol factory ignores struct read/write flags - * [THRIFT-1872] - issues with TBufferedTransport buffer - * [THRIFT-1904] - Incorrect code is generated for typedefs which use included types - * [THRIFT-1903] - PHP namespaces cause binary protocols to not be used - * [THRIFT-1895] - Delphi: reserved variable name "result" not detected properly - * [THRIFT-1881] - TNonblockingServer does not release open connections or threads on shutdown - * [THRIFT-1888] - Java Thrift client can't connect to Python Thrift server on same host - * [THRIFT-1831] - Bug in list deserializer - * [THRIFT-1824] - many compile warning, becase Thread.h includes config.h - * [THRIFT-1823] - Missing parenthesis breaks "IS_..." macro in generated code - * [THRIFT-1806] - Python generation always truncates __init__.py files - * [THRIFT-1795] - Race condition in TThreadedServerPool java implementation - * [THRIFT-1794] - C# asyncctp broken - * [THRIFT-1804] - Binary+compact protocol single byte error in Ruby library (ARM architecture): caused by different char signedness - * [THRIFT-1800] - Documentation text not always escaped correctly when rendered to HTML - * [THRIFT-1788] - C#: Constants static constructor does not compile - * [THRIFT-1816] - Need "require" included thrift files in "xxx_types.js" - * [THRIFT-1907] - Compiling namespace and sub-namespace directives for unrecognized generators should only be a warning - * [THRIFT-1913] - skipping unknown fields in java unions - * [THRIFT-2553] - C++ linker error - transport/TSocket - * [THRIFT-274] - Towards a working release/versioning process - -## Documentation - * [THRIFT-1971] - [Graphviz] Adds tutorial/general description documentation - * [THRIFT-2001] - http://thrift.apache.org/ Example "C++ Server" tab is broken - -## Improvement - * [THRIFT-1574] - Apache project branding requirements: DOAP file [PATCH] - * [THRIFT-1347] - Unify the exceptions returned in generated Go code - * [THRIFT-1353] - Switch to performance branch, get rid of BinaryParser - * [THRIFT-1629] - Ruby 1.9 Compatibility during Thrift configure, make, install - * [THRIFT-991] - Refactor Haskell code and generator - * [THRIFT-990] - Sanify gettimeofday usage codebase-wide - * [THRIFT-791] - Let C++ TSimpleServer be driven by an external main loop - * [THRIFT-2117] - Cocoa TBinaryProtocol strictWrite should be set to true by default - * [THRIFT-2014] - Change C++ lib includes to use style throughout - * [THRIFT-1972] - Add support for async processors - * [THRIFT-1970] - [Graphviz] Adds option to render exceptions relationships - * [THRIFT-1966] - Support different files for SSL certificates and keys - * [THRIFT-1965] - Adds Graphviz (graph description language) generator - * [THRIFT-1956] - Switch to Apache Commons Lang 3 - * [THRIFT-1962] - Multiplex processor should send any TApplicationException back to client - * [THRIFT-1960] - main() declares 22 unused gen bools - * [THRIFT-1951] - libthrift.jar has source files in it - * [THRIFT-1997] - Add accept backlog configuration method to TServerSocket - * [THRIFT-2003] - Deprecate senum - * [THRIFT-2052] - Vagrant machine image defaults to only 384MB of RAM - * [THRIFT-1980] - Modernize Go tooling, fix go client libary. - * [THRIFT-1977] - C# compiler should generate constant files prefixed with thrift file name - * [THRIFT-1985] - add a Vagrantfile to build and test Apache Thrift fully reproducable - * [THRIFT-1994] - Deprecate slist - * [THRIFT-1993] - Factory to create instances from known (generated) interface types with Delphi - * [THRIFT-2081] - Specified timeout should be used in TSocket.Open() - * [THRIFT-2084] - Delphi: Ability to create entity Thrift-generated instances based on TypeInfo - * [THRIFT-2083] - Improve the go lib: buffered Transport, save memory allocation, handle concurrent request - * [THRIFT-2109] - Secure connections should be supported in Go - * [THRIFT-2107] - minor Go generator fixes - * [THRIFT-1695] - allow warning-free compilation in VS 2012 and GNU 4.6 - * [THRIFT-1735] - integrate tutorial into regular build - * [THRIFT-1716] - max allowed connections should be PIPE_UNLIMITED_INSTANCES - * [THRIFT-1715] - Allow excluding python parts when building contrib/fb303 - * [THRIFT-1733] - Fix RPM build issues on RHEL6/OL6 systems - * [THRIFT-1728] - Upgradation of httpcomponents - * [THRIFT-1876] - Use enum names instead of casted integers in assignments - * [THRIFT-1874] - timeout for the server-side end of a named pipe - * [THRIFT-1897] - Support validation of required fields - * [THRIFT-1896] - Add TBase protocol for Cocoa - * [THRIFT-1880] - Make named pipes server work asynchronously (overlapped) to allow for clean server stops - * [THRIFT-1878] - Add the possibility to send custom headers - * [THRIFT-1882] - Use single include - * [THRIFT-1793] - C#: Use static read instead of instance read - * [THRIFT-1799] - Option to generate HTML in "standalone mode" - * [THRIFT-1815] - Code generators line buffer output - * [THRIFT-1890] - C++: Make named pipes server work asynchronously - * [THRIFT-474] - Generating Ruby on Rails friendly code - -## New Feature - * [THRIFT-801] - Provide an interactive shell (irb) when generating ruby bindings - * [THRIFT-2292] - Android Library Project - * [THRIFT-2012] - Modernizing Go - * [THRIFT-1969] - C#: Tests not properly linked from the solution - * [THRIFT-1785] - C#: Add TMemoryBuffer serializer/deserializer - * [THRIFT-1780] - Add option to generate nullable values - * [THRIFT-1786] - C# Union Typing - * [THRIFT-591] - Make the C++ runtime library be compatible with Windows and Visual Studio - * [THRIFT-514] - Add option to configure compiler output directory - -## Question - * [THRIFT-1764] - how to get the context of client when on a rpc call in server side? - * [THRIFT-1791] - thrift's namespace directive when generating haskell code - -## Sub-task - * [THRIFT-1594] - Java test clients should have a return codes that reflect whether it succeeds or not. - * [THRIFT-1595] - Java test server should follow the documented behavior as of THRIFT-1590 - * [THRIFT-986] - st: add version Info to the library - * [THRIFT-985] - php: add version Info to the library - * [THRIFT-984] - ocaml: add version Info to the library - * [THRIFT-1924] - Delphi: Inconsistency in serialization of optional fields - * [THRIFT-1922] - C#: Inconsistency in serialization of optional fields - * [THRIFT-1961] - C# tests should be in lib/csharp/test/... - * [THRIFT-1822] - PHP unit test does not work - * [THRIFT-1902] - C++: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-1901] - C#: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-1899] - Delphi: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-563] - Support for Multiplexing Services on any Transport, Protocol and Server - - - -Thrift 0.9 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1438] - lib/cpp/src/windows/config.h should read version from configure.ac rather than a #define - * [THRIFT-1446] - Compile error with Delphi 2009 in constant initializer - * [THRIFT-1450] - Problems building thrift 0.8.0 for Python and Ruby - * [THRIFT-1449] - Ruby client does not work on solaris (?) - * [THRIFT-1447] - NullpointerException in ProcessFunction.class :in "oneway" method - * [THRIFT-1433] - TServerSocket fix for MSVC - * [THRIFT-1429] - The nonblocking servers is supposed to use TransportFactory to read the data - * [THRIFT-1427] - PHP library uses non-multibyte safe functions with mbstring function overloading - * [THRIFT-1421] - Debian Packages can not be built - * [THRIFT-1394] - Treatment of optional fields is not consistent between C++ and Java - * [THRIFT-1511] - Server with oneway support ( JAVA ) - * [THRIFT-1496] - PHP compiler not namespacing enums - * [THRIFT-1495] - PHP TestClient fatals on missing class - * [THRIFT-1508] - TServerSocket does not allow for the user to specify the IP address to bind to - * [THRIFT-1504] - Cocoa Generator should use local file imports for base Thrift headers - * [THRIFT-1512] - Thrift socket support for Windows XP - * [THRIFT-1502] - TSimpleServer::serve(): Do not print out error message if server was stopped. - * [THRIFT-1501] - PHP old namespaces not generated for enums - * [THRIFT-1483] - java compiler does not generate type parameters for services in extended clauses - * [THRIFT-1479] - Compiled PHP process functions missing writeMessageEnd() - * [THRIFT-1492] - enabling c_glib render thrift unusable (even for C++ code) - * [THRIFT-1491] - Uninitialize processorFactory_ member in TServer.h - * [THRIFT-1475] - Incomplete records generation for Erlang - * [THRIFT-1486] - Javascript manual testserver not returning content types - * [THRIFT-1488] - src/concurrency/Thread.h:91:58: error: invalid conversion from 'pthread_t {aka _opaque_pthread_t*}' to 'apache::thrift::concurrency::Thread::id_t {aka long long unsigned int}' [-fpermissive] - * [THRIFT-1490] - Windows-specific header files - fixes & tweaks - * [THRIFT-1526] - Union TupleSchemeFactory returns StandardSchemes - * [THRIFT-1527] - Generated implementation of tupleReadStruct in unions return null when the setfield is unrecognized - * [THRIFT-1524] - TNonBlockingServer does not compile in Visual Studio 2010 - * [THRIFT-1529] - TupleProtocol can unintentionally include an extra byte in bit vectors when number of optional fields is an integral of 8 - * [THRIFT-1473] - JSON context stack may be left in an incorrect state when an exception is thrown during read or write operations - * [THRIFT-1456] - System.Net.HttpWebRequest' does not contain a definition for 'Proxy' - * [THRIFT-1468] - Memory leak in TSaslServerTransport - * [THRIFT-1461] - Recent TNonblockingServer changes broke --enable-boostthreads=yes, Windows - * [THRIFT-1460] - why not add unicode strings support to python directly? - * [THRIFT-1464] - AbstractNonblockingServer.FrameBuffer TNonblockingTransport accessor changed from public to private - * [THRIFT-1467] - Possible AV with empty strings when using JSON protocol - * [THRIFT-1523] - clientTimeout not worked as expected in TServerSocket created by TSSLTransportFactory - * [THRIFT-1537] - TFramedTransport issues - * [THRIFT-1519] - Thirft Build Failure referencing rb_intern2 symbol - * [THRIFT-1518] - Generated C++ code only sends the first optional field in the write() function for a struct. - * [THRIFT-1515] - NameError: global name 'TApplicationException' is not defined - * [THRIFT-1554] - Inherited service methods are not resolved in derived service implementations - * [THRIFT-1553] - thrift nodejs service side can't read map structure, key as enum, value as Object - * [THRIFT-1575] - Typo in server/TThreadPoolServer.h - * [THRIFT-1327] - Fix Spec Suite under Ruby-1.8.7 (works for MRI Ruby-1.9.2) - * [THRIFT-1326] - on some platforms, #include is necessary to be included in Thrift.h - * [THRIFT-1159] - THttpClient->Flush() issue (connection thru proxy) - * [THRIFT-1277] - Node.js serializes false booleans as null - * [THRIFT-1224] - Cannot insert UTF-8 text - * [THRIFT-1267] - Node.js can't throw exceptions. - * [THRIFT-1338] - Do not use an unpatched autoconf 2.65 to generate release tarball - * [THRIFT-1128] - MAC OS X: thrift.h incompatibility with Thrift.h - * [THRIFT-1631] - Fix C++ server constructor typos - * [THRIFT-1602] - PHP C Extension is not Compatible with PHP 5.4 - * [THRIFT-1610] - IWebProxy not available on WP7 platform - * [THRIFT-1606] - Race condition in BoostThreadFactory.cpp - * [THRIFT-1604] - Python exception handeling for changes from PEP 3110 - * [THRIFT-1607] - Incorrect file modes for several source files - * [THRIFT-1583] - c_glib leaks memory - * [THRIFT-1582] - Bad includes of nested thrift files in c_glib - * [THRIFT-1578] - C_GLib generated code does not compile - * [THRIFT-1597] - TJSONProtocol.php is missing from Makefile.am - * [THRIFT-1591] - Enable TCP_NODELAY for ruby gem - * [THRIFT-1624] - Isset Generated differently on different platforms - * [THRIFT-1622] - Incorrect size returned on read - * [THRIFT-1621] - Memory leaks - * [THRIFT-1612] - Base64 encoding is broken - * [THRIFT-1627] - compiler built using compilers.vcxproj cannot be used to build some test .thrift files - * [THRIFT-1571] - Update Ruby HTTP transport for recent Ruby versions - * [THRIFT-1023] - Thrift encoding (UTF-8) issue with Ruby 1.9.2 - * [THRIFT-1090] - Document the generation of a file called "Constants.java" - * [THRIFT-1082] - Thrift::FramedTransport sometimes calls close() on an undefined value - * [THRIFT-956] - Python module's version meta-data should be updated - * [THRIFT-973] - Cocoa library won't compile using clang - * [THRIFT-1632] - ruby: data corruption in thrift_native implementation of MemoryBufferTransport - * [THRIFT-1665] - TBinaryProtocol: exceeded message length raises generic TException - * [THRIFT-1664] - Reference to non-existing variable in build script - * [THRIFT-1663] - Java Thrift server is not throwing exceptions - * [THRIFT-1662] - "removeObject:" should be "removeObserver:" in [-TSocketServer dealloc]? - * [THRIFT-1643] - Denial of Service attack in TBinaryProtocol.readString - * [THRIFT-1674] - Update Thrift D library to be compatible with 2.060 - * [THRIFT-1673] - Ruby compile flags for extension for multi arch builds (os x) - * [THRIFT-1655] - Configure still trying to use thrift_generators in output - * [THRIFT-1654] - c_glib thrift_socket_read() returns corrupted data - * [THRIFT-1653] - TThreadedSelectorServer leaks CLOSE_WAIT sockets - * [THRIFT-1658] - Java thrift server is not throwing TApplicationException - * [THRIFT-1656] - Setting proper headers in THttpServer.cpp so that "Cross-Origin Resource Sharing" on js client can work. - * [THRIFT-1652] - TSaslTransport does not log the error when kerberos auth fails - * [THRIFT-2272] - CLONE - Denial of Service attack in TBinaryProtocol.readString - * [THRIFT-2086] - Invalid generated code for Node.JS when using namespaces - * [THRIFT-1686] - t_php_generator.cc uses "and" instead of "&&", and causes compiler errors with Visual Studio - * [THRIFT-1693] - libthrift has dependency on two different versions of httpcore - * [THRIFT-1689] - don't exit(-1) in TNonblockingServer - * [THRIFT-1679] - NodeJS: protocol readString() should treat string as utf8, not binary - * [THRIFT-1721] - Dist broken due to 0.8.0 to 0.9.0 changes - * [THRIFT-1710] - Minor issues in test case code - * [THRIFT-1709] - Warning "Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first" in TBinaryProtocol.cs at ReadInt64() - * [THRIFT-1707] - [ruby] Adjust server_spec.rb for RSpec 2.11.x and Ruby 1.9.3 - * [THRIFT-1671] - Cocoa code generator does not put keywords into generated method calls - * [THRIFT-1670] - Incompatibilities between different versions of a Thrift interface - * [THRIFT-1669] - NameError: global name 'TApplicationException' is not defined - * [THRIFT-1668] - Compile error in contrib/fb303, thrift/TDispatchProcessor.h: No such file or directory - * [THRIFT-1845] - Fix compiler warning caused by implicit string conversion with Xcode 4.6 - * [THRIFT-304] - Building the Python library requires development headers - * [THRIFT-369] - sets and maps break equality - * [THRIFT-556] - Ruby compiler does not correctly referred to top-level modules when a submodule masks the top-level name - * [THRIFT-481] - indentation of ruby classes is off by a few - -## Improvement - * [THRIFT-1498] - Allow TThreadedPoolServer.Args to pass a ExecutorService - * [THRIFT-1444] - FunctionRunner - add syntactic sugar to create shared_ptrs - * [THRIFT-1443] - define a TProcessor helper class to implement process() - * [THRIFT-1441] - Generate constructor with parameters for exception class to let it update message property automatically. - * [THRIFT-1520] - Embed version number in erlang .app file - * [THRIFT-1480] - python: remove tabs, adjust whitespace and address PEP8 warnings - * [THRIFT-1485] - Performance: pass large and/or refcounted arguments as "const" - * [THRIFT-1484] - Introduce phpunit test suite - * [THRIFT-1532] - The type specifications in the generated Erlang code should include "undefined" where it's used as a default value - * [THRIFT-1534] - Required fields in the Delphi code generator. - * [THRIFT-1469] - Java isset space optimization - * [THRIFT-1465] - Visibility of methods in generated java code - * [THRIFT-1453] - Don't change types of arguments when serializing with thrift php extension - * [THRIFT-1452] - generate a swap() method for all generated structs - * [THRIFT-1451] - FramedTransport: Prevent infinite loop when writing - * [THRIFT-1521] - Two patches for more Performance - * [THRIFT-1555] - Delphi version of the tutorial code - * [THRIFT-1535] - Why thrift don't use wrapped class for optional fields ? - * [THRIFT-1204] - Ruby autogenerated files should require 'thrift' gem - * [THRIFT-1344] - Using the httpc module directly rather than the deprecated http layer - * [THRIFT-1343] - no_auto_import min/2 to avoid compile warning - * [THRIFT-1340] - Add support of ARC to Objective-C - * [THRIFT-1611] - Improved code generation for typedefs - * [THRIFT-1593] - Pass on errors like "connection closed" to the handler module - * [THRIFT-1615] - PHP Namespace - * [THRIFT-1567] - Thrift/cpp: Allow alternate classes to be used for - * [THRIFT-1072] - Missing - (id) initWithSharedProcessor in TSharedProcessorFactory.h - * [THRIFT-1650] - [ruby] Update clean items and svn:ignore entries for OS X artifacts - * [THRIFT-1661] - [PATCH] Add --with-qt4 configure option - * [THRIFT-1675] - Do we have any plan to support scala? - * [THRIFT-1645] - Replace Object#tee with more conventional Object#tap in specs - * [THRIFT-1644] - Upgrade RSpec to 2.10.x and refactor specs as needed - * [THRIFT-1672] - MonoTouch (and Mono for Android) compatibility - * [THRIFT-1702] - a thrift manual - * [THRIFT-1694] - Re-Enable serialization for WP7 Silverlight - * [THRIFT-1691] - Serializer/deserializer support for Delphi - * [THRIFT-1688] - Update IDL page markup - * [THRIFT-1725] - Tutorial web pages for Delphi and C# - * [THRIFT-1714] - [ruby] Explicitly add CWD to Ruby test_suites.rb - * [THRIFT-317] - Issues with Java struct validation - * [THRIFT-164] - Build web tutorial on Incubator web site - * [THRIFT-541] - Cocoa code generator doesn't put keywords before all arguments. - * [THRIFT-681] - The HTML generator does not handle JavaDoc style comments very well - -## New Feature - * [THRIFT-1500] - D programming language support - * [THRIFT-1510] - There should be an implementation of the JsonProtocol for ruby - * [THRIFT-1115] - python TBase class for dynamic (de)serialization, and __slots__ option for memory savings - * [THRIFT-1953] - support for asp.net mvc 3 - -## Question - * [THRIFT-1235] - How could I use THttpServerTransportFactory withTNonBlockingServer - * [THRIFT-1368] - TNonblockingServer usage - * [THRIFT-1061] - Read an invalid frame size of 0. Are you using TFramedTransport on the client side? - * [THRIFT-491] - Ripping raw pthreads out of TFileTransport and associated test issues - -## Sub-task - * [THRIFT-1596] - Delphi: Test clients should have a return codes that reflect whether they succeeded or not - * [THRIFT-982] - javame: add version Info to the library - * [THRIFT-1722] - C# WP7 Assembly addition beaks mono build - * [THRIFT-336] - Compact Protocol in C# - -## Test - * [THRIFT-1613] - Add code back into empty source file ToStringTest.java - * [THRIFT-1718] - Incorrect check in TFileTransportTest - -## Wish - * [THRIFT-1463] - Decouple Thrift IDL from generators - * [THRIFT-1466] - Proper Documentation for Thrift C Glib - * [THRIFT-1539] - Build and distribute the fb303 python libraries along with thrift - * [THRIFT-1685] - Please add "aereo.com" to "Powered by Apache Thrift" list in about page - * [THRIFT-330] - TProcessor - additional method to called when connection is broken - - - -Thrift 0.8 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1436] - pip install thrift fails on Windows with "Unable to find vcvarsall.bat" - * [THRIFT-1432] - Javascript struct constants declared in the same file as their struct definition will cause an error - * [THRIFT-1428] - shared.thrft does not include namespace for php, so thrift compiler generate incorrect name - * [THRIFT-1426] - Dist package missing files for release 0.8 - * [THRIFT-1425] - The Node package is incompatible with latest node (0.6) & npm (1.0.27) - * [THRIFT-1416] - Python Unit test is broken on ci - * [THRIFT-1419] - AbstractNonBlockingServer does not catch errors when invoking the processor - * [THRIFT-1424] - Ruby specs fail when run with rake - * [THRIFT-1420] - Nonblocking and HsHa server should make sure to close all their socket connections when the selector exits - * [THRIFT-1413] - Generated code does not read MapEnd / ListEnd / SetEnd - * [THRIFT-1409] - Name conflict check does not work properly for exception object(Delphi). - * [THRIFT-1408] - Delphi Test Server: Exception test case fails due to naming conflict with e.message - * [THRIFT-1407] - Typo in Python socket server causes Thrift to fail when we enable a global socket timout - * [THRIFT-1397] - CI server fails during build due to unused parameters in delphi generator - * [THRIFT-1404] - Delphi compiler generates struct reader code with problem. - * [THRIFT-1400] - Ruby native extension aborts with __stack_chk_fail in OSX - * [THRIFT-1399] - One of the TServerImpl.Create CTORs lacks implementation - * [THRIFT-1390] - Debian packages build fix for Squeeze (build from the official 0.7.0 tarball) - * [THRIFT-1393] - TTransportException's thrown from THttpClient contain superfluous slashes in the Exception message - * [THRIFT-1392] - Enabling both namespaces and autoloading in generated PHP code won't work. - * [THRIFT-1406] - Build error after applying THRIFT-1395 - * [THRIFT-1405] - Delphi compiler does not generates container serializer properly. - * [THRIFT-1411] - java generator does not provide type parameter for TBaseProcessor - * [THRIFT-1473] - JSON context stack may be left in an incorrect state when an exception is thrown during read or write operations - * [THRIFT-1331] - Ruby library deserializes an empty map to nil - * [THRIFT-1330] - PHP Namespaces no longer generated - * [THRIFT-1328] - TBaseHelper.toString(...) appends ByteBuffer data outside of valid buffer range - * [THRIFT-1322] - OCaml lib fail to compile: Thrift.ml line 305, int vs int32 mismatch - * [THRIFT-1143] - Build doesn't detect correct architecture type on 64bit osx - * [THRIFT-1205] - port server unduly fragile with arbitrary input - * [THRIFT-1279] - type set is handled incorrectly when writing object - * [THRIFT-1298] - Standard scheme doesn't read or write metadata along with field values - * [THRIFT-1265] - C++ container deserialize - * [THRIFT-1263] - publish ruby client to rubygems - * [THRIFT-1384] - Java help menu missing newline near javame flag - * [THRIFT-1382] - Bundle install doesnot work because thrift crashes - * [THRIFT-1381] - Thrift C++ libs have incorrectly versioned names - * [THRIFT-1350] - Go library code does not build as of r60 (most recent release) - * [THRIFT-1365] - TupleProtocol#writeBitSet unintentionally writes a variable length byte array - * [THRIFT-1359] - --gen-cob cpp:cob_style does not compile anymore - * [THRIFT-1319] - Mismatch between how a union reads and writes a container - * [THRIFT-1309] - libfb303-0.7.0.jar missing in maven repository - * [THRIFT-1238] - Thrift JS client cannot read map of structures - * [THRIFT-1254] - Code can't be compiled against a regular JRE: Object.clone() override has a different return type - * [THRIFT-1367] - Mac OSX build fails with "no such file to load -- spec/rake/spectask" - * [THRIFT-1355] - Running make in lib/rb doesn't build the native extensions - * [THRIFT-1370] - Debian packaging should Build-Depend on libglib2.0-dev - * [THRIFT-1342] - Compilation problem on Windows of fastbinary.c - * [THRIFT-1341] - TProtocol.h endian detection wrong with boost - * [THRIFT-1583] - c_glib leaks memory - * [THRIFT-1582] - Bad includes of nested thrift files in c_glib - * [THRIFT-1578] - C_GLib generated code does not compile - * [THRIFT-1027] - 'make -j 16' fails with "unterminated #ifdef" error - * [THRIFT-1121] - Java server performance regression in 0.6 - * [THRIFT-857] - tests run by "make install" fail if generators are disabled - * [THRIFT-380] - Use setuptools for python build - -## Dependency upgrade - * [THRIFT-1257] - thrift's dependency scope on javax.servlet:servlet-api should be 'provided' - -## Improvement - * [THRIFT-1445] - minor C++ generator variable cleanup - * [THRIFT-1435] - make TException.Message property conformant to the usual expectations - * [THRIFT-1431] - Rename 'sys' module to 'util' - * [THRIFT-1396] - Dephi generator has dependacy on boost 1.42 later. - * [THRIFT-1395] - Patch to prevent warnings for integer types in some cases - * [THRIFT-1275] - thrift: always prefix namespaces with " ::" - * [THRIFT-1274] - thrift: fail compilation if an unexpected token is - * [THRIFT-1271] - thrift: fix missing namespace in generated local - * [THRIFT-1270] - thrift: add --allow-neg-keys argument to allow - * [THRIFT-1345] - Allow building without tests - * [THRIFT-1286] - Modernize the Thrift Ruby Library Dev Environment - * [THRIFT-1284] - thrift: fix processor inheritance - * [THRIFT-1283] - thrift: wrap t_cpp_generator::generate_process_function() to 80 - * [THRIFT-1282] - Upgrade httpclient to 4.1.2 (from 4.0.1) - * [THRIFT-1281] - add @generated to the docblock - * [THRIFT-1280] - Thrift: Improve Monitor exception-free interfaces - * [THRIFT-1278] - javadoc warnings - compilation - * [THRIFT-1227] - Erlang implementation of thrift JSON protocol - * [THRIFT-1295] - Duplicate include in TSocket.cpp - * [THRIFT-1294] - thrift: fix log message typos in TSimpleServer - * [THRIFT-1293] - thrift: improve handling of exceptions thrown by - * [THRIFT-1292] - thrift: silence log spew from TThreadedServer - * [THRIFT-1288] - Allow typedefed exceptions in throws clauses - * [THRIFT-1290] - thrift: TNonblockingServer: clean up state in the - * [THRIFT-1287] - thrift: start refactoring some of the C++ processor - * [THRIFT-1289] - thrift: implement TNonblockingServer::stop() - * [THRIFT-1305] - thrift: make TConnection a private inner class of - * [THRIFT-1304] - TNonblockingServer: pass in the connection context to - * [THRIFT-1302] - thrift: raise an exception if send() times out in - * [THRIFT-1301] - thrift: consolidate common code in TNonblockingServer - * [THRIFT-1377] - abort PHP deserialization on unknown field type - * [THRIFT-1379] - fix uninitialized enum values in thrift C++ objects - * [THRIFT-1376] - Make port specification option in thrift remote - * [THRIFT-1375] - fixed a hex char conversion bug in TJSONProtocol - * [THRIFT-1373] - Fix user-defined exception generation in thrift (python) - * [THRIFT-1361] - Optional replacement of pthread by boost::thread - * [THRIFT-1320] - Consistency of configure generated config.h - * [THRIFT-1317] - Remove copy constructibility from - * [THRIFT-1316] - thrift: update server classes to accept - * [THRIFT-1315] - thrift: generate server interface factory classes - * [THRIFT-1314] - thrift: add TProcessorFactory - * [THRIFT-1335] - Add accept timeout to TServerSocket - * [THRIFT-1334] - Add more info to IllegalStateException - * [THRIFT-1333] - Make RWGuard not copyable - * [THRIFT-1332] - TSSLTransportParameters class uses hard coded value keyManagerType: SunX509 - * [THRIFT-1251] - Generated java code should indicate which fields are required and which are optional - * [THRIFT-1387] - Build MSVC libraries with Boost Threads instead of Pthreads - * [THRIFT-1339] - Extend Tuple Protocol to TUnions - * [THRIFT-1031] - Patch to compile Thrift for vc++ 9.0 and 10.0 - * [THRIFT-1130] - Add the ability to specify symbolic default value for optional boolean - * [THRIFT-1123] - Patch to compile Thrift server and client for vc++ 9.0 and 10.0 - * [THRIFT-386] - Make it possible to build the Python library without the extension - -## New Feature - * [THRIFT-1401] - JSON-protocol for Delphi XE Libraries - * [THRIFT-1167] - Java nonblocking server with more than one thread for select and handling IO - * [THRIFT-1366] - Delphi generator, lirbrary and unit test. - * [THRIFT-1354] - Add rake task to build just the gem file - * [THRIFT-769] - Pluggable Serializers - -## Sub-task - * [THRIFT-1415] - delphi: add version Info to the library - * [THRIFT-1391] - Improved Delphi XE test cases - - - -Thrift 0.7 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1140] - Framed Transport Client using C (Glib) Library hangs when connecting to Ruby Server - * [THRIFT-1154] - HttpClient does not specify the connection close parameter - * [THRIFT-1153] - HttpClient does not specify the connection close parameter - * [THRIFT-1149] - Nonblocking server fails when client connection is reset - * [THRIFT-1146] - Android Incompatibility : in Android < 2.3 java.io.IOException doesn't support for Throwable parameter in constructor - * [THRIFT-1133] - Java and JavaScript tutorial is broken since we have Java maven deployment - * [THRIFT-1132] - Deserialization error in TApplicationException C# - * [THRIFT-1131] - C# JSON Protocol is unable to decode escaped characters in string - * [THRIFT-1208] - python TCompactProtocol.py writeBool and readBool not follow the compact-proto-spec-2.txt spec for CONTAINER_WRITE, CONTAINER_READ - * [THRIFT-1200] - JS compiler generates code that clobbers existing namespaces - * [THRIFT-1183] - Pure-ruby CompactProtocol raises ArgumentError when deserializing under Ruby 1.9 - * [THRIFT-1182] - Native deserializer segfaults on incorrect list element type - * [THRIFT-1181] - AS3 compiler generates incorrect code for setting default values in constructor - * [THRIFT-1234] - thrift --help is missing doc on py:utf8strings - * [THRIFT-1180] - AS3 compiler generates uncompilable code for binary types. - * [THRIFT-1194] - Java lib does not install artifacts to local dir correctly - * [THRIFT-1193] - Potential infinite loop in nonblocking_server - * [THRIFT-1192] - Typo: TProtocol.h tests for HAVE_SYS_PARAM_H_ - * [THRIFT-1190] - readBufferBytesAllocated in TNonblockingServer.java should be AtomicLong to fix FD leakage and general server malfunction - * [THRIFT-1187] - nonblocking_server shutdown race under Ruby 1.9 - * [THRIFT-1178] - Java: TBase signature should be T extends TBase - * [THRIFT-1164] - Segmentation fault on NULL pointer in t_js_generator::generate_const - * [THRIFT-1171] - Perl write/readDouble assumes little-endian platform - * [THRIFT-1222] - Unhandled exception for TEvhttpServer request - * [THRIFT-1220] - TProcessor::process never returns false - * [THRIFT-1285] - Stable 0.7.0 Windows compiler exe available on the webside is not the good one - * [THRIFT-1218] - c_glib uses wrong name in pkg-config - * [THRIFT-1215] - Undefined property Thirft in lib/js/thrift.js - * [THRIFT-1211] - When using THttpClient, non 200 responses leave the connection open - * [THRIFT-1228] - The php accelerator module calls flush incorrectly - * [THRIFT-1308] - libfb303-0.7.0.jar missing in maven repository - * [THRIFT-1255] - Mismatch of method name between JavaME's lib and generated code (compareTo/compareObjects) - * [THRIFT-1253] - Code generated for maps is not compiling - * [THRIFT-1252] - Segfault in Ruby deserializer - * [THRIFT-1094] - bug in TCompactProto python readMessageEnd method and updated test cases - * [THRIFT-1093] - several bugs in python TCompactProtocol - * [THRIFT-1092] - generated validate() method has wrong indentation - * [THRIFT-1011] - Error generating package imports when using classes from other packages - * [THRIFT-1050] - Declaring an argument named "manager" to a service method produces code that fails compile due to name conflicts with protected ivars in TAsyncClient - * [THRIFT-1074] - .keystore and .truststore are missing from the 0.6.0 distribution - * [THRIFT-1067] - Tons of bugs in php implementation - * [THRIFT-1065] - Unexpected exceptions not proper handled on JS - * [THRIFT-1076] - Erlang Thrift socket server has a bug that causes java thrift client of framed binary client to throw "out of sequence" exception - * [THRIFT-1057] - casts in TBinaryProtocol.tcc causing "dereferencing type-punned pointer will break strict-aliasing rules" warnings from gcc - * [THRIFT-1055] - csharp TServerSocket and TSocket do not disable Nagle via Socket.NoDelay = true like cpp and java do - * [THRIFT-1054] - explicit call to PKG_PROG_PKG_CONFIG is missing and first use of PKG_CHECK_MODULES may not happen, causes mono detection to fail - * [THRIFT-1117] - JavaScript Unit Test does not work anymore because libthrift*.jar where moved by Maven Deployment - * [THRIFT-1111] - The HTML generator does not distinguish between string and binary types - * [THRIFT-1032] - "make dist" fails due to c_glib problem - * [THRIFT-1036] - Auto-generated C++ code fails to compile with "-Werror -Wextra -Wall" g++ compiler flags - * [THRIFT-1041] - TDeserializer holds onto a reference of the array it reads after it is done deserializing - * [THRIFT-1106] - C++ code TAsyncProtocolProcessor.h & TAsyncBufferProcessor.h dont have virtual functions but no virtual destructor. Causes warnings on -Wall - * [THRIFT-1105] - OCaml generator does not prefix methods of included structs with their type - * [THRIFT-1104] - INSTALLDIRS should be included in configure script - * [THRIFT-1102] - typo in configure.ac: "==" operator in 'test' (instead of"'=") - * [THRIFT-1101] - bytebuffer length calculation in TBinaryProtocol writeBinary - * [THRIFT-1098] - Undefined properties in TBinaryProtocolFactory - * [THRIFT-1081] - PHP tests broken and somewhat incomplete - * [THRIFT-1080] - erlang test's 'make' fails on Mac OSX - * [THRIFT-1078] - ThriftTest.thrift generates invalid PHP library - * [THRIFT-1120] - proto.WriteListEnd being called in the wrong place - * [THRIFT-1119] - TJSONProtocol fails to UTF8 decode strings - * [THRIFT-867] - PHP accelerator module's output transport is incompatible with TFramedTransport - * [THRIFT-826] - PHP TSocket Write Timeout - * [THRIFT-835] - Bad AS3 syntax in constructors that set default values - * [THRIFT-788] - thrift_protocol.so: multiget/multiget_slice does not handle more than 17 keys correctly - * [THRIFT-125] - OCaml libraries don't compile with 32-bit ocaml - * [THRIFT-342] - PHP: can't have sets of complex types - * [THRIFT-731] - configure doesn't check for ant >= 1.7 - * [THRIFT-690] - Update TApplicationException codes - * [THRIFT-638] - BufferedTransport + C extensions block until recv timeout is reached on last fread call - -## Dependency upgrade - * [THRIFT-1177] - Update thrift to reflect changes in Go's networking libraries - -## Improvement - * [THRIFT-1155] - Remove log4j dependency from java client - * [THRIFT-1151] - Produce more informative runtime error in case of schema and data mismatch during serialization - * [THRIFT-1207] - Support DESTDIR on "make install" of ruby libs - * [THRIFT-1199] - Union structs should have generated methods to test whether a specific field is currently set - * [THRIFT-1233] - Remove unused include in generated C++ code - * [THRIFT-1189] - Ruby deserializer speed improvements - * [THRIFT-1170] - Thrift Generated Code and Java 5 - * [THRIFT-1174] - Publish as3 client implementation via Maven for use by flex-mojos users - * [THRIFT-1225] - TCompactProtocol for PHP - * [THRIFT-1221] - Remove SimpleCallback.h - * [THRIFT-1217] - Use evutil_socketpair instead of pipe (Windows port) - * [THRIFT-1216] - build Java Library behind a proxy - * [THRIFT-1231] - Remove bogus include - * [THRIFT-1213] - Membuffer should provide a way to get back the buffer - * [THRIFT-1237] - Java fb303 missing some methods - * [THRIFT-1063] - Fix Erlang Tutorial Files - * [THRIFT-1053] - Make remote client's IP address available for all socket related transports - * [THRIFT-1109] - Deploy fb303 along side libthrift to maven repo - * [THRIFT-1107] - improvement for compiler-generated python for 'None' object comparisons - * [THRIFT-1069] - Add command line option to prevent thrift from inserting gen-* directories - * [THRIFT-1049] - Allow for TServerSocket python library to bind to a specific host - * [THRIFT-1126] - Extending struct_info for erlang bindings - * [THRIFT-1100] - python TSSLSocket improvements, including certificate validation - * [THRIFT-994] - Don't try to invoke phpize if we don't have it - * [THRIFT-993] - Some improvements in C++ stubs for oneway operations - * [THRIFT-997] - Using valueOf for base types in getFieldValue - * [THRIFT-418] - Don't do runtime sorting of struct fields - * [THRIFT-151] - TSSLServerSocket and TSSLSocket implementation - * [THRIFT-27] - Generated erlang types don't contain default values for records - * [THRIFT-113] - to-string methods should omit optional null fields from output - * [THRIFT-363] - Maven Deploy - * [THRIFT-447] - Make an abstract base Client class so we can generate less code - * [THRIFT-627] - should c++ have setters for optional fields? - -## New Feature - * [THRIFT-1236] - Erlang Reconnecting Thrift Client - * [THRIFT-1021] - Framed transport support for OCaml - * [THRIFT-1068] - Python SSL Socket Support - * [THRIFT-1103] - TZlibTransport for python, a zlib compressed transport - * [THRIFT-1083] - Preforking python process pool server - * [THRIFT-999] - Add TForkingServer - -## Sub-task - * [THRIFT-1152] - Attributes from private to protected - * [THRIFT-1038] - Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable - -## Task - * [THRIFT-892] - Refactor erlang build system with rebar - -## Wish - * [THRIFT-625] - Add support for 'Go' - - - -Thrift 0.6.1 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1133] - Java and JavaScript tutorial is broken since we have Java maven deployment - * [THRIFT-1131] - C# JSON Protocol is unable to decode escaped characters in string - * [THRIFT-1074] - .keystore and .truststore are missing from the 0.6.0 distribution - -## Improvement - * [THRIFT-1109] - Deploy fb303 along side libthrift to maven repo - * [THRIFT-363] - Maven Deploy - -## Question - * [THRIFT-1206] - did the THRIFT 0.6.1 merge THRIFT-563 ? - -## Sub-task - * [THRIFT-1163] - How can i use multi service in one program? - -## Task - * [THRIFT-1112] - Apply THRIFT-363 to 0.6 branch - * [THRIFT-1113] - Apply THRIFT-1074 to 0.6 branch - - - -Thrift 0.6 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1020] - OCaml compiler generates invalid OCaml - * [THRIFT-1015] - TUnion does not handle ByteBuffer in toString - * [THRIFT-1013] - generated java code may have name clashes with thrift library - * [THRIFT-1009] - TUnion does not correctly deep copy a ByteBuffer - * [THRIFT-1032] - "make dist" fails due to c_glib problem - * [THRIFT-868] - Referencing constant values doesn't work with with typedef types - * [THRIFT-971] - java module can't be compiled without ivy and network connection - * [THRIFT-970] - Under heavy load, THttpClient may fail with "too many open files" - * [THRIFT-969] - Java Tutorial broken, move CalculatorHandler to a separate file - * [THRIFT-807] - JavaScript: Initialization of Base Types with 0 instead of null - * [THRIFT-955] - Thrift compiler for Windows uses lowercase names and directories which is inconsistent with compiling on other platforms - * [THRIFT-992] - Naming convention in C# constructor is not consistent with other fields causes compile errors - * [THRIFT-1008] - byte[] accessors throw NPE on unset field - * [THRIFT-1006] - Impossible to correctly qualify an enum constant in an external thrift file - * [THRIFT-950] - Haskell bindings treat 'byte' as unsigned 8-bit int (Data.Word.Word8), java/cpp as signed (byte/int8_t). - * [THRIFT-975] - lib/c_glib/README is missing => breaks make dist - * [THRIFT-944] - Support all version-4s of base - * [THRIFT-939] - optional binary fields throw NPE on default byte[] getters - * [THRIFT-935] - PHP Extension aborts the build if php-config is not installed - * [THRIFT-933] - Haskell's Thrift.cabal has warnings - * [THRIFT-932] - Haskell tests need to be run through 'make check' (and probably 'cabal check') too - * [THRIFT-904] - C# TSocket should disable nagle and linger - * [THRIFT-941] - Make PHP C Extension use the defined Protocol writeMessageBegin function - * [THRIFT-940] - 'make check' fails if boost is not in the std include and link paths - * [THRIFT-924] - Fix generated php structure constants - * [THRIFT-979] - ruby bindings used to work on jruby - * [THRIFT-977] - Hex Conversion Bug in C++ TJSONProtocol - * [THRIFT-347] - PHP TSocket Timeout Issues - * [THRIFT-517] - TExceptions thrown by server result in cryptic error message on client - Tried to read 4 bytes, but only got 0 bytes - -## Improvement - * [THRIFT-1024] - Add Python Twisted example to the Tutorial - * [THRIFT-958] - Change accessmodifer on trans_ field in the FrameBuffer class to public. - * [THRIFT-957] - THsHaServer: Change access modifier of the invoker field. - * [THRIFT-1002] - CodeStyle: t_c_glib_generator.cc - * [THRIFT-1005] - Give unions byte[] signature methods to go along with their ByteBuffer counterparts - * [THRIFT-951] - Add a new isServing() method to TServer - * [THRIFT-943] - Silly readme typo fix. - * [THRIFT-961] - JavaScript TestSuite using ant/ivy and Java's ServerTestBase Handler - * [THRIFT-960] - add TestServer, TestNonblockingServer and TestClient again - * [THRIFT-949] - Modify the TEnum interface so it defines a method similar to findByValue - * [THRIFT-946] - Augment FieldValueMetaData so it differentiates 'string' and 'binary' fields. - * [THRIFT-903] - custom ThreadFactory in THsHaServer - * [THRIFT-913] - Test Case for Url encoded strings + simple enhancement to lib/js/test/RunTestServer.sh - * [THRIFT-926] - Miscellaneous C++ improvements - * [THRIFT-929] - Improvements to the C++ test suite - * [THRIFT-893] - add JavaScript to the tutorial examples - * [THRIFT-1003] - Polishing c_glib code - * [THRIFT-71] - Debian packaging for thrift - -## New Feature - * [THRIFT-1033] - Node.js language target - * [THRIFT-947] - Provide a helper method to determine the TProtocol used to serialize some data. - * [THRIFT-928] - Make more statistics available in C++ servers - * [THRIFT-922] - Templatized [de]serialization code for C++ - * [THRIFT-923] - Event-driven client and server support for C++ - * [THRIFT-925] - Provide name<->value map for enums in C++ - * [THRIFT-927] - Add option to modify the PHP include path - * [THRIFT-377] - TFileTransport port in Java - * [THRIFT-106] - TSSLServerSocket - * [THRIFT-582] - C implementation of Thrift - * [THRIFT-745] - Make it easier to instantiate servers - -## Sub-task - * [THRIFT-1038] - Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable - -## Task - * [THRIFT-862] - Async client issues / improvements - -## Test - * [THRIFT-581] - Add a testsuite for txThrift (Twisted) - - - -Thrift 0.5.0 - Incubating --------------------------------------------------------------------------------- -THRIFT-505 Build Make configure give a summary of the enabled components (David Reiss) -THRIFT-506 Build Allow Thrift to be built without the C++ library (David Reiss) -THRIFT-844 Build Build Requirements state autoconf 2.59+ is required, but 2.60+ is needed (Harlan Lieberman-Berg) -THRIFT-850 Build Perl runtime requires Bit::Vector which may not be installed by default, but configure does not fail (Michael Lum) -THRIFT-854 Build Provide configure option and make rules to build/install php extension (Anthony Molinaro) -THRIFT-858 Build Have bootstrap.sh check for a suitable autoconf version before running (David Reiss) -THRIFT-871 Build Thrift compiler for WIndows (binary distribution) (David Reiss) -THRIFT-323 C# TJSONProtocol (Roger Meier) -THRIFT-634 C# C# Compiler Generates Incorrect Code For Fields which begin with an uppercase letter (Jon S Akhtar) -THRIFT-881 C# add csharp to the tutorial (Roger Meier) -THRIFT-856 C++ Building cpp library fails on OS X with malloc and free not being declared in scope (James Clarke) -THRIFT-865 C++ C++ compiler build depends on libfl even when flex/lex not detected (David Reiss) -THRIFT-900 C++ Unix domain socket (Roger Meier) -THRIFT-920 C++ C++ Test and Tutorial does not compile anymore due to the change within Enum handling (Roger Meier) -THRIFT-567 C++ Can't immediately stop a TSimpleServer thread that is idle (Rush Manbert) -THRIFT-756 C++ Exposing TSocket(int) constructor to public (Rajat Goel) -THRIFT-798 C++ TNonblockingServer leaks resources when destroyed (David Reiss) -THRIFT-812 C++, Python Demo of Thrift over ZeroMQ (David Reiss) -THRIFT-629 Cocoa Unused Field In TSocketServer Appears To Break iPhone Build (Jon S Akhtar) -THRIFT-838 Cocoa Generated Cocoa classes have useless @dynamic declarations (Kevin Ballard) -THRIFT-805 Cocoa Don't generate process_XXXX methods for oneway methods (Brad Taylor) -THRIFT-507 Compiler Remove the compiler's dependency on Boost (David Reiss) -THRIFT-895 Compiler (General) Thrift compiler does not allow two different enumerations to have the same key name for one of the enum values (David Reiss) -THRIFT-852 Compiler (General) Missing newline causes many compiler warnings (Anthony Molinaro) -THRIFT-877 Compiler (General) smalltalk namespace doesn't work (Bruce Lowekamp) -THRIFT-897 Compiler (General) Don't allow unqualified constant access to enum values (Bryan Duxbury) -THRIFT-9 Compiler (General) Add a default namespace declaration for all languages (David Reiss) -THRIFT-599 Erlang Don't use unnecessary processes in the Erlang transports and clients (David Reiss) -THRIFT-646 Erlang Erlang library is missing install target (David Reiss) -THRIFT-698 Erlang Generated module list should contain atoms, not strings (Anthony Molinaro) -THRIFT-866 Erlang term() in spec definitions seems to not work in erlang R12 (Anthony Molinaro) -THRIFT-886 Erlang Dialyzer warning (Anthony Molinaro) -THRIFT-785 Erlang Framed transport server problems (Anthony Molinaro) -THRIFT-884 HTML HTML Generator: add Key attribute to the Data Types Tables (Roger Meier) -THRIFT-652 Haskell Generated field name for strut is not capitalized correctly (Christian Lavoie) -THRIFT-743 Haskell compile error with GHC 6.12.1 (Christian Lavoie) -THRIFT-901 Haskell Allow the bindings to compile without -fglasgow-exts and with -Wall -Werror (Christian Lavoie) -THRIFT-905 Haskell Make haskell thrift bindings use automake to compile and install (Christian Lavoie) -THRIFT-906 Haskell Improve type mappings (Christian Lavoie) -THRIFT-914 Haskell Make haskell bindings 'easily' compilable (Christian Lavoie) -THRIFT-918 Haskell Make haskell tests run again (Christian Lavoie) -THRIFT-919 Haskell Update Haskell bindings README (Christian Lavoie) -THRIFT-787 Haskell Enums are not read correctly (Christian Lavoie) -THRIFT-250 Java ExecutorService as a constructor parameter for TServer (Ed Ceaser) -THRIFT-693 Java Thrift compiler generated java code that throws compiler warnings about deprecated methods. (Bryan Duxbury) -THRIFT-843 Java TNonblockingSocket connects without a timeout (Bryan Duxbury) -THRIFT-845 Java async client does not respect timeout (Ning Liang) -THRIFT-870 Java Java constants don't get Javadoc comments (Bryan Duxbury) -THRIFT-873 Java Java tests fail due to Too many open files (Todd Lipcon) -THRIFT-876 Java Add SASL support (Aaron T. Myers) -THRIFT-879 Java Remove @Override from TUnion.clear (Dave Engberg) -THRIFT-882 Java deep copy of binary fields does not copy ByteBuffer characteristics (arrayOffset, position) (Bryan Duxbury) -THRIFT-888 Java async client should also have nonblocking connect (Eric Jensen) -THRIFT-890 Java Java tutorial doesn't work (Todd Lipcon) -THRIFT-894 Java Make default accessors for binary fields return byte[]; provide new accessors to get ByteBuffer version (Bryan Duxbury) -THRIFT-896 Java TNonblockingSocket.isOpen() returns true even after close() (Eric Jensen) -THRIFT-907 Java libfb303 doesn't compile in 0.4.0 (Todd Lipcon) -THRIFT-912 Java Improvements and bug fixes to SASL implementation (Todd Lipcon) -THRIFT-917 Java THsHaServer should not accept an ExecutorService without catching RejectedExecutionException (Ed Ceaser) -THRIFT-931 Java Use log4j for Java tests (Todd Lipcon) -THRIFT-880 JavaME JavaME code generator and runtime library (Dave Engberg) -THRIFT-846 JavaScript JavaScript Test Framwork: extended Testcases (Roger Meier) -THRIFT-885 JavaScript Url encoded strings never get decoded? How do we fix this? (T Jake Luciani) -THRIFT-911 JavaScript (JavaScript compiler) Const structs, maps, sets, and lists generate a trailing comma (T Jake Luciani) -THRIFT-860 OCaml copy method and reset method (Lev Walkin) -THRIFT-682 PHP PHP extension doesn't compile on Mac OS X (Bryan Duxbury) -THRIFT-851 PHP php extension fails to compile on centos 5.x (Todd Lipcon) -THRIFT-840 Perl Perl protocol handler could be more robust against unrecognised types (Conrad Hughes) -THRIFT-758 Perl incorrect deference in exception handling (Yann Kerherve) -THRIFT-257 Python Support validation of required fields (Esteve Fernandez) -THRIFT-335 Python Compact Protocol for Python (David Reiss) -THRIFT-596 Python Make Python's TBufferedTransport use a configurable input buffer (David Reiss) -THRIFT-597 Python Python THttpServer performance improvements (David Reiss) -THRIFT-598 Python Allow Python's threading servers to use daemon threads (David Reiss) -THRIFT-666 Python Allow the handler to override HTTP responses in THttpServer (David Reiss) -THRIFT-673 Python Generated Python code has whitespace issues (Ian Eure) -THRIFT-721 Python THttpClient ignores url parameters (Thomas Kho) -THRIFT-824 Python TApplicationException.__str__() refers to class constants as globals (Peter Schuller) -THRIFT-855 Python Include optimized compiled python objects in install (Anthony Molinaro) -THRIFT-859 Python Allow py:twisted to be generated in different namespace than py (Bruce Lowekamp) -THRIFT-869 Python TSocket.py on Mac (and FreeBSD) doesn't handle ECONNRESET from recv() (Steven Knight) -THRIFT-875 Python Include python setup.cfg in dist (Anthony Molinaro) -THRIFT-610 Ruby binary_protocol.rb segfaults [line 86] (Unassigned) -THRIFT-899 Ruby Ruby read timeouts can sometimes be 2x what they should be (Ryan King) -THRIFT-909 Ruby allow block argument to struct constructor (Michael Stockton) -THRIFT-456 Test Suite Bad IP address string in test/cpp/src/main.cpp (Rush Manbert) - - -Thrift 0.4.0 - Incubating --------------------------------------------------------------------------------- -THRIFT-650 Build Make Check fails on Centos/OSX with 0.2.0 tarball (Anthony Molinaro) -THRIFT-770 Build Get 'make dist' to work without first compiling source code (Anthony Molinaro) -THRIFT-160 C# Created THttpTransport for the C# library based on WebHttpRequest (Michael Greene) -THRIFT-834 C# THttpClient resends contents of message after transport errors (Anatoly Fayngelerin) -THRIFT-247 C++ THttpServer Transport (Unassigned) -THRIFT-676 C++ Change C++ code generator so that generated classes can be wrapped with SWIG (Unassigned) -THRIFT-570 Compiler Thrift compiler does not error when duplicate method names are present (Bruce Simpson) -THRIFT-808 Compiler Segfault when constant declaration references a struct field that doesn't exist (Bryan Duxbury) -THRIFT-646 Erlang Erlang library is missing install target (Anthony Molinaro) -THRIFT-544 General multiple enums with the same key generate invalid code (Ben Taitelbaum) -THRIFT-434 General ruby compiler should warn when a reserved word is used (Michael Stockton) -THRIFT-799 General Files missing proper Apache license header (Bryan Duxbury) -THRIFT-832 HTML HTML generator shows unspecified struct fields as 'required' (Bryan Duxbury) -THRIFT-226 Java Collections with binary keys or values break equals() (Bryan Duxbury) -THRIFT-484 Java Ability to use a slice of a buffer instead of a direct byte[] for binary fields (Bryan Duxbury) -THRIFT-714 Java maxWorkerThreads parameter to THsHaServer has no effect (Bryan Duxbury) -THRIFT-751 Java Add clear() method to TBase (Bryan Duxbury) -THRIFT-765 Java Improved string encoding and decoding performance (Bryan Duxbury) -THRIFT-768 Java Async client for Java (Bryan Duxbury) -THRIFT-774 Java TDeserializer should provide a partialDeserialize method for primitive types (Piotr Kozikowski) -THRIFT-783 Java .equals java method is broken on structs containing binary-type fields (Unassigned) -THRIFT-804 Java CompareTo is broken for unions set to map, set, or list (Bryan Duxbury) -THRIFT-814 Java Include a TServlet in the standard Thrift distribution (Mathias Herberts) -THRIFT-818 Java Async client doesn't send method args (Bryan Duxbury) -THRIFT-830 Java Switch binary field implementation from byte[] to ByteBuffer (Bryan Duxbury) -THRIFT-831 Java FramedTransport implementation that reuses its buffers (Bryan Duxbury) -THRIFT-833 Java build.xml in lib/java is missing a classpathref attribute for the javadoc task (Bryan Duxbury) -THRIFT-836 Java Race condition causes CancelledKeyException in TAsyncClientManager (Bryan Duxbury) -THRIFT-842 Java Upgrade to current version of commons-lang (2.5 instead of 2.4) and/or change dependency in ivy.xml to not be exact (Bryan Duxbury) -THRIFT-815 JavaScript Deserialization of lists is critically broken. (T Jake Luciani) -THRIFT-827 OCaml OCaml generator to take default values into account (Lev Walkin) -THRIFT-647 PHP PHP library is missing install target (Anthony Molinaro) -THRIFT-682 PHP PHP extension doesn't compile on Mac OS X (Bryan Duxbury) -THRIFT-718 PHP Thrift PHP library includes closing tags and extraneous whitespace (Nicholas Telford) -THRIFT-778 PHP PHP socket listening server (Nick Jones) -THRIFT-780 PHP PHP extension sometimes causes an abort with two exceptions at the same time (David Reiss) -THRIFT-837 PHP PHP accelerator bug for writes > 8k (Thomas Kho) -THRIFT-782 Perl Perl code for writing containers doesn't count length of write*Begin or write*End (Conrad Hughes) -THRIFT-395 Python Python library + compiler does not support unicode strings (Unassigned) -THRIFT-133 Ruby 'namespace ruby' should error out, or be an alias to 'namespace rb' (Bryan Duxbury) -THRIFT-664 Ruby Ruby extension fails to build with Ruby 1.9.1 (Rajesh Malepati) -THRIFT-699 Ruby Excise unused "native protocol method table" stuff from thrift_native (Bryan Duxbury) -THRIFT-767 Ruby ruby compiler does not keep comments for enum values (Bryan Duxbury) -THRIFT-811 Ruby http_client_transport.rb: allow custom http headers (Tony Kamenick) -THRIFT-459 Ruby Ruby installation always tries to write to /Library/Ruby/site (Matthieu Imbert) - - -Thrift 0.1.0 - Incubating (not released) --------------------------------------------------------------------------------- -Compatibility Breaking Changes: - C++: - * It's quite possible that regenerating code and rebuilding will be - required. Make sure your headers match your libs! - - Java: - - Python: - - Ruby: - * Generated files now have underscored names [THRIFT-421] - * The library has been rearranged to be more Ruby-like [THRIFT-276] - - Erlang: - * Generated code will have to be regenerated, and the new code will - have to be deployed atomically with the new library code [THRIFT-136] - -New Features and Bug Fixes: - C++: - * Support for TCompactProtocol [THRIFT-333] - - Java: - * Support for TCompactProtocol [THRIFT-110] - - Python: - * Support for Twisted [THRIFT-148] - - Ruby: - * Support for TCompactProtocol [THRIFT-332] - diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 00000000000..ef6f240a379 --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,2916 @@ +# Apache Thrift Changelog + +## 1.0.0 + +### New Languages +### Deprecated Languages +### Removed Languages +### Breaking Changes +- [THRIFT-4702](https://issues.apache.org/jira/browse/THRIFT-4702) - Java class org.apache.thrift.AutoExpandingBuffer is no longer public +- [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - Java changes to UTF-8 handling require JDK 1.7 at a minimum +- [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - Java class org.apache.thrift.ShortStack is no longer public +- [THRIFT-4720](https://issues.apache.org/jira/browse/THRIFT-4720) - C++03/C++98 support has been removed; also removed boost as a runtime dependency +### Known Isues (Blocker or Critical) + +## 0.12.0 + +Released 2019-JAN-04 + +### New Languages +- Common LISP (cl) +- Swift +- Typescript (nodets) + +### Deprecated Languages +- C++03/C++98 (move to C++11) +- Cocoa (move to Swift) + +### Breaking Changes (since 0.11.0) +- [THRIFT-4529](https://issues.apache.org/jira/browse/THRIFT-4529) - Rust enum variants are now camel-cased instead of uppercased to conform to Rust naming conventions +- [THRIFT-4448](https://issues.apache.org/jira/browse/THRIFT-4448) - Support for golang 1.6 and earlier has been dropped. +- [THRIFT-4474](https://issues.apache.org/jira/browse/THRIFT-4474) - PHP now uses the PSR-4 loader by default instead of class maps. +- [THRIFT-4532](https://issues.apache.org/jira/browse/THRIFT-4532) - method signatures changed in the compiler's t_oop_generator. +- [THRIFT-4648](https://issues.apache.org/jira/browse/THRIFT-4648) - The C (GLib) compiler's handling of namespaces has been improved. + +### Known Issues (Blocker or Critical) +- [THRIFT-4037](https://issues.apache.org/jira/browse/THRIFT-4037) - build: use a single build system for thrift +- [THRIFT-4119](https://issues.apache.org/jira/browse/THRIFT-4119) - build: bootstrap.sh is missing from source tarball +- [THRIFT-3289](https://issues.apache.org/jira/browse/THRIFT-3289) - csharp: socket exhaustion in csharp implementation +- [THRIFT-3029](https://issues.apache.org/jira/browse/THRIFT-3029) - cocoa: Getters for fields defined with uppercase names do not work +- [THRIFT-3325](https://issues.apache.org/jira/browse/THRIFT-3325) - cocoa: Extended services aren't subclasses in generated Cocoa +- [THRIFT-4116](https://issues.apache.org/jira/browse/THRIFT-4116) - cocoa: Thrift de-capitalizes the name of IsSet property in Cocoa +- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - cpp: the http implementation is not standard; interop with other languages is spotty at best +- [THRIFT-4180](https://issues.apache.org/jira/browse/THRIFT-4180) - cpp: Impossible to build Thrift C++ library for Android (NDK) +- [THRIFT-4384](https://issues.apache.org/jira/browse/THRIFT-4384) - cpp: Using multiple async services simultaneously is not thread-safe +- [THRIFT-3108](https://issues.apache.org/jira/browse/THRIFT-3108) - haskell: Defaulted struct parameters on a service generates invalid Haskell +- [THRIFT-3990](https://issues.apache.org/jira/browse/THRIFT-3990) - nodejs: Exception swallowed by deserialization function +- [THRIFT-4214](https://issues.apache.org/jira/browse/THRIFT-4214) - nodejs: map key treated as hex value in JavaScript +- [THRIFT-4602](https://issues.apache.org/jira/browse/THRIFT-4602) - nodejs: ERROR in ./node_modules/thrift/lib/nodejs/lib/thrift/connection.js Module not found: Error: Can't resolve 'child_process' +- [THRIFT-4639](https://issues.apache.org/jira/browse/THRIFT-4639) - nodejs: Sequence numbering for multiplexed protocol broken +- [THRIFT-1310](https://issues.apache.org/jira/browse/THRIFT-1310) - php: sequence and reconnection management issues +- [THRIFT-1538](https://issues.apache.org/jira/browse/THRIFT-1538) - php: Error during deserialization int64 on 32-bit architecture +- [THRIFT-1580](https://issues.apache.org/jira/browse/THRIFT-1580) - php: thrift type i64 java to php serialize/deserealize not working +- [THRIFT-1950](https://issues.apache.org/jira/browse/THRIFT-1950) - php: PHP gets stuck in infinite loop +- [THRIFT-2954](https://issues.apache.org/jira/browse/THRIFT-2954) - python: sending int or float in a double field breaks the connection +- [THRIFT-4080](https://issues.apache.org/jira/browse/THRIFT-4080) - python: unix sockets can get stuck forever +- [THRIFT-4281](https://issues.apache.org/jira/browse/THRIFT-4281) - python: generated code is out of order and causes load issues +- [THRIFT-4677](https://issues.apache.org/jira/browse/THRIFT-4677) - py3: UnicodeDecideError in Python3 + +### Build Process +- [THRIFT-4067](https://issues.apache.org/jira/browse/THRIFT-4067) - Windows thrift compiler distributed on the apache web site has runtime dependencies +- [THRIFT-4308](https://issues.apache.org/jira/browse/THRIFT-4308) - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang +- [THRIFT-4579](https://issues.apache.org/jira/browse/THRIFT-4579) - Use Ubuntu Bionic (18.04 LTS) for CI builds instead of Artful (17.10) +- [THRIFT-4508](https://issues.apache.org/jira/browse/THRIFT-4508) - Define CI operating system coverage rules for the project and (hopefully) simplify CI a little more +- [THRIFT-4397](https://issues.apache.org/jira/browse/THRIFT-4397) - ubuntu install instructions broken on 16.04 +- [THRIFT-4545](https://issues.apache.org/jira/browse/THRIFT-4545) - Appveyor builds are failing due to a haskell / cabal update in chocolatey +- [THRIFT-4452](https://issues.apache.org/jira/browse/THRIFT-4452) - optimize Dockerfile (only onetime apt-get update) +- [THRIFT-4440](https://issues.apache.org/jira/browse/THRIFT-4440) - rm `build/docker/ubuntu-trusty/Dockerfile.orig` +- [THRIFT-4352](https://issues.apache.org/jira/browse/THRIFT-4352) - Ubuntu Artful doesn't appear to be compatible with Thrift and Haxe 3.4.2 +- [THRIFT-4666](https://issues.apache.org/jira/browse/THRIFT-4666) - DLang Client Pool Test fails sporadically +- [THRIFT-4676](https://issues.apache.org/jira/browse/THRIFT-4676) - CL tutorial build fails sporadically +- [THRIFT-4456](https://issues.apache.org/jira/browse/THRIFT-4456) - Make haxelib download quiet so it doesn't blow up the build log +- [THRIFT-4605](https://issues.apache.org/jira/browse/THRIFT-4605) - bootstrap.sh fails if automake=1.16.1 + +### c_glib +- [THRIFT-4648](https://issues.apache.org/jira/browse/THRIFT-4648) - The C (GLib) compiler's handling of namespaces has been improved. +- [THRIFT-4622](https://issues.apache.org/jira/browse/THRIFT-4622) - glibC compilation issue +- [THRIFT-4671](https://issues.apache.org/jira/browse/THRIFT-4671) - c glib is unable to handle client close unexpectedly + +### cl (new language support in 0.12.0) +- [THRIFT-82](https://issues.apache.org/jira/browse/THRIFT-82) - Common Lisp support + +### csharp +- [THRIFT-4558](https://issues.apache.org/jira/browse/THRIFT-4558) - reserved Csharp keywords are not escaped in some cases +- [THRIFT-4637](https://issues.apache.org/jira/browse/THRIFT-4637) - C# async mode generates incorrect code with inherited services +- [THRIFT-4672](https://issues.apache.org/jira/browse/THRIFT-4672) - IAsyncResult style methods not being supported by certain transports leads to issues in mixed ISync/IAsync use cases +- [THRIFT-4539](https://issues.apache.org/jira/browse/THRIFT-4539) - Allow TBufferedTransport to be used as base class +- [THRIFT-4535](https://issues.apache.org/jira/browse/THRIFT-4535) - XML docs; code cleanup (tabs->spaces; String->string) +- [THRIFT-4492](https://issues.apache.org/jira/browse/THRIFT-4492) - protected ExceptionType type member of TApplicationException cannot be accessed +- [THRIFT-4446](https://issues.apache.org/jira/browse/THRIFT-4446) - JSONProtocol Base64 Encoding Trims Padding +- [THRIFT-4455](https://issues.apache.org/jira/browse/THRIFT-4455) - Missing dispose calls in ThreadedServer & ThreadpoolServer +- [THRIFT-4609](https://issues.apache.org/jira/browse/THRIFT-4609) - keep InnerException wherever appropriate +- [THRIFT-4673](https://issues.apache.org/jira/browse/THRIFT-4673) - IAsyncResult not supported by layered transports (buffered/framed) + +### cpp +- [THRIFT-4476](https://issues.apache.org/jira/browse/THRIFT-4476) - Typecasting problem on list items +- [THRIFT-4465](https://issues.apache.org/jira/browse/THRIFT-4465) - TNonblockingServer throwing THRIFT LOGGER: TConnection::workSocket(): THRIFT_EAGAIN (unavailable resources) +- [THRIFT-4680](https://issues.apache.org/jira/browse/THRIFT-4680) - TBufferTransports.h does not compile under Visual Studio 2017 +- [THRIFT-4618](https://issues.apache.org/jira/browse/THRIFT-4618) - TNonblockingServer crash because of limitation of select() +- [THRIFT-4620](https://issues.apache.org/jira/browse/THRIFT-4620) - TZlibTransport.cpp doesn't ensure that there is enough space for the zlib flush marker in the buffer. +- [THRIFT-4571](https://issues.apache.org/jira/browse/THRIFT-4571) - ZeroMQ contrib library needs a refresh +- [THRIFT-4559](https://issues.apache.org/jira/browse/THRIFT-4559) - TSSLServerSocket incorrectly prints errors +- [THRIFT-4578](https://issues.apache.org/jira/browse/THRIFT-4578) - Move `TAsyncProtocolProcessor` into main thrift library +- [THRIFT-4418](https://issues.apache.org/jira/browse/THRIFT-4418) - evhttp_connection_new is deprecated; use evhttp_connection_base_new + +### compiler +- [THRIFT-4644](https://issues.apache.org/jira/browse/THRIFT-4644) - Compiler cannot be compiled on macOS(maybe also on other platforms with clang) +- [THRIFT-4531](https://issues.apache.org/jira/browse/THRIFT-4531) - Thrift generates wrong Python code for immutable structures with optional members +- [THRIFT-4513](https://issues.apache.org/jira/browse/THRIFT-4513) - thrift generated code is not stable for constants +- [THRIFT-4532](https://issues.apache.org/jira/browse/THRIFT-4532) - Avoid updating Thrift compiler generated code if the output has not changed +- [THRIFT-4400](https://issues.apache.org/jira/browse/THRIFT-4400) - Visual Studio Compiler project should link runtime statically in release builds +- [THRIFT-4399](https://issues.apache.org/jira/browse/THRIFT-4399) - plugin.thrift t_const_value is not used as a union in C++ code -- fix this +- [THRIFT-4496](https://issues.apache.org/jira/browse/THRIFT-4496) - Dealing with language keywords in Thrift (e.g. service method names) +- [THRIFT-4393](https://issues.apache.org/jira/browse/THRIFT-4393) - repeated runs of compiler produce different binary output at plugin interface + +### dlang +- [THRIFT-4478](https://issues.apache.org/jira/browse/THRIFT-4478) - Thrift will not build with dlang 2.078 or later +- [THRIFT-4503](https://issues.apache.org/jira/browse/THRIFT-4503) - dlang servers logError on normal client disconnection +- [THRIFT-4308](https://issues.apache.org/jira/browse/THRIFT-4308) - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang + +### dart +- [THRIFT-4646](https://issues.apache.org/jira/browse/THRIFT-4646) - Effective Dart and Exceptions +- [THRIFT-4439](https://issues.apache.org/jira/browse/THRIFT-4439) - Shouldn't download dart.deb directly. + +### delphi +- [THRIFT-4562](https://issues.apache.org/jira/browse/THRIFT-4562) - Calling wrong exception CTOR leads to "call failed: unknown result" instead of the real exception being thrown +- [THRIFT-4554](https://issues.apache.org/jira/browse/THRIFT-4554) - uncompileable code with member names that are also types under specific conditions +- [THRIFT-4422](https://issues.apache.org/jira/browse/THRIFT-4422) - Add Async implementation via IFuture +- [THRIFT-4485](https://issues.apache.org/jira/browse/THRIFT-4485) - Possible invalid ptr AV with overlapped read/write on pipes +- [THRIFT-4549](https://issues.apache.org/jira/browse/THRIFT-4549) - Thrift exceptions should derive from TException +- [THRIFT-4540](https://issues.apache.org/jira/browse/THRIFT-4540) - buffered transport broken when trying to re-open a formerly closed transport +- [THRIFT-4473](https://issues.apache.org/jira/browse/THRIFT-4473) - Move Thrift.Console.pas out of the Library +- [THRIFT-4490](https://issues.apache.org/jira/browse/THRIFT-4490) - Allow a default service as fallback for multiplex processors connected by old clients +- [THRIFT-4454](https://issues.apache.org/jira/browse/THRIFT-4454) - Large writes/reads may cause range check errors in debug mode +- [THRIFT-4461](https://issues.apache.org/jira/browse/THRIFT-4461) - Compiler directive should match Delphi XE4 +- [THRIFT-4462](https://issues.apache.org/jira/browse/THRIFT-4462) - First line in Console duplicated +- [THRIFT-4642](https://issues.apache.org/jira/browse/THRIFT-4642) - FPU ctrl word settings may cause an unexpected "denormalized" error +- [THRIFT-4589](https://issues.apache.org/jira/browse/THRIFT-4589) - HTTP client timeouts are a) incomplete and b) not used at all +- [THRIFT-4590](https://issues.apache.org/jira/browse/THRIFT-4590) - running the test client using HTTP transport leads to "CoInitialize not called" + +### erlang +- [THRIFT-4497](https://issues.apache.org/jira/browse/THRIFT-4497) - Erlang records should use map() for map type +- [THRIFT-4495](https://issues.apache.org/jira/browse/THRIFT-4495) - Erlang records should allow 'undefined' for non-required fields +- [THRIFT-4580](https://issues.apache.org/jira/browse/THRIFT-4580) - Fix erlang tutorial unpack on Windows +- [THRIFT-4582](https://issues.apache.org/jira/browse/THRIFT-4582) - Ubuntu Xenial erlang 18.3 "make check" fails + +### golang +- [THRIFT-4448](https://issues.apache.org/jira/browse/THRIFT-4448) - Support for golang 1.6 and earlier has been dropped. +- [THRIFT-4253](https://issues.apache.org/jira/browse/THRIFT-4253) - Go generator assigns strings to field in const instead of pointers. +- [THRIFT-4573](https://issues.apache.org/jira/browse/THRIFT-4573) - Unions Field Count Does Not Consider Binary +- [THRIFT-4447](https://issues.apache.org/jira/browse/THRIFT-4447) - Golang: Panic on p.c.Call when using deprecated initializers +- [THRIFT-4650](https://issues.apache.org/jira/browse/THRIFT-4650) - Required field incorrectly marked as set when fieldType does not match +- [THRIFT-4486](https://issues.apache.org/jira/browse/THRIFT-4486) - Golang: -remote.go client cleanup +- [THRIFT-4537](https://issues.apache.org/jira/browse/THRIFT-4537) - TSimpleServer can exit Accept loop with lock still acquired +- [THRIFT-4516](https://issues.apache.org/jira/browse/THRIFT-4516) - Add support for go 1.10 +- [THRIFT-4421](https://issues.apache.org/jira/browse/THRIFT-4421) - golang tests rely on gomock, which has change behaviour, causing tests to fail +- [THRIFT-4626](https://issues.apache.org/jira/browse/THRIFT-4626) - Communication crash when using binary/compact protocol and zlib transport +- [THRIFT-4659](https://issues.apache.org/jira/browse/THRIFT-4659) - golang race detected when closing listener socket + +### haskell +- [THRIFT-4634](https://issues.apache.org/jira/browse/THRIFT-4634) - Haskell builds with older cabal cannot reconcile complex version requirements + +### java +- [THRIFT-4259](https://issues.apache.org/jira/browse/THRIFT-4259) - Thrift does not compile due to Ant Maven task errors +- [THRIFT-1418](https://issues.apache.org/jira/browse/THRIFT-1418) - Compiling Thrift from source: Class org.apache.tools.ant.taskdefs.ConditionTask doesn't support the nested "typefound" element +- [THRIFT-4530](https://issues.apache.org/jira/browse/THRIFT-4530) - proposal: add nullability annotations to generated Java code +- [THRIFT-4614](https://issues.apache.org/jira/browse/THRIFT-4614) - Generate missing @Nullable annotations for Java iterator getters +- [THRIFT-4555](https://issues.apache.org/jira/browse/THRIFT-4555) - Getter of binary field in Java creates unnecessary copy +- [THRIFT-3983](https://issues.apache.org/jira/browse/THRIFT-3983) - libthrift is deployed on central with pom packaging instead of jar +- [THRIFT-4294](https://issues.apache.org/jira/browse/THRIFT-4294) - Java Configure Fails for Ant >= 1.10 +- [THRIFT-4178](https://issues.apache.org/jira/browse/THRIFT-4178) - Java libraries missing from package when using cmake +- [THRIFT-4120](https://issues.apache.org/jira/browse/THRIFT-4120) - pom files are not generated or provided in the build +- [THRIFT-1507](https://issues.apache.org/jira/browse/THRIFT-1507) - Maven can't download resource from central when behind a proxy and won't use local repository +- [THRIFT-4556](https://issues.apache.org/jira/browse/THRIFT-4556) - Optional rethrow of unhandled exceptions in java processor +- [THRIFT-4337](https://issues.apache.org/jira/browse/THRIFT-4337) - Able to set keyStore and trustStore as InputStream in the TSSLTransportFactory.TSSLTransportParameters +- [THRIFT-4566](https://issues.apache.org/jira/browse/THRIFT-4566) - Pass message of unhandled exception to optional rethrow. +- [THRIFT-4506](https://issues.apache.org/jira/browse/THRIFT-4506) - Remove assertion in Java SASL code that would be ignored in release builds +- [THRIFT-4470](https://issues.apache.org/jira/browse/THRIFT-4470) - Include popular IDE file templates to gitignore +- [THRIFT-4429](https://issues.apache.org/jira/browse/THRIFT-4429) - Make TThreadPoolServer.executorService_ available in inherited classes and refactor methods to be able customization +- [THRIFT-3769](https://issues.apache.org/jira/browse/THRIFT-3769) - Fix logic of THRIFT-2268 +- [THRIFT-4494](https://issues.apache.org/jira/browse/THRIFT-4494) - Increase Java Socket Buffer Size +- [THRIFT-4499](https://issues.apache.org/jira/browse/THRIFT-4499) - Remove Magic Number In TFIleTransport + +### js +- [THRIFT-4406](https://issues.apache.org/jira/browse/THRIFT-4406) - JavaScript: Use modern Promise implementations +- [THRIFT-4625](https://issues.apache.org/jira/browse/THRIFT-4625) - let / const variable decorators for es6 compiler +- [THRIFT-4653](https://issues.apache.org/jira/browse/THRIFT-4653) - ES6 Classes +- [THRIFT-4592](https://issues.apache.org/jira/browse/THRIFT-4592) - JS: readI32 performance on large arrays is very poor in Chrome +- [THRIFT-4509](https://issues.apache.org/jira/browse/THRIFT-4509) - js and nodejs libraries need to be refreshed with current libraries +- [THRIFT-4403](https://issues.apache.org/jira/browse/THRIFT-4403) - thrift.js: Incorrect usage of 'this' in TWebSocketTransport.__onOpen +- [THRIFT-4436](https://issues.apache.org/jira/browse/THRIFT-4436) - Deserialization of nested list discards content +- [THRIFT-4437](https://issues.apache.org/jira/browse/THRIFT-4437) - JS WebSocket client callbacks invoked twice on parallel requests +- [THRIFT-4679](https://issues.apache.org/jira/browse/THRIFT-4679) - Duplicate declaration of InputBufferUnderrunError in lib/nodejs/lib/thrift/json_protocol.js +- [THRIFT-4551](https://issues.apache.org/jira/browse/THRIFT-4551) - Add prettier for consistent JS code formatting + +### lua +- [THRIFT-4591](https://issues.apache.org/jira/browse/THRIFT-4591) - lua client uses two write() calls per framed message send +- [THRIFT-3863](https://issues.apache.org/jira/browse/THRIFT-3863) - Can't "make install" Lua Library + +### netcore +- [THRIFT-4524](https://issues.apache.org/jira/browse/THRIFT-4524) - .NET Core Server doesn't close properly when cancelled +- [THRIFT-4434](https://issues.apache.org/jira/browse/THRIFT-4434) - Update .NET Core components, add tests for .Net Core library and .Net Core compiler, fix bugs and build process +- [THRIFT-4446](https://issues.apache.org/jira/browse/THRIFT-4446) - JSONProtocol Base64 Encoding Trims Padding + +### node.js +- [THRIFT-4225](https://issues.apache.org/jira/browse/THRIFT-4225) - Error handling malformed arguments leaks memory, corrupts transport buffers causing next RPC to fail +- [THRIFT-3950](https://issues.apache.org/jira/browse/THRIFT-3950) - Memory leak while calling oneway method +- [THRIFT-3143](https://issues.apache.org/jira/browse/THRIFT-3143) - add typescript directory support +- [THRIFT-4564](https://issues.apache.org/jira/browse/THRIFT-4564) - TBufferedTransport can leave corrupt data in the buffer +- [THRIFT-4647](https://issues.apache.org/jira/browse/THRIFT-4647) - Node.js Fileserver webroot path +- [THRIFT-4489](https://issues.apache.org/jira/browse/THRIFT-4489) - Unix domain socket support for NodeJS client +- [THRIFT-4443](https://issues.apache.org/jira/browse/THRIFT-4443) - node.js json_protocol throws error in skip function +- [THRIFT-4604](https://issues.apache.org/jira/browse/THRIFT-4604) - NodeJS: Expose Int64 from browser.js for consumption by browser +- [THRIFT-4480](https://issues.apache.org/jira/browse/THRIFT-4480) - NodeJS warning on binary_protocol writeMessageEnd when seqid = 0 + +### perl +- [THRIFT-4382](https://issues.apache.org/jira/browse/THRIFT-4382) - Replace the use of Perl Indirect Object Syntax calls to new() +- [THRIFT-4471](https://issues.apache.org/jira/browse/THRIFT-4471) - Thrift CPAN release is missing Makefile.PL and the clients are unable to build the module +- [THRIFT-4416](https://issues.apache.org/jira/browse/THRIFT-4416) - Perl CPAN Packaging Improvements + +### php +- [THRIFT-4474](https://issues.apache.org/jira/browse/THRIFT-4474) - PHP generator use PSR-4 default +- [THRIFT-4463](https://issues.apache.org/jira/browse/THRIFT-4463) - PHP generated code match PSR-2 +- [THRIFT-4373](https://issues.apache.org/jira/browse/THRIFT-4373) - Extending Thrift class results in "Attempt serialize from non-Thrift object" +- [THRIFT-4354](https://issues.apache.org/jira/browse/THRIFT-4354) - TSocket block on read +- [THRIFT-4423](https://issues.apache.org/jira/browse/THRIFT-4423) - migrate php library to psr-4 +- [THRIFT-4656](https://issues.apache.org/jira/browse/THRIFT-4656) - infinite loop in latest PHP library +- [THRIFT-4477](https://issues.apache.org/jira/browse/THRIFT-4477) - TBufferedTransport must have underlying transport +- [THRIFT-4475](https://issues.apache.org/jira/browse/THRIFT-4475) - lib/php/test should be checked for PSR-2 +- [THRIFT-4498](https://issues.apache.org/jira/browse/THRIFT-4498) - add phpcs back +- [THRIFT-4460](https://issues.apache.org/jira/browse/THRIFT-4460) - php library use PSR-2 +- [THRIFT-4641](https://issues.apache.org/jira/browse/THRIFT-4641) - TCurlClient doesn't check for HTTP status code +- [THRIFT-4645](https://issues.apache.org/jira/browse/THRIFT-4645) - TCurlClient: show actual error message when throwing TTransportException +- [THRIFT-4674](https://issues.apache.org/jira/browse/THRIFT-4674) - Add stream context support into PHP/THttpClient +- [THRIFT-4459](https://issues.apache.org/jira/browse/THRIFT-4459) - reduce php library directory depth + +### python +- [THRIFT-4670](https://issues.apache.org/jira/browse/THRIFT-4670) - Twisted, slots, and void method fails with "object has no attribute 'success'" +- [THRIFT-4464](https://issues.apache.org/jira/browse/THRIFT-4464) - Potentially server-crashing typo in Python TNonblockingServer +- [THRIFT-4548](https://issues.apache.org/jira/browse/THRIFT-4548) - Supporting TBinaryProtocolAccelerated protocol when using TMultiplexedProcessor in Python +- [THRIFT-4577](https://issues.apache.org/jira/browse/THRIFT-4577) - Outdated cipher string in python unit test +- [THRIFT-4505](https://issues.apache.org/jira/browse/THRIFT-4505) - python build on Vagrant Windows boxes fails +- [THRIFT-4621](https://issues.apache.org/jira/browse/THRIFT-4621) - THeader for Python +- [THRIFT-4668](https://issues.apache.org/jira/browse/THRIFT-4668) - make socket backlog configurable for python +- [THRIFT-4561](https://issues.apache.org/jira/browse/THRIFT-4561) - Python: cleanup socket timeout settings + +### ruby +- [THRIFT-4289](https://issues.apache.org/jira/browse/THRIFT-4289) - Thrift RSpec test suite fails with Ruby 2.4.x due to Fixnum deprecation +- [THRIFT-4342](https://issues.apache.org/jira/browse/THRIFT-4342) - Support ruby rspec 3 +- [THRIFT-4525](https://issues.apache.org/jira/browse/THRIFT-4525) - Add ssl socket option to ruby cross tests +- [THRIFT-4450](https://issues.apache.org/jira/browse/THRIFT-4450) - Add seek support to TCompactInputProtocol in Rust +- [THRIFT-4631](https://issues.apache.org/jira/browse/THRIFT-4631) - Codegen Creates Invalid Ruby for Recursive Structs +- [THRIFT-4472](https://issues.apache.org/jira/browse/THRIFT-4472) - Fix the genspec for ruby so it does not complain about an invalid license + +### rust +- [THRIFT-4662](https://issues.apache.org/jira/browse/THRIFT-4662) - Rust const string calls function at compile time +- [THRIFT-4661](https://issues.apache.org/jira/browse/THRIFT-4661) - Rust enum name wrong case in generated structs +- [THRIFT-4617](https://issues.apache.org/jira/browse/THRIFT-4617) - Avoid generating conflicting struct names in Rust code +- [THRIFT-4529](https://issues.apache.org/jira/browse/THRIFT-4529) - Rust generation should include #![allow(non_snake_case)] or force conform to Rust style guidelines +- [THRIFT-4390](https://issues.apache.org/jira/browse/THRIFT-4390) - Rust binary protocol and buffered transport cannot handle writes above 4096 bytes +- [THRIFT-4419](https://issues.apache.org/jira/browse/THRIFT-4419) - Rust framed transport cannot handle writes above 4096 bytes +- [THRIFT-4658](https://issues.apache.org/jira/browse/THRIFT-4658) - Rust's TBinaryInputProtocol fails when strict is false +- [THRIFT-4187](https://issues.apache.org/jira/browse/THRIFT-4187) - Dart -> Rust Framed cross tests fail +- [THRIFT-4664](https://issues.apache.org/jira/browse/THRIFT-4664) - Rust cannot create ReadHalf/WriteHalf to implement custom tranports +- [THRIFT-4665](https://issues.apache.org/jira/browse/THRIFT-4665) - Keep Rust library up-to-date on crates.io + +### swift (new language support in 0.12.0) +- [THRIFT-3773](https://issues.apache.org/jira/browse/THRIFT-3773) - Swift Library + +### test suite +- [THRIFT-4515](https://issues.apache.org/jira/browse/THRIFT-4515) - Gracefully shutdown cross-test servers to fully test teardown +- [THRIFT-4085](https://issues.apache.org/jira/browse/THRIFT-4085) - Add .NET Core to the make cross standard test suite +- [THRIFT-4358](https://issues.apache.org/jira/browse/THRIFT-4358) - Add unix domain sockets in ruby to cross test - code exists + +### typescript (new language support in 0.12.0) +- [THRIFT-3143](https://issues.apache.org/jira/browse/THRIFT-3143) - add typescript directory support + +## 0.11.0 + +Released 2017-DEC-27 + +### Sub-task +- [THRIFT-2733](https://issues.apache.org/jira/browse/THRIFT-2733) - Erlang coding standards +- [THRIFT-2740](https://issues.apache.org/jira/browse/THRIFT-2740) - Perl coding standards +- [THRIFT-3610](https://issues.apache.org/jira/browse/THRIFT-3610) - Streamline exception handling in Python server handler +- [THRIFT-3686](https://issues.apache.org/jira/browse/THRIFT-3686) - Java processor should report internal error on uncaught exception +- [THRIFT-4049](https://issues.apache.org/jira/browse/THRIFT-4049) - Skip() should throw TProtocolException.INVALID_DATA on unknown data types +- [THRIFT-4053](https://issues.apache.org/jira/browse/THRIFT-4053) - Skip() should throw TProtocolException.INVALID_DATA on unknown data types +- [THRIFT-4136](https://issues.apache.org/jira/browse/THRIFT-4136) - Align is_binary() method with is_string() to simplify those checks +- [THRIFT-4137](https://issues.apache.org/jira/browse/THRIFT-4137) - Fix remaining undefined behavior invalid vptr casts in Thrift Compiler +- [THRIFT-4138](https://issues.apache.org/jira/browse/THRIFT-4138) - Fix remaining undefined behavior invalid vptr casts in C++ library +- [THRIFT-4296](https://issues.apache.org/jira/browse/THRIFT-4296) - Fix Ubuntu Xenial build environment for the python language +- [THRIFT-4298](https://issues.apache.org/jira/browse/THRIFT-4298) - Fix Ubuntu Xenial build environment for the go 1.6 language +- [THRIFT-4299](https://issues.apache.org/jira/browse/THRIFT-4299) - Fix Ubuntu Xenial build environment for the D language +- [THRIFT-4300](https://issues.apache.org/jira/browse/THRIFT-4300) - Fix make cross in Ubuntu Xenial docker environment, once all language support issues are fixed +- [THRIFT-4302](https://issues.apache.org/jira/browse/THRIFT-4302) - Fix Ubuntu Xenial make cross testing for lua and php7 +- [THRIFT-4398](https://issues.apache.org/jira/browse/THRIFT-4398) - Update EXTRA_DIST for "make dist" + +### Bug +- [THRIFT-381](https://issues.apache.org/jira/browse/THRIFT-381) - Fail fast if configure detects C++ problems +- [THRIFT-1677](https://issues.apache.org/jira/browse/THRIFT-1677) - MinGW support broken +- [THRIFT-1805](https://issues.apache.org/jira/browse/THRIFT-1805) - Thrift should not swallow ALL exceptions +- [THRIFT-2026](https://issues.apache.org/jira/browse/THRIFT-2026) - Fix TCompactProtocol 64 bit builds +- [THRIFT-2642](https://issues.apache.org/jira/browse/THRIFT-2642) - Recursive structs don't work in python +- [THRIFT-2889](https://issues.apache.org/jira/browse/THRIFT-2889) - stable release 0.9.2, erlang tutorial broken +- [THRIFT-2913](https://issues.apache.org/jira/browse/THRIFT-2913) - Ruby Server Thrift::ThreadPoolServer should serve inside a thread +- [THRIFT-2998](https://issues.apache.org/jira/browse/THRIFT-2998) - Node.js: Missing header from http request +- [THRIFT-3000](https://issues.apache.org/jira/browse/THRIFT-3000) - .NET implementation has trouble with mixed IP modes +- [THRIFT-3281](https://issues.apache.org/jira/browse/THRIFT-3281) - Travis CI build passed but the log says BUILD FAILED +- [THRIFT-3358](https://issues.apache.org/jira/browse/THRIFT-3358) - Makefile:1362: *** missing separator. Stop. +- [THRIFT-3600](https://issues.apache.org/jira/browse/THRIFT-3600) - Make TTwisted server send exception on unexpected handler error +- [THRIFT-3602](https://issues.apache.org/jira/browse/THRIFT-3602) - Make Tornado server send exception on unexpected handler error +- [THRIFT-3657](https://issues.apache.org/jira/browse/THRIFT-3657) - D TFileWriterTransport close should use non-priority send +- [THRIFT-3700](https://issues.apache.org/jira/browse/THRIFT-3700) - Go Map has wrong default value when optional +- [THRIFT-3703](https://issues.apache.org/jira/browse/THRIFT-3703) - Unions Field Count Does Not Consider Map/Set/List Fields +- [THRIFT-3730](https://issues.apache.org/jira/browse/THRIFT-3730) - server log error twice +- [THRIFT-3778](https://issues.apache.org/jira/browse/THRIFT-3778) - go client can not pass method parameter to server of other language if no field_id is given +- [THRIFT-3784](https://issues.apache.org/jira/browse/THRIFT-3784) - thrift-maven-plugin generates invalid include directories for IDL in dependency JARs +- [THRIFT-3801](https://issues.apache.org/jira/browse/THRIFT-3801) - Node Thrift client throws exception with multiplexer and responses that are bigger than a single buffer +- [THRIFT-3821](https://issues.apache.org/jira/browse/THRIFT-3821) - TMemoryBuffer buffer may overflow when resizing +- [THRIFT-3832](https://issues.apache.org/jira/browse/THRIFT-3832) - Thrift version 0.9.3 example on Windows, Visual Studio, linking errors during compiling +- [THRIFT-3847](https://issues.apache.org/jira/browse/THRIFT-3847) - thrift/config.h includes a #define for VERSION which will likely conflict with existing user environment or code +- [THRIFT-3873](https://issues.apache.org/jira/browse/THRIFT-3873) - Fix various build warnings when using Visual Studio +- [THRIFT-3891](https://issues.apache.org/jira/browse/THRIFT-3891) - TNonblockingServer configured with more than one IO threads does not always return from serve() upon stop() +- [THRIFT-3892](https://issues.apache.org/jira/browse/THRIFT-3892) - Thrift uses TLS SNI extension provided by OpenSSL library. Older version of OpenSSL(< 0.9.8f) may create problem because they do not support 'SSL_set_tlsext_host_name()'. +- [THRIFT-3895](https://issues.apache.org/jira/browse/THRIFT-3895) - Build fails using Java 1.8 with Ant < 1.9 +- [THRIFT-3896](https://issues.apache.org/jira/browse/THRIFT-3896) - map data with number string key cannot access that deserialized by php extension +- [THRIFT-3938](https://issues.apache.org/jira/browse/THRIFT-3938) - Python TNonblockingServer does not work with SSL +- [THRIFT-3944](https://issues.apache.org/jira/browse/THRIFT-3944) - TSSLSocket has dead code in checkHandshake +- [THRIFT-3946](https://issues.apache.org/jira/browse/THRIFT-3946) - Java 1.5 compatibility broken for binary fields (java5 option) +- [THRIFT-3960](https://issues.apache.org/jira/browse/THRIFT-3960) - Inherited services in Lua generator are not named correctly +- [THRIFT-3962](https://issues.apache.org/jira/browse/THRIFT-3962) - Ant build.xml broken on Windows for Java library +- [THRIFT-3963](https://issues.apache.org/jira/browse/THRIFT-3963) - Thrift.cabal filename does not match module name +- [THRIFT-3967](https://issues.apache.org/jira/browse/THRIFT-3967) - gobject/gparam.h:166:33: warning: enumerator value for ‘G_PARAM_DEPRECATED’ is not an integer constant expression +- [THRIFT-3968](https://issues.apache.org/jira/browse/THRIFT-3968) - Deserializing empty string/binary fields +- [THRIFT-3974](https://issues.apache.org/jira/browse/THRIFT-3974) - Using clang-3.8 and ThreadSanitizer on the concurrency_test claims bad PThread behavior +- [THRIFT-3984](https://issues.apache.org/jira/browse/THRIFT-3984) - PHP7 extension causes segfault +- [THRIFT-4008](https://issues.apache.org/jira/browse/THRIFT-4008) - broken ci due to upstream dependency versioning break +- [THRIFT-4009](https://issues.apache.org/jira/browse/THRIFT-4009) - Use @implementer instead of implements in TTwisted.py +- [THRIFT-4010](https://issues.apache.org/jira/browse/THRIFT-4010) - Q.fcall messing up with *this* pointer inside called function +- [THRIFT-4011](https://issues.apache.org/jira/browse/THRIFT-4011) - Sets of Thrift structs generate Go code that can't be serialized to JSON +- [THRIFT-4012](https://issues.apache.org/jira/browse/THRIFT-4012) - Python Twisted implementation uses implements, not compatible with Py3 +- [THRIFT-4014](https://issues.apache.org/jira/browse/THRIFT-4014) - align C# meta data in AssemblyInfo.cs +- [THRIFT-4015](https://issues.apache.org/jira/browse/THRIFT-4015) - Fix wrongly spelled "Thirft"s +- [THRIFT-4016](https://issues.apache.org/jira/browse/THRIFT-4016) - testInsanity() impl does not conform to test spec in ThriftTest.thrift +- [THRIFT-4023](https://issues.apache.org/jira/browse/THRIFT-4023) - Skip unexpected field types on read/write +- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types +- [THRIFT-4026](https://issues.apache.org/jira/browse/THRIFT-4026) - TSSLSocket doesn't work with Python < 2.7.9 +- [THRIFT-4029](https://issues.apache.org/jira/browse/THRIFT-4029) - Accelerated protocols do not build from thrift-py 0.10.0 on PyPI +- [THRIFT-4031](https://issues.apache.org/jira/browse/THRIFT-4031) - Go plugin generates invalid code for lists of typedef'ed built-in types +- [THRIFT-4033](https://issues.apache.org/jira/browse/THRIFT-4033) - Default build WITH_PLUGIN=ON for all builds results in packaging errors +- [THRIFT-4034](https://issues.apache.org/jira/browse/THRIFT-4034) - CMake doesn't work to build compiler on MacOS +- [THRIFT-4036](https://issues.apache.org/jira/browse/THRIFT-4036) - Add .NET Core environment/build support to the docker image +- [THRIFT-4038](https://issues.apache.org/jira/browse/THRIFT-4038) - socket check: checking an unsigned number against >= 0 never fails +- [THRIFT-4042](https://issues.apache.org/jira/browse/THRIFT-4042) - ExtractionError when using accelerated thrift in a multiprocess test +- [THRIFT-4043](https://issues.apache.org/jira/browse/THRIFT-4043) - thrift perl debian package is placing files in the wrong place +- [THRIFT-4044](https://issues.apache.org/jira/browse/THRIFT-4044) - Build job 17 failing on every pull request; hspec core (haskell) 2.4 issue +- [THRIFT-4046](https://issues.apache.org/jira/browse/THRIFT-4046) - MinGW with gcc 6.2 does not compile on Windows +- [THRIFT-4060](https://issues.apache.org/jira/browse/THRIFT-4060) - Thrift printTo ostream overload mechanism breaks down when types are nested +- [THRIFT-4062](https://issues.apache.org/jira/browse/THRIFT-4062) - Remove debug print from TServiceClient +- [THRIFT-4065](https://issues.apache.org/jira/browse/THRIFT-4065) - Document Perl ForkingServer signal restriction imposed by THRIFT-3848 and remove unnecessary code +- [THRIFT-4068](https://issues.apache.org/jira/browse/THRIFT-4068) - A code comment in Java ServerSocket is wrong around accept() +- [THRIFT-4073](https://issues.apache.org/jira/browse/THRIFT-4073) - enum files are still being generated with unused imports +- [THRIFT-4076](https://issues.apache.org/jira/browse/THRIFT-4076) - Appveyor builds failing because ant 1.9.8 was removed from apache servers +- [THRIFT-4077](https://issues.apache.org/jira/browse/THRIFT-4077) - AI_ADDRCONFIG redefined after recent change to PlatformSocket header +- [THRIFT-4079](https://issues.apache.org/jira/browse/THRIFT-4079) - Generated perl code that returns structures from included thrift files is missing a necessary use clause +- [THRIFT-4087](https://issues.apache.org/jira/browse/THRIFT-4087) - Spurious exception destroying TThreadedServer because of incorrect join() call +- [THRIFT-4102](https://issues.apache.org/jira/browse/THRIFT-4102) - TBufferedTransport performance issue since 0.10.0 +- [THRIFT-4106](https://issues.apache.org/jira/browse/THRIFT-4106) - concurrency_test fails randomly +- [THRIFT-4108](https://issues.apache.org/jira/browse/THRIFT-4108) - c_glib thrift ssl has multiple bugs and deprecated functions +- [THRIFT-4109](https://issues.apache.org/jira/browse/THRIFT-4109) - Configure Script uses string comparison for versions +- [THRIFT-4129](https://issues.apache.org/jira/browse/THRIFT-4129) - C++ TNonblockingServer fd leak when failing to dispatch new connections +- [THRIFT-4131](https://issues.apache.org/jira/browse/THRIFT-4131) - Javascript with WebSocket handles oneway methods wrong +- [THRIFT-4134](https://issues.apache.org/jira/browse/THRIFT-4134) - Fix remaining undefined behavior invalid vptr casts +- [THRIFT-4140](https://issues.apache.org/jira/browse/THRIFT-4140) - Use of non-thread-safe function gmtime() +- [THRIFT-4141](https://issues.apache.org/jira/browse/THRIFT-4141) - Installation of haxe in docker files refers to a redirect link and fails +- [THRIFT-4147](https://issues.apache.org/jira/browse/THRIFT-4147) - Rust: protocol should accept transports with non-static lifetime +- [THRIFT-4148](https://issues.apache.org/jira/browse/THRIFT-4148) - [maven-thrift-plugin] compile error while import a thrift in dependency jar file. +- [THRIFT-4149](https://issues.apache.org/jira/browse/THRIFT-4149) - System.out pollutes log files +- [THRIFT-4154](https://issues.apache.org/jira/browse/THRIFT-4154) - PHP close() of a TSocket needs to close any type of socket +- [THRIFT-4158](https://issues.apache.org/jira/browse/THRIFT-4158) - minor issue in README-MSYS2.md +- [THRIFT-4159](https://issues.apache.org/jira/browse/THRIFT-4159) - Building tests fails on MSYS2 (MinGW64) due to a (small?) linker error +- [THRIFT-4160](https://issues.apache.org/jira/browse/THRIFT-4160) - TNonblocking server fix use of closed/freed connections +- [THRIFT-4161](https://issues.apache.org/jira/browse/THRIFT-4161) - TNonBlocking server using uninitialized event in error paths +- [THRIFT-4162](https://issues.apache.org/jira/browse/THRIFT-4162) - TNonBlocking handling of TSockets in error state is incorrect after fd is closed +- [THRIFT-4164](https://issues.apache.org/jira/browse/THRIFT-4164) - Core in TSSLSocket cleanupOpenSSL when destroying a mutex used by openssl +- [THRIFT-4165](https://issues.apache.org/jira/browse/THRIFT-4165) - C++ build has many warnings under c++03 due to recent changes, cmake needs better platform-independent language level control +- [THRIFT-4166](https://issues.apache.org/jira/browse/THRIFT-4166) - Recent fix to remove boost::lexical_cast usage broke VS2010 +- [THRIFT-4167](https://issues.apache.org/jira/browse/THRIFT-4167) - Missing compile flag +- [THRIFT-4170](https://issues.apache.org/jira/browse/THRIFT-4170) - Support lua 5.1 or earlier properly for object length determination +- [THRIFT-4172](https://issues.apache.org/jira/browse/THRIFT-4172) - node.js tutorial client does not import assert, connection issues are not handled properly +- [THRIFT-4177](https://issues.apache.org/jira/browse/THRIFT-4177) - Java compiler produces deep copy constructor that could make shallow copy instead +- [THRIFT-4184](https://issues.apache.org/jira/browse/THRIFT-4184) - Building on Appveyor: invalid escape sequence \L +- [THRIFT-4185](https://issues.apache.org/jira/browse/THRIFT-4185) - fb303 counter encoding fix +- [THRIFT-4189](https://issues.apache.org/jira/browse/THRIFT-4189) - Framed/buffered transport Dispose() does not dispose the nested transport +- [THRIFT-4193](https://issues.apache.org/jira/browse/THRIFT-4193) - Lower the default maxReadBufferBytes for non-blocking servers +- [THRIFT-4195](https://issues.apache.org/jira/browse/THRIFT-4195) - Compilation to GO produces broken code +- [THRIFT-4196](https://issues.apache.org/jira/browse/THRIFT-4196) - Cannot generate recursive Rust types +- [THRIFT-4204](https://issues.apache.org/jira/browse/THRIFT-4204) - typo in compact spec +- [THRIFT-4206](https://issues.apache.org/jira/browse/THRIFT-4206) - Strings in container fields are not decoded properly with py:dynamic and py:utf8strings +- [THRIFT-4208](https://issues.apache.org/jira/browse/THRIFT-4208) - C# NamedPipesServer not really working in some scenarios +- [THRIFT-4211](https://issues.apache.org/jira/browse/THRIFT-4211) - Fix GError glib management under Thrift +- [THRIFT-4212](https://issues.apache.org/jira/browse/THRIFT-4212) - c_glib flush tries to close SSL even if socket is invalid +- [THRIFT-4213](https://issues.apache.org/jira/browse/THRIFT-4213) - Travis build fails at curl -sSL https://www.npmjs.com/install.sh | sh +- [THRIFT-4215](https://issues.apache.org/jira/browse/THRIFT-4215) - Golang TTransportFactory Pattern Squelches Errors +- [THRIFT-4216](https://issues.apache.org/jira/browse/THRIFT-4216) - Golang Http Clients Do Not Respect User Options +- [THRIFT-4218](https://issues.apache.org/jira/browse/THRIFT-4218) - Set TCP_NODELAY for PHP client socket +- [THRIFT-4219](https://issues.apache.org/jira/browse/THRIFT-4219) - Golang HTTP clients created with Nil buffer +- [THRIFT-4231](https://issues.apache.org/jira/browse/THRIFT-4231) - TJSONProtocol throws unexpected non-Thrift-exception on null strings +- [THRIFT-4232](https://issues.apache.org/jira/browse/THRIFT-4232) - ./configure does bad ant version check +- [THRIFT-4234](https://issues.apache.org/jira/browse/THRIFT-4234) - Travis build fails cross language tests with "Unsupported security protocol type" +- [THRIFT-4237](https://issues.apache.org/jira/browse/THRIFT-4237) - Go TServerSocket Race Conditions +- [THRIFT-4240](https://issues.apache.org/jira/browse/THRIFT-4240) - Go TSimpleServer does not close properly +- [THRIFT-4243](https://issues.apache.org/jira/browse/THRIFT-4243) - Go TSimpleServer race on wait in Stop() method +- [THRIFT-4245](https://issues.apache.org/jira/browse/THRIFT-4245) - Golang TFramedTransport's writeBuffer increases if writes to transport failed +- [THRIFT-4246](https://issues.apache.org/jira/browse/THRIFT-4246) - Sequence number mismatch on multiplexed clients +- [THRIFT-4247](https://issues.apache.org/jira/browse/THRIFT-4247) - Compile fails with openssl 1.1 +- [THRIFT-4248](https://issues.apache.org/jira/browse/THRIFT-4248) - Compile fails - strncpy, memcmp, memset not declared in src/thrift/transport/TSSLSocket.cpp +- [THRIFT-4251](https://issues.apache.org/jira/browse/THRIFT-4251) - Java Epoll Selector Bug +- [THRIFT-4257](https://issues.apache.org/jira/browse/THRIFT-4257) - Typescript async callbacks do not provide the correct types +- [THRIFT-4258](https://issues.apache.org/jira/browse/THRIFT-4258) - Boost/std thread wrapping faultiness +- [THRIFT-4260](https://issues.apache.org/jira/browse/THRIFT-4260) - Go context generation issue. Context is parameter in Interface not in implementation +- [THRIFT-4261](https://issues.apache.org/jira/browse/THRIFT-4261) - Go context generation issue: breaking change in generated code regarding thrift.TProcessorFunction interface +- [THRIFT-4262](https://issues.apache.org/jira/browse/THRIFT-4262) - Invalid binding to InterlockedCompareExchange64() with 64-bit targets +- [THRIFT-4263](https://issues.apache.org/jira/browse/THRIFT-4263) - Fix use after free bug for thrown exceptions +- [THRIFT-4266](https://issues.apache.org/jira/browse/THRIFT-4266) - Erlang library throws during skipping fields of composite type (maps, lists, structs, sets) +- [THRIFT-4268](https://issues.apache.org/jira/browse/THRIFT-4268) - Erlang library emits debugging output in transport layer +- [THRIFT-4273](https://issues.apache.org/jira/browse/THRIFT-4273) - erlang:now/0: Deprecated BIF. +- [THRIFT-4274](https://issues.apache.org/jira/browse/THRIFT-4274) - Python feature tests for SSL/TLS failing +- [THRIFT-4279](https://issues.apache.org/jira/browse/THRIFT-4279) - Wrong path in include directive in generated Thrift sources +- [THRIFT-4283](https://issues.apache.org/jira/browse/THRIFT-4283) - TNamedPipeServer race condition in interrupt +- [THRIFT-4284](https://issues.apache.org/jira/browse/THRIFT-4284) - File contains a NBSP: lib/nodejs/lib/thrift/web_server.js +- [THRIFT-4290](https://issues.apache.org/jira/browse/THRIFT-4290) - C# nullable option generates invalid code for non-required enum field with default value +- [THRIFT-4292](https://issues.apache.org/jira/browse/THRIFT-4292) - TimerManager::remove() is not implemented +- [THRIFT-4307](https://issues.apache.org/jira/browse/THRIFT-4307) - Make ssl-open timeout effective in golang client +- [THRIFT-4312](https://issues.apache.org/jira/browse/THRIFT-4312) - Erlang client cannot connect to Python server: exception error: econnrefused +- [THRIFT-4313](https://issues.apache.org/jira/browse/THRIFT-4313) - Program code of the Erlang tutorial files contain syntax errors +- [THRIFT-4316](https://issues.apache.org/jira/browse/THRIFT-4316) - TByteBuffer.java will read too much data if a previous read returns fewer bytes than requested +- [THRIFT-4319](https://issues.apache.org/jira/browse/THRIFT-4319) - command line switch for "evhttp" incorrectly resolved to anon pipes +- [THRIFT-4323](https://issues.apache.org/jira/browse/THRIFT-4323) - range check errors or NPE in edge cases +- [THRIFT-4324](https://issues.apache.org/jira/browse/THRIFT-4324) - field names can conflict with local vars in generated code +- [THRIFT-4328](https://issues.apache.org/jira/browse/THRIFT-4328) - Travis CI builds are timing out (job 1) and haxe builds are failing since 9/11 +- [THRIFT-4329](https://issues.apache.org/jira/browse/THRIFT-4329) - c_glib Doesn't have a multiplexed processor +- [THRIFT-4331](https://issues.apache.org/jira/browse/THRIFT-4331) - C++: TSSLSockets bug in handling huge messages, bug in handling polling +- [THRIFT-4332](https://issues.apache.org/jira/browse/THRIFT-4332) - Binary protocol has memory leaks +- [THRIFT-4334](https://issues.apache.org/jira/browse/THRIFT-4334) - Perl indentation incorrect when defaulting field attribute to a struct +- [THRIFT-4339](https://issues.apache.org/jira/browse/THRIFT-4339) - Thrift Framed Transport in Erlang crashes server when client disconnects +- [THRIFT-4340](https://issues.apache.org/jira/browse/THRIFT-4340) - Erlang fix a crash on client close +- [THRIFT-4355](https://issues.apache.org/jira/browse/THRIFT-4355) - Javascript indentation incorrect when defaulting field attribute to a struct +- [THRIFT-4356](https://issues.apache.org/jira/browse/THRIFT-4356) - thrift_protocol call Transport cause Segmentation fault +- [THRIFT-4359](https://issues.apache.org/jira/browse/THRIFT-4359) - Haxe compiler looks like it is producing incorrect code for map or set key that is binary type +- [THRIFT-4362](https://issues.apache.org/jira/browse/THRIFT-4362) - Missing size-check can lead to huge memory allocation +- [THRIFT-4364](https://issues.apache.org/jira/browse/THRIFT-4364) - Website contributing guide erroneously recommends submitting patches in JIRA +- [THRIFT-4365](https://issues.apache.org/jira/browse/THRIFT-4365) - Perl generated code uses indirect object syntax, which occasionally causes compilation errors. +- [THRIFT-4367](https://issues.apache.org/jira/browse/THRIFT-4367) - python TProcessor.process is missing "self" +- [THRIFT-4370](https://issues.apache.org/jira/browse/THRIFT-4370) - Ubuntu Artful cppcheck and flake8 are more stringent and causing SCA build job failures +- [THRIFT-4372](https://issues.apache.org/jira/browse/THRIFT-4372) - Pipe write operations across a network are limited to 65,535 bytes per write. +- [THRIFT-4374](https://issues.apache.org/jira/browse/THRIFT-4374) - cannot load thrift_protocol due to undefined symbol: _ZTVN10__cxxabiv120__si_class_type_infoE +- [THRIFT-4375](https://issues.apache.org/jira/browse/THRIFT-4375) - TMemory throw bad_alloc due to counter overflow +- [THRIFT-4376](https://issues.apache.org/jira/browse/THRIFT-4376) - Coverity high impact issue resolution +- [THRIFT-4377](https://issues.apache.org/jira/browse/THRIFT-4377) - haxe. socket handles leak in TSimpleServer +- [THRIFT-4381](https://issues.apache.org/jira/browse/THRIFT-4381) - Wrong isset bitfield value after transmission +- [THRIFT-4385](https://issues.apache.org/jira/browse/THRIFT-4385) - Go remote client -u flag is broken +- [THRIFT-4392](https://issues.apache.org/jira/browse/THRIFT-4392) - compiler/..../plugin.thrift structs mis-ordered blows up ocaml generator +- [THRIFT-4395](https://issues.apache.org/jira/browse/THRIFT-4395) - Unable to build in the ubuntu-xenial docker image: clap 2.28 requires Rust 1.20 +- [THRIFT-4396](https://issues.apache.org/jira/browse/THRIFT-4396) - inconsistent (or plain wrong) version numbers in master/trunk + +### Documentation +- [THRIFT-4157](https://issues.apache.org/jira/browse/THRIFT-4157) - outdated readme about Haxe installation on Linux + +### Improvement +- [THRIFT-105](https://issues.apache.org/jira/browse/THRIFT-105) - make a thrift_spec for a structures with negative tags +- [THRIFT-281](https://issues.apache.org/jira/browse/THRIFT-281) - Cocoa library code needs comments, badly +- [THRIFT-775](https://issues.apache.org/jira/browse/THRIFT-775) - performance improvements for Perl +- [THRIFT-2221](https://issues.apache.org/jira/browse/THRIFT-2221) - Generate c++ code with std::shared_ptr instead of boost::shared_ptr. +- [THRIFT-2364](https://issues.apache.org/jira/browse/THRIFT-2364) - OCaml: Use Oasis exclusively for build process +- [THRIFT-2504](https://issues.apache.org/jira/browse/THRIFT-2504) - TMultiplexedProcessor should allow registering default processor called if no service name is present +- [THRIFT-3207](https://issues.apache.org/jira/browse/THRIFT-3207) - Enable build with OpenSSL 1.1.0 series +- [THRIFT-3272](https://issues.apache.org/jira/browse/THRIFT-3272) - Perl SSL Authentication Support +- [THRIFT-3357](https://issues.apache.org/jira/browse/THRIFT-3357) - Generate EnumSet/EnumMap where elements/keys are enums +- [THRIFT-3369](https://issues.apache.org/jira/browse/THRIFT-3369) - Implement SSL/TLS support on C with c_glib +- [THRIFT-3467](https://issues.apache.org/jira/browse/THRIFT-3467) - Go Maps for Thrift Sets Should Have Values of Type struct{} +- [THRIFT-3580](https://issues.apache.org/jira/browse/THRIFT-3580) - THeader for Haskell +- [THRIFT-3627](https://issues.apache.org/jira/browse/THRIFT-3627) - Missing basic code style consistency of JavaScript. +- [THRIFT-3706](https://issues.apache.org/jira/browse/THRIFT-3706) - There's no support for Multiplexed protocol on c_glib library +- [THRIFT-3766](https://issues.apache.org/jira/browse/THRIFT-3766) - Add getUnderlyingTransport() to TZlibTransport +- [THRIFT-3776](https://issues.apache.org/jira/browse/THRIFT-3776) - Go code from multiple thrift files with the same namespace +- [THRIFT-3823](https://issues.apache.org/jira/browse/THRIFT-3823) - Escape documentation while generating non escaped documetation +- [THRIFT-3854](https://issues.apache.org/jira/browse/THRIFT-3854) - allow users to clear read buffers +- [THRIFT-3859](https://issues.apache.org/jira/browse/THRIFT-3859) - Unix Domain Socket Support in Objective-C +- [THRIFT-3921](https://issues.apache.org/jira/browse/THRIFT-3921) - C++ code should print enums as strings +- [THRIFT-3926](https://issues.apache.org/jira/browse/THRIFT-3926) - There should be an error emitted when http status code is not 200 +- [THRIFT-4007](https://issues.apache.org/jira/browse/THRIFT-4007) - Micro-optimization of TTransport.py +- [THRIFT-4040](https://issues.apache.org/jira/browse/THRIFT-4040) - Add real cause of TNonblockingServerSocket error to exception +- [THRIFT-4064](https://issues.apache.org/jira/browse/THRIFT-4064) - Update node library dependencies +- [THRIFT-4069](https://issues.apache.org/jira/browse/THRIFT-4069) - All perl packages should have proper namespace, version syntax, and use proper thrift exceptions +- [THRIFT-4071](https://issues.apache.org/jira/browse/THRIFT-4071) - Consolidate the Travis CI jobs where possible to put less stress on the Apache Foundation's allocation of CI build slaves +- [THRIFT-4072](https://issues.apache.org/jira/browse/THRIFT-4072) - Add the possibility to send custom headers in TCurlClient +- [THRIFT-4075](https://issues.apache.org/jira/browse/THRIFT-4075) - Better MinGW support for headers-only boost (without thread library) +- [THRIFT-4081](https://issues.apache.org/jira/browse/THRIFT-4081) - Provide a MinGW 64-bit Appveyor CI build for better pull request validation +- [THRIFT-4084](https://issues.apache.org/jira/browse/THRIFT-4084) - Improve SSL security in thrift by adding a make cross client that checks to make sure SSLv3 protocol cannot be negotiated +- [THRIFT-4095](https://issues.apache.org/jira/browse/THRIFT-4095) - Add multiplexed protocol to Travis CI for make cross +- [THRIFT-4099](https://issues.apache.org/jira/browse/THRIFT-4099) - Auto-derive Hash for generated Rust structs +- [THRIFT-4110](https://issues.apache.org/jira/browse/THRIFT-4110) - The debian build files do not produce a "-dbg" package for debug symbols of libthrift0 +- [THRIFT-4114](https://issues.apache.org/jira/browse/THRIFT-4114) - Space after '///' in doc comments +- [THRIFT-4126](https://issues.apache.org/jira/browse/THRIFT-4126) - Validate objects in php extension +- [THRIFT-4130](https://issues.apache.org/jira/browse/THRIFT-4130) - Ensure Apache Http connection is released back to pool after use +- [THRIFT-4151](https://issues.apache.org/jira/browse/THRIFT-4151) - Thrift Mutex Contention Profiling (pthreads) should be disabled by default +- [THRIFT-4176](https://issues.apache.org/jira/browse/THRIFT-4176) - Implement a threaded and threadpool server type for Rust +- [THRIFT-4183](https://issues.apache.org/jira/browse/THRIFT-4183) - Named pipe client blocks forever on Open() when there is no server at the other end +- [THRIFT-4190](https://issues.apache.org/jira/browse/THRIFT-4190) - improve C# TThreadPoolServer defaults +- [THRIFT-4197](https://issues.apache.org/jira/browse/THRIFT-4197) - Implement transparent gzip compression for HTTP transport +- [THRIFT-4198](https://issues.apache.org/jira/browse/THRIFT-4198) - Ruby should log Thrift internal errors to global logger +- [THRIFT-4203](https://issues.apache.org/jira/browse/THRIFT-4203) - thrift server stop gracefully +- [THRIFT-4205](https://issues.apache.org/jira/browse/THRIFT-4205) - c_glib is not linking against glib + gobject +- [THRIFT-4209](https://issues.apache.org/jira/browse/THRIFT-4209) - warning CS0414 in T[TLS]ServerSocket.cs +- [THRIFT-4210](https://issues.apache.org/jira/browse/THRIFT-4210) - include Thrift.45.csproj into CI runs +- [THRIFT-4217](https://issues.apache.org/jira/browse/THRIFT-4217) - HttpClient should support gzip and deflate +- [THRIFT-4222](https://issues.apache.org/jira/browse/THRIFT-4222) - Support Unix Domain Sockets in Golang TServerSocket +- [THRIFT-4233](https://issues.apache.org/jira/browse/THRIFT-4233) - Make THsHaServer.invoker available (get method only) in inherited classes +- [THRIFT-4236](https://issues.apache.org/jira/browse/THRIFT-4236) - Support context in go generated code. +- [THRIFT-4238](https://issues.apache.org/jira/browse/THRIFT-4238) - JSON generator: make annotation-aware +- [THRIFT-4269](https://issues.apache.org/jira/browse/THRIFT-4269) - Don't append '.' to Erlang namespace if it ends in '_'. +- [THRIFT-4270](https://issues.apache.org/jira/browse/THRIFT-4270) - Generate Erlang mapping functions for const maps and lists +- [THRIFT-4275](https://issues.apache.org/jira/browse/THRIFT-4275) - Add support for zope.interface only, apart from twisted support. +- [THRIFT-4285](https://issues.apache.org/jira/browse/THRIFT-4285) - Pull generated send/recv into library to allow behaviour to be customised +- [THRIFT-4287](https://issues.apache.org/jira/browse/THRIFT-4287) - Add c++ compiler "no_skeleton" flag option +- [THRIFT-4288](https://issues.apache.org/jira/browse/THRIFT-4288) - Implement logging levels properly for node.js +- [THRIFT-4295](https://issues.apache.org/jira/browse/THRIFT-4295) - Refresh the Docker image file suite for Ubuntu, Debian, and CentOS +- [THRIFT-4305](https://issues.apache.org/jira/browse/THRIFT-4305) - Emit ddoc for generated items +- [THRIFT-4306](https://issues.apache.org/jira/browse/THRIFT-4306) - Thrift imports not replicated to D service output +- [THRIFT-4315](https://issues.apache.org/jira/browse/THRIFT-4315) - Add default message for TApplicationException +- [THRIFT-4318](https://issues.apache.org/jira/browse/THRIFT-4318) - Delphi performance improvements +- [THRIFT-4325](https://issues.apache.org/jira/browse/THRIFT-4325) - Simplify automake cross compilation by relying on one global THRIFT compiler path +- [THRIFT-4327](https://issues.apache.org/jira/browse/THRIFT-4327) - Improve TimerManager API to allow removing specific task +- [THRIFT-4330](https://issues.apache.org/jira/browse/THRIFT-4330) - Allow unused crates in Rust files +- [THRIFT-4333](https://issues.apache.org/jira/browse/THRIFT-4333) - Erlang tutorial examples are using a different port (9999) +- [THRIFT-4343](https://issues.apache.org/jira/browse/THRIFT-4343) - Change CI builds to use node.js 8.x LTS once available +- [THRIFT-4345](https://issues.apache.org/jira/browse/THRIFT-4345) - Create a docker build environment that uses the minimum supported language levels +- [THRIFT-4346](https://issues.apache.org/jira/browse/THRIFT-4346) - Allow Zlib transport factory to wrap other transports +- [THRIFT-4348](https://issues.apache.org/jira/browse/THRIFT-4348) - Perl HTTP Client custom HTTP headers +- [THRIFT-4350](https://issues.apache.org/jira/browse/THRIFT-4350) - Update netcore build for dotnet 2.0 sdk and make cross validation +- [THRIFT-4351](https://issues.apache.org/jira/browse/THRIFT-4351) - Use Travis CI Build Stages to optimize the CI build +- [THRIFT-4353](https://issues.apache.org/jira/browse/THRIFT-4353) - cannot read via thrift_protocol at server side +- [THRIFT-4378](https://issues.apache.org/jira/browse/THRIFT-4378) - add set stopTimeoutUnit method to TThreadPoolServer + +### New Feature +- [THRIFT-750](https://issues.apache.org/jira/browse/THRIFT-750) - C++ Compiler Virtual Function Option +- [THRIFT-2945](https://issues.apache.org/jira/browse/THRIFT-2945) - Implement support for Rust language +- [THRIFT-3857](https://issues.apache.org/jira/browse/THRIFT-3857) - thrift js:node complier support an object as parameter not an instance of struct +- [THRIFT-3933](https://issues.apache.org/jira/browse/THRIFT-3933) - Port official C# .NET library for Thrift to C# .NET Core libary +- [THRIFT-4039](https://issues.apache.org/jira/browse/THRIFT-4039) - Update of Apache Thrift .Net Core lib +- [THRIFT-4113](https://issues.apache.org/jira/browse/THRIFT-4113) - Provide a buffer transport for reading/writing in memory byte stream + +### Question +- [THRIFT-2956](https://issues.apache.org/jira/browse/THRIFT-2956) - autoconf - possibly undefined macro - AC_PROG_BISON +- [THRIFT-4223](https://issues.apache.org/jira/browse/THRIFT-4223) - Add support to the isServing() method for the C++ library + +### Task +- [THRIFT-3622](https://issues.apache.org/jira/browse/THRIFT-3622) - Fix deprecated uses of std::auto_ptr +- [THRIFT-4028](https://issues.apache.org/jira/browse/THRIFT-4028) - Please remove System.out.format from the source code +- [THRIFT-4186](https://issues.apache.org/jira/browse/THRIFT-4186) - Build and test rust client in Travis + +### Test +- [THRIFT-4264](https://issues.apache.org/jira/browse/THRIFT-4264) - PHP - Support both shared & static linking of sockets library + +### Wish +- [THRIFT-4344](https://issues.apache.org/jira/browse/THRIFT-4344) - Define and maintain the minimum language level for all languages in one place + +## 0.10.0 + +### Bug +- [THRIFT-1840](https://issues.apache.org/jira/browse/THRIFT-1840) - Thrift Generated Code Causes Global Variable Leaks +- [THRIFT-1828](https://issues.apache.org/jira/browse/THRIFT-1828) - moc_TQTcpServer.cpp was removed from source tree but is in thrift-0.9.0.tar.gz +- [THRIFT-1790](https://issues.apache.org/jira/browse/THRIFT-1790) - cocoa: Duplicate interface definition error +- [THRIFT-1776](https://issues.apache.org/jira/browse/THRIFT-1776) - TPipeServer should implement "listen", so that TServerEventHandler preServe will work right +- [THRIFT-1351](https://issues.apache.org/jira/browse/THRIFT-1351) - Compiler does not care about binary strings +- [THRIFT-1229](https://issues.apache.org/jira/browse/THRIFT-1229) - Python fastbinary.c can not handle unicode as generated python code +- [THRIFT-749](https://issues.apache.org/jira/browse/THRIFT-749) - C++ TBufferedTransports do not flush their buffers on delete +- [THRIFT-747](https://issues.apache.org/jira/browse/THRIFT-747) - C++ TSocket->close calls shutdown breaking forked parent process +- [THRIFT-732](https://issues.apache.org/jira/browse/THRIFT-732) - server exits abnormally when client calls send_xxx function without calling recv_xxx function +- [THRIFT-3942](https://issues.apache.org/jira/browse/THRIFT-3942) - TSSLSocket does not honor send and receive timeouts +- [THRIFT-3941](https://issues.apache.org/jira/browse/THRIFT-3941) - WinXP version of thrift_poll() relies on undefined behavior by passing a destructed variable to select() +- [THRIFT-3940](https://issues.apache.org/jira/browse/THRIFT-3940) - Visual Studio project file for compiler is broken +- [THRIFT-3943](https://issues.apache.org/jira/browse/THRIFT-3943) - Coverity Scan identified some high severity defects +- [THRIFT-3929](https://issues.apache.org/jira/browse/THRIFT-3929) - PHP "nsglobal" Option Results in Syntax Error in Generated Code (Trailing Backslash) +- [THRIFT-3936](https://issues.apache.org/jira/browse/THRIFT-3936) - Cannot compile 0.10.0 development tip with VS2013 and earlier (snprintf, uint32_t) +- [THRIFT-3935](https://issues.apache.org/jira/browse/THRIFT-3935) - Incorrect skipping of map and set +- [THRIFT-3920](https://issues.apache.org/jira/browse/THRIFT-3920) - Ruby: Ensuring that HTTP failures will clear the http transport outbuf var +- [THRIFT-3919](https://issues.apache.org/jira/browse/THRIFT-3919) - C# TTLSServerSocket does not use clientTimeout +- [THRIFT-3917](https://issues.apache.org/jira/browse/THRIFT-3917) - Check backports.ssl_match_hostname module version +- [THRIFT-3909](https://issues.apache.org/jira/browse/THRIFT-3909) - Fix c_glib static lib CMake build +- [THRIFT-3904](https://issues.apache.org/jira/browse/THRIFT-3904) - Typo in node tutorial leads to wrong transport being used +- [THRIFT-3848](https://issues.apache.org/jira/browse/THRIFT-3848) - As an implementer of a perl socket server, I do not want to have to remember to ignore SIGCHLD for it to work properly +- [THRIFT-3844](https://issues.apache.org/jira/browse/THRIFT-3844) - thrift_protocol cannot compile in 7.0.7 +- [THRIFT-3843](https://issues.apache.org/jira/browse/THRIFT-3843) - integer issues with Haxe PHP targets cause ZigZag encoding to fail +- [THRIFT-3842](https://issues.apache.org/jira/browse/THRIFT-3842) - Dart generates incorrect code for a const struct +- [THRIFT-3841](https://issues.apache.org/jira/browse/THRIFT-3841) - dart compact protocol incorrectly serializes/deserialized doubles +- [THRIFT-3708](https://issues.apache.org/jira/browse/THRIFT-3708) - NameError: global name 'TProtocol' is not defined +- [THRIFT-3704](https://issues.apache.org/jira/browse/THRIFT-3704) - "TConnectedClient died: Could not refill buffer" message shown when using HTTP Server +- [THRIFT-3678](https://issues.apache.org/jira/browse/THRIFT-3678) - Fix javadoc errors on JDK 8 +- [THRIFT-3014](https://issues.apache.org/jira/browse/THRIFT-3014) - AppVeyor support +- [THRIFT-2994](https://issues.apache.org/jira/browse/THRIFT-2994) - Node.js TJSONProtocol cannot be used for object serialization. +- [THRIFT-2974](https://issues.apache.org/jira/browse/THRIFT-2974) - writeToParcel throws NPE for optional enum fields +- [THRIFT-2948](https://issues.apache.org/jira/browse/THRIFT-2948) - Python TJSONProtocol doesn't handle structs with binary fields containing invalid unicode. +- [THRIFT-2845](https://issues.apache.org/jira/browse/THRIFT-2845) - ChildService.Plo: No such file or directory +- [THRIFT-3276](https://issues.apache.org/jira/browse/THRIFT-3276) - Binary data does not decode correctly using the TJSONProtocol when the base64 encoded data is padded. +- [THRIFT-3253](https://issues.apache.org/jira/browse/THRIFT-3253) - Using latest version of D gives deprecation notices +- [THRIFT-2883](https://issues.apache.org/jira/browse/THRIFT-2883) - TTwisted.py, during ConnectionLost processing: exceptions.RuntimeError: dictionary changed size during iteration +- [THRIFT-2019](https://issues.apache.org/jira/browse/THRIFT-2019) - Writing on a disconnected socket on Mac causes SIG PIPE +- [THRIFT-2020](https://issues.apache.org/jira/browse/THRIFT-2020) - Thrift library has some empty files that haven't really been deleted +- [THRIFT-2049](https://issues.apache.org/jira/browse/THRIFT-2049) - Go compiler doesn't build on native Windows +- [THRIFT-2024](https://issues.apache.org/jira/browse/THRIFT-2024) - TServer.cpp warns on 64-bit platforms about truncating an rlim_t into an int +- [THRIFT-2023](https://issues.apache.org/jira/browse/THRIFT-2023) - gettimeofday implementation on Windows errors when no time zone is passed in. +- [THRIFT-2022](https://issues.apache.org/jira/browse/THRIFT-2022) - CoB and dense code generation still uses TR1 bind, even though that doesn't work with clang +- [THRIFT-2027](https://issues.apache.org/jira/browse/THRIFT-2027) - Minor 64-bit and NOMINMAX issues in C++ library +- [THRIFT-2156](https://issues.apache.org/jira/browse/THRIFT-2156) - TServerSocket::listen() is throwing exceptions with misleading information +- [THRIFT-2154](https://issues.apache.org/jira/browse/THRIFT-2154) - Missing #deepCopy should return T +- [THRIFT-3157](https://issues.apache.org/jira/browse/THRIFT-3157) - TBase signature should be TBase, F extends TFieldIdEnum> +- [THRIFT-3156](https://issues.apache.org/jira/browse/THRIFT-3156) - Node TLS: server executes processing logic two full times +- [THRIFT-3154](https://issues.apache.org/jira/browse/THRIFT-3154) - tutorial/py.tornado throw EOF exception +- [THRIFT-3063](https://issues.apache.org/jira/browse/THRIFT-3063) - C++ build -Wunused-parameter warnings on processor_test, TransportTest +- [THRIFT-3056](https://issues.apache.org/jira/browse/THRIFT-3056) - Add string/collection length limits for Python protocol readers +- [THRIFT-3237](https://issues.apache.org/jira/browse/THRIFT-3237) - Fix TNamedPipeServer::createNamedPipe memory leak +- [THRIFT-3233](https://issues.apache.org/jira/browse/THRIFT-3233) - Fix C++ ThreadManager::Impl::removeWorker worker join +- [THRIFT-3232](https://issues.apache.org/jira/browse/THRIFT-3232) - Cannot deserialize json messages created with fieldNamesAsString +- [THRIFT-3206](https://issues.apache.org/jira/browse/THRIFT-3206) - Fix Visual Studio build failure due 'pthread_self': identifier not found +- [THRIFT-3200](https://issues.apache.org/jira/browse/THRIFT-3200) - JS and nodejs do not encode JSON protocol binary fields as base64 +- [THRIFT-3199](https://issues.apache.org/jira/browse/THRIFT-3199) - Exception field has basic metadata +- [THRIFT-3182](https://issues.apache.org/jira/browse/THRIFT-3182) - TFramedTransport is in an invalid state after frame size exception +- [THRIFT-2536](https://issues.apache.org/jira/browse/THRIFT-2536) - new TSocket, uninitialised value reported by valgrind +- [THRIFT-2527](https://issues.apache.org/jira/browse/THRIFT-2527) - Apache Thrift IDL Compiler code generated for Node.js should be jshint clean +- [THRIFT-2519](https://issues.apache.org/jira/browse/THRIFT-2519) - "processor" class is not being generated +- [THRIFT-2431](https://issues.apache.org/jira/browse/THRIFT-2431) - TFileTransportTest fails with "check delta < XXX failed" +- [THRIFT-2708](https://issues.apache.org/jira/browse/THRIFT-2708) - Erlang library does not support "oneway" message type +- [THRIFT-3377](https://issues.apache.org/jira/browse/THRIFT-3377) - Deep copy is actually shallow when using typedef members +- [THRIFT-3376](https://issues.apache.org/jira/browse/THRIFT-3376) - C# and Python JSON protocol double values lose precision +- [THRIFT-3373](https://issues.apache.org/jira/browse/THRIFT-3373) - Various fixes for cross test servers and clients +- [THRIFT-3370](https://issues.apache.org/jira/browse/THRIFT-3370) - errno extern variable redefined. Not compiling for Android +- [THRIFT-3379](https://issues.apache.org/jira/browse/THRIFT-3379) - Potential out of range panic in Go JSON protocols +- [THRIFT-3371](https://issues.apache.org/jira/browse/THRIFT-3371) - Abstract namespace Unix domain sockets broken in C++ +- [THRIFT-3380](https://issues.apache.org/jira/browse/THRIFT-3380) - nodejs: 0.9.2 -> 0.9.3 upgrade breaks Protocol and Transport requires +- [THRIFT-3367](https://issues.apache.org/jira/browse/THRIFT-3367) - Fix bad links to coding_standards.md #634 +- [THRIFT-3401](https://issues.apache.org/jira/browse/THRIFT-3401) - Nested collections emit Objective-C code that cannot compile +- [THRIFT-3403](https://issues.apache.org/jira/browse/THRIFT-3403) - JSON String reader doesn't recognize UTF-16 surrogate pairs +- [THRIFT-3362](https://issues.apache.org/jira/browse/THRIFT-3362) - make check fails for C++ at the SecurityTest +- [THRIFT-3395](https://issues.apache.org/jira/browse/THRIFT-3395) - Cocoa compiler produces corrupt code when boxing enums inside map. +- [THRIFT-3394](https://issues.apache.org/jira/browse/THRIFT-3394) - compiler generates uncompilable code +- [THRIFT-3388](https://issues.apache.org/jira/browse/THRIFT-3388) - hash doesn't work on set/list +- [THRIFT-3391](https://issues.apache.org/jira/browse/THRIFT-3391) - Wrong bool formatting in test server +- [THRIFT-3390](https://issues.apache.org/jira/browse/THRIFT-3390) - TTornado server doesn't handle closed connections properly +- [THRIFT-3382](https://issues.apache.org/jira/browse/THRIFT-3382) - TBase class for C++ Library +- [THRIFT-3392](https://issues.apache.org/jira/browse/THRIFT-3392) - Java TZlibTransport does not close its wrapper streams upon close() +- [THRIFT-3383](https://issues.apache.org/jira/browse/THRIFT-3383) - i64 related warnings +- [THRIFT-3386](https://issues.apache.org/jira/browse/THRIFT-3386) - misc. warnings with make check +- [THRIFT-3385](https://issues.apache.org/jira/browse/THRIFT-3385) - warning: format ‘%lu’ expects ‘long unsigned int’, but has type ‘std::basic_string::size_type {aka unsigned int} +- [THRIFT-3355](https://issues.apache.org/jira/browse/THRIFT-3355) - npm WARN package.json thrift@1.0.0-dev No license field. +- [THRIFT-3360](https://issues.apache.org/jira/browse/THRIFT-3360) - Improve cross test servers and clients further +- [THRIFT-3359](https://issues.apache.org/jira/browse/THRIFT-3359) - Binary field incompatibilities +- [THRIFT-3354](https://issues.apache.org/jira/browse/THRIFT-3354) - Fix word-extraction substr bug in initialism code +- [THRIFT-3350](https://issues.apache.org/jira/browse/THRIFT-3350) - Python JSON protocol does not encode binary as Base64 +- [THRIFT-3577](https://issues.apache.org/jira/browse/THRIFT-3577) - assertion failed at line 512 of testcontainertest.c +- [THRIFT-3576](https://issues.apache.org/jira/browse/THRIFT-3576) - Boost test --log_format arg does not accept lowercase +- [THRIFT-3575](https://issues.apache.org/jira/browse/THRIFT-3575) - Go compiler tries to use unexported library methods when using read_write_private +- [THRIFT-3574](https://issues.apache.org/jira/browse/THRIFT-3574) - Cocoa generator makes uncompilable imports +- [THRIFT-3570](https://issues.apache.org/jira/browse/THRIFT-3570) - Remove duplicate instances that are added by upstream +- [THRIFT-3571](https://issues.apache.org/jira/browse/THRIFT-3571) - Make feature test result browsable +- [THRIFT-3569](https://issues.apache.org/jira/browse/THRIFT-3569) - c_glib protocols do not check number of bytes read by transport +- [THRIFT-3568](https://issues.apache.org/jira/browse/THRIFT-3568) - THeader server crashes on readSlow +- [THRIFT-3567](https://issues.apache.org/jira/browse/THRIFT-3567) - GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed +- [THRIFT-3566](https://issues.apache.org/jira/browse/THRIFT-3566) - C++/Qt: TQTcpServerTest::test_communicate() is never executed +- [THRIFT-3564](https://issues.apache.org/jira/browse/THRIFT-3564) - C++/Qt: potential core dump in TQTcpServer in case an exception occurs in TAsyncProcessor::process() +- [THRIFT-3558](https://issues.apache.org/jira/browse/THRIFT-3558) - typos in c_glib tests +- [THRIFT-3559](https://issues.apache.org/jira/browse/THRIFT-3559) - Fix awkward extra semi-colons with Cocoa container literals +- [THRIFT-3555](https://issues.apache.org/jira/browse/THRIFT-3555) - 'configure' script does not honor --with-openssl= for libcrypto for BN_init +- [THRIFT-3554](https://issues.apache.org/jira/browse/THRIFT-3554) - Constant decls may lead to "Error: internal error: prepare_member_name_mapping() already active for different struct" +- [THRIFT-3552](https://issues.apache.org/jira/browse/THRIFT-3552) - glib_c Memory Leak +- [THRIFT-3551](https://issues.apache.org/jira/browse/THRIFT-3551) - Thrift perl library missing package declaration +- [THRIFT-3549](https://issues.apache.org/jira/browse/THRIFT-3549) - Exceptions are not properly stringified in Perl library +- [THRIFT-3546](https://issues.apache.org/jira/browse/THRIFT-3546) - NodeJS code should not be namespaced (and is currently not strict-mode compliant) +- [THRIFT-3545](https://issues.apache.org/jira/browse/THRIFT-3545) - Container type literals do not compile +- [THRIFT-3538](https://issues.apache.org/jira/browse/THRIFT-3538) - Remove UnboundMethodType in TProtocolDecorator +- [THRIFT-3536](https://issues.apache.org/jira/browse/THRIFT-3536) - Error 'char' does not contain a definition for 'IsLowSurrogate' for WP7 target +- [THRIFT-3534](https://issues.apache.org/jira/browse/THRIFT-3534) - Link error when building with Qt5 +- [THRIFT-3533](https://issues.apache.org/jira/browse/THRIFT-3533) - Can not send nil pointer as service method argument +- [THRIFT-3507](https://issues.apache.org/jira/browse/THRIFT-3507) - THttpClient does not use proxy from http_proxy, https_proxy environment variables +- [THRIFT-3502](https://issues.apache.org/jira/browse/THRIFT-3502) - C++ TServerSocket passes small buffer to getsockname +- [THRIFT-3501](https://issues.apache.org/jira/browse/THRIFT-3501) - Forward slash in comment causes compiler error +- [THRIFT-3498](https://issues.apache.org/jira/browse/THRIFT-3498) - C++ library assumes optional function pthread_attr_setschedpolicy is available +- [THRIFT-3497](https://issues.apache.org/jira/browse/THRIFT-3497) - Build fails with "invalid use of incomplete type" +- [THRIFT-3496](https://issues.apache.org/jira/browse/THRIFT-3496) - C++: Cob style client fails when sending a consecutive request +- [THRIFT-3493](https://issues.apache.org/jira/browse/THRIFT-3493) - libthrift does not compile on windows using visual studio +- [THRIFT-3488](https://issues.apache.org/jira/browse/THRIFT-3488) - warning: unused variable 'program' +- [THRIFT-3489](https://issues.apache.org/jira/browse/THRIFT-3489) - warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings] +- [THRIFT-3487](https://issues.apache.org/jira/browse/THRIFT-3487) - Full support for newer Delphi versions +- [THRIFT-3528](https://issues.apache.org/jira/browse/THRIFT-3528) - Fix warnings in thrift.ll +- [THRIFT-3527](https://issues.apache.org/jira/browse/THRIFT-3527) - -gen py:dynamic,utf8strings ignores utf8strings option +- [THRIFT-3526](https://issues.apache.org/jira/browse/THRIFT-3526) - Code generated by py:utf8strings does not work for Python3 +- [THRIFT-3524](https://issues.apache.org/jira/browse/THRIFT-3524) - dcc32 warning "W1000 Symbol 'IsLowSurrogate' is deprecated: 'Use TCharHelper'" in Thrift.Protocol.JSON.pas +- [THRIFT-3525](https://issues.apache.org/jira/browse/THRIFT-3525) - py:dynamic fails to handle binary list/set/map element +- [THRIFT-3521](https://issues.apache.org/jira/browse/THRIFT-3521) - TSimpleJSONProtocolTest is not deterministic (fails when run on JDK 8) +- [THRIFT-3520](https://issues.apache.org/jira/browse/THRIFT-3520) - Dart TSocket onError stream should be typed as Object +- [THRIFT-3519](https://issues.apache.org/jira/browse/THRIFT-3519) - fastbinary does not work with -gen py:utf8strings +- [THRIFT-3518](https://issues.apache.org/jira/browse/THRIFT-3518) - TConcurrentClientSyncInfo files were missing for Visual Studio +- [THRIFT-3512](https://issues.apache.org/jira/browse/THRIFT-3512) - c_glib: Build fails due to missing features.h +- [THRIFT-3483](https://issues.apache.org/jira/browse/THRIFT-3483) - Incorrect empty binary handling introduced by THRIFT-3359 +- [THRIFT-3479](https://issues.apache.org/jira/browse/THRIFT-3479) - Oneway calls should not return exceptions to clients +- [THRIFT-3478](https://issues.apache.org/jira/browse/THRIFT-3478) - Restore dropped method to THsHaServer.java +- [THRIFT-3477](https://issues.apache.org/jira/browse/THRIFT-3477) - Parser fails on enum item that starts with 'E' letter and continues with number +- [THRIFT-3476](https://issues.apache.org/jira/browse/THRIFT-3476) - Missing include in ./src/thrift/protocol/TJSONProtocol.cpp +- [THRIFT-3474](https://issues.apache.org/jira/browse/THRIFT-3474) - Docker: thrift-compiler +- [THRIFT-3473](https://issues.apache.org/jira/browse/THRIFT-3473) - When "optional' is used with a struct member, C++ server seems to not return it correctly +- [THRIFT-3468](https://issues.apache.org/jira/browse/THRIFT-3468) - Dart TSocketTransport onError handler is too restrictive +- [THRIFT-3451](https://issues.apache.org/jira/browse/THRIFT-3451) - thrift_protocol PHP extension missing config.m4 file +- [THRIFT-3456](https://issues.apache.org/jira/browse/THRIFT-3456) - rounding issue in static assert +- [THRIFT-3455](https://issues.apache.org/jira/browse/THRIFT-3455) - struct write method's return value is incorrect +- [THRIFT-3454](https://issues.apache.org/jira/browse/THRIFT-3454) - Python Tornado tutorial is broken +- [THRIFT-3463](https://issues.apache.org/jira/browse/THRIFT-3463) - Java can't be disabled in CMake build +- [THRIFT-3450](https://issues.apache.org/jira/browse/THRIFT-3450) - NPE when using SSL +- [THRIFT-3449](https://issues.apache.org/jira/browse/THRIFT-3449) - TBaseAsyncProcessor fb.responseReady() never called for oneway functions +- [THRIFT-3471](https://issues.apache.org/jira/browse/THRIFT-3471) - Dart generator does not handle uppercase argument names +- [THRIFT-3470](https://issues.apache.org/jira/browse/THRIFT-3470) - Sporadic timeouts with pipes +- [THRIFT-3465](https://issues.apache.org/jira/browse/THRIFT-3465) - Go Code With Complex Const Initializer Compilation Depends On Struct Order +- [THRIFT-3464](https://issues.apache.org/jira/browse/THRIFT-3464) - Fix several defects in c_glib code generator +- [THRIFT-3462](https://issues.apache.org/jira/browse/THRIFT-3462) - Cocoa generates Incorrect #import header names +- [THRIFT-3453](https://issues.apache.org/jira/browse/THRIFT-3453) - remove rat_exclude +- [THRIFT-3418](https://issues.apache.org/jira/browse/THRIFT-3418) - Use of ciphers in ssl.wrap_socket() breaks python 2.6 compatibility +- [THRIFT-3417](https://issues.apache.org/jira/browse/THRIFT-3417) - "namespace xsd" is not really working +- [THRIFT-3413](https://issues.apache.org/jira/browse/THRIFT-3413) - Thrift code generation bug in Go when extending service +- [THRIFT-3420](https://issues.apache.org/jira/browse/THRIFT-3420) - C++: TSSLSockets are not interruptable +- [THRIFT-3415](https://issues.apache.org/jira/browse/THRIFT-3415) - include unistd.h conditionally +- [THRIFT-3414](https://issues.apache.org/jira/browse/THRIFT-3414) - #include in THeaderTransport.h breaks windows build +- [THRIFT-3411](https://issues.apache.org/jira/browse/THRIFT-3411) - Go generates remotes with wrong package qualifiers when including +- [THRIFT-3430](https://issues.apache.org/jira/browse/THRIFT-3430) - Go THttpClient does not read HTTP response body to completion when closing +- [THRIFT-3423](https://issues.apache.org/jira/browse/THRIFT-3423) - First call to thrift_transport:read_exact fails to dispatch correct function +- [THRIFT-3422](https://issues.apache.org/jira/browse/THRIFT-3422) - Go TServerSocket doesn't close on Interrupt +- [THRIFT-3421](https://issues.apache.org/jira/browse/THRIFT-3421) - rebar as dependency instead of bundling (was: rebar fails if PWD contains Unicode) +- [THRIFT-3428](https://issues.apache.org/jira/browse/THRIFT-3428) - Go test fails when running make check +- [THRIFT-3445](https://issues.apache.org/jira/browse/THRIFT-3445) - Throwable messages are hidden from JVM stack trace output +- [THRIFT-3443](https://issues.apache.org/jira/browse/THRIFT-3443) - Thrift include can generate uncompilable code +- [THRIFT-3444](https://issues.apache.org/jira/browse/THRIFT-3444) - Large 64 bit Integer does not preserve value through Node.js JSONProtocol +- [THRIFT-3436](https://issues.apache.org/jira/browse/THRIFT-3436) - misc. cross test issues with UTF-8 path names +- [THRIFT-3435](https://issues.apache.org/jira/browse/THRIFT-3435) - Put generated Java code for fullcamel tests in a separate package/namespace +- [THRIFT-3433](https://issues.apache.org/jira/browse/THRIFT-3433) - Doubles aren't interpreted correctly +- [THRIFT-3437](https://issues.apache.org/jira/browse/THRIFT-3437) - Mingw-w64 build fail +- [THRIFT-3434](https://issues.apache.org/jira/browse/THRIFT-3434) - Dart generator produces empty name in pubspec.yaml for includes without namespaces +- [THRIFT-3408](https://issues.apache.org/jira/browse/THRIFT-3408) - JSON generator emits incorrect types +- [THRIFT-3406](https://issues.apache.org/jira/browse/THRIFT-3406) - Cocoa client should not schedule streams on main runloop +- [THRIFT-3404](https://issues.apache.org/jira/browse/THRIFT-3404) - JSON String reader doesn't recognize UTF-16 surrogate pair +- [THRIFT-3636](https://issues.apache.org/jira/browse/THRIFT-3636) - Double precision is not fully preserved in C++ TJSONProtocol +- [THRIFT-3632](https://issues.apache.org/jira/browse/THRIFT-3632) - c_glib testserialization fails with glib assertion +- [THRIFT-3619](https://issues.apache.org/jira/browse/THRIFT-3619) - Using Thrift 0.9.3 with googletest on Linux gcc 4.9 / C++11 +- [THRIFT-3617](https://issues.apache.org/jira/browse/THRIFT-3617) - CMake does not build gv/xml generators +- [THRIFT-3615](https://issues.apache.org/jira/browse/THRIFT-3615) - Fix Python SSL client resource leak on connection failure +- [THRIFT-3616](https://issues.apache.org/jira/browse/THRIFT-3616) - lib/py/test/test_sslsocket.py is flaky +- [THRIFT-3643](https://issues.apache.org/jira/browse/THRIFT-3643) - Perl SSL server crushes if a client disconnect without handshake +- [THRIFT-3639](https://issues.apache.org/jira/browse/THRIFT-3639) - C# Thrift library forces TLS 1.0, thwarting TLS 1.2 usage +- [THRIFT-3633](https://issues.apache.org/jira/browse/THRIFT-3633) - Travis "C C++ - GCC" build was using clang +- [THRIFT-3634](https://issues.apache.org/jira/browse/THRIFT-3634) - Fix Python TSocket resource leak on connection failure +- [THRIFT-3630](https://issues.apache.org/jira/browse/THRIFT-3630) - Debian/Ubuntu install docs need an update +- [THRIFT-3629](https://issues.apache.org/jira/browse/THRIFT-3629) - Parser sets exitcode on errors, but generator does not +- [THRIFT-3608](https://issues.apache.org/jira/browse/THRIFT-3608) - lib/cpp/test/SecurityTest is flaky in jenkins Thrift-precommit build. +- [THRIFT-3601](https://issues.apache.org/jira/browse/THRIFT-3601) - Better conformance to PEP8 for generated code +- [THRIFT-3599](https://issues.apache.org/jira/browse/THRIFT-3599) - Validate client IP address against cert's SubjectAltName +- [THRIFT-3598](https://issues.apache.org/jira/browse/THRIFT-3598) - TBufferedTransport doesn't instantiate client connection +- [THRIFT-3597](https://issues.apache.org/jira/browse/THRIFT-3597) - `make check` hangs in go tests +- [THRIFT-3589](https://issues.apache.org/jira/browse/THRIFT-3589) - Dart generator uses wrong name in constructor for uppercase arguments with defaults +- [THRIFT-3588](https://issues.apache.org/jira/browse/THRIFT-3588) - Using TypeScript with --noImplicitAny fails +- [THRIFT-3584](https://issues.apache.org/jira/browse/THRIFT-3584) - boolean false value cannot be transferred +- [THRIFT-3578](https://issues.apache.org/jira/browse/THRIFT-3578) - Make THeaderTransport detect TCompact framed and unframed +- [THRIFT-3323](https://issues.apache.org/jira/browse/THRIFT-3323) - Python library does not handle escaped forward slash ("/") in JSON +- [THRIFT-3322](https://issues.apache.org/jira/browse/THRIFT-3322) - CMake generated "make check" failes on python_test +- [THRIFT-3321](https://issues.apache.org/jira/browse/THRIFT-3321) - Thrift can't be added as a subdirectory of another CMake-based project +- [THRIFT-3314](https://issues.apache.org/jira/browse/THRIFT-3314) - Dots in file names of includes causes dots in javascript variable names +- [THRIFT-3307](https://issues.apache.org/jira/browse/THRIFT-3307) - Segfault in Ruby serializer +- [THRIFT-3309](https://issues.apache.org/jira/browse/THRIFT-3309) - Missing TConstant.php in /lib/php/Makefile.am +- [THRIFT-3810](https://issues.apache.org/jira/browse/THRIFT-3810) - unresolved external symbol public: virtual void __cdecl apache::thrift::server::TServerFramework::serve(void) +- [THRIFT-3736](https://issues.apache.org/jira/browse/THRIFT-3736) - C++ library build fails if OpenSSL does not surrpot SSLv3 +- [THRIFT-3878](https://issues.apache.org/jira/browse/THRIFT-3878) - Compile error in TSSLSocket.cpp with new OpenSSL [CRYPTO_num_locks] +- [THRIFT-3949](https://issues.apache.org/jira/browse/THRIFT-3949) - missing make dist entry for compiler/cpp/test +- [THRIFT-449](https://issues.apache.org/jira/browse/THRIFT-449) - The wire format of the JSON Protocol may not always be valid JSON if it contains non-UTF8 encoded strings +- [THRIFT-162](https://issues.apache.org/jira/browse/THRIFT-162) - Thrift structures are unhashable, preventing them from being used as set elements +- [THRIFT-3961](https://issues.apache.org/jira/browse/THRIFT-3961) - TConnectedClient does not terminate the connection to the client if an exception while processing the received message occures. +- [THRIFT-3881](https://issues.apache.org/jira/browse/THRIFT-3881) - Travis CI builds are failing due to docker failures (three retries, and gives up) +- [THRIFT-3937](https://issues.apache.org/jira/browse/THRIFT-3937) - Cannot compile 0.10.0 development tip with gcc-4.6.x +- [THRIFT-3964](https://issues.apache.org/jira/browse/THRIFT-3964) - Unsupported mechanism type ????? due to dependency on default OS-dependent charset +- [THRIFT-3038](https://issues.apache.org/jira/browse/THRIFT-3038) - Use of volatile in cpp library +- [THRIFT-3301](https://issues.apache.org/jira/browse/THRIFT-3301) - Java generated code uses imports that can lead to class name collisions with IDL defined types +- [THRIFT-3348](https://issues.apache.org/jira/browse/THRIFT-3348) - PHP TCompactProtocol bool&int64 readvalue bug +- [THRIFT-3955](https://issues.apache.org/jira/browse/THRIFT-3955) - TThreadedServer Memory Leak +- [THRIFT-3829](https://issues.apache.org/jira/browse/THRIFT-3829) - Thrift does not install Python Libraries if Twisted is not installed +- [THRIFT-3932](https://issues.apache.org/jira/browse/THRIFT-3932) - C++ ThreadManager has a rare termination race +- [THRIFT-3828](https://issues.apache.org/jira/browse/THRIFT-3828) - cmake fails when Boost_INCLUDE_DIRS (and other variables passed to include_directories()) is empty +- [THRIFT-3958](https://issues.apache.org/jira/browse/THRIFT-3958) - CMake WITH_MT option for windows static runtime linking does not support the cmake build type RelWithDebInfo +- [THRIFT-3957](https://issues.apache.org/jira/browse/THRIFT-3957) - TConnectedClient does not disconnect from clients when their timeout is reached. +- [THRIFT-3953](https://issues.apache.org/jira/browse/THRIFT-3953) - TSSLSocket::close should handle exceptions from waitForEvent because it is called by the destructor. +- [THRIFT-3977](https://issues.apache.org/jira/browse/THRIFT-3977) - PHP extension creates undefined values when deserializing sets +- [THRIFT-3947](https://issues.apache.org/jira/browse/THRIFT-3947) - sockaddr type isn't always large enough for the return of getsockname +- [THRIFT-2755](https://issues.apache.org/jira/browse/THRIFT-2755) - ThreadSanitizer reports data race in ThreadManager::Impl::addWorker +- [THRIFT-3948](https://issues.apache.org/jira/browse/THRIFT-3948) - errno is not the correct method of getting the error in windows +- [THRIFT-4008](https://issues.apache.org/jira/browse/THRIFT-4008) - broken ci due to upstream dependency versioning break +- [THRIFT-3999](https://issues.apache.org/jira/browse/THRIFT-3999) - Fix Debian & Ubuntu package dependencies +- [THRIFT-3886](https://issues.apache.org/jira/browse/THRIFT-3886) - PHP cross test client returns 0 even when failing +- [THRIFT-3997](https://issues.apache.org/jira/browse/THRIFT-3997) - building thrift libs does not support new openssl + +### Documentation +- [THRIFT-3867](https://issues.apache.org/jira/browse/THRIFT-3867) - Specify BinaryProtocol and CompactProtocol + +### Epic +- [THRIFT-3049](https://issues.apache.org/jira/browse/THRIFT-3049) - As an iOS developer, I want a generator and library that produces Swift code +- [THRIFT-2336](https://issues.apache.org/jira/browse/THRIFT-2336) - UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + +### Improvement +- [THRIFT-1867](https://issues.apache.org/jira/browse/THRIFT-1867) - Python client/server should support client-side certificates. +- [THRIFT-1313](https://issues.apache.org/jira/browse/THRIFT-1313) - c_glib compact support +- [THRIFT-1385](https://issues.apache.org/jira/browse/THRIFT-1385) - make install doesn't install java library in the setted folder +- [THRIFT-1437](https://issues.apache.org/jira/browse/THRIFT-1437) - Update RPM spec +- [THRIFT-847](https://issues.apache.org/jira/browse/THRIFT-847) - Test Framework harmonization across all languages +- [THRIFT-819](https://issues.apache.org/jira/browse/THRIFT-819) - add Enumeration for protocol, transport and server types +- [THRIFT-3927](https://issues.apache.org/jira/browse/THRIFT-3927) - Emit an error instead of throw an error in the async callback +- [THRIFT-3931](https://issues.apache.org/jira/browse/THRIFT-3931) - TSimpleServer: If process request encounter UNKNOWN_METHOD, don't close transport. +- [THRIFT-3934](https://issues.apache.org/jira/browse/THRIFT-3934) - Automatically resolve OpenSSL binary version on Windows CI +- [THRIFT-3918](https://issues.apache.org/jira/browse/THRIFT-3918) - Run subset of make cross +- [THRIFT-3908](https://issues.apache.org/jira/browse/THRIFT-3908) - Remove redundant dependencies from Dockerfile +- [THRIFT-3907](https://issues.apache.org/jira/browse/THRIFT-3907) - Skip Docker image build on CI when unchanged +- [THRIFT-3868](https://issues.apache.org/jira/browse/THRIFT-3868) - Java struct equals should do identity check before field comparison +- [THRIFT-3849](https://issues.apache.org/jira/browse/THRIFT-3849) - Port Go serializer and deserializer to dart +- [THRIFT-2989](https://issues.apache.org/jira/browse/THRIFT-2989) - Complete CMake build for Apache Thrift +- [THRIFT-2980](https://issues.apache.org/jira/browse/THRIFT-2980) - ThriftMemoryBuffer doesn't have a constructor option to take an existing buffer +- [THRIFT-2856](https://issues.apache.org/jira/browse/THRIFT-2856) - refactor erlang basic transports and unify interfaces +- [THRIFT-2877](https://issues.apache.org/jira/browse/THRIFT-2877) - Optimize generated hashCode +- [THRIFT-2869](https://issues.apache.org/jira/browse/THRIFT-2869) - JSON: run schema validation from tests +- [THRIFT-3112](https://issues.apache.org/jira/browse/THRIFT-3112) - [Java] AsyncMethodCallback should be typed in generated AsyncIface +- [THRIFT-3263](https://issues.apache.org/jira/browse/THRIFT-3263) - PHP jsonSerialize() should cast scalar types +- [THRIFT-2905](https://issues.apache.org/jira/browse/THRIFT-2905) - Cocoa compiler should have option to produce "modern" Objective-C +- [THRIFT-2821](https://issues.apache.org/jira/browse/THRIFT-2821) - Enable the use of custom HTTP-Header in the Transport +- [THRIFT-2093](https://issues.apache.org/jira/browse/THRIFT-2093) - added the ability to set compression level in C++ zlib transport +- [THRIFT-2089](https://issues.apache.org/jira/browse/THRIFT-2089) - Compiler ignores duplicate typenames +- [THRIFT-2056](https://issues.apache.org/jira/browse/THRIFT-2056) - Moved all #include config.h statements to #include +- [THRIFT-2031](https://issues.apache.org/jira/browse/THRIFT-2031) - Make SO_KEEPALIVE configurable for C++ lib +- [THRIFT-2021](https://issues.apache.org/jira/browse/THRIFT-2021) - Improve large binary protocol string performance +- [THRIFT-2028](https://issues.apache.org/jira/browse/THRIFT-2028) - Cleanup threading headers / libraries +- [THRIFT-2014](https://issues.apache.org/jira/browse/THRIFT-2014) - Change C++ lib includes to use style throughout +- [THRIFT-2312](https://issues.apache.org/jira/browse/THRIFT-2312) - travis.yml: build everything +- [THRIFT-1915](https://issues.apache.org/jira/browse/THRIFT-1915) - Multiplexing Services +- [THRIFT-1736](https://issues.apache.org/jira/browse/THRIFT-1736) - Visual Studio top level project files within msvc +- [THRIFT-1735](https://issues.apache.org/jira/browse/THRIFT-1735) - integrate tutorial into regular build +- [THRIFT-1533](https://issues.apache.org/jira/browse/THRIFT-1533) - Make TTransport should be Closeable +- [THRIFT-35](https://issues.apache.org/jira/browse/THRIFT-35) - Move language tests into their appropriate library directory +- [THRIFT-1079](https://issues.apache.org/jira/browse/THRIFT-1079) - Support i64 in AS3 +- [THRIFT-1108](https://issues.apache.org/jira/browse/THRIFT-1108) - SSL support for the Ruby library +- [THRIFT-3856](https://issues.apache.org/jira/browse/THRIFT-3856) - update debian package deependencies +- [THRIFT-3833](https://issues.apache.org/jira/browse/THRIFT-3833) - haxe http server implementation (by embeding into php web server) +- [THRIFT-3839](https://issues.apache.org/jira/browse/THRIFT-3839) - Performance issue with big message deserialization using php extension +- [THRIFT-3820](https://issues.apache.org/jira/browse/THRIFT-3820) - Erlang: Detect OTP >= 18 to use new time correction +- [THRIFT-3816](https://issues.apache.org/jira/browse/THRIFT-3816) - Reduce docker build duration on Travis-CI +- [THRIFT-3815](https://issues.apache.org/jira/browse/THRIFT-3815) - Put appveyor dependency versions to one place +- [THRIFT-3788](https://issues.apache.org/jira/browse/THRIFT-3788) - Compatibility improvements and Win64 support +- [THRIFT-3792](https://issues.apache.org/jira/browse/THRIFT-3792) - Timeouts for anonymous pipes should be configurable +- [THRIFT-3794](https://issues.apache.org/jira/browse/THRIFT-3794) - Split Delphi application, protocol and transport exception subtypes into separate exceptions +- [THRIFT-3774](https://issues.apache.org/jira/browse/THRIFT-3774) - The generated code should have exception_names meta info +- [THRIFT-3762](https://issues.apache.org/jira/browse/THRIFT-3762) - Fix build warnings for deprecated Thrift "byte" fields +- [THRIFT-3756](https://issues.apache.org/jira/browse/THRIFT-3756) - Improve requiredness documentation +- [THRIFT-3761](https://issues.apache.org/jira/browse/THRIFT-3761) - Add debian package for Python3 +- [THRIFT-3742](https://issues.apache.org/jira/browse/THRIFT-3742) - haxe php cli support +- [THRIFT-3733](https://issues.apache.org/jira/browse/THRIFT-3733) - Socket timeout improvements +- [THRIFT-3728](https://issues.apache.org/jira/browse/THRIFT-3728) - http transport for thrift-lua +- [THRIFT-3905](https://issues.apache.org/jira/browse/THRIFT-3905) - Dart compiler does not initialize bool, int, and double properties +- [THRIFT-3911](https://issues.apache.org/jira/browse/THRIFT-3911) - Loosen Ruby dev dependency version requirements +- [THRIFT-3906](https://issues.apache.org/jira/browse/THRIFT-3906) - Run C# tests with make check +- [THRIFT-3900](https://issues.apache.org/jira/browse/THRIFT-3900) - Add Python SSL flags +- [THRIFT-3897](https://issues.apache.org/jira/browse/THRIFT-3897) - Provide meaningful exception type based on WebExceptionStatus in case of timeout +- [THRIFT-3808](https://issues.apache.org/jira/browse/THRIFT-3808) - Missing `DOUBLE` in thrift type enumeration +- [THRIFT-3803](https://issues.apache.org/jira/browse/THRIFT-3803) - Remove "file" attribute from XML generator +- [THRIFT-3660](https://issues.apache.org/jira/browse/THRIFT-3660) - Add V4 mapped address to test client cert's altname +- [THRIFT-3661](https://issues.apache.org/jira/browse/THRIFT-3661) - Use https to download meck in erlang test build +- [THRIFT-3659](https://issues.apache.org/jira/browse/THRIFT-3659) - Check configure result of CMake on CI +- [THRIFT-3667](https://issues.apache.org/jira/browse/THRIFT-3667) - Add TLS SNI support to clients +- [THRIFT-3651](https://issues.apache.org/jira/browse/THRIFT-3651) - Make backports.match_hostname and ipaddress optional +- [THRIFT-3666](https://issues.apache.org/jira/browse/THRIFT-3666) - Build D tutorial as part of Autotools build +- [THRIFT-3665](https://issues.apache.org/jira/browse/THRIFT-3665) - Add D libevent and OpenSSL to docker images +- [THRIFT-3664](https://issues.apache.org/jira/browse/THRIFT-3664) - Remove md5.c +- [THRIFT-3662](https://issues.apache.org/jira/browse/THRIFT-3662) - Add Haskell to debian docker image +- [THRIFT-3711](https://issues.apache.org/jira/browse/THRIFT-3711) - Add D to cross language test +- [THRIFT-3691](https://issues.apache.org/jira/browse/THRIFT-3691) - Run flake8 Python style check on Travis-CI +- [THRIFT-3692](https://issues.apache.org/jira/browse/THRIFT-3692) - (Re)enable Appveyor C++ and Python build +- [THRIFT-3677](https://issues.apache.org/jira/browse/THRIFT-3677) - Improve CMake Java build +- [THRIFT-3679](https://issues.apache.org/jira/browse/THRIFT-3679) - Add stdout log to testBinary in Java test server +- [THRIFT-3718](https://issues.apache.org/jira/browse/THRIFT-3718) - Reduce size of docker image for build environment +- [THRIFT-3698](https://issues.apache.org/jira/browse/THRIFT-3698) - [Travis-CI] Introduce retry to apt commands +- [THRIFT-3127](https://issues.apache.org/jira/browse/THRIFT-3127) - switch -recurse to --recurse and reserve -r +- [THRIFT-3087](https://issues.apache.org/jira/browse/THRIFT-3087) - Pass on errors like "connection closed" +- [THRIFT-3240](https://issues.apache.org/jira/browse/THRIFT-3240) - Thrift Python client should support subjectAltName and wildcard certs in TSSLSocket +- [THRIFT-3213](https://issues.apache.org/jira/browse/THRIFT-3213) - make cross should indicate when it skips a known failing test +- [THRIFT-3208](https://issues.apache.org/jira/browse/THRIFT-3208) - Fix Visual Studio solution build failure due to missing source +- [THRIFT-3186](https://issues.apache.org/jira/browse/THRIFT-3186) - Add TServerHTTP to Go library +- [THRIFT-2342](https://issues.apache.org/jira/browse/THRIFT-2342) - Add __FILE__ and __LINE__ to Thrift C++ excpetions +- [THRIFT-3372](https://issues.apache.org/jira/browse/THRIFT-3372) - Add dart generator to Visual Studio project +- [THRIFT-3366](https://issues.apache.org/jira/browse/THRIFT-3366) - ThriftTest to implement standard return values +- [THRIFT-3402](https://issues.apache.org/jira/browse/THRIFT-3402) - Provide a perl Unix Socket implementation +- [THRIFT-3361](https://issues.apache.org/jira/browse/THRIFT-3361) - Improve C# library +- [THRIFT-3393](https://issues.apache.org/jira/browse/THRIFT-3393) - Introduce i8 to provide consistent set of Thrift IDL integer types +- [THRIFT-3339](https://issues.apache.org/jira/browse/THRIFT-3339) - Support for database/sql +- [THRIFT-3565](https://issues.apache.org/jira/browse/THRIFT-3565) - C++: T[Async]Processor::getEventHandler() should be declared as const member functions +- [THRIFT-3563](https://issues.apache.org/jira/browse/THRIFT-3563) - C++/Qt: removed usage of macro QT_PREPEND_NAMESPACE as it isn't consequently used for all references to Qt types. +- [THRIFT-3562](https://issues.apache.org/jira/browse/THRIFT-3562) - Removed unused TAsyncProcessor::getAsyncServer() +- [THRIFT-3561](https://issues.apache.org/jira/browse/THRIFT-3561) - C++/Qt: make use of Q_DISABLE_COPY() to get rid of copy ctor and assignment operator +- [THRIFT-3556](https://issues.apache.org/jira/browse/THRIFT-3556) - c_glib file descriptor transport +- [THRIFT-3544](https://issues.apache.org/jira/browse/THRIFT-3544) - Make cross test fail when server process died unexpectedly +- [THRIFT-3540](https://issues.apache.org/jira/browse/THRIFT-3540) - Make python tutorial more in line with PEP8 +- [THRIFT-3535](https://issues.apache.org/jira/browse/THRIFT-3535) - Dart generator argument to produce a file structure usable in parent library +- [THRIFT-3505](https://issues.apache.org/jira/browse/THRIFT-3505) - Enhance Python TSSLSocket +- [THRIFT-3506](https://issues.apache.org/jira/browse/THRIFT-3506) - Eliminate old style classes from library code +- [THRIFT-3503](https://issues.apache.org/jira/browse/THRIFT-3503) - Enable py:utf8string by default +- [THRIFT-3499](https://issues.apache.org/jira/browse/THRIFT-3499) - Add package_prefix to python generator +- [THRIFT-3495](https://issues.apache.org/jira/browse/THRIFT-3495) - Minor enhancements and fixes for cross test +- [THRIFT-3486](https://issues.apache.org/jira/browse/THRIFT-3486) - Java generated `getFieldValue` is incompatible with `setFieldValue` for binary values. +- [THRIFT-3484](https://issues.apache.org/jira/browse/THRIFT-3484) - Consolidate temporary buffers in Java's TCompactProtocol +- [THRIFT-3516](https://issues.apache.org/jira/browse/THRIFT-3516) - Add feature test for THeader TBinaryProtocol interop +- [THRIFT-3515](https://issues.apache.org/jira/browse/THRIFT-3515) - Python 2.6 compatibility and test on CI +- [THRIFT-3514](https://issues.apache.org/jira/browse/THRIFT-3514) - PHP 7 compatible version of binary protocol +- [THRIFT-3469](https://issues.apache.org/jira/browse/THRIFT-3469) - Docker: Debian support +- [THRIFT-3416](https://issues.apache.org/jira/browse/THRIFT-3416) - Retire old "xxx_namespace" declarations from the IDL +- [THRIFT-3426](https://issues.apache.org/jira/browse/THRIFT-3426) - Align autogen comment in XSD +- [THRIFT-3424](https://issues.apache.org/jira/browse/THRIFT-3424) - Add CMake android build option +- [THRIFT-3439](https://issues.apache.org/jira/browse/THRIFT-3439) - Run make cross using Python3 when available +- [THRIFT-3440](https://issues.apache.org/jira/browse/THRIFT-3440) - Python make check takes too much time +- [THRIFT-3441](https://issues.apache.org/jira/browse/THRIFT-3441) - Stabilize Travis-CI builds +- [THRIFT-3431](https://issues.apache.org/jira/browse/THRIFT-3431) - Avoid "schemes" HashMap lookups during struct reads/writes +- [THRIFT-3432](https://issues.apache.org/jira/browse/THRIFT-3432) - Add a TByteBuffer transport to the Java library +- [THRIFT-3438](https://issues.apache.org/jira/browse/THRIFT-3438) - Enable py:new_style by default +- [THRIFT-3405](https://issues.apache.org/jira/browse/THRIFT-3405) - Go THttpClient misuses http.Client objects +- [THRIFT-3614](https://issues.apache.org/jira/browse/THRIFT-3614) - Improve logging of test_sslsocket.py +- [THRIFT-3647](https://issues.apache.org/jira/browse/THRIFT-3647) - Fix php extension build warnings +- [THRIFT-3642](https://issues.apache.org/jira/browse/THRIFT-3642) - Speed up cross test runner +- [THRIFT-3637](https://issues.apache.org/jira/browse/THRIFT-3637) - Implement compact protocol for dart +- [THRIFT-3613](https://issues.apache.org/jira/browse/THRIFT-3613) - Port Python C extension to Python 3 +- [THRIFT-3612](https://issues.apache.org/jira/browse/THRIFT-3612) - Add Python C extension for compact protocol +- [THRIFT-3611](https://issues.apache.org/jira/browse/THRIFT-3611) - Add --regex filter to cross test runner +- [THRIFT-3631](https://issues.apache.org/jira/browse/THRIFT-3631) - JSON protocol implementation for Lua +- [THRIFT-3609](https://issues.apache.org/jira/browse/THRIFT-3609) - Remove or replace TestPortFixture.h +- [THRIFT-3605](https://issues.apache.org/jira/browse/THRIFT-3605) - Have the compiler complain about invalid arguments and options +- [THRIFT-3596](https://issues.apache.org/jira/browse/THRIFT-3596) - Better conformance to PEP8 +- [THRIFT-3585](https://issues.apache.org/jira/browse/THRIFT-3585) - Compact protocol implementation for Lua +- [THRIFT-3582](https://issues.apache.org/jira/browse/THRIFT-3582) - Erlang libraries should have service metadata +- [THRIFT-3579](https://issues.apache.org/jira/browse/THRIFT-3579) - Introduce retry to make cross +- [THRIFT-3306](https://issues.apache.org/jira/browse/THRIFT-3306) - Java: TBinaryProtocol: Use 1 temp buffer instead of allocating 8 +- [THRIFT-3910](https://issues.apache.org/jira/browse/THRIFT-3910) - Do not invoke pip as part of build process +- [THRIFT-1857](https://issues.apache.org/jira/browse/THRIFT-1857) - Python 3.X Support +- [THRIFT-1944](https://issues.apache.org/jira/browse/THRIFT-1944) - Binding to zero port +- [THRIFT-3954](https://issues.apache.org/jira/browse/THRIFT-3954) - Enable the usage of structs called "Object" in Java +- [THRIFT-3981](https://issues.apache.org/jira/browse/THRIFT-3981) - Enable analyzer strong mode in Dart library +- [THRIFT-3998](https://issues.apache.org/jira/browse/THRIFT-3998) - Document ability to add custom tags to thrift structs +- [THRIFT-4006](https://issues.apache.org/jira/browse/THRIFT-4006) - Add a removeEventListener method on TSocket + +### New Feature +- [THRIFT-640](https://issues.apache.org/jira/browse/THRIFT-640) - Support deprecation +- [THRIFT-948](https://issues.apache.org/jira/browse/THRIFT-948) - SSL socket support for PHP +- [THRIFT-764](https://issues.apache.org/jira/browse/THRIFT-764) - add Support for Vala language +- [THRIFT-3046](https://issues.apache.org/jira/browse/THRIFT-3046) - Allow PSR4 class loading for generated classes (PHP) +- [THRIFT-2113](https://issues.apache.org/jira/browse/THRIFT-2113) - Erlang SSL Socket Support +- [THRIFT-1482](https://issues.apache.org/jira/browse/THRIFT-1482) - Unix domain socket support under PHP +- [THRIFT-519](https://issues.apache.org/jira/browse/THRIFT-519) - Support collections of types without having to explicitly define it +- [THRIFT-468](https://issues.apache.org/jira/browse/THRIFT-468) - Rack Middleware Application for Rails +- [THRIFT-1708](https://issues.apache.org/jira/browse/THRIFT-1708) - Add event handlers for processor events +- [THRIFT-3834](https://issues.apache.org/jira/browse/THRIFT-3834) - Erlang namespacing and exception metadata +- [THRIFT-2510](https://issues.apache.org/jira/browse/THRIFT-2510) - Implement TNonblockingServer's ability to listen on unix domain sockets +- [THRIFT-3397](https://issues.apache.org/jira/browse/THRIFT-3397) - Implement TProcessorFactory in C# to enable per-client processors +- [THRIFT-3523](https://issues.apache.org/jira/browse/THRIFT-3523) - XML Generator +- [THRIFT-3510](https://issues.apache.org/jira/browse/THRIFT-3510) - Add HttpTaskAsyncHandler implementation +- [THRIFT-3318](https://issues.apache.org/jira/browse/THRIFT-3318) - PHP: SimpleJSONProtocol Implementation +- [THRIFT-3299](https://issues.apache.org/jira/browse/THRIFT-3299) - Dart language bindings in Thrift +- [THRIFT-2835](https://issues.apache.org/jira/browse/THRIFT-2835) - Add possibility to distribute generators separately from thrift core, and load them dynamically +- [THRIFT-184](https://issues.apache.org/jira/browse/THRIFT-184) - Add OSGi Manifest headers to the libthrift java library to be able to use Thrift in the OSGi runtime +- [THRIFT-141](https://issues.apache.org/jira/browse/THRIFT-141) - If a required field is not present on serialization, throw an exception +- [THRIFT-1891](https://issues.apache.org/jira/browse/THRIFT-1891) - Add Windows ALPC transport which is right counterpart of Unix domain sockets + +### Question +- [THRIFT-1808](https://issues.apache.org/jira/browse/THRIFT-1808) - The Thrift struct should be considered self-contained? +- [THRIFT-2895](https://issues.apache.org/jira/browse/THRIFT-2895) - Tutorial cpp +- [THRIFT-3860](https://issues.apache.org/jira/browse/THRIFT-3860) - Elephant-bird application Test fails for Thrift +- [THRIFT-3811](https://issues.apache.org/jira/browse/THRIFT-3811) - HTTPS Support for C++ applications +- [THRIFT-3509](https://issues.apache.org/jira/browse/THRIFT-3509) - "make check" error + +### Story +- [THRIFT-3452](https://issues.apache.org/jira/browse/THRIFT-3452) - .travis.yml: Migrating from legacy to container-based infrastructure + +### Sub-task +- [THRIFT-1811](https://issues.apache.org/jira/browse/THRIFT-1811) - ruby tutorial as part of the regular build +- [THRIFT-2779](https://issues.apache.org/jira/browse/THRIFT-2779) - PHP TJSONProtocol encode unicode into UCS-4LE which can't be parsed by other language bindings +- [THRIFT-2110](https://issues.apache.org/jira/browse/THRIFT-2110) - Erlang: Support for Multiplexing Services on any Transport, Protocol and Server +- [THRIFT-3852](https://issues.apache.org/jira/browse/THRIFT-3852) - A Travis-CI job fails with "write error" +- [THRIFT-3740](https://issues.apache.org/jira/browse/THRIFT-3740) - Fix haxelib.json classpath +- [THRIFT-3653](https://issues.apache.org/jira/browse/THRIFT-3653) - incorrect union serialization +- [THRIFT-3652](https://issues.apache.org/jira/browse/THRIFT-3652) - incorrect serialization of optionals +- [THRIFT-3655](https://issues.apache.org/jira/browse/THRIFT-3655) - incorrect union serialization +- [THRIFT-3654](https://issues.apache.org/jira/browse/THRIFT-3654) - incorrect serialization of optionals +- [THRIFT-3656](https://issues.apache.org/jira/browse/THRIFT-3656) - incorrect serialization of optionals +- [THRIFT-3699](https://issues.apache.org/jira/browse/THRIFT-3699) - Fix integer limit symbol includes in Python C extension +- [THRIFT-3693](https://issues.apache.org/jira/browse/THRIFT-3693) - Fix include issue in C++ TSSLSocketInterruptTest on Windows +- [THRIFT-3694](https://issues.apache.org/jira/browse/THRIFT-3694) - [Windows] Disable tests of a few servers that are not supported +- [THRIFT-3696](https://issues.apache.org/jira/browse/THRIFT-3696) - Install pip to CentOS Docker images to fix Python builds +- [THRIFT-3638](https://issues.apache.org/jira/browse/THRIFT-3638) - Fix haxelib.json +- [THRIFT-3251](https://issues.apache.org/jira/browse/THRIFT-3251) - Add http transport for server to Go lib +- [THRIFT-2424](https://issues.apache.org/jira/browse/THRIFT-2424) - Recursive Types +- [THRIFT-2423](https://issues.apache.org/jira/browse/THRIFT-2423) - THeader +- [THRIFT-2413](https://issues.apache.org/jira/browse/THRIFT-2413) - Python: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol +- [THRIFT-2409](https://issues.apache.org/jira/browse/THRIFT-2409) - Java: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol +- [THRIFT-2412](https://issues.apache.org/jira/browse/THRIFT-2412) - D: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol +- [THRIFT-2411](https://issues.apache.org/jira/browse/THRIFT-2411) - C++: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol +- [THRIFT-2410](https://issues.apache.org/jira/browse/THRIFT-2410) - JavaMe: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol +- [THRIFT-2668](https://issues.apache.org/jira/browse/THRIFT-2668) - TestSuite: detailed result on passed tests by feature +- [THRIFT-2659](https://issues.apache.org/jira/browse/THRIFT-2659) - python Test Server fails when throwing TException +- [THRIFT-3398](https://issues.apache.org/jira/browse/THRIFT-3398) - Add CMake build for Haskell library and tests +- [THRIFT-3396](https://issues.apache.org/jira/browse/THRIFT-3396) - DART: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol +- [THRIFT-3364](https://issues.apache.org/jira/browse/THRIFT-3364) - Fix ruby binary field encoding in TJSONProtocol +- [THRIFT-3381](https://issues.apache.org/jira/browse/THRIFT-3381) - Fix for misc. codegen issues with THRIFT-2905 +- [THRIFT-3573](https://issues.apache.org/jira/browse/THRIFT-3573) - No rule to make target `../../../test/c_glib/src/.deps/testthrifttest-thrift_test_handler.Po'. +- [THRIFT-3572](https://issues.apache.org/jira/browse/THRIFT-3572) - "Unable to determine the behavior of a signed right shift" +- [THRIFT-3542](https://issues.apache.org/jira/browse/THRIFT-3542) - Add length limit support to Java test server +- [THRIFT-3537](https://issues.apache.org/jira/browse/THRIFT-3537) - Remove the (now obsolete) csharp:asyncctp flag +- [THRIFT-3532](https://issues.apache.org/jira/browse/THRIFT-3532) - Add configurable string and container read size limit to Python protocols +- [THRIFT-3531](https://issues.apache.org/jira/browse/THRIFT-3531) - Create cross lang feature test for string and container read length limit +- [THRIFT-3482](https://issues.apache.org/jira/browse/THRIFT-3482) - Haskell JSON protocol does not encode binary field as Base64 +- [THRIFT-3425](https://issues.apache.org/jira/browse/THRIFT-3425) - Minor fixes + simplification for CentOS Dockerfile +- [THRIFT-3442](https://issues.apache.org/jira/browse/THRIFT-3442) - Run CMake tests on Appveyor +- [THRIFT-3409](https://issues.apache.org/jira/browse/THRIFT-3409) - NodeJS binary field issues +- [THRIFT-3621](https://issues.apache.org/jira/browse/THRIFT-3621) - Fix lib/cpp/test/SecurityTest.cpp to use ephemeral ports +- [THRIFT-3628](https://issues.apache.org/jira/browse/THRIFT-3628) - Fix lib/cpp/test/TServerIntegrationTest.cpp to use ephemeral ports +- [THRIFT-3625](https://issues.apache.org/jira/browse/THRIFT-3625) - Kill unused #include "TestPortFixture.h" in lib/cpp/test/TServerTransportTest.cpp. +- [THRIFT-3646](https://issues.apache.org/jira/browse/THRIFT-3646) - Fix Python extension build warnings +- [THRIFT-3626](https://issues.apache.org/jira/browse/THRIFT-3626) - Fix lib/cpp/test/TSocketInterruptTest.cpp to use ephemeral ports. +- [THRIFT-3624](https://issues.apache.org/jira/browse/THRIFT-3624) - Fix lib/cpp/test/TServerSocketTest.cpp to use ephemeral ports +- [THRIFT-3623](https://issues.apache.org/jira/browse/THRIFT-3623) - Fix Fix cpp/lib/test/TSSLSocketInterruptTest.cpp to use ephemeral ports +- [THRIFT-3592](https://issues.apache.org/jira/browse/THRIFT-3592) - Add basic test client +- [THRIFT-3980](https://issues.apache.org/jira/browse/THRIFT-3980) - add TExtendedBinaryProtocol.java + +### Task +- [THRIFT-1801](https://issues.apache.org/jira/browse/THRIFT-1801) - Sync up TApplicationException codes across languages and thrift implementations +- [THRIFT-1259](https://issues.apache.org/jira/browse/THRIFT-1259) - Automate versioning + +### Test +- [THRIFT-3400](https://issues.apache.org/jira/browse/THRIFT-3400) - Add Erlang to cross test +- [THRIFT-3504](https://issues.apache.org/jira/browse/THRIFT-3504) - Fix FastbinaryTest.py + +### Wish +- [THRIFT-3923](https://issues.apache.org/jira/browse/THRIFT-3923) - Maybe remove Aereo from the "Powered by" list +- [THRIFT-2149](https://issues.apache.org/jira/browse/THRIFT-2149) - Add an option to disable the generation of default operators + +## 0.9.3 + +### Bug +- [THRIFT-2441](https://issues.apache.org/jira/browse/THRIFT-2441) - Cannot shutdown TThreadedServer when clients are still connected +- [THRIFT-2465](https://issues.apache.org/jira/browse/THRIFT-2465) - TBinaryProtocolT breaks if copied/moved +- [THRIFT-2474](https://issues.apache.org/jira/browse/THRIFT-2474) - thrift.h causes a compile failure +- [THRIFT-2540](https://issues.apache.org/jira/browse/THRIFT-2540) - Running configure from outside the source directory fails +- [THRIFT-2598](https://issues.apache.org/jira/browse/THRIFT-2598) - Add check for minimum Go version to configure.ac +- [THRIFT-2647](https://issues.apache.org/jira/browse/THRIFT-2647) - compiler-hs: don't decapitalize field names, do decapitalize argument bindings +- [THRIFT-2773](https://issues.apache.org/jira/browse/THRIFT-2773) - Generated Java code for 'oneway' methods is incorrect. +- [THRIFT-2789](https://issues.apache.org/jira/browse/THRIFT-2789) - TNonblockingServer leaks socket FD's under load +- [THRIFT-2682](https://issues.apache.org/jira/browse/THRIFT-2682) - TThreadedServer leaks per-thread memory +- [THRIFT-2674](https://issues.apache.org/jira/browse/THRIFT-2674) - JavaScript: declare Accept: and Content-Type: in request +- [THRIFT-3078](https://issues.apache.org/jira/browse/THRIFT-3078) - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket +- [THRIFT-3077](https://issues.apache.org/jira/browse/THRIFT-3077) - C++ TFileTransport ignores return code from ftruncate +- [THRIFT-3067](https://issues.apache.org/jira/browse/THRIFT-3067) - C++ cppcheck performance related warnings +- [THRIFT-3066](https://issues.apache.org/jira/browse/THRIFT-3066) - C++ TDenseProtocol assert modifies instead of checks +- [THRIFT-3071](https://issues.apache.org/jira/browse/THRIFT-3071) - bootstrap.sh on Ubuntu 12.04 (Precise) automake error +- [THRIFT-3069](https://issues.apache.org/jira/browse/THRIFT-3069) - C++ TServerSocket leaks socket on fcntl get or set flags error +- [THRIFT-3079](https://issues.apache.org/jira/browse/THRIFT-3079) - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket +- [THRIFT-3080](https://issues.apache.org/jira/browse/THRIFT-3080) - C++ TNonblockingServer connection leak while accept huge number connections. +- [THRIFT-3086](https://issues.apache.org/jira/browse/THRIFT-3086) - C++ Valgrind Error Cleanup +- [THRIFT-3085](https://issues.apache.org/jira/browse/THRIFT-3085) - thrift_reconnecting_client never try to reconnect +- [THRIFT-3123](https://issues.apache.org/jira/browse/THRIFT-3123) - Missing include in compiler/cpp/src/main.h breaks build in some environments +- [THRIFT-3125](https://issues.apache.org/jira/browse/THRIFT-3125) - Fix the list of exported headers in automake input +- [THRIFT-3126](https://issues.apache.org/jira/browse/THRIFT-3126) - PHP JSON serializer converts empty or int-indexed maps to lists +- [THRIFT-3132](https://issues.apache.org/jira/browse/THRIFT-3132) - Properly format date in Java @Generated annotations +- [THRIFT-3137](https://issues.apache.org/jira/browse/THRIFT-3137) - Travis build hangs after failure +- [THRIFT-3138](https://issues.apache.org/jira/browse/THRIFT-3138) - "make check" parallel execution is underministic +- [THRIFT-3139](https://issues.apache.org/jira/browse/THRIFT-3139) - JS library test is flaky +- [THRIFT-3140](https://issues.apache.org/jira/browse/THRIFT-3140) - ConcurrentModificationException is thrown by JavaScript test server +- [THRIFT-3124](https://issues.apache.org/jira/browse/THRIFT-3124) - Some signed/unsigned warnings while building compiler +- [THRIFT-3128](https://issues.apache.org/jira/browse/THRIFT-3128) - Go generated code produces name collisions between services +- [THRIFT-3146](https://issues.apache.org/jira/browse/THRIFT-3146) - Graphviz generates function name collisions between services +- [THRIFT-3147](https://issues.apache.org/jira/browse/THRIFT-3147) - Segfault while receiving data +- [THRIFT-3148](https://issues.apache.org/jira/browse/THRIFT-3148) - Markdown links to coding_standards are dead +- [THRIFT-3090](https://issues.apache.org/jira/browse/THRIFT-3090) - cmake build is broken on MacOSX +- [THRIFT-3097](https://issues.apache.org/jira/browse/THRIFT-3097) - cmake targets unconditionally depend on optional libraries +- [THRIFT-3094](https://issues.apache.org/jira/browse/THRIFT-3094) - master as of 2015-APR-13 fails -DBOOST_THREADS cmake build +- [THRIFT-3099](https://issues.apache.org/jira/browse/THRIFT-3099) - cmake build is broken on FreeBSD +- [THRIFT-3089](https://issues.apache.org/jira/browse/THRIFT-3089) - Assigning default ENUM values results in non-compilable java code if java namespace is not defined +- [THRIFT-3093](https://issues.apache.org/jira/browse/THRIFT-3093) - mingw compile fixes for c++ library 0.9.2 +- [THRIFT-3098](https://issues.apache.org/jira/browse/THRIFT-3098) - Thrift does not pretty print binary typedefs the way it does binary fields +- [THRIFT-3091](https://issues.apache.org/jira/browse/THRIFT-3091) - c_glib service method should return result from handler method +- [THRIFT-3088](https://issues.apache.org/jira/browse/THRIFT-3088) - TThreadPoolServer with Sasl auth may leak CLOSE_WAIT socket +- [THRIFT-3109](https://issues.apache.org/jira/browse/THRIFT-3109) - Cross test log file cannot be browsed when served in HTTP server +- [THRIFT-3113](https://issues.apache.org/jira/browse/THRIFT-3113) - m4 C++11 macro issue +- [THRIFT-3105](https://issues.apache.org/jira/browse/THRIFT-3105) - C++ libthriftnb library on Windows build failure +- [THRIFT-3115](https://issues.apache.org/jira/browse/THRIFT-3115) - Uncompileable code due to name collision with predefined used types +- [THRIFT-3117](https://issues.apache.org/jira/browse/THRIFT-3117) - Java TSSLTransportFactory can't load certificates within JAR archive +- [THRIFT-3102](https://issues.apache.org/jira/browse/THRIFT-3102) - could not make check for Go Library +- [THRIFT-3120](https://issues.apache.org/jira/browse/THRIFT-3120) - Minor spelling errors and an outdated URL +- [THRIFT-3121](https://issues.apache.org/jira/browse/THRIFT-3121) - Librt does not exist on OS X +- [THRIFT-3152](https://issues.apache.org/jira/browse/THRIFT-3152) - Compiler error on Mac OSX (missing #include ) +- [THRIFT-3162](https://issues.apache.org/jira/browse/THRIFT-3162) - make fails for dmd 2.067 +- [THRIFT-3164](https://issues.apache.org/jira/browse/THRIFT-3164) - Thrift C++ library SSL socket by default allows for unsecure SSLv3 negotiation +- [THRIFT-3168](https://issues.apache.org/jira/browse/THRIFT-3168) - Fix Maven POM +- [THRIFT-3170](https://issues.apache.org/jira/browse/THRIFT-3170) - Initialism code in the Go compiler causes chaos +- [THRIFT-3169](https://issues.apache.org/jira/browse/THRIFT-3169) - Do not export thrift.TestStruct and thrift.TestEnum in thrift Go library +- [THRIFT-3191](https://issues.apache.org/jira/browse/THRIFT-3191) - Perl compiler does not add support for unexpected exception handling +- [THRIFT-3178](https://issues.apache.org/jira/browse/THRIFT-3178) - glib C does not compile +- [THRIFT-3189](https://issues.apache.org/jira/browse/THRIFT-3189) - Perl ServerSocket should allow a specific interface to be listened to +- [THRIFT-3252](https://issues.apache.org/jira/browse/THRIFT-3252) - Missing TConcurrentClientSyncInfo.h in cpp Makefile, so doesn't install +- [THRIFT-3255](https://issues.apache.org/jira/browse/THRIFT-3255) - Thrift generator doesn't exclude 'package' keyword for thrift property names breaking java builds +- [THRIFT-3260](https://issues.apache.org/jira/browse/THRIFT-3260) - multiple warnings in c_glib tutorial +- [THRIFT-3256](https://issues.apache.org/jira/browse/THRIFT-3256) - Some D test timings are too aggressive for slow machines +- [THRIFT-3257](https://issues.apache.org/jira/browse/THRIFT-3257) - warning: extra tokens at end of #endif directive +- [THRIFT-3184](https://issues.apache.org/jira/browse/THRIFT-3184) - Thrift Go leaves file descriptors open +- [THRIFT-3203](https://issues.apache.org/jira/browse/THRIFT-3203) - DOAP - please fix "Ocaml" => "OCaml" +- [THRIFT-3210](https://issues.apache.org/jira/browse/THRIFT-3210) - (uncompileable) code generated for server events while are events not enabled +- [THRIFT-3215](https://issues.apache.org/jira/browse/THRIFT-3215) - TJSONProtocol '(c++) uses "throw new" to throw exceptions instead of "throw" +- [THRIFT-3202](https://issues.apache.org/jira/browse/THRIFT-3202) - Allow HSHAServer to configure min and max worker threads separately. +- [THRIFT-3205](https://issues.apache.org/jira/browse/THRIFT-3205) - TCompactProtocol return a wrong error when the io.EOF happens +- [THRIFT-3209](https://issues.apache.org/jira/browse/THRIFT-3209) - LGPL mentioned in license file +- [THRIFT-3197](https://issues.apache.org/jira/browse/THRIFT-3197) - keepAliveTime is hard coded as 60 sec in TThreadPoolServer +- [THRIFT-3196](https://issues.apache.org/jira/browse/THRIFT-3196) - Misspelling in lua TBinaryProtocol (stirctWrite => strictWrite) +- [THRIFT-3198](https://issues.apache.org/jira/browse/THRIFT-3198) - Allow construction of TTransportFactory with a specified maxLength +- [THRIFT-3192](https://issues.apache.org/jira/browse/THRIFT-3192) - Go import paths changed in 1.4, and expired June 1 +- [THRIFT-3271](https://issues.apache.org/jira/browse/THRIFT-3271) - Could not find or load main class configtest_ax_javac_and_java on some non-english systems +- [THRIFT-3273](https://issues.apache.org/jira/browse/THRIFT-3273) - c_glib: Generated code tries to convert between function and void pointers +- [THRIFT-3264](https://issues.apache.org/jira/browse/THRIFT-3264) - Fix Erlang 16 namespaced types +- [THRIFT-3270](https://issues.apache.org/jira/browse/THRIFT-3270) - reusing TNonblockingServer::TConnection cause dirty TSocket +- [THRIFT-3267](https://issues.apache.org/jira/browse/THRIFT-3267) - c_glib: "Critical" failure during unit tests +- [THRIFT-3277](https://issues.apache.org/jira/browse/THRIFT-3277) - THttpClient leaks connections if it's used for multiple requests +- [THRIFT-3278](https://issues.apache.org/jira/browse/THRIFT-3278) - NodeJS: Fix exception stack traces and names +- [THRIFT-3279](https://issues.apache.org/jira/browse/THRIFT-3279) - Fix a bug in retry_max_delay (NodeJS) +- [THRIFT-3280](https://issues.apache.org/jira/browse/THRIFT-3280) - Initialize retry variables on construction +- [THRIFT-3283](https://issues.apache.org/jira/browse/THRIFT-3283) - c_glib: Tutorial server always exits with warning +- [THRIFT-3284](https://issues.apache.org/jira/browse/THRIFT-3284) - c_glib: Empty service produces unused-variable warning +- [THRIFT-1925](https://issues.apache.org/jira/browse/THRIFT-1925) - c_glib generated code does not compile +- [THRIFT-1849](https://issues.apache.org/jira/browse/THRIFT-1849) - after transport->open() opens isOpen returns true and next open() goes thru when it shall not +- [THRIFT-1866](https://issues.apache.org/jira/browse/THRIFT-1866) - java compiler generates non-compiling code with const's defined in a thrift when name includes non-identifier chars +- [THRIFT-1938](https://issues.apache.org/jira/browse/THRIFT-1938) - FunctionRunner.h -- uses wrong path for Thread.h when installed +- [THRIFT-1844](https://issues.apache.org/jira/browse/THRIFT-1844) - Password string not cleared +- [THRIFT-2004](https://issues.apache.org/jira/browse/THRIFT-2004) - Thrift::Union violates :== method contract and crashes +- [THRIFT-2073](https://issues.apache.org/jira/browse/THRIFT-2073) - Thrift C++ THttpClient error: cannot refill buffer +- [THRIFT-2127](https://issues.apache.org/jira/browse/THRIFT-2127) - Autoconf scripting does not properly account for cross-compile +- [THRIFT-2180](https://issues.apache.org/jira/browse/THRIFT-2180) - Integer types issues in Cocoa lib on ARM64 +- [THRIFT-2189](https://issues.apache.org/jira/browse/THRIFT-2189) - Go needs "isset" to fully support "union" type (and optionals) +- [THRIFT-2192](https://issues.apache.org/jira/browse/THRIFT-2192) - autotools on Redhat based systems +- [THRIFT-2546](https://issues.apache.org/jira/browse/THRIFT-2546) - cross language tests fails at 'TestMultiException' when using nodejs server +- [THRIFT-2547](https://issues.apache.org/jira/browse/THRIFT-2547) - nodejs servers and clients fails to connect with cpp using compact protocol +- [THRIFT-2548](https://issues.apache.org/jira/browse/THRIFT-2548) - Nodejs servers and clients does not work properly with -ssl +- [THRIFT-1471](https://issues.apache.org/jira/browse/THRIFT-1471) - toString() does not print ByteBuffer values when nested in a List +- [THRIFT-1201](https://issues.apache.org/jira/browse/THRIFT-1201) - getaddrinfo resource leak +- [THRIFT-615](https://issues.apache.org/jira/browse/THRIFT-615) - TThreadPoolServer doesn't call task_done after pulling tasks from it's clients queue +- [THRIFT-162](https://issues.apache.org/jira/browse/THRIFT-162) - Thrift structures are unhashable, preventing them from being used as set elements +- [THRIFT-810](https://issues.apache.org/jira/browse/THRIFT-810) - Crashed client on TSocket::close under loads +- [THRIFT-557](https://issues.apache.org/jira/browse/THRIFT-557) - charset problem with file Autogenerated by Thrift +- [THRIFT-233](https://issues.apache.org/jira/browse/THRIFT-233) - IDL doesn't support negative hex literals +- [THRIFT-1649](https://issues.apache.org/jira/browse/THRIFT-1649) - contrib/zeromq does not build in 0.8.0 +- [THRIFT-1642](https://issues.apache.org/jira/browse/THRIFT-1642) - Miscalculation lead to throw unexpected "TTransportException::TIMED_OUT"(or called "EAGAIN (timed out)") exception +- [THRIFT-1587](https://issues.apache.org/jira/browse/THRIFT-1587) - TSocket::setRecvTimeout error +- [THRIFT-1248](https://issues.apache.org/jira/browse/THRIFT-1248) - pointer subtraction in TMemoryBuffer relies on undefined behavior +- [THRIFT-1774](https://issues.apache.org/jira/browse/THRIFT-1774) - Sasl Transport client would hang when trying to connect non-sasl transport server +- [THRIFT-1754](https://issues.apache.org/jira/browse/THRIFT-1754) - RangeError in buffer handling +- [THRIFT-1618](https://issues.apache.org/jira/browse/THRIFT-1618) - static structMap in FieldMetaData is not thread safe and can lead to deadlocks +- [THRIFT-2335](https://issues.apache.org/jira/browse/THRIFT-2335) - thrift incompatibility with py:tornado as server, java as client +- [THRIFT-2803](https://issues.apache.org/jira/browse/THRIFT-2803) - TCP_DEFER_ACCEPT not supported with domain sockets +- [THRIFT-2799](https://issues.apache.org/jira/browse/THRIFT-2799) - Build Problem(s): ld: library not found for -l:libboost_unit_test_framework.a +- [THRIFT-2801](https://issues.apache.org/jira/browse/THRIFT-2801) - C++ test suite compilation warnings +- [THRIFT-2802](https://issues.apache.org/jira/browse/THRIFT-2802) - C++ tutorial compilation warnings +- [THRIFT-2795](https://issues.apache.org/jira/browse/THRIFT-2795) - thrift_binary_protocol.c: 'dereferencing type-punned pointer will break strict-aliasing rules' +- [THRIFT-2817](https://issues.apache.org/jira/browse/THRIFT-2817) - TSimpleJSONProtocol reads beyond end of message +- [THRIFT-2826](https://issues.apache.org/jira/browse/THRIFT-2826) - html:standalone sometimes ignored +- [THRIFT-2829](https://issues.apache.org/jira/browse/THRIFT-2829) - Support haxelib installation via github +- [THRIFT-2828](https://issues.apache.org/jira/browse/THRIFT-2828) - slightly wrong help screen indent +- [THRIFT-2831](https://issues.apache.org/jira/browse/THRIFT-2831) - Removes dead code in web_server.js introduced in THRIFT-2819 +- [THRIFT-2823](https://issues.apache.org/jira/browse/THRIFT-2823) - All JS-tests are failing when run with grunt test +- [THRIFT-2827](https://issues.apache.org/jira/browse/THRIFT-2827) - Thrift 0.9.2 fails to compile on Yosemite due to tr1/functional include in ProcessorTest.cpp +- [THRIFT-2843](https://issues.apache.org/jira/browse/THRIFT-2843) - Automake configure.ac has possible typo related to Java +- [THRIFT-2813](https://issues.apache.org/jira/browse/THRIFT-2813) - multiple haxe library fixes/improvements +- [THRIFT-2825](https://issues.apache.org/jira/browse/THRIFT-2825) - Supplying unicode to python Thrift client can cause next request arguments to get overwritten +- [THRIFT-2840](https://issues.apache.org/jira/browse/THRIFT-2840) - Cabal file points to LICENSE file outside the path of the Haskell project. +- [THRIFT-2818](https://issues.apache.org/jira/browse/THRIFT-2818) - Trailing commas in array +- [THRIFT-2830](https://issues.apache.org/jira/browse/THRIFT-2830) - Clean up ant warnings in tutorial dir +- [THRIFT-2842](https://issues.apache.org/jira/browse/THRIFT-2842) - Erlang thrift client has infinite timeout +- [THRIFT-2810](https://issues.apache.org/jira/browse/THRIFT-2810) - Do not leave the underlying ServerSocket open if construction of TServerSocket fails +- [THRIFT-2812](https://issues.apache.org/jira/browse/THRIFT-2812) - Go server adding redundant buffering layer +- [THRIFT-2839](https://issues.apache.org/jira/browse/THRIFT-2839) - TFramedTransport read bug +- [THRIFT-2844](https://issues.apache.org/jira/browse/THRIFT-2844) - Nodejs support broken when running under Browserify +- [THRIFT-2814](https://issues.apache.org/jira/browse/THRIFT-2814) - args/result classes not found when no namespace is set +- [THRIFT-2847](https://issues.apache.org/jira/browse/THRIFT-2847) - function IfValue() is a duplicate of System.StrUtils.IfThen +- [THRIFT-2848](https://issues.apache.org/jira/browse/THRIFT-2848) - certain Delphi tests do not build if TypeRegistry is used +- [THRIFT-2854](https://issues.apache.org/jira/browse/THRIFT-2854) - Go Struct writer and reader looses important error information +- [THRIFT-2858](https://issues.apache.org/jira/browse/THRIFT-2858) - Enable header field case insensitive match in THttpServer +- [THRIFT-2857](https://issues.apache.org/jira/browse/THRIFT-2857) - C# generator creates uncompilable code for struct constants +- [THRIFT-2860](https://issues.apache.org/jira/browse/THRIFT-2860) - Delphi server closes connection on unexpected exceptions +- [THRIFT-2868](https://issues.apache.org/jira/browse/THRIFT-2868) - Enhance error handling in the Go client +- [THRIFT-2879](https://issues.apache.org/jira/browse/THRIFT-2879) - TMemoryBuffer: using lua string in wrong way +- [THRIFT-2851](https://issues.apache.org/jira/browse/THRIFT-2851) - Remove strange public Peek() from Go transports +- [THRIFT-2852](https://issues.apache.org/jira/browse/THRIFT-2852) - Better Open/IsOpen/Close behavior for StreamTransport. +- [THRIFT-2871](https://issues.apache.org/jira/browse/THRIFT-2871) - Missing semicolon in thrift.js +- [THRIFT-2872](https://issues.apache.org/jira/browse/THRIFT-2872) - ThreadManager deadlock for task expiration +- [THRIFT-2881](https://issues.apache.org/jira/browse/THRIFT-2881) - Handle errors from Accept() correctly +- [THRIFT-2849](https://issues.apache.org/jira/browse/THRIFT-2849) - Spell errors reported by codespell tool +- [THRIFT-2870](https://issues.apache.org/jira/browse/THRIFT-2870) - C++ TJSONProtocol using locale dependent formatting +- [THRIFT-2882](https://issues.apache.org/jira/browse/THRIFT-2882) - Lua Generator: using string.len funtion to get struct(map,list,set) size +- [THRIFT-2864](https://issues.apache.org/jira/browse/THRIFT-2864) - JSON generator missing from Visual Studio build project +- [THRIFT-2878](https://issues.apache.org/jira/browse/THRIFT-2878) - Go validation support of required fields +- [THRIFT-2873](https://issues.apache.org/jira/browse/THRIFT-2873) - TPipe and TPipeServer don't compile on Windows with UNICODE enabled +- [THRIFT-2888](https://issues.apache.org/jira/browse/THRIFT-2888) - import of is missing in JSON generator +- [THRIFT-2900](https://issues.apache.org/jira/browse/THRIFT-2900) - Python THttpClient does not reset socket timeout on exception +- [THRIFT-2907](https://issues.apache.org/jira/browse/THRIFT-2907) - 'ntohll' macro redefined +- [THRIFT-2884](https://issues.apache.org/jira/browse/THRIFT-2884) - Map does not serialize correctly for JSON protocol in Go library +- [THRIFT-2887](https://issues.apache.org/jira/browse/THRIFT-2887) - --with-openssl configure flag is ignored +- [THRIFT-2894](https://issues.apache.org/jira/browse/THRIFT-2894) - PHP json serializer skips maps with int/bool keys +- [THRIFT-2904](https://issues.apache.org/jira/browse/THRIFT-2904) - json_protocol_test.go fails +- [THRIFT-2906](https://issues.apache.org/jira/browse/THRIFT-2906) - library not found for -l:libboost_unit_test_framework.a +- [THRIFT-2890](https://issues.apache.org/jira/browse/THRIFT-2890) - binary data may lose bytes with JSON transport under specific circumstances +- [THRIFT-2891](https://issues.apache.org/jira/browse/THRIFT-2891) - binary data may cause a failure with JSON transport under specific circumstances +- [THRIFT-2901](https://issues.apache.org/jira/browse/THRIFT-2901) - Fix for generated TypeScript functions + indentation of JavaScript maps +- [THRIFT-2916](https://issues.apache.org/jira/browse/THRIFT-2916) - make check fails for D language +- [THRIFT-2918](https://issues.apache.org/jira/browse/THRIFT-2918) - Race condition in Python TProcessPoolServer test +- [THRIFT-2920](https://issues.apache.org/jira/browse/THRIFT-2920) - Erlang Thrift test uses wrong IDL file +- [THRIFT-2922](https://issues.apache.org/jira/browse/THRIFT-2922) - $TRIAL is used with Python tests but not tested accordingly +- [THRIFT-2912](https://issues.apache.org/jira/browse/THRIFT-2912) - Autotool build for C++ Qt library is invalid +- [THRIFT-2914](https://issues.apache.org/jira/browse/THRIFT-2914) - explicit dependency to Lua5.2 fails on some systems +- [THRIFT-2910](https://issues.apache.org/jira/browse/THRIFT-2910) - libevent is not really optional +- [THRIFT-2911](https://issues.apache.org/jira/browse/THRIFT-2911) - fix c++ version zeromq transport, the old version cannot work +- [THRIFT-2915](https://issues.apache.org/jira/browse/THRIFT-2915) - Lua generator missing from Visual Studio build project +- [THRIFT-2917](https://issues.apache.org/jira/browse/THRIFT-2917) - "make clean" breaks test/c_glib +- [THRIFT-2919](https://issues.apache.org/jira/browse/THRIFT-2919) - Haxe test server timeout too large +- [THRIFT-2923](https://issues.apache.org/jira/browse/THRIFT-2923) - JavaScript client assumes a message being written +- [THRIFT-2924](https://issues.apache.org/jira/browse/THRIFT-2924) - TNonblockingServer crashes when user-provided event_base is used +- [THRIFT-2925](https://issues.apache.org/jira/browse/THRIFT-2925) - CMake build does not work with OpenSSL nor anything installed in non-system location +- [THRIFT-2931](https://issues.apache.org/jira/browse/THRIFT-2931) - Access to undeclared static property: Thrift\Protocol\TProtocol::$TBINARYPROTOCOLACCELERATED +- [THRIFT-2893](https://issues.apache.org/jira/browse/THRIFT-2893) - CMake build fails with boost thread or std thread +- [THRIFT-2902](https://issues.apache.org/jira/browse/THRIFT-2902) - Generated c_glib code does not compile with clang +- [THRIFT-2903](https://issues.apache.org/jira/browse/THRIFT-2903) - Qt4 library built with CMake does not work +- [THRIFT-2942](https://issues.apache.org/jira/browse/THRIFT-2942) - CSharp generate invalid code for property named read or write +- [THRIFT-2932](https://issues.apache.org/jira/browse/THRIFT-2932) - Node.js Thrift connection libraries throw Exceptions into event emitter +- [THRIFT-2933](https://issues.apache.org/jira/browse/THRIFT-2933) - v0.9.2: doubles encoded in node with compact protocol cannot be decoded by python +- [THRIFT-2934](https://issues.apache.org/jira/browse/THRIFT-2934) - createServer signature mismatch +- [THRIFT-2981](https://issues.apache.org/jira/browse/THRIFT-2981) - IDL with no namespace produces unparsable PHP +- [THRIFT-2999](https://issues.apache.org/jira/browse/THRIFT-2999) - Addition of .gitattributes text auto in THRIFT-2724 causes modified files on checkout +- [THRIFT-2949](https://issues.apache.org/jira/browse/THRIFT-2949) - typo in compiler/cpp/README.md +- [THRIFT-2957](https://issues.apache.org/jira/browse/THRIFT-2957) - warning: source file %s is in a subdirectory, but option 'subdir-objects' is disabled +- [THRIFT-2953](https://issues.apache.org/jira/browse/THRIFT-2953) - TNamedPipeServerTransport is not Stop()able +- [THRIFT-2962](https://issues.apache.org/jira/browse/THRIFT-2962) - Docker Thrift env for development and testing +- [THRIFT-2971](https://issues.apache.org/jira/browse/THRIFT-2971) - C++ test and tutorial parallel build is unstable +- [THRIFT-2972](https://issues.apache.org/jira/browse/THRIFT-2972) - Missing backslash in lib/cpp/test/Makefile.am +- [THRIFT-2951](https://issues.apache.org/jira/browse/THRIFT-2951) - Fix Erlang name conflict test +- [THRIFT-2955](https://issues.apache.org/jira/browse/THRIFT-2955) - Using list of typedefs does not compile on Go +- [THRIFT-2960](https://issues.apache.org/jira/browse/THRIFT-2960) - namespace regression for Ruby +- [THRIFT-2959](https://issues.apache.org/jira/browse/THRIFT-2959) - nodejs: fix binary unit tests +- [THRIFT-2966](https://issues.apache.org/jira/browse/THRIFT-2966) - nodejs: Fix bad references to TProtocolException and TProtocolExceptionType +- [THRIFT-2970](https://issues.apache.org/jira/browse/THRIFT-2970) - grunt-jsdoc fails due to dependency issues +- [THRIFT-3001](https://issues.apache.org/jira/browse/THRIFT-3001) - C# Equals fails for binary fields (byte[]) +- [THRIFT-3003](https://issues.apache.org/jira/browse/THRIFT-3003) - Missing LICENSE file prevents package from being installed +- [THRIFT-3008](https://issues.apache.org/jira/browse/THRIFT-3008) - Node.js server does not fully support exception +- [THRIFT-3007](https://issues.apache.org/jira/browse/THRIFT-3007) - Travis build is broken because of directory conflict +- [THRIFT-3009](https://issues.apache.org/jira/browse/THRIFT-3009) - TSSLSocket does not use the correct hostname (breaks certificate checks) +- [THRIFT-3011](https://issues.apache.org/jira/browse/THRIFT-3011) - C# test server testException() not implemented according to specs +- [THRIFT-3012](https://issues.apache.org/jira/browse/THRIFT-3012) - Timing problems in NamedPipe implementation due to unnecessary open/close +- [THRIFT-3019](https://issues.apache.org/jira/browse/THRIFT-3019) - Golang generator missing docstring for structs +- [THRIFT-3021](https://issues.apache.org/jira/browse/THRIFT-3021) - Service remote tool does not import stub package with package prefix +- [THRIFT-3026](https://issues.apache.org/jira/browse/THRIFT-3026) - TMultiplexedProcessor does not have a constructor +- [THRIFT-3028](https://issues.apache.org/jira/browse/THRIFT-3028) - Regression caused by THRIFT-2180 +- [THRIFT-3017](https://issues.apache.org/jira/browse/THRIFT-3017) - order of map key/value types incorrect for one CTOR +- [THRIFT-3020](https://issues.apache.org/jira/browse/THRIFT-3020) - Cannot compile thrift as C++03 +- [THRIFT-3024](https://issues.apache.org/jira/browse/THRIFT-3024) - User-Agent "BattleNet" used in some Thrift library files +- [THRIFT-3047](https://issues.apache.org/jira/browse/THRIFT-3047) - Uneven calls to indent_up and indent_down in Cocoa generator +- [THRIFT-3048](https://issues.apache.org/jira/browse/THRIFT-3048) - NodeJS decoding of I64 is inconsistent across protocols +- [THRIFT-3043](https://issues.apache.org/jira/browse/THRIFT-3043) - go compiler generator uses non C++98 code +- [THRIFT-3044](https://issues.apache.org/jira/browse/THRIFT-3044) - Docker README.md paths to Dockerfiles are incorrect +- [THRIFT-3040](https://issues.apache.org/jira/browse/THRIFT-3040) - bower.json wrong "main" path +- [THRIFT-3051](https://issues.apache.org/jira/browse/THRIFT-3051) - Go Thrift generator creates bad go code +- [THRIFT-3057](https://issues.apache.org/jira/browse/THRIFT-3057) - Java compiler build is broken +- [THRIFT-3061](https://issues.apache.org/jira/browse/THRIFT-3061) - C++ TSSLSocket shutdown delay/vulnerability +- [THRIFT-3062](https://issues.apache.org/jira/browse/THRIFT-3062) - C++ TServerSocket invalid port number (over 999999) causes stack corruption +- [THRIFT-3065](https://issues.apache.org/jira/browse/THRIFT-3065) - Update libthrift dependencies (slf4j, httpcore, httpclient) +- [THRIFT-3244](https://issues.apache.org/jira/browse/THRIFT-3244) - TypeScript: fix namespace of included types +- [THRIFT-3246](https://issues.apache.org/jira/browse/THRIFT-3246) - Reduce the number of trivial warnings in Windows C++ CMake builds +- [THRIFT-3224](https://issues.apache.org/jira/browse/THRIFT-3224) - Fix TNamedPipeServer unpredictable behavior on accept +- [THRIFT-3230](https://issues.apache.org/jira/browse/THRIFT-3230) - Python compiler generates wrong code if there is function throwing a typedef of exception with another namespace +- [THRIFT-3236](https://issues.apache.org/jira/browse/THRIFT-3236) - MaxSkipDepth never checked +- [THRIFT-3239](https://issues.apache.org/jira/browse/THRIFT-3239) - Limit recursion depth +- [THRIFT-3241](https://issues.apache.org/jira/browse/THRIFT-3241) - fatal error: runtime: cannot map pages in arena address space +- [THRIFT-3242](https://issues.apache.org/jira/browse/THRIFT-3242) - OSGi Import-Package directive is missing the Apache HTTP packages +- [THRIFT-3234](https://issues.apache.org/jira/browse/THRIFT-3234) - Limit recursion depth +- [THRIFT-3222](https://issues.apache.org/jira/browse/THRIFT-3222) - TypeScript: Generated Enums are quoted +- [THRIFT-3229](https://issues.apache.org/jira/browse/THRIFT-3229) - unexpected Timeout exception when desired bytes are only partially available +- [THRIFT-3231](https://issues.apache.org/jira/browse/THRIFT-3231) - CPP: Limit recursion depth to 64 +- [THRIFT-3235](https://issues.apache.org/jira/browse/THRIFT-3235) - Limit recursion depth +- [THRIFT-3175](https://issues.apache.org/jira/browse/THRIFT-3175) - fastbinary.c python deserialize can cause huge allocations from garbage +- [THRIFT-3176](https://issues.apache.org/jira/browse/THRIFT-3176) - Union incorrectly implements == +- [THRIFT-3177](https://issues.apache.org/jira/browse/THRIFT-3177) - Fails to run rake test +- [THRIFT-3180](https://issues.apache.org/jira/browse/THRIFT-3180) - lua plugin: framed transport do not work +- [THRIFT-3179](https://issues.apache.org/jira/browse/THRIFT-3179) - lua plugin cant connect to remote server because function l_socket_create_and_connect always bind socket to localhost +- [THRIFT-3248](https://issues.apache.org/jira/browse/THRIFT-3248) - TypeScript: additional comma in method signature without parameters +- [THRIFT-3302](https://issues.apache.org/jira/browse/THRIFT-3302) - Go JSON protocol should encode Thrift byte type as signed integer string +- [THRIFT-3297](https://issues.apache.org/jira/browse/THRIFT-3297) - c_glib: an abstract base class is not generated +- [THRIFT-3294](https://issues.apache.org/jira/browse/THRIFT-3294) - TZlibTransport for Java does not write data correctly +- [THRIFT-3296](https://issues.apache.org/jira/browse/THRIFT-3296) - Go cross test does not conform to spec +- [THRIFT-3295](https://issues.apache.org/jira/browse/THRIFT-3295) - C# library does not build on Mono 4.0.2.5 or later +- [THRIFT-3293](https://issues.apache.org/jira/browse/THRIFT-3293) - JavaScript: null values turn into empty structs in constructor +- [THRIFT-3310](https://issues.apache.org/jira/browse/THRIFT-3310) - lib/erl/README.md has incorrect formatting +- [THRIFT-3319](https://issues.apache.org/jira/browse/THRIFT-3319) - CSharp tutorial will not build using the *.sln +- [THRIFT-3335](https://issues.apache.org/jira/browse/THRIFT-3335) - Ruby server does not handle processor exception +- [THRIFT-3338](https://issues.apache.org/jira/browse/THRIFT-3338) - Stray underscore in generated go when service name starts with "New" +- [THRIFT-3324](https://issues.apache.org/jira/browse/THRIFT-3324) - Update Go Docs for pulling all packages +- [THRIFT-3345](https://issues.apache.org/jira/browse/THRIFT-3345) - Clients blocked indefinitely when a java.lang.Error is thrown +- [THRIFT-3332](https://issues.apache.org/jira/browse/THRIFT-3332) - make dist fails on clean build +- [THRIFT-3326](https://issues.apache.org/jira/browse/THRIFT-3326) - Tests do not compile under *BSD +- [THRIFT-3334](https://issues.apache.org/jira/browse/THRIFT-3334) - Markdown notation of protocol spec is malformed +- [THRIFT-3331](https://issues.apache.org/jira/browse/THRIFT-3331) - warning: ‘etype’ may be used uninitialized in this function +- [THRIFT-3349](https://issues.apache.org/jira/browse/THRIFT-3349) - Python server does not handle processor exception +- [THRIFT-3343](https://issues.apache.org/jira/browse/THRIFT-3343) - Fix haskell README +- [THRIFT-3340](https://issues.apache.org/jira/browse/THRIFT-3340) - Python: enable json tests again +- [THRIFT-3311](https://issues.apache.org/jira/browse/THRIFT-3311) - Top level README.md has incorrect formmating +- [THRIFT-2936](https://issues.apache.org/jira/browse/THRIFT-2936) - Minor memory leak in SSL +- [THRIFT-3290](https://issues.apache.org/jira/browse/THRIFT-3290) - Using from in variable names causes the generated Python code to have errors +- [THRIFT-3225](https://issues.apache.org/jira/browse/THRIFT-3225) - Fix TPipeServer unpredictable behavior on interrupt() +- [THRIFT-3354](https://issues.apache.org/jira/browse/THRIFT-3354) - Fix word-extraction substr bug in initialism code +- [THRIFT-2006](https://issues.apache.org/jira/browse/THRIFT-2006) - TBinaryProtocol message header call name length is not validated and can be used to core the server +- [THRIFT-3329](https://issues.apache.org/jira/browse/THRIFT-3329) - C++ library unit tests don't compile against the new boost-1.59 unit test framework +- [THRIFT-2630](https://issues.apache.org/jira/browse/THRIFT-2630) - windows7 64bit pc. ipv4 and ipv6 pc.can't use +- [THRIFT-3336](https://issues.apache.org/jira/browse/THRIFT-3336) - Thrift generated streaming operators added in 0.9.2 cannot be overridden +- [THRIFT-2681](https://issues.apache.org/jira/browse/THRIFT-2681) - Core of unwind_cleanup +- [THRIFT-3317](https://issues.apache.org/jira/browse/THRIFT-3317) - cpp namespace org.apache issue appears in 0.9 + +### Documentation +- [THRIFT-3286](https://issues.apache.org/jira/browse/THRIFT-3286) - Apache Ant is a necessary dependency + +### Improvement +- [THRIFT-227](https://issues.apache.org/jira/browse/THRIFT-227) - Byte[] in collections aren't pretty printed like regular binary fields +- [THRIFT-2744](https://issues.apache.org/jira/browse/THRIFT-2744) - Vagrantfile for Centos 6.5 +- [THRIFT-2644](https://issues.apache.org/jira/browse/THRIFT-2644) - Haxe support +- [THRIFT-2756](https://issues.apache.org/jira/browse/THRIFT-2756) - register Media Type @ IANA +- [THRIFT-3076](https://issues.apache.org/jira/browse/THRIFT-3076) - Compatibility with Haxe 3.2.0 +- [THRIFT-3081](https://issues.apache.org/jira/browse/THRIFT-3081) - C++ Consolidate client processing loops in TServers +- [THRIFT-3083](https://issues.apache.org/jira/browse/THRIFT-3083) - C++ Consolidate server processing loops in TSimpleServer, TThreadedServer, TThreadPoolServer +- [THRIFT-3084](https://issues.apache.org/jira/browse/THRIFT-3084) - C++ add concurrent client limit to threaded servers +- [THRIFT-3074](https://issues.apache.org/jira/browse/THRIFT-3074) - Add compiler/cpp/lex.yythriftl.cc to gitignore. +- [THRIFT-3134](https://issues.apache.org/jira/browse/THRIFT-3134) - Remove use of deprecated "phantom.args" +- [THRIFT-3133](https://issues.apache.org/jira/browse/THRIFT-3133) - Allow "make cross" and "make precross" to run without building all languages +- [THRIFT-3142](https://issues.apache.org/jira/browse/THRIFT-3142) - Make JavaScript use downloaded libraries +- [THRIFT-3141](https://issues.apache.org/jira/browse/THRIFT-3141) - Improve logging of JavaScript test +- [THRIFT-3144](https://issues.apache.org/jira/browse/THRIFT-3144) - Proposal: make String representation of enums in generated go code less verbose +- [THRIFT-3130](https://issues.apache.org/jira/browse/THRIFT-3130) - Remove the last vestiges of THRIFT_OVERLOAD_IF from THRIFT-1316 +- [THRIFT-3131](https://issues.apache.org/jira/browse/THRIFT-3131) - Consolidate suggested import path for go thrift library to git.apache.org in docs and code +- [THRIFT-3092](https://issues.apache.org/jira/browse/THRIFT-3092) - Generated Haskell types should derive Generic +- [THRIFT-3110](https://issues.apache.org/jira/browse/THRIFT-3110) - Print error log after cross test failures on Travis +- [THRIFT-3114](https://issues.apache.org/jira/browse/THRIFT-3114) - Using local temp variables to not pollute the global table +- [THRIFT-3106](https://issues.apache.org/jira/browse/THRIFT-3106) - CMake summary should give more information why a library is set to off +- [THRIFT-3119](https://issues.apache.org/jira/browse/THRIFT-3119) - Java's TThreadedSelectorServer has indistinguishable log messages in run() +- [THRIFT-3122](https://issues.apache.org/jira/browse/THRIFT-3122) - Javascript struct constructor should properly initialize struct and container members from plain js arguments +- [THRIFT-3151](https://issues.apache.org/jira/browse/THRIFT-3151) - Fix links to git-wip* - should be git.apache.org +- [THRIFT-3167](https://issues.apache.org/jira/browse/THRIFT-3167) - Windows build from source instructions need to be revised +- [THRIFT-3155](https://issues.apache.org/jira/browse/THRIFT-3155) - move contrib/mingw32-toolchain.cmake to build/cmake/ +- [THRIFT-3160](https://issues.apache.org/jira/browse/THRIFT-3160) - Make generated go enums implement TextMarshaller and TextUnmarshaller interfaces +- [THRIFT-3150](https://issues.apache.org/jira/browse/THRIFT-3150) - Add an option to thrift go generator to make Read and Write methods private +- [THRIFT-3149](https://issues.apache.org/jira/browse/THRIFT-3149) - Make ReadFieldN methods in generated Go code private +- [THRIFT-3172](https://issues.apache.org/jira/browse/THRIFT-3172) - Add tutorial to Thrift web site +- [THRIFT-3214](https://issues.apache.org/jira/browse/THRIFT-3214) - Add Erlang option for using maps instead of dicts +- [THRIFT-3201](https://issues.apache.org/jira/browse/THRIFT-3201) - Capture github test artifacts for failed builds +- [THRIFT-3266](https://issues.apache.org/jira/browse/THRIFT-3266) - c_glib: Multiple compiler warnings building unit tests +- [THRIFT-3285](https://issues.apache.org/jira/browse/THRIFT-3285) - c_glib: Build library with all warnings enabled, no warnings generated +- [THRIFT-1954](https://issues.apache.org/jira/browse/THRIFT-1954) - Allow for a separate connection timeout value +- [THRIFT-2098](https://issues.apache.org/jira/browse/THRIFT-2098) - Add support for Qt5+ +- [THRIFT-2199](https://issues.apache.org/jira/browse/THRIFT-2199) - Remove Dense protocol (was: move to Contrib) +- [THRIFT-406](https://issues.apache.org/jira/browse/THRIFT-406) - C++ Test suite cleanup +- [THRIFT-902](https://issues.apache.org/jira/browse/THRIFT-902) - socket and connect timeout in TSocket should be distinguished +- [THRIFT-388](https://issues.apache.org/jira/browse/THRIFT-388) - Use a separate wire format for async calls +- [THRIFT-727](https://issues.apache.org/jira/browse/THRIFT-727) - support native C++ language specific exception message +- [THRIFT-1784](https://issues.apache.org/jira/browse/THRIFT-1784) - pep-3110 compliance for exception handling +- [THRIFT-1025](https://issues.apache.org/jira/browse/THRIFT-1025) - C++ ServerSocket should inherit from Socket with the necessary Ctor to listen on connections from a specific host +- [THRIFT-2269](https://issues.apache.org/jira/browse/THRIFT-2269) - Can deploy libthrift-source.jar to maven center repository +- [THRIFT-2804](https://issues.apache.org/jira/browse/THRIFT-2804) - Pull an interface out of TBaseAsyncProcessor +- [THRIFT-2806](https://issues.apache.org/jira/browse/THRIFT-2806) - more whitespace fixups +- [THRIFT-2811](https://issues.apache.org/jira/browse/THRIFT-2811) - Make remote socket address accessible +- [THRIFT-2809](https://issues.apache.org/jira/browse/THRIFT-2809) - .gitignore update for compiler's visual project +- [THRIFT-2846](https://issues.apache.org/jira/browse/THRIFT-2846) - Expose ciphers parameter from ssl.wrap_socket() +- [THRIFT-2859](https://issues.apache.org/jira/browse/THRIFT-2859) - JSON generator: output complete descriptors +- [THRIFT-2861](https://issues.apache.org/jira/browse/THRIFT-2861) - add buffered transport +- [THRIFT-2865](https://issues.apache.org/jira/browse/THRIFT-2865) - Test case for Go: SeqId out of sequence +- [THRIFT-2866](https://issues.apache.org/jira/browse/THRIFT-2866) - Go generator source code is hard to read and maintain +- [THRIFT-2880](https://issues.apache.org/jira/browse/THRIFT-2880) - Read the network address from the listener if available. +- [THRIFT-2875](https://issues.apache.org/jira/browse/THRIFT-2875) - Typo in TDenseProtocol.h comment +- [THRIFT-2874](https://issues.apache.org/jira/browse/THRIFT-2874) - TBinaryProtocol member variable "string_buf_" is never used. +- [THRIFT-2855](https://issues.apache.org/jira/browse/THRIFT-2855) - Move contributing.md to the root of the repository +- [THRIFT-2862](https://issues.apache.org/jira/browse/THRIFT-2862) - Enable RTTI and/or build macros for generated code +- [THRIFT-2876](https://issues.apache.org/jira/browse/THRIFT-2876) - Add test for THRIFT-2526 Assignment operators and copy constructors in c++ don't copy the __isset struct +- [THRIFT-2897](https://issues.apache.org/jira/browse/THRIFT-2897) - Generate -isEqual: and -hash methods +- [THRIFT-2909](https://issues.apache.org/jira/browse/THRIFT-2909) - Improve travis build +- [THRIFT-2921](https://issues.apache.org/jira/browse/THRIFT-2921) - Make Erlang impl ready for OTP 18 release (dict/0 and set/0 are deprecated) +- [THRIFT-2928](https://issues.apache.org/jira/browse/THRIFT-2928) - Rename the erlang test_server module +- [THRIFT-2940](https://issues.apache.org/jira/browse/THRIFT-2940) - Allow installing Thrift from git as NPM module by providing package.json in top level directory +- [THRIFT-2937](https://issues.apache.org/jira/browse/THRIFT-2937) - Allow setting a maximum frame size in TFramedTransport +- [THRIFT-2976](https://issues.apache.org/jira/browse/THRIFT-2976) - nodejs: xhr and websocket support for browserify +- [THRIFT-2996](https://issues.apache.org/jira/browse/THRIFT-2996) - Test for Haxe 3.1.3 or better +- [THRIFT-2969](https://issues.apache.org/jira/browse/THRIFT-2969) - nodejs: DRY up library tests +- [THRIFT-2973](https://issues.apache.org/jira/browse/THRIFT-2973) - Update Haxe lib readme regarding Haxe 3.1.3 +- [THRIFT-2952](https://issues.apache.org/jira/browse/THRIFT-2952) - Improve handling of Server.Stop() +- [THRIFT-2964](https://issues.apache.org/jira/browse/THRIFT-2964) - nodejs: move protocols and transports into separate files +- [THRIFT-2963](https://issues.apache.org/jira/browse/THRIFT-2963) - nodejs - add test coverage +- [THRIFT-3006](https://issues.apache.org/jira/browse/THRIFT-3006) - Attach 'omitempty' json tag for optional fields in Go +- [THRIFT-3027](https://issues.apache.org/jira/browse/THRIFT-3027) - Go compiler does not ensure common initialisms have consistent case +- [THRIFT-3030](https://issues.apache.org/jira/browse/THRIFT-3030) - TThreadedServer: Property for number of clientThreads +- [THRIFT-3023](https://issues.apache.org/jira/browse/THRIFT-3023) - Go compiler is a little overly conservative with names of attributes +- [THRIFT-3018](https://issues.apache.org/jira/browse/THRIFT-3018) - Compact protocol for Delphi +- [THRIFT-3025](https://issues.apache.org/jira/browse/THRIFT-3025) - Change pure Int constants into @enums (where possible) +- [THRIFT-3031](https://issues.apache.org/jira/browse/THRIFT-3031) - migrate "shouldStop" flag to TServer +- [THRIFT-3022](https://issues.apache.org/jira/browse/THRIFT-3022) - Compact protocol for Haxe +- [THRIFT-3041](https://issues.apache.org/jira/browse/THRIFT-3041) - Generate asynchronous clients for Cocoa +- [THRIFT-3053](https://issues.apache.org/jira/browse/THRIFT-3053) - Perl SSL Socket Support (Encryption) +- [THRIFT-3247](https://issues.apache.org/jira/browse/THRIFT-3247) - Generate a C++ thread-safe client +- [THRIFT-3217](https://issues.apache.org/jira/browse/THRIFT-3217) - Provide a little endian variant of the binary protocol in C++ +- [THRIFT-3223](https://issues.apache.org/jira/browse/THRIFT-3223) - TypeScript: Add initial support for Enum Maps +- [THRIFT-3220](https://issues.apache.org/jira/browse/THRIFT-3220) - Option to suppress @Generated Annotation entirely +- [THRIFT-3300](https://issues.apache.org/jira/browse/THRIFT-3300) - Reimplement TZlibTransport in Java using streams +- [THRIFT-3288](https://issues.apache.org/jira/browse/THRIFT-3288) - c_glib: Build unit tests with all warnings enabled, no warnings generated +- [THRIFT-3347](https://issues.apache.org/jira/browse/THRIFT-3347) - Improve cross test servers and clients +- [THRIFT-3342](https://issues.apache.org/jira/browse/THRIFT-3342) - Improve ruby cross test client and server compatibility +- [THRIFT-2296](https://issues.apache.org/jira/browse/THRIFT-2296) - Add C++ Base class for service +- [THRIFT-3337](https://issues.apache.org/jira/browse/THRIFT-3337) - Add testBool method to cross tests +- [THRIFT-3303](https://issues.apache.org/jira/browse/THRIFT-3303) - Disable concurrent cabal jobs on Travis to avoid GHC crash +- [THRIFT-2623](https://issues.apache.org/jira/browse/THRIFT-2623) - Docker container for Thrift +- [THRIFT-3298](https://issues.apache.org/jira/browse/THRIFT-3298) - thrift endian converters may conflict with other libraries +- [THRIFT-1559](https://issues.apache.org/jira/browse/THRIFT-1559) - Provide memory pool for TBinaryProtocol to eliminate memory fragmentation +- [THRIFT-424](https://issues.apache.org/jira/browse/THRIFT-424) - Steal ProtocolBuffers' VarInt implementation for C++ + +### New Feature +- [THRIFT-3070](https://issues.apache.org/jira/browse/THRIFT-3070) - Add ability to set the LocalCertificateSelectionCallback +- [THRIFT-1909](https://issues.apache.org/jira/browse/THRIFT-1909) - Java: Add compiler flag to use the "option pattern" for optional fields +- [THRIFT-2099](https://issues.apache.org/jira/browse/THRIFT-2099) - Stop TThreadPoolServer with alive connections. +- [THRIFT-123](https://issues.apache.org/jira/browse/THRIFT-123) - implement TZlibTransport in Java +- [THRIFT-2368](https://issues.apache.org/jira/browse/THRIFT-2368) - New option: reuse-objects for Java generator +- [THRIFT-2836](https://issues.apache.org/jira/browse/THRIFT-2836) - Optionally generate C++11 MoveConstructible types +- [THRIFT-2824](https://issues.apache.org/jira/browse/THRIFT-2824) - Flag to disable html escaping doctext +- [THRIFT-2819](https://issues.apache.org/jira/browse/THRIFT-2819) - Add WebsSocket client to node.js +- [THRIFT-3050](https://issues.apache.org/jira/browse/THRIFT-3050) - Client certificate authentication for non-http TLS in C# +- [THRIFT-3292](https://issues.apache.org/jira/browse/THRIFT-3292) - Implement TZlibTransport in Go + +### Question +- [THRIFT-2583](https://issues.apache.org/jira/browse/THRIFT-2583) - Thrift on xPC target (SpeedGoat) +- [THRIFT-2592](https://issues.apache.org/jira/browse/THRIFT-2592) - thrift server using c_glib +- [THRIFT-2832](https://issues.apache.org/jira/browse/THRIFT-2832) - c_glib: Handle string lists correctly +- [THRIFT-3136](https://issues.apache.org/jira/browse/THRIFT-3136) - thrift installation problem on mac +- [THRIFT-3346](https://issues.apache.org/jira/browse/THRIFT-3346) - c_glib: Tutorials example crashes saying Calculator.ping implementation returned FALSE but did not set an error + +### Sub-task +- [THRIFT-2578](https://issues.apache.org/jira/browse/THRIFT-2578) - Moving 'make cross' from test.sh to test.py +- [THRIFT-2734](https://issues.apache.org/jira/browse/THRIFT-2734) - Go coding standards +- [THRIFT-2748](https://issues.apache.org/jira/browse/THRIFT-2748) - Add Vagrantfile for Centos 6.5 +- [THRIFT-2753](https://issues.apache.org/jira/browse/THRIFT-2753) - Misc. Haxe improvements +- [THRIFT-2640](https://issues.apache.org/jira/browse/THRIFT-2640) - Compact Protocol in Cocoa +- [THRIFT-3262](https://issues.apache.org/jira/browse/THRIFT-3262) - warning: overflow in implicit constant conversion in DenseProtoTest.cpp +- [THRIFT-3194](https://issues.apache.org/jira/browse/THRIFT-3194) - Can't build with go enabled. gomock SCC path incorrect. +- [THRIFT-3275](https://issues.apache.org/jira/browse/THRIFT-3275) - c_glib tutorial warnings in generated code +- [THRIFT-1125](https://issues.apache.org/jira/browse/THRIFT-1125) - Multiplexing support for the Ruby Library +- [THRIFT-2807](https://issues.apache.org/jira/browse/THRIFT-2807) - PHP Code Style +- [THRIFT-2841](https://issues.apache.org/jira/browse/THRIFT-2841) - Add comprehensive integration tests for the whole Go stack +- [THRIFT-2815](https://issues.apache.org/jira/browse/THRIFT-2815) - Haxe: Support for Multiplexing Services on any Transport, Protocol and Server +- [THRIFT-2886](https://issues.apache.org/jira/browse/THRIFT-2886) - Integrate binary type in standard Thrift cross test +- [THRIFT-2946](https://issues.apache.org/jira/browse/THRIFT-2946) - Enhance usability of cross test framework +- [THRIFT-2967](https://issues.apache.org/jira/browse/THRIFT-2967) - Add .editorconfig to root +- [THRIFT-3033](https://issues.apache.org/jira/browse/THRIFT-3033) - Perl: Support for Multiplexing Services on any Transport, Protocol and Server +- [THRIFT-3174](https://issues.apache.org/jira/browse/THRIFT-3174) - Initialism code in the Go compiler doesn't check first word +- [THRIFT-3193](https://issues.apache.org/jira/browse/THRIFT-3193) - Option to supress date value in @Generated annotation +- [THRIFT-3305](https://issues.apache.org/jira/browse/THRIFT-3305) - Missing dist files for 0.9.3 release candidate +- [THRIFT-3341](https://issues.apache.org/jira/browse/THRIFT-3341) - Add testBool methods +- [THRIFT-3308](https://issues.apache.org/jira/browse/THRIFT-3308) - Fix broken test cases for 0.9.3 release candidate + +### Task +- [THRIFT-2834](https://issues.apache.org/jira/browse/THRIFT-2834) - Remove semi-colons from python code generator +- [THRIFT-2853](https://issues.apache.org/jira/browse/THRIFT-2853) - Adjust comments not applying anymore after THRIFT-2852 + +### Test +- [THRIFT-3211](https://issues.apache.org/jira/browse/THRIFT-3211) - Add make cross support for php TCompactProtocol + +### Wish +- [THRIFT-2838](https://issues.apache.org/jira/browse/THRIFT-2838) - TNonblockingServer can bind to port 0 (i.e., get an OS-assigned port) but there is no way to get the port number + +## 0.9.2 + +### Bug +- [THRIFT-2793](https://issues.apache.org/jira/browse/THRIFT-2793) - Go compiler produces uncompilable code +- [THRIFT-1481](https://issues.apache.org/jira/browse/THRIFT-1481) - Unix domain sockets in C++ do not support the abstract namespace +- [THRIFT-1455](https://issues.apache.org/jira/browse/THRIFT-1455) - TBinaryProtocolT::writeString casts from size_t to uint32_t, which is not safe on 64-bit platforms +- [THRIFT-1579](https://issues.apache.org/jira/browse/THRIFT-1579) - PHP Extention - function thrift_protocol_read_binary not working from TBinarySerializer::deserialize +- [THRIFT-1584](https://issues.apache.org/jira/browse/THRIFT-1584) - Error: could not SetMinThreads in ThreadPool on single-core machines +- [THRIFT-1614](https://issues.apache.org/jira/browse/THRIFT-1614) - Thrift build from svn repo sources fails with automake-1.12 +- [THRIFT-1047](https://issues.apache.org/jira/browse/THRIFT-1047) - rb_thrift_memory_buffer_write treats arg as string without check, segfaults if you pass non-string +- [THRIFT-1639](https://issues.apache.org/jira/browse/THRIFT-1639) - Java/Python: Serialization/Deserialization of double type using CompactProtocol +- [THRIFT-1647](https://issues.apache.org/jira/browse/THRIFT-1647) - NodeJS BufferedTransport does not work beyond the hello-world example +- [THRIFT-2130](https://issues.apache.org/jira/browse/THRIFT-2130) - Thrift's D library/test: parts of "make check" code do not compile with recent dmd-2.062 through dmd-2.064alpha +- [THRIFT-2140](https://issues.apache.org/jira/browse/THRIFT-2140) - Error compiling cpp tutorials +- [THRIFT-2139](https://issues.apache.org/jira/browse/THRIFT-2139) - MSVC 2012 Error - Cannot compile due to BoostThreadFactory +- [THRIFT-2138](https://issues.apache.org/jira/browse/THRIFT-2138) - pkgconfig file created with wrong include path +- [THRIFT-2160](https://issues.apache.org/jira/browse/THRIFT-2160) - Warning in thrift.h when compiling with -Wunused and NDEBUG +- [THRIFT-2158](https://issues.apache.org/jira/browse/THRIFT-2158) - Compact, JSON, and SimpleJSON protocols are not working correctly +- [THRIFT-2167](https://issues.apache.org/jira/browse/THRIFT-2167) - nodejs lib throws error if options argument isn't passed +- [THRIFT-2288](https://issues.apache.org/jira/browse/THRIFT-2288) - Go impl of Thrift JSON protocol wrongly writes/expects true/false for bools +- [THRIFT-2147](https://issues.apache.org/jira/browse/THRIFT-2147) - Thrift IDL grammar allows for dotted identifier names +- [THRIFT-2145](https://issues.apache.org/jira/browse/THRIFT-2145) - Rack and Thin are not just development dependencies +- [THRIFT-2267](https://issues.apache.org/jira/browse/THRIFT-2267) - Should be able to choose socket family in Python TSocket +- [THRIFT-2276](https://issues.apache.org/jira/browse/THRIFT-2276) - java path in spec file needs updating +- [THRIFT-2281](https://issues.apache.org/jira/browse/THRIFT-2281) - Generated send/recv code ignores errors returned by the underlying protocol +- [THRIFT-2280](https://issues.apache.org/jira/browse/THRIFT-2280) - TJSONProtocol.Flush() does not really flush the transport +- [THRIFT-2274](https://issues.apache.org/jira/browse/THRIFT-2274) - TNonblockingServer and TThreadedSelectorServer do not close their channel selectors on exit and leak file descriptors +- [THRIFT-2265](https://issues.apache.org/jira/browse/THRIFT-2265) - php library doesn't build +- [THRIFT-2232](https://issues.apache.org/jira/browse/THRIFT-2232) - IsSet* broken in Go +- [THRIFT-2246](https://issues.apache.org/jira/browse/THRIFT-2246) - Unset enum value is printed by ToString() +- [THRIFT-2240](https://issues.apache.org/jira/browse/THRIFT-2240) - thrift.vim (contrib) does not correctly handle 'union' +- [THRIFT-2243](https://issues.apache.org/jira/browse/THRIFT-2243) - TNonblockingServer in thrift crashes when TFramedTransport opens +- [THRIFT-2230](https://issues.apache.org/jira/browse/THRIFT-2230) - Cannot Build on RHEL/Centos/Amazon Linux 6.x +- [THRIFT-2247](https://issues.apache.org/jira/browse/THRIFT-2247) - Go generator doesn't deal well with map keys of type binary +- [THRIFT-2253](https://issues.apache.org/jira/browse/THRIFT-2253) - Python Tornado TTornadoServer base class change +- [THRIFT-2261](https://issues.apache.org/jira/browse/THRIFT-2261) - java: error: unmappable character for encoding ASCII +- [THRIFT-2259](https://issues.apache.org/jira/browse/THRIFT-2259) - C#: unexpected null logDelegate() pointer causes AV in TServer.serve() +- [THRIFT-2225](https://issues.apache.org/jira/browse/THRIFT-2225) - SSLContext destroy before cleanupOpenSSL +- [THRIFT-2224](https://issues.apache.org/jira/browse/THRIFT-2224) - TSSLSocket.h and TSSLServerSocket.h should use the platfromsocket too +- [THRIFT-2229](https://issues.apache.org/jira/browse/THRIFT-2229) - thrift failed to build on OSX 10.9 GM +- [THRIFT-2227](https://issues.apache.org/jira/browse/THRIFT-2227) - Thrift compiler generates spurious warnings with Xlint +- [THRIFT-2219](https://issues.apache.org/jira/browse/THRIFT-2219) - Thrift gem fails to build on OS X Mavericks with 1.9.3 rubies +- [THRIFT-2226](https://issues.apache.org/jira/browse/THRIFT-2226) - TServerSocket - keepAlive wrong initialization order +- [THRIFT-2285](https://issues.apache.org/jira/browse/THRIFT-2285) - TJsonProtocol implementation for Java doesn't allow a slash (/) to be escaped (\/) +- [THRIFT-2216](https://issues.apache.org/jira/browse/THRIFT-2216) - Extraneous semicolon in TProtocolUtil.h makes clang mad +- [THRIFT-2215](https://issues.apache.org/jira/browse/THRIFT-2215) - Generated HTML/Graphviz lists referenced enum identifiers as UNKNOWN. +- [THRIFT-2211](https://issues.apache.org/jira/browse/THRIFT-2211) - Exception constructor does not contain namespace prefix. +- [THRIFT-2210](https://issues.apache.org/jira/browse/THRIFT-2210) - lib/java TSimpleJSONProtocol can emit invalid JSON +- [THRIFT-2209](https://issues.apache.org/jira/browse/THRIFT-2209) - Ruby generator -- please namespace classes +- [THRIFT-2202](https://issues.apache.org/jira/browse/THRIFT-2202) - Delphi TServerImpl.DefaultLogDelegate may stop the server with I/O-Error 105 +- [THRIFT-2201](https://issues.apache.org/jira/browse/THRIFT-2201) - Ternary operator returns different types (build error for some compilers) +- [THRIFT-2200](https://issues.apache.org/jira/browse/THRIFT-2200) - nested structs cause generate_fingerprint() to slow down at excessive CPU load +- [THRIFT-2197](https://issues.apache.org/jira/browse/THRIFT-2197) - fix jar output directory in rpm spec file +- [THRIFT-2196](https://issues.apache.org/jira/browse/THRIFT-2196) - Fix invalid dependency in Makefile.am +- [THRIFT-2194](https://issues.apache.org/jira/browse/THRIFT-2194) - Node: Not actually prepending residual data in TFramedTransport.receiver +- [THRIFT-2193](https://issues.apache.org/jira/browse/THRIFT-2193) - Java code generator emits spurious semicolon when deep copying binary data +- [THRIFT-2191](https://issues.apache.org/jira/browse/THRIFT-2191) - Fix charp JSONProtocol.ReadJSONDouble (specify InvariantCulture) +- [THRIFT-2214](https://issues.apache.org/jira/browse/THRIFT-2214) - System header sys/param.h is included inside the Thrift namespace +- [THRIFT-2178](https://issues.apache.org/jira/browse/THRIFT-2178) - Thrift generator returns error exit code on --version +- [THRIFT-2171](https://issues.apache.org/jira/browse/THRIFT-2171) - NodeJS implementation has extremely low test coverage +- [THRIFT-2183](https://issues.apache.org/jira/browse/THRIFT-2183) - gem install fails on zsh +- [THRIFT-2182](https://issues.apache.org/jira/browse/THRIFT-2182) - segfault in regression tests (GC bug in rb_thrift_memory_buffer_write) +- [THRIFT-2181](https://issues.apache.org/jira/browse/THRIFT-2181) - oneway calls don't work in NodeJS +- [THRIFT-2169](https://issues.apache.org/jira/browse/THRIFT-2169) - JavaME Thrift Library causes "java.io.IOException: No Response Entries Available" after using the Thrift client for some time +- [THRIFT-2168](https://issues.apache.org/jira/browse/THRIFT-2168) - Node.js appears broken (at least, examples don't work as intended) +- [THRIFT-2293](https://issues.apache.org/jira/browse/THRIFT-2293) - TSSLTransportFactory.createSSLContext() leaves files open +- [THRIFT-2279](https://issues.apache.org/jira/browse/THRIFT-2279) - TSerializer only returns the first 1024 bytes serialized +- [THRIFT-2278](https://issues.apache.org/jira/browse/THRIFT-2278) - Buffered transport doesn't support writes > buffer size +- [THRIFT-2275](https://issues.apache.org/jira/browse/THRIFT-2275) - Fix memory leak in golang compact_protocol. +- [THRIFT-2282](https://issues.apache.org/jira/browse/THRIFT-2282) - Incorect code generated for some typedefs +- [THRIFT-2009](https://issues.apache.org/jira/browse/THRIFT-2009) - Go redeclaration error +- [THRIFT-1964](https://issues.apache.org/jira/browse/THRIFT-1964) - 'Isset' causes problems with C#/.NET serializers +- [THRIFT-2026](https://issues.apache.org/jira/browse/THRIFT-2026) - Fix TCompactProtocol 64 bit builds +- [THRIFT-2108](https://issues.apache.org/jira/browse/THRIFT-2108) - Fix TAsyncClientManager timeout race +- [THRIFT-2068](https://issues.apache.org/jira/browse/THRIFT-2068) - Multiple calls from same connection are not processed in node +- [THRIFT-1750](https://issues.apache.org/jira/browse/THRIFT-1750) - Make compiler build cleanly under visual studio 10 +- [THRIFT-1755](https://issues.apache.org/jira/browse/THRIFT-1755) - Comment parsing bug +- [THRIFT-1771](https://issues.apache.org/jira/browse/THRIFT-1771) - "make check" fails on x64 for libboost_unit_test_framework.a +- [THRIFT-1841](https://issues.apache.org/jira/browse/THRIFT-1841) - NodeJS Thrift incorrectly parses non-UTF8-string types +- [THRIFT-1908](https://issues.apache.org/jira/browse/THRIFT-1908) - Using php thrift_protocol accelerated transfer causes core dump +- [THRIFT-1892](https://issues.apache.org/jira/browse/THRIFT-1892) - Socket timeouts are declared in milli-seconds, but are actually set in micro-seconds +- [THRIFT-2303](https://issues.apache.org/jira/browse/THRIFT-2303) - TBufferredTransport not properly closing underlying transport +- [THRIFT-2313](https://issues.apache.org/jira/browse/THRIFT-2313) - nodejs server crash after processing the first request when using MultiplexedProcessor/FramedBuffer/BinaryProtocol +- [THRIFT-2311](https://issues.apache.org/jira/browse/THRIFT-2311) - Go: invalid code generated when exception name is a go keyword +- [THRIFT-2308](https://issues.apache.org/jira/browse/THRIFT-2308) - node: TJSONProtocol parse error when reading from buffered message +- [THRIFT-2316](https://issues.apache.org/jira/browse/THRIFT-2316) - ccp: TFileTransportTest +- [THRIFT-2352](https://issues.apache.org/jira/browse/THRIFT-2352) - msvc failed to compile thrift tests +- [THRIFT-2337](https://issues.apache.org/jira/browse/THRIFT-2337) - Golang does not report TIMED_OUT exceptions +- [THRIFT-2340](https://issues.apache.org/jira/browse/THRIFT-2340) - Generated server implementation does not send response type EXCEPTION on the Thrift.TApplicationExceptionType.UNKNOWN_METHOD exception +- [THRIFT-2354](https://issues.apache.org/jira/browse/THRIFT-2354) - Connection errors can lead to case_clause exceptions +- [THRIFT-2339](https://issues.apache.org/jira/browse/THRIFT-2339) - Uncaught exception in thrift c# driver +- [THRIFT-2356](https://issues.apache.org/jira/browse/THRIFT-2356) - c++ thrift client not working with ssl (SSL_connect hangs) +- [THRIFT-2331](https://issues.apache.org/jira/browse/THRIFT-2331) - Missing call to ReadStructBegin() in TApplicationException.Read() +- [THRIFT-2323](https://issues.apache.org/jira/browse/THRIFT-2323) - Uncompileable Delphi code generated for typedef'd structs +- [THRIFT-2322](https://issues.apache.org/jira/browse/THRIFT-2322) - Correctly show the number of times ExecutorService (java) has rejected the client. +- [THRIFT-2389](https://issues.apache.org/jira/browse/THRIFT-2389) - namespaces handled wrongly in acrionscript 3.0 implementation +- [THRIFT-2388](https://issues.apache.org/jira/browse/THRIFT-2388) - GoLang - Fix data races in simple_server and server_socket +- [THRIFT-2386](https://issues.apache.org/jira/browse/THRIFT-2386) - Thrift refuses to link yylex +- [THRIFT-2375](https://issues.apache.org/jira/browse/THRIFT-2375) - Excessive
's in generated HTML +- [THRIFT-2373](https://issues.apache.org/jira/browse/THRIFT-2373) - warning CS0414 in THttpClient.cs: private field 'Thrift.Transport.THttpClient.connection' assigned but never used +- [THRIFT-2372](https://issues.apache.org/jira/browse/THRIFT-2372) - thrift/json_protocol.go:160: function ends without a return statement +- [THRIFT-2371](https://issues.apache.org/jira/browse/THRIFT-2371) - ruby bundler version fails on ~1.3.1, remove and take latest avail +- [THRIFT-2370](https://issues.apache.org/jira/browse/THRIFT-2370) - Compiler SEGFAULTs generating HTML documentation for complex strucre +- [THRIFT-2384](https://issues.apache.org/jira/browse/THRIFT-2384) - Binary map keys produce uncompilable code in go +- [THRIFT-2380](https://issues.apache.org/jira/browse/THRIFT-2380) - unreachable code (CID 1174546, CID 1174679) +- [THRIFT-2378](https://issues.apache.org/jira/browse/THRIFT-2378) - service method arguments of binary type lead to uncompileable Go code +- [THRIFT-2363](https://issues.apache.org/jira/browse/THRIFT-2363) - Issue with character encoding of Success returned from Login using Thrift Proxy and NodeJS +- [THRIFT-2359](https://issues.apache.org/jira/browse/THRIFT-2359) - TBufferedTransport doesn't clear it's buffer on a failed flush call +- [THRIFT-2428](https://issues.apache.org/jira/browse/THRIFT-2428) - Python 3 setup.py support +- [THRIFT-2367](https://issues.apache.org/jira/browse/THRIFT-2367) - Build failure: stdlib and boost both define uint64_t +- [THRIFT-2365](https://issues.apache.org/jira/browse/THRIFT-2365) - C# decodes too many binary bytes from JSON +- [THRIFT-2402](https://issues.apache.org/jira/browse/THRIFT-2402) - byte count of FrameBuffer in AWAITING_CLOSE state is not subtracted from readBufferBytesAllocated +- [THRIFT-2396](https://issues.apache.org/jira/browse/THRIFT-2396) - Build Error on MacOSX +- [THRIFT-2395](https://issues.apache.org/jira/browse/THRIFT-2395) - thrift Ruby gem requires development dependency 'thin' regardless of environment +- [THRIFT-2414](https://issues.apache.org/jira/browse/THRIFT-2414) - c_glib fix several bug. +- [THRIFT-2420](https://issues.apache.org/jira/browse/THRIFT-2420) - Go argument parser for methods without arguments does not skip fields +- [THRIFT-2439](https://issues.apache.org/jira/browse/THRIFT-2439) - Bug in TProtocolDecorator Class causes parsing errors +- [THRIFT-2419](https://issues.apache.org/jira/browse/THRIFT-2419) - golang - Fix fmt.Errorf in generated code +- [THRIFT-2418](https://issues.apache.org/jira/browse/THRIFT-2418) - Go handler function panics on internal error +- [THRIFT-2405](https://issues.apache.org/jira/browse/THRIFT-2405) - Node.js Multiplexer tests fail (silently) +- [THRIFT-2581](https://issues.apache.org/jira/browse/THRIFT-2581) - TFDTransport destructor should not throw +- [THRIFT-2575](https://issues.apache.org/jira/browse/THRIFT-2575) - Thrift includes siginfo_t within apache::thrift::protocol namespace +- [THRIFT-2577](https://issues.apache.org/jira/browse/THRIFT-2577) - TFileTransport missuse of closesocket on windows platform +- [THRIFT-2576](https://issues.apache.org/jira/browse/THRIFT-2576) - Implement Thrift.Protocol.prototype.skip method in JavaScript library +- [THRIFT-2588](https://issues.apache.org/jira/browse/THRIFT-2588) - Thrift compiler is not buildable in Visual Studio 2010 +- [THRIFT-2594](https://issues.apache.org/jira/browse/THRIFT-2594) - JS Compiler: Single quotes are not being escaped in constants. +- [THRIFT-2591](https://issues.apache.org/jira/browse/THRIFT-2591) - TFramedTransport does not handle payloads split across packets correctly +- [THRIFT-2599](https://issues.apache.org/jira/browse/THRIFT-2599) - Uncompileable Delphi code due to naming conflicts with IDL +- [THRIFT-2590](https://issues.apache.org/jira/browse/THRIFT-2590) - C++ Visual Studio solution doesn't include Multiplexing support +- [THRIFT-2595](https://issues.apache.org/jira/browse/THRIFT-2595) - Node.js: Fix global leaks and copy-paste errors +- [THRIFT-2565](https://issues.apache.org/jira/browse/THRIFT-2565) - autoconf fails to find mingw-g++ cross compiler on travis CI +- [THRIFT-2555](https://issues.apache.org/jira/browse/THRIFT-2555) - excessive "unused field" comments +- [THRIFT-2554](https://issues.apache.org/jira/browse/THRIFT-2554) - double initialization in generated Read() method +- [THRIFT-2551](https://issues.apache.org/jira/browse/THRIFT-2551) - OutOfMemoryError "unable to create new native thread" kills serve thread +- [THRIFT-2543](https://issues.apache.org/jira/browse/THRIFT-2543) - Generated enum type in haskell should be qualified +- [THRIFT-2560](https://issues.apache.org/jira/browse/THRIFT-2560) - Thrift compiler generator tries to concat ints with strings using + +- [THRIFT-2559](https://issues.apache.org/jira/browse/THRIFT-2559) - Centos 6.5 unable to "make" with Thrift 0.9.1 +- [THRIFT-2526](https://issues.apache.org/jira/browse/THRIFT-2526) - Assignment operators and copy constructors in c++ don't copy the __isset struct +- [THRIFT-2454](https://issues.apache.org/jira/browse/THRIFT-2454) - c_glib: There is no gethostbyname_r() in some OS. +- [THRIFT-2451](https://issues.apache.org/jira/browse/THRIFT-2451) - Do not use pointers for optional fields with defaults. Do not write such fields if its value set to default. Also, do not use pointers for any optional fields mapped to go map or slice. generate Get accessors +- [THRIFT-2450](https://issues.apache.org/jira/browse/THRIFT-2450) - include HowToContribute in the src repo +- [THRIFT-2448](https://issues.apache.org/jira/browse/THRIFT-2448) - thrift/test/test.sh has incorrect Node.js test path +- [THRIFT-2460](https://issues.apache.org/jira/browse/THRIFT-2460) - unopened socket fd must be less than zero. +- [THRIFT-2459](https://issues.apache.org/jira/browse/THRIFT-2459) - --version should not exit 1 +- [THRIFT-2468](https://issues.apache.org/jira/browse/THRIFT-2468) - Timestamp handling +- [THRIFT-2467](https://issues.apache.org/jira/browse/THRIFT-2467) - Unable to build contrib/fb303 on OSX 10.9.2 +- [THRIFT-2466](https://issues.apache.org/jira/browse/THRIFT-2466) - Improper error handling for SSL/TLS connections that don't complete a handshake +- [THRIFT-2463](https://issues.apache.org/jira/browse/THRIFT-2463) - test/py/RunClientServer.py fails sometimes +- [THRIFT-2458](https://issues.apache.org/jira/browse/THRIFT-2458) - Generated golang server code for "oneway" methods is incorrect +- [THRIFT-2456](https://issues.apache.org/jira/browse/THRIFT-2456) - THttpClient fails when using async support outside Silverlight +- [THRIFT-2524](https://issues.apache.org/jira/browse/THRIFT-2524) - Visual Studio project is missing TThreadedServer files +- [THRIFT-2523](https://issues.apache.org/jira/browse/THRIFT-2523) - Visual Studio project is missing OverlappedSubmissionThread files +- [THRIFT-2520](https://issues.apache.org/jira/browse/THRIFT-2520) - cpp:cob_style generates incorrect .tcc file +- [THRIFT-2508](https://issues.apache.org/jira/browse/THRIFT-2508) - Uncompileable C# code due to language keywords in IDL +- [THRIFT-2506](https://issues.apache.org/jira/browse/THRIFT-2506) - Update TProtocolException error codes to be used consistently throughout the library +- [THRIFT-2505](https://issues.apache.org/jira/browse/THRIFT-2505) - go: struct should always be a pointer to avoid copying of potentially size-unbounded structs +- [THRIFT-2515](https://issues.apache.org/jira/browse/THRIFT-2515) - TLS Method error during make +- [THRIFT-2503](https://issues.apache.org/jira/browse/THRIFT-2503) - C++: Fix name collision when a struct has a member named "val" +- [THRIFT-2477](https://issues.apache.org/jira/browse/THRIFT-2477) - thrift --help text with misplaced comma +- [THRIFT-2492](https://issues.apache.org/jira/browse/THRIFT-2492) - test/cpp does not compile on mac +- [THRIFT-2500](https://issues.apache.org/jira/browse/THRIFT-2500) - sending random data crashes thrift(golang) service +- [THRIFT-2475](https://issues.apache.org/jira/browse/THRIFT-2475) - c_glib: buffered_transport_write function return always TRUE. +- [THRIFT-2495](https://issues.apache.org/jira/browse/THRIFT-2495) - JavaScript/Node string constants lack proper escaping +- [THRIFT-2491](https://issues.apache.org/jira/browse/THRIFT-2491) - unable to import generated ThriftTest service +- [THRIFT-2490](https://issues.apache.org/jira/browse/THRIFT-2490) - c_glib: if fail to read a exception from server, client may be occurred double free +- [THRIFT-2470](https://issues.apache.org/jira/browse/THRIFT-2470) - THttpHandler swallows exceptions from processor +- [THRIFT-2533](https://issues.apache.org/jira/browse/THRIFT-2533) - Boost version in requirements should be updated +- [THRIFT-2532](https://issues.apache.org/jira/browse/THRIFT-2532) - Java version in installation requirements should be updated +- [THRIFT-2529](https://issues.apache.org/jira/browse/THRIFT-2529) - TBufferedTransport split Tcp data bug in nodeJs +- [THRIFT-2537](https://issues.apache.org/jira/browse/THRIFT-2537) - Path for "go get" does not work (pull request 115) +- [THRIFT-2443](https://issues.apache.org/jira/browse/THRIFT-2443) - Node fails cross lang tests +- [THRIFT-2437](https://issues.apache.org/jira/browse/THRIFT-2437) - Author fields in Python setup.py must be strings not lists. +- [THRIFT-2435](https://issues.apache.org/jira/browse/THRIFT-2435) - Java compiler doesn't like struct member names that are identical to an existing enum or struct type +- [THRIFT-2434](https://issues.apache.org/jira/browse/THRIFT-2434) - Missing namespace import for php TMultiplexedProcessor implementation +- [THRIFT-2432](https://issues.apache.org/jira/browse/THRIFT-2432) - Flaky parallel build +- [THRIFT-2430](https://issues.apache.org/jira/browse/THRIFT-2430) - Crash during TThreadPoolServer shutdown +- [THRIFT-667](https://issues.apache.org/jira/browse/THRIFT-667) - Period should not be allowed in identifier names +- [THRIFT-1212](https://issues.apache.org/jira/browse/THRIFT-1212) - Members capital case conflict +- [THRIFT-2584](https://issues.apache.org/jira/browse/THRIFT-2584) - Error handler not listened on javascript client +- [THRIFT-2294](https://issues.apache.org/jira/browse/THRIFT-2294) - Incorrect Makefile generation +- [THRIFT-2601](https://issues.apache.org/jira/browse/THRIFT-2601) - Fix vagrant to work again for builds again +- [THRIFT-2092](https://issues.apache.org/jira/browse/THRIFT-2092) - TNonblocking server should release handler as soon as connection closes +- [THRIFT-2557](https://issues.apache.org/jira/browse/THRIFT-2557) - CS0542 member names cannot be the same as their enclosing type +- [THRIFT-2605](https://issues.apache.org/jira/browse/THRIFT-2605) - TSocket warning on gcc 4.8.3 +- [THRIFT-2607](https://issues.apache.org/jira/browse/THRIFT-2607) - ThreadManager.cpp warning on clang++ 3.4 +- [THRIFT-1998](https://issues.apache.org/jira/browse/THRIFT-1998) - TCompactProtocol.tcc - one more warning on Visual 2010 +- [THRIFT-2610](https://issues.apache.org/jira/browse/THRIFT-2610) - MSVC warning in TSocket.cpp +- [THRIFT-2614](https://issues.apache.org/jira/browse/THRIFT-2614) - TNonblockingServer.cpp warnings on MSVC +- [THRIFT-2608](https://issues.apache.org/jira/browse/THRIFT-2608) - TNonblockingServer.cpp warnings on clang 3.4 +- [THRIFT-2606](https://issues.apache.org/jira/browse/THRIFT-2606) - ThreadManager.h warning in clang++ 3.4 +- [THRIFT-2609](https://issues.apache.org/jira/browse/THRIFT-2609) - TFileTransport.h unused field warning (clang 3.4) +- [THRIFT-2416](https://issues.apache.org/jira/browse/THRIFT-2416) - Cannot use TCompactProtocol with MSVC +- [THRIFT-1803](https://issues.apache.org/jira/browse/THRIFT-1803) - Ruby Thrift 0.9.0 tries to encode UUID to UTF8 and crashes +- [THRIFT-2385](https://issues.apache.org/jira/browse/THRIFT-2385) - Problem with gethostbyname2 during make check +- [THRIFT-2262](https://issues.apache.org/jira/browse/THRIFT-2262) - thrift server 'MutateRow' operation gives no indication of success / failure +- [THRIFT-2048](https://issues.apache.org/jira/browse/THRIFT-2048) - Prefer boolean context to nullptr_t conversion +- [THRIFT-2528](https://issues.apache.org/jira/browse/THRIFT-2528) - Thrift Erlang Library: Multiple thrift applications in one bundle +- [THRIFT-1999](https://issues.apache.org/jira/browse/THRIFT-1999) - warning on gcc 4.7 while compiling BoostMutex.cpp +- [THRIFT-2104](https://issues.apache.org/jira/browse/THRIFT-2104) - Structs lose binary data when transferred from server to client in Java +- [THRIFT-2184](https://issues.apache.org/jira/browse/THRIFT-2184) - undefined method rspec_verify for Thrift::MemoryBufferTransport +- [THRIFT-2351](https://issues.apache.org/jira/browse/THRIFT-2351) - PHP TCompactProtocol has fails to decode messages +- [THRIFT-2016](https://issues.apache.org/jira/browse/THRIFT-2016) - Resource Leak in thrift struct under compiler/cpp/src/parse/t_function.h +- [THRIFT-2273](https://issues.apache.org/jira/browse/THRIFT-2273) - Please delete old releases from mirroring system +- [THRIFT-2270](https://issues.apache.org/jira/browse/THRIFT-2270) - Faulty library version numbering at build or documentation +- [THRIFT-2203](https://issues.apache.org/jira/browse/THRIFT-2203) - Tests keeping failing on Jenkins and Travis CI +- [THRIFT-2399](https://issues.apache.org/jira/browse/THRIFT-2399) - thrift.el: recognize "//"-style comments in emacs thrift-mode +- [THRIFT-2582](https://issues.apache.org/jira/browse/THRIFT-2582) - "FileTransport error" exception is raised when trying to use Java's TFileTransport +- [THRIFT-1682](https://issues.apache.org/jira/browse/THRIFT-1682) - Multiple thread calling a Service function unsafely causes message corruption and terminates with Broken Pipe +- [THRIFT-2357](https://issues.apache.org/jira/browse/THRIFT-2357) - recurse option has no effect when generating php +- [THRIFT-2248](https://issues.apache.org/jira/browse/THRIFT-2248) - Go generator doesn't deal well with map keys of type binary +- [THRIFT-2426](https://issues.apache.org/jira/browse/THRIFT-2426) - clarify IP rights and contributions from fbthrift +- [THRIFT-2041](https://issues.apache.org/jira/browse/THRIFT-2041) - TNonblocking server compilation on windows (ARITHMETIC_RIGHT_SHIFT) +- [THRIFT-2400](https://issues.apache.org/jira/browse/THRIFT-2400) - thrift.el: recognize "//"-style comments in emacs thrift-mode +- [THRIFT-1717](https://issues.apache.org/jira/browse/THRIFT-1717) - Fix deb build in jenkins +- [THRIFT-2266](https://issues.apache.org/jira/browse/THRIFT-2266) - ThreadManager.h:24:10: fatal error: 'tr1/functional' file not found on Mac 10.9 (Mavericks) +- [THRIFT-1300](https://issues.apache.org/jira/browse/THRIFT-1300) - Test failures with parallel builds (make -j) +- [THRIFT-2487](https://issues.apache.org/jira/browse/THRIFT-2487) - Tutorial requires two IDL files but only one is linked from the Thrift web site +- [THRIFT-2329](https://issues.apache.org/jira/browse/THRIFT-2329) - missing release tags within git +- [THRIFT-2306](https://issues.apache.org/jira/browse/THRIFT-2306) - concurent client calls with nodejs +- [THRIFT-2222](https://issues.apache.org/jira/browse/THRIFT-2222) - ruby gem cannot be compiled on OS X mavericks +- [THRIFT-2381](https://issues.apache.org/jira/browse/THRIFT-2381) - code which generated by thrift2/hbase.thrift compile error +- [THRIFT-2390](https://issues.apache.org/jira/browse/THRIFT-2390) - no close event when connection lost +- [THRIFT-2146](https://issues.apache.org/jira/browse/THRIFT-2146) - Unable to pass multiple "--gen" options to the thrift compiler +- [THRIFT-2438](https://issues.apache.org/jira/browse/THRIFT-2438) - Unexpected readFieldEnd call causes JSON Parsing errors +- [THRIFT-2498](https://issues.apache.org/jira/browse/THRIFT-2498) - Error message "Invalid method name" while trying to call HBase Thrift API +- [THRIFT-841](https://issues.apache.org/jira/browse/THRIFT-841) - Build cruft +- [THRIFT-2570](https://issues.apache.org/jira/browse/THRIFT-2570) - Wrong URL given in http://thrift.apache.org/developers +- [THRIFT-2604](https://issues.apache.org/jira/browse/THRIFT-2604) - Fix debian packaging +- [THRIFT-2618](https://issues.apache.org/jira/browse/THRIFT-2618) - Unignore /aclocal files required for build +- [THRIFT-2562](https://issues.apache.org/jira/browse/THRIFT-2562) - ./configure create MakeFile in lib/d with errors +- [THRIFT-2593](https://issues.apache.org/jira/browse/THRIFT-2593) - Unable to build thrift on ubuntu-12.04 (Precise) +- [THRIFT-2461](https://issues.apache.org/jira/browse/THRIFT-2461) - Can't install thrift-0.8.0 on OS X 10.9.2 +- [THRIFT-2602](https://issues.apache.org/jira/browse/THRIFT-2602) - Fix missing dist files +- [THRIFT-2620](https://issues.apache.org/jira/browse/THRIFT-2620) - Fix python packaging +- [THRIFT-2545](https://issues.apache.org/jira/browse/THRIFT-2545) - Test CPP fails to build (possibly typo) + +## Documentation +- [THRIFT-2155](https://issues.apache.org/jira/browse/THRIFT-2155) - Adding one liner guide to rename the version.h.in and rename thrifty.cc.h +- [THRIFT-1991](https://issues.apache.org/jira/browse/THRIFT-1991) - Add exceptions to examples +- [THRIFT-2334](https://issues.apache.org/jira/browse/THRIFT-2334) - add a tutorial for node JS +- [THRIFT-2392](https://issues.apache.org/jira/browse/THRIFT-2392) - Actionscript tutorial +- [THRIFT-2383](https://issues.apache.org/jira/browse/THRIFT-2383) - contrib: sample for connecting Thrift with Rebus +- [THRIFT-2382](https://issues.apache.org/jira/browse/THRIFT-2382) - contrib: sample for connecting Thrift with STOMP + +### Improvement +- [THRIFT-1457](https://issues.apache.org/jira/browse/THRIFT-1457) - Capacity of TframedTransport write buffer is never reset +- [THRIFT-1135](https://issues.apache.org/jira/browse/THRIFT-1135) - Node.js tutorial +- [THRIFT-1371](https://issues.apache.org/jira/browse/THRIFT-1371) - Socket timeouts (SO_RCVTIMEO and SO_SNDTIMEO) not supported on Solaris +- [THRIFT-2142](https://issues.apache.org/jira/browse/THRIFT-2142) - Minor tweaks to thrift.el for better emacs package compatibility +- [THRIFT-2268](https://issues.apache.org/jira/browse/THRIFT-2268) - Modify TSaslTransport to ignore TCP health checks from loadbalancers +- [THRIFT-2264](https://issues.apache.org/jira/browse/THRIFT-2264) - GitHub page incorrectly states that Thrift is still incubating +- [THRIFT-2263](https://issues.apache.org/jira/browse/THRIFT-2263) - Always generate good hashCode for Java +- [THRIFT-2233](https://issues.apache.org/jira/browse/THRIFT-2233) - Java compiler should defensively copy its binary inputs +- [THRIFT-2239](https://issues.apache.org/jira/browse/THRIFT-2239) - Address FindBugs errors +- [THRIFT-2249](https://issues.apache.org/jira/browse/THRIFT-2249) - Add SMP Build option to thrift.spec (and three config defines) +- [THRIFT-2254](https://issues.apache.org/jira/browse/THRIFT-2254) - Exceptions generated by Go compiler should implement error interface +- [THRIFT-2260](https://issues.apache.org/jira/browse/THRIFT-2260) - Thrift imposes unneeded dependency on commons-lang3 +- [THRIFT-2258](https://issues.apache.org/jira/browse/THRIFT-2258) - Add TLS v1.1/1.2 support to TSSLSocket.cpp +- [THRIFT-2205](https://issues.apache.org/jira/browse/THRIFT-2205) - Node.js Test Server to support test.js JavaScript Browser test and sundry fixes +- [THRIFT-2204](https://issues.apache.org/jira/browse/THRIFT-2204) - SSL client for the cocoa client +- [THRIFT-2172](https://issues.apache.org/jira/browse/THRIFT-2172) - Java compiler allocates optionals array for every struct with an optional field +- [THRIFT-2185](https://issues.apache.org/jira/browse/THRIFT-2185) - use cabal instead of runhaskell in haskell library +- [THRIFT-1926](https://issues.apache.org/jira/browse/THRIFT-1926) - PHP Constant Generation Refactoring +- [THRIFT-2029](https://issues.apache.org/jira/browse/THRIFT-2029) - Port C++ tests to Windows +- [THRIFT-2054](https://issues.apache.org/jira/browse/THRIFT-2054) - TSimpleFileTransport - Java Lib has no straight forward TTransport based file transport +- [THRIFT-2040](https://issues.apache.org/jira/browse/THRIFT-2040) - "uninitialized variable" warnings on MSVC/windows +- [THRIFT-2034](https://issues.apache.org/jira/browse/THRIFT-2034) - Give developers' C++ code direct access to socket FDs on server side +- [THRIFT-2095](https://issues.apache.org/jira/browse/THRIFT-2095) - Use print function for Python 3 compatiblity +- [THRIFT-1868](https://issues.apache.org/jira/browse/THRIFT-1868) - Make the TPC backlog configurable in the Java servers +- [THRIFT-1813](https://issues.apache.org/jira/browse/THRIFT-1813) - Add @Generated annotation to generated classes +- [THRIFT-1815](https://issues.apache.org/jira/browse/THRIFT-1815) - Code generators line buffer output +- [THRIFT-2305](https://issues.apache.org/jira/browse/THRIFT-2305) - TFramedTransport empty constructor should probably be private +- [THRIFT-2304](https://issues.apache.org/jira/browse/THRIFT-2304) - Move client assignments from construtor in method +- [THRIFT-2309](https://issues.apache.org/jira/browse/THRIFT-2309) - Ruby (gem) & PHP RPM subpackages +- [THRIFT-2318](https://issues.apache.org/jira/browse/THRIFT-2318) - perl: dependency Class::Accessor not checked +- [THRIFT-2317](https://issues.apache.org/jira/browse/THRIFT-2317) - exclude tutorial from build +- [THRIFT-2320](https://issues.apache.org/jira/browse/THRIFT-2320) - Program level doctext does not get attached by parser +- [THRIFT-2349](https://issues.apache.org/jira/browse/THRIFT-2349) - Golang - improve tutorial +- [THRIFT-2348](https://issues.apache.org/jira/browse/THRIFT-2348) - PHP Generator: add array typehint to functions +- [THRIFT-2344](https://issues.apache.org/jira/browse/THRIFT-2344) - configure.ac: compiler-only option +- [THRIFT-2343](https://issues.apache.org/jira/browse/THRIFT-2343) - Golang - Return a single error for all exceptions instead of multiple return values +- [THRIFT-2341](https://issues.apache.org/jira/browse/THRIFT-2341) - Enable generation of Delphi XMLDoc comments (a.k.a. "Help Insight") +- [THRIFT-2355](https://issues.apache.org/jira/browse/THRIFT-2355) - Add SSL and Web Socket Support to Node and JavaScript +- [THRIFT-2350](https://issues.apache.org/jira/browse/THRIFT-2350) - Add async calls to normal JavaScript +- [THRIFT-2330](https://issues.apache.org/jira/browse/THRIFT-2330) - Generate PHPDoc comments +- [THRIFT-2332](https://issues.apache.org/jira/browse/THRIFT-2332) - RPMBUILD: run bootstrap (if needed) +- [THRIFT-2391](https://issues.apache.org/jira/browse/THRIFT-2391) - simple socket transport for actionscript 3.0 +- [THRIFT-2376](https://issues.apache.org/jira/browse/THRIFT-2376) - nodejs: allow Promise style calls for client and server +- [THRIFT-2369](https://issues.apache.org/jira/browse/THRIFT-2369) - Add ssl support for nodejs implementation +- [THRIFT-2401](https://issues.apache.org/jira/browse/THRIFT-2401) - Haskell tutorial compiles +- [THRIFT-2417](https://issues.apache.org/jira/browse/THRIFT-2417) - C# Union classes are not partial +- [THRIFT-2415](https://issues.apache.org/jira/browse/THRIFT-2415) - Named pipes server performance & message mode +- [THRIFT-2404](https://issues.apache.org/jira/browse/THRIFT-2404) - emit warning on (typically inefficient) list +- [THRIFT-2398](https://issues.apache.org/jira/browse/THRIFT-2398) - Improve Node Server Library +- [THRIFT-2397](https://issues.apache.org/jira/browse/THRIFT-2397) - Add CORS and CSP support for JavaScript and Node.js libraries +- [THRIFT-2407](https://issues.apache.org/jira/browse/THRIFT-2407) - use markdown (rename README => README.md) +- [THRIFT-2300](https://issues.apache.org/jira/browse/THRIFT-2300) - D configure info output should follow same format as other languages +- [THRIFT-2579](https://issues.apache.org/jira/browse/THRIFT-2579) - Windows CE support +- [THRIFT-2574](https://issues.apache.org/jira/browse/THRIFT-2574) - Compiler option to generate namespace directories for Ruby +- [THRIFT-2571](https://issues.apache.org/jira/browse/THRIFT-2571) - Simplify cross compilation using CMake +- [THRIFT-2569](https://issues.apache.org/jira/browse/THRIFT-2569) - Introduce file to specify third party library locations on Windows +- [THRIFT-2568](https://issues.apache.org/jira/browse/THRIFT-2568) - Implement own certificate handler +- [THRIFT-2552](https://issues.apache.org/jira/browse/THRIFT-2552) - eliminate warning from configure.ac +- [THRIFT-2549](https://issues.apache.org/jira/browse/THRIFT-2549) - Generate json tag for struct members. use go.tag annotation to override the default generated tag. +- [THRIFT-2544](https://issues.apache.org/jira/browse/THRIFT-2544) - Add support for socket transport for c# library when using Windows Phone projects +- [THRIFT-2453](https://issues.apache.org/jira/browse/THRIFT-2453) - haskell tutorial: fix up division by 0 example +- [THRIFT-2449](https://issues.apache.org/jira/browse/THRIFT-2449) - Enhance typedef structure to distinguish between forwards and real typedefs +- [THRIFT-2446](https://issues.apache.org/jira/browse/THRIFT-2446) - There is no way to handle server stream errors +- [THRIFT-2455](https://issues.apache.org/jira/browse/THRIFT-2455) - Allow client certificates to be used with THttpClient +- [THRIFT-2511](https://issues.apache.org/jira/browse/THRIFT-2511) - Node.js needs the compact protocol +- [THRIFT-2493](https://issues.apache.org/jira/browse/THRIFT-2493) - Node.js lib needs HTTP client +- [THRIFT-2502](https://issues.apache.org/jira/browse/THRIFT-2502) - Optimize go implementations of binary and compact protocols for speed +- [THRIFT-2494](https://issues.apache.org/jira/browse/THRIFT-2494) - Add enum toString helper function in c_glib +- [THRIFT-2471](https://issues.apache.org/jira/browse/THRIFT-2471) - Make cpp.ref annotation language agnostic +- [THRIFT-2497](https://issues.apache.org/jira/browse/THRIFT-2497) - server and client for test/go, also several fixes and improvements +- [THRIFT-2535](https://issues.apache.org/jira/browse/THRIFT-2535) - TJSONProtocol when serialized yields TField ids rather than names +- [THRIFT-2220](https://issues.apache.org/jira/browse/THRIFT-2220) - Add a new struct structv? +- [THRIFT-1352](https://issues.apache.org/jira/browse/THRIFT-1352) - Thrift server +- [THRIFT-989](https://issues.apache.org/jira/browse/THRIFT-989) - Push boost m4 macros upstream +- [THRIFT-1349](https://issues.apache.org/jira/browse/THRIFT-1349) - Remove unnecessary print outs +- [THRIFT-2496](https://issues.apache.org/jira/browse/THRIFT-2496) - server and client for test/go, also several fixes and improvements +- [THRIFT-1114](https://issues.apache.org/jira/browse/THRIFT-1114) - Maven publish shouldn't require passwords hardcoded in settings.xml +- [THRIFT-2043](https://issues.apache.org/jira/browse/THRIFT-2043) - visual 2010 warnings - unreachable code +- [THRIFT-1683](https://issues.apache.org/jira/browse/THRIFT-1683) - Implement alternatives to Javascript Client side Transport protocol, just as NPAPI and WebSocket. +- [THRIFT-1746](https://issues.apache.org/jira/browse/THRIFT-1746) - provide a SPDX file +- [THRIFT-1772](https://issues.apache.org/jira/browse/THRIFT-1772) - Serialization does not check types of embedded structures. +- [THRIFT-2387](https://issues.apache.org/jira/browse/THRIFT-2387) - nodejs: external imports should be centralized in index.js +- [THRIFT-2037](https://issues.apache.org/jira/browse/THRIFT-2037) - More general macro THRIFT_UNUSED_VARIABLE + +### New Feature +- [THRIFT-1012](https://issues.apache.org/jira/browse/THRIFT-1012) - Transport for DataInput DataOutput interface +- [THRIFT-2256](https://issues.apache.org/jira/browse/THRIFT-2256) - Using c++11/c++0x std library replace boost library +- [THRIFT-2250](https://issues.apache.org/jira/browse/THRIFT-2250) - JSON and MemoryBuffer for JavaME +- [THRIFT-2114](https://issues.apache.org/jira/browse/THRIFT-2114) - Python Service Remote SSL Option +- [THRIFT-1719](https://issues.apache.org/jira/browse/THRIFT-1719) - SASL client support for Python +- [THRIFT-1894](https://issues.apache.org/jira/browse/THRIFT-1894) - Thrift multi-threaded async Java Server using Java 7 AsynchronousChannelGroup +- [THRIFT-1893](https://issues.apache.org/jira/browse/THRIFT-1893) - HTTP/JSON server/client for node js +- [THRIFT-2347](https://issues.apache.org/jira/browse/THRIFT-2347) - C# TLS Transport based on THRIFT-181 +- [THRIFT-2377](https://issues.apache.org/jira/browse/THRIFT-2377) - Allow addition of custom HTTP Headers to an HTTP Transport +- [THRIFT-2408](https://issues.apache.org/jira/browse/THRIFT-2408) - Named Pipe Transport Option for C# +- [THRIFT-2572](https://issues.apache.org/jira/browse/THRIFT-2572) - Add string/collection length limit checks (from C++) to java protocol readers +- [THRIFT-2469](https://issues.apache.org/jira/browse/THRIFT-2469) - "java:fullcamel" option to automatically camel-case underscored attribute names +- [THRIFT-795](https://issues.apache.org/jira/browse/THRIFT-795) - Importing service functions (simulation multiple inheritance) +- [THRIFT-2164](https://issues.apache.org/jira/browse/THRIFT-2164) - Add a Get/Post Http Server to Node along with examples +- [THRIFT-2255](https://issues.apache.org/jira/browse/THRIFT-2255) - add Parent Class for generated Struct class + +### Question +- [THRIFT-2539](https://issues.apache.org/jira/browse/THRIFT-2539) - Tsocket.cpp addrinfo ai_flags = AI_ADDRCONFIG +- [THRIFT-2440](https://issues.apache.org/jira/browse/THRIFT-2440) - how to connect as3 to java by thrift , +- [THRIFT-2379](https://issues.apache.org/jira/browse/THRIFT-2379) - Memmory leaking while using multithreading in C++ server. +- [THRIFT-2277](https://issues.apache.org/jira/browse/THRIFT-2277) - Thrift: installing fb303 error +- [THRIFT-2567](https://issues.apache.org/jira/browse/THRIFT-2567) - Csharp slow ? +- [THRIFT-2573](https://issues.apache.org/jira/browse/THRIFT-2573) - thrift 0.9.2 release + +### Sub-task +- [THRIFT-981](https://issues.apache.org/jira/browse/THRIFT-981) - cocoa: add version Info to the library +- [THRIFT-2132](https://issues.apache.org/jira/browse/THRIFT-2132) - Go: Support for Multiplexing Services on any Transport, Protocol and Server +- [THRIFT-2299](https://issues.apache.org/jira/browse/THRIFT-2299) - TJsonProtocol implementation for Ruby does not allow for both possible slash (solidus) encodings +- [THRIFT-2298](https://issues.apache.org/jira/browse/THRIFT-2298) - TJsonProtocol implementation for C# does not allow for both possible slash (solidus) encodings +- [THRIFT-2297](https://issues.apache.org/jira/browse/THRIFT-2297) - TJsonProtocol implementation for Delphi does not allow for both possible slash (solidus) encodings +- [THRIFT-2271](https://issues.apache.org/jira/browse/THRIFT-2271) - JavaScript: Support for Multiplexing Services +- [THRIFT-2251](https://issues.apache.org/jira/browse/THRIFT-2251) - go test for compact protocol is not running +- [THRIFT-2195](https://issues.apache.org/jira/browse/THRIFT-2195) - Delphi: Add event handlers for server and processing events +- [THRIFT-2176](https://issues.apache.org/jira/browse/THRIFT-2176) - TSimpleJSONProtocol.ReadFieldBegin() does not return field type and ID +- [THRIFT-2175](https://issues.apache.org/jira/browse/THRIFT-2175) - Wrong field type set for binary +- [THRIFT-2174](https://issues.apache.org/jira/browse/THRIFT-2174) - Deserializing JSON fails in specific cases +- [THRIFT-2053](https://issues.apache.org/jira/browse/THRIFT-2053) - NodeJS: Support for Multiplexing Services +- [THRIFT-1914](https://issues.apache.org/jira/browse/THRIFT-1914) - Python: Support for Multiplexing Services on any Transport, Protocol and Server +- [THRIFT-1810](https://issues.apache.org/jira/browse/THRIFT-1810) - add ruby to test/test.sh +- [THRIFT-2310](https://issues.apache.org/jira/browse/THRIFT-2310) - PHP: Client-side support for Multiplexing Services +- [THRIFT-2346](https://issues.apache.org/jira/browse/THRIFT-2346) - C#: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol +- [THRIFT-2345](https://issues.apache.org/jira/browse/THRIFT-2345) - Delphi: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol +- [THRIFT-2338](https://issues.apache.org/jira/browse/THRIFT-2338) - First doctext wrongly interpreted as program doctext in some cases +- [THRIFT-2325](https://issues.apache.org/jira/browse/THRIFT-2325) - SSL test certificates +- [THRIFT-2358](https://issues.apache.org/jira/browse/THRIFT-2358) - C++: add compact protocol to cross language test suite +- [THRIFT-2425](https://issues.apache.org/jira/browse/THRIFT-2425) - PHP: Server-side support for Multiplexing Services +- [THRIFT-2421](https://issues.apache.org/jira/browse/THRIFT-2421) - Tree/Recursive struct support in thrift +- [THRIFT-2290](https://issues.apache.org/jira/browse/THRIFT-2290) - Update Go tutorial to align with THRIFT-2232 +- [THRIFT-2558](https://issues.apache.org/jira/browse/THRIFT-2558) - CSharp compiler generator tries to concat ints with strings using + +- [THRIFT-2507](https://issues.apache.org/jira/browse/THRIFT-2507) - Additional LUA TProtocolException error code needed? +- [THRIFT-2499](https://issues.apache.org/jira/browse/THRIFT-2499) - Compiler: allow annotations without "= value" +- [THRIFT-2534](https://issues.apache.org/jira/browse/THRIFT-2534) - Cross language test results should recorded to a status.md or status.html file automatically +- [THRIFT-66](https://issues.apache.org/jira/browse/THRIFT-66) - Java: Allow multiplexing multiple services over a single TCP connection +- [THRIFT-1681](https://issues.apache.org/jira/browse/THRIFT-1681) - Add Lua Support +- [THRIFT-1727](https://issues.apache.org/jira/browse/THRIFT-1727) - Ruby-1.9: data loss: "binary" fields are re-encoded +- [THRIFT-1726](https://issues.apache.org/jira/browse/THRIFT-1726) - Ruby-1.9: "binary" fields are represented by string whose encoding is "UTF-8" +- [THRIFT-988](https://issues.apache.org/jira/browse/THRIFT-988) - perl: add version Info to the library via configure +- [THRIFT-334](https://issues.apache.org/jira/browse/THRIFT-334) - Compact Protocol for PHP +- [THRIFT-2444](https://issues.apache.org/jira/browse/THRIFT-2444) - pull request 88: thrift: clean up enum value assignment + +### Task +- [THRIFT-2223](https://issues.apache.org/jira/browse/THRIFT-2223) - Spam links on wiki +- [THRIFT-2566](https://issues.apache.org/jira/browse/THRIFT-2566) - Please create a DOAP file for your TLP +- [THRIFT-2237](https://issues.apache.org/jira/browse/THRIFT-2237) - Update archive to contain all versions +- [THRIFT-962](https://issues.apache.org/jira/browse/THRIFT-962) - Tutorial page on our website is really unhelpful + +### Test +- [THRIFT-2327](https://issues.apache.org/jira/browse/THRIFT-2327) - nodejs: nodejs test suite should be bundled with the library +- [THRIFT-2445](https://issues.apache.org/jira/browse/THRIFT-2445) - THRIFT-2384 (code generation for go maps with binary keys) should be tested +- [THRIFT-2501](https://issues.apache.org/jira/browse/THRIFT-2501) - C# The test parameters from the TestServer and TestClient are different from the http://thrift.apache.org/test/ + +### Wish +- [THRIFT-2190](https://issues.apache.org/jira/browse/THRIFT-2190) - Add the JavaScript thrift.js lib to the Bower registry +- [THRIFT-2076](https://issues.apache.org/jira/browse/THRIFT-2076) - boost::optional instead of __isset + +## 0.9.1 + +### Bug +- [THRIFT-1440](https://issues.apache.org/jira/browse/THRIFT-1440) - debian packaging: minor-ish policy problems +- [THRIFT-1402](https://issues.apache.org/jira/browse/THRIFT-1402) - Generated Y_types.js does not require() X_types.js when an include in the IDL file was used +- [THRIFT-1551](https://issues.apache.org/jira/browse/THRIFT-1551) - 2 thrift file define only struct (no service), one include another, the gen nodejs file didn't have "requires" at the top +- [THRIFT-1264](https://issues.apache.org/jira/browse/THRIFT-1264) - TSocketClient is queried by run loop after deallocation in Cocoa +- [THRIFT-1600](https://issues.apache.org/jira/browse/THRIFT-1600) - Thrift Go Compiler and Library out of date with Go 1 Release. +- [THRIFT-1603](https://issues.apache.org/jira/browse/THRIFT-1603) - Thrift IDL allows for multiple exceptions, args or struct member names to be the same +- [THRIFT-1062](https://issues.apache.org/jira/browse/THRIFT-1062) - Problems with python tutorials +- [THRIFT-864](https://issues.apache.org/jira/browse/THRIFT-864) - default value fails if identifier is a struct +- [THRIFT-930](https://issues.apache.org/jira/browse/THRIFT-930) - Ruby and Haskell bindings don't properly support DESTDIR (makes packaging painful) +- [THRIFT-820](https://issues.apache.org/jira/browse/THRIFT-820) - The readLength attribute of TBinaryProtocol is used as an instance variable and is decremented on each call of checkReadLength +- [THRIFT-1640](https://issues.apache.org/jira/browse/THRIFT-1640) - None of the tutorials linked on the website contain content +- [THRIFT-1637](https://issues.apache.org/jira/browse/THRIFT-1637) - NPM registry does not include version 0.8 +- [THRIFT-1648](https://issues.apache.org/jira/browse/THRIFT-1648) - NodeJS clients always receive 0 for 'double' values. +- [THRIFT-1660](https://issues.apache.org/jira/browse/THRIFT-1660) - Python Thrift library can be installed with pip but not easy_install +- [THRIFT-1657](https://issues.apache.org/jira/browse/THRIFT-1657) - Chrome browser sending OPTIONS method before POST in xmlHttpRequest +- [THRIFT-2118](https://issues.apache.org/jira/browse/THRIFT-2118) - Certificate error handling still incorrect +- [THRIFT-2137](https://issues.apache.org/jira/browse/THRIFT-2137) - Ruby test lib fails jenkins build #864 +- [THRIFT-2136](https://issues.apache.org/jira/browse/THRIFT-2136) - Vagrant build not compiling java, ruby, php, go libs due to missing dependencies +- [THRIFT-2135](https://issues.apache.org/jira/browse/THRIFT-2135) - GO lib leaves behind test files that are auto generated +- [THRIFT-2134](https://issues.apache.org/jira/browse/THRIFT-2134) - mingw-cross-compile script failing with strip errors +- [THRIFT-2133](https://issues.apache.org/jira/browse/THRIFT-2133) - java TestTBinaryProtocol.java test failing +- [THRIFT-2126](https://issues.apache.org/jira/browse/THRIFT-2126) - lib/cpp/src/thrift/concurrency/STD* files missing from DIST +- [THRIFT-2125](https://issues.apache.org/jira/browse/THRIFT-2125) - debian missing from DIST +- [THRIFT-2124](https://issues.apache.org/jira/browse/THRIFT-2124) - .o, .so, .la, .deps, .libs, gen-* files left tutorials, test and lib/cpp when making DIST +- [THRIFT-2123](https://issues.apache.org/jira/browse/THRIFT-2123) - GO lib missing files in DIST build +- [THRIFT-2121](https://issues.apache.org/jira/browse/THRIFT-2121) - Compilation bug for Node.js +- [THRIFT-2129](https://issues.apache.org/jira/browse/THRIFT-2129) - php ext missing from dist +- [THRIFT-2128](https://issues.apache.org/jira/browse/THRIFT-2128) - lib GO tests fail with funct ends without a return statement +- [THRIFT-2286](https://issues.apache.org/jira/browse/THRIFT-2286) - Failed to compile Thrift0.9.1 with boost1.55 by VS2010 if select Debug-mt&x64 mode. +- [THRIFT-1973](https://issues.apache.org/jira/browse/THRIFT-1973) - TCompactProtocol in C# lib does not serialize and deserialize negative int32 and int64 number correctly +- [THRIFT-1992](https://issues.apache.org/jira/browse/THRIFT-1992) - casts in TCompactProtocol.tcc causing "dereferencing type-punned pointer will break strict-aliasing rules" warnings from gcc +- [THRIFT-1930](https://issues.apache.org/jira/browse/THRIFT-1930) - C# generates unsigned byte for Thrift "byte" type +- [THRIFT-1929](https://issues.apache.org/jira/browse/THRIFT-1929) - Update website to use Mirrors for downloads +- [THRIFT-1928](https://issues.apache.org/jira/browse/THRIFT-1928) - Race may still exist in TFileTransport::flush() +- [THRIFT-1934](https://issues.apache.org/jira/browse/THRIFT-1934) - Tabs in Example section on main page are not working +- [THRIFT-1933](https://issues.apache.org/jira/browse/THRIFT-1933) - Delphi generator crashes when a typedef references another typedef from an included file +- [THRIFT-1942](https://issues.apache.org/jira/browse/THRIFT-1942) - Binary accelerated cpp extension does not use Thrift namespaces for Exceptions +- [THRIFT-1959](https://issues.apache.org/jira/browse/THRIFT-1959) - C#: Add Union TMemoryBuffer support +- [THRIFT-1958](https://issues.apache.org/jira/browse/THRIFT-1958) - C#: Use static Object.Equals instead of .Equals() calls in equals +- [THRIFT-1957](https://issues.apache.org/jira/browse/THRIFT-1957) - NodeJS TFramedTransport and TBufferedTransport read bytes as unsigned +- [THRIFT-1955](https://issues.apache.org/jira/browse/THRIFT-1955) - Union Type writer generated in C# does not WriteStructBegin +- [THRIFT-1952](https://issues.apache.org/jira/browse/THRIFT-1952) - Travis CI +- [THRIFT-1949](https://issues.apache.org/jira/browse/THRIFT-1949) - WP7 build broken +- [THRIFT-1943](https://issues.apache.org/jira/browse/THRIFT-1943) - docstrings for enum values are ignored +- [THRIFT-2070](https://issues.apache.org/jira/browse/THRIFT-2070) - Improper `HexChar' and 'HexVal' implementation in TJSONProtocol.cs +- [THRIFT-2017](https://issues.apache.org/jira/browse/THRIFT-2017) - Resource Leak in thrift struct under compiler/cpp/src/parse/t_program.h +- [THRIFT-2032](https://issues.apache.org/jira/browse/THRIFT-2032) - C# client leaks sockets/handles +- [THRIFT-1996](https://issues.apache.org/jira/browse/THRIFT-1996) - JavaME Constants generation is broken / inconsistent with regular Java generation +- [THRIFT-2002](https://issues.apache.org/jira/browse/THRIFT-2002) - Haskell: Test use Data.Maybe instead of Maybe +- [THRIFT-2051](https://issues.apache.org/jira/browse/THRIFT-2051) - Vagrant fails to build erlang +- [THRIFT-2050](https://issues.apache.org/jira/browse/THRIFT-2050) - Vagrant C# lib compile fails with TException missing +- [THRIFT-1978](https://issues.apache.org/jira/browse/THRIFT-1978) - Ruby: Thrift should allow for the SSL verify mode to be set +- [THRIFT-1984](https://issues.apache.org/jira/browse/THRIFT-1984) - namespace collision in python bindings +- [THRIFT-1988](https://issues.apache.org/jira/browse/THRIFT-1988) - When trying to build a debian package it fails as the file NEWS doesn't exist +- [THRIFT-1975](https://issues.apache.org/jira/browse/THRIFT-1975) - TBinaryProtocol CheckLength can't be used for a client +- [THRIFT-1995](https://issues.apache.org/jira/browse/THRIFT-1995) - '.' allowed at end of identifier generates non-compilable code +- [THRIFT-2112](https://issues.apache.org/jira/browse/THRIFT-2112) - Error in Go generator when using typedefs in map keys +- [THRIFT-2088](https://issues.apache.org/jira/browse/THRIFT-2088) - Typos in Thrift compiler help text +- [THRIFT-2080](https://issues.apache.org/jira/browse/THRIFT-2080) - C# multiplex processor does not catch IOException +- [THRIFT-2082](https://issues.apache.org/jira/browse/THRIFT-2082) - Executing "gmake clean" is broken +- [THRIFT-2102](https://issues.apache.org/jira/browse/THRIFT-2102) - constants are not referencing to correct type when included from another thrift file +- [THRIFT-2100](https://issues.apache.org/jira/browse/THRIFT-2100) - typedefs are not correctly referenced when including from other thrift files +- [THRIFT-2066](https://issues.apache.org/jira/browse/THRIFT-2066) - 'make install' does not install two headers required for C++ bindings +- [THRIFT-2065](https://issues.apache.org/jira/browse/THRIFT-2065) - Not valid constants filename in Java +- [THRIFT-2047](https://issues.apache.org/jira/browse/THRIFT-2047) - Thrift.Protocol.TCompactProtocol, intToZigZag data lost (TCompactProtocol.cs) +- [THRIFT-2036](https://issues.apache.org/jira/browse/THRIFT-2036) - Thrift gem warns about class variable access from top level +- [THRIFT-2057](https://issues.apache.org/jira/browse/THRIFT-2057) - Vagrant fails on php tests +- [THRIFT-2105](https://issues.apache.org/jira/browse/THRIFT-2105) - Generated code for default values of collections ignores t_field::T_REQUIRED +- [THRIFT-2091](https://issues.apache.org/jira/browse/THRIFT-2091) - Unnecessary 'friend' declaration causes warning in TWinsockSingleton +- [THRIFT-2090](https://issues.apache.org/jira/browse/THRIFT-2090) - Go generator, fix including of other thrift files +- [THRIFT-2106](https://issues.apache.org/jira/browse/THRIFT-2106) - Fix support for namespaces in GO generator +- [THRIFT-1783](https://issues.apache.org/jira/browse/THRIFT-1783) - C# doesn't handle required fields correctly +- [THRIFT-1782](https://issues.apache.org/jira/browse/THRIFT-1782) - async only defined in silverlight +- [THRIFT-1779](https://issues.apache.org/jira/browse/THRIFT-1779) - Missing process_XXXX method in generated TProcessor implementation for all 'oneway' service functions +- [THRIFT-1692](https://issues.apache.org/jira/browse/THRIFT-1692) - SO_REUSEADDR allows for socket hijacking on Windows +- [THRIFT-1720](https://issues.apache.org/jira/browse/THRIFT-1720) - JRuby times out on successful connection +- [THRIFT-1713](https://issues.apache.org/jira/browse/THRIFT-1713) - Named and Anonymous Pipe transport (Delphi) +- [THRIFT-1699](https://issues.apache.org/jira/browse/THRIFT-1699) - Native Union#read has extra read_field_end call +- [THRIFT-1749](https://issues.apache.org/jira/browse/THRIFT-1749) - Python TSSLSocket error handling obscures actual error +- [THRIFT-1748](https://issues.apache.org/jira/browse/THRIFT-1748) - Guard and RWGuard macros defined in global namespace +- [THRIFT-1734](https://issues.apache.org/jira/browse/THRIFT-1734) - Front webpage is still advertising v0.8 as current release +- [THRIFT-1729](https://issues.apache.org/jira/browse/THRIFT-1729) - C glib refactor left empty folders in svn +- [THRIFT-1767](https://issues.apache.org/jira/browse/THRIFT-1767) - unions can't have required fields (Delphi) +- [THRIFT-1765](https://issues.apache.org/jira/browse/THRIFT-1765) - Incorrect error message printed for null or negative keys +- [THRIFT-1778](https://issues.apache.org/jira/browse/THRIFT-1778) - Configure requires manual intervention due to tar failure +- [THRIFT-1777](https://issues.apache.org/jira/browse/THRIFT-1777) - TPipeServer is UNSTOPPABLE +- [THRIFT-1753](https://issues.apache.org/jira/browse/THRIFT-1753) - Multiple C++ Windows, OSX, and iOS portability issues +- [THRIFT-1756](https://issues.apache.org/jira/browse/THRIFT-1756) - 'make -j 8' fails with "unterminated #ifdef" error +- [THRIFT-1773](https://issues.apache.org/jira/browse/THRIFT-1773) - Python library should run on python 2.4 +- [THRIFT-1769](https://issues.apache.org/jira/browse/THRIFT-1769) - unions can't have required fields (C++) +- [THRIFT-1768](https://issues.apache.org/jira/browse/THRIFT-1768) - unions can't have required fields (Compiler) +- [THRIFT-1666](https://issues.apache.org/jira/browse/THRIFT-1666) - htonll usage in TBinaryProtocol.tcc generates warning with MSVC2010 +- [THRIFT-1919](https://issues.apache.org/jira/browse/THRIFT-1919) - libthrift depends on httpcore-4.1.3 (directly) and httpcore-4.1.4 (transitively) +- [THRIFT-1864](https://issues.apache.org/jira/browse/THRIFT-1864) - implement event handler for non-blocking server +- [THRIFT-1859](https://issues.apache.org/jira/browse/THRIFT-1859) - Generated error c++ code with -out and include_prefix param +- [THRIFT-1869](https://issues.apache.org/jira/browse/THRIFT-1869) - TThreadPoolServer (java) dies when threadpool is consumed +- [THRIFT-1842](https://issues.apache.org/jira/browse/THRIFT-1842) - Memory leak with Pipes +- [THRIFT-1838](https://issues.apache.org/jira/browse/THRIFT-1838) - Can't build compiler on OS X because of missing thrifty.h +- [THRIFT-1846](https://issues.apache.org/jira/browse/THRIFT-1846) - Restore socket.h header to support builds with Android NDK +- [THRIFT-1850](https://issues.apache.org/jira/browse/THRIFT-1850) - make check hangs on TSocket tests in TransportTest.cpp +- [THRIFT-1873](https://issues.apache.org/jira/browse/THRIFT-1873) - Binary protocol factory ignores struct read/write flags +- [THRIFT-1872](https://issues.apache.org/jira/browse/THRIFT-1872) - issues with TBufferedTransport buffer +- [THRIFT-1904](https://issues.apache.org/jira/browse/THRIFT-1904) - Incorrect code is generated for typedefs which use included types +- [THRIFT-1903](https://issues.apache.org/jira/browse/THRIFT-1903) - PHP namespaces cause binary protocols to not be used +- [THRIFT-1895](https://issues.apache.org/jira/browse/THRIFT-1895) - Delphi: reserved variable name "result" not detected properly +- [THRIFT-1881](https://issues.apache.org/jira/browse/THRIFT-1881) - TNonblockingServer does not release open connections or threads on shutdown +- [THRIFT-1888](https://issues.apache.org/jira/browse/THRIFT-1888) - Java Thrift client can't connect to Python Thrift server on same host +- [THRIFT-1831](https://issues.apache.org/jira/browse/THRIFT-1831) - Bug in list deserializer +- [THRIFT-1824](https://issues.apache.org/jira/browse/THRIFT-1824) - many compile warning, becase Thread.h includes config.h +- [THRIFT-1823](https://issues.apache.org/jira/browse/THRIFT-1823) - Missing parenthesis breaks "IS_..." macro in generated code +- [THRIFT-1806](https://issues.apache.org/jira/browse/THRIFT-1806) - Python generation always truncates __init__.py files +- [THRIFT-1795](https://issues.apache.org/jira/browse/THRIFT-1795) - Race condition in TThreadedServerPool java implementation +- [THRIFT-1794](https://issues.apache.org/jira/browse/THRIFT-1794) - C# asyncctp broken +- [THRIFT-1804](https://issues.apache.org/jira/browse/THRIFT-1804) - Binary+compact protocol single byte error in Ruby library (ARM architecture): caused by different char signedness +- [THRIFT-1800](https://issues.apache.org/jira/browse/THRIFT-1800) - Documentation text not always escaped correctly when rendered to HTML +- [THRIFT-1788](https://issues.apache.org/jira/browse/THRIFT-1788) - C#: Constants static constructor does not compile +- [THRIFT-1816](https://issues.apache.org/jira/browse/THRIFT-1816) - Need "require" included thrift files in "xxx_types.js" +- [THRIFT-1907](https://issues.apache.org/jira/browse/THRIFT-1907) - Compiling namespace and sub-namespace directives for unrecognized generators should only be a warning +- [THRIFT-1913](https://issues.apache.org/jira/browse/THRIFT-1913) - skipping unknown fields in java unions +- [THRIFT-2553](https://issues.apache.org/jira/browse/THRIFT-2553) - C++ linker error - transport/TSocket +- [THRIFT-274](https://issues.apache.org/jira/browse/THRIFT-274) - Towards a working release/versioning process + +### Documentation +- [THRIFT-1971](https://issues.apache.org/jira/browse/THRIFT-1971) - [Graphviz] Adds tutorial/general description documentation +- [THRIFT-2001](https://issues.apache.org/jira/browse/THRIFT-2001) - http://thrift.apache.org/ Example "C++ Server" tab is broken + +### Improvement +- [THRIFT-1574](https://issues.apache.org/jira/browse/THRIFT-1574) - Apache project branding requirements: DOAP file [PATCH] +- [THRIFT-1347](https://issues.apache.org/jira/browse/THRIFT-1347) - Unify the exceptions returned in generated Go code +- [THRIFT-1353](https://issues.apache.org/jira/browse/THRIFT-1353) - Switch to performance branch, get rid of BinaryParser +- [THRIFT-1629](https://issues.apache.org/jira/browse/THRIFT-1629) - Ruby 1.9 Compatibility during Thrift configure, make, install +- [THRIFT-991](https://issues.apache.org/jira/browse/THRIFT-991) - Refactor Haskell code and generator +- [THRIFT-990](https://issues.apache.org/jira/browse/THRIFT-990) - Sanify gettimeofday usage codebase-wide +- [THRIFT-791](https://issues.apache.org/jira/browse/THRIFT-791) - Let C++ TSimpleServer be driven by an external main loop +- [THRIFT-2117](https://issues.apache.org/jira/browse/THRIFT-2117) - Cocoa TBinaryProtocol strictWrite should be set to true by default +- [THRIFT-2014](https://issues.apache.org/jira/browse/THRIFT-2014) - Change C++ lib includes to use style throughout +- [THRIFT-1972](https://issues.apache.org/jira/browse/THRIFT-1972) - Add support for async processors +- [THRIFT-1970](https://issues.apache.org/jira/browse/THRIFT-1970) - [Graphviz] Adds option to render exceptions relationships +- [THRIFT-1966](https://issues.apache.org/jira/browse/THRIFT-1966) - Support different files for SSL certificates and keys +- [THRIFT-1965](https://issues.apache.org/jira/browse/THRIFT-1965) - Adds Graphviz (graph description language) generator +- [THRIFT-1956](https://issues.apache.org/jira/browse/THRIFT-1956) - Switch to Apache Commons Lang 3 +- [THRIFT-1962](https://issues.apache.org/jira/browse/THRIFT-1962) - Multiplex processor should send any TApplicationException back to client +- [THRIFT-1960](https://issues.apache.org/jira/browse/THRIFT-1960) - main() declares 22 unused gen bools +- [THRIFT-1951](https://issues.apache.org/jira/browse/THRIFT-1951) - libthrift.jar has source files in it +- [THRIFT-1997](https://issues.apache.org/jira/browse/THRIFT-1997) - Add accept backlog configuration method to TServerSocket +- [THRIFT-2003](https://issues.apache.org/jira/browse/THRIFT-2003) - Deprecate senum +- [THRIFT-2052](https://issues.apache.org/jira/browse/THRIFT-2052) - Vagrant machine image defaults to only 384MB of RAM +- [THRIFT-1980](https://issues.apache.org/jira/browse/THRIFT-1980) - Modernize Go tooling, fix go client libary. +- [THRIFT-1977](https://issues.apache.org/jira/browse/THRIFT-1977) - C# compiler should generate constant files prefixed with thrift file name +- [THRIFT-1985](https://issues.apache.org/jira/browse/THRIFT-1985) - add a Vagrantfile to build and test Apache Thrift fully reproducable +- [THRIFT-1994](https://issues.apache.org/jira/browse/THRIFT-1994) - Deprecate slist +- [THRIFT-1993](https://issues.apache.org/jira/browse/THRIFT-1993) - Factory to create instances from known (generated) interface types with Delphi +- [THRIFT-2081](https://issues.apache.org/jira/browse/THRIFT-2081) - Specified timeout should be used in TSocket.Open() +- [THRIFT-2084](https://issues.apache.org/jira/browse/THRIFT-2084) - Delphi: Ability to create entity Thrift-generated instances based on TypeInfo +- [THRIFT-2083](https://issues.apache.org/jira/browse/THRIFT-2083) - Improve the go lib: buffered Transport, save memory allocation, handle concurrent request +- [THRIFT-2109](https://issues.apache.org/jira/browse/THRIFT-2109) - Secure connections should be supported in Go +- [THRIFT-2107](https://issues.apache.org/jira/browse/THRIFT-2107) - minor Go generator fixes +- [THRIFT-1695](https://issues.apache.org/jira/browse/THRIFT-1695) - allow warning-free compilation in VS 2012 and GNU 4.6 +- [THRIFT-1735](https://issues.apache.org/jira/browse/THRIFT-1735) - integrate tutorial into regular build +- [THRIFT-1716](https://issues.apache.org/jira/browse/THRIFT-1716) - max allowed connections should be PIPE_UNLIMITED_INSTANCES +- [THRIFT-1715](https://issues.apache.org/jira/browse/THRIFT-1715) - Allow excluding python parts when building contrib/fb303 +- [THRIFT-1733](https://issues.apache.org/jira/browse/THRIFT-1733) - Fix RPM build issues on RHEL6/OL6 systems +- [THRIFT-1728](https://issues.apache.org/jira/browse/THRIFT-1728) - Upgradation of httpcomponents +- [THRIFT-1876](https://issues.apache.org/jira/browse/THRIFT-1876) - Use enum names instead of casted integers in assignments +- [THRIFT-1874](https://issues.apache.org/jira/browse/THRIFT-1874) - timeout for the server-side end of a named pipe +- [THRIFT-1897](https://issues.apache.org/jira/browse/THRIFT-1897) - Support validation of required fields +- [THRIFT-1896](https://issues.apache.org/jira/browse/THRIFT-1896) - Add TBase protocol for Cocoa +- [THRIFT-1880](https://issues.apache.org/jira/browse/THRIFT-1880) - Make named pipes server work asynchronously (overlapped) to allow for clean server stops +- [THRIFT-1878](https://issues.apache.org/jira/browse/THRIFT-1878) - Add the possibility to send custom headers +- [THRIFT-1882](https://issues.apache.org/jira/browse/THRIFT-1882) - Use single include +- [THRIFT-1793](https://issues.apache.org/jira/browse/THRIFT-1793) - C#: Use static read instead of instance read +- [THRIFT-1799](https://issues.apache.org/jira/browse/THRIFT-1799) - Option to generate HTML in "standalone mode" +- [THRIFT-1815](https://issues.apache.org/jira/browse/THRIFT-1815) - Code generators line buffer output +- [THRIFT-1890](https://issues.apache.org/jira/browse/THRIFT-1890) - C++: Make named pipes server work asynchronously +- [THRIFT-474](https://issues.apache.org/jira/browse/THRIFT-474) - Generating Ruby on Rails friendly code + +### New Feature +- [THRIFT-801](https://issues.apache.org/jira/browse/THRIFT-801) - Provide an interactive shell (irb) when generating ruby bindings +- [THRIFT-2292](https://issues.apache.org/jira/browse/THRIFT-2292) - Android Library Project +- [THRIFT-2012](https://issues.apache.org/jira/browse/THRIFT-2012) - Modernizing Go +- [THRIFT-1969](https://issues.apache.org/jira/browse/THRIFT-1969) - C#: Tests not properly linked from the solution +- [THRIFT-1785](https://issues.apache.org/jira/browse/THRIFT-1785) - C#: Add TMemoryBuffer serializer/deserializer +- [THRIFT-1780](https://issues.apache.org/jira/browse/THRIFT-1780) - Add option to generate nullable values +- [THRIFT-1786](https://issues.apache.org/jira/browse/THRIFT-1786) - C# Union Typing +- [THRIFT-591](https://issues.apache.org/jira/browse/THRIFT-591) - Make the C++ runtime library be compatible with Windows and Visual Studio +- [THRIFT-514](https://issues.apache.org/jira/browse/THRIFT-514) - Add option to configure compiler output directory + +### Question +- [THRIFT-1764](https://issues.apache.org/jira/browse/THRIFT-1764) - how to get the context of client when on a rpc call in server side? +- [THRIFT-1791](https://issues.apache.org/jira/browse/THRIFT-1791) - thrift's namespace directive when generating haskell code + +### Sub-task +- [THRIFT-1594](https://issues.apache.org/jira/browse/THRIFT-1594) - Java test clients should have a return codes that reflect whether it succeeds or not. +- [THRIFT-1595](https://issues.apache.org/jira/browse/THRIFT-1595) - Java test server should follow the documented behavior as of THRIFT-1590 +- [THRIFT-986](https://issues.apache.org/jira/browse/THRIFT-986) - st: add version Info to the library +- [THRIFT-985](https://issues.apache.org/jira/browse/THRIFT-985) - php: add version Info to the library +- [THRIFT-984](https://issues.apache.org/jira/browse/THRIFT-984) - ocaml: add version Info to the library +- [THRIFT-1924](https://issues.apache.org/jira/browse/THRIFT-1924) - Delphi: Inconsistency in serialization of optional fields +- [THRIFT-1922](https://issues.apache.org/jira/browse/THRIFT-1922) - C#: Inconsistency in serialization of optional fields +- [THRIFT-1961](https://issues.apache.org/jira/browse/THRIFT-1961) - C# tests should be in lib/csharp/test/... +- [THRIFT-1822](https://issues.apache.org/jira/browse/THRIFT-1822) - PHP unit test does not work +- [THRIFT-1902](https://issues.apache.org/jira/browse/THRIFT-1902) - C++: Support for Multiplexing Services on any Transport, Protocol and Server +- [THRIFT-1901](https://issues.apache.org/jira/browse/THRIFT-1901) - C#: Support for Multiplexing Services on any Transport, Protocol and Server +- [THRIFT-1899](https://issues.apache.org/jira/browse/THRIFT-1899) - Delphi: Support for Multiplexing Services on any Transport, Protocol and Server +- [THRIFT-563](https://issues.apache.org/jira/browse/THRIFT-563) - Support for Multiplexing Services on any Transport, Protocol and Server + +## 0.9 + +### Bug +- [THRIFT-1438](https://issues.apache.org/jira/browse/THRIFT-1438) - lib/cpp/src/windows/config.h should read version from configure.ac rather than a #define +- [THRIFT-1446](https://issues.apache.org/jira/browse/THRIFT-1446) - Compile error with Delphi 2009 in constant initializer +- [THRIFT-1450](https://issues.apache.org/jira/browse/THRIFT-1450) - Problems building thrift 0.8.0 for Python and Ruby +- [THRIFT-1449](https://issues.apache.org/jira/browse/THRIFT-1449) - Ruby client does not work on solaris (?) +- [THRIFT-1447](https://issues.apache.org/jira/browse/THRIFT-1447) - NullpointerException in ProcessFunction.class :in "oneway" method +- [THRIFT-1433](https://issues.apache.org/jira/browse/THRIFT-1433) - TServerSocket fix for MSVC +- [THRIFT-1429](https://issues.apache.org/jira/browse/THRIFT-1429) - The nonblocking servers is supposed to use TransportFactory to read the data +- [THRIFT-1427](https://issues.apache.org/jira/browse/THRIFT-1427) - PHP library uses non-multibyte safe functions with mbstring function overloading +- [THRIFT-1421](https://issues.apache.org/jira/browse/THRIFT-1421) - Debian Packages can not be built +- [THRIFT-1394](https://issues.apache.org/jira/browse/THRIFT-1394) - Treatment of optional fields is not consistent between C++ and Java +- [THRIFT-1511](https://issues.apache.org/jira/browse/THRIFT-1511) - Server with oneway support ( JAVA ) +- [THRIFT-1496](https://issues.apache.org/jira/browse/THRIFT-1496) - PHP compiler not namespacing enums +- [THRIFT-1495](https://issues.apache.org/jira/browse/THRIFT-1495) - PHP TestClient fatals on missing class +- [THRIFT-1508](https://issues.apache.org/jira/browse/THRIFT-1508) - TServerSocket does not allow for the user to specify the IP address to bind to +- [THRIFT-1504](https://issues.apache.org/jira/browse/THRIFT-1504) - Cocoa Generator should use local file imports for base Thrift headers +- [THRIFT-1512](https://issues.apache.org/jira/browse/THRIFT-1512) - Thrift socket support for Windows XP +- [THRIFT-1502](https://issues.apache.org/jira/browse/THRIFT-1502) - TSimpleServer::serve(): Do not print out error message if server was stopped. +- [THRIFT-1501](https://issues.apache.org/jira/browse/THRIFT-1501) - PHP old namespaces not generated for enums +- [THRIFT-1483](https://issues.apache.org/jira/browse/THRIFT-1483) - java compiler does not generate type parameters for services in extended clauses +- [THRIFT-1479](https://issues.apache.org/jira/browse/THRIFT-1479) - Compiled PHP process functions missing writeMessageEnd() +- [THRIFT-1492](https://issues.apache.org/jira/browse/THRIFT-1492) - enabling c_glib render thrift unusable (even for C++ code) +- [THRIFT-1491](https://issues.apache.org/jira/browse/THRIFT-1491) - Uninitialize processorFactory_ member in TServer.h +- [THRIFT-1475](https://issues.apache.org/jira/browse/THRIFT-1475) - Incomplete records generation for Erlang +- [THRIFT-1486](https://issues.apache.org/jira/browse/THRIFT-1486) - Javascript manual testserver not returning content types +- [THRIFT-1488](https://issues.apache.org/jira/browse/THRIFT-1488) - src/concurrency/Thread.h:91:58: error: invalid conversion from 'pthread_t {aka _opaque_pthread_t*}' to 'apache::thrift::concurrency::Thread::id_t {aka long long unsigned int}' [-fpermissive] +- [THRIFT-1490](https://issues.apache.org/jira/browse/THRIFT-1490) - Windows-specific header files - fixes & tweaks +- [THRIFT-1526](https://issues.apache.org/jira/browse/THRIFT-1526) - Union TupleSchemeFactory returns StandardSchemes +- [THRIFT-1527](https://issues.apache.org/jira/browse/THRIFT-1527) - Generated implementation of tupleReadStruct in unions return null when the setfield is unrecognized +- [THRIFT-1524](https://issues.apache.org/jira/browse/THRIFT-1524) - TNonBlockingServer does not compile in Visual Studio 2010 +- [THRIFT-1529](https://issues.apache.org/jira/browse/THRIFT-1529) - TupleProtocol can unintentionally include an extra byte in bit vectors when number of optional fields is an integral of 8 +- [THRIFT-1473](https://issues.apache.org/jira/browse/THRIFT-1473) - JSON context stack may be left in an incorrect state when an exception is thrown during read or write operations +- [THRIFT-1456](https://issues.apache.org/jira/browse/THRIFT-1456) - System.Net.HttpWebRequest' does not contain a definition for 'Proxy' +- [THRIFT-1468](https://issues.apache.org/jira/browse/THRIFT-1468) - Memory leak in TSaslServerTransport +- [THRIFT-1461](https://issues.apache.org/jira/browse/THRIFT-1461) - Recent TNonblockingServer changes broke --enable-boostthreads=yes, Windows +- [THRIFT-1460](https://issues.apache.org/jira/browse/THRIFT-1460) - why not add unicode strings support to python directly? +- [THRIFT-1464](https://issues.apache.org/jira/browse/THRIFT-1464) - AbstractNonblockingServer.FrameBuffer TNonblockingTransport accessor changed from public to private +- [THRIFT-1467](https://issues.apache.org/jira/browse/THRIFT-1467) - Possible AV with empty strings when using JSON protocol +- [THRIFT-1523](https://issues.apache.org/jira/browse/THRIFT-1523) - clientTimeout not worked as expected in TServerSocket created by TSSLTransportFactory +- [THRIFT-1537](https://issues.apache.org/jira/browse/THRIFT-1537) - TFramedTransport issues +- [THRIFT-1519](https://issues.apache.org/jira/browse/THRIFT-1519) - Thirft Build Failure referencing rb_intern2 symbol +- [THRIFT-1518](https://issues.apache.org/jira/browse/THRIFT-1518) - Generated C++ code only sends the first optional field in the write() function for a struct. +- [THRIFT-1515](https://issues.apache.org/jira/browse/THRIFT-1515) - NameError: global name 'TApplicationException' is not defined +- [THRIFT-1554](https://issues.apache.org/jira/browse/THRIFT-1554) - Inherited service methods are not resolved in derived service implementations +- [THRIFT-1553](https://issues.apache.org/jira/browse/THRIFT-1553) - thrift nodejs service side can't read map structure, key as enum, value as Object +- [THRIFT-1575](https://issues.apache.org/jira/browse/THRIFT-1575) - Typo in server/TThreadPoolServer.h +- [THRIFT-1327](https://issues.apache.org/jira/browse/THRIFT-1327) - Fix Spec Suite under Ruby-1.8.7 (works for MRI Ruby-1.9.2) +- [THRIFT-1326](https://issues.apache.org/jira/browse/THRIFT-1326) - on some platforms, #include is necessary to be included in Thrift.h +- [THRIFT-1159](https://issues.apache.org/jira/browse/THRIFT-1159) - THttpClient->Flush() issue (connection thru proxy) +- [THRIFT-1277](https://issues.apache.org/jira/browse/THRIFT-1277) - Node.js serializes false booleans as null +- [THRIFT-1224](https://issues.apache.org/jira/browse/THRIFT-1224) - Cannot insert UTF-8 text +- [THRIFT-1267](https://issues.apache.org/jira/browse/THRIFT-1267) - Node.js can't throw exceptions. +- [THRIFT-1338](https://issues.apache.org/jira/browse/THRIFT-1338) - Do not use an unpatched autoconf 2.65 to generate release tarball +- [THRIFT-1128](https://issues.apache.org/jira/browse/THRIFT-1128) - MAC OS X: thrift.h incompatibility with Thrift.h +- [THRIFT-1631](https://issues.apache.org/jira/browse/THRIFT-1631) - Fix C++ server constructor typos +- [THRIFT-1602](https://issues.apache.org/jira/browse/THRIFT-1602) - PHP C Extension is not Compatible with PHP 5.4 +- [THRIFT-1610](https://issues.apache.org/jira/browse/THRIFT-1610) - IWebProxy not available on WP7 platform +- [THRIFT-1606](https://issues.apache.org/jira/browse/THRIFT-1606) - Race condition in BoostThreadFactory.cpp +- [THRIFT-1604](https://issues.apache.org/jira/browse/THRIFT-1604) - Python exception handeling for changes from PEP 3110 +- [THRIFT-1607](https://issues.apache.org/jira/browse/THRIFT-1607) - Incorrect file modes for several source files +- [THRIFT-1583](https://issues.apache.org/jira/browse/THRIFT-1583) - c_glib leaks memory +- [THRIFT-1582](https://issues.apache.org/jira/browse/THRIFT-1582) - Bad includes of nested thrift files in c_glib +- [THRIFT-1578](https://issues.apache.org/jira/browse/THRIFT-1578) - C_GLib generated code does not compile +- [THRIFT-1597](https://issues.apache.org/jira/browse/THRIFT-1597) - TJSONProtocol.php is missing from Makefile.am +- [THRIFT-1591](https://issues.apache.org/jira/browse/THRIFT-1591) - Enable TCP_NODELAY for ruby gem +- [THRIFT-1624](https://issues.apache.org/jira/browse/THRIFT-1624) - Isset Generated differently on different platforms +- [THRIFT-1622](https://issues.apache.org/jira/browse/THRIFT-1622) - Incorrect size returned on read +- [THRIFT-1621](https://issues.apache.org/jira/browse/THRIFT-1621) - Memory leaks +- [THRIFT-1612](https://issues.apache.org/jira/browse/THRIFT-1612) - Base64 encoding is broken +- [THRIFT-1627](https://issues.apache.org/jira/browse/THRIFT-1627) - compiler built using compilers.vcxproj cannot be used to build some test .thrift files +- [THRIFT-1571](https://issues.apache.org/jira/browse/THRIFT-1571) - Update Ruby HTTP transport for recent Ruby versions +- [THRIFT-1023](https://issues.apache.org/jira/browse/THRIFT-1023) - Thrift encoding (UTF-8) issue with Ruby 1.9.2 +- [THRIFT-1090](https://issues.apache.org/jira/browse/THRIFT-1090) - Document the generation of a file called "Constants.java" +- [THRIFT-1082](https://issues.apache.org/jira/browse/THRIFT-1082) - Thrift::FramedTransport sometimes calls close() on an undefined value +- [THRIFT-956](https://issues.apache.org/jira/browse/THRIFT-956) - Python module's version meta-data should be updated +- [THRIFT-973](https://issues.apache.org/jira/browse/THRIFT-973) - Cocoa library won't compile using clang +- [THRIFT-1632](https://issues.apache.org/jira/browse/THRIFT-1632) - ruby: data corruption in thrift_native implementation of MemoryBufferTransport +- [THRIFT-1665](https://issues.apache.org/jira/browse/THRIFT-1665) - TBinaryProtocol: exceeded message length raises generic TException +- [THRIFT-1664](https://issues.apache.org/jira/browse/THRIFT-1664) - Reference to non-existing variable in build script +- [THRIFT-1663](https://issues.apache.org/jira/browse/THRIFT-1663) - Java Thrift server is not throwing exceptions +- [THRIFT-1662](https://issues.apache.org/jira/browse/THRIFT-1662) - "removeObject:" should be "removeObserver:" in [-TSocketServer dealloc]? +- [THRIFT-1643](https://issues.apache.org/jira/browse/THRIFT-1643) - Denial of Service attack in TBinaryProtocol.readString +- [THRIFT-1674](https://issues.apache.org/jira/browse/THRIFT-1674) - Update Thrift D library to be compatible with 2.060 +- [THRIFT-1673](https://issues.apache.org/jira/browse/THRIFT-1673) - Ruby compile flags for extension for multi arch builds (os x) +- [THRIFT-1655](https://issues.apache.org/jira/browse/THRIFT-1655) - Configure still trying to use thrift_generators in output +- [THRIFT-1654](https://issues.apache.org/jira/browse/THRIFT-1654) - c_glib thrift_socket_read() returns corrupted data +- [THRIFT-1653](https://issues.apache.org/jira/browse/THRIFT-1653) - TThreadedSelectorServer leaks CLOSE_WAIT sockets +- [THRIFT-1658](https://issues.apache.org/jira/browse/THRIFT-1658) - Java thrift server is not throwing TApplicationException +- [THRIFT-1656](https://issues.apache.org/jira/browse/THRIFT-1656) - Setting proper headers in THttpServer.cpp so that "Cross-Origin Resource Sharing" on js client can work. +- [THRIFT-1652](https://issues.apache.org/jira/browse/THRIFT-1652) - TSaslTransport does not log the error when kerberos auth fails +- [THRIFT-2272](https://issues.apache.org/jira/browse/THRIFT-2272) - CLONE - Denial of Service attack in TBinaryProtocol.readString +- [THRIFT-2086](https://issues.apache.org/jira/browse/THRIFT-2086) - Invalid generated code for Node.JS when using namespaces +- [THRIFT-1686](https://issues.apache.org/jira/browse/THRIFT-1686) - t_php_generator.cc uses "and" instead of "&&", and causes compiler errors with Visual Studio +- [THRIFT-1693](https://issues.apache.org/jira/browse/THRIFT-1693) - libthrift has dependency on two different versions of httpcore +- [THRIFT-1689](https://issues.apache.org/jira/browse/THRIFT-1689) - don't exit(-1) in TNonblockingServer +- [THRIFT-1679](https://issues.apache.org/jira/browse/THRIFT-1679) - NodeJS: protocol readString() should treat string as utf8, not binary +- [THRIFT-1721](https://issues.apache.org/jira/browse/THRIFT-1721) - Dist broken due to 0.8.0 to 0.9.0 changes +- [THRIFT-1710](https://issues.apache.org/jira/browse/THRIFT-1710) - Minor issues in test case code +- [THRIFT-1709](https://issues.apache.org/jira/browse/THRIFT-1709) - Warning "Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first" in TBinaryProtocol.cs at ReadInt64() +- [THRIFT-1707](https://issues.apache.org/jira/browse/THRIFT-1707) - [ruby] Adjust server_spec.rb for RSpec 2.11.x and Ruby 1.9.3 +- [THRIFT-1671](https://issues.apache.org/jira/browse/THRIFT-1671) - Cocoa code generator does not put keywords into generated method calls +- [THRIFT-1670](https://issues.apache.org/jira/browse/THRIFT-1670) - Incompatibilities between different versions of a Thrift interface +- [THRIFT-1669](https://issues.apache.org/jira/browse/THRIFT-1669) - NameError: global name 'TApplicationException' is not defined +- [THRIFT-1668](https://issues.apache.org/jira/browse/THRIFT-1668) - Compile error in contrib/fb303, thrift/TDispatchProcessor.h: No such file or directory +- [THRIFT-1845](https://issues.apache.org/jira/browse/THRIFT-1845) - Fix compiler warning caused by implicit string conversion with Xcode 4.6 +- [THRIFT-304](https://issues.apache.org/jira/browse/THRIFT-304) - Building the Python library requires development headers +- [THRIFT-369](https://issues.apache.org/jira/browse/THRIFT-369) - sets and maps break equality +- [THRIFT-556](https://issues.apache.org/jira/browse/THRIFT-556) - Ruby compiler does not correctly referred to top-level modules when a submodule masks the top-level name +- [THRIFT-481](https://issues.apache.org/jira/browse/THRIFT-481) - indentation of ruby classes is off by a few + +### Improvement +- [THRIFT-1498](https://issues.apache.org/jira/browse/THRIFT-1498) - Allow TThreadedPoolServer.Args to pass a ExecutorService +- [THRIFT-1444](https://issues.apache.org/jira/browse/THRIFT-1444) - FunctionRunner - add syntactic sugar to create shared_ptrs +- [THRIFT-1443](https://issues.apache.org/jira/browse/THRIFT-1443) - define a TProcessor helper class to implement process() +- [THRIFT-1441](https://issues.apache.org/jira/browse/THRIFT-1441) - Generate constructor with parameters for exception class to let it update message property automatically. +- [THRIFT-1520](https://issues.apache.org/jira/browse/THRIFT-1520) - Embed version number in erlang .app file +- [THRIFT-1480](https://issues.apache.org/jira/browse/THRIFT-1480) - python: remove tabs, adjust whitespace and address PEP8 warnings +- [THRIFT-1485](https://issues.apache.org/jira/browse/THRIFT-1485) - Performance: pass large and/or refcounted arguments as "const" +- [THRIFT-1484](https://issues.apache.org/jira/browse/THRIFT-1484) - Introduce phpunit test suite +- [THRIFT-1532](https://issues.apache.org/jira/browse/THRIFT-1532) - The type specifications in the generated Erlang code should include "undefined" where it's used as a default value +- [THRIFT-1534](https://issues.apache.org/jira/browse/THRIFT-1534) - Required fields in the Delphi code generator. +- [THRIFT-1469](https://issues.apache.org/jira/browse/THRIFT-1469) - Java isset space optimization +- [THRIFT-1465](https://issues.apache.org/jira/browse/THRIFT-1465) - Visibility of methods in generated java code +- [THRIFT-1453](https://issues.apache.org/jira/browse/THRIFT-1453) - Don't change types of arguments when serializing with thrift php extension +- [THRIFT-1452](https://issues.apache.org/jira/browse/THRIFT-1452) - generate a swap() method for all generated structs +- [THRIFT-1451](https://issues.apache.org/jira/browse/THRIFT-1451) - FramedTransport: Prevent infinite loop when writing +- [THRIFT-1521](https://issues.apache.org/jira/browse/THRIFT-1521) - Two patches for more Performance +- [THRIFT-1555](https://issues.apache.org/jira/browse/THRIFT-1555) - Delphi version of the tutorial code +- [THRIFT-1535](https://issues.apache.org/jira/browse/THRIFT-1535) - Why thrift don't use wrapped class for optional fields ? +- [THRIFT-1204](https://issues.apache.org/jira/browse/THRIFT-1204) - Ruby autogenerated files should require 'thrift' gem +- [THRIFT-1344](https://issues.apache.org/jira/browse/THRIFT-1344) - Using the httpc module directly rather than the deprecated http layer +- [THRIFT-1343](https://issues.apache.org/jira/browse/THRIFT-1343) - no_auto_import min/2 to avoid compile warning +- [THRIFT-1340](https://issues.apache.org/jira/browse/THRIFT-1340) - Add support of ARC to Objective-C +- [THRIFT-1611](https://issues.apache.org/jira/browse/THRIFT-1611) - Improved code generation for typedefs +- [THRIFT-1593](https://issues.apache.org/jira/browse/THRIFT-1593) - Pass on errors like "connection closed" to the handler module +- [THRIFT-1615](https://issues.apache.org/jira/browse/THRIFT-1615) - PHP Namespace +- [THRIFT-1567](https://issues.apache.org/jira/browse/THRIFT-1567) - Thrift/cpp: Allow alternate classes to be used for +- [THRIFT-1072](https://issues.apache.org/jira/browse/THRIFT-1072) - Missing - (id) initWithSharedProcessor in TSharedProcessorFactory.h +- [THRIFT-1650](https://issues.apache.org/jira/browse/THRIFT-1650) - [ruby] Update clean items and svn:ignore entries for OS X artifacts +- [THRIFT-1661](https://issues.apache.org/jira/browse/THRIFT-1661) - [PATCH] Add --with-qt4 configure option +- [THRIFT-1675](https://issues.apache.org/jira/browse/THRIFT-1675) - Do we have any plan to support scala? +- [THRIFT-1645](https://issues.apache.org/jira/browse/THRIFT-1645) - Replace Object#tee with more conventional Object#tap in specs +- [THRIFT-1644](https://issues.apache.org/jira/browse/THRIFT-1644) - Upgrade RSpec to 2.10.x and refactor specs as needed +- [THRIFT-1672](https://issues.apache.org/jira/browse/THRIFT-1672) - MonoTouch (and Mono for Android) compatibility +- [THRIFT-1702](https://issues.apache.org/jira/browse/THRIFT-1702) - a thrift manual +- [THRIFT-1694](https://issues.apache.org/jira/browse/THRIFT-1694) - Re-Enable serialization for WP7 Silverlight +- [THRIFT-1691](https://issues.apache.org/jira/browse/THRIFT-1691) - Serializer/deserializer support for Delphi +- [THRIFT-1688](https://issues.apache.org/jira/browse/THRIFT-1688) - Update IDL page markup +- [THRIFT-1725](https://issues.apache.org/jira/browse/THRIFT-1725) - Tutorial web pages for Delphi and C# +- [THRIFT-1714](https://issues.apache.org/jira/browse/THRIFT-1714) - [ruby] Explicitly add CWD to Ruby test_suites.rb +- [THRIFT-317](https://issues.apache.org/jira/browse/THRIFT-317) - Issues with Java struct validation +- [THRIFT-164](https://issues.apache.org/jira/browse/THRIFT-164) - Build web tutorial on Incubator web site +- [THRIFT-541](https://issues.apache.org/jira/browse/THRIFT-541) - Cocoa code generator doesn't put keywords before all arguments. +- [THRIFT-681](https://issues.apache.org/jira/browse/THRIFT-681) - The HTML generator does not handle JavaDoc style comments very well + +### New Feature +- [THRIFT-1500](https://issues.apache.org/jira/browse/THRIFT-1500) - D programming language support +- [THRIFT-1510](https://issues.apache.org/jira/browse/THRIFT-1510) - There should be an implementation of the JsonProtocol for ruby +- [THRIFT-1115](https://issues.apache.org/jira/browse/THRIFT-1115) - python TBase class for dynamic (de)serialization, and __slots__ option for memory savings +- [THRIFT-1953](https://issues.apache.org/jira/browse/THRIFT-1953) - support for asp.net mvc 3 + +### Question +- [THRIFT-1235](https://issues.apache.org/jira/browse/THRIFT-1235) - How could I use THttpServerTransportFactory withTNonBlockingServer +- [THRIFT-1368](https://issues.apache.org/jira/browse/THRIFT-1368) - TNonblockingServer usage +- [THRIFT-1061](https://issues.apache.org/jira/browse/THRIFT-1061) - Read an invalid frame size of 0. Are you using TFramedTransport on the client side? +- [THRIFT-491](https://issues.apache.org/jira/browse/THRIFT-491) - Ripping raw pthreads out of TFileTransport and associated test issues + +### Sub-task +- [THRIFT-1596](https://issues.apache.org/jira/browse/THRIFT-1596) - Delphi: Test clients should have a return codes that reflect whether they succeeded or not +- [THRIFT-982](https://issues.apache.org/jira/browse/THRIFT-982) - javame: add version Info to the library +- [THRIFT-1722](https://issues.apache.org/jira/browse/THRIFT-1722) - C# WP7 Assembly addition beaks mono build +- [THRIFT-336](https://issues.apache.org/jira/browse/THRIFT-336) - Compact Protocol in C# + +### Test +- [THRIFT-1613](https://issues.apache.org/jira/browse/THRIFT-1613) - Add code back into empty source file ToStringTest.java +- [THRIFT-1718](https://issues.apache.org/jira/browse/THRIFT-1718) - Incorrect check in TFileTransportTest + +### Wish +- [THRIFT-1463](https://issues.apache.org/jira/browse/THRIFT-1463) - Decouple Thrift IDL from generators +- [THRIFT-1466](https://issues.apache.org/jira/browse/THRIFT-1466) - Proper Documentation for Thrift C Glib +- [THRIFT-1539](https://issues.apache.org/jira/browse/THRIFT-1539) - Build and distribute the fb303 python libraries along with thrift +- [THRIFT-1685](https://issues.apache.org/jira/browse/THRIFT-1685) - Please add "aereo.com" to "Powered by Apache Thrift" list in about page +- [THRIFT-330](https://issues.apache.org/jira/browse/THRIFT-330) - TProcessor - additional method to called when connection is broken + +## 0.8 + +### Bug +- [THRIFT-1436](https://issues.apache.org/jira/browse/THRIFT-1436) - pip install thrift fails on Windows with "Unable to find vcvarsall.bat" +- [THRIFT-1432](https://issues.apache.org/jira/browse/THRIFT-1432) - Javascript struct constants declared in the same file as their struct definition will cause an error +- [THRIFT-1428](https://issues.apache.org/jira/browse/THRIFT-1428) - shared.thrft does not include namespace for php, so thrift compiler generate incorrect name +- [THRIFT-1426](https://issues.apache.org/jira/browse/THRIFT-1426) - Dist package missing files for release 0.8 +- [THRIFT-1425](https://issues.apache.org/jira/browse/THRIFT-1425) - The Node package is incompatible with latest node (0.6) & npm (1.0.27) +- [THRIFT-1416](https://issues.apache.org/jira/browse/THRIFT-1416) - Python Unit test is broken on ci +- [THRIFT-1419](https://issues.apache.org/jira/browse/THRIFT-1419) - AbstractNonBlockingServer does not catch errors when invoking the processor +- [THRIFT-1424](https://issues.apache.org/jira/browse/THRIFT-1424) - Ruby specs fail when run with rake +- [THRIFT-1420](https://issues.apache.org/jira/browse/THRIFT-1420) - Nonblocking and HsHa server should make sure to close all their socket connections when the selector exits +- [THRIFT-1413](https://issues.apache.org/jira/browse/THRIFT-1413) - Generated code does not read MapEnd / ListEnd / SetEnd +- [THRIFT-1409](https://issues.apache.org/jira/browse/THRIFT-1409) - Name conflict check does not work properly for exception object(Delphi). +- [THRIFT-1408](https://issues.apache.org/jira/browse/THRIFT-1408) - Delphi Test Server: Exception test case fails due to naming conflict with e.message +- [THRIFT-1407](https://issues.apache.org/jira/browse/THRIFT-1407) - Typo in Python socket server causes Thrift to fail when we enable a global socket timout +- [THRIFT-1397](https://issues.apache.org/jira/browse/THRIFT-1397) - CI server fails during build due to unused parameters in delphi generator +- [THRIFT-1404](https://issues.apache.org/jira/browse/THRIFT-1404) - Delphi compiler generates struct reader code with problem. +- [THRIFT-1400](https://issues.apache.org/jira/browse/THRIFT-1400) - Ruby native extension aborts with __stack_chk_fail in OSX +- [THRIFT-1399](https://issues.apache.org/jira/browse/THRIFT-1399) - One of the TServerImpl.Create CTORs lacks implementation +- [THRIFT-1390](https://issues.apache.org/jira/browse/THRIFT-1390) - Debian packages build fix for Squeeze (build from the official 0.7.0 tarball) +- [THRIFT-1393](https://issues.apache.org/jira/browse/THRIFT-1393) - TTransportException's thrown from THttpClient contain superfluous slashes in the Exception message +- [THRIFT-1392](https://issues.apache.org/jira/browse/THRIFT-1392) - Enabling both namespaces and autoloading in generated PHP code won't work. +- [THRIFT-1406](https://issues.apache.org/jira/browse/THRIFT-1406) - Build error after applying THRIFT-1395 +- [THRIFT-1405](https://issues.apache.org/jira/browse/THRIFT-1405) - Delphi compiler does not generates container serializer properly. +- [THRIFT-1411](https://issues.apache.org/jira/browse/THRIFT-1411) - java generator does not provide type parameter for TBaseProcessor +- [THRIFT-1473](https://issues.apache.org/jira/browse/THRIFT-1473) - JSON context stack may be left in an incorrect state when an exception is thrown during read or write operations +- [THRIFT-1331](https://issues.apache.org/jira/browse/THRIFT-1331) - Ruby library deserializes an empty map to nil +- [THRIFT-1330](https://issues.apache.org/jira/browse/THRIFT-1330) - PHP Namespaces no longer generated +- [THRIFT-1328](https://issues.apache.org/jira/browse/THRIFT-1328) - TBaseHelper.toString(...) appends ByteBuffer data outside of valid buffer range +- [THRIFT-1322](https://issues.apache.org/jira/browse/THRIFT-1322) - OCaml lib fail to compile: Thrift.ml line 305, int vs int32 mismatch +- [THRIFT-1143](https://issues.apache.org/jira/browse/THRIFT-1143) - Build doesn't detect correct architecture type on 64bit osx +- [THRIFT-1205](https://issues.apache.org/jira/browse/THRIFT-1205) - port server unduly fragile with arbitrary input +- [THRIFT-1279](https://issues.apache.org/jira/browse/THRIFT-1279) - type set is handled incorrectly when writing object +- [THRIFT-1298](https://issues.apache.org/jira/browse/THRIFT-1298) - Standard scheme doesn't read or write metadata along with field values +- [THRIFT-1265](https://issues.apache.org/jira/browse/THRIFT-1265) - C++ container deserialize +- [THRIFT-1263](https://issues.apache.org/jira/browse/THRIFT-1263) - publish ruby client to rubygems +- [THRIFT-1384](https://issues.apache.org/jira/browse/THRIFT-1384) - Java help menu missing newline near javame flag +- [THRIFT-1382](https://issues.apache.org/jira/browse/THRIFT-1382) - Bundle install doesnot work because thrift crashes +- [THRIFT-1381](https://issues.apache.org/jira/browse/THRIFT-1381) - Thrift C++ libs have incorrectly versioned names +- [THRIFT-1350](https://issues.apache.org/jira/browse/THRIFT-1350) - Go library code does not build as of r60 (most recent release) +- [THRIFT-1365](https://issues.apache.org/jira/browse/THRIFT-1365) - TupleProtocol#writeBitSet unintentionally writes a variable length byte array +- [THRIFT-1359](https://issues.apache.org/jira/browse/THRIFT-1359) - --gen-cob cpp:cob_style does not compile anymore +- [THRIFT-1319](https://issues.apache.org/jira/browse/THRIFT-1319) - Mismatch between how a union reads and writes a container +- [THRIFT-1309](https://issues.apache.org/jira/browse/THRIFT-1309) - libfb303-0.7.0.jar missing in maven repository +- [THRIFT-1238](https://issues.apache.org/jira/browse/THRIFT-1238) - Thrift JS client cannot read map of structures +- [THRIFT-1254](https://issues.apache.org/jira/browse/THRIFT-1254) - Code can't be compiled against a regular JRE: Object.clone() override has a different return type +- [THRIFT-1367](https://issues.apache.org/jira/browse/THRIFT-1367) - Mac OSX build fails with "no such file to load -- spec/rake/spectask" +- [THRIFT-1355](https://issues.apache.org/jira/browse/THRIFT-1355) - Running make in lib/rb doesn't build the native extensions +- [THRIFT-1370](https://issues.apache.org/jira/browse/THRIFT-1370) - Debian packaging should Build-Depend on libglib2.0-dev +- [THRIFT-1342](https://issues.apache.org/jira/browse/THRIFT-1342) - Compilation problem on Windows of fastbinary.c +- [THRIFT-1341](https://issues.apache.org/jira/browse/THRIFT-1341) - TProtocol.h endian detection wrong with boost +- [THRIFT-1583](https://issues.apache.org/jira/browse/THRIFT-1583) - c_glib leaks memory +- [THRIFT-1582](https://issues.apache.org/jira/browse/THRIFT-1582) - Bad includes of nested thrift files in c_glib +- [THRIFT-1578](https://issues.apache.org/jira/browse/THRIFT-1578) - C_GLib generated code does not compile +- [THRIFT-1027](https://issues.apache.org/jira/browse/THRIFT-1027) - 'make -j 16' fails with "unterminated #ifdef" error +- [THRIFT-1121](https://issues.apache.org/jira/browse/THRIFT-1121) - Java server performance regression in 0.6 +- [THRIFT-857](https://issues.apache.org/jira/browse/THRIFT-857) - tests run by "make install" fail if generators are disabled +- [THRIFT-380](https://issues.apache.org/jira/browse/THRIFT-380) - Use setuptools for python build + +### Dependency upgrade +- [THRIFT-1257](https://issues.apache.org/jira/browse/THRIFT-1257) - thrift's dependency scope on javax.servlet:servlet-api should be 'provided' + +### Improvement +- [THRIFT-1445](https://issues.apache.org/jira/browse/THRIFT-1445) - minor C++ generator variable cleanup +- [THRIFT-1435](https://issues.apache.org/jira/browse/THRIFT-1435) - make TException.Message property conformant to the usual expectations +- [THRIFT-1431](https://issues.apache.org/jira/browse/THRIFT-1431) - Rename 'sys' module to 'util' +- [THRIFT-1396](https://issues.apache.org/jira/browse/THRIFT-1396) - Dephi generator has dependacy on boost 1.42 later. +- [THRIFT-1395](https://issues.apache.org/jira/browse/THRIFT-1395) - Patch to prevent warnings for integer types in some cases +- [THRIFT-1275](https://issues.apache.org/jira/browse/THRIFT-1275) - thrift: always prefix namespaces with " ::" +- [THRIFT-1274](https://issues.apache.org/jira/browse/THRIFT-1274) - thrift: fail compilation if an unexpected token is +- [THRIFT-1271](https://issues.apache.org/jira/browse/THRIFT-1271) - thrift: fix missing namespace in generated local +- [THRIFT-1270](https://issues.apache.org/jira/browse/THRIFT-1270) - thrift: add --allow-neg-keys argument to allow +- [THRIFT-1345](https://issues.apache.org/jira/browse/THRIFT-1345) - Allow building without tests +- [THRIFT-1286](https://issues.apache.org/jira/browse/THRIFT-1286) - Modernize the Thrift Ruby Library Dev Environment +- [THRIFT-1284](https://issues.apache.org/jira/browse/THRIFT-1284) - thrift: fix processor inheritance +- [THRIFT-1283](https://issues.apache.org/jira/browse/THRIFT-1283) - thrift: wrap t_cpp_generator::generate_process_function() to 80 +- [THRIFT-1282](https://issues.apache.org/jira/browse/THRIFT-1282) - Upgrade httpclient to 4.1.2 (from 4.0.1) +- [THRIFT-1281](https://issues.apache.org/jira/browse/THRIFT-1281) - add @generated to the docblock +- [THRIFT-1280](https://issues.apache.org/jira/browse/THRIFT-1280) - Thrift: Improve Monitor exception-free interfaces +- [THRIFT-1278](https://issues.apache.org/jira/browse/THRIFT-1278) - javadoc warnings - compilation +- [THRIFT-1227](https://issues.apache.org/jira/browse/THRIFT-1227) - Erlang implementation of thrift JSON protocol +- [THRIFT-1295](https://issues.apache.org/jira/browse/THRIFT-1295) - Duplicate include in TSocket.cpp +- [THRIFT-1294](https://issues.apache.org/jira/browse/THRIFT-1294) - thrift: fix log message typos in TSimpleServer +- [THRIFT-1293](https://issues.apache.org/jira/browse/THRIFT-1293) - thrift: improve handling of exceptions thrown by +- [THRIFT-1292](https://issues.apache.org/jira/browse/THRIFT-1292) - thrift: silence log spew from TThreadedServer +- [THRIFT-1288](https://issues.apache.org/jira/browse/THRIFT-1288) - Allow typedefed exceptions in throws clauses +- [THRIFT-1290](https://issues.apache.org/jira/browse/THRIFT-1290) - thrift: TNonblockingServer: clean up state in the +- [THRIFT-1287](https://issues.apache.org/jira/browse/THRIFT-1287) - thrift: start refactoring some of the C++ processor +- [THRIFT-1289](https://issues.apache.org/jira/browse/THRIFT-1289) - thrift: implement TNonblockingServer::stop() +- [THRIFT-1305](https://issues.apache.org/jira/browse/THRIFT-1305) - thrift: make TConnection a private inner class of +- [THRIFT-1304](https://issues.apache.org/jira/browse/THRIFT-1304) - TNonblockingServer: pass in the connection context to +- [THRIFT-1302](https://issues.apache.org/jira/browse/THRIFT-1302) - thrift: raise an exception if send() times out in +- [THRIFT-1301](https://issues.apache.org/jira/browse/THRIFT-1301) - thrift: consolidate common code in TNonblockingServer +- [THRIFT-1377](https://issues.apache.org/jira/browse/THRIFT-1377) - abort PHP deserialization on unknown field type +- [THRIFT-1379](https://issues.apache.org/jira/browse/THRIFT-1379) - fix uninitialized enum values in thrift C++ objects +- [THRIFT-1376](https://issues.apache.org/jira/browse/THRIFT-1376) - Make port specification option in thrift remote +- [THRIFT-1375](https://issues.apache.org/jira/browse/THRIFT-1375) - fixed a hex char conversion bug in TJSONProtocol +- [THRIFT-1373](https://issues.apache.org/jira/browse/THRIFT-1373) - Fix user-defined exception generation in thrift (python) +- [THRIFT-1361](https://issues.apache.org/jira/browse/THRIFT-1361) - Optional replacement of pthread by boost::thread +- [THRIFT-1320](https://issues.apache.org/jira/browse/THRIFT-1320) - Consistency of configure generated config.h +- [THRIFT-1317](https://issues.apache.org/jira/browse/THRIFT-1317) - Remove copy constructibility from +- [THRIFT-1316](https://issues.apache.org/jira/browse/THRIFT-1316) - thrift: update server classes to accept +- [THRIFT-1315](https://issues.apache.org/jira/browse/THRIFT-1315) - thrift: generate server interface factory classes +- [THRIFT-1314](https://issues.apache.org/jira/browse/THRIFT-1314) - thrift: add TProcessorFactory +- [THRIFT-1335](https://issues.apache.org/jira/browse/THRIFT-1335) - Add accept timeout to TServerSocket +- [THRIFT-1334](https://issues.apache.org/jira/browse/THRIFT-1334) - Add more info to IllegalStateException +- [THRIFT-1333](https://issues.apache.org/jira/browse/THRIFT-1333) - Make RWGuard not copyable +- [THRIFT-1332](https://issues.apache.org/jira/browse/THRIFT-1332) - TSSLTransportParameters class uses hard coded value keyManagerType: SunX509 +- [THRIFT-1251](https://issues.apache.org/jira/browse/THRIFT-1251) - Generated java code should indicate which fields are required and which are optional +- [THRIFT-1387](https://issues.apache.org/jira/browse/THRIFT-1387) - Build MSVC libraries with Boost Threads instead of Pthreads +- [THRIFT-1339](https://issues.apache.org/jira/browse/THRIFT-1339) - Extend Tuple Protocol to TUnions +- [THRIFT-1031](https://issues.apache.org/jira/browse/THRIFT-1031) - Patch to compile Thrift for vc++ 9.0 and 10.0 +- [THRIFT-1130](https://issues.apache.org/jira/browse/THRIFT-1130) - Add the ability to specify symbolic default value for optional boolean +- [THRIFT-1123](https://issues.apache.org/jira/browse/THRIFT-1123) - Patch to compile Thrift server and client for vc++ 9.0 and 10.0 +- [THRIFT-386](https://issues.apache.org/jira/browse/THRIFT-386) - Make it possible to build the Python library without the extension + +### New Feature +- [THRIFT-1401](https://issues.apache.org/jira/browse/THRIFT-1401) - JSON-protocol for Delphi XE Libraries +- [THRIFT-1167](https://issues.apache.org/jira/browse/THRIFT-1167) - Java nonblocking server with more than one thread for select and handling IO +- [THRIFT-1366](https://issues.apache.org/jira/browse/THRIFT-1366) - Delphi generator, lirbrary and unit test. +- [THRIFT-1354](https://issues.apache.org/jira/browse/THRIFT-1354) - Add rake task to build just the gem file +- [THRIFT-769](https://issues.apache.org/jira/browse/THRIFT-769) - Pluggable Serializers + +### Sub-task +- [THRIFT-1415](https://issues.apache.org/jira/browse/THRIFT-1415) - delphi: add version Info to the library +- [THRIFT-1391](https://issues.apache.org/jira/browse/THRIFT-1391) - Improved Delphi XE test cases + +## 0.7 + +### Bug +- [THRIFT-1140](https://issues.apache.org/jira/browse/THRIFT-1140) - Framed Transport Client using C (Glib) Library hangs when connecting to Ruby Server +- [THRIFT-1154](https://issues.apache.org/jira/browse/THRIFT-1154) - HttpClient does not specify the connection close parameter +- [THRIFT-1153](https://issues.apache.org/jira/browse/THRIFT-1153) - HttpClient does not specify the connection close parameter +- [THRIFT-1149](https://issues.apache.org/jira/browse/THRIFT-1149) - Nonblocking server fails when client connection is reset +- [THRIFT-1146](https://issues.apache.org/jira/browse/THRIFT-1146) - Android Incompatibility : in Android < 2.3 java.io.IOException doesn't support for Throwable parameter in constructor +- [THRIFT-1133](https://issues.apache.org/jira/browse/THRIFT-1133) - Java and JavaScript tutorial is broken since we have Java maven deployment +- [THRIFT-1132](https://issues.apache.org/jira/browse/THRIFT-1132) - Deserialization error in TApplicationException C# +- [THRIFT-1131](https://issues.apache.org/jira/browse/THRIFT-1131) - C# JSON Protocol is unable to decode escaped characters in string +- [THRIFT-1208](https://issues.apache.org/jira/browse/THRIFT-1208) - python TCompactProtocol.py writeBool and readBool not follow the compact-proto-spec-2.txt spec for CONTAINER_WRITE, CONTAINER_READ +- [THRIFT-1200](https://issues.apache.org/jira/browse/THRIFT-1200) - JS compiler generates code that clobbers existing namespaces +- [THRIFT-1183](https://issues.apache.org/jira/browse/THRIFT-1183) - Pure-ruby CompactProtocol raises ArgumentError when deserializing under Ruby 1.9 +- [THRIFT-1182](https://issues.apache.org/jira/browse/THRIFT-1182) - Native deserializer segfaults on incorrect list element type +- [THRIFT-1181](https://issues.apache.org/jira/browse/THRIFT-1181) - AS3 compiler generates incorrect code for setting default values in constructor +- [THRIFT-1234](https://issues.apache.org/jira/browse/THRIFT-1234) - thrift --help is missing doc on py:utf8strings +- [THRIFT-1180](https://issues.apache.org/jira/browse/THRIFT-1180) - AS3 compiler generates uncompilable code for binary types. +- [THRIFT-1194](https://issues.apache.org/jira/browse/THRIFT-1194) - Java lib does not install artifacts to local dir correctly +- [THRIFT-1193](https://issues.apache.org/jira/browse/THRIFT-1193) - Potential infinite loop in nonblocking_server +- [THRIFT-1192](https://issues.apache.org/jira/browse/THRIFT-1192) - Typo: TProtocol.h tests for HAVE_SYS_PARAM_H_ +- [THRIFT-1190](https://issues.apache.org/jira/browse/THRIFT-1190) - readBufferBytesAllocated in TNonblockingServer.java should be AtomicLong to fix FD leakage and general server malfunction +- [THRIFT-1187](https://issues.apache.org/jira/browse/THRIFT-1187) - nonblocking_server shutdown race under Ruby 1.9 +- [THRIFT-1178](https://issues.apache.org/jira/browse/THRIFT-1178) - Java: TBase signature should be T extends TBase +- [THRIFT-1164](https://issues.apache.org/jira/browse/THRIFT-1164) - Segmentation fault on NULL pointer in t_js_generator::generate_const +- [THRIFT-1171](https://issues.apache.org/jira/browse/THRIFT-1171) - Perl write/readDouble assumes little-endian platform +- [THRIFT-1222](https://issues.apache.org/jira/browse/THRIFT-1222) - Unhandled exception for TEvhttpServer request +- [THRIFT-1220](https://issues.apache.org/jira/browse/THRIFT-1220) - TProcessor::process never returns false +- [THRIFT-1285](https://issues.apache.org/jira/browse/THRIFT-1285) - Stable 0.7.0 Windows compiler exe available on the webside is not the good one +- [THRIFT-1218](https://issues.apache.org/jira/browse/THRIFT-1218) - c_glib uses wrong name in pkg-config +- [THRIFT-1215](https://issues.apache.org/jira/browse/THRIFT-1215) - Undefined property Thirft in lib/js/thrift.js +- [THRIFT-1211](https://issues.apache.org/jira/browse/THRIFT-1211) - When using THttpClient, non 200 responses leave the connection open +- [THRIFT-1228](https://issues.apache.org/jira/browse/THRIFT-1228) - The php accelerator module calls flush incorrectly +- [THRIFT-1308](https://issues.apache.org/jira/browse/THRIFT-1308) - libfb303-0.7.0.jar missing in maven repository +- [THRIFT-1255](https://issues.apache.org/jira/browse/THRIFT-1255) - Mismatch of method name between JavaME's lib and generated code (compareTo/compareObjects) +- [THRIFT-1253](https://issues.apache.org/jira/browse/THRIFT-1253) - Code generated for maps is not compiling +- [THRIFT-1252](https://issues.apache.org/jira/browse/THRIFT-1252) - Segfault in Ruby deserializer +- [THRIFT-1094](https://issues.apache.org/jira/browse/THRIFT-1094) - bug in TCompactProto python readMessageEnd method and updated test cases +- [THRIFT-1093](https://issues.apache.org/jira/browse/THRIFT-1093) - several bugs in python TCompactProtocol +- [THRIFT-1092](https://issues.apache.org/jira/browse/THRIFT-1092) - generated validate() method has wrong indentation +- [THRIFT-1011](https://issues.apache.org/jira/browse/THRIFT-1011) - Error generating package imports when using classes from other packages +- [THRIFT-1050](https://issues.apache.org/jira/browse/THRIFT-1050) - Declaring an argument named "manager" to a service method produces code that fails compile due to name conflicts with protected ivars in TAsyncClient +- [THRIFT-1074](https://issues.apache.org/jira/browse/THRIFT-1074) - .keystore and .truststore are missing from the 0.6.0 distribution +- [THRIFT-1067](https://issues.apache.org/jira/browse/THRIFT-1067) - Tons of bugs in php implementation +- [THRIFT-1065](https://issues.apache.org/jira/browse/THRIFT-1065) - Unexpected exceptions not proper handled on JS +- [THRIFT-1076](https://issues.apache.org/jira/browse/THRIFT-1076) - Erlang Thrift socket server has a bug that causes java thrift client of framed binary client to throw "out of sequence" exception +- [THRIFT-1057](https://issues.apache.org/jira/browse/THRIFT-1057) - casts in TBinaryProtocol.tcc causing "dereferencing type-punned pointer will break strict-aliasing rules" warnings from gcc +- [THRIFT-1055](https://issues.apache.org/jira/browse/THRIFT-1055) - csharp TServerSocket and TSocket do not disable Nagle via Socket.NoDelay = true like cpp and java do +- [THRIFT-1054](https://issues.apache.org/jira/browse/THRIFT-1054) - explicit call to PKG_PROG_PKG_CONFIG is missing and first use of PKG_CHECK_MODULES may not happen, causes mono detection to fail +- [THRIFT-1117](https://issues.apache.org/jira/browse/THRIFT-1117) - JavaScript Unit Test does not work anymore because libthrift*.jar where moved by Maven Deployment +- [THRIFT-1111](https://issues.apache.org/jira/browse/THRIFT-1111) - The HTML generator does not distinguish between string and binary types +- [THRIFT-1032](https://issues.apache.org/jira/browse/THRIFT-1032) - "make dist" fails due to c_glib problem +- [THRIFT-1036](https://issues.apache.org/jira/browse/THRIFT-1036) - Auto-generated C++ code fails to compile with "-Werror -Wextra -Wall" g++ compiler flags +- [THRIFT-1041](https://issues.apache.org/jira/browse/THRIFT-1041) - TDeserializer holds onto a reference of the array it reads after it is done deserializing +- [THRIFT-1106](https://issues.apache.org/jira/browse/THRIFT-1106) - C++ code TAsyncProtocolProcessor.h & TAsyncBufferProcessor.h dont have virtual functions but no virtual destructor. Causes warnings on -Wall +- [THRIFT-1105](https://issues.apache.org/jira/browse/THRIFT-1105) - OCaml generator does not prefix methods of included structs with their type +- [THRIFT-1104](https://issues.apache.org/jira/browse/THRIFT-1104) - INSTALLDIRS should be included in configure script +- [THRIFT-1102](https://issues.apache.org/jira/browse/THRIFT-1102) - typo in configure.ac: "==" operator in 'test' (instead of"'=") +- [THRIFT-1101](https://issues.apache.org/jira/browse/THRIFT-1101) - bytebuffer length calculation in TBinaryProtocol writeBinary +- [THRIFT-1098](https://issues.apache.org/jira/browse/THRIFT-1098) - Undefined properties in TBinaryProtocolFactory +- [THRIFT-1081](https://issues.apache.org/jira/browse/THRIFT-1081) - PHP tests broken and somewhat incomplete +- [THRIFT-1080](https://issues.apache.org/jira/browse/THRIFT-1080) - erlang test's 'make' fails on Mac OSX +- [THRIFT-1078](https://issues.apache.org/jira/browse/THRIFT-1078) - ThriftTest.thrift generates invalid PHP library +- [THRIFT-1120](https://issues.apache.org/jira/browse/THRIFT-1120) - proto.WriteListEnd being called in the wrong place +- [THRIFT-1119](https://issues.apache.org/jira/browse/THRIFT-1119) - TJSONProtocol fails to UTF8 decode strings +- [THRIFT-867](https://issues.apache.org/jira/browse/THRIFT-867) - PHP accelerator module's output transport is incompatible with TFramedTransport +- [THRIFT-826](https://issues.apache.org/jira/browse/THRIFT-826) - PHP TSocket Write Timeout +- [THRIFT-835](https://issues.apache.org/jira/browse/THRIFT-835) - Bad AS3 syntax in constructors that set default values +- [THRIFT-788](https://issues.apache.org/jira/browse/THRIFT-788) - thrift_protocol.so: multiget/multiget_slice does not handle more than 17 keys correctly +- [THRIFT-125](https://issues.apache.org/jira/browse/THRIFT-125) - OCaml libraries don't compile with 32-bit ocaml +- [THRIFT-342](https://issues.apache.org/jira/browse/THRIFT-342) - PHP: can't have sets of complex types +- [THRIFT-731](https://issues.apache.org/jira/browse/THRIFT-731) - configure doesn't check for ant >= 1.7 +- [THRIFT-690](https://issues.apache.org/jira/browse/THRIFT-690) - Update TApplicationException codes +- [THRIFT-638](https://issues.apache.org/jira/browse/THRIFT-638) - BufferedTransport + C extensions block until recv timeout is reached on last fread call + +### Dependency upgrade +- [THRIFT-1177](https://issues.apache.org/jira/browse/THRIFT-1177) - Update thrift to reflect changes in Go's networking libraries + +### Improvement +- [THRIFT-1155](https://issues.apache.org/jira/browse/THRIFT-1155) - Remove log4j dependency from java client +- [THRIFT-1151](https://issues.apache.org/jira/browse/THRIFT-1151) - Produce more informative runtime error in case of schema and data mismatch during serialization +- [THRIFT-1207](https://issues.apache.org/jira/browse/THRIFT-1207) - Support DESTDIR on "make install" of ruby libs +- [THRIFT-1199](https://issues.apache.org/jira/browse/THRIFT-1199) - Union structs should have generated methods to test whether a specific field is currently set +- [THRIFT-1233](https://issues.apache.org/jira/browse/THRIFT-1233) - Remove unused include in generated C++ code +- [THRIFT-1189](https://issues.apache.org/jira/browse/THRIFT-1189) - Ruby deserializer speed improvements +- [THRIFT-1170](https://issues.apache.org/jira/browse/THRIFT-1170) - Thrift Generated Code and Java 5 +- [THRIFT-1174](https://issues.apache.org/jira/browse/THRIFT-1174) - Publish as3 client implementation via Maven for use by flex-mojos users +- [THRIFT-1225](https://issues.apache.org/jira/browse/THRIFT-1225) - TCompactProtocol for PHP +- [THRIFT-1221](https://issues.apache.org/jira/browse/THRIFT-1221) - Remove SimpleCallback.h +- [THRIFT-1217](https://issues.apache.org/jira/browse/THRIFT-1217) - Use evutil_socketpair instead of pipe (Windows port) +- [THRIFT-1216](https://issues.apache.org/jira/browse/THRIFT-1216) - build Java Library behind a proxy +- [THRIFT-1231](https://issues.apache.org/jira/browse/THRIFT-1231) - Remove bogus include +- [THRIFT-1213](https://issues.apache.org/jira/browse/THRIFT-1213) - Membuffer should provide a way to get back the buffer +- [THRIFT-1237](https://issues.apache.org/jira/browse/THRIFT-1237) - Java fb303 missing some methods +- [THRIFT-1063](https://issues.apache.org/jira/browse/THRIFT-1063) - Fix Erlang Tutorial Files +- [THRIFT-1053](https://issues.apache.org/jira/browse/THRIFT-1053) - Make remote client's IP address available for all socket related transports +- [THRIFT-1109](https://issues.apache.org/jira/browse/THRIFT-1109) - Deploy fb303 along side libthrift to maven repo +- [THRIFT-1107](https://issues.apache.org/jira/browse/THRIFT-1107) - improvement for compiler-generated python for 'None' object comparisons +- [THRIFT-1069](https://issues.apache.org/jira/browse/THRIFT-1069) - Add command line option to prevent thrift from inserting gen-* directories +- [THRIFT-1049](https://issues.apache.org/jira/browse/THRIFT-1049) - Allow for TServerSocket python library to bind to a specific host +- [THRIFT-1126](https://issues.apache.org/jira/browse/THRIFT-1126) - Extending struct_info for erlang bindings +- [THRIFT-1100](https://issues.apache.org/jira/browse/THRIFT-1100) - python TSSLSocket improvements, including certificate validation +- [THRIFT-994](https://issues.apache.org/jira/browse/THRIFT-994) - Don't try to invoke phpize if we don't have it +- [THRIFT-993](https://issues.apache.org/jira/browse/THRIFT-993) - Some improvements in C++ stubs for oneway operations +- [THRIFT-997](https://issues.apache.org/jira/browse/THRIFT-997) - Using valueOf for base types in getFieldValue +- [THRIFT-418](https://issues.apache.org/jira/browse/THRIFT-418) - Don't do runtime sorting of struct fields +- [THRIFT-151](https://issues.apache.org/jira/browse/THRIFT-151) - TSSLServerSocket and TSSLSocket implementation +- [THRIFT-27](https://issues.apache.org/jira/browse/THRIFT-27) - Generated erlang types don't contain default values for records +- [THRIFT-113](https://issues.apache.org/jira/browse/THRIFT-113) - to-string methods should omit optional null fields from output +- [THRIFT-363](https://issues.apache.org/jira/browse/THRIFT-363) - Maven Deploy +- [THRIFT-447](https://issues.apache.org/jira/browse/THRIFT-447) - Make an abstract base Client class so we can generate less code +- [THRIFT-627](https://issues.apache.org/jira/browse/THRIFT-627) - should c++ have setters for optional fields? + +### New Feature +- [THRIFT-1236](https://issues.apache.org/jira/browse/THRIFT-1236) - Erlang Reconnecting Thrift Client +- [THRIFT-1021](https://issues.apache.org/jira/browse/THRIFT-1021) - Framed transport support for OCaml +- [THRIFT-1068](https://issues.apache.org/jira/browse/THRIFT-1068) - Python SSL Socket Support +- [THRIFT-1103](https://issues.apache.org/jira/browse/THRIFT-1103) - TZlibTransport for python, a zlib compressed transport +- [THRIFT-1083](https://issues.apache.org/jira/browse/THRIFT-1083) - Preforking python process pool server +- [THRIFT-999](https://issues.apache.org/jira/browse/THRIFT-999) - Add TForkingServer + +### Sub-task +- [THRIFT-1152](https://issues.apache.org/jira/browse/THRIFT-1152) - Attributes from private to protected +- [THRIFT-1038](https://issues.apache.org/jira/browse/THRIFT-1038) - Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable + +### Task +- [THRIFT-892](https://issues.apache.org/jira/browse/THRIFT-892) - Refactor erlang build system with rebar + +### Wish +- [THRIFT-625](https://issues.apache.org/jira/browse/THRIFT-625) - Add support for 'Go' + +## 0.6.1 + +### Bug +- [THRIFT-1133](https://issues.apache.org/jira/browse/THRIFT-1133) - Java and JavaScript tutorial is broken since we have Java maven deployment +- [THRIFT-1131](https://issues.apache.org/jira/browse/THRIFT-1131) - C# JSON Protocol is unable to decode escaped characters in string +- [THRIFT-1074](https://issues.apache.org/jira/browse/THRIFT-1074) - .keystore and .truststore are missing from the 0.6.0 distribution + +### Improvement +- [THRIFT-1109](https://issues.apache.org/jira/browse/THRIFT-1109) - Deploy fb303 along side libthrift to maven repo +- [THRIFT-363](https://issues.apache.org/jira/browse/THRIFT-363) - Maven Deploy + +### Question +- [THRIFT-1206](https://issues.apache.org/jira/browse/THRIFT-1206) - did the THRIFT 0.6.1 merge THRIFT-563 ? + +### Sub-task +- [THRIFT-1163](https://issues.apache.org/jira/browse/THRIFT-1163) - How can i use multi service in one program? + +### Task +- [THRIFT-1112](https://issues.apache.org/jira/browse/THRIFT-1112) - Apply THRIFT-363 to 0.6 branch +- [THRIFT-1113](https://issues.apache.org/jira/browse/THRIFT-1113) - Apply THRIFT-1074 to 0.6 branch + +## 0.6 + +### Bug +- [THRIFT-1020](https://issues.apache.org/jira/browse/THRIFT-1020) - OCaml compiler generates invalid OCaml +- [THRIFT-1015](https://issues.apache.org/jira/browse/THRIFT-1015) - TUnion does not handle ByteBuffer in toString +- [THRIFT-1013](https://issues.apache.org/jira/browse/THRIFT-1013) - generated java code may have name clashes with thrift library +- [THRIFT-1009](https://issues.apache.org/jira/browse/THRIFT-1009) - TUnion does not correctly deep copy a ByteBuffer +- [THRIFT-1032](https://issues.apache.org/jira/browse/THRIFT-1032) - "make dist" fails due to c_glib problem +- [THRIFT-868](https://issues.apache.org/jira/browse/THRIFT-868) - Referencing constant values doesn't work with with typedef types +- [THRIFT-971](https://issues.apache.org/jira/browse/THRIFT-971) - java module can't be compiled without ivy and network connection +- [THRIFT-970](https://issues.apache.org/jira/browse/THRIFT-970) - Under heavy load, THttpClient may fail with "too many open files" +- [THRIFT-969](https://issues.apache.org/jira/browse/THRIFT-969) - Java Tutorial broken, move CalculatorHandler to a separate file +- [THRIFT-807](https://issues.apache.org/jira/browse/THRIFT-807) - JavaScript: Initialization of Base Types with 0 instead of null +- [THRIFT-955](https://issues.apache.org/jira/browse/THRIFT-955) - Thrift compiler for Windows uses lowercase names and directories which is inconsistent with compiling on other platforms +- [THRIFT-992](https://issues.apache.org/jira/browse/THRIFT-992) - Naming convention in C# constructor is not consistent with other fields causes compile errors +- [THRIFT-1008](https://issues.apache.org/jira/browse/THRIFT-1008) - byte[] accessors throw NPE on unset field +- [THRIFT-1006](https://issues.apache.org/jira/browse/THRIFT-1006) - Impossible to correctly qualify an enum constant in an external thrift file +- [THRIFT-950](https://issues.apache.org/jira/browse/THRIFT-950) - Haskell bindings treat 'byte' as unsigned 8-bit int (Data.Word.Word8), java/cpp as signed (byte/int8_t). +- [THRIFT-975](https://issues.apache.org/jira/browse/THRIFT-975) - lib/c_glib/README is missing => breaks make dist +- [THRIFT-944](https://issues.apache.org/jira/browse/THRIFT-944) - Support all version-4s of base +- [THRIFT-939](https://issues.apache.org/jira/browse/THRIFT-939) - optional binary fields throw NPE on default byte[] getters +- [THRIFT-935](https://issues.apache.org/jira/browse/THRIFT-935) - PHP Extension aborts the build if php-config is not installed +- [THRIFT-933](https://issues.apache.org/jira/browse/THRIFT-933) - Haskell's Thrift.cabal has warnings +- [THRIFT-932](https://issues.apache.org/jira/browse/THRIFT-932) - Haskell tests need to be run through 'make check' (and probably 'cabal check') too +- [THRIFT-904](https://issues.apache.org/jira/browse/THRIFT-904) - C# TSocket should disable nagle and linger +- [THRIFT-941](https://issues.apache.org/jira/browse/THRIFT-941) - Make PHP C Extension use the defined Protocol writeMessageBegin function +- [THRIFT-940](https://issues.apache.org/jira/browse/THRIFT-940) - 'make check' fails if boost is not in the std include and link paths +- [THRIFT-924](https://issues.apache.org/jira/browse/THRIFT-924) - Fix generated php structure constants +- [THRIFT-979](https://issues.apache.org/jira/browse/THRIFT-979) - ruby bindings used to work on jruby +- [THRIFT-977](https://issues.apache.org/jira/browse/THRIFT-977) - Hex Conversion Bug in C++ TJSONProtocol +- [THRIFT-347](https://issues.apache.org/jira/browse/THRIFT-347) - PHP TSocket Timeout Issues +- [THRIFT-517](https://issues.apache.org/jira/browse/THRIFT-517) - TExceptions thrown by server result in cryptic error message on client - Tried to read 4 bytes, but only got 0 bytes + +### Improvement +- [THRIFT-1024](https://issues.apache.org/jira/browse/THRIFT-1024) - Add Python Twisted example to the Tutorial +- [THRIFT-958](https://issues.apache.org/jira/browse/THRIFT-958) - Change accessmodifer on trans_ field in the FrameBuffer class to public. +- [THRIFT-957](https://issues.apache.org/jira/browse/THRIFT-957) - THsHaServer: Change access modifier of the invoker field. +- [THRIFT-1002](https://issues.apache.org/jira/browse/THRIFT-1002) - CodeStyle: t_c_glib_generator.cc +- [THRIFT-1005](https://issues.apache.org/jira/browse/THRIFT-1005) - Give unions byte[] signature methods to go along with their ByteBuffer counterparts +- [THRIFT-951](https://issues.apache.org/jira/browse/THRIFT-951) - Add a new isServing() method to TServer +- [THRIFT-943](https://issues.apache.org/jira/browse/THRIFT-943) - Silly readme typo fix. +- [THRIFT-961](https://issues.apache.org/jira/browse/THRIFT-961) - JavaScript TestSuite using ant/ivy and Java's ServerTestBase Handler +- [THRIFT-960](https://issues.apache.org/jira/browse/THRIFT-960) - add TestServer, TestNonblockingServer and TestClient again +- [THRIFT-949](https://issues.apache.org/jira/browse/THRIFT-949) - Modify the TEnum interface so it defines a method similar to findByValue +- [THRIFT-946](https://issues.apache.org/jira/browse/THRIFT-946) - Augment FieldValueMetaData so it differentiates 'string' and 'binary' fields. +- [THRIFT-903](https://issues.apache.org/jira/browse/THRIFT-903) - custom ThreadFactory in THsHaServer +- [THRIFT-913](https://issues.apache.org/jira/browse/THRIFT-913) - Test Case for Url encoded strings + simple enhancement to lib/js/test/RunTestServer.sh +- [THRIFT-926](https://issues.apache.org/jira/browse/THRIFT-926) - Miscellaneous C++ improvements +- [THRIFT-929](https://issues.apache.org/jira/browse/THRIFT-929) - Improvements to the C++ test suite +- [THRIFT-893](https://issues.apache.org/jira/browse/THRIFT-893) - add JavaScript to the tutorial examples +- [THRIFT-1003](https://issues.apache.org/jira/browse/THRIFT-1003) - Polishing c_glib code +- [THRIFT-71](https://issues.apache.org/jira/browse/THRIFT-71) - Debian packaging for thrift + +### New Feature +- [THRIFT-1033](https://issues.apache.org/jira/browse/THRIFT-1033) - Node.js language target +- [THRIFT-947](https://issues.apache.org/jira/browse/THRIFT-947) - Provide a helper method to determine the TProtocol used to serialize some data. +- [THRIFT-928](https://issues.apache.org/jira/browse/THRIFT-928) - Make more statistics available in C++ servers +- [THRIFT-922](https://issues.apache.org/jira/browse/THRIFT-922) - Templatized [de]serialization code for C++ +- [THRIFT-923](https://issues.apache.org/jira/browse/THRIFT-923) - Event-driven client and server support for C++ +- [THRIFT-925](https://issues.apache.org/jira/browse/THRIFT-925) - Provide name<->value map for enums in C++ +- [THRIFT-927](https://issues.apache.org/jira/browse/THRIFT-927) - Add option to modify the PHP include path +- [THRIFT-377](https://issues.apache.org/jira/browse/THRIFT-377) - TFileTransport port in Java +- [THRIFT-106](https://issues.apache.org/jira/browse/THRIFT-106) - TSSLServerSocket +- [THRIFT-582](https://issues.apache.org/jira/browse/THRIFT-582) - C implementation of Thrift +- [THRIFT-745](https://issues.apache.org/jira/browse/THRIFT-745) - Make it easier to instantiate servers + +### Sub-task +- [THRIFT-1038](https://issues.apache.org/jira/browse/THRIFT-1038) - Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable + +### Task +- [THRIFT-862](https://issues.apache.org/jira/browse/THRIFT-862) - Async client issues / improvements + +### Test +- [THRIFT-581](https://issues.apache.org/jira/browse/THRIFT-581) - Add a testsuite for txThrift (Twisted) + +## Incubating Versions + +Thrift 0.5.0 - Incubating +-------------------------------------------------------------------------------- +THRIFT-505 Build Make configure give a summary of the enabled components (David Reiss) +THRIFT-506 Build Allow Thrift to be built without the C++ library (David Reiss) +THRIFT-844 Build Build Requirements state autoconf 2.59+ is required, but 2.60+ is needed (Harlan Lieberman-Berg) +THRIFT-850 Build Perl runtime requires Bit::Vector which may not be installed by default, but configure does not fail (Michael Lum) +THRIFT-854 Build Provide configure option and make rules to build/install php extension (Anthony Molinaro) +THRIFT-858 Build Have bootstrap.sh check for a suitable autoconf version before running (David Reiss) +THRIFT-871 Build Thrift compiler for WIndows (binary distribution) (David Reiss) +THRIFT-323 C# TJSONProtocol (Roger Meier) +THRIFT-634 C# C# Compiler Generates Incorrect Code For Fields which begin with an uppercase letter (Jon S Akhtar) +THRIFT-881 C# add csharp to the tutorial (Roger Meier) +THRIFT-856 C++ Building cpp library fails on OS X with malloc and free not being declared in scope (James Clarke) +THRIFT-865 C++ C++ compiler build depends on libfl even when flex/lex not detected (David Reiss) +THRIFT-900 C++ Unix domain socket (Roger Meier) +THRIFT-920 C++ C++ Test and Tutorial does not compile anymore due to the change within Enum handling (Roger Meier) +THRIFT-567 C++ Can't immediately stop a TSimpleServer thread that is idle (Rush Manbert) +THRIFT-756 C++ Exposing TSocket(int) constructor to public (Rajat Goel) +THRIFT-798 C++ TNonblockingServer leaks resources when destroyed (David Reiss) +THRIFT-812 C++, Python Demo of Thrift over ZeroMQ (David Reiss) +THRIFT-629 Cocoa Unused Field In TSocketServer Appears To Break iPhone Build (Jon S Akhtar) +THRIFT-838 Cocoa Generated Cocoa classes have useless @dynamic declarations (Kevin Ballard) +THRIFT-805 Cocoa Don't generate process_XXXX methods for oneway methods (Brad Taylor) +THRIFT-507 Compiler Remove the compiler's dependency on Boost (David Reiss) +THRIFT-895 Compiler (General) Thrift compiler does not allow two different enumerations to have the same key name for one of the enum values (David Reiss) +THRIFT-852 Compiler (General) Missing newline causes many compiler warnings (Anthony Molinaro) +THRIFT-877 Compiler (General) smalltalk namespace doesn't work (Bruce Lowekamp) +THRIFT-897 Compiler (General) Don't allow unqualified constant access to enum values (Bryan Duxbury) +THRIFT-9 Compiler (General) Add a default namespace declaration for all languages (David Reiss) +THRIFT-599 Erlang Don't use unnecessary processes in the Erlang transports and clients (David Reiss) +THRIFT-646 Erlang Erlang library is missing install target (David Reiss) +THRIFT-698 Erlang Generated module list should contain atoms, not strings (Anthony Molinaro) +THRIFT-866 Erlang term() in spec definitions seems to not work in erlang R12 (Anthony Molinaro) +THRIFT-886 Erlang Dialyzer warning (Anthony Molinaro) +THRIFT-785 Erlang Framed transport server problems (Anthony Molinaro) +THRIFT-884 HTML HTML Generator: add Key attribute to the Data Types Tables (Roger Meier) +THRIFT-652 Haskell Generated field name for strut is not capitalized correctly (Christian Lavoie) +THRIFT-743 Haskell compile error with GHC 6.12.1 (Christian Lavoie) +THRIFT-901 Haskell Allow the bindings to compile without -fglasgow-exts and with -Wall -Werror (Christian Lavoie) +THRIFT-905 Haskell Make haskell thrift bindings use automake to compile and install (Christian Lavoie) +THRIFT-906 Haskell Improve type mappings (Christian Lavoie) +THRIFT-914 Haskell Make haskell bindings 'easily' compilable (Christian Lavoie) +THRIFT-918 Haskell Make haskell tests run again (Christian Lavoie) +THRIFT-919 Haskell Update Haskell bindings README (Christian Lavoie) +THRIFT-787 Haskell Enums are not read correctly (Christian Lavoie) +THRIFT-250 Java ExecutorService as a constructor parameter for TServer (Ed Ceaser) +THRIFT-693 Java Thrift compiler generated java code that throws compiler warnings about deprecated methods. (Bryan Duxbury) +THRIFT-843 Java TNonblockingSocket connects without a timeout (Bryan Duxbury) +THRIFT-845 Java async client does not respect timeout (Ning Liang) +THRIFT-870 Java Java constants don't get Javadoc comments (Bryan Duxbury) +THRIFT-873 Java Java tests fail due to Too many open files (Todd Lipcon) +THRIFT-876 Java Add SASL support (Aaron T. Myers) +THRIFT-879 Java Remove @Override from TUnion.clear (Dave Engberg) +THRIFT-882 Java deep copy of binary fields does not copy ByteBuffer characteristics (arrayOffset, position) (Bryan Duxbury) +THRIFT-888 Java async client should also have nonblocking connect (Eric Jensen) +THRIFT-890 Java Java tutorial doesn't work (Todd Lipcon) +THRIFT-894 Java Make default accessors for binary fields return byte[]; provide new accessors to get ByteBuffer version (Bryan Duxbury) +THRIFT-896 Java TNonblockingSocket.isOpen() returns true even after close() (Eric Jensen) +THRIFT-907 Java libfb303 doesn't compile in 0.4.0 (Todd Lipcon) +THRIFT-912 Java Improvements and bug fixes to SASL implementation (Todd Lipcon) +THRIFT-917 Java THsHaServer should not accept an ExecutorService without catching RejectedExecutionException (Ed Ceaser) +THRIFT-931 Java Use log4j for Java tests (Todd Lipcon) +THRIFT-880 JavaME JavaME code generator and runtime library (Dave Engberg) +THRIFT-846 JavaScript JavaScript Test Framwork: extended Testcases (Roger Meier) +THRIFT-885 JavaScript Url encoded strings never get decoded? How do we fix this? (T Jake Luciani) +THRIFT-911 JavaScript (JavaScript compiler) Const structs, maps, sets, and lists generate a trailing comma (T Jake Luciani) +THRIFT-860 OCaml copy method and reset method (Lev Walkin) +THRIFT-682 PHP PHP extension doesn't compile on Mac OS X (Bryan Duxbury) +THRIFT-851 PHP php extension fails to compile on centos 5.x (Todd Lipcon) +THRIFT-840 Perl Perl protocol handler could be more robust against unrecognised types (Conrad Hughes) +THRIFT-758 Perl incorrect deference in exception handling (Yann Kerherve) +THRIFT-257 Python Support validation of required fields (Esteve Fernandez) +THRIFT-335 Python Compact Protocol for Python (David Reiss) +THRIFT-596 Python Make Python's TBufferedTransport use a configurable input buffer (David Reiss) +THRIFT-597 Python Python THttpServer performance improvements (David Reiss) +THRIFT-598 Python Allow Python's threading servers to use daemon threads (David Reiss) +THRIFT-666 Python Allow the handler to override HTTP responses in THttpServer (David Reiss) +THRIFT-673 Python Generated Python code has whitespace issues (Ian Eure) +THRIFT-721 Python THttpClient ignores url parameters (Thomas Kho) +THRIFT-824 Python TApplicationException.__str__() refers to class constants as globals (Peter Schuller) +THRIFT-855 Python Include optimized compiled python objects in install (Anthony Molinaro) +THRIFT-859 Python Allow py:twisted to be generated in different namespace than py (Bruce Lowekamp) +THRIFT-869 Python TSocket.py on Mac (and FreeBSD) doesn't handle ECONNRESET from recv() (Steven Knight) +THRIFT-875 Python Include python setup.cfg in dist (Anthony Molinaro) +THRIFT-610 Ruby binary_protocol.rb segfaults [line 86] (Unassigned) +THRIFT-899 Ruby Ruby read timeouts can sometimes be 2x what they should be (Ryan King) +THRIFT-909 Ruby allow block argument to struct constructor (Michael Stockton) +THRIFT-456 Test Suite Bad IP address string in test/cpp/src/main.cpp (Rush Manbert) + + +Thrift 0.4.0 - Incubating +-------------------------------------------------------------------------------- +THRIFT-650 Build Make Check fails on Centos/OSX with 0.2.0 tarball (Anthony Molinaro) +THRIFT-770 Build Get 'make dist' to work without first compiling source code (Anthony Molinaro) +THRIFT-160 C# Created THttpTransport for the C# library based on WebHttpRequest (Michael Greene) +THRIFT-834 C# THttpClient resends contents of message after transport errors (Anatoly Fayngelerin) +THRIFT-247 C++ THttpServer Transport (Unassigned) +THRIFT-676 C++ Change C++ code generator so that generated classes can be wrapped with SWIG (Unassigned) +THRIFT-570 Compiler Thrift compiler does not error when duplicate method names are present (Bruce Simpson) +THRIFT-808 Compiler Segfault when constant declaration references a struct field that doesn't exist (Bryan Duxbury) +THRIFT-646 Erlang Erlang library is missing install target (Anthony Molinaro) +THRIFT-544 General multiple enums with the same key generate invalid code (Ben Taitelbaum) +THRIFT-434 General ruby compiler should warn when a reserved word is used (Michael Stockton) +THRIFT-799 General Files missing proper Apache license header (Bryan Duxbury) +THRIFT-832 HTML HTML generator shows unspecified struct fields as 'required' (Bryan Duxbury) +THRIFT-226 Java Collections with binary keys or values break equals() (Bryan Duxbury) +THRIFT-484 Java Ability to use a slice of a buffer instead of a direct byte[] for binary fields (Bryan Duxbury) +THRIFT-714 Java maxWorkerThreads parameter to THsHaServer has no effect (Bryan Duxbury) +THRIFT-751 Java Add clear() method to TBase (Bryan Duxbury) +THRIFT-765 Java Improved string encoding and decoding performance (Bryan Duxbury) +THRIFT-768 Java Async client for Java (Bryan Duxbury) +THRIFT-774 Java TDeserializer should provide a partialDeserialize method for primitive types (Piotr Kozikowski) +THRIFT-783 Java .equals java method is broken on structs containing binary-type fields (Unassigned) +THRIFT-804 Java CompareTo is broken for unions set to map, set, or list (Bryan Duxbury) +THRIFT-814 Java Include a TServlet in the standard Thrift distribution (Mathias Herberts) +THRIFT-818 Java Async client doesn't send method args (Bryan Duxbury) +THRIFT-830 Java Switch binary field implementation from byte[] to ByteBuffer (Bryan Duxbury) +THRIFT-831 Java FramedTransport implementation that reuses its buffers (Bryan Duxbury) +THRIFT-833 Java build.xml in lib/java is missing a classpathref attribute for the javadoc task (Bryan Duxbury) +THRIFT-836 Java Race condition causes CancelledKeyException in TAsyncClientManager (Bryan Duxbury) +THRIFT-842 Java Upgrade to current version of commons-lang (2.5 instead of 2.4) and/or change dependency in ivy.xml to not be exact (Bryan Duxbury) +THRIFT-815 JavaScript Deserialization of lists is critically broken. (T Jake Luciani) +THRIFT-827 OCaml OCaml generator to take default values into account (Lev Walkin) +THRIFT-647 PHP PHP library is missing install target (Anthony Molinaro) +THRIFT-682 PHP PHP extension doesn't compile on Mac OS X (Bryan Duxbury) +THRIFT-718 PHP Thrift PHP library includes closing tags and extraneous whitespace (Nicholas Telford) +THRIFT-778 PHP PHP socket listening server (Nick Jones) +THRIFT-780 PHP PHP extension sometimes causes an abort with two exceptions at the same time (David Reiss) +THRIFT-837 PHP PHP accelerator bug for writes > 8k (Thomas Kho) +THRIFT-782 Perl Perl code for writing containers doesn't count length of write*Begin or write*End (Conrad Hughes) +THRIFT-395 Python Python library + compiler does not support unicode strings (Unassigned) +THRIFT-133 Ruby 'namespace ruby' should error out, or be an alias to 'namespace rb' (Bryan Duxbury) +THRIFT-664 Ruby Ruby extension fails to build with Ruby 1.9.1 (Rajesh Malepati) +THRIFT-699 Ruby Excise unused "native protocol method table" stuff from thrift_native (Bryan Duxbury) +THRIFT-767 Ruby ruby compiler does not keep comments for enum values (Bryan Duxbury) +THRIFT-811 Ruby http_client_transport.rb: allow custom http headers (Tony Kamenick) +THRIFT-459 Ruby Ruby installation always tries to write to /Library/Ruby/site (Matthieu Imbert) + + +Thrift 0.1.0 - Incubating (not released) +-------------------------------------------------------------------------------- +Compatibility Breaking Changes: + C++: +- It's quite possible that regenerating code and rebuilding will be + required. Make sure your headers match your libs! + + Java: + + Python: + + Ruby: +- Generated files now have underscored names [THRIFT-421] +- The library has been rearranged to be more Ruby-like [THRIFT-276] + + Erlang: +- Generated code will have to be regenerated, and the new code will + have to be deployed atomically with the new library code [THRIFT-136] + +New Features and Bug Fixes: + C++: +- Support for TCompactProtocol [THRIFT-333] + + Java: +- Support for TCompactProtocol [THRIFT-110] + + Python: +- Support for Twisted [THRIFT-148] + + Ruby: +- Support for TCompactProtocol [THRIFT-332] + diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f57a66c4d5..e6dd5638bf1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,33 +17,25 @@ # under the License. # -cmake_minimum_required(VERSION 3.1) +cmake_minimum_required(VERSION 3.3) -# CMake 3.1 supports C++ standards selection with CMAKE_CXX_STANDARD -# If you need CMake 3.1+ for Ubuntu 14.04, try -# https://launchpad.net/~george-edison55/+archive/ubuntu/cmake-3.x -# If you need CMake 3.1+ for debian "jessie", get it from jessie-backports -# Otherwise -# http://cmake.org - -project("Apache Thrift") +if(POLICY CMP0048) + cmake_policy(SET CMP0048 NEW) # package version behavior added in cmake 3.0 +endif() +if(POLICY CMP0074) + cmake_policy(SET CMP0074 NEW) # find_package behavior added in cmake 3.12 +endif() -set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake") +# PACKAGE_VERSION is used by cpack scripts currently +# Both thrift_VERSION and PACKAGE_VERSION should be the same for now +set(thrift_VERSION "1.0.0") +set(PACKAGE_VERSION ${thrift_VERSION}) -# TODO: add `git rev-parse --short HEAD` -# Read the version information from the Autoconf file -file (STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGURE_AC REGEX "AC_INIT\\(.*\\)" ) +project("thrift" VERSION ${PACKAGE_VERSION}) +message(STATUS "Configuring ${CMAKE_PROJECT_NAME} ${thrift_VERSION}") -# The following variable is used in the version.h.in file -string(REGEX REPLACE "AC_INIT\\(\\[.*\\], \\[([0-9]+\\.[0-9]+\\.[0-9]+(-dev)?)\\]\\)" "\\1" PACKAGE_VERSION ${CONFIGURE_AC}) -message(STATUS "Parsed Thrift package version: ${PACKAGE_VERSION}") -# These are internal to CMake -string(REGEX REPLACE "([0-9]+\\.[0-9]+\\.[0-9]+)(-dev)?" "\\1" thrift_VERSION ${PACKAGE_VERSION}) -string(REGEX REPLACE "([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" thrift_VERSION_MAJOR ${thrift_VERSION}) -string(REGEX REPLACE "[0-9]+\\.([0-9])+\\.[0-9]+" "\\1" thrift_VERSION_MINOR ${thrift_VERSION}) -string(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" thrift_VERSION_PATCH ${thrift_VERSION}) -message(STATUS "Parsed Thrift version: ${thrift_VERSION} (${thrift_VERSION_MAJOR}.${thrift_VERSION_MINOR}.${thrift_VERSION_PATCH})") +set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/build/cmake") # Some default settings include(DefineCMakeDefaults) @@ -58,13 +50,14 @@ include(DefinePlatformSpecifc) # Generate the config.h file include(ConfigureChecks) -# Package it +# Packaging include(CPackConfig) - +# Dependencies +include(BoostMacros) find_package(Threads) - include(CTest) + if(BUILD_TESTING) message(STATUS "Building with unittests") diff --git a/LANGUAGES.md b/LANGUAGES.md index 24a3cf5cebc..5c3290990f2 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -59,7 +59,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u C++ 0.2.0 YesYes -C++98 +C++98 (through 0.12.0)C++11 (after 0.12.0) YesYesYesYesYesYes YesYesYes YesYesYesYes diff --git a/Makefile.am b/Makefile.am index 511452dfc85..addfa0cfbe6 100755 --- a/Makefile.am +++ b/Makefile.am @@ -129,7 +129,7 @@ EXTRA_DIST = \ sonar-project.properties \ LANGUAGES.md \ LICENSE \ - CHANGES \ + CHANGES.md \ NOTICE \ README.md \ Thrift.podspec diff --git a/appveyor.yml b/appveyor.yml index e021479e102..ab6f582ea61 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -36,17 +36,17 @@ environment: - PROFILE: MSVC2017 PLATFORM: x64 CONFIGURATION: Release - BOOST_VERSION: 1.65.1 + BOOST_VERSION: 1.67.0 LIBEVENT_VERSION: 2.1.8 PYTHON_VERSION: 3.6 QT_VERSION: 5.10 ZLIB_VERSION: 1.2.11 DISABLED_TESTS: StressTestNonBlocking - - PROFILE: MSVC2013 + - PROFILE: MSVC2015 PLATFORM: x86 CONFIGURATION: Release - BOOST_VERSION: 1.58.0 + BOOST_VERSION: 1.62.0 LIBEVENT_VERSION: 2.0.22 PYTHON_VERSION: 3.5 QT_VERSION: 5.8 @@ -102,8 +102,8 @@ test_script: # # enables RDP at the end of the build job so you can login and re-run # commands to see why something failed... -#on_finish: -# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) +# on_finish: +# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) # # also need: # environment: diff --git a/build/appveyor/MSVC-appveyor-build.bat b/build/appveyor/MSVC-appveyor-build.bat index a4b92a29cd2..0b7f0ef23c0 100644 --- a/build/appveyor/MSVC-appveyor-build.bat +++ b/build/appveyor/MSVC-appveyor-build.bat @@ -21,6 +21,21 @@ CALL cl_setenv.bat || EXIT /B MKDIR "%BUILDDIR%" || EXIT /B CD "%BUILDDIR%" || EXIT /B +:: When libraries cannot be found, things might have been updated +:: so uncomment this and submit a pull request to see what's there +:: now... +:: DIR C:\Libraries +:: DIR C:\Libraries\boost_1_69_0\lib* +:: DIR C:\Libraries\boost_1_68_0\lib* +:: DIR C:\Libraries\boost_1_67_0\lib* +:: DIR C:\Libraries\boost_1_66_0\lib* +:: DIR C:\Libraries\boost_1_65_0\lib* +:: DIR C:\Libraries\boost_1_64_0\lib* +:: DIR C:\Libraries\boost_1_63_0\lib* +:: DIR C:\Libraries\boost_1_62_0\lib* +:: DIR C:\Libraries\boost_1_61_0\lib* +:: DIR C:\Libraries\boost_1_60_0\lib* + @ECHO ON cmake "%SRCDIR%" ^ -G"%GENERATOR%" ^ diff --git a/build/cmake/BoostMacros.cmake b/build/cmake/BoostMacros.cmake new file mode 100644 index 00000000000..0c7f13dfaf1 --- /dev/null +++ b/build/cmake/BoostMacros.cmake @@ -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. +# + +set(BOOST_MINREV 1.53) + +macro(REQUIRE_BOOST_HEADERS) + find_package(Boost ${BOOST_MINREV} QUIET REQUIRED) + if (NOT Boost_FOUND) + string(CONCAT fatal_message + "Boost 1.53 or later is required to build sources in ${CMAKE_CURRENT_SOURCE_DIR}") + message(FATAL_ERROR, ${fatal_message}) + endif() + include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") +endmacro() + +macro(REQUIRE_BOOST_LIBRARIES libs) + message(STATUS "Locating boost libraries required by sources in ${CMAKE_CURRENT_SOURCE_DIR}") + find_package(Boost ${BOOST_MINREV} REQUIRED COMPONENTS ${${libs}}) + if (NOT Boost_FOUND) + string(CONCAT fatal_message + "Boost 1.53 or later is required to build sources in ${CMAKE_CURRENT_SOURCE_DIR}, " + "or use -DBUILD_TESTING=OFF") + message(FATAL_ERROR, ${fatal_message}) + endif() +endmacro() diff --git a/build/cmake/DefineCMakeDefaults.cmake b/build/cmake/DefineCMakeDefaults.cmake index 93255e05cdb..7ae21362da1 100644 --- a/build/cmake/DefineCMakeDefaults.cmake +++ b/build/cmake/DefineCMakeDefaults.cmake @@ -34,10 +34,6 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) # since cmake 2.4.0 set(CMAKE_COLOR_MAKEFILE ON) -# Define the generic version of the libraries here -set(GENERIC_LIB_VERSION "1.0.0") -set(GENERIC_LIB_SOVERSION "0") - # Set the default build type to release with debug info if (NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 9aff53c16bb..207b770c71c 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -50,7 +50,6 @@ endif() # C++ option(WITH_CPP "Build C++ Thrift library" ON) if(WITH_CPP) - find_package(Boost 1.53 QUIET) # NOTE: Currently the following options are C++ specific, # but in future other libraries might reuse them. # So they are not dependent on WITH_CPP but setting them without WITH_CPP currently @@ -78,10 +77,11 @@ if(WITH_CPP) find_package(OpenSSL QUIET) CMAKE_DEPENDENT_OPTION(WITH_OPENSSL "Build with OpenSSL support" ON "OPENSSL_FOUND" OFF) + # if disabled, builds with posix thread class - deprecated and will be removed... option(WITH_STDTHREADS "Build with C++ std::thread support" ON) endif() CMAKE_DEPENDENT_OPTION(BUILD_CPP "Build C++ library" ON - "BUILD_LIBRARIES;WITH_CPP;Boost_FOUND" OFF) + "BUILD_LIBRARIES;WITH_CPP" OFF) CMAKE_DEPENDENT_OPTION(WITH_PLUGIN "Build compiler plugin support" OFF "BUILD_COMPILER;BUILD_CPP" OFF) @@ -93,20 +93,9 @@ endif() CMAKE_DEPENDENT_OPTION(BUILD_C_GLIB "Build C (GLib) library" ON "BUILD_LIBRARIES;WITH_C_GLIB;GLIB_FOUND" OFF) -if(BUILD_CPP) - set(boost_components) - if(BUILD_TESTING) - list(APPEND boost_components system thread) - endif() - if(BUILD_TESTING) - list(APPEND boost_components unit_test_framework filesystem chrono program_options) - endif() - if(boost_components) - find_package(Boost 1.53 REQUIRED COMPONENTS ${boost_components}) - endif() -elseif(BUILD_C_GLIB AND BUILD_TESTING) - find_package(Boost 1.53 REQUIRED) -endif() + #if(BUILD_C_GLIB AND BUILD_TESTING) + # find_package(Boost 1.53 REQUIRED) + #endif() # Java option(WITH_JAVA "Build Java Thrift library" ON) @@ -170,7 +159,6 @@ message(STATUS " Build Thrift libraries: ${BUILD_LIBRARIES} message(STATUS " Language libraries:") message(STATUS " Build C++ library: ${BUILD_CPP}") MESSAGE_DEP(WITH_CPP "Disabled by WITH_CPP=OFF") -MESSAGE_DEP(Boost_FOUND "Boost headers missing") message(STATUS " C++ Language Level: ${CXX_LANGUAGE_LEVEL}") message(STATUS " Build C (GLib) library: ${BUILD_C_GLIB}") MESSAGE_DEP(WITH_C_GLIB "Disabled by WITH_C_GLIB=OFF") diff --git a/build/docker/scripts/cmake.sh b/build/docker/scripts/cmake.sh index ccc311e44c0..eb384d55224 100755 --- a/build/docker/scripts/cmake.sh +++ b/build/docker/scripts/cmake.sh @@ -19,5 +19,4 @@ for LIB in $BUILD_LIBS; do done $MAKEPROG -j3 cpack -ctest -VV -E "(python_test)" -# disabled cmake python_test for now since it fails in travis under centos +ctest -VV diff --git a/build/veralign.sh b/build/veralign.sh index 61744b43261..491ef36b546 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -49,11 +49,11 @@ FILES[doap.rdf]=manual # These files can be updated automatically: FILES[ApacheThrift.nuspec]=simpleReplace +FILES[CMakeLists.txt]=simpleReplace FILES[Thrift-swift3.podspec]=simpleReplace FILES[Thrift.podspec]=simpleReplace FILES[appveyor.yml]=simpleReplace FILES[bower.json]=jsonReplace -FILES[build/cmake/DefineCMakeDefaults.cmake]=simpleReplace FILES[configure.ac]=configureReplace FILES[contrib/thrift.spec]=simpleReplace FILES[lib/cocoa/src/Thrift.h]=simpleReplace @@ -100,7 +100,7 @@ FILES[tutorial/delphi/DelphiServer/DelphiServer.dproj]=simpleReplace FILES[tutorial/hs/ThriftTutorial.cabal]=simpleReplace FILES[tutorial/ocaml/_oasis]=simpleReplace -if [ ! -f "CHANGES" ]; then +if [ ! -f "CHANGES.md" ]; then >&2 echo "error: run veralign.sh while in the thrift root directory" exit 1 fi diff --git a/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc b/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc index be3bad16128..306086397fb 100644 --- a/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc @@ -4507,23 +4507,21 @@ string t_c_glib_generator::generate_new_array_from_type(t_type* ttype) { ***************************************/ /** - * Upper case a string. Wraps boost's string utility. + * Upper case a string. */ string to_upper_case(string name) { string s(name); std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s; - // return boost::to_upper_copy (name); } /** - * Lower case a string. Wraps boost's string utility. + * Lower case a string. */ string to_lower_case(string name) { string s(name); std::transform(s.begin(), s.end(), s.begin(), ::tolower); return s; - // return boost::to_lower_copy (name); } /** diff --git a/compiler/cpp/src/thrift/generate/t_cl_generator.cc b/compiler/cpp/src/thrift/generate/t_cl_generator.cc index 628d0d8d785..38807f45a1a 100644 --- a/compiler/cpp/src/thrift/generate/t_cl_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cl_generator.cc @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -35,6 +34,7 @@ #include "thrift/platform.h" #include "t_oop_generator.h" + using namespace std; diff --git a/compiler/cpp/src/thrift/windows/config.h b/compiler/cpp/src/thrift/windows/config.h index d2269cf7814..6ba4f9ae6c1 100644 --- a/compiler/cpp/src/thrift/windows/config.h +++ b/compiler/cpp/src/thrift/windows/config.h @@ -46,25 +46,6 @@ // squelch bool conversion performance warning #pragma warning(disable : 4800) -// MSVC10 (2010) or later has stdint.h -#if _MSC_VER >= 1600 -#define HAVE_STDINT_H 1 -#endif - -// Must be using VS2010 or later, or boost, so that C99 types are defined in the global namespace -#ifdef HAVE_STDINT_H -#include -#else -#include - -typedef boost::int64_t int64_t; -typedef boost::uint64_t uint64_t; -typedef boost::int32_t int32_t; -typedef boost::uint32_t uint32_t; -typedef boost::int16_t int16_t; -typedef boost::uint16_t uint16_t; -typedef boost::int8_t int8_t; -typedef boost::uint8_t uint8_t; -#endif +#include #endif // _THRIFT_WINDOWS_CONFIG_H_ diff --git a/compiler/cpp/test/CMakeLists.txt b/compiler/cpp/test/CMakeLists.txt index a09f23d7c24..572b55890d4 100644 --- a/compiler/cpp/test/CMakeLists.txt +++ b/compiler/cpp/test/CMakeLists.txt @@ -17,10 +17,13 @@ # under the License. # +# Unit tests for the compiler still require boost +include(BoostMacros) +REQUIRE_BOOST_HEADERS() +set(BOOST_COMPONENTS unit_test_framework) +REQUIRE_BOOST_LIBRARIES(BOOST_COMPONENTS) if(${WITH_PLUGIN}) - include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") - # Make sure gen-cpp files can be included include_directories("${CMAKE_CURRENT_BINARY_DIR}") diff --git a/lib/c_glib/test/CMakeLists.txt b/lib/c_glib/test/CMakeLists.txt index fb3e41cecf4..318b5762985 100644 --- a/lib/c_glib/test/CMakeLists.txt +++ b/lib/c_glib/test/CMakeLists.txt @@ -20,7 +20,7 @@ set(TEST_PREFIX "c_glib") -include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) +# include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) #Make sure gen-cpp and gen-c_glib files can be included include_directories("${CMAKE_CURRENT_BINARY_DIR}") diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index 9ea82c3dffc..9e36665bd4c 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -17,7 +17,10 @@ # under the License. # -include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") +# Remove the following once lib/cpp no longer depends on boost headers: +include(BoostMacros) +REQUIRE_BOOST_HEADERS() + include_directories(src) # SYSLIBS contains libraries that need to be linked to all lib targets diff --git a/lib/cpp/README.md b/lib/cpp/README.md index e744a6a4621..5806f7b4a56 100755 --- a/lib/cpp/README.md +++ b/lib/cpp/README.md @@ -33,8 +33,8 @@ In case you do not want to open another README.md file, do this thrift src: Thrift is divided into two libraries. -* libthrift - The core Thrift library contains all the core Thrift code. It requires - boost shared pointers, pthreads, and librt. +* libthrift - The core Thrift library contains all the core Thrift code. This requires + openssl, pthreads, and librt. * libthriftnb - This library contains the Thrift nonblocking server, which uses libevent. To link this library you will also need to link libevent. @@ -54,14 +54,12 @@ you are using libthriftnb you will also need libevent. ## Dependencies -If your C++ environment implements C++11 or later, thrift will automatically use -std::shared_ptr. Otherwise you will need the boost library to provide a shared_ptr -implementation for C++ environments pre-C++11. If you are linking against code -that expects to be using boost::shared_ptr, you can define the preprocessor -variable FORCE_BOOST_SMART_PTR for your build of thrift to make it use boost instead -of std for a number of memory related classes. See thrift/stdcxx.h for more. +C++11 is required at a minimum. C++03/C++98 are not supported after version 0.12.0. -libevent (for libthriftnb only) +Boost is required to run the C++ unit tests. It is not necessary to link against +the runtime library. + +libevent (for libthriftnb only) - most linux distributions have dev packages for this: http://monkey.org/~provos/libevent/ # Using Thrift with C++ on Windows @@ -85,35 +83,17 @@ The same linking guidelines described above for libthriftnb apply to windows as ## Linking Against Thrift You need to link your project that uses thrift against all the thrift -dependencies; in the case of libthrift, boost and for +dependencies; in the case of libthrift, openssl, pthreads, and librt and for libthriftnb, libevent. In the project properties you must also set HAVE_CONFIG_H as force include -the config header: "windows/confg.h" +the config header: "windows/config.h" ## Dependencies -The same dependencies for shared_ptr as described above apply to windows as well. - -boost thread -http://www.boost.org/doc/libs/release/doc/html/thread.html - libevent (for libthriftnb only) http://monkey.org/~provos/libevent/ -## Notes on boost thread (static vs shared): - -By default lib/cpp/windows/force_inc.h defines: - - #define BOOST_ALL_NO_LIB 1 - #define BOOST_THREAD_NO_LIB 1 - -This has for effect to have the host application linking against Thrift -to have to link with boost thread as a static library. - -If you wanted instead to link with boost thread as a shared library, -you'll need to uncomment those two lines, and recompile. - ## Windows version compatibility The Thrift library targets Windows XP for broadest compatbility. A notable @@ -122,6 +102,8 @@ function. To target Vista, Win7 or other versions, comment out the line #define TARGET_WIN_XP. +See Apache Jira THRIFT-2798 for more about TARGET_WIN_XP. + ## Named Pipes Named Pipe transport has been added in the TPipe and TPipeServer classes. This @@ -138,50 +120,16 @@ TSimpleServer, TThreadedServer, and TThreadPoolServer. ## Implementation -There're two main classes TSSLSocketFactory and TSSLSocket. Instances of +There are two main classes TSSLSocketFactory and TSSLSocket. Instances of TSSLSocket are always created from TSSLSocketFactory. -PosixSSLThreadFactory creates PosixSSLThread. The only difference from the -PthreadThread type is that it cleanups OpenSSL error queue upon exiting -the thread. Ideally, OpenSSL APIs should only be called from PosixSSLThread. - ## How to use SSL APIs -This is for demo. In real code, typically only one TSSLSocketFactory -instance is needed. - - shared_ptr getSSLSocketFactory() { - shared_ptr factory(new TSSLSocketFactory()); - // client: load trusted certificates - factory->loadTrustedCertificates("my-trusted-ca-certificates.pem"); - // client: optionally set your own access manager, otherwise, - // the default client access manager will be loaded. +See the TestClient.cpp and TestServer.cpp files for examples. - factory->loadCertificate("my-certificate-signed-by-ca.pem"); - factory->loadPrivateKey("my-private-key.pem"); - // server: optionally setup access manager - // shared_ptr accessManager(new MyAccessManager); - // factory->access(accessManager); - ... - } +### AccessManager (certificate validation) - -client code sample - - shared_ptr factory = getSSLSocketFactory(); - shared_ptr socket = factory.createSocket(host, port); - shared_ptr transport(new TBufferedTransport(socket)); - ... - - -server code sample - - shared_ptr factory = getSSLSocketFactory(); - shared_ptr socket(new TSSLServerSocket(port, factory)); - shared_ptr transportFactory(new TBufferedTransportFactory)); - ... - -## AccessManager +An example of certificate validation can be found in TestServer.cpp. AccessManager defines a callback interface. It has three callback methods: @@ -272,8 +220,29 @@ OpenSSL's RAND_poll() when OpenSSL library is first initialized. The PRNG seed is key to the application security. This method should be overridden if it's not strong enough for you. +# Deprecations + +## 0.12.0 + +Support for C++03/C++98 was deprecated. +Support for Boost at runtime was deprecated. + # Breaking Changes +## 1.0.0 + +Support for C++03/C++98 has been dropped. Use version 0.12.0 to support that +language level. As a consequence, boost is no longer required as a runtime +library depenedency, but is is still required to build the runtime library +and to run the unit tests. We will work towards removing boost as a +build dependency for folks who just want to build the runtime and not +run the tests. This means the header thrift/stdcxx.h has been removed and +anything that relied on it has been changed to directly use C++11 concepts. + +The classes BoostThreadFactory, PosixThreadFactory, StdThreadFactory, and +PlatformThreadFactory will all be removed, and we will use a ThreadFactory +based on C++11. + ## 0.11.0 Older versions of thrift depended on the classes which diff --git a/lib/cpp/test/CMakeLists.txt b/lib/cpp/test/CMakeLists.txt index 82d47a6b6e8..b30ef1780b9 100644 --- a/lib/cpp/test/CMakeLists.txt +++ b/lib/cpp/test/CMakeLists.txt @@ -17,11 +17,13 @@ # under the License. # -include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") +# Unit tests still require boost +include(BoostMacros) +REQUIRE_BOOST_HEADERS() +set(BOOST_COMPONENTS chrono date_time filesystem random thread unit_test_framework) +REQUIRE_BOOST_LIBRARIES(BOOST_COMPONENTS) -if (WITH_DYN_LINK_TEST) - add_definitions( -DBOOST_TEST_DYN_LINK ) -endif() +include(ThriftMacros) # Make sure gen-cpp files can be included include_directories("${CMAKE_CURRENT_BINARY_DIR}") diff --git a/test/cpp/CMakeLists.txt b/test/cpp/CMakeLists.txt index 95d2991f8b8..0c0bd2f5758 100755 --- a/test/cpp/CMakeLists.txt +++ b/test/cpp/CMakeLists.txt @@ -17,11 +17,15 @@ # under the License. # +# The test executables still depend on Boost +include(BoostMacros) +REQUIRE_BOOST_HEADERS() +set(BOOST_COMPONENTS filesystem program_options random) +REQUIRE_BOOST_LIBRARIES(BOOST_COMPONENTS) + # Contains the thrift specific LINK_AGAINST_THRIFT_LIBRARY include(ThriftMacros) -include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") - find_package(OpenSSL REQUIRED) include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") diff --git a/tutorial/cpp/CMakeLists.txt b/tutorial/cpp/CMakeLists.txt index 8634b4144b2..c6d8fc32038 100644 --- a/tutorial/cpp/CMakeLists.txt +++ b/tutorial/cpp/CMakeLists.txt @@ -17,7 +17,8 @@ # under the License. # -include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") +include(BoostMacros) +REQUIRE_BOOST_HEADERS() #Make sure gen-cpp files can be included include_directories("${CMAKE_CURRENT_BINARY_DIR}") From ca8af9b48f9e62edc57c4a233c6377144214ef5a Mon Sep 17 00:00:00 2001 From: cyy Date: Fri, 11 Jan 2019 22:13:12 +0800 Subject: [PATCH 129/756] THRIFT-4730: remove pthread code and refactor, ending up with just ThreadFactory --- .travis.yml | 2 +- build/appveyor/CYGW-appveyor-build.bat | 3 +- build/cmake/DefineOptions.cmake | 3 - build/cmake/DefinePlatformSpecifc.cmake | 5 - build/cmake/config.h.in | 3 - contrib/transport-sample/ThriftCommon.h | 4 +- lib/cpp/CMakeLists.txt | 27 +- lib/cpp/Makefile.am | 12 +- lib/cpp/src/thrift/concurrency/Monitor.cpp | 164 ++++----- lib/cpp/src/thrift/concurrency/Mutex.cpp | 335 +----------------- lib/cpp/src/thrift/concurrency/Mutex.h | 101 +----- .../thrift/concurrency/PosixThreadFactory.cpp | 335 ------------------ .../thrift/concurrency/PosixThreadFactory.h | 129 ------- lib/cpp/src/thrift/concurrency/StdMonitor.cpp | 213 ----------- .../thrift/concurrency/StdThreadFactory.cpp | 153 -------- .../concurrency/{StdMutex.cpp => Thread.cpp} | 48 +-- lib/cpp/src/thrift/concurrency/Thread.h | 132 +++---- ...tformThreadFactory.h => ThreadFactory.cpp} | 30 +- .../{StdThreadFactory.h => ThreadFactory.h} | 46 ++- .../src/thrift/concurrency/ThreadManager.h | 2 +- lib/cpp/src/thrift/concurrency/TimerManager.h | 2 +- .../src/thrift/server/TNonblockingServer.cpp | 9 +- .../src/thrift/server/TNonblockingServer.h | 10 +- lib/cpp/src/thrift/server/TThreadedServer.cpp | 2 +- lib/cpp/src/thrift/server/TThreadedServer.h | 10 +- lib/cpp/src/thrift/transport/TFileTransport.h | 4 +- lib/cpp/src/thrift/windows/config.h | 5 - lib/cpp/test/CMakeLists.txt | 5 - lib/cpp/test/Makefile.am | 4 - lib/cpp/test/TNonblockingSSLServerTest.cpp | 7 +- lib/cpp/test/TNonblockingServerTest.cpp | 9 +- lib/cpp/test/TServerIntegrationTest.cpp | 8 +- lib/cpp/test/TransportTest.cpp | 2 +- lib/cpp/test/concurrency/MutexTest.cpp | 123 ------- .../test/concurrency/RWMutexStarveTest.cpp | 157 -------- lib/cpp/test/concurrency/ThreadFactoryTests.h | 10 +- lib/cpp/test/concurrency/ThreadManagerTests.h | 59 +-- lib/cpp/test/concurrency/TimerManagerTests.h | 12 +- lib/cpp/test/processor/ProcessorTest.cpp | 6 +- lib/cpp/test/processor/ServerThread.cpp | 4 +- test/cpp/src/StressTest.cpp | 6 +- test/cpp/src/StressTestNonBlocking.cpp | 6 +- test/cpp/src/TestServer.cpp | 8 +- test/threads/ThreadsClient.cpp | 2 +- test/threads/ThreadsServer.cpp | 6 +- tutorial/cpp/CppServer.cpp | 4 +- 46 files changed, 284 insertions(+), 1943 deletions(-) delete mode 100644 lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp delete mode 100644 lib/cpp/src/thrift/concurrency/PosixThreadFactory.h delete mode 100644 lib/cpp/src/thrift/concurrency/StdMonitor.cpp delete mode 100644 lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp rename lib/cpp/src/thrift/concurrency/{StdMutex.cpp => Thread.cpp} (52%) rename lib/cpp/src/thrift/concurrency/{PlatformThreadFactory.h => ThreadFactory.cpp} (64%) rename lib/cpp/src/thrift/concurrency/{StdThreadFactory.h => ThreadFactory.h} (59%) delete mode 100644 lib/cpp/test/concurrency/MutexTest.cpp delete mode 100644 lib/cpp/test/concurrency/RWMutexStarveTest.cpp diff --git a/.travis.yml b/.travis.yml index 637b5d534a0..75685d55e32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -142,7 +142,7 @@ jobs: - JOB="C++ (Std Thread) and Plugin" - SCRIPT="cmake.sh" - BUILD_LIBS="CPP TESTING TUTORIALS" - - BUILD_ARG="-DWITH_PLUGIN=ON -DWITH_STDTHREADS=ON -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF" + - BUILD_ARG="-DWITH_PLUGIN=ON -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF" - BUILD_ENV="-e CC=clang -e CXX=clang++" # ------------------------- phase: dist ------------------------- diff --git a/build/appveyor/CYGW-appveyor-build.bat b/build/appveyor/CYGW-appveyor-build.bat index c226222941e..6d57ca30d2e 100644 --- a/build/appveyor/CYGW-appveyor-build.bat +++ b/build/appveyor/CYGW-appveyor-build.bat @@ -28,8 +28,7 @@ SET CMAKEARGS=^ -DCMAKE_CXX_STANDARD=11 ^ -DWITH_PYTHON=OFF ^ -DWITH_SHARED_LIB=OFF ^ - -DWITH_STATIC_LIB=ON ^ - -DWITH_STDTHREADS=ON + -DWITH_STATIC_LIB=ON @ECHO ON %BASH% -lc "mkdir -p %BUILDDIR% && cd %BUILDDIR% && cmake.exe %SRCDIR% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% --target install" || EXIT /B diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 207b770c71c..9d95b7c74d8 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -77,8 +77,6 @@ if(WITH_CPP) find_package(OpenSSL QUIET) CMAKE_DEPENDENT_OPTION(WITH_OPENSSL "Build with OpenSSL support" ON "OPENSSL_FOUND" OFF) - # if disabled, builds with posix thread class - deprecated and will be removed... - option(WITH_STDTHREADS "Build with C++ std::thread support" ON) endif() CMAKE_DEPENDENT_OPTION(BUILD_CPP "Build C++ library" ON "BUILD_LIBRARIES;WITH_CPP" OFF) @@ -182,7 +180,6 @@ message(STATUS " Library features:") message(STATUS " Build shared libraries: ${WITH_SHARED_LIB}") message(STATUS " Build static libraries: ${WITH_STATIC_LIB}") message(STATUS " Build with Boost static link library: ${WITH_BOOST_STATIC}") -message(STATUS " Build with C++ std::thread support: ${WITH_STDTHREADS}") message(STATUS " Build with libevent support: ${WITH_LIBEVENT}") message(STATUS " Build with OpenSSL support: ${WITH_OPENSSL}") message(STATUS " Build with Qt4 support: ${WITH_QT4}") diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index 3f112b625fc..9d7c9030cdc 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -89,11 +89,6 @@ endif() add_definitions("-D__STDC_FORMAT_MACROS") add_definitions("-D__STDC_LIMIT_MACROS") -# WITH_*THREADS selects which threading library to use -if(WITH_STDTHREADS) - add_definitions("-DUSE_STD_THREAD=1") -endif() - # C++ Language Level set(CXX_LANGUAGE_LEVEL "C++${CMAKE_CXX_STANDARD}") if (CMAKE_CXX_STANDARD_REQUIRED) diff --git a/build/cmake/config.h.in b/build/cmake/config.h.in index 5f0ae4681c3..a3d66428cb9 100644 --- a/build/cmake/config.h.in +++ b/build/cmake/config.h.in @@ -64,9 +64,6 @@ see: aclocal/ac_prog_bison.m4 */ #cmakedefine BISON_USE_PARSER_H_EXTENSION 1 -/* replaces POSIX pthread by std::thread */ -#cmakedefine USE_STD_THREAD 1 - /* Define to 1 if strerror_r returns char *. */ #cmakedefine STRERROR_R_CHAR_P 1 diff --git a/contrib/transport-sample/ThriftCommon.h b/contrib/transport-sample/ThriftCommon.h index e16d87dddf3..078ad4474bc 100644 --- a/contrib/transport-sample/ThriftCommon.h +++ b/contrib/transport-sample/ThriftCommon.h @@ -25,7 +25,7 @@ // Required Includes //'server' side #includes #include -#include +#include #include #include //'client' side #includes @@ -87,7 +87,7 @@ namespace thriftcommon else { //Multi-threaded server boost::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(NumThreads); - boost::shared_ptr threadFactory = boost::shared_ptr(new PlatformThreadFactory()); + boost::shared_ptr threadFactory = boost::shared_ptr(new ThreadFactory()); threadManager->threadFactory(threadFactory); threadManager->start(); server.reset(new TThreadPoolServer(processor, transport, tfactory, pfactory, threadManager)); diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index 9e36665bd4c..e12c08ce2fd 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -105,32 +105,19 @@ if(OPENSSL_FOUND AND WITH_OPENSSL) list(APPEND SYSLIBS "${OPENSSL_LIBRARIES}") endif() -# WITH_*THREADS selects which threading library to use -if(UNIX AND NOT WITH_STDTHREADS) +if(UNIX) if(ANDROID) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") else() list(APPEND SYSLIBS pthread) endif() - set( thriftcpp_threads_SOURCES - src/thrift/concurrency/PosixThreadFactory.cpp - src/thrift/concurrency/Mutex.cpp - src/thrift/concurrency/Monitor.cpp - ) -else() - if(UNIX) - if(ANDROID) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") - else() - list(APPEND SYSLIBS pthread) - endif() - endif() - set( thriftcpp_threads_SOURCES - src/thrift/concurrency/StdThreadFactory.cpp - src/thrift/concurrency/StdMutex.cpp - src/thrift/concurrency/StdMonitor.cpp - ) endif() +set( thriftcpp_threads_SOURCES + src/thrift/concurrency/ThreadFactory.cpp + src/thrift/concurrency/Thread.cpp + src/thrift/concurrency/Monitor.cpp + src/thrift/concurrency/Mutex.cpp +) # Thrift non blocking server set( thriftcppnb_SOURCES diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index 85bb9abf82c..19bedd75385 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -107,8 +107,9 @@ libthrift_la_SOURCES = src/thrift/TApplicationException.cpp \ src/thrift/server/TThreadedServer.cpp libthrift_la_SOURCES += src/thrift/concurrency/Mutex.cpp \ - src/thrift/concurrency/Monitor.cpp \ - src/thrift/concurrency/PosixThreadFactory.cpp + src/thrift/concurrency/ThreadFactory.cpp \ + src/thrift/concurrency/Thread.cpp \ + src/thrift/concurrency/Monitor.cpp libthriftnb_la_SOURCES = src/thrift/server/TNonblockingServer.cpp \ src/thrift/async/TEvhttpServer.cpp \ @@ -166,12 +167,7 @@ include_concurrency_HEADERS = \ src/thrift/concurrency/Exception.h \ src/thrift/concurrency/Mutex.h \ src/thrift/concurrency/Monitor.h \ - src/thrift/concurrency/PlatformThreadFactory.h \ - src/thrift/concurrency/PosixThreadFactory.h \ - src/thrift/concurrency/StdMonitor.cpp \ - src/thrift/concurrency/StdMutex.cpp \ - src/thrift/concurrency/StdThreadFactory.cpp \ - src/thrift/concurrency/StdThreadFactory.h \ + src/thrift/concurrency/ThreadFactory.h \ src/thrift/concurrency/Thread.h \ src/thrift/concurrency/ThreadManager.h \ src/thrift/concurrency/TimerManager.h \ diff --git a/lib/cpp/src/thrift/concurrency/Monitor.cpp b/lib/cpp/src/thrift/concurrency/Monitor.cpp index 9570cc691c7..7b3b209a74d 100644 --- a/lib/cpp/src/thrift/concurrency/Monitor.cpp +++ b/lib/cpp/src/thrift/concurrency/Monitor.cpp @@ -23,43 +23,36 @@ #include #include #include -#include - #include -#include - -#include +#include +#include +#include +#include namespace apache { namespace thrift { - -using std::unique_ptr; -using std::shared_ptr; - namespace concurrency { /** - * Monitor implementation using the POSIX pthread library + * Monitor implementation using the std thread library * * @version $Id:$ */ class Monitor::Impl { public: - Impl() : ownedMutex_(new Mutex()), mutex_(NULL), condInitialized_(false) { - init(ownedMutex_.get()); - } - - Impl(Mutex* mutex) : mutex_(NULL), condInitialized_(false) { init(mutex); } + Impl() : ownedMutex_(new Mutex()), conditionVariable_(), mutex_(NULL) { init(ownedMutex_.get()); } - Impl(Monitor* monitor) : mutex_(NULL), condInitialized_(false) { init(&(monitor->mutex())); } + Impl(Mutex* mutex) : ownedMutex_(), conditionVariable_(), mutex_(NULL) { init(mutex); } - ~Impl() { cleanup(); } + Impl(Monitor* monitor) : ownedMutex_(), conditionVariable_(), mutex_(NULL) { + init(&(monitor->mutex())); + } Mutex& mutex() { return *mutex_; } - void lock() { mutex().lock(); } - void unlock() { mutex().unlock(); } + void lock() { mutex_->lock(); } + void unlock() { mutex_->unlock(); } /** * Exception-throwing version of waitForTimeRelative(), called simply @@ -68,15 +61,12 @@ class Monitor::Impl { * If the condition occurs, this function returns cleanly; on timeout or * error an exception is thrown. */ - void wait(int64_t timeout_ms) const { + void wait(int64_t timeout_ms) { int result = waitForTimeRelative(timeout_ms); if (result == THRIFT_ETIMEDOUT) { - // pthread_cond_timedwait has been observed to return early on - // various platforms, so comment out this assert. - // assert(Util::currentTime() >= (now + timeout)); throw TimedOutException(); } else if (result != 0) { - throw TException("pthread_cond_wait() or pthread_cond_timedwait() failed"); + throw TException("Monitor::wait() failed"); } } @@ -86,88 +76,86 @@ class Monitor::Impl { * * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. */ - int waitForTimeRelative(int64_t timeout_ms) const { + int waitForTimeRelative(int64_t timeout_ms) { if (timeout_ms == 0LL) { return waitForever(); } - struct THRIFT_TIMESPEC abstime; - Util::toTimespec(abstime, Util::currentTime() + timeout_ms); - return waitForTime(&abstime); + assert(mutex_); + std::timed_mutex* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); + assert(mutexImpl); + + std::unique_lock lock(*mutexImpl, std::adopt_lock); + bool timedout = (conditionVariable_.wait_for(lock, std::chrono::milliseconds(timeout_ms)) + == std::cv_status::timeout); + lock.release(); + return (timedout ? THRIFT_ETIMEDOUT : 0); } /** * Waits until the absolute time specified using struct THRIFT_TIMESPEC. * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. */ - int waitForTime(const THRIFT_TIMESPEC* abstime) const { + int waitForTime(const THRIFT_TIMESPEC* abstime) { + struct timeval temp; + temp.tv_sec = static_cast(abstime->tv_sec); + temp.tv_usec = static_cast(abstime->tv_nsec) / 1000; + return waitForTime(&temp); + } + + /** + * Waits until the absolute time specified using struct timeval. + * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. + */ + int waitForTime(const struct timeval* abstime) { assert(mutex_); - pthread_mutex_t* mutexImpl = reinterpret_cast(mutex_->getUnderlyingImpl()); + std::timed_mutex* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); assert(mutexImpl); - // XXX Need to assert that caller owns mutex - return pthread_cond_timedwait(&pthread_cond_, mutexImpl, abstime); + struct timeval currenttime; + Util::toTimeval(currenttime, Util::currentTime()); + + long tv_sec = static_cast(abstime->tv_sec - currenttime.tv_sec); + long tv_usec = static_cast(abstime->tv_usec - currenttime.tv_usec); + if (tv_sec < 0) + tv_sec = 0; + if (tv_usec < 0) + tv_usec = 0; + + std::unique_lock lock(*mutexImpl, std::adopt_lock); + bool timedout = (conditionVariable_.wait_for(lock, + std::chrono::seconds(tv_sec) + + std::chrono::microseconds(tv_usec)) + == std::cv_status::timeout); + lock.release(); + return (timedout ? THRIFT_ETIMEDOUT : 0); } - int waitForTime(const struct timeval* abstime) const { - struct THRIFT_TIMESPEC temp; - temp.tv_sec = abstime->tv_sec; - temp.tv_nsec = abstime->tv_usec * 1000; - return waitForTime(&temp); - } /** * Waits forever until the condition occurs. * Returns 0 if condition occurs, or an error code otherwise. */ - int waitForever() const { + int waitForever() { assert(mutex_); - pthread_mutex_t* mutexImpl = reinterpret_cast(mutex_->getUnderlyingImpl()); + std::timed_mutex* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); assert(mutexImpl); - return pthread_cond_wait(&pthread_cond_, mutexImpl); - } - void notify() { - // XXX Need to assert that caller owns mutex - int iret = pthread_cond_signal(&pthread_cond_); - THRIFT_UNUSED_VARIABLE(iret); - assert(iret == 0); + std::unique_lock lock(*mutexImpl, std::adopt_lock); + conditionVariable_.wait(lock); + lock.release(); + return 0; } - void notifyAll() { - // XXX Need to assert that caller owns mutex - int iret = pthread_cond_broadcast(&pthread_cond_); - THRIFT_UNUSED_VARIABLE(iret); - assert(iret == 0); - } - -private: - void init(Mutex* mutex) { - mutex_ = mutex; + void notify() { conditionVariable_.notify_one(); } - if (pthread_cond_init(&pthread_cond_, NULL) == 0) { - condInitialized_ = true; - } + void notifyAll() { conditionVariable_.notify_all(); } - if (!condInitialized_) { - cleanup(); - throw SystemResourceException(); - } - } - - void cleanup() { - if (condInitialized_) { - condInitialized_ = false; - int iret = pthread_cond_destroy(&pthread_cond_); - THRIFT_UNUSED_VARIABLE(iret); - assert(iret == 0); - } - } +private: + void init(Mutex* mutex) { mutex_ = mutex; } - unique_ptr ownedMutex_; + const std::unique_ptr ownedMutex_; + std::condition_variable_any conditionVariable_; Mutex* mutex_; - - mutable pthread_cond_t pthread_cond_; - mutable bool condInitialized_; }; Monitor::Monitor() : impl_(new Monitor::Impl()) { @@ -182,43 +170,43 @@ Monitor::~Monitor() { } Mutex& Monitor::mutex() const { - return impl_->mutex(); + return const_cast(impl_)->mutex(); } void Monitor::lock() const { - impl_->lock(); + const_cast(impl_)->lock(); } void Monitor::unlock() const { - impl_->unlock(); + const_cast(impl_)->unlock(); } void Monitor::wait(int64_t timeout) const { - impl_->wait(timeout); + const_cast(impl_)->wait(timeout); } int Monitor::waitForTime(const THRIFT_TIMESPEC* abstime) const { - return impl_->waitForTime(abstime); + return const_cast(impl_)->waitForTime(abstime); } int Monitor::waitForTime(const timeval* abstime) const { - return impl_->waitForTime(abstime); + return const_cast(impl_)->waitForTime(abstime); } int Monitor::waitForTimeRelative(int64_t timeout_ms) const { - return impl_->waitForTimeRelative(timeout_ms); + return const_cast(impl_)->waitForTimeRelative(timeout_ms); } int Monitor::waitForever() const { - return impl_->waitForever(); + return const_cast(impl_)->waitForever(); } void Monitor::notify() const { - impl_->notify(); + const_cast(impl_)->notify(); } void Monitor::notifyAll() const { - impl_->notifyAll(); + const_cast(impl_)->notifyAll(); } } } diff --git a/lib/cpp/src/thrift/concurrency/Mutex.cpp b/lib/cpp/src/thrift/concurrency/Mutex.cpp index a5264617d5a..75802835d0b 100644 --- a/lib/cpp/src/thrift/concurrency/Mutex.cpp +++ b/lib/cpp/src/thrift/concurrency/Mutex.cpp @@ -17,202 +17,29 @@ * under the License. */ -// needed to test for pthread implementation capabilities: -#define __USE_GNU - -#include - -#include -#include #include -#include - -#include -#include -#include -#include -#include -#include +#include +#include namespace apache { namespace thrift { namespace concurrency { -// Enable this to turn on mutex contention profiling support -// #define THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING - -#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING - -static int32_t mutexProfilingCounter = 0; -static int32_t mutexProfilingSampleRate = 0; -static MutexWaitCallback mutexProfilingCallback = 0; - -void enableMutexProfiling(int32_t profilingSampleRate, MutexWaitCallback callback) { - mutexProfilingSampleRate = profilingSampleRate; - mutexProfilingCallback = callback; -} - -#define PROFILE_MUTEX_START_LOCK() int64_t _lock_startTime = maybeGetProfilingStartTime(); - -#define PROFILE_MUTEX_NOT_LOCKED() \ - do { \ - if (_lock_startTime > 0) { \ - int64_t endTime = Util::currentTimeUsec(); \ - (*mutexProfilingCallback)(this, endTime - _lock_startTime); \ - } \ - } while (0) - -#define PROFILE_MUTEX_LOCKED() \ - do { \ - profileTime_ = _lock_startTime; \ - if (profileTime_ > 0) { \ - profileTime_ = Util::currentTimeUsec() - profileTime_; \ - } \ - } while (0) - -#define PROFILE_MUTEX_START_UNLOCK() \ - int64_t _temp_profileTime = profileTime_; \ - profileTime_ = 0; - -#define PROFILE_MUTEX_UNLOCKED() \ - do { \ - if (_temp_profileTime > 0) { \ - (*mutexProfilingCallback)(this, _temp_profileTime); \ - } \ - } while (0) - -static inline int64_t maybeGetProfilingStartTime() { - if (mutexProfilingSampleRate && mutexProfilingCallback) { - // This block is unsynchronized, but should produce a reasonable sampling - // rate on most architectures. The main race conditions are the gap - // between the decrement and the test, the non-atomicity of decrement, and - // potential caching of different values at different CPUs. - // - // - if two decrements race, the likeliest result is that the counter - // decrements slowly (perhaps much more slowly) than intended. - // - // - many threads could potentially decrement before resetting the counter - // to its large value, causing each additional incoming thread to - // profile every call. This situation is unlikely to persist for long - // as the critical gap is quite short, but profiling could be bursty. - sig_atomic_t localValue = --mutexProfilingCounter; - if (localValue <= 0) { - mutexProfilingCounter = mutexProfilingSampleRate; - return Util::currentTimeUsec(); - } - } - - return 0; -} - -#else -#define PROFILE_MUTEX_START_LOCK() -#define PROFILE_MUTEX_NOT_LOCKED() -#define PROFILE_MUTEX_LOCKED() -#define PROFILE_MUTEX_START_UNLOCK() -#define PROFILE_MUTEX_UNLOCKED() -#endif // THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING - -#define EINTR_LOOP(_CALL) int ret; do { ret = _CALL; } while (ret == EINTR) -#define ABORT_ONFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret) { abort(); } } -#define THROW_SRE(_CALLSTR, RET) { throw SystemResourceException(boost::str(boost::format("%1% returned %2% (%3%)") % _CALLSTR % RET % ::strerror(RET))); } -#define THROW_SRE_ONFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret) { THROW_SRE(#_CALL, ret); } } -#define THROW_SRE_TRYFAIL(_CALL) { EINTR_LOOP(_CALL); if (ret == 0) { return true; } else if (ret == EBUSY) { return false; } THROW_SRE(#_CALL, ret); } - /** - * Implementation of Mutex class using POSIX mutex + * Implementation of Mutex class using C++11 std::timed_mutex * - * Throws apache::thrift::concurrency::SystemResourceException on error. + * Methods throw std::system_error on error. * * @version $Id:$ */ -class Mutex::impl { -public: - impl(Initializer init) : initialized_(false) { -#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING - profileTime_ = 0; -#endif - init(&pthread_mutex_); - initialized_ = true; - } +class Mutex::impl : public std::timed_mutex {}; - ~impl() { - if (initialized_) { - initialized_ = false; - ABORT_ONFAIL(pthread_mutex_destroy(&pthread_mutex_)); - } - } - - void lock() const { - PROFILE_MUTEX_START_LOCK(); - THROW_SRE_ONFAIL(pthread_mutex_lock(&pthread_mutex_)); - PROFILE_MUTEX_LOCKED(); - } - - bool trylock() const { - THROW_SRE_TRYFAIL(pthread_mutex_trylock(&pthread_mutex_)); - } - - bool timedlock(int64_t milliseconds) const { -#if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 200112L - PROFILE_MUTEX_START_LOCK(); - - struct THRIFT_TIMESPEC ts; - Util::toTimespec(ts, milliseconds + Util::currentTime()); - EINTR_LOOP(pthread_mutex_timedlock(&pthread_mutex_, &ts)); - if (ret == 0) { - PROFILE_MUTEX_LOCKED(); - return true; - } else if (ret == ETIMEDOUT) { - PROFILE_MUTEX_NOT_LOCKED(); - return false; - } - - THROW_SRE("pthread_mutex_timedlock(&pthread_mutex_, &ts)", ret); -#else - /* Otherwise follow solution used by Mono for Android */ - struct THRIFT_TIMESPEC sleepytime, now, to; - - /* This is just to avoid a completely busy wait */ - sleepytime.tv_sec = 0; - sleepytime.tv_nsec = 10000000L; /* 10ms */ - - Util::toTimespec(to, milliseconds + Util::currentTime()); - - while ((trylock()) == false) { - Util::toTimespec(now, Util::currentTime()); - if (now.tv_sec >= to.tv_sec && now.tv_nsec >= to.tv_nsec) { - return false; - } - nanosleep(&sleepytime, NULL); - } - - return true; -#endif - } - - void unlock() const { - PROFILE_MUTEX_START_UNLOCK(); - THROW_SRE_ONFAIL(pthread_mutex_unlock(&pthread_mutex_)); - PROFILE_MUTEX_UNLOCKED(); - } - - void* getUnderlyingImpl() const { return (void*)&pthread_mutex_; } - -private: - mutable pthread_mutex_t pthread_mutex_; - mutable bool initialized_; -#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING - mutable int64_t profileTime_; -#endif -}; - -Mutex::Mutex(Initializer init) : impl_(new Mutex::impl(init)) { +Mutex::Mutex() : impl_(new Mutex::impl()) { } void* Mutex::getUnderlyingImpl() const { - return impl_->getUnderlyingImpl(); + return impl_.get(); } void Mutex::lock() const { @@ -220,161 +47,17 @@ void Mutex::lock() const { } bool Mutex::trylock() const { - return impl_->trylock(); + return impl_->try_lock(); } bool Mutex::timedlock(int64_t ms) const { - return impl_->timedlock(ms); + return impl_->try_lock_for(std::chrono::milliseconds(ms)); } void Mutex::unlock() const { impl_->unlock(); } -void Mutex::DEFAULT_INITIALIZER(void* arg) { - pthread_mutex_t* pthread_mutex = (pthread_mutex_t*)arg; - THROW_SRE_ONFAIL(pthread_mutex_init(pthread_mutex, NULL)); -} - -#if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) || defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP) || defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) -static void init_with_kind(pthread_mutex_t* mutex, int kind) { - pthread_mutexattr_t mutexattr; - THROW_SRE_ONFAIL(pthread_mutexattr_init(&mutexattr)); - THROW_SRE_ONFAIL(pthread_mutexattr_settype(&mutexattr, kind)); - THROW_SRE_ONFAIL(pthread_mutex_init(mutex, &mutexattr)); - THROW_SRE_ONFAIL(pthread_mutexattr_destroy(&mutexattr)); -} -#endif - -#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP -void Mutex::ADAPTIVE_INITIALIZER(void* arg) { - // From mysql source: mysys/my_thr_init.c - // Set mutex type to "fast" a.k.a "adaptive" - // - // In this case the thread may steal the mutex from some other thread - // that is waiting for the same mutex. This will save us some - // context switches but may cause a thread to 'starve forever' while - // waiting for the mutex (not likely if the code within the mutex is - // short). - init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_ADAPTIVE_NP); -} -#endif - -#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP -void Mutex::ERRORCHECK_INITIALIZER(void* arg) { - init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_ERRORCHECK); -} -#endif - -#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP -void Mutex::RECURSIVE_INITIALIZER(void* arg) { - init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_RECURSIVE_NP); -} -#endif - -/** - * Implementation of ReadWriteMutex class using POSIX rw lock - * - * @version $Id:$ - */ -class ReadWriteMutex::impl { -public: - impl() : initialized_(false) { -#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING - profileTime_ = 0; -#endif - THROW_SRE_ONFAIL(pthread_rwlock_init(&rw_lock_, NULL)); - initialized_ = true; - } - - ~impl() { - if (initialized_) { - initialized_ = false; - ABORT_ONFAIL(pthread_rwlock_destroy(&rw_lock_)); - } - } - - void acquireRead() const { - PROFILE_MUTEX_START_LOCK(); - THROW_SRE_ONFAIL(pthread_rwlock_rdlock(&rw_lock_)); - PROFILE_MUTEX_NOT_LOCKED(); // not exclusive, so use not-locked path - } - - void acquireWrite() const { - PROFILE_MUTEX_START_LOCK(); - THROW_SRE_ONFAIL(pthread_rwlock_wrlock(&rw_lock_)); - PROFILE_MUTEX_LOCKED(); - } - - bool attemptRead() const { THROW_SRE_TRYFAIL(pthread_rwlock_tryrdlock(&rw_lock_)); } - - bool attemptWrite() const { THROW_SRE_TRYFAIL(pthread_rwlock_trywrlock(&rw_lock_)); } - - void release() const { - PROFILE_MUTEX_START_UNLOCK(); - THROW_SRE_ONFAIL(pthread_rwlock_unlock(&rw_lock_)); - PROFILE_MUTEX_UNLOCKED(); - } - -private: - mutable pthread_rwlock_t rw_lock_; - mutable bool initialized_; -#ifdef THRIFT_PTHREAD_MUTEX_CONTENTION_PROFILING - mutable int64_t profileTime_; -#endif -}; - -ReadWriteMutex::ReadWriteMutex() : impl_(new ReadWriteMutex::impl()) { -} - -void ReadWriteMutex::acquireRead() const { - impl_->acquireRead(); -} - -void ReadWriteMutex::acquireWrite() const { - impl_->acquireWrite(); -} - -bool ReadWriteMutex::attemptRead() const { - return impl_->attemptRead(); -} - -bool ReadWriteMutex::attemptWrite() const { - return impl_->attemptWrite(); -} - -void ReadWriteMutex::release() const { - impl_->release(); -} - -NoStarveReadWriteMutex::NoStarveReadWriteMutex() : writerWaiting_(false) { -} - -void NoStarveReadWriteMutex::acquireRead() const { - if (writerWaiting_) { - // writer is waiting, block on the writer's mutex until he's done with it - mutex_.lock(); - mutex_.unlock(); - } - - ReadWriteMutex::acquireRead(); -} - -void NoStarveReadWriteMutex::acquireWrite() const { - // if we can acquire the rwlock the easy way, we're done - if (attemptWrite()) { - return; - } - - // failed to get the rwlock, do it the hard way: - // locking the mutex and setting writerWaiting will cause all new readers to - // block on the mutex rather than on the rwlock. - mutex_.lock(); - writerWaiting_ = true; - ReadWriteMutex::acquireWrite(); - writerWaiting_ = false; - mutex_.unlock(); -} } } } // apache::thrift::concurrency diff --git a/lib/cpp/src/thrift/concurrency/Mutex.h b/lib/cpp/src/thrift/concurrency/Mutex.h index a1f539685c2..123ae785d39 100644 --- a/lib/cpp/src/thrift/concurrency/Mutex.h +++ b/lib/cpp/src/thrift/concurrency/Mutex.h @@ -28,31 +28,6 @@ namespace apache { namespace thrift { namespace concurrency { -#ifndef THRIFT_NO_CONTENTION_PROFILING - -/** - * Determines if the Thrift Mutex and ReadWriteMutex classes will attempt to - * profile their blocking acquire methods. If this value is set to non-zero, - * Thrift will attempt to invoke the callback once every profilingSampleRate - * times. However, as the sampling is not synchronized the rate is not - * guranateed, and could be subject to big bursts and swings. Please ensure - * your sampling callback is as performant as your application requires. - * - * The callback will get called with the wait time taken to lock the mutex in - * usec and a (void*) that uniquely identifies the Mutex (or ReadWriteMutex) - * being locked. - * - * The enableMutexProfiling() function is unsynchronized; calling this function - * while profiling is already enabled may result in race conditions. On - * architectures where a pointer assignment is atomic, this is safe but there - * is no guarantee threads will agree on a single callback within any - * particular time period. - */ -typedef void (*MutexWaitCallback)(const void* id, int64_t waitTimeMicros); -void enableMutexProfiling(int32_t profilingSampleRate, MutexWaitCallback callback); - -#endif - /** * NOTE: All mutex implementations throw an exception on failure. See each * specific implementation to understand the exception type(s) used. @@ -65,9 +40,7 @@ void enableMutexProfiling(int32_t profilingSampleRate, MutexWaitCallback callbac */ class Mutex { public: - typedef void (*Initializer)(void*); - - Mutex(Initializer init = DEFAULT_INITIALIZER); + Mutex(); virtual ~Mutex() {} virtual void lock() const; @@ -77,57 +50,11 @@ class Mutex { void* getUnderlyingImpl() const; - // If you attempt to use one of these and it fails to link, it means - // your version of pthreads does not support it - try another one. - static void ADAPTIVE_INITIALIZER(void*); - static void DEFAULT_INITIALIZER(void*); - static void ERRORCHECK_INITIALIZER(void*); - static void RECURSIVE_INITIALIZER(void*); - -private: - class impl; - std::shared_ptr impl_; -}; - -class ReadWriteMutex { -public: - ReadWriteMutex(); - virtual ~ReadWriteMutex() {} - - // these get the lock and block until it is done successfully - virtual void acquireRead() const; - virtual void acquireWrite() const; - - // these attempt to get the lock, returning false immediately if they fail - virtual bool attemptRead() const; - virtual bool attemptWrite() const; - - // this releases both read and write locks - virtual void release() const; - private: class impl; std::shared_ptr impl_; }; -/** - * A ReadWriteMutex that guarantees writers will not be starved by readers: - * When a writer attempts to acquire the mutex, all new readers will be - * blocked from acquiring the mutex until the writer has acquired and - * released it. In some operating systems, this may already be guaranteed - * by a regular ReadWriteMutex. - */ -class NoStarveReadWriteMutex : public ReadWriteMutex { -public: - NoStarveReadWriteMutex(); - - virtual void acquireRead() const; - virtual void acquireWrite() const; - -private: - Mutex mutex_; - mutable volatile bool writerWaiting_; -}; class Guard : boost::noncopyable { public: @@ -156,32 +83,6 @@ class Guard : boost::noncopyable { const Mutex* mutex_; }; -// Can be used as second argument to RWGuard to make code more readable -// as to whether we're doing acquireRead() or acquireWrite(). -enum RWGuardType { RW_READ = 0, RW_WRITE = 1 }; - -class RWGuard : boost::noncopyable { -public: - RWGuard(const ReadWriteMutex& value, bool write = false) : rw_mutex_(value) { - if (write) { - rw_mutex_.acquireWrite(); - } else { - rw_mutex_.acquireRead(); - } - } - - RWGuard(const ReadWriteMutex& value, RWGuardType type) : rw_mutex_(value) { - if (type == RW_WRITE) { - rw_mutex_.acquireWrite(); - } else { - rw_mutex_.acquireRead(); - } - } - ~RWGuard() { rw_mutex_.release(); } - -private: - const ReadWriteMutex& rw_mutex_; -}; } } } // apache::thrift::concurrency diff --git a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp deleted file mode 100644 index 5c592697776..00000000000 --- a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include - -#include -#include -#include - -#if GOOGLE_PERFTOOLS_REGISTER_THREAD -#include -#endif - -#include -#include - -#include - -#include - -namespace apache { -namespace thrift { -namespace concurrency { - -/** - * The POSIX thread class. - * - * @version $Id:$ - */ -class PthreadThread : public Thread { -public: - enum STATE { uninitialized, starting, started, stopping, stopped }; - - static const int MB = 1024 * 1024; - - static void* threadMain(void* arg); - -private: - pthread_t pthread_; - Monitor monitor_; // guard to protect state_ and also notification - STATE state_; // to protect proper thread start behavior - int policy_; - int priority_; - int stackSize_; - std::weak_ptr self_; - bool detached_; - -public: - PthreadThread(int policy, - int priority, - int stackSize, - bool detached, - std::shared_ptr runnable) - : - -#ifndef _WIN32 - pthread_(0), -#endif // _WIN32 - state_(uninitialized), - policy_(policy), - priority_(priority), - stackSize_(stackSize), - detached_(detached) { - - this->Thread::runnable(runnable); - } - - ~PthreadThread() { - /* Nothing references this thread, if is is not detached, do a join - now, otherwise the thread-id and, possibly, other resources will - be leaked. */ - if (!detached_) { - try { - join(); - } catch (...) { - // We're really hosed. - } - } - } - - STATE getState() const - { - Synchronized sync(monitor_); - return state_; - } - - void setState(STATE newState) - { - Synchronized sync(monitor_); - state_ = newState; - - // unblock start() with the knowledge that the thread has actually - // started running, which avoids a race in detached threads. - if (newState == started) { - monitor_.notify(); - } - } - - void start() { - if (getState() != uninitialized) { - return; - } - - pthread_attr_t thread_attr; - if (pthread_attr_init(&thread_attr) != 0) { - throw SystemResourceException("pthread_attr_init failed"); - } - - if (pthread_attr_setdetachstate(&thread_attr, - detached_ ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE) - != 0) { - throw SystemResourceException("pthread_attr_setdetachstate failed"); - } - - // Set thread stack size - if (pthread_attr_setstacksize(&thread_attr, MB * stackSize_) != 0) { - throw SystemResourceException("pthread_attr_setstacksize failed"); - } - -// Set thread policy -#ifdef _WIN32 - // WIN32 Pthread implementation doesn't seem to support sheduling policies other then - // PosixThreadFactory::OTHER - runtime error - policy_ = PosixThreadFactory::OTHER; -#endif - -#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0 - if (pthread_attr_setschedpolicy(&thread_attr, policy_) != 0) { - throw SystemResourceException("pthread_attr_setschedpolicy failed"); - } -#endif - - struct sched_param sched_param; - sched_param.sched_priority = priority_; - - // Set thread priority - if (pthread_attr_setschedparam(&thread_attr, &sched_param) != 0) { - throw SystemResourceException("pthread_attr_setschedparam failed"); - } - - // Create reference - std::shared_ptr* selfRef = new std::shared_ptr(); - *selfRef = self_.lock(); - - setState(starting); - - Synchronized sync(monitor_); - - if (pthread_create(&pthread_, &thread_attr, threadMain, (void*)selfRef) != 0) { - throw SystemResourceException("pthread_create failed"); - } - - // The caller may not choose to guarantee the scope of the Runnable - // being used in the thread, so we must actually wait until the thread - // starts before we return. If we do not wait, it would be possible - // for the caller to start destructing the Runnable and the Thread, - // and we would end up in a race. This was identified with valgrind. - monitor_.wait(); - } - - void join() { - if (!detached_ && getState() != uninitialized) { - void* ignore; - /* XXX - If join fails it is most likely due to the fact - that the last reference was the thread itself and cannot - join. This results in leaked threads and will eventually - cause the process to run out of thread resources. - We're beyond the point of throwing an exception. Not clear how - best to handle this. */ - int res = pthread_join(pthread_, &ignore); - detached_ = (res == 0); - if (res != 0) { - GlobalOutput.printf("PthreadThread::join(): fail with code %d", res); - } - } - } - - Thread::id_t getId() { - -#ifndef _WIN32 - return (Thread::id_t)pthread_; -#else - return (Thread::id_t)pthread_.p; -#endif // _WIN32 - } - - std::shared_ptr runnable() const { return Thread::runnable(); } - - void runnable(std::shared_ptr value) { Thread::runnable(value); } - - void weakRef(std::shared_ptr self) { - assert(self.get() == this); - self_ = std::weak_ptr(self); - } -}; - -void* PthreadThread::threadMain(void* arg) { - std::shared_ptr thread = *(std::shared_ptr*)arg; - delete reinterpret_cast*>(arg); - -#if GOOGLE_PERFTOOLS_REGISTER_THREAD - ProfilerRegisterThread(); -#endif - - thread->setState(started); - - thread->runnable()->run(); - - STATE _s = thread->getState(); - if (_s != stopping && _s != stopped) { - thread->setState(stopping); - } - - return (void*)0; -} - -/** - * Converts generic posix thread schedule policy enums into pthread - * API values. - */ -static int toPthreadPolicy(PosixThreadFactory::POLICY policy) { - switch (policy) { - case PosixThreadFactory::OTHER: - return SCHED_OTHER; - case PosixThreadFactory::FIFO: - return SCHED_FIFO; - case PosixThreadFactory::ROUND_ROBIN: - return SCHED_RR; - } - return SCHED_OTHER; -} - -/** - * Converts relative thread priorities to absolute value based on posix - * thread scheduler policy - * - * The idea is simply to divide up the priority range for the given policy - * into the correpsonding relative priority level (lowest..highest) and - * then pro-rate accordingly. - */ -static int toPthreadPriority(PosixThreadFactory::POLICY policy, PosixThreadFactory::PRIORITY priority) { - int pthread_policy = toPthreadPolicy(policy); - int min_priority = 0; - int max_priority = 0; -#ifdef HAVE_SCHED_GET_PRIORITY_MIN - min_priority = sched_get_priority_min(pthread_policy); -#endif -#ifdef HAVE_SCHED_GET_PRIORITY_MAX - max_priority = sched_get_priority_max(pthread_policy); -#endif - int quanta = (PosixThreadFactory::HIGHEST - PosixThreadFactory::LOWEST) + 1; - float stepsperquanta = (float)(max_priority - min_priority) / quanta; - - if (priority <= PosixThreadFactory::HIGHEST) { - return (int)(min_priority + stepsperquanta * priority); - } else { - // should never get here for priority increments. - assert(false); - return (int)(min_priority + stepsperquanta * PosixThreadFactory::NORMAL); - } -} - -PosixThreadFactory::PosixThreadFactory(POLICY policy, - PRIORITY priority, - int stackSize, - bool detached) - : ThreadFactory(detached), - policy_(policy), - priority_(priority), - stackSize_(stackSize) { -} - -PosixThreadFactory::PosixThreadFactory(bool detached) - : ThreadFactory(detached), - policy_(ROUND_ROBIN), - priority_(NORMAL), - stackSize_(1) { -} - -std::shared_ptr PosixThreadFactory::newThread(std::shared_ptr runnable) const { - std::shared_ptr result - = std::shared_ptr(new PthreadThread(toPthreadPolicy(policy_), - toPthreadPriority(policy_, priority_), - stackSize_, - isDetached(), - runnable)); - result->weakRef(result); - runnable->thread(result); - return result; -} - -int PosixThreadFactory::getStackSize() const { - return stackSize_; -} - -void PosixThreadFactory::setStackSize(int value) { - stackSize_ = value; -} - -PosixThreadFactory::PRIORITY PosixThreadFactory::getPriority() const { - return priority_; -} - -void PosixThreadFactory::setPriority(PRIORITY value) { - priority_ = value; -} - -Thread::id_t PosixThreadFactory::getCurrentThreadId() const { -#ifndef _WIN32 - return (Thread::id_t)pthread_self(); -#else - return (Thread::id_t)pthread_self().p; -#endif // _WIN32 -} - -} -} -} // apache::thrift::concurrency diff --git a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h b/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h deleted file mode 100644 index cb3b17c9c9c..00000000000 --- a/lib/cpp/src/thrift/concurrency/PosixThreadFactory.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ -#define _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ 1 - -#include - -#include - -namespace apache { -namespace thrift { -namespace concurrency { - -/** - * A thread factory to create posix threads - * - * @version $Id:$ - */ -class PosixThreadFactory : public ThreadFactory { - -public: - /** - * POSIX Thread scheduler policies - */ - enum POLICY { OTHER, FIFO, ROUND_ROBIN }; - - /** - * POSIX Thread scheduler relative priorities, - * - * Absolute priority is determined by scheduler policy and OS. This - * enumeration specifies relative priorities such that one can specify a - * priority within a giving scheduler policy without knowing the absolute - * value of the priority. - */ - enum PRIORITY { - LOWEST = 0, - LOWER = 1, - LOW = 2, - NORMAL = 3, - HIGH = 4, - HIGHER = 5, - HIGHEST = 6, - INCREMENT = 7, - DECREMENT = 8 - }; - - /** - * Posix thread (pthread) factory. All threads created by a factory are reference-counted - * via std::shared_ptr. The factory guarantees that threads and the Runnable tasks - * they host will be properly cleaned up once the last strong reference to both is - * given up. - * - * Threads are created with the specified policy, priority, stack-size and detachable-mode - * detached means the thread is free-running and will release all system resources the - * when it completes. A detachable thread is not joinable. The join method - * of a detachable thread will return immediately with no error. - * - * By default threads are not joinable. - */ - PosixThreadFactory(POLICY policy = ROUND_ROBIN, - PRIORITY priority = NORMAL, - int stackSize = 1, - bool detached = true); - - /** - * Provide a constructor compatible with the other factories - * The default policy is POLICY::ROUND_ROBIN. - * The default priority is PRIORITY::NORMAL. - * The default stackSize is 1. - */ - PosixThreadFactory(bool detached); - - // From ThreadFactory; - std::shared_ptr newThread(std::shared_ptr runnable) const; - - // From ThreadFactory; - Thread::id_t getCurrentThreadId() const; - - /** - * Gets stack size for newly created threads - * - * @return int size in megabytes - */ - virtual int getStackSize() const; - - /** - * Sets stack size for newly created threads - * - * @param value size in megabytes - */ - virtual void setStackSize(int value); - - /** - * Gets priority relative to current policy - */ - virtual PRIORITY getPriority() const; - - /** - * Sets priority relative to current policy - */ - virtual void setPriority(PRIORITY priority); - -private: - POLICY policy_; - PRIORITY priority_; - int stackSize_; -}; -} -} -} // apache::thrift::concurrency - -#endif // #ifndef _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ diff --git a/lib/cpp/src/thrift/concurrency/StdMonitor.cpp b/lib/cpp/src/thrift/concurrency/StdMonitor.cpp deleted file mode 100644 index 7b3b209a74d..00000000000 --- a/lib/cpp/src/thrift/concurrency/StdMonitor.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace apache { -namespace thrift { -namespace concurrency { - -/** - * Monitor implementation using the std thread library - * - * @version $Id:$ - */ -class Monitor::Impl { - -public: - Impl() : ownedMutex_(new Mutex()), conditionVariable_(), mutex_(NULL) { init(ownedMutex_.get()); } - - Impl(Mutex* mutex) : ownedMutex_(), conditionVariable_(), mutex_(NULL) { init(mutex); } - - Impl(Monitor* monitor) : ownedMutex_(), conditionVariable_(), mutex_(NULL) { - init(&(monitor->mutex())); - } - - Mutex& mutex() { return *mutex_; } - void lock() { mutex_->lock(); } - void unlock() { mutex_->unlock(); } - - /** - * Exception-throwing version of waitForTimeRelative(), called simply - * wait(int64) for historical reasons. Timeout is in milliseconds. - * - * If the condition occurs, this function returns cleanly; on timeout or - * error an exception is thrown. - */ - void wait(int64_t timeout_ms) { - int result = waitForTimeRelative(timeout_ms); - if (result == THRIFT_ETIMEDOUT) { - throw TimedOutException(); - } else if (result != 0) { - throw TException("Monitor::wait() failed"); - } - } - - /** - * Waits until the specified timeout in milliseconds for the condition to - * occur, or waits forever if timeout_ms == 0. - * - * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. - */ - int waitForTimeRelative(int64_t timeout_ms) { - if (timeout_ms == 0LL) { - return waitForever(); - } - - assert(mutex_); - std::timed_mutex* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); - assert(mutexImpl); - - std::unique_lock lock(*mutexImpl, std::adopt_lock); - bool timedout = (conditionVariable_.wait_for(lock, std::chrono::milliseconds(timeout_ms)) - == std::cv_status::timeout); - lock.release(); - return (timedout ? THRIFT_ETIMEDOUT : 0); - } - - /** - * Waits until the absolute time specified using struct THRIFT_TIMESPEC. - * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. - */ - int waitForTime(const THRIFT_TIMESPEC* abstime) { - struct timeval temp; - temp.tv_sec = static_cast(abstime->tv_sec); - temp.tv_usec = static_cast(abstime->tv_nsec) / 1000; - return waitForTime(&temp); - } - - /** - * Waits until the absolute time specified using struct timeval. - * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. - */ - int waitForTime(const struct timeval* abstime) { - assert(mutex_); - std::timed_mutex* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); - assert(mutexImpl); - - struct timeval currenttime; - Util::toTimeval(currenttime, Util::currentTime()); - - long tv_sec = static_cast(abstime->tv_sec - currenttime.tv_sec); - long tv_usec = static_cast(abstime->tv_usec - currenttime.tv_usec); - if (tv_sec < 0) - tv_sec = 0; - if (tv_usec < 0) - tv_usec = 0; - - std::unique_lock lock(*mutexImpl, std::adopt_lock); - bool timedout = (conditionVariable_.wait_for(lock, - std::chrono::seconds(tv_sec) - + std::chrono::microseconds(tv_usec)) - == std::cv_status::timeout); - lock.release(); - return (timedout ? THRIFT_ETIMEDOUT : 0); - } - - /** - * Waits forever until the condition occurs. - * Returns 0 if condition occurs, or an error code otherwise. - */ - int waitForever() { - assert(mutex_); - std::timed_mutex* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); - assert(mutexImpl); - - std::unique_lock lock(*mutexImpl, std::adopt_lock); - conditionVariable_.wait(lock); - lock.release(); - return 0; - } - - void notify() { conditionVariable_.notify_one(); } - - void notifyAll() { conditionVariable_.notify_all(); } - -private: - void init(Mutex* mutex) { mutex_ = mutex; } - - const std::unique_ptr ownedMutex_; - std::condition_variable_any conditionVariable_; - Mutex* mutex_; -}; - -Monitor::Monitor() : impl_(new Monitor::Impl()) { -} -Monitor::Monitor(Mutex* mutex) : impl_(new Monitor::Impl(mutex)) { -} -Monitor::Monitor(Monitor* monitor) : impl_(new Monitor::Impl(monitor)) { -} - -Monitor::~Monitor() { - delete impl_; -} - -Mutex& Monitor::mutex() const { - return const_cast(impl_)->mutex(); -} - -void Monitor::lock() const { - const_cast(impl_)->lock(); -} - -void Monitor::unlock() const { - const_cast(impl_)->unlock(); -} - -void Monitor::wait(int64_t timeout) const { - const_cast(impl_)->wait(timeout); -} - -int Monitor::waitForTime(const THRIFT_TIMESPEC* abstime) const { - return const_cast(impl_)->waitForTime(abstime); -} - -int Monitor::waitForTime(const timeval* abstime) const { - return const_cast(impl_)->waitForTime(abstime); -} - -int Monitor::waitForTimeRelative(int64_t timeout_ms) const { - return const_cast(impl_)->waitForTimeRelative(timeout_ms); -} - -int Monitor::waitForever() const { - return const_cast(impl_)->waitForever(); -} - -void Monitor::notify() const { - const_cast(impl_)->notify(); -} - -void Monitor::notifyAll() const { - const_cast(impl_)->notifyAll(); -} -} -} -} // apache::thrift::concurrency diff --git a/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp b/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp deleted file mode 100644 index c885f3acab4..00000000000 --- a/lib/cpp/src/thrift/concurrency/StdThreadFactory.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include - -#if USE_STD_THREAD - -#include -#include -#include -#include - -#include -#include - -namespace apache { -namespace thrift { -namespace concurrency { - -/** - * The C++11 thread class. - * - * Note that we use boost shared_ptr rather than std shared_ptrs here - * because the Thread/Runnable classes use those and we don't want to - * mix them. - * - * @version $Id:$ - */ -class StdThread : public Thread, public std::enable_shared_from_this { -public: - enum STATE { uninitialized, starting, started, stopping, stopped }; - - static void threadMain(std::shared_ptr thread); - -private: - std::unique_ptr thread_; - Monitor monitor_; - STATE state_; - bool detached_; - -public: - StdThread(bool detached, std::shared_ptr runnable) - : state_(uninitialized), detached_(detached) { - this->Thread::runnable(runnable); - } - - ~StdThread() { - if (!detached_ && thread_->joinable()) { - try { - join(); - } catch (...) { - // We're really hosed. - } - } - } - - STATE getState() const - { - Synchronized sync(monitor_); - return state_; - } - - void setState(STATE newState) - { - Synchronized sync(monitor_); - state_ = newState; - - // unblock start() with the knowledge that the thread has actually - // started running, which avoids a race in detached threads. - if (newState == started) { - monitor_.notify(); - } - } - - void start() { - if (getState() != uninitialized) { - return; - } - - std::shared_ptr selfRef = shared_from_this(); - setState(starting); - - Synchronized sync(monitor_); - thread_ = std::unique_ptr(new std::thread(threadMain, selfRef)); - - if (detached_) - thread_->detach(); - - // Wait for the thread to start and get far enough to grab everything - // that it needs from the calling context, thus absolving the caller - // from being required to hold on to runnable indefinitely. - monitor_.wait(); - } - - void join() { - if (!detached_ && state_ != uninitialized) { - thread_->join(); - } - } - - Thread::id_t getId() { return thread_.get() ? thread_->get_id() : std::thread::id(); } - - std::shared_ptr runnable() const { return Thread::runnable(); } - - void runnable(std::shared_ptr value) { Thread::runnable(value); } -}; - -void StdThread::threadMain(std::shared_ptr thread) { -#if GOOGLE_PERFTOOLS_REGISTER_THREAD - ProfilerRegisterThread(); -#endif - - thread->setState(started); - thread->runnable()->run(); - - if (thread->getState() != stopping && thread->getState() != stopped) { - thread->setState(stopping); - } -} - -StdThreadFactory::StdThreadFactory(bool detached) : ThreadFactory(detached) { -} - -std::shared_ptr StdThreadFactory::newThread(std::shared_ptr runnable) const { - std::shared_ptr result = std::shared_ptr(new StdThread(isDetached(), runnable)); - runnable->thread(result); - return result; -} - -Thread::id_t StdThreadFactory::getCurrentThreadId() const { - return std::this_thread::get_id(); -} -} -} -} // apache::thrift::concurrency - -#endif // USE_STD_THREAD diff --git a/lib/cpp/src/thrift/concurrency/StdMutex.cpp b/lib/cpp/src/thrift/concurrency/Thread.cpp similarity index 52% rename from lib/cpp/src/thrift/concurrency/StdMutex.cpp rename to lib/cpp/src/thrift/concurrency/Thread.cpp index e0f79fa37f0..a2bb1270f92 100644 --- a/lib/cpp/src/thrift/concurrency/StdMutex.cpp +++ b/lib/cpp/src/thrift/concurrency/Thread.cpp @@ -17,55 +17,21 @@ * under the License. */ -#include - -#include -#include - -#include -#include -#include +#include namespace apache { namespace thrift { namespace concurrency { -/** - * Implementation of Mutex class using C++11 std::timed_mutex - * - * Methods throw std::system_error on error. - * - * @version $Id:$ - */ -class Mutex::impl : public std::timed_mutex {}; - -Mutex::Mutex(Initializer init) : impl_(new Mutex::impl()) { - ((void)init); -} - -void* Mutex::getUnderlyingImpl() const { - return impl_.get(); -} - -void Mutex::lock() const { - impl_->lock(); -} - -bool Mutex::trylock() const { - return impl_->try_lock(); -} - -bool Mutex::timedlock(int64_t ms) const { - return impl_->try_lock_for(std::chrono::milliseconds(ms)); -} +void Thread::threadMain(std::shared_ptr thread) { + thread->setState(started); + thread->runnable()->run(); -void Mutex::unlock() const { - impl_->unlock(); + if (thread->getState() != stopping && thread->getState() != stopped) { + thread->setState(stopping); + } } -void Mutex::DEFAULT_INITIALIZER(void* arg) { - ((void)arg); -} } } } // apache::thrift::concurrency diff --git a/lib/cpp/src/thrift/concurrency/Thread.h b/lib/cpp/src/thrift/concurrency/Thread.h index b2ea4e2975b..729d11a48e3 100644 --- a/lib/cpp/src/thrift/concurrency/Thread.h +++ b/lib/cpp/src/thrift/concurrency/Thread.h @@ -22,16 +22,10 @@ #include #include +#include #include - -#if USE_STD_THREAD -#include -#else -#ifdef HAVE_PTHREAD_H -#include -#endif -#endif +#include namespace apache { namespace thrift { @@ -75,94 +69,106 @@ class Runnable { * * @see apache::thrift::concurrency::ThreadFactory) */ -class Thread { +class Thread final : public std::enable_shared_from_this { public: -#if USE_STD_THREAD typedef std::thread::id id_t; + enum STATE { uninitialized, starting, started, stopping, stopped }; + + static void threadMain(std::shared_ptr thread); + static inline bool is_current(id_t t) { return t == std::this_thread::get_id(); } static inline id_t get_current() { return std::this_thread::get_id(); } -#else - typedef pthread_t id_t; - - static inline bool is_current(id_t t) { return pthread_equal(pthread_self(), t); } - static inline id_t get_current() { return pthread_self(); } -#endif - virtual ~Thread(){}; + Thread(bool detached, std::shared_ptr runnable) + : state_(uninitialized), detached_(detached) { + this->_runnable = runnable; + } + + ~Thread() { + if (!detached_ && thread_->joinable()) { + try { + join(); + } catch (...) { + // We're really hosed. + } + } + } + + STATE getState() const + { + Synchronized sync(monitor_); + return state_; + } + + void setState(STATE newState) + { + Synchronized sync(monitor_); + state_ = newState; + + // unblock start() with the knowledge that the thread has actually + // started running, which avoids a race in detached threads. + if (newState == started) { + monitor_.notify(); + } + } /** * Starts the thread. Does platform specific thread creation and * configuration then invokes the run method of the Runnable object bound * to this thread. */ - virtual void start() = 0; + void start() { + if (getState() != uninitialized) { + return; + } + + std::shared_ptr selfRef = shared_from_this(); + setState(starting); + + Synchronized sync(monitor_); + thread_ = std::unique_ptr(new std::thread(threadMain, selfRef)); + + if (detached_) + thread_->detach(); + + // Wait for the thread to start and get far enough to grab everything + // that it needs from the calling context, thus absolving the caller + // from being required to hold on to runnable indefinitely. + monitor_.wait(); + } /** * Join this thread. If this thread is joinable, the calling thread blocks * until this thread completes. If the target thread is not joinable, then * nothing happens. */ - virtual void join() = 0; + void join() { + if (!detached_ && state_ != uninitialized) { + thread_->join(); + } + } /** * Gets the thread's platform-specific ID */ - virtual id_t getId() = 0; + Thread::id_t getId() { return thread_.get() ? thread_->get_id() : std::thread::id(); } /** * Gets the runnable object this thread is hosting */ - virtual std::shared_ptr runnable() const { return _runnable; } - -protected: - virtual void runnable(std::shared_ptr value) { _runnable = value; } + std::shared_ptr runnable() const { return _runnable; } private: std::shared_ptr _runnable; -}; - -/** - * Factory to create platform-specific thread object and bind them to Runnable - * object for execution - */ -class ThreadFactory { -protected: - ThreadFactory(bool detached) : detached_(detached) { } - -public: - virtual ~ThreadFactory() { } - - /** - * Gets current detached mode - */ - bool isDetached() const { return detached_; } - - /** - * Sets the detached disposition of newly created threads. - */ - void setDetached(bool detached) { detached_ = detached; } - - /** - * Create a new thread. - */ - virtual std::shared_ptr newThread(std::shared_ptr runnable) const = 0; - - /** - * Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread - */ - virtual Thread::id_t getCurrentThreadId() const = 0; - - /** - * For code readability define the unknown/undefined thread id - */ - static const Thread::id_t unknown_thread_id; - -private: + std::unique_ptr thread_; + Monitor monitor_; + STATE state_; bool detached_; }; + } } } // apache::thrift::concurrency diff --git a/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h b/lib/cpp/src/thrift/concurrency/ThreadFactory.cpp similarity index 64% rename from lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h rename to lib/cpp/src/thrift/concurrency/ThreadFactory.cpp index 99b44033b3c..941b993712b 100644 --- a/lib/cpp/src/thrift/concurrency/PlatformThreadFactory.h +++ b/lib/cpp/src/thrift/concurrency/ThreadFactory.cpp @@ -17,32 +17,24 @@ * under the License. */ -#ifndef _THRIFT_CONCURRENCY_PLATFORMTHREADFACTORY_H_ -#define _THRIFT_CONCURRENCY_PLATFORMTHREADFACTORY_H_ 1 - -// clang-format off #include -#if USE_STD_THREAD -# include -#else -# include -#endif -// clang-format on + +#include +#include namespace apache { namespace thrift { namespace concurrency { -// clang-format off -#if USE_STD_THREAD - typedef StdThreadFactory PlatformThreadFactory; -#else - typedef PosixThreadFactory PlatformThreadFactory; -#endif -// clang-format on +std::shared_ptr ThreadFactory::newThread(std::shared_ptr runnable) const { + std::shared_ptr result = std::shared_ptr(new Thread(isDetached(), runnable)); + runnable->thread(result); + return result; +} +Thread::id_t ThreadFactory::getCurrentThreadId() const { + return std::this_thread::get_id(); +} } } } // apache::thrift::concurrency - -#endif // #ifndef _THRIFT_CONCURRENCY_PLATFORMTHREADFACTORY_H_ diff --git a/lib/cpp/src/thrift/concurrency/StdThreadFactory.h b/lib/cpp/src/thrift/concurrency/ThreadFactory.h similarity index 59% rename from lib/cpp/src/thrift/concurrency/StdThreadFactory.h rename to lib/cpp/src/thrift/concurrency/ThreadFactory.h index e74046b7b30..f317afcde78 100644 --- a/lib/cpp/src/thrift/concurrency/StdThreadFactory.h +++ b/lib/cpp/src/thrift/concurrency/ThreadFactory.h @@ -17,45 +17,65 @@ * under the License. */ -#ifndef _THRIFT_CONCURRENCY_STDTHREADFACTORY_H_ -#define _THRIFT_CONCURRENCY_STDTHREADFACTORY_H_ 1 +#ifndef _THRIFT_CONCURRENCY_THREADFACTORY_H_ +#define _THRIFT_CONCURRENCY_THREADFACTORY_H_ 1 #include #include - namespace apache { namespace thrift { namespace concurrency { /** - * A thread factory to create std::threads. - * - * @version $Id:$ + * Factory to create thread object and bind them to Runnable + * object for execution */ -class StdThreadFactory : public ThreadFactory { - +class ThreadFactory final { public: /** - * Std thread factory. All threads created by a factory are reference-counted + * All threads created by a factory are reference-counted * via std::shared_ptr. The factory guarantees that threads and the Runnable tasks * they host will be properly cleaned up once the last strong reference * to both is given up. * * By default threads are not joinable. */ + ThreadFactory(bool detached = true) : detached_(detached) { } - StdThreadFactory(bool detached = true); + ~ThreadFactory() = default; + + /** + * Gets current detached mode + */ + bool isDetached() const { return detached_; } + + /** + * Sets the detached disposition of newly created threads. + */ + void setDetached(bool detached) { detached_ = detached; } - // From ThreadFactory; + /** + * Create a new thread. + */ std::shared_ptr newThread(std::shared_ptr runnable) const; - // From ThreadFactory; + /** + * Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread + */ Thread::id_t getCurrentThreadId() const; + + /** + * For code readability define the unknown/undefined thread id + */ + static const Thread::id_t unknown_thread_id; + +private: + bool detached_; }; } } } // apache::thrift::concurrency -#endif // #ifndef _THRIFT_CONCURRENCY_STDTHREADFACTORY_H_ +#endif // #ifndef _THRIFT_CONCURRENCY_THREADFACTORY_H_ diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.h b/lib/cpp/src/thrift/concurrency/ThreadManager.h index 470fc0aaea3..4b4b3d49188 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadManager.h +++ b/lib/cpp/src/thrift/concurrency/ThreadManager.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include namespace apache { namespace thrift { diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.h b/lib/cpp/src/thrift/concurrency/TimerManager.h index ba792264c53..4d73b002db5 100644 --- a/lib/cpp/src/thrift/concurrency/TimerManager.h +++ b/lib/cpp/src/thrift/concurrency/TimerManager.h @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.cpp b/lib/cpp/src/thrift/server/TNonblockingServer.cpp index f16fce78986..31ff2a96a49 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.cpp +++ b/lib/cpp/src/thrift/server/TNonblockingServer.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include @@ -1118,12 +1118,7 @@ void TNonblockingServer::registerEvents(event_base* user_event_base) { // Launch all the secondary IO threads in separate threads if (ioThreads_.size() > 1) { - ioThreadFactory_.reset(new PlatformThreadFactory( -#if !USE_STD_THREAD - PlatformThreadFactory::OTHER, // scheduler - PlatformThreadFactory::NORMAL, // priority - 1, // stack size (MB) -#endif + ioThreadFactory_.reset(new ThreadFactory( false // detached )); diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.h b/lib/cpp/src/thrift/server/TNonblockingServer.h index e79c24f6236..2c2389c3c1f 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.h +++ b/lib/cpp/src/thrift/server/TNonblockingServer.h @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -53,7 +53,7 @@ using apache::thrift::transport::TNonblockingServerTransport; using apache::thrift::protocol::TProtocol; using apache::thrift::concurrency::Runnable; using apache::thrift::concurrency::ThreadManager; -using apache::thrift::concurrency::PlatformThreadFactory; +using apache::thrift::concurrency::ThreadFactory; using apache::thrift::concurrency::ThreadFactory; using apache::thrift::concurrency::Thread; using apache::thrift::concurrency::Mutex; @@ -166,7 +166,7 @@ class TNonblockingServer : public TServer { bool threadPoolProcessing_; // Factory to create the IO threads - std::shared_ptr ioThreadFactory_; + std::shared_ptr ioThreadFactory_; // Vector of IOThread objects that will handle our IO std::vector > ioThreads_; @@ -386,9 +386,7 @@ class TNonblockingServer : public TServer { /** * Sets the number of IO threads used by this server. Can only be used before - * the call to serve() and has no effect afterwards. We always use a - * PosixThreadFactory for the IO worker threads, because they must joinable - * for clean shutdown. + * the call to serve() and has no effect afterwards. */ void setNumIOThreads(size_t numThreads) { numIOThreads_ = numThreads; diff --git a/lib/cpp/src/thrift/server/TThreadedServer.cpp b/lib/cpp/src/thrift/server/TThreadedServer.cpp index 2264df79b33..ed2d80d000e 100644 --- a/lib/cpp/src/thrift/server/TThreadedServer.cpp +++ b/lib/cpp/src/thrift/server/TThreadedServer.cpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include namespace apache { diff --git a/lib/cpp/src/thrift/server/TThreadedServer.h b/lib/cpp/src/thrift/server/TThreadedServer.h index c5ccd03c8d2..9fc9d1125b5 100644 --- a/lib/cpp/src/thrift/server/TThreadedServer.h +++ b/lib/cpp/src/thrift/server/TThreadedServer.h @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include @@ -44,7 +44,7 @@ class TThreadedServer : public TServerFramework { const std::shared_ptr& protocolFactory, const std::shared_ptr& threadFactory = std::shared_ptr( - new apache::thrift::concurrency::PlatformThreadFactory(false))); + new apache::thrift::concurrency::ThreadFactory(false))); TThreadedServer( const std::shared_ptr& processor, @@ -53,7 +53,7 @@ class TThreadedServer : public TServerFramework { const std::shared_ptr& protocolFactory, const std::shared_ptr& threadFactory = std::shared_ptr( - new apache::thrift::concurrency::PlatformThreadFactory(false))); + new apache::thrift::concurrency::ThreadFactory(false))); TThreadedServer( const std::shared_ptr& processorFactory, @@ -64,7 +64,7 @@ class TThreadedServer : public TServerFramework { const std::shared_ptr& outputProtocolFactory, const std::shared_ptr& threadFactory = std::shared_ptr( - new apache::thrift::concurrency::PlatformThreadFactory(false))); + new apache::thrift::concurrency::ThreadFactory(false))); TThreadedServer( const std::shared_ptr& processor, @@ -75,7 +75,7 @@ class TThreadedServer : public TServerFramework { const std::shared_ptr& outputProtocolFactory, const std::shared_ptr& threadFactory = std::shared_ptr( - new apache::thrift::concurrency::PlatformThreadFactory(false))); + new apache::thrift::concurrency::ThreadFactory(false))); virtual ~TThreadedServer(); diff --git a/lib/cpp/src/thrift/transport/TFileTransport.h b/lib/cpp/src/thrift/transport/TFileTransport.h index 6cc7bd24b01..ece271aae4d 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.h +++ b/lib/cpp/src/thrift/transport/TFileTransport.h @@ -30,7 +30,7 @@ #include #include -#include +#include #include namespace apache { @@ -336,7 +336,7 @@ class TFileTransport : public TFileReaderTransport, public TFileWriterTransport static const uint32_t DEFAULT_WRITER_THREAD_SLEEP_TIME_US = 60 * 1000 * 1000; // writer thread - apache::thrift::concurrency::PlatformThreadFactory threadFactory_; + apache::thrift::concurrency::ThreadFactory threadFactory_; std::shared_ptr writerThread_; // buffers to hold data before it is flushed. Each element of the buffer stores a msg that diff --git a/lib/cpp/src/thrift/windows/config.h b/lib/cpp/src/thrift/windows/config.h index a5f44577d8a..14a3f4f3691 100644 --- a/lib/cpp/src/thrift/windows/config.h +++ b/lib/cpp/src/thrift/windows/config.h @@ -28,11 +28,6 @@ #error "This is a Windows header only" #endif -// use std::thread in MSVC11 (2012) or newer and in MinGW -#if (_MSC_VER >= 1700) || defined(__MINGW32__) -#define USE_STD_THREAD 1 -#endif - // Something that defines PRId64 is required to build #define HAVE_INTTYPES_H 1 diff --git a/lib/cpp/test/CMakeLists.txt b/lib/cpp/test/CMakeLists.txt index b30ef1780b9..8a8aadad10d 100644 --- a/lib/cpp/test/CMakeLists.txt +++ b/lib/cpp/test/CMakeLists.txt @@ -84,11 +84,6 @@ set(UnitTest_SOURCES TServerTransportTest.cpp ) -if(NOT WITH_STDTHREADS AND NOT MSVC AND NOT MINGW) - list(APPEND UnitTest_SOURCES concurrency/MutexTest.cpp) - list(APPEND UnitTest_SOURCES concurrency/RWMutexStarveTest.cpp) -endif() - add_executable(UnitTests ${UnitTest_SOURCES}) target_link_libraries(UnitTests testgencpp ${Boost_LIBRARIES}) LINK_AGAINST_THRIFT_LIBRARY(UnitTests thrift) diff --git a/lib/cpp/test/Makefile.am b/lib/cpp/test/Makefile.am index d645a6501ab..5bb9eb76029 100755 --- a/lib/cpp/test/Makefile.am +++ b/lib/cpp/test/Makefile.am @@ -135,10 +135,6 @@ UnitTests_SOURCES = \ TServerTransportTest.cpp \ TTransportCheckThrow.h -UnitTests_SOURCES += \ - concurrency/MutexTest.cpp \ - concurrency/RWMutexStarveTest.cpp - UnitTests_LDADD = \ libtestgencpp.la \ $(BOOST_TEST_LDADD) \ diff --git a/lib/cpp/test/TNonblockingSSLServerTest.cpp b/lib/cpp/test/TNonblockingSSLServerTest.cpp index 330380b3486..2111de8b0cb 100644 --- a/lib/cpp/test/TNonblockingSSLServerTest.cpp +++ b/lib/cpp/test/TNonblockingSSLServerTest.cpp @@ -218,12 +218,7 @@ class Fixture { runner->userEventBase = userEventBase_; std::unique_ptr threadFactory( - new apache::thrift::concurrency::PlatformThreadFactory( -#if !USE_STD_THREAD - concurrency::PlatformThreadFactory::OTHER, concurrency::PlatformThreadFactory::NORMAL, - 1, -#endif - false)); + new apache::thrift::concurrency::ThreadFactory(false)); thread = threadFactory->newThread(runner); thread->start(); runner->readyBarrier(); diff --git a/lib/cpp/test/TNonblockingServerTest.cpp b/lib/cpp/test/TNonblockingServerTest.cpp index f0bb283ff7b..f2f59220376 100644 --- a/lib/cpp/test/TNonblockingServerTest.cpp +++ b/lib/cpp/test/TNonblockingServerTest.cpp @@ -33,7 +33,7 @@ using apache::thrift::concurrency::Guard; using apache::thrift::concurrency::Monitor; using apache::thrift::concurrency::Mutex; -using apache::thrift::concurrency::PlatformThreadFactory; +using apache::thrift::concurrency::ThreadFactory; using apache::thrift::concurrency::Runnable; using apache::thrift::concurrency::Thread; using apache::thrift::concurrency::ThreadFactory; @@ -147,12 +147,7 @@ class Fixture { runner->userEventBase = userEventBase_; shared_ptr threadFactory( - new PlatformThreadFactory( -#if !USE_STD_THREAD - PlatformThreadFactory::OTHER, PlatformThreadFactory::NORMAL, - 1, -#endif - false)); + new ThreadFactory(false)); thread = threadFactory->newThread(runner); thread->start(); runner->readyBarrier(); diff --git a/lib/cpp/test/TServerIntegrationTest.cpp b/lib/cpp/test/TServerIntegrationTest.cpp index 7976c8bcf60..a7680d89e0e 100644 --- a/lib/cpp/test/TServerIntegrationTest.cpp +++ b/lib/cpp/test/TServerIntegrationTest.cpp @@ -379,7 +379,7 @@ BOOST_FIXTURE_TEST_CASE(test_threadpool_factory, TServerIntegrationProcessorFactoryTestFixture) { pServer->getThreadManager()->threadFactory( shared_ptr( - new apache::thrift::concurrency::PlatformThreadFactory)); + new apache::thrift::concurrency::ThreadFactory)); pServer->getThreadManager()->start(); // thread factory has 4 threads as a default @@ -394,7 +394,7 @@ BOOST_FIXTURE_TEST_CASE(test_threadpool, TServerIntegrationProcessorTestFixture) { pServer->getThreadManager()->threadFactory( shared_ptr( - new apache::thrift::concurrency::PlatformThreadFactory)); + new apache::thrift::concurrency::ThreadFactory)); pServer->getThreadManager()->start(); // thread factory has 4 threads as a default @@ -409,7 +409,7 @@ BOOST_FIXTURE_TEST_CASE(test_threadpool_bound, TServerIntegrationProcessorTestFixture) { pServer->getThreadManager()->threadFactory( shared_ptr( - new apache::thrift::concurrency::PlatformThreadFactory)); + new apache::thrift::concurrency::ThreadFactory)); pServer->getThreadManager()->start(); pServer->setConcurrentClientLimit(4); @@ -420,7 +420,7 @@ BOOST_FIXTURE_TEST_CASE(test_threadpool_stress, TServerIntegrationProcessorTestFixture) { pServer->getThreadManager()->threadFactory( shared_ptr( - new apache::thrift::concurrency::PlatformThreadFactory)); + new apache::thrift::concurrency::ThreadFactory)); pServer->getThreadManager()->start(); stress(10, boost::posix_time::seconds(3)); diff --git a/lib/cpp/test/TransportTest.cpp b/lib/cpp/test/TransportTest.cpp index ce1954469c6..387207142b4 100644 --- a/lib/cpp/test/TransportTest.cpp +++ b/lib/cpp/test/TransportTest.cpp @@ -1031,7 +1031,7 @@ struct global_fixture { apache::thrift::transport::TWinsockSingleton::create(); #endif - apache::thrift::concurrency::PlatformThreadFactory factory; + apache::thrift::concurrency::ThreadFactory factory; factory.setDetached(false); alarmThread_ = factory.newThread( diff --git a/lib/cpp/test/concurrency/MutexTest.cpp b/lib/cpp/test/concurrency/MutexTest.cpp deleted file mode 100644 index 781ec1a4072..00000000000 --- a/lib/cpp/test/concurrency/MutexTest.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// This is linked into the UnitTests test executable - -#include - -#include "thrift/concurrency/Exception.h" -#include "thrift/concurrency/Mutex.h" - -using boost::unit_test::test_suite; -using boost::unit_test::framework::master_test_suite; - -using namespace apache::thrift::concurrency; - -struct LFAT -{ - LFAT() - : uut(Mutex::ERRORCHECK_INITIALIZER) - { - BOOST_CHECK_EQUAL(0, pthread_mutex_init(&mx, 0)); - BOOST_CHECK_EQUAL(0, pthread_cond_init(&cv, 0)); - } - - Mutex uut; - pthread_mutex_t mx; - pthread_cond_t cv; -}; - -// Helper for testing mutex behavior when locked by another thread -void * lockFromAnotherThread(void *ptr) -{ - struct LFAT *lfat = (LFAT *)ptr; - BOOST_CHECK_EQUAL (0, pthread_mutex_lock(&lfat->mx)); // synchronize with testing thread - BOOST_CHECK_NO_THROW( lfat->uut.lock()); - BOOST_CHECK_EQUAL (0, pthread_cond_signal(&lfat->cv)); // tell testing thread we have locked the mutex - BOOST_CHECK_EQUAL (0, pthread_cond_wait(&lfat->cv, &lfat->mx)); // wait for testing thread to signal condition variable telling us to unlock - BOOST_CHECK_NO_THROW( lfat->uut.unlock()); - return ptr; // testing thread should join to ensure completeness -} - -BOOST_AUTO_TEST_SUITE(MutexTest) - -BOOST_AUTO_TEST_CASE(happy_path) -{ - Mutex uut(Mutex::ERRORCHECK_INITIALIZER); // needed to test unlocking twice without undefined behavior - - BOOST_CHECK_NO_THROW( uut.lock()); - BOOST_CHECK_THROW ( uut.lock(), SystemResourceException); // EDEADLK (this thread owns it) - BOOST_CHECK_NO_THROW( uut.unlock()); -} - -BOOST_AUTO_TEST_CASE(recursive_happy_path) -{ - Mutex uut(Mutex::RECURSIVE_INITIALIZER); - - BOOST_CHECK_NO_THROW( uut.lock()); - BOOST_CHECK_NO_THROW( uut.lock()); - BOOST_CHECK_NO_THROW( uut.unlock()); - BOOST_CHECK_NO_THROW( uut.lock()); - BOOST_CHECK_NO_THROW( uut.lock()); - BOOST_CHECK_NO_THROW( uut.unlock()); - BOOST_CHECK_NO_THROW( uut.lock()); - BOOST_CHECK_NO_THROW( uut.unlock()); - BOOST_CHECK_NO_THROW( uut.unlock()); - BOOST_CHECK_NO_THROW( uut.unlock()); -} - -BOOST_AUTO_TEST_CASE(trylock) -{ - Mutex uut(Mutex::ADAPTIVE_INITIALIZER); // just using another initializer for coverage - - BOOST_CHECK ( uut.trylock()); - BOOST_CHECK (!uut.trylock()); - BOOST_CHECK_NO_THROW( uut.unlock()); -} - -BOOST_AUTO_TEST_CASE(timedlock) -{ - pthread_t th; - struct LFAT lfat; - - BOOST_CHECK ( lfat.uut.timedlock(100)); - BOOST_CHECK_THROW ( lfat.uut.timedlock(100), - SystemResourceException); // EDEADLK (current thread owns mutex - logic error) - BOOST_CHECK_NO_THROW( lfat.uut.unlock()); - - BOOST_CHECK_EQUAL (0, pthread_mutex_lock(&lfat.mx)); // synchronize with helper thread - BOOST_CHECK_EQUAL (0, pthread_create(&th, NULL, - lockFromAnotherThread, &lfat)); // create helper thread - BOOST_CHECK_EQUAL (0, pthread_cond_wait(&lfat.cv, &lfat.mx)); // wait for helper thread to lock mutex - - BOOST_CHECK (!lfat.uut.timedlock(100)); // false: another thread owns the lock - - BOOST_CHECK_EQUAL (0, pthread_cond_signal(&lfat.cv)); // tell helper thread we are done - BOOST_CHECK_EQUAL (0, pthread_mutex_unlock(&lfat.mx)); // let helper thread clean up - BOOST_CHECK_EQUAL (0, pthread_join(th, 0)); // wait for testing thread to unlock and be done -} - -BOOST_AUTO_TEST_CASE(underlying) -{ - Mutex uut; - - BOOST_CHECK ( uut.getUnderlyingImpl()); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/lib/cpp/test/concurrency/RWMutexStarveTest.cpp b/lib/cpp/test/concurrency/RWMutexStarveTest.cpp deleted file mode 100644 index 985a230a05f..00000000000 --- a/lib/cpp/test/concurrency/RWMutexStarveTest.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// This is linked into the UnitTests test executable - -#include - -#include "thrift/concurrency/Mutex.h" -#include "thrift/concurrency/PosixThreadFactory.h" -#include - -using std::shared_ptr; -using boost::unit_test::test_suite; -using boost::unit_test::framework::master_test_suite; - -using namespace apache::thrift::concurrency; - -class Locker : public Runnable { -protected: - Locker(shared_ptr rwlock, bool writer) - : rwlock_(rwlock), writer_(writer), started_(false), gotLock_(false), signaled_(false) {} - -public: - virtual void run() { - started_ = true; - if (writer_) { - rwlock_->acquireWrite(); - } else { - rwlock_->acquireRead(); - } - gotLock_ = true; - while (!signaled_) { - usleep(5000); - } - rwlock_->release(); - } - - bool started() const { return started_; } - bool gotLock() const { return gotLock_; } - void signal() { signaled_ = true; } - -protected: - shared_ptr rwlock_; - bool writer_; - volatile bool started_; - volatile bool gotLock_; - volatile bool signaled_; -}; - -class Reader : public Locker { -public: - Reader(shared_ptr rwlock) : Locker(rwlock, false) {} -}; - -class Writer : public Locker { -public: - Writer(shared_ptr rwlock) : Locker(rwlock, true) {} -}; - -void test_starve(PosixThreadFactory::POLICY policy) { - // the man pages for pthread_wrlock_rdlock suggest that any OS guarantee about - // writer starvation may be influenced by the scheduling policy, so let's try - // all 3 policies to see if any of them work. - PosixThreadFactory factory(policy); - factory.setDetached(false); - - shared_ptr rwlock(new NoStarveReadWriteMutex()); - - shared_ptr reader1(new Reader(rwlock)); - shared_ptr reader2(new Reader(rwlock)); - shared_ptr writer(new Writer(rwlock)); - - shared_ptr treader1 = factory.newThread(reader1); - shared_ptr treader2 = factory.newThread(reader2); - shared_ptr twriter = factory.newThread(writer); - - // launch a reader and make sure he has the lock - treader1->start(); - while (!reader1->gotLock()) { - usleep(2000); - } - - // launch a writer and make sure he's blocked on the lock - twriter->start(); - while (!writer->started()) { - usleep(2000); - } - // tricky part... we can never be 100% sure that the writer is actually - // blocked on the lock, but we can pretty reasonably sure because we know - // he just executed the line immediately before getting the lock, and - // we'll wait a full second for him to get on it. - sleep(1); - - // launch a second reader... if the RWMutex guarantees that writers won't - // starve, this reader should not be able to acquire the lock until the writer - // has acquired and released it. - treader2->start(); - while (!reader2->started()) { - usleep(2000); - } - // again... can't be 100% sure the reader is waiting on (or has) the lock - // but we can be close. - sleep(1); - - // tell reader 1 to let go of the lock - reader1->signal(); - - // wait for someone to get the lock - while (!reader2->gotLock() && !writer->gotLock()) { - usleep(2000); - } - - // the test succeeded if the WRITER got the lock. - bool success = writer->gotLock(); - - // tell everyone we're done and wait for them to finish - reader2->signal(); - writer->signal(); - treader1->join(); - treader2->join(); - twriter->join(); - - // make sure it worked. - BOOST_CHECK_MESSAGE(success, "writer is starving"); -} - -BOOST_AUTO_TEST_SUITE(RWMutexStarveTest) - -BOOST_AUTO_TEST_CASE(test_starve_other) { - test_starve(PosixThreadFactory::OTHER); -} - -BOOST_AUTO_TEST_CASE(test_starve_rr) { - test_starve(PosixThreadFactory::ROUND_ROBIN); -} - -BOOST_AUTO_TEST_CASE(test_starve_fifo) { - test_starve(PosixThreadFactory::FIFO); -} - -BOOST_AUTO_TEST_SUITE_END() diff --git a/lib/cpp/test/concurrency/ThreadFactoryTests.h b/lib/cpp/test/concurrency/ThreadFactoryTests.h index ba9850286cb..8ab754c8980 100644 --- a/lib/cpp/test/concurrency/ThreadFactoryTests.h +++ b/lib/cpp/test/concurrency/ThreadFactoryTests.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include @@ -66,7 +66,7 @@ class ThreadFactoryTests { bool reapNThreads(int loop = 1, int count = 10) { - PlatformThreadFactory threadFactory = PlatformThreadFactory(); + ThreadFactory threadFactory = ThreadFactory(); shared_ptr monitor(new Monitor); for (int lix = 0; lix < loop; lix++) { @@ -159,7 +159,7 @@ class ThreadFactoryTests { shared_ptr task = shared_ptr(new SynchStartTask(monitor, state)); - PlatformThreadFactory threadFactory = PlatformThreadFactory(); + ThreadFactory threadFactory = ThreadFactory(); shared_ptr thread = threadFactory.newThread(task); @@ -265,7 +265,7 @@ class ThreadFactoryTests { Monitor& _mon; }; - void foo(PlatformThreadFactory* tf) { (void)tf; } + void foo(ThreadFactory* tf) { (void)tf; } bool floodNTest(size_t loop = 1, size_t count = 100000) { @@ -274,7 +274,7 @@ class ThreadFactoryTests { for (size_t lix = 0; lix < loop; lix++) { - PlatformThreadFactory threadFactory = PlatformThreadFactory(); + ThreadFactory threadFactory = ThreadFactory(); threadFactory.setDetached(true); for (size_t tix = 0; tix < count; tix++) { diff --git a/lib/cpp/test/concurrency/ThreadManagerTests.h b/lib/cpp/test/concurrency/ThreadManagerTests.h index d6c092d6cc5..b3a319a5710 100644 --- a/lib/cpp/test/concurrency/ThreadManagerTests.h +++ b/lib/cpp/test/concurrency/ThreadManagerTests.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -108,12 +108,9 @@ class ThreadManagerTests { shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workerCount); - shared_ptr threadFactory - = shared_ptr(new PlatformThreadFactory(false)); + shared_ptr threadFactory + = shared_ptr(new ThreadFactory(false)); -#if !USE_STD_THREAD - threadFactory->setPriority(PosixThreadFactory::HIGHEST); -#endif threadManager->threadFactory(threadFactory); threadManager->start(); @@ -257,12 +254,9 @@ class ThreadManagerTests { shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workerCount, pendingTaskMaxCount); - shared_ptr threadFactory - = shared_ptr(new PlatformThreadFactory()); + shared_ptr threadFactory + = shared_ptr(new ThreadFactory()); -#if !USE_STD_THREAD - threadFactory->setPriority(PosixThreadFactory::HIGHEST); -#endif threadManager->threadFactory(threadFactory); threadManager->start(); @@ -401,54 +395,15 @@ class ThreadManagerTests { return false; } -#if !USE_STD_THREAD - // test once with a detached thread factory and once with a joinable thread factory - - shared_ptr threadFactory - = shared_ptr(new PosixThreadFactory(false)); - - std::cout << "\t\t\tapiTest with joinable thread factory" << std::endl; - if (!apiTestWithThreadFactory(threadFactory)) { - return false; - } - - threadFactory.reset(new PosixThreadFactory(true)); - std::cout << "\t\t\tapiTest with detached thread factory" << std::endl; - return apiTestWithThreadFactory(threadFactory); -#else - return apiTestWithThreadFactory(shared_ptr(new PlatformThreadFactory())); -#endif + return apiTestWithThreadFactory(shared_ptr(new ThreadFactory())); } - bool apiTestWithThreadFactory(shared_ptr threadFactory) + bool apiTestWithThreadFactory(shared_ptr threadFactory) { shared_ptr threadManager = ThreadManager::newSimpleThreadManager(1); threadManager->threadFactory(threadFactory); -#if !USE_STD_THREAD - threadFactory->setPriority(PosixThreadFactory::HIGHEST); - - // verify we cannot change the thread factory to one with the opposite detached setting - shared_ptr threadFactory2 - = shared_ptr(new PlatformThreadFactory( - PosixThreadFactory::ROUND_ROBIN, - PosixThreadFactory::NORMAL, - 1, - !threadFactory->isDetached())); - try { - threadManager->threadFactory(threadFactory2); - // if the call succeeded we changed the thread factory to one that had the opposite setting for "isDetached()". - // this is bad, because the thread manager checks with the thread factory to see if it should join threads - // as they are leaving - so the detached status of new threads cannot change while there are existing threads. - std::cerr << "\t\t\tShould not be able to change thread factory detached disposition" << std::endl; - return false; - } - catch (InvalidArgumentException& ex) { - /* expected */ - } -#endif - std::cout << "\t\t\t\tstarting.. " << std::endl; threadManager->start(); diff --git a/lib/cpp/test/concurrency/TimerManagerTests.h b/lib/cpp/test/concurrency/TimerManagerTests.h index 1c52c470b54..c15b14b8099 100644 --- a/lib/cpp/test/concurrency/TimerManagerTests.h +++ b/lib/cpp/test/concurrency/TimerManagerTests.h @@ -18,7 +18,7 @@ */ #include -#include +#include #include #include @@ -80,7 +80,7 @@ class TimerManagerTests { { TimerManager timerManager; - timerManager.threadFactory(shared_ptr(new PlatformThreadFactory())); + timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); if (timerManager.state() != TimerManager::STARTED) { std::cerr << "timerManager is not in the STARTED state, but should be" << std::endl; @@ -125,7 +125,7 @@ class TimerManagerTests { */ bool test01(int64_t timeout = 1000LL) { TimerManager timerManager; - timerManager.threadFactory(shared_ptr(new PlatformThreadFactory())); + timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); assert(timerManager.state() == TimerManager::STARTED); @@ -158,7 +158,7 @@ class TimerManagerTests { */ bool test02(int64_t timeout = 1000LL) { TimerManager timerManager; - timerManager.threadFactory(shared_ptr(new PlatformThreadFactory())); + timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); assert(timerManager.state() == TimerManager::STARTED); @@ -191,7 +191,7 @@ class TimerManagerTests { */ bool test03(int64_t timeout = 1000LL) { TimerManager timerManager; - timerManager.threadFactory(shared_ptr(new PlatformThreadFactory())); + timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); assert(timerManager.state() == TimerManager::STARTED); @@ -228,7 +228,7 @@ class TimerManagerTests { */ bool test04(int64_t timeout = 1000LL) { TimerManager timerManager; - timerManager.threadFactory(shared_ptr(new PlatformThreadFactory())); + timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); assert(timerManager.state() == TimerManager::STARTED); diff --git a/lib/cpp/test/processor/ProcessorTest.cpp b/lib/cpp/test/processor/ProcessorTest.cpp index 36ce0131190..9483a0e913d 100644 --- a/lib/cpp/test/processor/ProcessorTest.cpp +++ b/lib/cpp/test/processor/ProcessorTest.cpp @@ -25,7 +25,7 @@ #include -#include +#include #include #include #include @@ -94,7 +94,7 @@ class TThreadPoolServerTraits { const std::shared_ptr& protocolFactory) { std::shared_ptr socket(new TServerSocket(port)); - std::shared_ptr threadFactory(new PlatformThreadFactory); + std::shared_ptr threadFactory(new ThreadFactory); std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(8); threadManager->threadFactory(threadFactory); threadManager->start(); @@ -123,7 +123,7 @@ class TNonblockingServerTraits { } std::shared_ptr socket(new TNonblockingServerSocket(port)); - std::shared_ptr threadFactory(new PlatformThreadFactory); + std::shared_ptr threadFactory(new ThreadFactory); std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(8); threadManager->threadFactory(threadFactory); threadManager->start(); diff --git a/lib/cpp/test/processor/ServerThread.cpp b/lib/cpp/test/processor/ServerThread.cpp index 4d1ec4c1dbc..b0505005be1 100644 --- a/lib/cpp/test/processor/ServerThread.cpp +++ b/lib/cpp/test/processor/ServerThread.cpp @@ -21,7 +21,7 @@ #include "ServerThread.h" -#include +#include #include #include #include @@ -38,7 +38,7 @@ void ServerThread::start() { helper_.reset(new Helper(this)); // Start the other thread - concurrency::PlatformThreadFactory threadFactory; + concurrency::ThreadFactory threadFactory; threadFactory.setDetached(false); thread_ = threadFactory.newThread(helper_); diff --git a/test/cpp/src/StressTest.cpp b/test/cpp/src/StressTest.cpp index 585f89a9e27..f4c281c7f72 100644 --- a/test/cpp/src/StressTest.cpp +++ b/test/cpp/src/StressTest.cpp @@ -18,7 +18,7 @@ */ #include -#include +#include #include #include #include @@ -390,8 +390,8 @@ int main(int argc, char** argv) { cerr << usage.str(); } - std::shared_ptr threadFactory - = std::shared_ptr(new PlatformThreadFactory()); + std::shared_ptr threadFactory + = std::shared_ptr(new ThreadFactory()); // Dispatcher std::shared_ptr serviceHandler(new Server()); diff --git a/test/cpp/src/StressTestNonBlocking.cpp b/test/cpp/src/StressTestNonBlocking.cpp index 1d3ed732bca..5f0b293b9b3 100644 --- a/test/cpp/src/StressTestNonBlocking.cpp +++ b/test/cpp/src/StressTestNonBlocking.cpp @@ -18,7 +18,7 @@ */ #include -#include +#include #include #include #include @@ -343,8 +343,8 @@ int main(int argc, char** argv) { cerr << usage.str(); } - std::shared_ptr threadFactory - = std::shared_ptr(new PlatformThreadFactory()); + std::shared_ptr threadFactory + = std::shared_ptr(new ThreadFactory()); // Dispatcher std::shared_ptr serviceHandler(new Server()); diff --git a/test/cpp/src/TestServer.cpp b/test/cpp/src/TestServer.cpp index 622201766f6..410662819fc 100644 --- a/test/cpp/src/TestServer.cpp +++ b/test/cpp/src/TestServer.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include #include @@ -770,8 +770,8 @@ int main(int argc, char** argv) { server.reset(new TSimpleServer(testProcessor, serverSocket, transportFactory, protocolFactory)); } else if (server_type == "thread-pool") { - std::shared_ptr threadFactory - = std::shared_ptr(new PlatformThreadFactory()); + std::shared_ptr threadFactory + = std::shared_ptr(new ThreadFactory()); std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workers); threadManager->threadFactory(threadFactory); @@ -817,7 +817,7 @@ int main(int argc, char** argv) { server->setOutputProtocolFactory(std::shared_ptr()); } - apache::thrift::concurrency::PlatformThreadFactory factory; + apache::thrift::concurrency::ThreadFactory factory; factory.setDetached(false); std::shared_ptr serverThreadRunner(server); std::shared_ptr thread diff --git a/test/threads/ThreadsClient.cpp b/test/threads/ThreadsClient.cpp index 9306a3f2528..e8bd79e697e 100644 --- a/test/threads/ThreadsClient.cpp +++ b/test/threads/ThreadsClient.cpp @@ -27,7 +27,7 @@ #include #include #include -#include +#include #if _WIN32 #include #endif diff --git a/test/threads/ThreadsServer.cpp b/test/threads/ThreadsServer.cpp index a267c3b90c4..3811b60c5eb 100644 --- a/test/threads/ThreadsServer.cpp +++ b/test/threads/ThreadsServer.cpp @@ -28,7 +28,7 @@ #include #include #include -#include +#include #if _WIN32 #include #endif @@ -118,8 +118,8 @@ int main(int argc, char **argv) { /* shared_ptr threadManager = ThreadManager::newSimpleThreadManager(10); - shared_ptr threadFactory = - shared_ptr(new PlatformThreadFactory()); + shared_ptr threadFactory = + shared_ptr(new ThreadFactory()); threadManager->threadFactory(threadFactory); threadManager->start(); diff --git a/tutorial/cpp/CppServer.cpp b/tutorial/cpp/CppServer.cpp index f7379d5368b..3b5ce4012bf 100644 --- a/tutorial/cpp/CppServer.cpp +++ b/tutorial/cpp/CppServer.cpp @@ -18,7 +18,7 @@ */ #include -#include +#include #include #include #include @@ -160,7 +160,7 @@ int main() { std::shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workerCount); threadManager->threadFactory( - std::make_shared()); + std::make_shared()); threadManager->start(); // This server allows "workerCount" connection at a time, and reuses threads From cc19bf1d7b5a32ed345e31c5634ac4d1e2b1d86e Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 7 Jan 2019 17:31:00 -0500 Subject: [PATCH 130/756] THRIFT-4697: Add release management docs to GitHub [ci skip] --- doc/ReleaseManagement.md | 395 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 395 insertions(+) create mode 100644 doc/ReleaseManagement.md diff --git a/doc/ReleaseManagement.md b/doc/ReleaseManagement.md new file mode 100644 index 00000000000..a7b2369d155 --- /dev/null +++ b/doc/ReleaseManagement.md @@ -0,0 +1,395 @@ +# Apache Thrift Release Management + +Instructions for preparing and distributing a release of Apache Thrift are fairly complex. These procedures are documented here, and we're working to automate as much of this as possible. There are few projects like ours that integrate with 28 programming languages. Given the extreme number of package management systems that Apache Thrift integrates with (compared to perhaps any), part of the burden of releasing Apache Thrift is to manually package and upload some of these [language-specific packages](http://apache.thrift.org/libraries). + +It is important to note here that Apache Thrift is designed for version interoperability, so one can use a version 0.7.0 client with a 0.12.0 server. A particular version number does not make any guarantees as to the features available in any given language. See the [Language Feature Matrix](https://github.com/apache/thrift/blob/master/LANGUAGES.md) to learn more. + +## Concepts + +### Versioning + +Apache Thrift and the vast majority of package management systems out there conform to the [SemVer 2.0](https://semver.org/spec/v2.0.0.html) version numbering specification. + +In terms of releases, the important version numbers for Apache Thrift are the major and minor. The patch number is used in the following cases: + +1. There were language-specific critical defects or packaging issues. +1. There was something horribly and fundamentally wrong with a x.x.0 release. + +#### External Package Patches + +It is common to have language-specific critical defects or packaging errors that need to be resolved between releases of Apache Thrift. The project handles these on a case-by-case basis for languages that have their own [package management systems](http://apache.thrift.org/libraries). When a language-specific patch is made, the patch level of the distribution pushed to the external package manager is bumped. + + As such, there may be cases between Apache Thrift releases where there are (for example) a `0.12.1` and `0.12.2` version of a Haskell Hackage package, and perhaps also a `0.12.3` version of a dlang dub package. You will not find a tag or an official project release in these cases, however the code changes will be reflected in the release branch and in master. In these cases we would not release a version of Apache Thrift nor would we refresh all the external language packages. + +#### Version in the master branch + +The master branch will always contain the next anticipated release version. When a release cycle begins, a branch is cut from master. The release branch will already have all of the correct versions, and therefore release branches can be easily merged back into master. (This was not true of releases before 0.12.0). + +### Code Repository + +The authoritative repository for Apache Thrift is stored in [GitHub](https://github.com/apache/thrift). It is mirrored by [GitBox](https://gitbox.apache.org/repos/asf?p=thrift.git). + +### Branches + +All code (submitted via pull request or direct push) is committed to the `master` branch. Until version 1.0 of Apache Thrift each release branch was named ``, for example in version `0.12.0` there is a branch named the same. For version 1.0 releases any beyond, releases will have a branch named `release/`. + +### Tags + +Up to version `0.12.0` each release of Apache Thrift was tagged with a `` tag. Starting with the `0.12.0` release, each release of Apache Thrift will be tagged with a `v` tag to satisfy external package management tools (such as ones for dlang and golang). For example the tag of version `0.12.0` is `v0.12.0`. + +## Release Procedures + +### Release Schedule + +Apache Thrift has no official release schedule, however the project aims to release at least twice per year. + +A complete release cycle will take about 1 week to complete, if things go well, with half of that time waiting for a vote. + +### Release Manager + +Before a release cycle begins, someone must nominate themselves on the development mailing list as the release manager for that release. In order to be a release manager you must meet the following criteria: + +1. You are a [member](http://people.apache.org/phonebook.html?pmc=thrift) of the Apache PMC group. +1. Your profile at https://id.apache.org/ is valid and contains a PGP key. If it does not, see the [Apache OpenPGP Instructions](https://www.apache.org/dev/openpgp.html). If your PGP private key creation seems to hang indefinitely while creating entropy, try these fixes: + - Generate disk I/O with: `dd if=/dev/sda of=/dev/zero` + - Install the `rng-tools` package. +1. Your PGP key is visible in the [Apache Committer Keys](http://people.apache.org/keys/committer/) for code signing. This list is updated periodically from your Apache ID (see previous step). +1. You have read and agree with the contents of the [ASF Release Distribution Policy](https://www.apache.org/dev/release-distribution.html). +1. You have access and the ability to use subversion. All distribution artifacts are released through a subversion commit. +1. You can build in the Linux Docker Container, and you have Visual Studio 2017. +1. You have sufficient time to complete a release distribution. + +### Release Candidate + +All Apache Thrift releases go through a 72-hour final release candidate voting procedure. Votes from members of the Apache Thrift PMC are binding, and all others are non-binding. For these examples, the `master` branch is at version 1.0.0 and that is the next release. + +1. Scrub the Apache Jira backlog. There are a couple things to do: + + 1. [Open Issues without a Component](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20THRIFT%20and%20status%20!%3D%20Closed%20and%20component%20is%20empty) - make sure everything has an assigned component, as the release notes are grouped together by language. + + 1. [Open Issues with a Fix Version](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20THRIFT%20and%20status%20in%20(OPEN%2C%20%27IN%20PROGRESS%27%2C%20REOPENED)%20and%20fixVersion%20is%20not%20empty) - these will be issues that someone placed a fixVersion on in Jira, but have not been resolved or closed yet. They are likely stale somehow. Resolutions for these issues include resolving or closing the issue in Jira, or simply removing the fixVersion if the issue hasn't been fixed. + + 1. [Open Blocking Issues](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20THRIFT%20and%20priority%20in%20(blocker)%20and%20status%20not%20in%20(closed)%20order%20by%20component%20ASC) - blocking issues should block a release. Scrub the list to see if they are really blocking the release, and if not change their priority. + + 1. [Open Critical Issues](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20THRIFT%20and%20priority%20in%20(critical)%20and%20status%20not%20in%20(closed)%20and%20type%20not%20in%20(%22wish%22)%20order%20by%20component%20ASC) - this list will end up in the known critical issues list in the changes file. Scrub it to make sure everything is actually critical. + + It is healthy to scrub these periodically, whether or not you are making a new release. + +1. Check that the version number in the `master` branch matches the version number of the upcomning release. To check the `master` branch version, run: + + ```bash + thrift$ grep AC_INIT configure.ac | cut -d'[' -f3 | cut -d']' -f1 + 1.0.0 + ``` + + If it does not match (this should be extremely rare), you need to submit a pull request setting the `master` branch to the desired version of the upcoming release. In the following example, we prepare to commit a branch where the version number is changed from `1.0.0` to `1.1.0`: + + ```bash + thrift$ git checkout -b fix-version-for-release + thrift$ build/veralign.sh 1.0.0 1.1.0 + # check to see if any of the manually modified files needs changes + thrift$ git push ... # make a pull request + ``` + +1. Create a release branch for the release, in this example `1.0.0`: + + ```bash + thrift$ git checkout master + thrift$ git pull + thrift$ git checkout -b "release/1.0.0" + thrift$ git push + ``` + + Now there is a `release/1.0.0` branch in GitHub for Apache Thrift. + + By creating a release branch we allow work to continue on the `master` branch for the next release while we finalize this one. Note that `release/1.0.0` and `master` in this example are now identical, and therefore it is possible to merge the release branch back into `master` at the end of the release! + +1. Modify these files manually, inserting the release into them at the appropriate location. Follow existing patterns in each file: + - `doap.rdf` + - `debian/changelog` + +1. Generate the content for `CHANGES.md` - this is one of the most time-consuming parts of the release cycle. It is a lot of work, but the result is well worth it to the consumers of Apache Thrift: + + 1. Find all [Issues Fixed but not Closed in 1.0.0](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20thrift%20and%20fixVersion%20%3D%201.0.0%20and%20status%20!%3D%20closed) (adjust the version in the link to suit your needs). + + 1. Export the list of issues to a CSV (Current Fields) and open in Excel (or a similar spreadsheet). + + 1. Hide all columns except for the issue id (i.e. THRIFT-nnnn), the component (first one), and the summary. + + 1. Sort by component ascending and then by id ascending. + + 1. Create a fourth column that will contain the contents of each line that goes into the release notes. Once you have the formula working in one cell paste it into the other rows to populate them. Use a formula to get the column to look like this: + + ```vcol + Issue Component Summary RelNote + THRIFT-123 C++ - Library Drop C++03 [THRIFT-123](https://issues.apache.org/jira/browse/THRIFT-3978) - Drop C++03 + ``` + + For example, if the row above was row "B" in EXCEL it would look something like: + + ```text + =CONCAT("[", B1, "]", + "https://issues.apache.org/jira/browse/", + B1, " - ", B3) + ``` + + 1. Create a level 3 section in `CHANGES.md` under the release for each component and copy the items from the RelNote column into the changes file. + + 1. Find all [Open Critical Issues](https://issues.apache.org/jira/issues/?filter=-1&jql=project%20%3D%20THRIFT%20and%20priority%20in%20(critical)%20and%20status%20not%20in%20(closed)%20and%20type%20not%20in%20(%22wish%22)%20order%20by%20component%20ASC) and add them to `CHANGES.md` in the list of known critical issues for the release. + +1. Commit all changes to the release branch. + +1. Generate the source tarball. + + 1. On a linux system get a clean copy of the release branch, for example: + + ```bash + ~$ git clone -b "release/1.0.0" git@github.com:apache/thrift.git thrift-1.0.0-src + ``` + + 1. In the clean copy of the release branch, start a docker build container and run `make dist`: + + ```code + ~$ cd thrift-1.0.0-src + ~/thrift-1.0.0-src$ docker run -v $(pwd):/thrift/src:rw \ + -it thrift/thrift-build:ubuntu-bionic /bin/bash + root@8b4101188aa2:/thrift/src# ./bootstrap.sh && ./configure && make dist + ``` + + The result will be a file named `thrift-1.0.0.tar.gz`. Check the size and make sure it is roughly 4MB. It could get larger over time, but it shouldn't jump by orders of magnitude. Once satisfied you can exit the docker container with `exit`. + + 1. Generate signatures and checksums for the tarball: + + ```bash + gpg --armor --output thrift-1.0.0.tar.gz.asc --detach-sig thrift-1.0.0.tar.gz + md5sum thrift-1.0.0.tar.gz > thrift-1.0.0.tar.gz.md5 + sha1sum thrift-1.0.0.tar.gz > thrift-1.0.0.tar.gz.sha1 + sha256sum thrift-1.0.0.tar.gz > thrift-1.0.0.tar.gz.sha256 + +1. Generate the Windows Thrift Compiler. This is a statically linked compiler that is portable and folks find it useful to be able to download one, especially if they are using third-party distributed runtime libraries for interpreted languages on Windows. There are two ways to generate this: + + - Using a Development VM + + 1. On a Windows machine with Visual Studio, pull down the source code and checkout the release branch. + 1. Open an x64 Native Tools Command Prompt for VS 2017 and create an out-of-tree build directory. + 1. Install the latest version of cmake. + 1. Install chocolatey and install winflexbison with chocolatey. + 1. Run cmake to generate an out-of-tree build environment: + ```cmd + C:\build> cmake ..\thrift -DBISON_EXECUTABLE=c:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe -DFLEX_EXECUTABLE=c:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe -DWITH_MT=ON -DWITH_SHARED_LIB=OFF -DWITH_CPP=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TUTORIALS=OFF -DBUILD_COMPILER=ON + C:\build> cmake --build . --config Release + ``` + + - Using [Docker for Windows](../build/docker/msvc2017/README.md), follow the instructions for building the compiler. + - In both cases: + 1. Verify the executable only depends on kernel32.dll using [depends.exe](http://www.dependencywalker.com/). + 1. Copy the executable `thrift.exe` to your linux system where the signed tarball lives and rename it to `thrift-1.0.0.exe` (substitute the correct version, of course). + 1. Sign the executable the same way you signed the tarball. + +1. Upload the release artifacts to the Apache Dist/Dev site. This requires subversion: + + ```bash + ~$ mkdir -p dist/dev + ~$ cd dist/dev + ~/dist/dev$ svn co "https://dist.apache.org/repos/dist/dev/thrift" thrift + ~/dist/dev$ cd thrift + ``` + + Copy the tarball, windows compiler executable, and 8 additional signing files into a new directory for the release: + + ``` bash + ~/dist/dev/thrift$ mkdir 1.0.0-rc0 + # copy the files into the directory + ~/dist/dev/thrift$ svn add 1.0.0-rc0 + ``` + + The layout of the files should match the [current release](https://www.apache.org/dist/thrift/). Once done, add the release candidate and check it in: + + ```bash + ~/dist/dev/thrift$ svn status + # verify everything is correct + ~/dist/dev/thrift$ svn add 1.0.0-rc0 -m "apache thrift 1.0.0-rc0 in dist dev" \ + --username --password + ``` + +1. Verify the release candidate artifacts are available at: + + [https://dist.apache.org/repos/dist/dev/thrift/](https://dist.apache.org/repos/dist/dev/thrift/) + +1. Send a voting announcement message to `dev@thrift.apache.org` following this template as a guide: + + ```code + To: dev@thrift.apache.org + Subject: [VOTE] Apache Thrift 1.0.0-rc0 release candidate + --- + All, + + I propose that we accept the following release candidate as the official Apache Thrift 1.0.0 release: + + https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.tar.gz + + The release candidate was created from the release/1.0.0 branch and can be cloned using: + + git clone -b release/1.0.0 https://github.com/apache/thrift.git + + The release candidates GPG signature can be found at: + https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.tar.gz.asc + + The release candidates checksums are: + md5: + sha1: + sha256: + + + A prebuilt statically-linked Windows compiler is available at: + https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.exe + + Prebuilt statically-linked Windows compiler GPG signature: + https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.exe.asc + + Prebuilt statically-linked Windows compiler checksums are: + md5: + sha1: + sha256: + + The CHANGES list for this release is available at: + https://github.com/apache/thrift/blob/release/1.0.0/CHANGES.md + + + Please download, verify sig/sum, install and test the libraries and languages of your choice. + + This vote will close in 72 hours on 2019-07-06 21:00 UTC + + [ ] +1 Release this as Apache Thrift 1.0.0 + [ ] +0 + [ ] -1 Do not release this as Apache Thrift 1.0.0 because... + ``` + +1. If any issues are brought up with the release candidate, you will need to package another and reset the voting clock. + +### Official Release + +1. Send a message to `dev@thrift.apache.org` with the voting results. Use this template as a guide: + + ```code + To: dev~thrift.apache.org + Subject: [VOTE][RESULT] Release Apache Thrift 1.0.0 + --- + All, + + Including my own vote of +1 we have N binding +1 and no -1. + The vote for the Apache Thrift 1.0.0 release is ***successful***. + Thank you to all who helped test and verify. + ``` + +1. Use svn to checkout the release part of thrift (similar to dev) and copy the files over from dev, matching the previous release structure: + + ```bash + ~$ mkdir -p dist/release + ~$ cd dist/release + ~/dist/release$ svn co "https://dist.apache.org/repos/dist/release/thrift" thrift + ~/dist/release$ cd thrift + ~/dist/release/thrift$ mkdir 1.0.0 + ~/dist/release/thrift$ cp -p ../../dev/thrift/1.0.0-rc0/* 1.0.0/ + ~/dist/release/thrift$ svn status + # verify everything is correct + ~/dist/release/thrift$ svn add 1.0.0 -m "Apache Thrift 1.0.0 official release" \ + --username --password + ``` + + **NOTE** One you check in, you need to wait about a day for all the mirrors to update. You cannot send the announcement email or update the web site until the mirrors are updated. + +1. Create and push a tag for the release, for example "v1.0.0". + + **NOTE:** All new releases must have the "v" prefix to satisfy third party package managers (dlang dub, golang, etc..) + + ```bash + ~/thrift$ # make sure you are on the release branch + ~/thrift$ git checkout release/1.0.0 + ~/thrift$ git pull + ~/thrift$ git tag v1.0.0 + ~/thrift$ git push --tags + ``` + +1. Create a new release from the [GitHub Tags Page](https://github.com/apache/thrift/tags). Attach the statically built Windows thrift compiler as a binary here. + +1. Merge the release branch into master. This ensures all changes made to fix up the release are in master. + + ```bash + ~/thrift$ git checkout master + ~/thrift$ git pull + ~/thrift$ git merge release/1.0.0 + ``` + + The merge of 1.0.0 into master should proceed as a fast-forward since the 1.0.0 release branch. If there are discrepancies the best thing to do is resolve them and then submit a pull request. This pull request must be *MERGED* and not *REBASED* after the CI build is successful. You may want to do this yourself and mark the pull request as `[DO NOT MERGE]`. + +1. Update the ASF CMS content for thrift to include the new release. Note over time we will retire this in favor of including all documentation in the GitHub repository. The page with the variables that are important like the current release or distribution links is in trunk/lib/path.pm in the ASF CMS for thrift. + + 1. Go to the [ASF CMS for Thrift](https://cms.apache.org/thrift/). + 1. Get a working copy. + 1. On the top right, click on `trunk`. + 1. Navigate into `lib`. + 1. Open `path.pm`. + 1. Edit + 1. Change `current_release` and `current_release_date` to reflect the correct information. + 1. Submit + 1. Commit + 1. Submit + 1. Follow Staging Build until it completes. + 1. Open the Staged site. + 1. Ensure the download links work. + 1. Publish Site. + +1. Make an announcement on the dev@ and user@ mailing lists of the release. There's no template to follow, but you can point folks to the official web site at https://thrift.apache.org, and to the GitHub site at https://github.org/apache.thrift. + +### Post-Release + +1. Visit https://reporter.apache.org/addrelease.html?thrift and register it. You will get an automated reminder as the one who committed into dist. This informs the Apache Board of Directors of releases through project reports. + +1. Create a local branch to bump the release number to the next anticipated release: + + ```bash + ~/thrift$ git checkout -b bump-master + ~/thrift$ build/veralign.sh 1.0.0 1.1.0 + ``` + + The veralign script will set the version number in all of the language packaging files and headers. You do not need to worry about the manually modified files at this time. You should however ensure everything is correct by looking at the diff. + +1. Create a pull request to advance master to the next anticipated release. + +1. In Apache Jira, select all tickets where the fix version is the release and the status is not closed ([example](https://issues.apache.org/jira/issues/?jql=project%20%3D%20THRIFT%20AND%20fixVersion%20%3D%201.0%20%20and%20status%20!%3D%20Closed)) and use the bulk editing tool to close them. +1. **FIXME** Ask someone with admin access to Apache Jira to change the fixVersion in question from unreleased to released, for example: + https://issues.apache.org/jira/browse/THRIFT-4686 + +1. Ensure that the [Jira release page](https://issues.apache.org/jira/projects/THRIFT?selectedItem=com.atlassian.jira.jira-projects-plugin%3Arelease-page&status=unreleased) for the version has the same number of issues in the version as issues done, and that there are no issues in progress and no issues to do, and no warnings. + +* [Report any CVEs](https://apache.org/security/committers.html) that were fixed. You can email `security@apache.org` if you are not sure if there are any CVEs to report. + +#### Third Party Package Managers + +See https://thrift.apache.org/lib/ for the current status of each external package manager's distribution. Information below is from the 0.12.0 release: + +* [dart] Releasing this requires a google account. + * You will need to install the same version of dart that is used in the docker image. + * Go into lib/dart and run "pub publish --dry-run" and resolve any warnings. + * Run "pub publish" and go through the google account authorization to allow it. +* [dlang] Within a day, the dlang dub site https://code.dlang.org/packages/apache-thrift?tab=info + should pick up the release based on the tag. No action needed. +* [haskell] https://hackage.haskell.org/package/thrift + https://jira.apache.org/jira/browse/THRIFT-4698 +* [npmjs] @jfarrell is the only one who can do this right now. + https://issues.apache.org/jira/browse/THRIFT-4688 +* [perl] A submission to CPAN is necessary (normally jeking3 does this): + * Checkout the release branch or tag on a linux system. + * Fire up the docker build container. + * Run "make clean" and remove any gen-perl directories. + * Inside `lib/perl` run the script `build-cpan-dist.sh`. + * Upload the resulting package. If there's a mistake that needs to be corrected, + increase the suffix. (_1, _2, ...) and upload another. You cannot replace a release on CPAN. +* [php] @jfarrell, @bufferoverflow, @jeking3 are the only ones who can do this right now. + * Once the release is tagged, one just has to hit the "Update" button to pick it up. +* [pypi] @jfarrell is the only one who can do this right now. + https://issues.apache.org/jira/browse/THRIFT-4687 +* [rust] Any thrift project committer is allowed to upload a new crate. + +If you have any questions email `dev@thrift.apache.org`. \ No newline at end of file From d7c11ada8857e834ebdba9af71344c6c0425207d Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 11 Jan 2019 19:19:44 -0500 Subject: [PATCH 131/756] Fix swift version [ci skip] --- build/veralign.sh | 1 + lib/swift/Sources/Thrift.swift | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build/veralign.sh b/build/veralign.sh index 491ef36b546..b9c1e71bfbe 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -84,6 +84,7 @@ FILES[lib/py/setup.py]=simpleReplace FILES[lib/rb/thrift.gemspec]=simpleReplace FILES[lib/rs/Cargo.toml]=simpleReplace FILES[lib/st/package.xml]=simpleReplace +FILES[lib/swift/Sources/Thrift.swift]=simpleReplace FILES[package.json]=jsonReplace FILES[sonar-project.properties]=simpleReplace FILES[test/csharp/Properties/AssemblyInfo.cs]=simpleReplace diff --git a/lib/swift/Sources/Thrift.swift b/lib/swift/Sources/Thrift.swift index 5bd1758090f..4898c77e775 100644 --- a/lib/swift/Sources/Thrift.swift +++ b/lib/swift/Sources/Thrift.swift @@ -1,3 +1,3 @@ class Thrift { - let version = "1.1.0" + let version = "1.0.0" } From 91854f0b30aba0b6c1d41297bb101e72081a1bf4 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 11 Jan 2019 19:20:37 -0500 Subject: [PATCH 132/756] THRIFT-4597: update Jira links on right side of languages.md [ci skip] --- LANGUAGES.md | 67 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/LANGUAGES.md b/LANGUAGES.md index 5c3290990f2..12e735ad3df 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -42,7 +42,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes Yes -ActionScript +ActionScript C (glib) @@ -53,7 +53,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes YesYesYes Yes -C (glib) +C (glib) C++ @@ -64,7 +64,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYesYes YesYesYesYes YesYesYesYes -C++ +C++ C# @@ -75,7 +75,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYesYes YesYesYes -C# (.NET) +C# (.NET) Cocoa @@ -86,10 +86,10 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYes Yes -Cocoa +Cocoa -Common Lisp +Common LISP 0.12.0 Yes SBCL 1.4.5SBCL 1.4.15 @@ -97,7 +97,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes YesYesYes Yes -Common Lisp +Common LISP Dlang @@ -108,7 +108,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYesYes YesYesYes YesYesYesYes -D +D Dart @@ -119,7 +119,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYesYes -Dart +Dart Delphi @@ -130,7 +130,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYesYes Yes -Delphi +Delphi .NET Core @@ -141,7 +141,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYesYes Yes -.NET Core +.NET Core Erlang @@ -152,7 +152,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYesYes Yes -Erlang +Erlang Go @@ -163,7 +163,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYesYes YesYesYesYes Yes -Go +Go Haskell @@ -174,7 +174,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYes YesYes -Haskell +Haskell Haxe @@ -185,7 +185,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYesYes Yes -Haxe +Haxe Java (SE) @@ -196,7 +196,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYesYes YesYesYesYes YesYesYesYes -Java SE +Java SE Java (ME) @@ -207,7 +207,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes YesYes -Java ME +Java ME Javascript @@ -218,7 +218,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes YesYes -Javascript +Javascript Lua @@ -229,7 +229,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYes Yes -Lua +Lua node.js @@ -240,7 +240,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYesYes Yes -node.js +node.js node.ts @@ -251,7 +251,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes Yes -node.ts +node.ts OCaml @@ -262,7 +262,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes Yes YesYes -OCaml +OCaml Perl @@ -273,7 +273,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYes YesYes -Perl +Perl PHP @@ -284,7 +284,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYesYes YesYes -PHP +PHP Python @@ -295,7 +295,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYesYes YesYesYes -Python +Python Ruby @@ -306,7 +306,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes YesYesYesYes YesYesYesYes -Ruby +Ruby Rust @@ -317,7 +317,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes YesYesYes Yes -Rust +Rust Smalltalk @@ -328,7 +328,18 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes -Smalltalk +Smalltalk + + +Cocoa +0.12.0 +Yes +4.2.1 +YesYesYesYes +YesYes +YesYesYes +Yes +Swift From 76ee393d20044f7bf930611cf8fc370acb8e9e1a Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 11 Jan 2019 19:24:39 -0500 Subject: [PATCH 133/756] THRIFT-4597: fix swift language info in languages.md [ci skip] --- LANGUAGES.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/LANGUAGES.md b/LANGUAGES.md index 12e735ad3df..4b5e200167d 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -331,9 +331,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Smalltalk -Cocoa +Swift 0.12.0 -Yes +Yes 4.2.1 YesYesYesYes YesYes @@ -363,4 +363,5 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Servers - + From 278528cf7b1dd5dd977bce882aa126fac8695697 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 11 Jan 2019 12:17:44 -0500 Subject: [PATCH 134/756] THRIFT-4732: windows cmake refinements and add windows docker build support --- CMakeLists.txt | 2 +- appveyor.yml | 7 + build/appveyor/CYGW-appveyor-build.bat | 4 +- build/appveyor/MING-appveyor-build.bat | 4 +- build/appveyor/MSVC-appveyor-build.bat | 6 +- build/appveyor/cl_setenv.bat | 23 +- build/cmake/DefineOptions.cmake | 50 ++-- build/cmake/DefinePlatformSpecifc.cmake | 25 +- build/cmake/README.md | 46 ++-- build/cmake/ThriftMacros.cmake | 76 +----- build/docker/msvc2017/Dockerfile | 96 ++++++++ build/docker/msvc2017/README.md | 50 ++++ build/docker/msvc2017/build-compiler.bat | 44 ++++ build/docker/msvc2017/build.bat | 44 ++++ build/wincpp/README.md | 219 ------------------ build/wincpp/build-thrift-compiler.bat | 79 ------- build/wincpp/build-thrift.bat | 163 ------------- build/wincpp/scripts/cl_setarch.bat | 47 ---- build/wincpp/scripts/cl_setcompiler.bat | 58 ----- build/wincpp/scripts/cl_setgenerator.bat | 69 ------ build/wincpp/scripts/tpversions.bat | 24 -- .../wincpp/thirdparty/src/build-libevent.bat | 86 ------- build/wincpp/thirdparty/src/build-openssl.bat | 106 --------- build/wincpp/thirdparty/src/build-zlib.bat | 75 ------ compiler/cpp/CMakeLists.txt | 52 ++--- compiler/cpp/test/CMakeLists.txt | 30 +-- lib/cpp/CMakeLists.txt | 2 +- lib/cpp/README.md | 9 +- lib/cpp/src/thrift/TOutput.cpp | 2 + lib/cpp/src/thrift/TOutput.h | 2 +- lib/cpp/src/thrift/protocol/TJSONProtocol.cpp | 4 +- 31 files changed, 384 insertions(+), 1120 deletions(-) create mode 100644 build/docker/msvc2017/Dockerfile create mode 100644 build/docker/msvc2017/README.md create mode 100644 build/docker/msvc2017/build-compiler.bat create mode 100644 build/docker/msvc2017/build.bat delete mode 100644 build/wincpp/README.md delete mode 100644 build/wincpp/build-thrift-compiler.bat delete mode 100644 build/wincpp/build-thrift.bat delete mode 100644 build/wincpp/scripts/cl_setarch.bat delete mode 100644 build/wincpp/scripts/cl_setcompiler.bat delete mode 100644 build/wincpp/scripts/cl_setgenerator.bat delete mode 100644 build/wincpp/scripts/tpversions.bat delete mode 100644 build/wincpp/thirdparty/src/build-libevent.bat delete mode 100644 build/wincpp/thirdparty/src/build-openssl.bat delete mode 100644 build/wincpp/thirdparty/src/build-zlib.bat diff --git a/CMakeLists.txt b/CMakeLists.txt index e6dd5638bf1..e67916465b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ # under the License. # -cmake_minimum_required(VERSION 3.3) +cmake_minimum_required(VERSION 3.4) if(POLICY CMP0048) cmake_policy(SET CMP0048 NEW) # package version behavior added in cmake 3.0 diff --git a/appveyor.yml b/appveyor.yml index ab6f582ea61..4c0144cdcad 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,6 +23,11 @@ version: '1.0.0.{build}' shallow_clone: true +branches: + only: + - master + - /^(release/)?\d+\.\d+\.\d+$/ + os: - Visual Studio 2017 @@ -36,6 +41,7 @@ environment: - PROFILE: MSVC2017 PLATFORM: x64 CONFIGURATION: Release + BUILD_SHARED_LIBS: OFF BOOST_VERSION: 1.67.0 LIBEVENT_VERSION: 2.1.8 PYTHON_VERSION: 3.6 @@ -46,6 +52,7 @@ environment: - PROFILE: MSVC2015 PLATFORM: x86 CONFIGURATION: Release + BUILD_SHARED_LIBS: OFF BOOST_VERSION: 1.62.0 LIBEVENT_VERSION: 2.0.22 PYTHON_VERSION: 3.5 diff --git a/build/appveyor/CYGW-appveyor-build.bat b/build/appveyor/CYGW-appveyor-build.bat index 6d57ca30d2e..fbcc84b0c42 100644 --- a/build/appveyor/CYGW-appveyor-build.bat +++ b/build/appveyor/CYGW-appveyor-build.bat @@ -26,9 +26,7 @@ SET CMAKEARGS=^ -DCMAKE_CXX_EXTENSIONS=ON ^ -DCMAKE_CXX_FLAGS="-D_GNU_SOURCE" ^ -DCMAKE_CXX_STANDARD=11 ^ - -DWITH_PYTHON=OFF ^ - -DWITH_SHARED_LIB=OFF ^ - -DWITH_STATIC_LIB=ON + -DWITH_PYTHON=OFF @ECHO ON %BASH% -lc "mkdir -p %BUILDDIR% && cd %BUILDDIR% && cmake.exe %SRCDIR% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% --target install" || EXIT /B diff --git a/build/appveyor/MING-appveyor-build.bat b/build/appveyor/MING-appveyor-build.bat index b37a95a79dc..eec65f897f6 100644 --- a/build/appveyor/MING-appveyor-build.bat +++ b/build/appveyor/MING-appveyor-build.bat @@ -27,9 +27,7 @@ SET CMAKEARGS=^ -DCMAKE_C_COMPILER=/mingw%NORM_PLATFORM%/bin/gcc.exe ^ -DCMAKE_CXX_COMPILER=/mingw%NORM_PLATFORM%/bin/g++.exe ^ -DOPENSSL_ROOT_DIR=/mingw%NORM_PLATFORM% ^ - -DWITH_PYTHON=OFF ^ - -DWITH_SHARED_LIB=OFF ^ - -DWITH_STATIC_LIB=ON + -DWITH_PYTHON=OFF @ECHO ON %BASH% -lc "mkdir -p %BUILDDIR% && cd %BUILDDIR% && cmake.exe %SRCDIR% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% --target install" || EXIT /B diff --git a/build/appveyor/MSVC-appveyor-build.bat b/build/appveyor/MSVC-appveyor-build.bat index 0b7f0ef23c0..892daa17aeb 100644 --- a/build/appveyor/MSVC-appveyor-build.bat +++ b/build/appveyor/MSVC-appveyor-build.bat @@ -42,19 +42,17 @@ CD "%BUILDDIR%" || EXIT /B -DBISON_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison3\tools\win_bison.exe ^ -DBOOST_ROOT="%BOOST_ROOT%" ^ -DBOOST_LIBRARYDIR="%BOOST_LIBRARYDIR%" ^ + -DBUILD_SHARED_LIBS="%BUILD_SHARED_LIBS%" ^ -DCMAKE_BUILD_TYPE="%CONFIGURATION%" ^ -DCMAKE_INSTALL_PREFIX="%INSTDIR%" ^ -DFLEX_EXECUTABLE=C:\ProgramData\chocolatey\lib\winflexbison3\tools\win_flex.exe ^ - -DINTTYPES_ROOT="%WIN3P%\msinttypes" ^ -DLIBEVENT_ROOT="%WIN3P%\libevent-%LIBEVENT_VERSION%-stable" ^ -DOPENSSL_ROOT_DIR="%OPENSSL_ROOT%" ^ -DOPENSSL_USE_STATIC_LIBS=OFF ^ -DZLIB_LIBRARY="%WIN3P%\zlib-inst\lib\zlib%ZLIB_LIB_SUFFIX%.lib" ^ -DZLIB_ROOT="%WIN3P%\zlib-inst" ^ -DWITH_PYTHON=%WITH_PYTHON% ^ - -DWITH_%THREADMODEL%THREADS=ON ^ - -DWITH_SHARED_LIB=OFF ^ - -DWITH_STATIC_LIB=ON || EXIT /B + -DWITH_%THREADMODEL%THREADS=ON || EXIT /B @ECHO OFF cmake --build . ^ diff --git a/build/appveyor/cl_setenv.bat b/build/appveyor/cl_setenv.bat index c33366d6943..da4d4ee4fb3 100644 --- a/build/appveyor/cl_setenv.bat +++ b/build/appveyor/cl_setenv.bat @@ -107,15 +107,18 @@ IF "%PROFILE:~0,4%" == "MSVC" ( GOTO :EOF :SETUPNEWERMSVC - FOR /F "USEBACKQ TOKENS=*" %%i IN (`call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -version "[15.0,16.0)" -property installationPath`) DO ( - IF "%MSVCROOT%" == "" (SET MSVCROOT=%%i) + :: If VsDevCmd.bat has already executed, as is the case in the + :: msvc2017 docker container, skip this... + IF NOT DEFINED VSCMD_VER ( + FOR /F "USEBACKQ TOKENS=*" %%i IN (`call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -version "[15.0,16.0)" -property installationPath`) DO ( + IF "%MSVCROOT%" == "" (SET MSVCROOT=%%i) + ) + SET MSVCPLAT=x86 + IF "%PLATFORM%" == "x64" (SET MSVCPLAT=amd64) + + SET CURRENTDIR=%CD% + CALL "!MSVCROOT!\Common7\Tools\VsDevCmd.bat" -arch=!MSVCPLAT! || EXIT /B + CD %CURRENTDIR% + EXIT /B ) - SET MSVCPLAT=x86 - IF "%PLATFORM%" == "x64" (SET MSVCPLAT=amd64) - - SET CURRENTDIR=%CD% - CALL "!MSVCROOT!\Common7\Tools\VsDevCmd.bat" -arch=!MSVCPLAT! || EXIT /B - CD %CURRENTDIR% - EXIT /B - :EOF diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 9d95b7c74d8..19cb104e872 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -28,8 +28,8 @@ option(BUILD_COMPILER "Build Thrift compiler" ON) if(BUILD_COMPILER OR EXISTS ${THRIFT_COMPILER}) set(HAVE_COMPILER ON) endif() -CMAKE_DEPENDENT_OPTION(BUILD_TESTING "Build with unit tests" ON "HAVE_COMPILER" OFF) CMAKE_DEPENDENT_OPTION(BUILD_EXAMPLES "Build examples" ON "HAVE_COMPILER" OFF) +CMAKE_DEPENDENT_OPTION(BUILD_TESTING "Build with unit tests" ON "HAVE_COMPILER" OFF) CMAKE_DEPENDENT_OPTION(BUILD_TUTORIALS "Build Thrift tutorials" ON "HAVE_COMPILER" OFF) option(BUILD_LIBRARIES "Build Thrift libraries" ON) @@ -40,9 +40,7 @@ option(BUILD_LIBRARIES "Build Thrift libraries" ON) # and enables the library if all are found. This means the default is to build as # much as possible but leaving out libraries if their dependencies are not met. -option(WITH_BOOST_STATIC "Build with Boost static link library" OFF) -set(Boost_USE_STATIC_LIBS ${WITH_BOOST_STATIC}) -if (NOT WITH_BOOST_STATIC) +if (NOT Boost_USE_STATIC_LIBS) add_definitions(-DBOOST_ALL_DYN_LINK) add_definitions(-DBOOST_TEST_DYN_LINK) endif() @@ -113,7 +111,7 @@ option(WITH_PYTHON "Build Python Thrift library" ON) find_package(PythonInterp QUIET) # for Python executable find_package(PythonLibs QUIET) # for Python.h CMAKE_DEPENDENT_OPTION(BUILD_PYTHON "Build Python library" ON - "BUILD_LIBRARIES;WITH_PYTHON;PYTHONLIBS_FOUND" OFF) + "BUILD_LIBRARIES;WITH_PYTHON;PYTHONINTERP_FOUND;PYTHONLIBS_FOUND" OFF) # Haskell option(WITH_HASKELL "Build Haskell Thrift library" ON) @@ -123,22 +121,29 @@ CMAKE_DEPENDENT_OPTION(BUILD_HASKELL "Build GHC library" ON "BUILD_LIBRARIES;WITH_HASKELL;GHC_FOUND;CABAL_FOUND" OFF) # Common library options -option(WITH_SHARED_LIB "Build shared libraries" ON) -option(WITH_STATIC_LIB "Build static libraries" ON) -if (NOT WITH_SHARED_LIB AND NOT WITH_STATIC_LIB) - message(FATAL_ERROR "Cannot build with both shared and static outputs disabled!") -endif() - -#NOTE: C++ compiler options are defined in the lib/cpp/CMakeLists.txt +# https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html +# Default on Windows is static, shared mode library support needs work... +CMAKE_DEPENDENT_OPTION(BUILD_SHARED_LIBS "Build shared libraries" OFF "WIN32" ON) + +if (WITH_SHARED_LIB) + message(WARNING "WITH_SHARED_LIB is deprecated; use -DBUILD_SHARED_LIBS=ON instead") + set(BUILD_SHARED_LIBS ON) +elseif (WITH_STATIC_LIB) + if (WITH_SHARED_LIB) + message(FATAL_ERROR "Cannot build shared and static together; set BUILD_SHARED_LIBS instead.") + endif () + message(WARNING "WITH_STATIC_LIB is deprecated; use -DBUILD_SHARED_LIBS=OFF instead") + set(BUILD_SHARED_LIBS OFF) +endif () # Visual Studio only options if(MSVC) -option(WITH_MT "Build using MT instead of MD (MSVC only)" OFF) + option(WITH_MT "Build using MT instead of MD (MSVC only)" OFF) endif(MSVC) macro(MESSAGE_DEP flag summary) if(NOT ${flag}) - message(STATUS " - ${summary}") + message(STATUS " - ${summary}") endif() endmacro(MESSAGE_DEP flag summary) @@ -176,14 +181,13 @@ message(STATUS " Build Haskell library: ${BUILD_HASKELL}") MESSAGE_DEP(WITH_HASKELL "Disabled by WITH_HASKELL=OFF") MESSAGE_DEP(GHC_FOUND "GHC missing") MESSAGE_DEP(CABAL_FOUND "Cabal missing") -message(STATUS " Library features:") -message(STATUS " Build shared libraries: ${WITH_SHARED_LIB}") -message(STATUS " Build static libraries: ${WITH_STATIC_LIB}") -message(STATUS " Build with Boost static link library: ${WITH_BOOST_STATIC}") -message(STATUS " Build with libevent support: ${WITH_LIBEVENT}") -message(STATUS " Build with OpenSSL support: ${WITH_OPENSSL}") -message(STATUS " Build with Qt4 support: ${WITH_QT4}") -message(STATUS " Build with Qt5 support: ${WITH_QT5}") -message(STATUS " Build with ZLIB support: ${WITH_ZLIB}") +if (BUILD_CPP) + message(STATUS " Library features:") + message(STATUS " Build shared libraries: ${BUILD_SHARED_LIBS}") + message(STATUS " Build with libevent support: ${WITH_LIBEVENT}") + message(STATUS " Build with Qt4 support: ${WITH_QT4}") + message(STATUS " Build with Qt5 support: ${WITH_QT5}") + message(STATUS " Build with ZLIB support: ${WITH_ZLIB}") +endif () message(STATUS "----------------------------------------------------------") endmacro(PRINT_CONFIG_SUMMARY) diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index 9d7c9030cdc..ac33e2900c6 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -20,8 +20,16 @@ # Uncomment this to show some basic cmake variables about platforms # include (NewPlatformDebug) +# For Debug build types, append a "d" to the library names. +set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Set debug library postfix" FORCE) + # Visual Studio specific options if(MSVC) + # Allow for shared library builds + if(BUILD_SHARED_LIBS) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON CACHE TYPE BOOL FORCE) + endif() + #For visual studio the library naming is as following: # Dynamic libraries: # - thrift.dll for release library @@ -36,11 +44,6 @@ if(MSVC) # # the same holds for other libraries like libthriftz etc. - # For Debug build types, append a "d" to the library names. - set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Set debug library postfix" FORCE) - set(CMAKE_RELEASE_POSTFIX "" CACHE STRING "Set release library postfix" FORCE) - set(CMAKE_RELWITHDEBINFO_POSTFIX "" CACHE STRING "Set release library postfix" FORCE) - # Build using /MT option instead of /MD if the WITH_MT options is set if(WITH_MT) set(CompilerFlags @@ -56,9 +59,9 @@ if(MSVC) foreach(CompilerFlag ${CompilerFlags}) string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") endforeach() - set(STATIC_POSTFIX "mt" CACHE STRING "Set static library postfix" FORCE) + set(THRIFT_RUNTIME_POSTFIX "mt" CACHE STRING "Set static library postfix" FORCE) else(WITH_MT) - set(STATIC_POSTFIX "md" CACHE STRING "Set static library postfix" FORCE) + set(THRIFT_RUNTIME_POSTFIX "md" CACHE STRING "Set static library postfix" FORCE) endif(WITH_MT) # Disable boost auto linking pragmas - cmake includes the right files @@ -72,14 +75,6 @@ if(MSVC) add_definitions("/MP") # parallel build add_definitions("/W3") # warning level 3 - - # VS2010 does not provide inttypes which we need for "PRId64" used in many places - find_package(Inttypes) - if (Inttypes_FOUND) - include_directories(${INTTYPES_INCLUDE_DIRS}) - # OpenSSL conflicts with the definition of PRId64 unless it is defined first - add_definitions("/FIinttypes.h") - endif () elseif(UNIX) find_program( MEMORYCHECK_COMMAND valgrind ) set( MEMORYCHECK_COMMAND_OPTIONS "--gen-suppressions=all --leak-check=full" ) diff --git a/build/cmake/README.md b/build/cmake/README.md index e5c128bc36c..a0eb859bd24 100644 --- a/build/cmake/README.md +++ b/build/cmake/README.md @@ -1,6 +1,7 @@ -# Apache Thrift - CMake build +# Apache Thrift - CMake Build ## Goal + Extend Apache Thrift's *make cross* approach to the build system. Due to growing the field of operating system support, a proper executable @@ -11,12 +12,26 @@ package generation process. As nice side benefit of CMake is the generation of development environment specific soultion files. => No solution files within source tree. +## Prerequisites + +These are language-specific, however for C++ you must provide: + +- Boost +- OpenSSL + +You may optionally provide: + +- libevent +- zlib ## Usage -just do this: - mkdir cmake-build && cd cmake-build - cmake .. +To use CMake you first create an out-of-tree build directory, then use +CMake to generate a build framework, then build: + + mkdir /tmp/build + cd /tmp/build + cmake /location/to/thrift if you use a specific toolchain pass it to cmake, the same for options: @@ -25,13 +40,6 @@ if you use a specific toolchain pass it to cmake, the same for options: cmake -DTHRIFT_COMPILER_HS=OFF .. cmake -DWITH_ZLIB=ON .. -or on Windows - - cmake -G "Visual Studio 12 2013 Win64" \ - -DBOOST_ROOT=C:/3rdparty/boost_1_58_0 \ - -DZLIB_ROOT=C:/3rdparty/zlib128-dll \ - -DWITH_SHARED_LIB=off .. - and open the development environment you like with the solution or do this: make @@ -39,15 +47,25 @@ and open the development environment you like with the solution or do this: make cross make dist -to generate an installer and distribution package do this: +or on Windows, the following will produce a solution file you can use +inside Visual Studio: + + cmake -G "Visual Studio 15 2017 Win64" \ + -DBOOST_ROOT=C:/3rdparty/boost_1_69_0 \ + -DBOOST_LIBRARYDIR=C:/3rdparty/boost_1_69_0/lib64-msvc-14.1^ + -DZLIB_ROOT=C:/3rdparty/zlib-1.2.11 + + ## TODO + * git hash or tag based versioning depending on source state * build tutorial * build test -* with/without language lib// * enable/disable * make cross * make dist (create an alias to make package_source) @@ -57,4 +75,4 @@ to generate an installer and distribution package do this: * libthrift * tutorial * test -* merge into /README.md +* merge into /README.md \ No newline at end of file diff --git a/build/cmake/ThriftMacros.cmake b/build/cmake/ThriftMacros.cmake index f837f9482f4..366719fbb93 100644 --- a/build/cmake/ThriftMacros.cmake +++ b/build/cmake/ThriftMacros.cmake @@ -17,89 +17,31 @@ # under the License. # - -set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Set debug library postfix" FORCE) - - macro(ADD_LIBRARY_THRIFT name) - -if(WITH_SHARED_LIB) - add_library(${name} SHARED ${ARGN}) + add_library(${name} ${ARGN}) set_target_properties(${name} PROPERTIES - OUTPUT_NAME ${name} - VERSION ${thrift_VERSION} - SOVERSION ${thrift_VERSION} ) - #set_target_properties(${name} PROPERTIES PUBLIC_HEADER "${thriftcpp_HEADERS}") + OUTPUT_NAME ${name}${THRIFT_RUNTIME_POSTFIX} # windows link variants (/MT, /MD, /MTd, /MDd) get different names + VERSION ${thrift_VERSION} ) + # set_target_properties(${name} PROPERTIES PUBLIC_HEADER "${thriftcpp_HEADERS}") install(TARGETS ${name} RUNTIME DESTINATION "${BIN_INSTALL_DIR}" LIBRARY DESTINATION "${LIB_INSTALL_DIR}" ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" PUBLIC_HEADER DESTINATION "${INCLUDE_INSTALL_DIR}") -endif() - -if(WITH_STATIC_LIB) - add_library(${name}_static STATIC ${ARGN}) - set_target_properties(${name}_static PROPERTIES - OUTPUT_NAME ${name}${STATIC_POSTFIX} - VERSION ${thrift_VERSION} - SOVERSION ${thrift_VERSION} ) - install(TARGETS ${name}_static - RUNTIME DESTINATION "${BIN_INSTALL_DIR}" - LIBRARY DESTINATION "${LIB_INSTALL_DIR}" - ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" - PUBLIC_HEADER DESTINATION "${INCLUDE_INSTALL_DIR}") -endif() - -endmacro(ADD_LIBRARY_THRIFT) - +endmacro() macro(TARGET_INCLUDE_DIRECTORIES_THRIFT name) - -if(WITH_SHARED_LIB) target_include_directories(${name} ${ARGN}) -endif() - -if(WITH_STATIC_LIB) - target_include_directories(${name}_static ${ARGN}) -endif() - -endmacro(TARGET_INCLUDE_DIRECTORIES_THRIFT) - +endmacro() macro(TARGET_LINK_LIBRARIES_THRIFT name) - -if(WITH_SHARED_LIB) target_link_libraries(${name} ${ARGN}) -endif() - -if(WITH_STATIC_LIB) - target_link_libraries(${name}_static ${ARGN}) -endif() - -endmacro(TARGET_LINK_LIBRARIES_THRIFT) - +endmacro() macro(LINK_AGAINST_THRIFT_LIBRARY target libname) - -if (WITH_SHARED_LIB) target_link_libraries(${target} ${libname}) -elseif (WITH_STATIC_LIB) - target_link_libraries(${target} ${libname}_static) -else() - message(FATAL "Not linking with shared or static libraries?") -endif() - -endmacro(LINK_AGAINST_THRIFT_LIBRARY) - +endmacro() macro(TARGET_LINK_LIBRARIES_THRIFT_AGAINST_THRIFT_LIBRARY target libname) - -if(WITH_SHARED_LIB) target_link_libraries(${target} ${ARGN} ${libname}) -endif() - -if(WITH_STATIC_LIB) - target_link_libraries(${target}_static ${ARGN} ${libname}_static) -endif() - -endmacro(TARGET_LINK_LIBRARIES_THRIFT_AGAINST_THRIFT_LIBRARY) +endmacro() diff --git a/build/docker/msvc2017/Dockerfile b/build/docker/msvc2017/Dockerfile new file mode 100644 index 00000000000..7da895cb562 --- /dev/null +++ b/build/docker/msvc2017/Dockerfile @@ -0,0 +1,96 @@ +# escape=` +# +# 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. +# + +FROM microsoft/dotnet-framework:4.7.1 + +# Restore the default Windows shell for correct batch processing below. +SHELL ["cmd", "/S", "/C"] + +# Install Build Tools excluding workloads and components with known issues. +ADD https://aka.ms/vs/15/release/vs_buildtools.exe C:\TEMP\vs_buildtools.exe +RUN C:\TEMP\vs_buildtools.exe --quiet --wait --norestart --nocache ` + --installPath C:\BuildTools ` + --all ` + --remove Microsoft.VisualStudio.Component.Windows10SDK.10240 ` + --remove Microsoft.VisualStudio.Component.Windows10SDK.10586 ` + --remove Microsoft.VisualStudio.Component.Windows10SDK.14393 ` + --remove Microsoft.VisualStudio.Component.Windows81SDK ` + || IF "%ERRORLEVEL%"=="3010" EXIT 0 +RUN DEL C:\TEMP\vs_buildtools.exe + +# Install CMake +ADD https://github.com/Kitware/CMake/releases/download/v3.13.2/cmake-3.13.2-win64-x64.msi C:\TEMP\cmake.msi +RUN msiexec.exe /i C:\TEMP\cmake.msi /qn && ` + SETX PATH "%PATH%;C:\Program Files\CMake\bin" && ` + DEL C:\TEMP\cmake.msi + +# Install boost (for the thrift runtime library build) +ADD https://boost.teeks99.com/bin/1.69.0/boost_1_69_0-msvc-14.1-64.exe C:\TEMP\boost.exe +RUN C:\TEMP\boost.exe /DIR="C:\Libraries\boost_1_69_0" /SILENT && ` + DEL C:\TEMP\boost.exe + +# Install chocolatey +RUN @"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" ` + -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command ` + "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" ` + && SETX PATH "%PATH%;%ALLUSERSPROFILE%\chocolatey\bin" + +# Install winflexbison (for the thrift compiler build) +RUN choco install winflexbison3 -y + +# Install 7zip and curl (used by the libevent and zlib build scripts) +RUN choco install 7zip curl -y + +# Install libevent +COPY appveyor\build-libevent.bat C:\TEMP\build-libevent.bat +ENV LIBEVENT_VERSION=2.1.8 +ENV WIN3P=C:\TEMP\WIN3P +RUN C:\BuildTools\Common7\Tools\VsDevCmd.bat -arch=amd64 && ` + MKDIR C:\TEMP\WIN3P && ` + C:\TEMP\build-libevent.bat && ` + MKDIR C:\Libraries\libevent-%LIBEVENT_VERSION% && ` + MOVE C:\TEMP\WIN3P\libevent-%LIBEVENT_VERSION%-stable\include C:\Libraries\libevent-%LIBEVENT_VERSION% && ` + MOVE C:\TEMP\WIN3P\libevent-%LIBEVENT_VERSION%-stable\lib C:\Libraries\libevent-%LIBEVENT_VERSION% && ` + RMDIR /S /Q C:\TEMP\WIN3P + +# Install zlib +COPY appveyor\build-zlib.bat C:\TEMP\build-zlib.bat +ENV ZLIB_VERSION=1.2.11 +ENV WIN3P=C:\TEMP\WIN3P +RUN C:\BuildTools\Common7\Tools\VsDevCmd.bat -arch=amd64 && ` + MKDIR C:\TEMP\WIN3P && ` + C:\TEMP\build-zlib.bat && ` + MOVE C:\TEMP\WIN3P\zlib-inst C:\Libraries\zlib-%ZLIB_VERSION% && ` + RMDIR /S /Q C:\TEMP\WIN3P + +# Install OpenSSL 1.1.0 +ADD http://slproweb.com/download/Win64OpenSSL-1_1_0j.exe C:\TEMP\openssl.exe +RUN C:\TEMP\openssl.exe /silent && ` + DEL C:\TEMP\openssl.exe + +# Install java +RUN choco install jdk8 -y + +# Install haskell +RUN choco install ghc -y + +# Install python3 +RUN choco install python3 -y + +# Start developer command prompt with any other commands specified. +ENTRYPOINT C:\BuildTools\Common7\Tools\VsDevCmd.bat -arch=amd64 && + +# Default to PowerShell if no other command specified. +CMD ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"] \ No newline at end of file diff --git a/build/docker/msvc2017/README.md b/build/docker/msvc2017/README.md new file mode 100644 index 00000000000..0c882d74758 --- /dev/null +++ b/build/docker/msvc2017/README.md @@ -0,0 +1,50 @@ +# Building Thrift using Docker for Windows + +The build image is very large (just under 30GB) so plan accordingly. +Once Microsoft supports build tools in nano, it should get better. + +Install Docker for Windows and switch to Windows container mode. + +Pull from docker hub: + + PS C:\> docker pull thrift/thrift-build:msvc2017 + +or build in a docker for windows environment: + + PS C:\Thrift> docker build -t thrift/thrift-build:msvc2017 -f build\docker\msvc2017\Dockerfile build\ + +The following directories are used inside the container: + + C:\Build the out-of-tree build directory + C:\Install the install target directory + C:\Thrift the source tree + +You can override these as docker volumes if desired. + +### Compiler + +To build a portable windows thrift compiler (with a statically linked +runtime) and get it placed into C:\install: + + docker run -v C:\thrift:C:\thrift^ + -v C:\install:C:\install^ + --rm -t thrift/thrift-build:msvc2017^ + C:\thrift\build\docker\msvc2017\build-compiler.bat + +The end result is a portable windows thrift compiler located at + + C:\Install\bin\thrift.exe + +If you run it through the [Dependency Walker](http://www.dependencywalker.com/) +you will see it only depends on KERNEL32.DLL which means the runtime is statically +linked, so the executable is portable and self-contained. This is how the +windows thrift compiler is built for each Apache Thrift release. + +### Libraries + +To build, test everything and get the C++ SDK placed into C:\install: + + docker run -v C:\thrift:C:\thrift^ + -v C:\install:C:\install^ + -m 4096 --rm -t thrift/thrift-build:msvc2017^ + C:\thrift\build\docker\msvc2017\build.bat \ No newline at end of file diff --git a/build/docker/msvc2017/build-compiler.bat b/build/docker/msvc2017/build-compiler.bat new file mode 100644 index 00000000000..5534428b446 --- /dev/null +++ b/build/docker/msvc2017/build-compiler.bat @@ -0,0 +1,44 @@ +:: +:: 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. +:: + +:: +:: Build script example for inside the windows docker container +:: +:: C:\build is the out-of-tree build directory +:: C:\install is the location where artifacts are placed +:: C:\thrift is where the sources are +:: + +:: Make and go into the out-of-tree directory +IF NOT EXIST C:\build (MKDIR C:\build) +cd c:\build + +:: Generate the out-of-tree build files +cmake^ + -DBOOST_ROOT=C:\Libraries\boost_1_69_0^ + -DBOOST_LIBRARYDIR=C:\Libraries\boost_1_69_0\lib64-msvc-14.1^ + -DBUILD_LIBRARIES=OFF^ + -DCMAKE_BUILD_TYPE=Release^ + -DCMAKE_INSTALL_PREFIX=C:\install^ + -DWITH_MT=ON^ + c:\thrift || EXIT /B + +:: Build +cmake --build . --target thrift-compiler --config Release || EXIT /B + +:: Test +cmake --build . --target check || EXIT /B + +:: Install +cmake --build . --target install \ No newline at end of file diff --git a/build/docker/msvc2017/build.bat b/build/docker/msvc2017/build.bat new file mode 100644 index 00000000000..ac7b68a1c05 --- /dev/null +++ b/build/docker/msvc2017/build.bat @@ -0,0 +1,44 @@ +:: +:: 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. +:: + +:: +:: Build script example for inside the windows docker container +:: +:: C:\build is the out-of-tree build directory +:: C:\install is the location where artifacts are placed +:: C:\thrift is where the sources are +:: + +:: Make and go into the out-of-tree directory +IF NOT EXIST C:\build (MKDIR C:\build) +cd c:\build + +:: Generate the out-of-tree build files +cmake^ + -DBOOST_ROOT=C:\Libraries\boost_1_69_0^ + -DBOOST_LIBRARYDIR=C:\Libraries\boost_1_69_0\lib64-msvc-14.1^ + -DLIBEVENT_ROOT=C:\Libraries\libevent-2.1.8^ + -DZLIB_ROOT=C:\Libraries\zlib-1.2.11^ + -DCMAKE_BUILD_TYPE=Release^ + -DCMAKE_INSTALL_PREFIX=C:\install^ + c:\thrift || EXIT /B + +:: Build +cmake --build . --config Release || EXIT /B + +:: Test +cmake --build . --target check || EXIT /B + +:: Install +cmake --build . --target install \ No newline at end of file diff --git a/build/wincpp/README.md b/build/wincpp/README.md deleted file mode 100644 index a231780407d..00000000000 --- a/build/wincpp/README.md +++ /dev/null @@ -1,219 +0,0 @@ - - -# Building thrift on Windows (Native) - -Thrift uses cmake to make it easier to build the project on multiple platforms, however to build a fully functional and production ready thrift on Windows requires a number of third party libraries to be obtained or built. Once third party libraries are ready, the right combination of options must be passed to cmake in order to generate the correct environment. - -## Summary - -These instructions will help you build thrift for windows using Visual -Studio 2010 or later. The contributed batch files will help you build -the third party libraries needed for complete thrift functionality as -well as thrift itself. - -These instructions follow a directory layout that looks like the following: - - workspace\ - build\ - this is where the out-of-tree thrift cmake builds are generated - dist\ - this is where the thrift build results end up - thirdparty\ - this is where all third party binaries and libraries live - build\ - this is where all third party out-of-tree builds are generated - (except for openssl, which only builds in-tree) - dist\ - this is where all third party distributions end up - src\ - this is where all third party source projects live - scripts\ - batch files used to set environment variables for builds - thrift\ - this is where the thrift source project lives - -Create a "workspace" directory somewhere on your system and then copy the contents of this -directory to there, then clone or unpack thrift into `workspace\thrift`. - -## Third Party Libraries - -Batch scripts are provided to build some third party libraries. You must download them and place them into the directory noted for each. You can use different versions if you prefer; these instructions were made with the versions listed. - -> TIP: To modify the versions used in the batch scripts, look in scripts\tpversions.bat. - -Build them in the order listed to satisfy their dependencies. - -### winflexbison - - source: web site - location: https://sourceforge.net/projects/winflexbison/files/win_flex_bison-latest.zip/download - version: "latest" - directory: workspace\thirdparty\dist\winflexbison - -This package is required to build the compiler. This third party package does not need to be built as it is a binary distribution of the "bison" and "flex" tools normally found on Unix boxes. - -> TIP: If you are only interested in building the compiler, you can skip the remaining third party libraries. - -### zlib - - source: web site - location: http://zlib.net/ - version: 1.2.9 - directory: workspace\thirdparty\src\zlib-1.2.9 - -To build, open the appropriate Visual Studio command prompt and then run -the build-zlib.bat script in thirdparty\src. - -### openssl - - source: web site - location: https://www.openssl.org/ - version: 1.1.0c - directory: workspace\thirdparty\src\openssl-1.1.0c - depends-on: zlib - -If you are using openssl-1.1.0 or later, they changed static builds to use Microsoft Static RTL for release builds. zlib by default uses a dynamic runtime, as does libevent. Edit the file Configurations/10-main.conf and replace the section contents for "VC-noCE-common" with what appears below to make openssl build with dynamic runtime instead: - - "VC-noCE-common" => { - inherit_from => [ "VC-common" ], - template => 1, - cflags => add(picker(default => "-DUNICODE -D_UNICODE", - debug => "/MDd /Od -DDEBUG -D_DEBUG", - release => "/MD /O2" - )), - bin_cflags => add(picker(debug => "/MDd", - release => "/MD", - )), - bin_lflags => add("/subsystem:console /opt:ref"), - ex_libs => add(sub { - my @ex_libs = (); - push @ex_libs, 'ws2_32.lib' unless $disabled{sock}; - push @ex_libs, 'gdi32.lib advapi32.lib crypt32.lib user32.lib'; - return join(" ", @ex_libs); - }), - }, - -To build, open the appropriate Visual Studio command prompt and then run -the build-openssl.bat script in thirdparty\src. - -### libevent - - source: git - location: https://github.com/nmathewson/Libevent.git - use: commit 3821cca1a637f4da4099c9343e7326da00f6981c or later - date: Fri Dec 23 16:19:35 2016 +0800 or later - version: corresponds to 2.1.7rc + patches - directory: workspace\thirdparty\src\libevent-2.1.7rc2 - depends-on: openssl, zlib - -To build, open the appropriate Visual Studio command prompt and then run -the build-libevent.bat script in thirdparty\src. - -### msinttypes - - source: web site - location: https://code.google.com/archive/p/msinttypes/downloads - version: 26 - directory: workspace\thirdparty\dist\msinttypes - -> TIP: This is only necessary for Visual Studio 2010, which did not include an header. - -This third party package does not need to be built as it is a distribution of header files. - -### boost - - source: web site - location: http://boost.teeks99.com/ - version: 1_62_0 - directory: workspace\thirdparty\dist\boost_1_62_0 - -The pre-built binary versions of boost come in self-unpacking executables. Run each of the ones you are interested in and point them at the same thirdparty dist directory. - -## Building a Production thrift Compiler - -### Prerequisites - -* CMake-2.8.12.2 or later -* Visual Studio 2010 or later -* thrift source placed into workspace\thrift -* winflexbison placed into workspace\thirdparty\dist - -### Instructions - -By following these instructions you will end up with a release mode thrift compiler that is suitable for distribution as it has no external dependencies. - -1. Open the appropriate Visual Studio Command Prompt. -2. `cd workspace` -3. `build-thrift-compiler.bat` - -The batch file uses CMake to generate an out-of-tree build directory in `workspace\build` and then builds the compiler. The resulting `thrift.exe` program is placed into `workspace\dist` in a path that depends on your compiler version and platform. For example, if you use a Visual Studio 2010 x64 Command Prompt, the compiler will be placed into `workspace\dist\thrift-compiler-dev\vc100\x64\Release\thrift.exe` - -#### Details - -This section is for those who are curious about the CMake options used in the build process. - -CMake takes the source tree as the first argument and uses the remaining arguments for configuration. The batch file `build-thrift-compiler` essentially performs the following commands: - - C:\> CD workspace\build - C:\workspace\build> "C:\Program Files\CMake\bin\cmake.exe" ..\thrift - -DBISON_EXECUTABLE=..\thirdparty\dist\winflexbison\win_bison.exe - -DCMAKE_BUILD_TYPE=Release - -DFLEX_EXECUTABLE=..\thirdparty\dist\winflexbison\win_flex.exe - -DWITH_MT=ON - -DWITH_SHARED_LIB=OFF - -G"NMake Makefiles" - C:\workspace\build> NMAKE /FMakefile thrift-compiler - -WITH_MT controls the dynamic or static runtime library selection. To build a production compiler, the thrift project recommends using the static runtime library to make the executable portable. The batch file sets this. - -You can build a Visual Studio project file by following the example but substituting a different generator for the "-G" option. Run `cmake.exe --help` for a list of generators. Typically, this is one of the following on Windows (omit "Win64" to build 32-bit instead): - -* "Visual Studio 10 2010 Win64" -* "Visual Studio 11 2012 Win64" -* "Visual Studio 12 2013 Win64" -* "Visual Studio 14 2015 Win64" -* "Visual Studio 15 2017 Win64" - -For example you can build using a Visual Studio solution file on the command line by doing: - - C:\> CD workspace\build - C:\workspace\build> "C:\Program Files\CMake\bin\cmake.exe" ..\thrift - -DBISON_EXECUTABLE=..\thirdparty\dist\winflexbison\win_bison.exe - -DCMAKE_BUILD_TYPE=Release - -DFLEX_EXECUTABLE=..\thirdparty\dist\winflexbison\win_flex.exe - -DWITH_MT=ON - -DWITH_SHARED_LIB=OFF - -G"Visual Studio 14 2015 Win64" - C:\workspace\build> MSBUILD "Apache Thrift.sln" /p:Configuration=Release /p:Platform=x64 /t:thrift-compiler - -You can also double-click on the solution file to bring it up in Visual Studio and build or debug interactively from there. - -## Building the thrift C++ Run-Time Library - -These instructions are similar to the compiler build however there are additional dependencies on third party libraries to build a feature-complete runtime. The resulting static link library for thrift uses a dynamic Microsoft runtime. - -1. Open the desired Visual Studio Command Prompt. -2. `cd workspace` -3. `build-thrift.bat` - -Thrift depends on boost, libevent, openssl, and zlib in order to build with all server and transport types. To use later versions of boost like 1.62 you will need a recent version of cmake (at least 3.7). - -The build-thrift script has options to build debug or release and to optionally disable any of the generation (cmake), build, or test phases. By default, the batch file will generate an out-of-tree build directory inside `workspace\build`, then perform a release build, then run the unit tests. The batch file accepts some option flags to control its behavior: - - :: Flags you can use to change this behavior: - :: - :: /DEBUG - if building, perform a debug build instead - :: /NOGENERATE - skip cmake generation - useful if you - :: have already generated a solution and just - :: want to build - :: /NOBUILD - skip cmake build - useful if you just - :: want to generate a solution - :: /NOTEST - skip ctest execution - -For example if you want to generate the cmake environment without building or running tests: - - C:\workspace> build-thrift.bat /NOBUILD /NOTEST diff --git a/build/wincpp/build-thrift-compiler.bat b/build/wincpp/build-thrift-compiler.bat deleted file mode 100644 index b6b42a8d76f..00000000000 --- a/build/wincpp/build-thrift-compiler.bat +++ /dev/null @@ -1,79 +0,0 @@ -:: -:: 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. -:: - -:: -:: Produces a production thrift compiler suitable for redistribution. -:: The compiler is linked to runtime statically for maximum portability. -:: Assumes the thirdparty files for "winflexbison" have been placed -:: according to the README.md instructions. -:: -:: Open a Visual Studio Command Prompt of your choosing and then -:: run this script. - -@ECHO OFF -SETLOCAL EnableDelayedExpansion - -IF NOT DEFINED PACKAGE_NAME SET PACKAGE_NAME=thrift -IF NOT DEFINED PACKAGE_VERSION SET PACKAGE_VERSION=dev -IF NOT DEFINED SOURCE_DIR SET SOURCEDIR=%~dp0%PACKAGE_NAME% -IF NOT DEFINED WIN3P_ROOT SET WIN3P_ROOT=%~dp0thirdparty - -:: Set COMPILER to (vc100 - vc140) depending on the current environment -CALL scripts\cl_setcompiler.bat || EXIT /B - -:: Set ARCH to either win32 or x64 depending on the current environment -CALL scripts\cl_setarch.bat || EXIT /B - -:: Set GENERATOR for CMake depending on the current environment -CALL scripts\cl_setgenerator.bat || EXIT /B - -IF NOT DEFINED BUILDTYPE ( - SET BUILDTYPE=Release -) - - SET BUILDDIR=%~dp0build\%PACKAGE_NAME%-compiler\%PACKAGE_VERSION%\%COMPILER%\ - SET OUTDIR=%~dp0dist\%PACKAGE_NAME%-compiler-%PACKAGE_VERSION%\%COMPILER%\%ARCH%\%BUILDTYPE%\ - SET BOOST_LIBDIR=lib%ARCH:~-2,2%-msvc-%COMPILER:~-3,2%.0 - IF "%BUILDTYPE%" == "Debug" (SET ZLIB_STATIC_SUFFIX=d) - - ECHO/ - ECHO ========================================================================= - ECHO Configuration: %PACKAGE_NAME% %PACKAGE_VERSION% %COMPILER%:%ARCH%:%BUILDTYPE% "%GENERATOR%" -IF DEFINED COMPILERONLY ( - ECHO COMPILER ONLY -) - ECHO Build Directory: %BUILDDIR% - ECHO Install Directory: %OUTDIR% - ECHO Source Directory: %SOURCEDIR% - ECHO ========================================================================= - ECHO/ - - MKDIR "%BUILDDIR%" - CD "%BUILDDIR%" || EXIT /B - - CMAKE.EXE %~dp0thrift ^ - -G"%GENERATOR%" ^ - -DBISON_EXECUTABLE=%WIN3P_ROOT%\dist\winflexbison\win_bison.exe ^ - -DCMAKE_BUILD_TYPE=%BUILDTYPE% ^ - -DFLEX_EXECUTABLE=%WIN3P_ROOT%\dist\winflexbison\win_flex.exe ^ - -DWITH_MT=ON ^ - -DWITH_SHARED_LIB=OFF || EXIT /B - - CD %BUILDDIR% - - CMAKE.EXE --build . --config %BUILDTYPE% --target thrift-compiler || EXIT /B - XCOPY /F /Y %BUILDDIR%\bin\%BUILDTYPE%\thrift.exe %OUTDIR% - -ENDLOCAL -EXIT /B diff --git a/build/wincpp/build-thrift.bat b/build/wincpp/build-thrift.bat deleted file mode 100644 index b867acf2456..00000000000 --- a/build/wincpp/build-thrift.bat +++ /dev/null @@ -1,163 +0,0 @@ -:: -:: 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. -:: - -:: -:: Generates a Visual Studio solution for thrift and then builds it. -:: Assumes third party libraries have been built or placed already. -:: -:: Open a Visual Studio Command Prompt of your choosing and then -:: run this script. -:: -:: Normally the script will run cmake to generate a solution, then -:: perform a build, then run tests on the complete thrift library -:: in release mode. -:: -:: Flags you can use to change this behavior: -:: -:: /DEBUG - debug instead of release -:: /IDE - launch Visual Studio with a path set -:: up correctly to run tests instead of -:: performing any other actions, i.e. -:: implies setting the next three flags -:: /NOGENERATE - skip cmake generation - useful if you -:: have already generated a solution and just -:: want to build -:: /NOBUILD - skip cmake build - useful if you just -:: want to generate a solution -:: /NOTEST - skip ctest execution -:: - -@ECHO OFF -SETLOCAL EnableDelayedExpansion - -:: Sets variables for third party versions used in build -CALL scripts\tpversions.bat || EXIT /B - -IF NOT DEFINED PACKAGE_NAME SET PACKAGE_NAME=thrift -IF NOT DEFINED PACKAGE_VERSION SET PACKAGE_VERSION=dev -IF NOT DEFINED SOURCE_DIR SET SOURCEDIR=%~dp0%PACKAGE_NAME% -IF NOT DEFINED WIN3P_ROOT SET WIN3P_ROOT=%~dp0thirdparty - -:: Set COMPILER to (vc100 - vc140) depending on the current environment -CALL scripts\cl_setcompiler.bat || EXIT /B - -:: Set ARCH to either win32 or x64 depending on the current environment -CALL scripts\cl_setarch.bat || EXIT /B - -:: Set GENERATOR for CMake depending on the current environment -CALL scripts\cl_setgenerator.bat || EXIT /B - -:: Defaults - -IF NOT DEFINED BUILDTYPE SET BUILDTYPE=Release -SET OPT_IDE=0 -SET OPT_BUILD=1 -SET OPT_GENERATE=1 -SET OPT_TEST=1 - -:: Apply Flags - -IF /I "%1" == "/DEBUG" SET BUILDTYPE=Debug -IF /I "%2" == "/DEBUG" SET BUILDTYPE=Debug -IF /I "%3" == "/DEBUG" SET BUILDTYPE=Debug -IF /I "%1" == "/IDE" SET OPT_IDE=1 -IF /I "%2" == "/IDE" SET OPT_IDE=1 -IF /I "%3" == "/IDE" SET OPT_IDE=1 -IF /I "%1" == "/NOBUILD" SET OPT_BUILD=0 -IF /I "%2" == "/NOBUILD" SET OPT_BUILD=0 -IF /I "%3" == "/NOBUILD" SET OPT_BUILD=0 -IF /I "%1" == "/NOGENERATE" SET OPT_GENERATE=0 -IF /I "%2" == "/NOGENERATE" SET OPT_GENERATE=0 -IF /I "%3" == "/NOGENERATE" SET OPT_GENERATE=0 -IF /I "%1" == "/NOTEST" SET OPT_TEST=0 -IF /I "%2" == "/NOTEST" SET OPT_TEST=0 -IF /I "%3" == "/NOTEST" SET OPT_TEST=0 - -IF %OPT_IDE% == 1 ( - SET OPT_GENERATE=0 - SET OPT_BUILD=0 - SET OPT_TEST=0 -) - - SET BUILDDIR=%~dp0build\%PACKAGE_NAME%\%PACKAGE_VERSION%\%COMPILER%\%ARCH%\ - SET OUTDIR=%~dp0dist\%PACKAGE_NAME%-%PACKAGE_VERSION%\%COMPILER%\%ARCH%\%BUILDTYPE%\ - SET BOOST_LIBDIR=lib%ARCH:~-2,2%-msvc-%COMPILER:~-3,2%.0 - IF "%BUILDTYPE%" == "Debug" (SET ZLIB_STATIC_SUFFIX=d) - - ECHO/ - ECHO ========================================================================= - ECHO Configuration: %PACKAGE_NAME% %PACKAGE_VERSION% %COMPILER%:%ARCH%:%BUILDTYPE% "%GENERATOR%" -IF DEFINED COMPILERONLY ( - ECHO COMPILER ONLY -) - ECHO Build Directory: %BUILDDIR% - ECHO Install Directory: %OUTDIR% - ECHO Source Directory: %SOURCEDIR% - ECHO ========================================================================= - ECHO/ - -IF %OPT_IDE% == 1 ( - - CALL :SETRUNPATH || EXIT /B - CALL DEVENV "!BUILDDIR!Apache Thrift.sln" || EXIT /B - EXIT /B - -) - - MKDIR "%BUILDDIR%" - CD "%BUILDDIR%" || EXIT /B - -IF %OPT_GENERATE% == 1 ( - - CMAKE.EXE %~dp0thrift ^ - -G"%GENERATOR%" ^ - -DBISON_EXECUTABLE=%WIN3P_ROOT%\dist\winflexbison\win_bison.exe ^ - -DBOOST_ROOT=%WIN3P_ROOT%\dist\boost_%TP_BOOST_VERSION% ^ - -DBOOST_LIBRARYDIR=%WIN3P_ROOT%\dist\boost_%TP_BOOST_VERSION%\%BOOST_LIBDIR% ^ - -DCMAKE_INSTALL_PREFIX=%OUTDIR% ^ - -DCMAKE_BUILD_TYPE=%BUILDTYPE% ^ - -DFLEX_EXECUTABLE=%WIN3P_ROOT%\dist\winflexbison\win_flex.exe ^ - -DINTTYPES_ROOT=%WIN3P_ROOT%\dist\msinttypes ^ - -DLIBEVENT_ROOT=%WIN3P_ROOT%\dist\libevent-%TP_LIBEVENT_VERSION%\%COMPILER%\%ARCH%\%BUILDTYPE% ^ - -DOPENSSL_ROOT_DIR=%WIN3P_ROOT%\dist\openssl-%TP_OPENSSL_VERSION%\%COMPILER%\%ARCH%\%BUILDTYPE%\dynamic ^ - -DOPENSSL_USE_STATIC_LIBS=OFF ^ - -DZLIB_LIBRARY=%WIN3P_ROOT%\dist\zlib-%TP_ZLIB_VERSION%\%COMPILER%\%ARCH%\lib\zlib%ZLIB_LIB_SUFFIX%.lib ^ - -DZLIB_ROOT=%WIN3P_ROOT%\dist\zlib-%TP_ZLIB_VERSION%\%COMPILER%\%ARCH% ^ - -DWITH_SHARED_LIB=OFF ^ - -DWITH_STATIC_LIB=ON || EXIT /B - -) - -IF %OPT_BUILD% == 1 ( - - CD %BUILDDIR% - CMAKE.EXE --build . --config %BUILDTYPE% --target INSTALL || EXIT /B - -) - -IF %OPT_TEST% == 1 ( - - CALL :SETRUNPATH || EXIT /B - CMAKE.EXE --build . --config %BUILDTYPE% --target RUN_TESTS || EXIT /B - -) - -:SETRUNPATH - SET PATH=!PATH!;%WIN3P_ROOT%\dist\boost_%TP_BOOST_VERSION%\%BOOST_LIBDIR% - SET PATH=!PATH!;%WIN3P_ROOT%\dist\openssl-%TP_OPENSSL_VERSION%\%COMPILER%\%ARCH%\%BUILDTYPE%\dynamic\bin - SET PATH=!PATH!;%WIN3P_ROOT%\dist\zlib-%TP_ZLIB_VERSION%\%COMPILER%\%ARCH%\bin - EXIT /B - -ENDLOCAL -EXIT /B diff --git a/build/wincpp/scripts/cl_setarch.bat b/build/wincpp/scripts/cl_setarch.bat deleted file mode 100644 index 9570a1e856c..00000000000 --- a/build/wincpp/scripts/cl_setarch.bat +++ /dev/null @@ -1,47 +0,0 @@ -:: -:: 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. -:: - -:: -:: Detect the architecture we're building for. -:: Set the ARCH environment variable to one of: -:: win32 -:: x64 -:: -:: Honors any existing ARCH environment variable -:: setting instead of overwriting it, to allow it -:: to be forced if needed. -:: -:: Sets ERRORLEVEL to 0 if ARCH can be determined, -:: to 1 if it cannot. -:: - -IF DEFINED ARCH ( - ECHO [warn ] using existing environment variable ARCH - EXIT /B 0 -) - -CALL :CHECK x64 -IF %ERRORLEVEL% == 0 (SET ARCH=x64) ELSE (SET ARCH=win32) - -IF NOT DEFINED ARCH ( - ECHO [error] unable to determine the target architecture - EXIT /B 1 -) - -ECHO [info ] detected target architecture %ARCH% -EXIT /B 0 - -:CHECK -cl /? 2>&1 | findstr /C:" for %1%" > nul -EXIT /B %ERRORLEVEL% diff --git a/build/wincpp/scripts/cl_setcompiler.bat b/build/wincpp/scripts/cl_setcompiler.bat deleted file mode 100644 index 8405d761689..00000000000 --- a/build/wincpp/scripts/cl_setcompiler.bat +++ /dev/null @@ -1,58 +0,0 @@ -:: -:: 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. -:: - -:: -:: Detect the compiler edition we're building in. -:: Set the COMPILER environment variable to one of: -:: vc100 = Visual Studio 2010 -:: vc110 = Visual Studio 2012 -:: vc120 = Visual Studio 2013 -:: vc140 = Visual Studio 2015 -:: vc150 = Visual Studio 2017 -:: -:: Honors any existing COMPILER environment variable -:: setting instead of overwriting it, to allow it -:: to be forced if needed. -:: -:: Sets ERRORLEVEL to 0 if COMPILER can be determined, -:: to 1 if it cannot. -:: - -IF DEFINED COMPILER ( - ECHO [warn ] using existing environment variable COMPILER - EXIT /B 0 -) - -CALL :CHECK 16 -IF %ERRORLEVEL% == 0 (IF NOT DEFINED COMPILER SET COMPILER=vc100) -CALL :CHECK 17 -IF %ERRORLEVEL% == 0 (IF NOT DEFINED COMPILER SET COMPILER=vc110) -CALL :CHECK 18 -IF %ERRORLEVEL% == 0 (IF NOT DEFINED COMPILER SET COMPILER=vc120) -CALL :CHECK 19.00 -IF %ERRORLEVEL% == 0 (IF NOT DEFINED COMPILER SET COMPILER=vc140) -CALL :CHECK 19.10 -IF %ERRORLEVEL% == 0 (IF NOT DEFINED COMPILER SET COMPILER=vc150) - -IF NOT DEFINED COMPILER ( - ECHO [error] unable to determine the compiler edition - EXIT /B 1 -) - -ECHO [info ] detected compiler edition %COMPILER% -EXIT /B 0 - -:CHECK -cl /? 2>&1 | findstr /C:"Version %1%." > nul -EXIT /B %ERRORLEVEL% diff --git a/build/wincpp/scripts/cl_setgenerator.bat b/build/wincpp/scripts/cl_setgenerator.bat deleted file mode 100644 index bae2742f7ba..00000000000 --- a/build/wincpp/scripts/cl_setgenerator.bat +++ /dev/null @@ -1,69 +0,0 @@ -:: -:: 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. -:: - -:: -:: Detect the compiler edition we're building in and then -:: set the GENERATOR environment variable to one of: -:: -:: Visual Studio 15 2017 [arch] = Generates Visual Studio 2017 project files. -:: Optional [arch] can be "Win64" or "ARM". -:: Visual Studio 14 2015 [arch] = Generates Visual Studio 2015 project files. -:: Optional [arch] can be "Win64" or "ARM". -:: Visual Studio 12 2013 [arch] = Generates Visual Studio 2013 project files. -:: Optional [arch] can be "Win64" or "ARM". -:: Visual Studio 11 2012 [arch] = Generates Visual Studio 2012 project files. -:: Optional [arch] can be "Win64" or "ARM". -:: Visual Studio 10 2010 [arch] = Generates Visual Studio 2010 project files. -:: Optional [arch] can be "Win64" or "IA64". -:: -:: Honors any existing GENERATOR environment variable -:: setting instead of overwriting it, to allow it -:: to be forced if needed. -:: -:: Sets ERRORLEVEL to 0 if GENERATOR can be determined, -:: to 1 if it cannot. -:: -:: Requires cl_setarch.bat to have been executed or the ARCH environment -:: variable to be set. -:: - -IF "%ARCH%" == "x64" (SET GENARCH= Win64) - -IF DEFINED GENERATOR ( - ECHO [warn ] using existing environment variable GENERATOR - EXIT /B 0 -) - -CALL :CHECK 16 -IF %ERRORLEVEL% == 0 (IF NOT DEFINED GENERATOR SET GENERATOR=Visual Studio 10 2010%GENARCH%) -CALL :CHECK 17 -IF %ERRORLEVEL% == 0 (IF NOT DEFINED GENERATOR SET GENERATOR=Visual Studio 11 2012%GENARCH%) -CALL :CHECK 18 -IF %ERRORLEVEL% == 0 (IF NOT DEFINED GENERATOR SET GENERATOR=Visual Studio 12 2013%GENARCH%) -CALL :CHECK 19.00 -IF %ERRORLEVEL% == 0 (IF NOT DEFINED GENERATOR SET GENERATOR=Visual Studio 14 2015%GENARCH%) -CALL :CHECK 19.10 -IF %ERRORLEVEL% == 0 (IF NOT DEFINED GENERATOR SET GENERATOR=Visual Studio 15 2017%GENARCH%) - -IF NOT DEFINED GENERATOR ( - ECHO [error] unable to determine the CMake generator to use - EXIT /B 1 -) - -ECHO [info ] using CMake generator %GENERATOR% -EXIT /B 0 - -:CHECK -cl /? 2>&1 | findstr /C:"Version %1%." > nul -EXIT /B %ERRORLEVEL% diff --git a/build/wincpp/scripts/tpversions.bat b/build/wincpp/scripts/tpversions.bat deleted file mode 100644 index d80c868789c..00000000000 --- a/build/wincpp/scripts/tpversions.bat +++ /dev/null @@ -1,24 +0,0 @@ -:: -:: 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. -:: - -:: -:: Set the versions of third party libraries to use. -:: - -IF NOT DEFINED TP_BOOST_VERSION SET TP_BOOST_VERSION=1_62_0 -IF NOT DEFINED TP_LIBEVENT_VERSION SET TP_LIBEVENT_VERSION=2.1.7rc2 -IF NOT DEFINED TP_OPENSSL_VERSION SET TP_OPENSSL_VERSION=1.1.0c -IF NOT DEFINED TP_ZLIB_VERSION SET TP_ZLIB_VERSION=1.2.9 - -EXIT /B 0 diff --git a/build/wincpp/thirdparty/src/build-libevent.bat b/build/wincpp/thirdparty/src/build-libevent.bat deleted file mode 100644 index 4af505c61fb..00000000000 --- a/build/wincpp/thirdparty/src/build-libevent.bat +++ /dev/null @@ -1,86 +0,0 @@ -:: -:: 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. -:: - -:: -:: Build script for libevent on windows -:: Use libevent master from github which has cmake integration -:: Uses the environment set up by a Visual Studio Command Prompt shortcut -:: to target a specific architecture and compiler -:: -:: Creates a static link library. -:: Links against OpenSSL and zlib statically. -:: - -@ECHO OFF -SETLOCAL EnableDelayedExpansion - -:: Sets variables for third party versions used in build -CALL ..\..\scripts\tpversions.bat || EXIT /B - -:: use "build-libevent.bat /yes" to skip the question part -IF /I "%1" == "/YES" SET NOASK=1 - -:: Set COMPILER to (vc100 - vc140) depending on the current environment -CALL ..\..\scripts\cl_setcompiler.bat || EXIT /B - -:: Set ARCH to either win32 or x64 depending on the current environment -CALL ..\..\scripts\cl_setarch.bat || EXIT /B - -IF NOT DEFINED GENERATOR SET GENERATOR=NMake Makefiles -IF NOT DEFINED PACKAGE_NAME SET PACKAGE_NAME=libevent -IF NOT DEFINED PACKAGE_VERSION SET PACKAGE_VERSION=%TP_LIBEVENT_VERSION% -IF NOT DEFINED SOURCEDIR SET SOURCEDIR=%~dp0%PACKAGE_NAME%-%PACKAGE_VERSION% -IF NOT DEFINED WIN3P_ROOT SET WIN3P_ROOT=%~dp0.. - -FOR %%X IN ( - Debug - Release -) DO ( - SET BUILDTYPE=%%X - SET BUILDDIR=%WIN3P_ROOT%\build\%PACKAGE_NAME%\%PACKAGE_VERSION%\%COMPILER%\%ARCH%\!BUILDTYPE! - SET OUTDIR=%WIN3P_ROOT%\dist\%PACKAGE_NAME%-%PACKAGE_VERSION%\%COMPILER%\%ARCH%\!BUILDTYPE! - - IF "!BUILDTYPE!" == "Debug" (SET ZLIB_LIB_SUFFIX=d) - - SET CMAKE_DEFS=^ - -DEVENT__DISABLE_SAMPLES=ON ^ - -DEVENT__DISABLE_TESTS=ON ^ - -DOPENSSL_USE_STATIC_LIBS=OFF ^ - -DOPENSSL_ROOT_DIR=%WIN3P_ROOT%\dist\openssl-%TP_OPENSSL_VERSION%\%COMPILER%\%ARCH%\!BUILDTYPE!\dynamic ^ - -DZLIB_LIBRARY=%WIN3P_ROOT%\dist\zlib-%TP_ZLIB_VERSION%\%COMPILER%\%ARCH%\lib\zlib!ZLIB_LIB_SUFFIX!.lib ^ - -DZLIB_ROOT=%WIN3P_ROOT%\dist\zlib-%TP_ZLIB_VERSION%\%COMPILER%\%ARCH% - - ECHO/ - ECHO ========================================================================= - ECHO Building: %PACKAGE_NAME% v%PACKAGE_VERSION% %COMPILER%:%ARCH%:!BUILDTYPE! "%GENERATOR%" - ECHO CMake Definitions: !CMAKE_DEFS! - ECHO Build Directory: !BUILDDIR! - ECHO Install Directory: !OUTDIR! - ECHO Source Directory: %SOURCEDIR% - ECHO ========================================================================= - ECHO/ - - IF NOT DEFINED NOASK ( - CHOICE /M "Do you want to build this configuration? " /c YN - IF !ERRORLEVEL! NEQ 1 (EXIT /B !ERRORLEVEL!) - ) - - MKDIR "!BUILDDIR!" - CD "!BUILDDIR!" || EXIT /B - - CMAKE.EXE -G"%GENERATOR%" -DCMAKE_INSTALL_PREFIX=!OUTDIR! -DCMAKE_BUILD_TYPE=!BUILDTYPE! !CMAKE_DEFS! "%SOURCEDIR%" || EXIT /B - NMAKE /fMakefile install || EXIT /B -) - -ENDLOCAL diff --git a/build/wincpp/thirdparty/src/build-openssl.bat b/build/wincpp/thirdparty/src/build-openssl.bat deleted file mode 100644 index cf270f05b39..00000000000 --- a/build/wincpp/thirdparty/src/build-openssl.bat +++ /dev/null @@ -1,106 +0,0 @@ -:: -:: 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. -:: - -:: -:: Build script for openssl on windows -:: openssl uses an in-tree build so you have to clean between each one -:: -:: Uses the environment set up by a Visual Studio Command Prompt shortcut -:: to target a specific architecture and compiler -:: -:: If you use Lavasoft Ad-Aware, disable it for this build. It blocks the creation -:: of any file named "clienthellotest.exe" for whatever reason, which breaks the build. -:: - -@ECHO OFF -SETLOCAL EnableDelayedExpansion - -:: Sets variables for third party versions used in build -CALL ..\..\scripts\tpversions.bat || EXIT /B - -:: use "build-openssl.bat /yes" to skip the question part -IF /I "%1" == "/YES" SET NOASK=1 - -IF NOT DEFINED PACKAGE_NAME SET PACKAGE_NAME=openssl -IF NOT DEFINED PACKAGE_VERSION SET PACKAGE_VERSION=%TP_OPENSSL_VERSION% -IF NOT DEFINED SOURCEDIR SET SOURCEDIR=%~dp0%PACKAGE_NAME%-%PACKAGE_VERSION% -IF NOT DEFINED WIN3P_ROOT SET WIN3P_ROOT=%~dp0.. - -:: Set COMPILER to (vc100 - vc140) depending on the current environment -CALL ..\..\scripts\cl_setcompiler.bat || EXIT /B - -:: Set ARCH to either win32 or x64 depending on the current environment -CALL ..\..\scripts\cl_setarch.bat || EXIT /B - -IF "%ARCH%" == "x64" ( - SET TODO=debug-VC-WIN64A VC-WIN64A -) ELSE ( - SET TODO=debug-VC-WIN32 VC-WIN32 -) - -FOR %%X IN ( !TODO! ) DO ( - SET BUILDTYPE=%%X - FOR %%Y IN ( - nt - ntdll - ) DO ( - SET LIBTYPE=%%Y - - IF "!BUILDTYPE:~0,6!" == "debug-" ( - SET OUTBUILDTYPE=debug - SET ZLIBLIBSUFFIX=d - ) ELSE ( - SET OUTBUILDTYPE=release - SET ZLIBLIBSUFFIX= - ) - - IF "!LIBTYPE!" == "ntdll" ( - SET BUILD_OPTIONS=shared - SET OUTLIBTYPE=dynamic - SET ZLIBLIB=zlib!ZLIBLIBSUFFIX! - SET ZLIBOPT=zlib-dynamic - ) ELSE ( - SET BUILD_OPTIONS=no-shared - SET OUTLIBTYPE=static - SET ZLIBLIB=zlibstatic!ZLIBLIBSUFFIX!.lib - SET ZLIBOPT=zlib - ) - - SET LIB=%~dp0..\dist\zlib-%TP_ZLIB_VERSION%\!COMPILER!\!ARCH!\lib;!LIB! - SET BUILD_OPTIONS=!BUILD_OPTIONS! no-asm no-unit-test !ZLIBOPT! --openssldir=ssl --with-zlib-include=%~dp0..\dist\zlib-%TP_ZLIB_VERSION%\!COMPILER!\!ARCH!\include --with-zlib-lib=!ZLIBLIB! - SET OUTDIR=%WIN3P_ROOT%\dist\%PACKAGE_NAME%-%PACKAGE_VERSION%\%COMPILER%\%ARCH%\!OUTBUILDTYPE!\!OUTLIBTYPE! - - ECHO/ - ECHO ========================================================================= - ECHO Building: %PACKAGE_NAME% %PACKAGE_VERSION% %COMPILER%:%ARCH%:!OUTBUILDTYPE!:!OUTLIBTYPE! [!BUILDTYPE!] - ECHO Configure Options: !BUILD_OPTIONS! - ECHO Install Directory: !OUTDIR! - ECHO Source Directory: %SOURCEDIR% - ECHO ========================================================================= - ECHO/ - - IF NOT DEFINED NOASK ( - CHOICE /M "Do you want to build this configuration? " /c YN - IF !ERRORLEVEL! NEQ 1 (EXIT /B !ERRORLEVEL!) - ) - - CD %SOURCEDIR% || EXIT /B - perl Configure !BUILDTYPE! --prefix="!OUTDIR!" !BUILD_OPTIONS! || EXIT /B - NMAKE /FMakefile install_sw || EXIT /B - NMAKE /FMakefile clean || EXIT /B - ) -) - -ENDLOCAL -EXIT /B diff --git a/build/wincpp/thirdparty/src/build-zlib.bat b/build/wincpp/thirdparty/src/build-zlib.bat deleted file mode 100644 index 2427230d0fe..00000000000 --- a/build/wincpp/thirdparty/src/build-zlib.bat +++ /dev/null @@ -1,75 +0,0 @@ -:: -:: 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. -:: - -:: -:: Build script for zlib on windows. -:: Uses the environment set up by a Visual Studio Command Prompt shortcut -:: to target a specific architecture and compiler. -:: - -@ECHO OFF -SETLOCAL EnableDelayedExpansion - -:: Sets variables for third party versions used in build -CALL ..\..\scripts\tpversions.bat || EXIT /B - -:: use "build-zlib.bat /yes" to skip the question part -IF /I "%1" == "/YES" SET NOASK=1 - -IF NOT DEFINED GENERATOR SET GENERATOR=NMake Makefiles -IF NOT DEFINED PACKAGE_NAME SET PACKAGE_NAME=zlib -IF NOT DEFINED PACKAGE_VERSION SET PACKAGE_VERSION=%TP_ZLIB_VERSION% -IF NOT DEFINED SOURCE_DIR SET SOURCEDIR=%~dp0%PACKAGE_NAME%-%PACKAGE_VERSION% -IF NOT DEFINED WIN3P_ROOT SET WIN3P_ROOT=%~dp0.. - -:: Set COMPILER to (vc100 - vc140) depending on the current environment -CALL ..\..\scripts\cl_setcompiler.bat || EXIT /B - -:: Set ARCH to either win32 or x64 depending on the current environment -CALL ..\..\scripts\cl_setarch.bat || EXIT /B - -FOR %%X IN ( - Debug - Release -) DO ( - SET BUILDTYPE=%%X - SET BUILDDIR=%WIN3P_ROOT%\build\%PACKAGE_NAME%\%PACKAGE_VERSION%\%COMPILER%\%ARCH%\!BUILDTYPE! - SET OUTDIR=%WIN3P_ROOT%\dist\%PACKAGE_NAME%-%PACKAGE_VERSION%\%COMPILER%\%ARCH% - - ECHO/ - ECHO ========================================================================= - ECHO Building: %PACKAGE_NAME% v%PACKAGE_VERSION% %COMPILER%:%ARCH%:!BUILDTYPE! "%GENERATOR%" - ECHO Build Directory: !BUILDDIR! - ECHO Install Directory: !OUTDIR! - ECHO Source Directory: %SOURCEDIR% - ECHO ========================================================================= - ECHO/ - - IF NOT DEFINED NOASK ( - CHOICE /M "Do you want to build this configuration? " /c YN - IF !ERRORLEVEL! NEQ 1 (EXIT /B !ERRORLEVEL!) - ) - - MKDIR "!BUILDDIR!" - CD "!BUILDDIR!" || EXIT /B - - CMAKE.EXE -G"%GENERATOR%" -DCMAKE_INSTALL_PREFIX=!OUTDIR! -DCMAKE_BUILD_TYPE=!BUILDTYPE! "%SOURCEDIR%" || EXIT /B - NMAKE /fMakefile install || EXIT /B - - IF "!BUILDTYPE!" == "Debug" ( - COPY "!BUILDDIR!\zlibd.pdb" "!OUTDIR!\bin\" || EXIT /B - ) -) - -ENDLOCAL diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt index 0df790ee2d1..96efe65ab56 100644 --- a/compiler/cpp/CMakeLists.txt +++ b/compiler/cpp/CMakeLists.txt @@ -16,18 +16,11 @@ # specific language governing permissions and limitations # under the License. # -cmake_minimum_required(VERSION 2.8.12) + +cmake_minimum_required(VERSION 3.3) +project("thrift-compiler" VERSION ${PACKAGE_VERSION}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h) -if(MSVC) - # The winflexbison generator outputs some macros that conflict with the Visual Studio 2010 copy of stdint.h - # This might be fixed in later versions of Visual Studio, but an easy solution is to include stdint.h first - if(HAVE_STDINT_H) - add_definitions(-D__STDC_FORMAT_MACROS) - add_definitions(-D__STDC_LIMIT_MACROS) - add_definitions(/FI"stdint.h") - endif(HAVE_STDINT_H) -endif() find_package(FLEX REQUIRED) find_package(BISON REQUIRED) @@ -78,36 +71,37 @@ macro(THRIFT_ADD_COMPILER name description initial) endmacro() # The following compiler can be enabled or disabled +THRIFT_ADD_COMPILER(as3 "Enable compiler for ActionScript 3" ON) THRIFT_ADD_COMPILER(c_glib "Enable compiler for C with Glib" ON) +THRIFT_ADD_COMPILER(cl "Enable compiler for Common LISP" ON) +THRIFT_ADD_COMPILER(cocoa "Enable compiler for Cocoa Objective-C" ON) THRIFT_ADD_COMPILER(cpp "Enable compiler for C++" ON) -THRIFT_ADD_COMPILER(java "Enable compiler for Java" ON) -THRIFT_ADD_COMPILER(as3 "Enable compiler for ActionScript 3" ON) -THRIFT_ADD_COMPILER(dart "Enable compiler for Dart" ON) -THRIFT_ADD_COMPILER(haxe "Enable compiler for Haxe" ON) THRIFT_ADD_COMPILER(csharp "Enable compiler for C#" ON) -THRIFT_ADD_COMPILER(netcore "Enable compiler for .NET Core" ON) -THRIFT_ADD_COMPILER(py "Enable compiler for Python 2.0" ON) -THRIFT_ADD_COMPILER(rb "Enable compiler for Ruby" ON) -THRIFT_ADD_COMPILER(perl "Enable compiler for Perl" ON) -THRIFT_ADD_COMPILER(php "Enable compiler for PHP" ON) +THRIFT_ADD_COMPILER(d "Enable compiler for D" ON) +THRIFT_ADD_COMPILER(dart "Enable compiler for Dart" ON) +THRIFT_ADD_COMPILER(delphi "Enable compiler for Delphi" ON) THRIFT_ADD_COMPILER(erl "Enable compiler for Erlang" ON) -THRIFT_ADD_COMPILER(cocoa "Enable compiler for Cocoa Objective-C" ON) -THRIFT_ADD_COMPILER(swift "Enable compiler for Cocoa Swift" ON) -THRIFT_ADD_COMPILER(st "Enable compiler for Smalltalk" ON) -THRIFT_ADD_COMPILER(ocaml "Enable compiler for OCaml" ON) +THRIFT_ADD_COMPILER(go "Enable compiler for Go" ON) +THRIFT_ADD_COMPILER(gv "Enable compiler for GraphViz" ON) +THRIFT_ADD_COMPILER(haxe "Enable compiler for Haxe" ON) THRIFT_ADD_COMPILER(hs "Enable compiler for Haskell" ON) -THRIFT_ADD_COMPILER(xsd "Enable compiler for XSD" ON) THRIFT_ADD_COMPILER(html "Enable compiler for HTML Documentation" ON) +THRIFT_ADD_COMPILER(java "Enable compiler for Java" ON) +THRIFT_ADD_COMPILER(javame "Enable compiler for Java ME" ON) THRIFT_ADD_COMPILER(js "Enable compiler for JavaScript" ON) THRIFT_ADD_COMPILER(json "Enable compiler for JSON" ON) -THRIFT_ADD_COMPILER(javame "Enable compiler for Java ME" ON) -THRIFT_ADD_COMPILER(delphi "Enable compiler for Delphi" ON) -THRIFT_ADD_COMPILER(go "Enable compiler for Go" ON) -THRIFT_ADD_COMPILER(d "Enable compiler for D" ON) THRIFT_ADD_COMPILER(lua "Enable compiler for Lua" ON) -THRIFT_ADD_COMPILER(gv "Enable compiler for GraphViz" ON) +THRIFT_ADD_COMPILER(netcore "Enable compiler for .NET Core" ON) +THRIFT_ADD_COMPILER(ocaml "Enable compiler for OCaml" ON) +THRIFT_ADD_COMPILER(perl "Enable compiler for Perl" ON) +THRIFT_ADD_COMPILER(php "Enable compiler for PHP" ON) +THRIFT_ADD_COMPILER(py "Enable compiler for Python 2.0" ON) +THRIFT_ADD_COMPILER(rb "Enable compiler for Ruby" ON) THRIFT_ADD_COMPILER(rs "Enable compiler for Rust" ON) +THRIFT_ADD_COMPILER(st "Enable compiler for Smalltalk" ON) +THRIFT_ADD_COMPILER(swift "Enable compiler for Cocoa Swift" ON) THRIFT_ADD_COMPILER(xml "Enable compiler for XML" ON) +THRIFT_ADD_COMPILER(xsd "Enable compiler for XSD" ON) # Thrift is looking for include files in the src directory # we also add the current binary directory for generated files diff --git a/compiler/cpp/test/CMakeLists.txt b/compiler/cpp/test/CMakeLists.txt index 572b55890d4..373cb78f075 100644 --- a/compiler/cpp/test/CMakeLists.txt +++ b/compiler/cpp/test/CMakeLists.txt @@ -31,18 +31,10 @@ if(${WITH_PLUGIN}) plugin/conversion_test.cc ) add_executable(plugintest ${plugintest_SOURCES}) - if(WITH_SHARED_LIB AND NOT MSVC) - target_link_libraries(plugintest - thriftc - ${Boost_LIBRARIES} - ) - else() - target_link_libraries(plugintest - thriftc_static - thrift_static - ${Boost_LIBRARIES} - ) - endif() + target_link_libraries(plugintest + thriftc + ${Boost_LIBRARIES} + ) add_test(NAME PluginUnitTest COMMAND plugintest) set(thrift-gen-mycpp_SOURCES @@ -50,11 +42,7 @@ if(${WITH_PLUGIN}) plugin/cpp_plugin.cc ) add_executable(thrift-gen-mycpp ${thrift-gen-mycpp_SOURCES}) - if(WITH_SHARED_LIB AND NOT MSVC) - target_link_libraries(thrift-gen-mycpp thriftc) - else() - target_link_libraries(thrift-gen-mycpp thriftc_static thrift_static) - endif() + target_link_libraries(thrift-gen-mycpp thriftc) if(CMAKE_BUILD_TYPE STREQUAL "Debug") set(BUILDTYPE "Debug") @@ -91,5 +79,9 @@ foreach(LANG ${thrift_compiler_LANGS}) endforeach() -find_package(PythonInterp REQUIRED) -add_test(NAME StalenessCheckTest COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/compiler/staleness_check.py ${THRIFT_COMPILER}) +find_package(PythonInterp QUIET) +if(PYTHONINTERP_FOUND) + add_test(NAME StalenessCheckTest COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/compiler/staleness_check.py ${THRIFT_COMPILER}) +else() + message(WARNING "Skipping StalenessCheckTest as there is no python interpreter available.") +endif() \ No newline at end of file diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index e12c08ce2fd..8e5ebcf61c7 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -158,8 +158,8 @@ if(WITH_LIBEVENT) include_directories(SYSTEM ${LIBEVENT_INCLUDE_DIRS}) ADD_LIBRARY_THRIFT(thriftnb ${thriftcppnb_SOURCES}) + LINK_AGAINST_THRIFT_LIBRARY(thriftnb thrift) TARGET_LINK_LIBRARIES_THRIFT(thriftnb ${SYSLIBS} ${LIBEVENT_LIBRARIES}) - TARGET_LINK_LIBRARIES_THRIFT_AGAINST_THRIFT_LIBRARY(thriftnb thrift) endif() if(WITH_ZLIB) diff --git a/lib/cpp/README.md b/lib/cpp/README.md index 5806f7b4a56..bc47d2d6d0f 100755 --- a/lib/cpp/README.md +++ b/lib/cpp/README.md @@ -240,8 +240,13 @@ run the tests. This means the header thrift/stdcxx.h has been removed and anything that relied on it has been changed to directly use C++11 concepts. The classes BoostThreadFactory, PosixThreadFactory, StdThreadFactory, and -PlatformThreadFactory will all be removed, and we will use a ThreadFactory -based on C++11. +PlatformThreadFactory have been removed, and we will use a ThreadFactory +based on C++11 (essentially StdThreadFactory was renamed ThreadFactory). + +The CMake build options WITH_SHARED_LIBS and WITH_STATIC_LIBS are deprecated. +The project no longer performs a side-by-side static and shared build; you +tell CMake through BUILD_SHARED_LIBS whether to make shared or static +libraries now. This is CMake standard behavior. ## 0.11.0 diff --git a/lib/cpp/src/thrift/TOutput.cpp b/lib/cpp/src/thrift/TOutput.cpp index ae3a9e28220..af36137b4c9 100644 --- a/lib/cpp/src/thrift/TOutput.cpp +++ b/lib/cpp/src/thrift/TOutput.cpp @@ -29,6 +29,8 @@ namespace thrift { TOutput GlobalOutput; +TOutput::TOutput() : f_(&errorTimeWrapper) {} + void TOutput::printf(const char* message, ...) { #ifndef THRIFT_SQUELCH_CONSOLE_OUTPUT // Try to reduce heap usage, even if printf is called rarely. diff --git a/lib/cpp/src/thrift/TOutput.h b/lib/cpp/src/thrift/TOutput.h index 1375f737d54..6135cfa15ee 100644 --- a/lib/cpp/src/thrift/TOutput.h +++ b/lib/cpp/src/thrift/TOutput.h @@ -25,7 +25,7 @@ namespace thrift { class TOutput { public: - TOutput() : f_(&errorTimeWrapper) {} + TOutput(); inline void setOutputFunction(void (*function)(const char*)) { f_ = function; } diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp index 4576fa16672..db407f2c666 100644 --- a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp @@ -898,7 +898,7 @@ uint32_t TJSONProtocol::readJSONDouble(double& num) { } try { num = fromString(str); - } catch (std::runtime_error& e) { + } catch (const std::runtime_error&) { throw TProtocolException(TProtocolException::INVALID_DATA, "Expected numeric value; got \"" + str + "\""); } @@ -911,7 +911,7 @@ uint32_t TJSONProtocol::readJSONDouble(double& num) { result += readJSONNumericChars(str); try { num = fromString(str); - } catch (std::runtime_error& e) { + } catch (const std::runtime_error&) { throw TProtocolException(TProtocolException::INVALID_DATA, "Expected numeric value; got \"" + str + "\""); } From 17355425429274e7971fff39d7e45279cdf550fa Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 11 Jan 2019 23:06:08 -0500 Subject: [PATCH 135/756] THRIFT-4735: Remove Qt4 build support --- CHANGES.md | 4 +++ build/cmake/DefineOptions.cmake | 8 ----- build/cmake/DefinePlatformSpecifc.cmake | 12 +++----- build/veralign.sh | 1 + compiler/cpp/src/thrift/main.cc | 2 +- configure.ac | 15 ---------- contrib/Vagrantfile | 2 +- lib/cpp/CMakeLists.txt | 22 ++------------ lib/cpp/Makefile.am | 19 +----------- lib/cpp/README.md | 6 ++++ lib/cpp/test/CMakeLists.txt | 12 -------- lib/cpp/thrift-qt.pc.in | 30 ------------------- lib/swift/Tests/ThriftTests/ThriftTests.swift | 2 +- 13 files changed, 21 insertions(+), 114 deletions(-) delete mode 100755 lib/cpp/thrift-qt.pc.in diff --git a/CHANGES.md b/CHANGES.md index ef6f240a379..7d76413cc1d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,10 @@ - [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - Java changes to UTF-8 handling require JDK 1.7 at a minimum - [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - Java class org.apache.thrift.ShortStack is no longer public - [THRIFT-4720](https://issues.apache.org/jira/browse/THRIFT-4720) - C++03/C++98 support has been removed; also removed boost as a runtime dependency +- [THRIFT-4730](https://issues.apache.org/jira/browse/THRIFT-4730) - C++: BoostThreadFactory, PosixThreadFactory, StdThreadFactory removed +- [THRIFT-4732](https://issues.apache.org/jira/browse/THRIFT-4732) - C++: CMake build changed to use BUILD_SHARED_LIBS +- [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735] - C++: Removed Qt4 support + ### Known Isues (Blocker or Critical) ## 0.12.0 diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 19cb104e872..e9b094c7bdc 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -62,16 +62,9 @@ if(WITH_CPP) find_package(Libevent QUIET) CMAKE_DEPENDENT_OPTION(WITH_LIBEVENT "Build with libevent support" ON "Libevent_FOUND" OFF) - find_package(Qt4 QUIET COMPONENTS QtCore QtNetwork) - CMAKE_DEPENDENT_OPTION(WITH_QT4 "Build with Qt4 support" ON - "QT4_FOUND" OFF) find_package(Qt5 QUIET COMPONENTS Core Network) CMAKE_DEPENDENT_OPTION(WITH_QT5 "Build with Qt5 support" ON "Qt5_FOUND" OFF) - if(${WITH_QT4} AND ${WITH_QT5} AND ${CMAKE_MAJOR_VERSION} LESS 3) - # cmake < 3.0.0 causes conflict when building both Qt4 and Qt5 - set(WITH_QT4 OFF) - endif() find_package(OpenSSL QUIET) CMAKE_DEPENDENT_OPTION(WITH_OPENSSL "Build with OpenSSL support" ON "OPENSSL_FOUND" OFF) @@ -185,7 +178,6 @@ if (BUILD_CPP) message(STATUS " Library features:") message(STATUS " Build shared libraries: ${BUILD_SHARED_LIBS}") message(STATUS " Build with libevent support: ${WITH_LIBEVENT}") - message(STATUS " Build with Qt4 support: ${WITH_QT4}") message(STATUS " Build with Qt5 support: ${WITH_QT5}") message(STATUS " Build with ZLIB support: ${WITH_ZLIB}") endif () diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index ac33e2900c6..298780c97e2 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -59,22 +59,18 @@ if(MSVC) foreach(CompilerFlag ${CompilerFlags}) string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") endforeach() - set(THRIFT_RUNTIME_POSTFIX "mt" CACHE STRING "Set static library postfix" FORCE) + set(THRIFT_RUNTIME_POSTFIX "mt" CACHE STRING "Set runtime library postfix" FORCE) else(WITH_MT) - set(THRIFT_RUNTIME_POSTFIX "md" CACHE STRING "Set static library postfix" FORCE) + set(THRIFT_RUNTIME_POSTFIX "md" CACHE STRING "Set runtime library postfix" FORCE) endif(WITH_MT) # Disable boost auto linking pragmas - cmake includes the right files add_definitions("-DBOOST_ALL_NO_LIB") - # Windows build does not know how to make a shared library yet - # as there are no __declspec(dllexport) or exports files in the project. - if (WITH_SHARED_LIB) - message (FATAL_ERROR "Windows build does not support shared library output yet, please set -DWITH_SHARED_LIB=off") - endif() - add_definitions("/MP") # parallel build add_definitions("/W3") # warning level 3 + + add_definitions("-DUNICODE -D_UNICODE") elseif(UNIX) find_program( MEMORYCHECK_COMMAND valgrind ) set( MEMORYCHECK_COMMAND_OPTIONS "--gen-suppressions=all --leak-check=full" ) diff --git a/build/veralign.sh b/build/veralign.sh index b9c1e71bfbe..4ed7c5174af 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -85,6 +85,7 @@ FILES[lib/rb/thrift.gemspec]=simpleReplace FILES[lib/rs/Cargo.toml]=simpleReplace FILES[lib/st/package.xml]=simpleReplace FILES[lib/swift/Sources/Thrift.swift]=simpleReplace +FILES[lib/swift/Tests/ThriftTests/ThriftTests.swift]=simpleReplace FILES[package.json]=jsonReplace FILES[sonar-project.properties]=simpleReplace FILES[test/csharp/Properties/AssemblyInfo.cs]=simpleReplace diff --git a/compiler/cpp/src/thrift/main.cc b/compiler/cpp/src/thrift/main.cc index cdc171c7adf..eddbd56b03e 100644 --- a/compiler/cpp/src/thrift/main.cc +++ b/compiler/cpp/src/thrift/main.cc @@ -171,7 +171,7 @@ char* saferealpath(const char* path, char* resolved_path) { #ifdef _WIN32 char buf[MAX_PATH]; char* basename; - DWORD len = GetFullPathName(path, MAX_PATH, buf, &basename); + DWORD len = GetFullPathNameA(path, MAX_PATH, buf, &basename); if (len == 0 || len > MAX_PATH - 1) { strcpy(resolved_path, path); } else { diff --git a/configure.ac b/configure.ac index 21746292b27..d229734a8ad 100755 --- a/configure.ac +++ b/configure.ac @@ -161,18 +161,6 @@ if test "$with_cpp" = "yes"; then AX_LIB_ZLIB([1.2.3]) have_zlib=$success - AX_THRIFT_LIB(qt4, [Qt], yes) - have_qt=no - if test "$with_qt4" = "yes"; then - PKG_CHECK_MODULES([QT], [QtCore >= 4.3, QtNetwork >= 4.3], have_qt=yes, have_qt=no) - fi - if test "$have_qt" = "yes"; then - AC_PATH_PROGS([QT_MOC], [moc-qt4 moc], "fail") - if test "$QT_MOC" = "fail"; then - have_qt=no - fi - fi - AX_THRIFT_LIB(qt5, [Qt5], yes) have_qt5=no qt_reduce_reloc="" @@ -191,7 +179,6 @@ fi AM_CONDITIONAL([WITH_CPP], [test "$have_cpp" = "yes"]) AM_CONDITIONAL([AMX_HAVE_LIBEVENT], [test "$have_libevent" = "yes"]) AM_CONDITIONAL([AMX_HAVE_ZLIB], [test "$have_zlib" = "yes"]) -AM_CONDITIONAL([AMX_HAVE_QT], [test "$have_qt" = "yes"]) AM_CONDITIONAL([AMX_HAVE_QT5], [test "$have_qt5" = "yes"]) AM_CONDITIONAL([QT5_REDUCE_RELOCATIONS], [test "x$qt_reduce_reloc" != "x"]) @@ -811,7 +798,6 @@ AC_CONFIG_FILES([ lib/cpp/test/Makefile lib/cpp/thrift-nb.pc lib/cpp/thrift-z.pc - lib/cpp/thrift-qt.pc lib/cpp/thrift-qt5.pc lib/cpp/thrift.pc lib/c_glib/Makefile @@ -971,7 +957,6 @@ if test "$have_cpp" = "yes" ; then echo " C++ compiler .............. : $CXX" echo " Build TZlibTransport ...... : $have_zlib" echo " Build TNonblockingServer .. : $have_libevent" - echo " Build TQTcpServer (Qt4) ... : $have_qt" echo " Build TQTcpServer (Qt5) ... : $have_qt5" echo " C++ compiler version ...... : $($CXX --version | head -1)" fi diff --git a/contrib/Vagrantfile b/contrib/Vagrantfile index ff53316bb02..b340563330f 100644 --- a/contrib/Vagrantfile +++ b/contrib/Vagrantfile @@ -37,7 +37,7 @@ sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -qq -y # Install Dependencies # --- # General dependencies -sudo apt-get install -qq automake libtool flex bison pkg-config g++ libssl-dev make libqt4-dev git debhelper +sudo apt-get install -qq automake libtool flex bison pkg-config g++ libssl-dev make git debhelper # C++ dependencies sudo apt-get install -qq libboost-dev libboost-test-dev libboost-program-options-dev libboost-filesystem-dev libboost-system-dev libevent-dev diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index 8e5ebcf61c7..90a6c28855c 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -94,8 +94,7 @@ else() ) endif() -# If OpenSSL is not found just ignore the OpenSSL stuff -find_package(OpenSSL) +# If OpenSSL is not found or disabled just ignore the OpenSSL stuff if(OPENSSL_FOUND AND WITH_OPENSSL) list( APPEND thriftcpp_SOURCES src/thrift/transport/TSSLSocket.cpp @@ -128,7 +127,7 @@ set( thriftcppnb_SOURCES src/thrift/async/TEvhttpClientChannel.cpp ) -# Thrift zlib server +# Thrift zlib transport set( thriftcppz_SOURCES src/thrift/transport/TZlibTransport.cpp src/thrift/protocol/THeaderProtocol.cpp @@ -137,12 +136,6 @@ set( thriftcppz_SOURCES src/thrift/transport/THeaderTransport.cpp ) -# Thrift Qt4 server -set( thriftcppqt_SOURCES - src/thrift/qt/TQIODeviceTransport.cpp - src/thrift/qt/TQTcpServer.cpp -) - # Contains the thrift specific ADD_LIBRARY_THRIFT and TARGET_LINK_LIBRARIES_THRIFT include(ThriftMacros) @@ -171,16 +164,7 @@ if(WITH_ZLIB) TARGET_LINK_LIBRARIES_THRIFT_AGAINST_THRIFT_LIBRARY(thriftz thrift) endif() -if(WITH_QT4) - set(CMAKE_AUTOMOC ON) - find_package(Qt4 REQUIRED COMPONENTS QtCore QtNetwork) - ADD_LIBRARY_THRIFT(thriftqt ${thriftcppqt_SOURCES}) - TARGET_LINK_LIBRARIES_THRIFT(thriftqt ${SYSLIBS} Qt4::QtCore Qt4::QtNetwork) - TARGET_LINK_LIBRARIES_THRIFT_AGAINST_THRIFT_LIBRARY(thriftqt thrift) -endif() - if(WITH_QT5) - # Qt5 has its own directory to avoid conflict with Qt4 caused by CMAKE_AUTOMOC add_subdirectory(src/thrift/qt) endif() @@ -188,8 +172,6 @@ if(MSVC) add_definitions("-DUNICODE -D_UNICODE") endif() -add_definitions("-D__STDC_LIMIT_MACROS") - # Install the headers install(DIRECTORY "src/thrift" DESTINATION "${INCLUDE_INSTALL_DIR}" FILES_MATCHING PATTERN "*.h" PATTERN "*.tcc") diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index 19bedd75385..de0c058c1ce 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -19,9 +19,6 @@ AUTOMAKE_OPTIONS = subdir-objects -moc_%.cpp: %.h - $(QT_MOC) $(QT_CFLAGS) $< -o $@ - moc__%.cpp: %.h $(QT5_MOC) $(QT5_CFLAGS) $< -o $@ @@ -52,10 +49,6 @@ if AMX_HAVE_ZLIB lib_LTLIBRARIES += libthriftz.la pkgconfig_DATA += thrift-z.pc endif -if AMX_HAVE_QT -lib_LTLIBRARIES += libthriftqt.la -pkgconfig_DATA += thrift-qt.pc -endif if AMX_HAVE_QT5 lib_LTLIBRARIES += libthriftqt5.la pkgconfig_DATA += thrift-qt5.pc @@ -120,33 +113,24 @@ libthriftz_la_SOURCES = src/thrift/transport/TZlibTransport.cpp \ src/thrift/protocol/THeaderProtocol.cpp -libthriftqt_la_MOC = src/thrift/qt/moc_TQTcpServer.cpp -nodist_libthriftqt_la_SOURCES = $(libthriftqt_la_MOC) -libthriftqt_la_SOURCES = src/thrift/qt/TQIODeviceTransport.cpp \ - src/thrift/qt/TQTcpServer.cpp -CLEANFILES = $(libthriftqt_la_MOC) - libthriftqt5_la_MOC = src/thrift/qt/moc__TQTcpServer.cpp nodist_libthriftqt5_la_SOURCES = $(libthriftqt5_la_MOC) libthriftqt5_la_SOURCES = src/thrift/qt/TQIODeviceTransport.cpp \ src/thrift/qt/TQTcpServer.cpp -CLEANFILES += $(libthriftqt5_la_MOC) +CLEANFILES = $(libthriftqt5_la_MOC) # Flags for the various libraries libthriftnb_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBEVENT_CPPFLAGS) libthriftz_la_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CPPFLAGS) -libthriftqt_la_CPPFLAGS = $(AM_CPPFLAGS) $(QT_CFLAGS) libthriftqt5_la_CPPFLAGS = $(AM_CPPFLAGS) $(QT5_CFLAGS) if QT5_REDUCE_RELOCATIONS libthriftqt5_la_CPPFLAGS += -fPIC endif libthriftnb_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftz_la_CXXFLAGS = $(AM_CXXFLAGS) -libthriftqt_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftqt5_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftnb_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) libthriftz_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(ZLIB_LIBS) -libthriftqt_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(QT_LIBS) libthriftqt5_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(QT5_LIBS) include_thriftdir = $(includedir)/thrift @@ -269,7 +253,6 @@ EXTRA_DIST = \ thrift-nb.pc.in \ thrift.pc.in \ thrift-z.pc.in \ - thrift-qt.pc.in \ thrift-qt5.pc.in \ src/thrift/qt/CMakeLists.txt \ $(WINDOWS_DIST) diff --git a/lib/cpp/README.md b/lib/cpp/README.md index bc47d2d6d0f..ce46319b915 100755 --- a/lib/cpp/README.md +++ b/lib/cpp/README.md @@ -231,6 +231,7 @@ Support for Boost at runtime was deprecated. ## 1.0.0 +THRIFT-4720: Support for C++03/C++98 has been dropped. Use version 0.12.0 to support that language level. As a consequence, boost is no longer required as a runtime library depenedency, but is is still required to build the runtime library @@ -239,15 +240,20 @@ build dependency for folks who just want to build the runtime and not run the tests. This means the header thrift/stdcxx.h has been removed and anything that relied on it has been changed to directly use C++11 concepts. +THRIFT-4730: The classes BoostThreadFactory, PosixThreadFactory, StdThreadFactory, and PlatformThreadFactory have been removed, and we will use a ThreadFactory based on C++11 (essentially StdThreadFactory was renamed ThreadFactory). +THRIFT-4732: The CMake build options WITH_SHARED_LIBS and WITH_STATIC_LIBS are deprecated. The project no longer performs a side-by-side static and shared build; you tell CMake through BUILD_SHARED_LIBS whether to make shared or static libraries now. This is CMake standard behavior. +THRIFT-4735: +Qt4 support was removed. + ## 0.11.0 Older versions of thrift depended on the classes which diff --git a/lib/cpp/test/CMakeLists.txt b/lib/cpp/test/CMakeLists.txt index 8a8aadad10d..ef08dbce225 100644 --- a/lib/cpp/test/CMakeLists.txt +++ b/lib/cpp/test/CMakeLists.txt @@ -336,18 +336,6 @@ add_test(NAME SecurityTest COMMAND SecurityTest -- "${CMAKE_CURRENT_SOURCE_DIR}/ endif() -if(WITH_QT4) -set(CMAKE_AUTOMOC ON) -find_package(Qt4 REQUIRED COMPONENTS QtTest) -set(TQTcpServerTest_SOURCES - qt/TQTcpServerTest.cpp -) -add_executable(TQTcpServerTest ${TQTcpServerTest_SOURCES}) -target_link_libraries(TQTcpServerTest testgencpp_cob thriftqt Qt4::QtTest) -LINK_AGAINST_THRIFT_LIBRARY(TQTcpServerTest thrift) -add_test(NAME TQTcpServerTest COMMAND TQTcpServerTest) -endif() - if(WITH_QT5) add_subdirectory(qt) endif() diff --git a/lib/cpp/thrift-qt.pc.in b/lib/cpp/thrift-qt.pc.in deleted file mode 100755 index 5e60d840d39..00000000000 --- a/lib/cpp/thrift-qt.pc.in +++ /dev/null @@ -1,30 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: Thrift -Description: Thrift Qt API -Version: @VERSION@ -Requires: thrift = @VERSION@ -Libs: -L${libdir} -lthriftqt -Cflags: -I${includedir} diff --git a/lib/swift/Tests/ThriftTests/ThriftTests.swift b/lib/swift/Tests/ThriftTests/ThriftTests.swift index 9316100180a..8f0b1fe183b 100644 --- a/lib/swift/Tests/ThriftTests/ThriftTests.swift +++ b/lib/swift/Tests/ThriftTests/ThriftTests.swift @@ -3,7 +3,7 @@ import XCTest class ThriftTests: XCTestCase { func testVersion() { - XCTAssertEqual(Thrift().version, "1.1.0") + XCTAssertEqual(Thrift().version, "1.0.0") } func test_in_addr_extension() { From f3ec277e7e2c147342831ecec590bc2f71b07761 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 12 Jan 2019 11:52:04 -0500 Subject: [PATCH 136/756] Fix cygwin builds on appveyor --- appveyor.yml | 11 ++--------- build/appveyor/CYGW-appveyor-build.bat | 6 ++++-- build/appveyor/CYGW-appveyor-install.bat | 12 +++++++++++- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4c0144cdcad..977ade6eb01 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -32,8 +32,6 @@ os: - Visual Studio 2017 matrix: - allow_failures: - - PROFILE: CYGWIN fast_finish: true environment: @@ -51,7 +49,7 @@ environment: - PROFILE: MSVC2015 PLATFORM: x86 - CONFIGURATION: Release + CONFIGURATION: Debug BUILD_SHARED_LIBS: OFF BOOST_VERSION: 1.62.0 LIBEVENT_VERSION: 2.0.22 @@ -67,15 +65,10 @@ environment: DISABLED_TESTS: StressTestNonBlocking - PROFILE: CYGWIN - PLATFORM: x86 + PLATFORM: x64 CONFIGURATION: RelWithDebInfo DISABLED_TESTS: (ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest|StressTestNonBlocking) -# - PROFILE: CYGWIN -# PLATFORM: x64 -# CONFIGURATION: RelWithDebInfo -# DISABLED_TESTS: (ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest|StressTestNonBlocking) - install: - cd %APPVEYOR_BUILD_FOLDER% - call build\appveyor\%PROFILE:~0,4%-appveyor-install.bat diff --git a/build/appveyor/CYGW-appveyor-build.bat b/build/appveyor/CYGW-appveyor-build.bat index fbcc84b0c42..7f332871433 100644 --- a/build/appveyor/CYGW-appveyor-build.bat +++ b/build/appveyor/CYGW-appveyor-build.bat @@ -23,11 +23,13 @@ SET CMAKEARGS=^ -G'%GENERATOR%' ^ -DCMAKE_BUILD_TYPE=%CONFIGURATION% ^ -DCMAKE_INSTALL_PREFIX=%INSTDIR% ^ - -DCMAKE_CXX_EXTENSIONS=ON ^ -DCMAKE_CXX_FLAGS="-D_GNU_SOURCE" ^ - -DCMAKE_CXX_STANDARD=11 ^ + -DWITH_JAVA=OFF ^ -DWITH_PYTHON=OFF +:: -DCMAKE_CXX_EXTENSIONS=ON ^ +:: -DCMAKE_CXX_STANDARD=11 ^ + @ECHO ON %BASH% -lc "mkdir -p %BUILDDIR% && cd %BUILDDIR% && cmake.exe %SRCDIR% %CMAKEARGS% && cmake --build . --config %CONFIGURATION% --target install" || EXIT /B @ECHO OFF diff --git a/build/appveyor/CYGW-appveyor-install.bat b/build/appveyor/CYGW-appveyor-install.bat index 77db7d40a7e..79b6ef06bc0 100644 --- a/build/appveyor/CYGW-appveyor-install.bat +++ b/build/appveyor/CYGW-appveyor-install.bat @@ -31,4 +31,14 @@ CALL cl_showenv.bat || EXIT /B %BASH% -lc "wget rawgit.com/transcode-open/apt-cyg/master/apt-cyg && install apt-cyg /bin && rm -f apt-cyg" || EXIT /B %BASH% -lc "apt-cyg update" || EXIT /B -%BASH% -lc "apt-cyg install bison cmake flex gcc-g++ libboost-devel libevent-devel make openssl-devel zlib-devel" +%BASH% -lc "apt-cyg install bison cmake flex gcc-g++ libboost-devel libevent-devel make openssl-devel xz zlib-devel" + +:: +:: We need a newer version of cmake, the one cygwin provides is too old +:: to recognize the version of boost. Luckily there is a pre-release +:: one available, however cygwin's own setup program has no command line +:: option to allow access to test packages! +:: + +%BASH% -lc "apt-cyg remove cmake" +%BASH% -lc "cd / && wget http://mirror.clarkson.edu/cygwin/x86_64/release/cmake/cmake-3.13.1-1.tar.xz && tar xJf cmake-3.13.1-1.tar.xz && hash -r && cmake --version" From 234fb47229dad47842e97a599614dbbd81b7c4a2 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sun, 13 Jan 2019 23:19:18 -0500 Subject: [PATCH 137/756] THRIFT-4719: remove cocoa --- Thrift-swift3.podspec | 16 - Thrift.podspec | 10 +- build/docker/README.md | 1 - build/veralign.sh | 3 +- compiler/cpp/CMakeLists.txt | 1 - compiler/cpp/Makefile.am | 45 +- compiler/cpp/compiler.vcxproj | 10 +- .../src/thrift/generate/t_cocoa_generator.cc | 3309 ----------------- compiler/cpp/src/thrift/thriftl.ll | 5 +- compiler/cpp/tests/CMakeLists.txt | 40 +- contrib/thrift.spec | 4 +- debian/copyright | 1 - doap.rdf | 3 +- doc/specs/idl.md | 32 +- lib/Makefile.am | 1 - lib/cocoa/README.md | 21 - lib/cocoa/coding_standards.md | 1 - lib/cocoa/src/TApplicationError.h | 55 - lib/cocoa/src/TApplicationError.m | 231 -- lib/cocoa/src/TBaseClient.h | 27 - lib/cocoa/src/TBaseClient.m | 51 - lib/cocoa/src/TBinary.swift | 122 - lib/cocoa/src/TEnum.swift | 31 - lib/cocoa/src/TError.h | 23 - lib/cocoa/src/TError.m | 23 - lib/cocoa/src/TList.swift | 148 - lib/cocoa/src/TMap.swift | 158 - lib/cocoa/src/TProcessor.h | 35 - lib/cocoa/src/TProcessorFactory.h | 33 - lib/cocoa/src/TProtocol.swift | 190 - lib/cocoa/src/TSerializable.swift | 178 - lib/cocoa/src/TSet.swift | 161 - lib/cocoa/src/TSharedProcessorFactory.h | 28 - lib/cocoa/src/TSharedProcessorFactory.m | 49 - lib/cocoa/src/TStruct.swift | 31 - lib/cocoa/src/Thrift.h | 20 - lib/cocoa/src/protocol/TBase.h | 46 - lib/cocoa/src/protocol/TBinaryProtocol.h | 49 - lib/cocoa/src/protocol/TBinaryProtocol.m | 740 ---- lib/cocoa/src/protocol/TCompactProtocol.h | 42 - lib/cocoa/src/protocol/TCompactProtocol.m | 983 ----- lib/cocoa/src/protocol/TMultiplexedProtocol.h | 38 - lib/cocoa/src/protocol/TMultiplexedProtocol.m | 66 - lib/cocoa/src/protocol/TProtocol.h | 164 - lib/cocoa/src/protocol/TProtocolDecorator.h | 34 - lib/cocoa/src/protocol/TProtocolDecorator.m | 295 -- lib/cocoa/src/protocol/TProtocolError.h | 76 - lib/cocoa/src/protocol/TProtocolError.m | 33 - lib/cocoa/src/protocol/TProtocolFactory.h | 36 - lib/cocoa/src/protocol/TProtocolUtil.h | 33 - lib/cocoa/src/protocol/TProtocolUtil.m | 171 - lib/cocoa/src/server/TSocketServer.h | 51 - lib/cocoa/src/server/TSocketServer.m | 239 -- lib/cocoa/src/transport/TAsyncTransport.h | 46 - lib/cocoa/src/transport/TFramedTransport.h | 33 - lib/cocoa/src/transport/TFramedTransport.m | 180 - .../src/transport/THTTPSessionTransport.h | 47 - .../src/transport/THTTPSessionTransport.m | 268 -- lib/cocoa/src/transport/THTTPTransport.h | 39 - lib/cocoa/src/transport/THTTPTransport.m | 182 - lib/cocoa/src/transport/TMemoryBuffer.h | 37 - lib/cocoa/src/transport/TMemoryBuffer.m | 121 - .../src/transport/TNSFileHandleTransport.h | 38 - .../src/transport/TNSFileHandleTransport.m | 118 - lib/cocoa/src/transport/TNSStreamTransport.h | 43 - lib/cocoa/src/transport/TNSStreamTransport.m | 153 - lib/cocoa/src/transport/TSSLSocketTransport.h | 37 - lib/cocoa/src/transport/TSSLSocketTransport.m | 304 -- .../src/transport/TSSLSocketTransportError.h | 30 - .../src/transport/TSSLSocketTransportError.m | 23 - lib/cocoa/src/transport/TSocketTransport.h | 36 - lib/cocoa/src/transport/TSocketTransport.m | 131 - lib/cocoa/src/transport/TTransport.h | 48 - lib/cocoa/src/transport/TTransportError.h | 43 - lib/cocoa/src/transport/TTransportError.m | 27 - lib/cpp/test/OneWayTest.thrift | 1 - test/ThriftTest.thrift | 19 +- 77 files changed, 71 insertions(+), 10126 deletions(-) delete mode 100644 Thrift-swift3.podspec delete mode 100644 compiler/cpp/src/thrift/generate/t_cocoa_generator.cc delete mode 100644 lib/cocoa/README.md delete mode 100644 lib/cocoa/coding_standards.md delete mode 100644 lib/cocoa/src/TApplicationError.h delete mode 100644 lib/cocoa/src/TApplicationError.m delete mode 100644 lib/cocoa/src/TBaseClient.h delete mode 100644 lib/cocoa/src/TBaseClient.m delete mode 100644 lib/cocoa/src/TBinary.swift delete mode 100644 lib/cocoa/src/TEnum.swift delete mode 100644 lib/cocoa/src/TError.h delete mode 100644 lib/cocoa/src/TError.m delete mode 100644 lib/cocoa/src/TList.swift delete mode 100644 lib/cocoa/src/TMap.swift delete mode 100644 lib/cocoa/src/TProcessor.h delete mode 100644 lib/cocoa/src/TProcessorFactory.h delete mode 100644 lib/cocoa/src/TProtocol.swift delete mode 100644 lib/cocoa/src/TSerializable.swift delete mode 100644 lib/cocoa/src/TSet.swift delete mode 100644 lib/cocoa/src/TSharedProcessorFactory.h delete mode 100644 lib/cocoa/src/TSharedProcessorFactory.m delete mode 100644 lib/cocoa/src/TStruct.swift delete mode 100644 lib/cocoa/src/Thrift.h delete mode 100644 lib/cocoa/src/protocol/TBase.h delete mode 100644 lib/cocoa/src/protocol/TBinaryProtocol.h delete mode 100644 lib/cocoa/src/protocol/TBinaryProtocol.m delete mode 100644 lib/cocoa/src/protocol/TCompactProtocol.h delete mode 100644 lib/cocoa/src/protocol/TCompactProtocol.m delete mode 100644 lib/cocoa/src/protocol/TMultiplexedProtocol.h delete mode 100644 lib/cocoa/src/protocol/TMultiplexedProtocol.m delete mode 100644 lib/cocoa/src/protocol/TProtocol.h delete mode 100644 lib/cocoa/src/protocol/TProtocolDecorator.h delete mode 100644 lib/cocoa/src/protocol/TProtocolDecorator.m delete mode 100644 lib/cocoa/src/protocol/TProtocolError.h delete mode 100644 lib/cocoa/src/protocol/TProtocolError.m delete mode 100644 lib/cocoa/src/protocol/TProtocolFactory.h delete mode 100644 lib/cocoa/src/protocol/TProtocolUtil.h delete mode 100644 lib/cocoa/src/protocol/TProtocolUtil.m delete mode 100644 lib/cocoa/src/server/TSocketServer.h delete mode 100644 lib/cocoa/src/server/TSocketServer.m delete mode 100644 lib/cocoa/src/transport/TAsyncTransport.h delete mode 100644 lib/cocoa/src/transport/TFramedTransport.h delete mode 100644 lib/cocoa/src/transport/TFramedTransport.m delete mode 100644 lib/cocoa/src/transport/THTTPSessionTransport.h delete mode 100644 lib/cocoa/src/transport/THTTPSessionTransport.m delete mode 100644 lib/cocoa/src/transport/THTTPTransport.h delete mode 100644 lib/cocoa/src/transport/THTTPTransport.m delete mode 100644 lib/cocoa/src/transport/TMemoryBuffer.h delete mode 100644 lib/cocoa/src/transport/TMemoryBuffer.m delete mode 100644 lib/cocoa/src/transport/TNSFileHandleTransport.h delete mode 100644 lib/cocoa/src/transport/TNSFileHandleTransport.m delete mode 100644 lib/cocoa/src/transport/TNSStreamTransport.h delete mode 100644 lib/cocoa/src/transport/TNSStreamTransport.m delete mode 100644 lib/cocoa/src/transport/TSSLSocketTransport.h delete mode 100644 lib/cocoa/src/transport/TSSLSocketTransport.m delete mode 100644 lib/cocoa/src/transport/TSSLSocketTransportError.h delete mode 100644 lib/cocoa/src/transport/TSSLSocketTransportError.m delete mode 100644 lib/cocoa/src/transport/TSocketTransport.h delete mode 100644 lib/cocoa/src/transport/TSocketTransport.m delete mode 100644 lib/cocoa/src/transport/TTransport.h delete mode 100644 lib/cocoa/src/transport/TTransportError.h delete mode 100644 lib/cocoa/src/transport/TTransportError.m diff --git a/Thrift-swift3.podspec b/Thrift-swift3.podspec deleted file mode 100644 index 126c00b24af..00000000000 --- a/Thrift-swift3.podspec +++ /dev/null @@ -1,16 +0,0 @@ -Pod::Spec.new do |s| - s.name = "Thrift-swift3" - s.version = "1.0.0" - s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC." - s.description = <<-DESC -The Apache Thrift scalable cross-language software framework for networked services development combines a software stack with a code generation engine to build services that work efficiently and seamlessly between many programming languages. - DESC - s.homepage = "http://thrift.apache.org" - s.license = { :type => 'Apache License, Version 2.0', :url => 'https://www.apache.org/licenses/LICENSE-2.0' } - s.author = { "Apache Thrift Developers" => "dev@thrift.apache.org" } - s.ios.deployment_target = '9.0' - s.osx.deployment_target = '10.10' - s.requires_arc = true - s.source = { :git => "https://github.com/apache/thrift.git", :tag => "v1.0.0" } - s.source_files = "lib/swift/Sources/*.swift" -end diff --git a/Thrift.podspec b/Thrift.podspec index a406eec230b..126c00b24af 100644 --- a/Thrift.podspec +++ b/Thrift.podspec @@ -1,5 +1,5 @@ Pod::Spec.new do |s| - s.name = "Thrift" + s.name = "Thrift-swift3" s.version = "1.0.0" s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC." s.description = <<-DESC @@ -8,11 +8,9 @@ The Apache Thrift scalable cross-language software framework for networked servi s.homepage = "http://thrift.apache.org" s.license = { :type => 'Apache License, Version 2.0', :url => 'https://www.apache.org/licenses/LICENSE-2.0' } s.author = { "Apache Thrift Developers" => "dev@thrift.apache.org" } + s.ios.deployment_target = '9.0' + s.osx.deployment_target = '10.10' s.requires_arc = true - s.ios.deployment_target = '7.0' - s.osx.deployment_target = '10.8' - s.ios.framework = 'CFNetwork' - s.osx.framework = 'CoreServices' s.source = { :git => "https://github.com/apache/thrift.git", :tag => "v1.0.0" } - s.source_files = 'lib/cocoa/src/**/*.{h,m,swift}' + s.source_files = "lib/swift/Sources/*.swift" end diff --git a/build/docker/README.md b/build/docker/README.md index 966d690c9de..d00f87d66fd 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -174,7 +174,6 @@ Last updated: October 1, 2017 | C# (mono) | 4.2.1.0 | 4.6.2.7 | | | c_glib | 2.48.2 | 2.56.0 | | | cl (sbcl) | | 1.4.15 | | -| cocoa | | | Not in CI | | d | 2.075.1 | 2.083.1 | | | dart | 1.22.1 | 1.24.3 | | | delphi | | | Not in CI | diff --git a/build/veralign.sh b/build/veralign.sh index 4ed7c5174af..c54de538b12 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -50,13 +50,12 @@ FILES[doap.rdf]=manual # These files can be updated automatically: FILES[ApacheThrift.nuspec]=simpleReplace FILES[CMakeLists.txt]=simpleReplace -FILES[Thrift-swift3.podspec]=simpleReplace FILES[Thrift.podspec]=simpleReplace FILES[appveyor.yml]=simpleReplace FILES[bower.json]=jsonReplace FILES[configure.ac]=configureReplace FILES[contrib/thrift.spec]=simpleReplace -FILES[lib/cocoa/src/Thrift.h]=simpleReplace +FILES[doc/specs/idl.md]=simpleReplace FILES[lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs]=simpleReplace FILES[lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj]=simpleReplace FILES[lib/csharp/src/Properties/AssemblyInfo.cs]=simpleReplace diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt index 96efe65ab56..372cbab75fe 100644 --- a/compiler/cpp/CMakeLists.txt +++ b/compiler/cpp/CMakeLists.txt @@ -74,7 +74,6 @@ endmacro() THRIFT_ADD_COMPILER(as3 "Enable compiler for ActionScript 3" ON) THRIFT_ADD_COMPILER(c_glib "Enable compiler for C with Glib" ON) THRIFT_ADD_COMPILER(cl "Enable compiler for Common LISP" ON) -THRIFT_ADD_COMPILER(cocoa "Enable compiler for Cocoa Objective-C" ON) THRIFT_ADD_COMPILER(cpp "Enable compiler for C++" ON) THRIFT_ADD_COMPILER(csharp "Enable compiler for C#" ON) THRIFT_ADD_COMPILER(d "Enable compiler for D" ON) diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am index 0b8ef2e7e19..087f6bdbd03 100644 --- a/compiler/cpp/Makefile.am +++ b/compiler/cpp/Makefile.am @@ -79,38 +79,37 @@ thrift_SOURCES = src/thrift/main.h \ src/thrift/audit/t_audit.h # Specific client generator source -thrift_SOURCES += src/thrift/generate/t_c_glib_generator.cc \ +thrift_SOURCES += src/thrift/generate/t_as3_generator.cc \ + src/thrift/generate/t_c_glib_generator.cc \ + src/thrift/generate/t_cl_generator.cc \ src/thrift/generate/t_cpp_generator.cc \ - src/thrift/generate/t_java_generator.cc \ - src/thrift/generate/t_json_generator.cc \ - src/thrift/generate/t_as3_generator.cc \ + src/thrift/generate/t_csharp_generator.cc \ + src/thrift/generate/t_d_generator.cc \ src/thrift/generate/t_dart_generator.cc \ + src/thrift/generate/t_delphi_generator.cc \ + src/thrift/generate/t_erl_generator.cc \ + src/thrift/generate/t_go_generator.cc \ + src/thrift/generate/t_gv_generator.cc \ src/thrift/generate/t_haxe_generator.cc \ - src/thrift/generate/t_csharp_generator.cc \ + src/thrift/generate/t_hs_generator.cc \ + src/thrift/generate/t_html_generator.cc \ + src/thrift/generate/t_java_generator.cc \ + src/thrift/generate/t_javame_generator.cc \ + src/thrift/generate/t_js_generator.cc \ + src/thrift/generate/t_json_generator.cc \ + src/thrift/generate/t_lua_generator.cc \ src/thrift/generate/t_netcore_generator.cc \ src/thrift/generate/t_netcore_generator.h \ - src/thrift/generate/t_py_generator.cc \ - src/thrift/generate/t_rb_generator.cc \ + src/thrift/generate/t_ocaml_generator.cc \ src/thrift/generate/t_perl_generator.cc \ src/thrift/generate/t_php_generator.cc \ - src/thrift/generate/t_erl_generator.cc \ - src/thrift/generate/t_cocoa_generator.cc \ - src/thrift/generate/t_swift_generator.cc \ + src/thrift/generate/t_py_generator.cc \ + src/thrift/generate/t_rb_generator.cc \ + src/thrift/generate/t_rs_generator.cc \ src/thrift/generate/t_st_generator.cc \ - src/thrift/generate/t_ocaml_generator.cc \ - src/thrift/generate/t_hs_generator.cc \ - src/thrift/generate/t_xsd_generator.cc \ + src/thrift/generate/t_swift_generator.cc \ src/thrift/generate/t_xml_generator.cc \ - src/thrift/generate/t_html_generator.cc \ - src/thrift/generate/t_js_generator.cc \ - src/thrift/generate/t_javame_generator.cc \ - src/thrift/generate/t_delphi_generator.cc \ - src/thrift/generate/t_go_generator.cc \ - src/thrift/generate/t_gv_generator.cc \ - src/thrift/generate/t_d_generator.cc \ - src/thrift/generate/t_lua_generator.cc \ - src/thrift/generate/t_rs_generator.cc \ - src/thrift/generate/t_cl_generator.cc + src/thrift/generate/t_xsd_generator.cc thrift_CPPFLAGS = -I$(srcdir)/src thrift_CXXFLAGS = -Wall -Wextra -pedantic -Werror diff --git a/compiler/cpp/compiler.vcxproj b/compiler/cpp/compiler.vcxproj index 0628b54c85b..3b597280b1a 100644 --- a/compiler/cpp/compiler.vcxproj +++ b/compiler/cpp/compiler.vcxproj @@ -54,11 +54,10 @@ - + + - - @@ -69,11 +68,12 @@ - + + @@ -247,4 +247,4 @@ - \ No newline at end of file + diff --git a/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc b/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc deleted file mode 100644 index ac644f5c599..00000000000 --- a/compiler/cpp/src/thrift/generate/t_cocoa_generator.cc +++ /dev/null @@ -1,3309 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include "thrift/platform.h" -#include "thrift/generate/t_oop_generator.h" - -using std::map; -using std::ostream; -using std::ofstream; -using std::ostringstream; -using std::string; -using std::stringstream; -using std::vector; - -static const string endl = "\n"; // avoid ostream << std::endl flushes - -/** - * Objective-C code generator. - * - * mostly copy/pasting/tweaking from mcslee's work. - */ -class t_cocoa_generator : public t_oop_generator { -public: - t_cocoa_generator(t_program* program, - const std::map& parsed_options, - const std::string& option_string) - : t_oop_generator(program) { - (void)option_string; - std::map::const_iterator iter; - - log_unexpected_ = false; - validate_required_ = false; - async_clients_ = false; - promise_kit_ = false; - debug_descriptions_ = false; - pods_ = false; - for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { - if( iter->first.compare("log_unexpected") == 0) { - log_unexpected_ = true; - } else if( iter->first.compare("validate_required") == 0) { - validate_required_ = true; - } else if( iter->first.compare("async_clients") == 0) { - async_clients_ = true; - } else if( iter->first.compare("promise_kit") == 0) { - promise_kit_ = true; - } else if( iter->first.compare("debug_descriptions") == 0) { - debug_descriptions_ = true; - } else if( iter->first.compare("pods") == 0) { - pods_ = true; - } else { - throw "unknown option cocoa:" + iter->first; - } - } - - out_dir_base_ = "gen-cocoa"; - } - - /** - * Init and close methods - */ - - void init_generator(); - void close_generator(); - - void generate_consts(std::vector consts); - - /** - * Program-level generation functions - */ - - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); - - void print_const_value(ostream& out, - string name, - t_type* type, - t_const_value* value, - bool defval = false); - std::string render_const_value(ostream& out, - t_type* type, - t_const_value* value, - bool box_it = false); - - void generate_cocoa_struct(t_struct* tstruct, bool is_exception); - void generate_cocoa_struct_interface(std::ostream& out, - t_struct* tstruct, - bool is_xception = false); - void generate_cocoa_struct_implementation(std::ostream& out, - t_struct* tstruct, - bool is_xception = false, - bool is_result = false); - void generate_cocoa_struct_initializer_signature(std::ostream& out, t_struct* tstruct); - void generate_cocoa_struct_init_with_coder_method(ostream& out, - t_struct* tstruct, - bool is_exception); - void generate_cocoa_struct_encode_with_coder_method(ostream& out, - t_struct* tstruct, - bool is_exception); - void generate_cocoa_struct_copy_method(ostream& out, - t_struct* tstruct, - bool is_exception); - void generate_cocoa_struct_hash_method(ostream& out, t_struct* tstruct); - void generate_cocoa_struct_is_equal_method(ostream& out, - t_struct* tstruct, - bool is_exception); - void generate_cocoa_struct_field_accessor_implementations(std::ostream& out, - t_struct* tstruct, - bool is_exception); - void generate_cocoa_struct_reader(std::ostream& out, t_struct* tstruct); - void generate_cocoa_struct_result_writer(std::ostream& out, t_struct* tstruct); - void generate_cocoa_struct_writer(std::ostream& out, t_struct* tstruct); - void generate_cocoa_struct_validator(std::ostream& out, t_struct* tstruct); - void generate_cocoa_struct_description(std::ostream& out, t_struct* tstruct); - - std::string function_result_helper_struct_type(t_service *tservice, t_function* tfunction); - std::string function_args_helper_struct_type(t_service* tservice, t_function* tfunction); - void generate_function_helpers(t_service *tservice, t_function* tfunction); - - /** - * Service-level generation functions - */ - - void generate_cocoa_service_protocol(std::ostream& out, t_service* tservice); - void generate_cocoa_service_async_protocol(std::ostream& out, t_service* tservice); - - void generate_cocoa_service_client_interface(std::ostream& out, t_service* tservice); - void generate_cocoa_service_client_async_interface(std::ostream& out, t_service* tservice); - - void generate_cocoa_service_client_send_function_implementation(ostream& out, - t_service* tservice, - t_function* tfunction, - bool needs_protocol); - void generate_cocoa_service_client_send_function_invocation(ostream& out, t_function* tfunction); - void generate_cocoa_service_client_send_async_function_invocation(ostream& out, - t_function* tfunction, - string failureBlockName); - void generate_cocoa_service_client_recv_function_implementation(ostream& out, - t_service* tservice, - t_function* tfunction, - bool needs_protocol); - void generate_cocoa_service_client_implementation(std::ostream& out, t_service* tservice); - void generate_cocoa_service_client_async_implementation(std::ostream& out, t_service* tservice); - - void generate_cocoa_service_server_interface(std::ostream& out, t_service* tservice); - void generate_cocoa_service_server_implementation(std::ostream& out, t_service* tservice); - void generate_cocoa_service_helpers(t_service* tservice); - void generate_service_client(t_service* tservice); - void generate_service_server(t_service* tservice); - void generate_process_function(t_service* tservice, t_function* tfunction); - - /** - * Serialization constructs - */ - - void generate_deserialize_field(std::ostream& out, t_field* tfield, std::string fieldName); - - void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); - - void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); - - void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); - - void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); - - void generate_deserialize_list_element(std::ostream& out, - t_list* tlist, - std::string prefix = ""); - - void generate_serialize_field(std::ostream& out, t_field* tfield, std::string prefix = ""); - - void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string fieldName = ""); - - void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); - - void generate_serialize_map_element(std::ostream& out, - t_map* tmap, - std::string iter, - std::string map); - - void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); - - void generate_serialize_list_element(std::ostream& out, - t_list* tlist, - std::string index, - std::string listName); - - /** - * Helper rendering functions - */ - - std::string cocoa_prefix(); - std::string cocoa_imports(); - std::string cocoa_thrift_imports(); - std::string type_name(t_type* ttype, bool class_ref = false, bool needs_mutable = false); - std::string element_type_name(t_type* ttype); - std::string base_type_name(t_base_type* tbase); - std::string declare_property(t_field* tfield); - std::string declare_property_isset(t_field* tfield); - std::string declare_property_unset(t_field* tfield); - std::string invalid_return_statement(t_function* tfunction); - std::string function_signature(t_function* tfunction, bool include_error); - std::string async_function_signature(t_function* tfunction, bool include_error); - std::string promise_function_signature(t_function* tfunction); - std::string argument_list(t_struct* tstruct, string protocol_name, bool include_error); - std::string type_to_enum(t_type* ttype); - std::string format_string_for_type(t_type* type); - std::string format_cast_for_type(t_type* type); - std::string call_field_setter(t_field* tfield, std::string fieldName); - std::string box(t_type *ttype, std::string field_name); - std::string unbox(t_type* ttype, std::string field_name); - std::string getter_name(string field_name); - std::string setter_name(string field_name); - - bool type_can_be_copy(t_type* ttype) { - ttype = get_true_type(ttype); - - return ttype->is_string(); - } - - bool type_can_be_null(t_type* ttype) { - ttype = get_true_type(ttype); - - return ttype->is_container() || ttype->is_struct() || ttype->is_xception() - || ttype->is_string(); - } - -private: - std::string cocoa_prefix_; - std::string constants_declarations_; - int error_constant_; - - /** - * File streams - */ - - ofstream_with_content_based_conditional_update f_header_; - ofstream_with_content_based_conditional_update f_impl_; - - bool log_unexpected_; - bool validate_required_; - bool async_clients_; - bool promise_kit_; - bool debug_descriptions_; - bool pods_; -}; - -/** - * Prepares for file generation by opening up the necessary file output - * streams. - */ -void t_cocoa_generator::init_generator() { - // Make output directory - MKDIR(get_out_dir().c_str()); - cocoa_prefix_ = program_->get_namespace("cocoa"); - - // we have a .h header file... - string f_header_name = cocoa_prefix_ + capitalize(program_name_) + ".h"; - string f_header_fullname = get_out_dir() + f_header_name; - f_header_.open(f_header_fullname.c_str()); - - f_header_ << autogen_comment() << endl; - - f_header_ << cocoa_imports() << cocoa_thrift_imports(); - - // ...and a .m implementation file - string f_impl_name = cocoa_prefix_ + capitalize(program_name_) + ".m"; - string f_impl_fullname = get_out_dir() + f_impl_name; - f_impl_.open(f_impl_fullname.c_str()); - - f_impl_ << autogen_comment() << endl; - - f_impl_ << cocoa_imports() << cocoa_thrift_imports() << "#import \"" << f_header_name << "\"" - << endl << endl; - - error_constant_ = 60000; -} - -/** - * Prints standard Cocoa imports - * - * @return List of imports for Cocoa libraries - */ -string t_cocoa_generator::cocoa_imports() { - return string() + "#import \n" + "\n"; -} - -/** - * Prints thrift runtime imports - * - * @return List of imports necessary for thrift runtime - */ -string t_cocoa_generator::cocoa_thrift_imports() { - - vector includes_list; - includes_list.push_back("TProtocol.h"); - includes_list.push_back("TProtocolFactory.h"); - includes_list.push_back("TApplicationError.h"); - includes_list.push_back("TProtocolError.h"); - includes_list.push_back("TProtocolUtil.h"); - includes_list.push_back("TProcessor.h"); - includes_list.push_back("TBase.h"); - includes_list.push_back("TAsyncTransport.h"); - includes_list.push_back("TBaseClient.h"); - - std::ostringstream includes; - - vector::const_iterator i_iter; - for (i_iter=includes_list.begin(); i_iter!=includes_list.end(); ++i_iter) { - includes << "#import "; - if (pods_) { - includes << ""; - } else { - includes << "\"" << *i_iter << "\""; - } - includes << endl; - } - - includes << endl; - - if (promise_kit_) { - includes << "#import "; - if (pods_) { - includes << ""; - } else { - includes << "\"PromiseKit.h\""; - } - includes << endl; - } - - // Include other Thrift includes - const vector& other_includes = program_->get_includes(); - for (size_t i = 0; i < other_includes.size(); ++i) { - includes << "#import \"" - << other_includes[i]->get_namespace("cocoa") - << capitalize(other_includes[i]->get_name()) - << ".h\"" << endl; - } - - includes << endl; - - return includes.str(); -} - -/** - * Finish up generation. - */ -void t_cocoa_generator::close_generator() { - // stick our constants declarations at the end of the header file - // since they refer to things we are defining. - f_header_ << constants_declarations_ << endl; -} - -/** - * Generates a typedef. This is just a simple 1-liner in objective-c - * - * @param ttypedef The type definition - */ -void t_cocoa_generator::generate_typedef(t_typedef* ttypedef) { - if (ttypedef->get_type()->is_map()) { - t_map *map = (t_map *)ttypedef->get_type(); - if (map->get_key_type()->is_struct()) { - f_header_ << indent() << "@class " << type_name(map->get_key_type(), true) << ";" << endl; - } - if (map->get_val_type()->is_struct()) { - f_header_ << indent() << "@class " << type_name(map->get_val_type(), true) << ";" << endl; - } - } - else if (ttypedef->get_type()->is_set()) { - t_set *set = (t_set *)ttypedef->get_type(); - if (set->get_elem_type()->is_struct()) { - f_header_ << indent() << "@class " << type_name(set->get_elem_type(), true) << ";" << endl; - } - } - else if (ttypedef->get_type()->is_list()) { - t_list *list = (t_list *)ttypedef->get_type(); - if (list->get_elem_type()->is_struct()) { - f_header_ << indent() << "@class " << type_name(list->get_elem_type(), true) << ";" << endl; - } - } - f_header_ << indent() << "typedef " << type_name(ttypedef->get_type()) << " " << cocoa_prefix_ - << ttypedef->get_symbolic() << ";" << endl << endl; - if (ttypedef->get_type()->is_container()) { - f_header_ << indent() << "typedef " << type_name(ttypedef->get_type(), false, true) << " " << cocoa_prefix_ - << "Mutable" << ttypedef->get_symbolic() << ";" << endl << endl; - } -} - -/** - * Generates code for an enumerated type. In Objective-C, this is - * essentially the same as the thrift definition itself, instead using - * NS_ENUM keyword in Objective-C. For namespace purposes, the name of - * the enum is prefixed to each element in keeping with Cocoa & Swift - * standards. - * - * @param tenum The enumeration - */ -void t_cocoa_generator::generate_enum(t_enum* tenum) { - f_header_ << indent() << "typedef NS_ENUM(SInt32, " << cocoa_prefix_ << tenum->get_name() << ") {" << endl; - indent_up(); - - vector constants = tenum->get_constants(); - vector::iterator c_iter; - bool first = true; - for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { - if (first) { - first = false; - } else { - f_header_ << "," << endl; - } - f_header_ << indent() << cocoa_prefix_ << tenum->get_name() << (*c_iter)->get_name(); - f_header_ << " = " << (*c_iter)->get_value(); - } - - indent_down(); - f_header_ << endl << "};" << endl << endl; -} - -/** - * Generates a class that holds all the constants. - */ -void t_cocoa_generator::generate_consts(std::vector consts) { - std::ostringstream const_interface; - - const_interface << "FOUNDATION_EXPORT NSString *" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain;" << endl - << endl; - - - bool needs_class = false; - - // Public constants for base types & strings - vector::iterator c_iter; - for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { - t_type* type = (*c_iter)->get_type()->get_true_type(); - if (!type->is_container() && !type->is_struct()) { - const_interface << "FOUNDATION_EXPORT " << type_name(type) << " " - << cocoa_prefix_ << capitalize((*c_iter)->get_name()) << ";" << endl; - } - else { - needs_class = true; - } - } - - - string constants_class_name = cocoa_prefix_ + capitalize(program_name_) + "Constants"; - - if (needs_class) { - - const_interface << endl; - - const_interface << "@interface " << constants_class_name << " : NSObject "; - scope_up(const_interface); - scope_down(const_interface); - - // getter method for each constant defined. - for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { - string name = (*c_iter)->get_name(); - t_type* type = (*c_iter)->get_type()->get_true_type(); - if (type->is_container() || type->is_struct()) { - t_type* type = (*c_iter)->get_type(); - const_interface << endl << "+ (" << type_name(type) << ") " << name << ";" << endl; - } - } - - const_interface << endl << "@end"; - } - - // this gets spit into the header file in ::close_generator - constants_declarations_ = const_interface.str(); - - f_impl_ << "NSString *" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain = " - << "@\"" << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain\";" << endl << endl; - - // variables in the .m hold all simple constant values - for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { - string name = (*c_iter)->get_name(); - t_type* type = (*c_iter)->get_type(); - f_impl_ << type_name(type) << " " << cocoa_prefix_ << name; - t_type* ttype = type->get_true_type(); - if (!ttype->is_container() && !ttype->is_struct()) { - f_impl_ << " = " << render_const_value(f_impl_, type, (*c_iter)->get_value()); - } - f_impl_ << ";" << endl; - } - f_impl_ << endl; - - if (needs_class) { - - f_impl_ << "@implementation " << constants_class_name << endl << endl; - - // initialize complex constants when the class is loaded - f_impl_ << "+ (void) initialize "; - scope_up(f_impl_); - - for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { - t_type* ttype = (*c_iter)->get_type()->get_true_type(); - if (ttype->is_container() || ttype->is_struct()) { - f_impl_ << endl; - print_const_value(f_impl_, - cocoa_prefix_ + (*c_iter)->get_name(), - (*c_iter)->get_type(), - (*c_iter)->get_value(), - false); - f_impl_ << ";" << endl; - } - } - scope_down(f_impl_); - - // getter method for each constant - for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { - string name = (*c_iter)->get_name(); - t_type* type = (*c_iter)->get_type()->get_true_type(); - if (type->is_container() || type->is_struct()) { - f_impl_ << endl << "+ (" << type_name(type) << ") " << name << " "; - scope_up(f_impl_); - indent(f_impl_) << "return " << cocoa_prefix_ << name << ";" << endl; - scope_down(f_impl_); - } - } - - f_impl_ << "@end" << endl << endl; - } -} - -/** - * Generates a struct definition for a thrift data type. This is a class - * with protected data members, read(), write(), and getters and setters. - * - * @param tstruct The struct definition - */ -void t_cocoa_generator::generate_struct(t_struct* tstruct) { - generate_cocoa_struct_interface(f_header_, tstruct, false); - generate_cocoa_struct_implementation(f_impl_, tstruct, false); -} - -/** - * Exceptions are structs, but they inherit from NSException - * - * @param tstruct The struct definition - */ -void t_cocoa_generator::generate_xception(t_struct* txception) { - generate_cocoa_struct_interface(f_header_, txception, true); - generate_cocoa_struct_implementation(f_impl_, txception, true); -} - -/** - * Generate the interface for a struct - * - * @param tstruct The struct definition - */ -void t_cocoa_generator::generate_cocoa_struct_interface(ostream& out, - t_struct* tstruct, - bool is_exception) { - - if (is_exception) { - out << "enum {" << endl - << " " << cocoa_prefix_ << capitalize(program_name_) << "Error" << tstruct->get_name() << " = -" << error_constant_++ << endl - << "};" << endl - << endl; - } - - out << "@interface " << cocoa_prefix_ << tstruct->get_name() << " : "; - - if (is_exception) { - out << "NSError "; - } else { - out << "NSObject "; - } - out << " " << endl; - - out << endl; - - // properties - const vector& members = tstruct->get_members(); - if (members.size() > 0) { - vector::const_iterator m_iter; - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - out << indent() << declare_property(*m_iter) << endl; - out << indent() << declare_property_isset(*m_iter) << endl; - out << indent() << declare_property_unset(*m_iter) << endl; - out << endl; - } - } - - out << endl; - - // initializer for all fields - if (!members.empty()) { - generate_cocoa_struct_initializer_signature(out, tstruct); - out << ";" << endl; - } - out << endl; - - out << "@end" << endl << endl; -} - -/** - * Generate signature for initializer of struct with a parameter for - * each field. - */ -void t_cocoa_generator::generate_cocoa_struct_initializer_signature(ostream& out, - t_struct* tstruct) { - const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; - indent(out) << "- (instancetype) initWith"; - for (m_iter = members.begin(); m_iter != members.end();) { - if (m_iter == members.begin()) { - out << capitalize((*m_iter)->get_name()); - } else { - out << (*m_iter)->get_name(); - } - out << ": (" << type_name((*m_iter)->get_type()) << ") " << (*m_iter)->get_name(); - ++m_iter; - if (m_iter != members.end()) { - out << " "; - } - } -} - -/** - * Generate the initWithCoder method for this struct so it's compatible with - * the NSCoding protocol - */ -void t_cocoa_generator::generate_cocoa_struct_init_with_coder_method(ostream& out, - t_struct* tstruct, - bool is_exception) { - - indent(out) << "- (instancetype) initWithCoder: (NSCoder *) decoder" << endl; - scope_up(out); - - if (is_exception) { - // NSExceptions conform to NSCoding, so we can call super - indent(out) << "self = [super initWithCoder: decoder];" << endl; - } else { - indent(out) << "self = [super init];" << endl; - } - - indent(out) << "if (self) "; - scope_up(out); - - const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* t = get_true_type((*m_iter)->get_type()); - out << indent() << "if ([decoder containsValueForKey: @\"" << (*m_iter)->get_name() << "\"])" - << endl; - scope_up(out); - out << indent() << "_" << (*m_iter)->get_name() << " = "; - if (type_can_be_null(t)) { - out << "[decoder decodeObjectForKey: @\"" << (*m_iter)->get_name() << "\"];" - << endl; - } else if (t->is_enum()) { - out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; - } else { - t_base_type::t_base tbase = ((t_base_type*)t)->get_base(); - switch (tbase) { - case t_base_type::TYPE_BOOL: - out << "[decoder decodeBoolForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; - break; - case t_base_type::TYPE_I8: - out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; - break; - case t_base_type::TYPE_I16: - out << "[decoder decodeIntForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; - break; - case t_base_type::TYPE_I32: - out << "[decoder decodeInt32ForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; - break; - case t_base_type::TYPE_I64: - out << "[decoder decodeInt64ForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; - break; - case t_base_type::TYPE_DOUBLE: - out << "[decoder decodeDoubleForKey: @\"" << (*m_iter)->get_name() << "\"];" << endl; - break; - default: - throw "compiler error: don't know how to decode thrift type: " - + t_base_type::t_base_name(tbase); - } - } - out << indent() << "_" << (*m_iter)->get_name() << "IsSet = YES;" << endl; - scope_down(out); - } - - scope_down(out); - - out << indent() << "return self;" << endl; - scope_down(out); - out << endl; -} - -/** - * Generate the encodeWithCoder method for this struct so it's compatible with - * the NSCoding protocol - */ -void t_cocoa_generator::generate_cocoa_struct_encode_with_coder_method(ostream& out, - t_struct* tstruct, - bool is_exception) { - - indent(out) << "- (void) encodeWithCoder: (NSCoder *) encoder" << endl; - scope_up(out); - - if (is_exception) { - // NSExceptions conform to NSCoding, so we can call super - out << indent() << "[super encodeWithCoder: encoder];" << endl; - } - - const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* t = get_true_type((*m_iter)->get_type()); - out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl; - scope_up(out); - if (type_can_be_null(t)) { - out << indent() << "[encoder encodeObject: _" << (*m_iter)->get_name() << " forKey: @\"" - << (*m_iter)->get_name() << "\"];" << endl; - } else if (t->is_enum()) { - out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\"" - << (*m_iter)->get_name() << "\"];" << endl; - } else { - t_base_type::t_base tbase = ((t_base_type*)t)->get_base(); - switch (tbase) { - case t_base_type::TYPE_BOOL: - out << indent() << "[encoder encodeBool: _" << (*m_iter)->get_name() << " forKey: @\"" - << (*m_iter)->get_name() << "\"];" << endl; - break; - case t_base_type::TYPE_I8: - out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\"" - << (*m_iter)->get_name() << "\"];" << endl; - break; - case t_base_type::TYPE_I16: - out << indent() << "[encoder encodeInt: _" << (*m_iter)->get_name() << " forKey: @\"" - << (*m_iter)->get_name() << "\"];" << endl; - break; - case t_base_type::TYPE_I32: - out << indent() << "[encoder encodeInt32: _" << (*m_iter)->get_name() << " forKey: @\"" - << (*m_iter)->get_name() << "\"];" << endl; - break; - case t_base_type::TYPE_I64: - out << indent() << "[encoder encodeInt64: _" << (*m_iter)->get_name() << " forKey: @\"" - << (*m_iter)->get_name() << "\"];" << endl; - break; - case t_base_type::TYPE_DOUBLE: - out << indent() << "[encoder encodeDouble: _" << (*m_iter)->get_name() << " forKey: @\"" - << (*m_iter)->get_name() << "\"];" << endl; - break; - default: - throw "compiler error: don't know how to encode thrift type: " - + t_base_type::t_base_name(tbase); - } - } - scope_down(out); - } - - scope_down(out); - out << endl; -} - -/** - * Generate the copy method for this struct - */ -void t_cocoa_generator::generate_cocoa_struct_copy_method(ostream& out, t_struct* tstruct, bool is_exception) { - out << indent() << "- (instancetype) copyWithZone:(NSZone *)zone" << endl; - scope_up(out); - - if (is_exception) { - out << indent() << type_name(tstruct) << " val = [" << cocoa_prefix_ << tstruct->get_name() << " errorWithDomain: self.domain code: self.code userInfo: self.userInfo];" << endl; - } else { - out << indent() << type_name(tstruct) << " val = [" << cocoa_prefix_ << tstruct->get_name() << " new];" << endl; - } - - const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* t = get_true_type((*m_iter)->get_type()); - out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl; - scope_up(out); - if (type_can_be_null(t)) { - out << indent() << "val." << (*m_iter)->get_name() << " = [self." << (*m_iter)->get_name() << " copy];"; - } else { - out << indent() << "val." << (*m_iter)->get_name() << " = self." << (*m_iter)->get_name() << ";"; - } - out << endl; - scope_down(out); - } - - out << indent() << "return val;" << endl; - - scope_down(out); - out << endl; -} - -/** - * Generate the hash method for this struct - */ -void t_cocoa_generator::generate_cocoa_struct_hash_method(ostream& out, t_struct* tstruct) { - indent(out) << "- (NSUInteger) hash" << endl; - scope_up(out); - out << indent() << "NSUInteger hash = 17;" << endl; - - const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* t = get_true_type((*m_iter)->get_type()); - out << indent() << "hash = (hash * 31) ^ _" << (*m_iter)->get_name() - << "IsSet ? 2654435761 : 0;" << endl; - out << indent() << "if (_" << (*m_iter)->get_name() << "IsSet)" << endl; - scope_up(out); - if (type_can_be_null(t)) { - out << indent() << "hash = (hash * 31) ^ [_" << (*m_iter)->get_name() << " hash];" << endl; - } else { - out << indent() << "hash = (hash * 31) ^ [@(_" << (*m_iter)->get_name() << ") hash];" - << endl; - } - scope_down(out); - } - - out << indent() << "return hash;" << endl; - scope_down(out); - out << endl; -} - -/** - * Generate the isEqual method for this struct - */ -void t_cocoa_generator::generate_cocoa_struct_is_equal_method(ostream& out, t_struct* tstruct, bool is_exception) { - indent(out) << "- (BOOL) isEqual: (id) anObject" << endl; - scope_up(out); - - indent(out) << "if (self == anObject) {" << endl; - indent_up(); - indent(out) << "return YES;" << endl; - indent_down(); - indent(out) << "}" << endl; - - string class_name = cocoa_prefix_ + tstruct->get_name(); - - if (is_exception) { - indent(out) << "if (![super isEqual:anObject]) {" << endl; - indent_up(); - indent(out) << "return NO;" << endl; - indent_down(); - indent(out) << "}" << endl << endl; - } - else { - indent(out) << "if (![anObject isKindOfClass:[" << class_name << " class]]) {" << endl; - indent_up(); - indent(out) << "return NO;" << endl; - indent_down(); - indent(out) << "}" << endl; - } - - const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; - - if (!members.empty()) { - indent(out) << class_name << " *other = (" << class_name << " *)anObject;" << endl; - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* t = get_true_type((*m_iter)->get_type()); - string name = (*m_iter)->get_name(); - if (type_can_be_null(t)) { - out << indent() << "if ((_" << name << "IsSet != other->_" << name << "IsSet) ||" << endl - << indent() << " " - << "(_" << name << "IsSet && " - << "((_" << name << " || other->_" << name << ") && " - << "![_" << name << " isEqual:other->_" << name << "]))) {" << endl; - } else { - out << indent() << "if ((_" << name << "IsSet != other->_" << name << "IsSet) ||" << endl - << indent() << " " - << "(_" << name << "IsSet && " - << "(_" << name << " != other->_" << name << "))) {" << endl; - } - indent_up(); - indent(out) << "return NO;" << endl; - indent_down(); - indent(out) << "}" << endl; - } - } - - out << indent() << "return YES;" << endl; - scope_down(out); - out << endl; -} - -/** - * Generate struct implementation. - * - * @param tstruct The struct definition - * @param is_exception Is this an exception? - * @param is_result If this is a result it needs a different writer - */ -void t_cocoa_generator::generate_cocoa_struct_implementation(ostream& out, - t_struct* tstruct, - bool is_exception, - bool is_result) { - indent(out) << "@implementation " << cocoa_prefix_ << tstruct->get_name() << endl << endl; - - const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; - - // exceptions need to call the designated initializer on NSException - if (is_exception) { - out << indent() << "- (instancetype) init" << endl; - scope_up(out); - out << indent() << "return [super initWithDomain: " << cocoa_prefix_ << capitalize(program_name_) << "ErrorDomain" << endl - << indent() << " code: " << cocoa_prefix_ << capitalize(program_name_) << "Error" << tstruct->get_name() << endl - << indent() << " userInfo: nil];" << endl; - scope_down(out); - out << endl; - } else { - // struct - - // default initializer - // setup instance variables with default values - indent(out) << "- (instancetype) init" << endl; - scope_up(out); - indent(out) << "self = [super init];" << endl; - indent(out) << "if (self)"; - scope_up(out); - if (members.size() > 0) { - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* t = get_true_type((*m_iter)->get_type()); - if ((*m_iter)->get_value() != NULL) { - print_const_value(out, - "self." + (*m_iter)->get_name(), - t, - (*m_iter)->get_value(), - false); - } - } - } - scope_down(out); - indent(out) << "return self;" << endl; - scope_down(out); - out << endl; - } - - // initializer with all fields as params - if (!members.empty()) { - generate_cocoa_struct_initializer_signature(out, tstruct); - out << endl; - scope_up(out); - if (is_exception) { - out << indent() << "self = [self init];" << endl; - } else { - out << indent() << "self = [super init];" << endl; - } - - indent(out) << "if (self)"; - scope_up(out); - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - out << indent() << "_" << (*m_iter)->get_name() << " = "; - if (get_true_type((*m_iter)->get_type())->is_container()) { - out << "[" << (*m_iter)->get_name() << " mutableCopy];" << endl; - } else { - out << (*m_iter)->get_name() << ";" << endl; - } - out << indent() << "_" << (*m_iter)->get_name() << "IsSet = YES;" << endl; - } - scope_down(out); - - out << indent() << "return self;" << endl; - scope_down(out); - out << endl; - } - - // initWithCoder for NSCoding - generate_cocoa_struct_init_with_coder_method(out, tstruct, is_exception); - // encodeWithCoder for NSCoding - generate_cocoa_struct_encode_with_coder_method(out, tstruct, is_exception); - // hash and isEqual for NSObject - generate_cocoa_struct_hash_method(out, tstruct); - generate_cocoa_struct_is_equal_method(out, tstruct, is_exception); - // copy for NSObject - generate_cocoa_struct_copy_method(out, tstruct, is_exception); - - // the rest of the methods - generate_cocoa_struct_field_accessor_implementations(out, tstruct, is_exception); - generate_cocoa_struct_reader(out, tstruct); - if (is_result) { - generate_cocoa_struct_result_writer(out, tstruct); - } else { - generate_cocoa_struct_writer(out, tstruct); - } - generate_cocoa_struct_validator(out, tstruct); - generate_cocoa_struct_description(out, tstruct); - - out << "@end" << endl << endl; -} - -/** - * Generates a function to read all the fields of the struct. - * - * @param tstruct The struct definition - */ -void t_cocoa_generator::generate_cocoa_struct_reader(ostream& out, t_struct* tstruct) { - out << "- (BOOL) read: (id ) inProtocol error: (NSError *__autoreleasing *)__thriftError" << endl; - scope_up(out); - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - // Declare stack tmp variables - indent(out) << "NSString * fieldName;" << endl; - indent(out) << "SInt32 fieldType;" << endl; - indent(out) << "SInt32 fieldID;" << endl; - out << endl; - - indent(out) << "if (![inProtocol readStructBeginReturningName: NULL error: __thriftError]) return NO;" << endl; - - // Loop over reading in fields - indent(out) << "while (true)" << endl; - scope_up(out); - - // Read beginning field marker - indent(out) - << "if (![inProtocol readFieldBeginReturningName: &fieldName type: &fieldType fieldID: &fieldID error: __thriftError]) return NO;" - << endl; - - // Check for field STOP marker and break - indent(out) << "if (fieldType == TTypeSTOP) { " << endl; - indent_up(); - indent(out) << "break;" << endl; - indent_down(); - indent(out) << "}" << endl; - - // Switch statement on the field we are reading - indent(out) << "switch (fieldID)" << endl; - - scope_up(out); - - // Generate deserialization code for known cases - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; - indent_up(); - indent(out) << "if (fieldType == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; - indent_up(); - - generate_deserialize_field(out, *f_iter, "fieldValue"); - indent(out) << call_field_setter(*f_iter, "fieldValue") << endl; - - indent_down(); - out << indent() << "} else { " << endl; - if (log_unexpected_) { - out << indent() << " NSLog(@\"%s: field ID %i has unexpected type %i. Skipping.\", " - "__PRETTY_FUNCTION__, (int)fieldID, (int)fieldType);" << endl; - } - - out << indent() << " if (![TProtocolUtil skipType: fieldType onProtocol: inProtocol error: __thriftError]) return NO;" << endl; - out << indent() << "}" << endl << indent() << "break;" << endl; - indent_down(); - } - - // In the default case we skip the field - out << indent() << "default:" << endl; - if (log_unexpected_) { - out << indent() << " NSLog(@\"%s: unexpected field ID %i with type %i. Skipping.\", " - "__PRETTY_FUNCTION__, (int)fieldID, (int)fieldType);" << endl; - } - - out << indent() << " if (![TProtocolUtil skipType: fieldType onProtocol: inProtocol error: __thriftError]) return NO;" << endl; - - out << indent() << " break;" << endl; - - scope_down(out); - - // Read field end marker - indent(out) << "if (![inProtocol readFieldEnd: __thriftError]) return NO;" << endl; - - scope_down(out); - - out << indent() << "if (![inProtocol readStructEnd: __thriftError]) return NO;" << endl; - - // performs various checks (e.g. check that all required fields are set) - if (validate_required_) { - out << indent() << "if (![self validate: __thriftError]) return NO;" << endl; - } - - indent(out) << "return YES;" << endl; - - indent_down(); - out << indent() << "}" << endl << endl; -} - -/** - * Generates a function to write all the fields of the struct - * - * @param tstruct The struct definition - */ -void t_cocoa_generator::generate_cocoa_struct_writer(ostream& out, t_struct* tstruct) { - out << indent() << "- (BOOL) write: (id ) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl; - indent_up(); - - string name = tstruct->get_name(); - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << name << "\" error: __thriftError]) return NO;" << endl; - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - out << indent() << "if (_" << (*f_iter)->get_name() << "IsSet) {" << endl; - indent_up(); - bool null_allowed = type_can_be_null((*f_iter)->get_type()); - if (null_allowed) { - out << indent() << "if (_" << (*f_iter)->get_name() << " != nil) {" << endl; - indent_up(); - } - - indent(out) << "if (![outProtocol writeFieldBeginWithName: @\"" << (*f_iter)->get_name() - << "\" type: " << type_to_enum((*f_iter)->get_type()) - << " fieldID: " << (*f_iter)->get_key() << " error: __thriftError]) return NO;" << endl; - - // Write field contents - generate_serialize_field(out, *f_iter, "_" + (*f_iter)->get_name()); - - // Write field closer - indent(out) << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl; - - if (null_allowed) { - scope_down(out); - } - scope_down(out); - } - // Write the struct map - out << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" << endl - << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" << endl; - - indent(out) << "return YES;" << endl; - - indent_down(); - out << indent() << "}" << endl << endl; -} - -/** - * Generates a function to write all the fields of the struct, which - * is a function result. These fields are only written if they are - * set, and only one of them can be set at a time. - * - * @param tstruct The struct definition - */ -void t_cocoa_generator::generate_cocoa_struct_result_writer(ostream& out, t_struct* tstruct) { - out << indent() << "- (BOOL) write: (id ) outProtocol error: (NSError *__autoreleasing *)__thriftError {" << endl; - indent_up(); - - string name = tstruct->get_name(); - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << name << "\" error: __thriftError]) return NO;" << endl; - - bool first = true; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (first) { - first = false; - out << endl << indent() << "if "; - } else { - out << " else if "; - } - - out << "(_" << (*f_iter)->get_name() << "IsSet) {" << endl; - indent_up(); - - bool null_allowed = type_can_be_null((*f_iter)->get_type()); - if (null_allowed) { - out << indent() << "if (_" << (*f_iter)->get_name() << " != nil) {" << endl; - indent_up(); - } - - indent(out) << "if (![outProtocol writeFieldBeginWithName: @\"" << (*f_iter)->get_name() - << "\" type: " << type_to_enum((*f_iter)->get_type()) - << " fieldID: " << (*f_iter)->get_key() << " error: __thriftError]) return NO;" << endl; - - // Write field contents - generate_serialize_field(out, *f_iter, "_" + (*f_iter)->get_name()); - - // Write field closer - indent(out) << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl; - - if (null_allowed) { - indent_down(); - indent(out) << "}" << endl; - } - - indent_down(); - indent(out) << "}"; - } - // Write the struct map - out << endl << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" - << endl << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" - << endl; - - indent(out) << "return YES;" << endl; - - indent_down(); - out << indent() << "}" << endl << endl; -} - -/** - * Generates a function to perform various checks - * (e.g. check that all required fields are set) - * - * @param tstruct The struct definition - */ -void t_cocoa_generator::generate_cocoa_struct_validator(ostream& out, t_struct* tstruct) { - out << indent() << "- (BOOL) validate: (NSError *__autoreleasing *)__thriftError {" << endl; - indent_up(); - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - out << indent() << "// check for required fields" << endl; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - t_field* field = (*f_iter); - if ((*f_iter)->get_req() == t_field::T_REQUIRED) { - out << indent() << "if (!_" << field->get_name() << "IsSet) "; - scope_up(out); - indent(out) << "if (__thriftError) "; - scope_up(out); - out << indent() << "*__thriftError = [NSError errorWithDomain: TProtocolErrorDomain" << endl - << indent() << " code: TProtocolErrorUnknown" << endl - << indent() << " userInfo: @{TProtocolErrorExtendedErrorKey: @(TProtocolExtendedErrorMissingRequiredField)," << endl - << indent() << " TProtocolErrorFieldNameKey: @\"" << (*f_iter)->get_name() << "\"}];" << endl; - scope_down(out); - scope_down(out); - } - } - indent(out) << "return YES;" << endl; - indent_down(); - out << indent() << "}" << endl << endl; -} - -/** - * Generate property accessor methods for all fields in the struct. - * getter, setter, isset getter. - * - * @param tstruct The struct definition - */ -void t_cocoa_generator::generate_cocoa_struct_field_accessor_implementations(ostream& out, - t_struct* tstruct, - bool is_exception) { - (void)is_exception; - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - t_field* field = *f_iter; - t_type* type = get_true_type(field->get_type()); - std::string field_name = field->get_name(); - std::string cap_name = field_name; - cap_name[0] = toupper(cap_name[0]); - - // Simple setter - indent(out) << "- (void) set" << cap_name << ": (" << type_name(type, false, true) << ") " << field_name - << " {" << endl; - indent_up(); - indent(out) << "_" << field_name << " = " << field_name << ";" << endl; - indent(out) << "_" << field_name << "IsSet = YES;" << endl; - indent_down(); - indent(out) << "}" << endl << endl; - - // Unsetter - do we need this? - indent(out) << "- (void) unset" << cap_name << " {" << endl; - indent_up(); - if (type_can_be_null(type)) { - indent(out) << "_" << field_name << " = nil;" << endl; - } - indent(out) << "_" << field_name << "IsSet = NO;" << endl; - indent_down(); - indent(out) << "}" << endl << endl; - } -} - -/** - * Generates a description method for the given struct - * - * @param tstruct The struct definition - */ -void t_cocoa_generator::generate_cocoa_struct_description(ostream& out, t_struct* tstruct) { - - // Allow use of debugDescription so the app can add description via a cateogory/extension - if (debug_descriptions_) { - out << indent() << "- (NSString *) debugDescription {" << endl; - } - else { - out << indent() << "- (NSString *) description {" << endl; - } - indent_up(); - - out << indent() << "NSMutableString * ms = [NSMutableString stringWithString: @\"" - << cocoa_prefix_ << tstruct->get_name() << "(\"];" << endl; - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - bool first = true; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (first) { - first = false; - indent(out) << "[ms appendString: @\"" << (*f_iter)->get_name() << ":\"];" << endl; - } else { - indent(out) << "[ms appendString: @\"," << (*f_iter)->get_name() << ":\"];" << endl; - } - t_type* ttype = (*f_iter)->get_type(); - indent(out) << "[ms appendFormat: @\"" << format_string_for_type(ttype) << "\", " - << format_cast_for_type(ttype) << "_" << (*f_iter)->get_name() << "];" << endl; - } - out << indent() << "[ms appendString: @\")\"];" << endl << indent() - << "return [NSString stringWithString: ms];" << endl; - - indent_down(); - indent(out) << "}" << endl << endl; -} - -/** - * Generates a thrift service. In Objective-C this consists of a - * protocol definition, a client interface and a client implementation. - * - * @param tservice The service definition - */ -void t_cocoa_generator::generate_service(t_service* tservice) { - generate_cocoa_service_protocol(f_header_, tservice); - generate_cocoa_service_client_interface(f_header_, tservice); - generate_cocoa_service_server_interface(f_header_, tservice); - generate_cocoa_service_helpers(tservice); - generate_cocoa_service_client_implementation(f_impl_, tservice); - generate_cocoa_service_server_implementation(f_impl_, tservice); - if (async_clients_) { - generate_cocoa_service_async_protocol(f_header_, tservice); - generate_cocoa_service_client_async_interface(f_header_, tservice); - generate_cocoa_service_client_async_implementation(f_impl_, tservice); - } -} - -/** - * Generates structs for all the service return types - * - * @param tservice The service - */ -void t_cocoa_generator::generate_cocoa_service_helpers(t_service* tservice) { - vector functions = tservice->get_functions(); - vector::iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - - t_struct* ts = (*f_iter)->get_arglist(); - - string qname = function_args_helper_struct_type(tservice, *f_iter); - - t_struct qname_ts = t_struct(ts->get_program(), qname); - - const vector& members = ts->get_members(); - vector::const_iterator m_iter; - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - qname_ts.append(*m_iter); - } - - generate_cocoa_struct_interface(f_impl_, &qname_ts, false); - generate_cocoa_struct_implementation(f_impl_, &qname_ts, false, false); - generate_function_helpers(tservice, *f_iter); - } -} - -string t_cocoa_generator::function_result_helper_struct_type(t_service *tservice, t_function* tfunction) { - if (tfunction->is_oneway()) { - return tservice->get_name() + "_" + tfunction->get_name(); - } else { - return tservice->get_name() + "_" + tfunction->get_name() + "_result"; - } -} - -string t_cocoa_generator::function_args_helper_struct_type(t_service *tservice, t_function* tfunction) { - return tservice->get_name() + "_" + tfunction->get_name() + "_args"; -} - -/** - * Generates a struct and helpers for a function. - * - * @param tfunction The function - */ -void t_cocoa_generator::generate_function_helpers(t_service *tservice, t_function* tfunction) { - if (tfunction->is_oneway()) { - return; - } - - // create a result struct with a success field of the return type, - // and a field for each type of exception thrown - t_struct result(program_, function_result_helper_struct_type(tservice, tfunction)); - t_field success(tfunction->get_returntype(), "success", 0); - if (!tfunction->get_returntype()->is_void()) { - result.append(&success); - } - - t_struct* xs = tfunction->get_xceptions(); - const vector& fields = xs->get_members(); - vector::const_iterator f_iter; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - result.append(*f_iter); - } - - // generate the result struct - generate_cocoa_struct_interface(f_impl_, &result, false); - generate_cocoa_struct_implementation(f_impl_, &result, false, true); -} - -/** - * Generates a service protocol definition. - * - * @param tservice The service to generate a protocol definition for - */ -void t_cocoa_generator::generate_cocoa_service_protocol(ostream& out, t_service* tservice) { - out << "@protocol " << cocoa_prefix_ << tservice->get_name() << " " << endl; - - vector functions = tservice->get_functions(); - vector::iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - out << "- " << function_signature(*f_iter, true) << ";" - << " // throws "; - t_struct* xs = (*f_iter)->get_xceptions(); - const std::vector& xceptions = xs->get_members(); - vector::const_iterator x_iter; - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - out << type_name((*x_iter)->get_type()) + ", "; - } - out << "TException" << endl; - } - out << "@end" << endl << endl; -} - -/** - * Generates an asynchronous service protocol definition. - * - * @param tservice The service to generate a protocol definition for - */ -void t_cocoa_generator::generate_cocoa_service_async_protocol(ostream& out, t_service* tservice) { - out << "@protocol " << cocoa_prefix_ << tservice->get_name() << "Async" - << " " << endl; - - vector functions = tservice->get_functions(); - vector::iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - out << "- " << async_function_signature(*f_iter, false) << ";" << endl; - if (promise_kit_) { - out << "- " << promise_function_signature(*f_iter) << ";" << endl; - } - } - out << "@end" << endl << endl; -} - -/** - * Generates a service client interface definition. - * - * @param tservice The service to generate a client interface definition for - */ -void t_cocoa_generator::generate_cocoa_service_client_interface(ostream& out, - t_service* tservice) { - out << "@interface " << cocoa_prefix_ << tservice->get_name() << "Client : TBaseClient <" - << cocoa_prefix_ << tservice->get_name() << "> " << endl; - - out << "- (id) initWithProtocol: (id ) protocol;" << endl; - out << "- (id) initWithInProtocol: (id ) inProtocol outProtocol: (id ) " - "outProtocol;" << endl; - out << "@end" << endl << endl; -} - -/** - * Generates a service client interface definition. - * - * @param tservice The service to generate a client interface definition for - */ -void t_cocoa_generator::generate_cocoa_service_client_async_interface(ostream& out, - t_service* tservice) { - out << "@interface " << cocoa_prefix_ << tservice->get_name() << "ClientAsync : TBaseClient <" - << cocoa_prefix_ << tservice->get_name() << "Async> " << endl - << endl; - - out << "- (id) initWithProtocolFactory: (id ) protocolFactory " - << "transportFactory: (id ) transportFactory;" << endl; - out << "@end" << endl << endl; -} - -/** - * Generates a service server interface definition. In other words, the TProcess implementation for - *the - * service definition. - * - * @param tservice The service to generate a client interface definition for - */ -void t_cocoa_generator::generate_cocoa_service_server_interface(ostream& out, - t_service* tservice) { - out << "@interface " << cocoa_prefix_ << tservice->get_name() - << "Processor : NSObject " << endl; - - out << "- (id) initWith" << tservice->get_name() << ": (id <" << cocoa_prefix_ - << tservice->get_name() << ">) service;" << endl; - out << "- (id<" << cocoa_prefix_ << tservice->get_name() << ">) service;" << endl; - - out << "@end" << endl << endl; -} - -void t_cocoa_generator::generate_cocoa_service_client_send_function_implementation( - ostream& out, - t_service *tservice, - t_function* tfunction, - bool needs_protocol) { - string funname = tfunction->get_name(); - - t_function send_function(g_type_bool, - string("send_") + tfunction->get_name(), - tfunction->get_arglist()); - - string argsname = function_args_helper_struct_type(tservice, tfunction); - - // Open function - indent(out) << "- (BOOL) send_" << tfunction->get_name() << argument_list(tfunction->get_arglist(), needs_protocol ? "outProtocol" : "", true) << endl; - scope_up(out); - - // Serialize the request - out << indent() << "if (![outProtocol writeMessageBeginWithName: @\"" << funname << "\"" - << (tfunction->is_oneway() ? " type: TMessageTypeONEWAY" : " type: TMessageTypeCALL") - << " sequenceID: 0 error: __thriftError]) return NO;" << endl; - - out << indent() << "if (![outProtocol writeStructBeginWithName: @\"" << argsname - << "\" error: __thriftError]) return NO;" << endl; - - // write out function parameters - t_struct* arg_struct = tfunction->get_arglist(); - const vector& fields = arg_struct->get_members(); - vector::const_iterator fld_iter; - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - string fieldName = (*fld_iter)->get_name(); - if (type_can_be_null((*fld_iter)->get_type())) { - out << indent() << "if (" << fieldName << " != nil)"; - scope_up(out); - } - out << indent() << "if (![outProtocol writeFieldBeginWithName: @\"" << fieldName - << "\"" - " type: " << type_to_enum((*fld_iter)->get_type()) - << " fieldID: " << (*fld_iter)->get_key() << " error: __thriftError]) return NO;" << endl; - - generate_serialize_field(out, *fld_iter, fieldName); - - out << indent() << "if (![outProtocol writeFieldEnd: __thriftError]) return NO;" << endl; - - if (type_can_be_null((*fld_iter)->get_type())) { - indent_down(); - out << indent() << "}" << endl; - } - } - - out << indent() << "if (![outProtocol writeFieldStop: __thriftError]) return NO;" << endl; - out << indent() << "if (![outProtocol writeStructEnd: __thriftError]) return NO;" << endl; - out << indent() << "if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl; - out << indent() << "return YES;" << endl; - scope_down(out); - out << endl; -} - -void t_cocoa_generator::generate_cocoa_service_client_recv_function_implementation( - ostream& out, - t_service* tservice, - t_function* tfunction, - bool needs_protocol) { - - - // Open function - indent(out) << "- (BOOL) recv_" << tfunction->get_name(); - if (!tfunction->get_returntype()->is_void()) { - out << ": (" << type_name(tfunction->get_returntype(), false, true) << " *) result "; - if (needs_protocol) { - out << "protocol"; - } else { - out << "error"; - } - } - if (needs_protocol) { - out << ": (id) inProtocol error"; - } - out << ": (NSError *__autoreleasing *)__thriftError" << endl; - scope_up(out); - - // TODO(mcslee): Message validation here, was the seqid etc ok? - - // check for an exception - out << indent() << "NSError *incomingException = [self checkIncomingMessageException: inProtocol];" << endl - << indent() << "if (incomingException)"; - scope_up(out); - out << indent() << "if (__thriftError)"; - scope_up(out); - out << indent() << "*__thriftError = incomingException;" << endl; - scope_down(out); - out << indent() << "return NO;" << endl; - scope_down(out); - - // FIXME - could optimize here to reduce creation of temporary objects. - string resultname = function_result_helper_struct_type(tservice, tfunction); - out << indent() << cocoa_prefix_ << resultname << " * resulter = [" << cocoa_prefix_ << resultname << " new];" << endl; - indent(out) << "if (![resulter read: inProtocol error: __thriftError]) return NO;" << endl; - indent(out) << "if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl; - - // Careful, only return _result if not a void function - if (!tfunction->get_returntype()->is_void()) { - out << indent() << "if (resulter.successIsSet)"; - scope_up(out); - out << indent() << "*result = resulter.success;" << endl; - out << indent() << "return YES;" << endl; - scope_down(out); - } - - t_struct* xs = tfunction->get_xceptions(); - const std::vector& xceptions = xs->get_members(); - vector::const_iterator x_iter; - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - out << indent() << "if (resulter." << (*x_iter)->get_name() << "IsSet)"; - scope_up(out); - out << indent() << "if (__thriftError)"; - scope_up(out); - out << indent() << "*__thriftError = [resulter " << (*x_iter)->get_name() << "];" << endl; - scope_down(out); - out << indent() << "return NO;" << endl; - scope_down(out); - } - - // If you get here it's an exception, unless a void function - if (tfunction->get_returntype()->is_void()) { - indent(out) << "return YES;" << endl; - } else { - out << indent() << "if (__thriftError)"; - scope_up(out); - out << indent() << "*__thriftError = [NSError errorWithDomain: TApplicationErrorDomain" << endl - << indent() << " code: TApplicationErrorMissingResult" << endl - << indent() << " userInfo: @{TApplicationErrorMethodKey: @\"" - << tfunction->get_name() << "\"}];" << endl; - scope_down(out); - out << indent() << "return NO;" << endl; - } - - // Close function - scope_down(out); - out << endl; -} - -/** - * Generates an invocation of a given 'send_' function. - * - * @param tfunction The service to generate an implementation for - */ -void t_cocoa_generator::generate_cocoa_service_client_send_function_invocation( - ostream& out, - t_function* tfunction) { - - t_struct* arg_struct = tfunction->get_arglist(); - const vector& fields = arg_struct->get_members(); - vector::const_iterator fld_iter; - out << indent() << "if (![self send_" << tfunction->get_name(); - bool first = true; - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - string fieldName = (*fld_iter)->get_name(); - out << " "; - if (first) { - first = false; - out << ": " << fieldName; - } else { - out << fieldName << ": " << fieldName; - } - } - if (!fields.empty()) { - out << " error"; - } - out << ": __thriftError]) " << invalid_return_statement(tfunction) << endl; -} - -/** - * Generates an invocation of a given 'send_' function. - * - * @param tfunction The service to generate an implementation for - */ -void t_cocoa_generator::generate_cocoa_service_client_send_async_function_invocation( - ostream& out, - t_function* tfunction, - string failureBlockName) { - - t_struct* arg_struct = tfunction->get_arglist(); - const vector& fields = arg_struct->get_members(); - vector::const_iterator fld_iter; - out << indent() << "if (![self send_" << tfunction->get_name(); - bool first = true; - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - string fieldName = (*fld_iter)->get_name(); - out << " "; - if (first) { - first = false; - out << ": " << fieldName; - } else { - out << fieldName << ": " << fieldName; - } - } - if (!fields.empty()) { - out << " protocol"; - } - out << ": protocol error: &thriftError]) "; - scope_up(out); - out << indent() << failureBlockName << "(thriftError);" << endl - << indent() << "return;" << endl; - scope_down(out); -} - -/** - * Generates a service client implementation. - * - * @param tservice The service to generate an implementation for - */ -void t_cocoa_generator::generate_cocoa_service_client_implementation(ostream& out, - t_service* tservice) { - - string name = cocoa_prefix_ + tservice->get_name() + "Client"; - - out << "@interface " << name << " () "; - scope_up(out); - out << endl; - out << indent() << "id inProtocol;" << endl; - out << indent() << "id outProtocol;" << endl; - out << endl; - scope_down(out); - out << endl; - out << "@end" << endl << endl; - - out << "@implementation " << name << endl; - - // initializers - out << "- (id) initWithProtocol: (id ) protocol" << endl; - scope_up(out); - out << indent() << "return [self initWithInProtocol: protocol outProtocol: protocol];" << endl; - scope_down(out); - out << endl; - - out << "- (id) initWithInProtocol: (id ) anInProtocol outProtocol: (id ) " - "anOutProtocol" << endl; - scope_up(out); - out << indent() << "self = [super init];" << endl; - out << indent() << "if (self) "; - scope_up(out); - out << indent() << "inProtocol = anInProtocol;" << endl; - out << indent() << "outProtocol = anOutProtocol;" << endl; - scope_down(out); - out << indent() << "return self;" << endl; - scope_down(out); - out << endl; - - // generate client method implementations - vector functions = tservice->get_functions(); - vector::const_iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - - generate_cocoa_service_client_send_function_implementation(out, tservice, *f_iter, false); - - if (!(*f_iter)->is_oneway()) { - generate_cocoa_service_client_recv_function_implementation(out, tservice, *f_iter, false); - } - - // Open function - indent(out) << "- " << function_signature(*f_iter, true) << endl; - scope_up(out); - generate_cocoa_service_client_send_function_invocation(out, *f_iter); - - out << indent() << "if (![[outProtocol transport] flush: __thriftError]) " << invalid_return_statement(*f_iter) << endl; - if (!(*f_iter)->is_oneway()) { - if ((*f_iter)->get_returntype()->is_void()) { - out << indent() << "if (![self recv_" << (*f_iter)->get_name() << ": __thriftError]) return NO;" << endl; - out << indent() << "return YES;" << endl; - } else { - out << indent() << type_name((*f_iter)->get_returntype(), false, true) << " __result;" << endl - << indent() << "if (![self recv_" << (*f_iter)->get_name() << ": &__result error: __thriftError]) " - << invalid_return_statement(*f_iter) << endl; - if (type_can_be_null((*f_iter)->get_returntype())) { - out << indent() << "return __result;" << endl; - } else { - out << indent() << "return @(__result);" << endl; - } - } - } - else { - out << indent() << "return YES;" << endl; - } - scope_down(out); - out << endl; - } - - out << "@end" << endl << endl; -} - -/** - * Generates a service client implementation for its asynchronous interface. - * - * @param tservice The service to generate an implementation for - */ -void t_cocoa_generator::generate_cocoa_service_client_async_implementation(ostream& out, - t_service* tservice) { - - string name = cocoa_prefix_ + tservice->get_name() + "ClientAsync"; - - out << "@interface " << name << " () "; - scope_up(out); - out << endl; - out << indent() << "id protocolFactory;" << endl; - out << indent() << "id transportFactory;" << endl; - out << endl; - scope_down(out); - out << endl; - out << "@end" << endl << endl; - - - out << "@implementation " << name << endl - << endl << "- (id) initWithProtocolFactory: (id ) aProtocolFactory " - "transportFactory: (id ) aTransportFactory;" << endl; - - scope_up(out); - out << indent() << "self = [super init];" << endl; - out << indent() << "if (self) {" << endl; - out << indent() << " protocolFactory = aProtocolFactory;" << endl; - out << indent() << " transportFactory = aTransportFactory;" << endl; - out << indent() << "}" << endl; - out << indent() << "return self;" << endl; - scope_down(out); - out << endl; - - // generate client method implementations - vector functions = tservice->get_functions(); - vector::const_iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - - generate_cocoa_service_client_send_function_implementation(out, tservice, *f_iter, true); - - if (!(*f_iter)->is_oneway()) { - generate_cocoa_service_client_recv_function_implementation(out, tservice, *f_iter, true); - } - - // Open function - indent(out) << "- " << async_function_signature(*f_iter, false) << endl; - scope_up(out); - - out << indent() << "NSError *thriftError;" << endl - << indent() << "id transport = [transportFactory newTransport];" << endl - << indent() << "id protocol = [protocolFactory newProtocolOnTransport:transport];" << endl - << endl; - - generate_cocoa_service_client_send_async_function_invocation(out, *f_iter, "failureBlock"); - - out << indent() << "[transport flushWithCompletion:^{" << endl; - indent_up(); - - if (!(*f_iter)->is_oneway()) { - out << indent() << "NSError *thriftError;" << endl; - - if (!(*f_iter)->get_returntype()->is_void()) { - out << indent() << type_name((*f_iter)->get_returntype()) << " result;" << endl; - } - out << indent() << "if (![self recv_" << (*f_iter)->get_name(); - if (!(*f_iter)->get_returntype()->is_void()) { - out << ": &result protocol"; - } - out << ": protocol error: &thriftError]) "; - scope_up(out); - out << indent() << "failureBlock(thriftError);" << endl - << indent() << "return;" << endl; - scope_down(out); - } - - out << indent() << "responseBlock("; - if (!(*f_iter)->is_oneway() && !(*f_iter)->get_returntype()->is_void()) { - out << "result"; - } - out << ");" << endl; - - indent_down(); - - out << indent() << "} failure:failureBlock];" << endl; - - scope_down(out); - - out << endl; - - // Promise function - if (promise_kit_) { - - indent(out) << "- " << promise_function_signature(*f_iter) << endl; - scope_up(out); - - out << indent() << "return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolver) {" << endl; - indent_up(); - - out << indent() << "NSError *thriftError;" << endl - << indent() << "id transport = [transportFactory newTransport];" << endl - << indent() << "id protocol = [protocolFactory newProtocolOnTransport:transport];" << endl - << endl; - - generate_cocoa_service_client_send_async_function_invocation(out, *f_iter, "resolver"); - - out << indent() << "[transport flushWithCompletion:^{" << endl; - indent_up(); - - if (!(*f_iter)->is_oneway()) { - out << indent() << "NSError *thriftError;" << endl; - - if (!(*f_iter)->get_returntype()->is_void()) { - out << indent() << type_name((*f_iter)->get_returntype()) << " result;" << endl; - } - out << indent() << "if (![self recv_" << (*f_iter)->get_name(); - if (!(*f_iter)->get_returntype()->is_void()) { - out << ": &result protocol"; - } - out << ": protocol error: &thriftError]) "; - scope_up(out); - out << indent() << "resolver(thriftError);" << endl - << indent() << "return;" << endl; - scope_down(out); - } - - out << indent() << "resolver("; - if ((*f_iter)->is_oneway() || (*f_iter)->get_returntype()->is_void()) { - out << "@YES"; - } else if (type_can_be_null((*f_iter)->get_returntype())) { - out << "result"; - } else { - out << "@(result)"; - } - out << ");" << endl; - - indent_down(); - - out << indent() << "} failure:^(NSError *error) {" << endl; - indent_up(); - out << indent() << "resolver(error);" << endl; - indent_down(); - out << indent() << "}];" << endl; - - indent_down(); - out << indent() << "}];" << endl; - - scope_down(out); - - out << endl; - - } - - } - - out << "@end" << endl << endl; -} - -/** - * Generates a service server implementation. In other words the actual TProcessor implementation - * for the service. - * - * @param tservice The service to generate an implementation for - */ -void t_cocoa_generator::generate_cocoa_service_server_implementation(ostream& out, - t_service* tservice) { - - string name = cocoa_prefix_ + tservice->get_name() + "Processor"; - - out << "@interface " << name << " () "; - - scope_up(out); - out << indent() << "id <" << cocoa_prefix_ << tservice->get_name() << "> service;" << endl; - out << indent() << "NSDictionary * methodMap;" << endl; - scope_down(out); - - out << "@end" << endl << endl; - - out << "@implementation " << name << endl; - - // initializer - out << endl; - out << "- (id) initWith" << tservice->get_name() << ": (id <" << cocoa_prefix_ << tservice->get_name() << ">) aService" << endl; - scope_up(out); - out << indent() << "self = [super init];" << endl; - out << indent() << "if (self) "; - scope_up(out); - out << indent() << "service = aService;" << endl; - out << indent() << "methodMap = [NSMutableDictionary dictionary];" << endl; - - // generate method map for routing incoming calls - vector functions = tservice->get_functions(); - vector::const_iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - string funname = (*f_iter)->get_name(); - scope_up(out); - out << indent() << "SEL s = @selector(process_" << funname << "_withSequenceID:inProtocol:outProtocol:error:);" << endl; - out << indent() << "NSMethodSignature * sig = [self methodSignatureForSelector: s];" << endl; - out << indent() << "NSInvocation * invocation = [NSInvocation invocationWithMethodSignature: sig];" << endl; - out << indent() << "[invocation setSelector: s];" << endl; - out << indent() << "[invocation retainArguments];" << endl; - out << indent() << "[methodMap setValue: invocation forKey: @\"" << funname << "\"];" << endl; - scope_down(out); - } - scope_down(out); - out << indent() << "return self;" << endl; - scope_down(out); - - // implementation of the 'service' method which returns the service associated with this - // processor - out << endl; - out << indent() << "- (id<" << cocoa_prefix_ << tservice->get_name() << ">) service" << endl; - out << indent() << "{" << endl; - out << indent() << " return service;" << endl; - out << indent() << "}" << endl; - - // implementation of the TProcess method, which dispatches the incoming call using the method map - out << endl; - out << indent() << "- (BOOL) processOnInputProtocol: (id ) inProtocol" << endl; - out << indent() << " outputProtocol: (id ) outProtocol" << endl; - out << indent() << " error: (NSError *__autoreleasing *)__thriftError" << endl; - out << indent() << "{" << endl; - out << indent() << " NSString * messageName;" << endl; - out << indent() << " SInt32 messageType;" << endl; - out << indent() << " SInt32 seqID;" << endl; - out << indent() << " if (![inProtocol readMessageBeginReturningName: &messageName" << endl; - out << indent() << " type: &messageType" << endl; - out << indent() << " sequenceID: &seqID" << endl; - out << indent() << " error: __thriftError]) return NO;" << endl; - out << indent() << " NSInvocation * invocation = [methodMap valueForKey: messageName];" << endl; - out << indent() << " if (invocation == nil) {" << endl; - out << indent() << " if (![TProtocolUtil skipType: TTypeSTRUCT onProtocol: inProtocol error: __thriftError]) return NO;" << endl; - out << indent() << " if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl; - out << indent() << " NSError * x = [NSError errorWithDomain: TApplicationErrorDomain" << endl; - out << indent() << " code: TApplicationErrorUnknownMethod" << endl; - out << indent() << " userInfo: @{TApplicationErrorMethodKey: messageName}];" << endl; - out << indent() << " if (![outProtocol writeMessageBeginWithName: messageName" << endl; - out << indent() << " type: TMessageTypeEXCEPTION" << endl; - out << indent() << " sequenceID: seqID" << endl; - out << indent() << " error: __thriftError]) return NO;" << endl; - out << indent() << " if (![x write: outProtocol error: __thriftError]) return NO;" << endl; - out << indent() << " if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl; - out << indent() << " if (![[outProtocol transport] flush: __thriftError]) return NO;" << endl; - out << indent() << " return YES;" << endl; - out << indent() << " }" << endl; - out << indent() << " // NSInvocation does not conform to NSCopying protocol" << endl; - out << indent() << " NSInvocation * i = [NSInvocation invocationWithMethodSignature: " - "[invocation methodSignature]];" << endl; - out << indent() << " [i setSelector: [invocation selector]];" << endl; - out << indent() << " [i setArgument: &seqID atIndex: 2];" << endl; - out << indent() << " [i setArgument: &inProtocol atIndex: 3];" << endl; - out << indent() << " [i setArgument: &outProtocol atIndex: 4];" << endl; - out << indent() << " [i setArgument: &__thriftError atIndex: 5];" << endl; - out << indent() << " [i setTarget: self];" << endl; - out << indent() << " [i invoke];" << endl; - out << indent() << " return YES;" << endl; - out << indent() << "}" << endl; - - // generate a process_XXXX method for each service function, which reads args, calls the service, - // and writes results - functions = tservice->get_functions(); - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - out << endl; - string funname = (*f_iter)->get_name(); - out << indent() << "- (BOOL) process_" << funname - << "_withSequenceID: (SInt32) seqID inProtocol: (id) inProtocol outProtocol: " - "(id) outProtocol error:(NSError *__autoreleasing *)__thriftError" << endl; - scope_up(out); - string argstype = cocoa_prefix_ + function_args_helper_struct_type(tservice, *f_iter); - out << indent() << argstype << " * args = [" << argstype << " new];" << endl; - out << indent() << "if (![args read: inProtocol error: __thriftError]) return NO;" << endl; - out << indent() << "if (![inProtocol readMessageEnd: __thriftError]) return NO;" << endl; - - // prepare the result if not oneway - if (!(*f_iter)->is_oneway()) { - string resulttype = cocoa_prefix_ + function_result_helper_struct_type(tservice, *f_iter); - out << indent() << resulttype << " * result = [" << resulttype << " new];" << endl; - } - - // make the call to the actual service object - out << indent(); - if ((*f_iter)->get_returntype()->is_void()) { - out << "BOOL"; - } else if (type_can_be_null((*f_iter)->get_returntype())) { - out << type_name((*f_iter)->get_returntype(), false, true); - } else { - out << "NSNumber *"; - } - out << " serviceResult = "; - if ((*f_iter)->get_returntype()->get_true_type()->is_container()) { - out << "(" << type_name((*f_iter)->get_returntype(), false, true) << ")"; - } - out << "[service " << funname; - // supplying arguments - t_struct* arg_struct = (*f_iter)->get_arglist(); - const vector& fields = arg_struct->get_members(); - vector::const_iterator fld_iter; - bool first = true; - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - string fieldName = (*fld_iter)->get_name(); - if (first) { - first = false; - out << ": [args " << fieldName << "]"; - } else { - out << " " << fieldName << ": [args " << fieldName << "]"; - } - } - if (!fields.empty()) { - out << " error"; - } - out << ": __thriftError];" << endl; - out << indent() << "if (!serviceResult) return NO;" << endl; - if (!(*f_iter)->get_returntype()->is_void()) { - out << indent() << "[result setSuccess: " << unbox((*f_iter)->get_returntype(), "serviceResult") << "];" << endl; - } - - // write out the result if not oneway - if (!(*f_iter)->is_oneway()) { - out << indent() << "if (![outProtocol writeMessageBeginWithName: @\"" << funname << "\"" << endl; - out << indent() << " type: TMessageTypeREPLY" << endl; - out << indent() << " sequenceID: seqID" << endl; - out << indent() << " error: __thriftError]) return NO;" << endl; - out << indent() << "if (![result write: outProtocol error: __thriftError]) return NO;" << endl; - out << indent() << "if (![outProtocol writeMessageEnd: __thriftError]) return NO;" << endl; - out << indent() << "if (![[outProtocol transport] flush: __thriftError]) return NO;" << endl; - } - out << indent() << "return YES;" << endl; - - scope_down(out); - } - - out << "@end" << endl << endl; -} - -/** - * Deserializes a field of any type. - * - * @param tfield The field - * @param fieldName The variable name for this field - */ -void t_cocoa_generator::generate_deserialize_field(ostream& out, - t_field* tfield, - string fieldName) { - t_type* type = get_true_type(tfield->get_type()); - - if (type->is_void()) { - throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + tfield->get_name(); - } - - if (type->is_struct() || type->is_xception()) { - generate_deserialize_struct(out, (t_struct*)type, fieldName); - } else if (type->is_container()) { - generate_deserialize_container(out, type, fieldName); - } else if (type->is_base_type() || type->is_enum()) { - indent(out) << type_name(type) << " " << fieldName << ";" << endl; - indent(out) << "if (![inProtocol "; - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "compiler error: cannot serialize void field in a struct: " + tfield->get_name(); - break; - case t_base_type::TYPE_STRING: - if (type->is_binary()) { - out << "readBinary:&" << fieldName << " error: __thriftError]"; - } else { - out << "readString:&" << fieldName << " error: __thriftError]"; - } - break; - case t_base_type::TYPE_BOOL: - out << "readBool:&" << fieldName << " error: __thriftError]"; - break; - case t_base_type::TYPE_I8: - out << "readByte:(UInt8 *)&" << fieldName << " error: __thriftError]"; - break; - case t_base_type::TYPE_I16: - out << "readI16:&" << fieldName << " error: __thriftError]"; - break; - case t_base_type::TYPE_I32: - out << "readI32:&" << fieldName << " error: __thriftError]"; - break; - case t_base_type::TYPE_I64: - out << "readI64:&" << fieldName << " error: __thriftError]"; - break; - case t_base_type::TYPE_DOUBLE: - out << "readDouble:&" << fieldName << " error: __thriftError]"; - break; - default: - throw "compiler error: no Objective-C name for base type " - + t_base_type::t_base_name(tbase); - } - } else if (type->is_enum()) { - out << "readI32:&" << fieldName << " error: __thriftError]"; - } - out << ") return NO;" << endl; - } else { - printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", - tfield->get_name().c_str(), - type_name(type).c_str()); - } -} - -/** - * Generates an unserializer for a struct, allocates the struct and invokes read: - */ -void t_cocoa_generator::generate_deserialize_struct(ostream& out, - t_struct* tstruct, - string fieldName) { - indent(out) << type_name(tstruct) << fieldName << " = [[" << type_name(tstruct, true) - << " alloc] init];" << endl; - indent(out) << "if (![" << fieldName << " read: inProtocol error: __thriftError]) return NO;" << endl; -} - -/** - * Deserializes a container by reading its size and then iterating - */ -void t_cocoa_generator::generate_deserialize_container(ostream& out, - t_type* ttype, - string fieldName) { - string size = tmp("_size"); - indent(out) << "SInt32 " << size << ";" << endl; - - // Declare variables, read header - if (ttype->is_map()) { - indent(out) << "if (![inProtocol readMapBeginReturningKeyType: NULL valueType: NULL size: &" << size << " error: __thriftError]) return NO;" << endl; - indent(out) << "NSMutableDictionary * " << fieldName - << " = [[NSMutableDictionary alloc] initWithCapacity: " << size << "];" << endl; - } else if (ttype->is_set()) { - indent(out) << "if (![inProtocol readSetBeginReturningElementType: NULL size: &" << size << " error: __thriftError]) return NO;" - << endl; - indent(out) << "NSMutableSet * " << fieldName - << " = [[NSMutableSet alloc] initWithCapacity: " << size << "];" << endl; - } else if (ttype->is_list()) { - indent(out) << "if (![inProtocol readListBeginReturningElementType: NULL size: &" << size << " error: __thriftError]) return NO;" - << endl; - indent(out) << "NSMutableArray * " << fieldName - << " = [[NSMutableArray alloc] initWithCapacity: " << size << "];" << endl; - } - // FIXME - the code above does not verify that the element types of - // the containers being read match the element types of the - // containers we are reading into. Does that matter? - - // For loop iterates over elements - string i = tmp("_i"); - indent(out) << "int " << i << ";" << endl << indent() << "for (" << i << " = 0; " << i << " < " - << size << "; " - << "++" << i << ")" << endl; - - scope_up(out); - - if (ttype->is_map()) { - generate_deserialize_map_element(out, (t_map*)ttype, fieldName); - } else if (ttype->is_set()) { - generate_deserialize_set_element(out, (t_set*)ttype, fieldName); - } else if (ttype->is_list()) { - generate_deserialize_list_element(out, (t_list*)ttype, fieldName); - } - - scope_down(out); - - // Read container end - if (ttype->is_map()) { - indent(out) << "if (![inProtocol readMapEnd: __thriftError]) return NO;" << endl; - } else if (ttype->is_set()) { - indent(out) << "if (![inProtocol readSetEnd: __thriftError]) return NO;" << endl; - } else if (ttype->is_list()) { - indent(out) << "if (![inProtocol readListEnd: __thriftError]) return NO;" << endl; - } -} - -/** - * Take a variable of a given type and wrap it in code to make it - * suitable for putting into a container, if necessary. Basically, - * wrap scaler primitives in NSNumber objects. - */ -string t_cocoa_generator::box(t_type* ttype, string field_name) { - - ttype = get_true_type(ttype); - if (ttype->is_enum()) { - return "@(" + field_name + ")"; - } else if (ttype->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "can't box void"; - case t_base_type::TYPE_BOOL: - case t_base_type::TYPE_I8: - case t_base_type::TYPE_I16: - case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: - case t_base_type::TYPE_DOUBLE: - return "@(" + field_name + ")"; - default: - break; - } - } - - // do nothing - return field_name; -} - -/** - * Extracts the actual value from a boxed value - */ -string t_cocoa_generator::unbox(t_type* ttype, string field_name) { - ttype = get_true_type(ttype); - if (ttype->is_enum()) { - return "[" + field_name + " intValue]"; - } else if (ttype->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "can't unbox void"; - case t_base_type::TYPE_BOOL: - return "[" + field_name + " boolValue]"; - case t_base_type::TYPE_I8: - return "((SInt8)[" + field_name + " charValue])"; - case t_base_type::TYPE_I16: - return "((SInt16)[" + field_name + " shortValue])"; - case t_base_type::TYPE_I32: - return "((SInt32)[" + field_name + " longValue])"; - case t_base_type::TYPE_I64: - return "((SInt64)[" + field_name + " longLongValue])"; - case t_base_type::TYPE_DOUBLE: - return "[" + field_name + " doubleValue]"; - default: - break; - } - } - - // do nothing - return field_name; -} - -/** - * Generates code to deserialize a map element - */ -void t_cocoa_generator::generate_deserialize_map_element(ostream& out, - t_map* tmap, - string fieldName) { - string key = tmp("_key"); - string val = tmp("_val"); - t_type* keyType = tmap->get_key_type(); - t_type* valType = tmap->get_val_type(); - t_field fkey(keyType, key); - t_field fval(valType, val); - - generate_deserialize_field(out, &fkey, key); - generate_deserialize_field(out, &fval, val); - - indent(out) << "[" << fieldName << " setObject: " << box(valType, val) - << " forKey: " << box(keyType, key) << "];" << endl; -} - -/** - * Deserializes a set element - */ -void t_cocoa_generator::generate_deserialize_set_element(ostream& out, - t_set* tset, - string fieldName) { - string elem = tmp("_elem"); - t_type* type = tset->get_elem_type(); - t_field felem(type, elem); - - generate_deserialize_field(out, &felem, elem); - - indent(out) << "[" << fieldName << " addObject: " << box(type, elem) << "];" << endl; -} - -/** - * Deserializes a list element - */ -void t_cocoa_generator::generate_deserialize_list_element(ostream& out, - t_list* tlist, - string fieldName) { - string elem = tmp("_elem"); - t_type* type = tlist->get_elem_type(); - t_field felem(type, elem); - - generate_deserialize_field(out, &felem, elem); - - indent(out) << "[" << fieldName << " addObject: " << box(type, elem) << "];" << endl; -} - -/** - * Serializes a field of any type. - * - * @param tfield The field to serialize - * @param fieldName Name to of the variable holding the field - */ -void t_cocoa_generator::generate_serialize_field(ostream& out, t_field* tfield, string fieldName) { - t_type* type = get_true_type(tfield->get_type()); - - // Do nothing for void types - if (type->is_void()) { - throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + tfield->get_name(); - } - - if (type->is_struct() || type->is_xception()) { - generate_serialize_struct(out, (t_struct*)type, fieldName); - } else if (type->is_container()) { - generate_serialize_container(out, type, fieldName); - } else if (type->is_base_type() || type->is_enum()) { - indent(out) << "if (![outProtocol "; - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "compiler error: cannot serialize void field in a struct: " + fieldName; - break; - case t_base_type::TYPE_STRING: - if (type->is_binary()) { - out << "writeBinary: " << fieldName << " error: __thriftError]"; - } else { - out << "writeString: " << fieldName << " error: __thriftError]"; - } - break; - case t_base_type::TYPE_BOOL: - out << "writeBool: " << fieldName << " error: __thriftError]"; - break; - case t_base_type::TYPE_I8: - out << "writeByte: (UInt8)" << fieldName << " error: __thriftError]"; - break; - case t_base_type::TYPE_I16: - out << "writeI16: " << fieldName << " error: __thriftError]"; - break; - case t_base_type::TYPE_I32: - out << "writeI32: " << fieldName << " error: __thriftError]"; - break; - case t_base_type::TYPE_I64: - out << "writeI64: " << fieldName << " error: __thriftError]"; - break; - case t_base_type::TYPE_DOUBLE: - out << "writeDouble: " << fieldName << " error: __thriftError]"; - break; - default: - throw "compiler error: no Objective-C name for base type " - + t_base_type::t_base_name(tbase); - } - } else if (type->is_enum()) { - out << "writeI32: " << fieldName << " error: __thriftError]"; - } - out << ") return NO;" << endl; - } else { - printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s' TYPE '%s'\n", - tfield->get_name().c_str(), - type_name(type).c_str()); - } -} - -/** - * Serialize a struct. - * - * @param tstruct The struct to serialize - * @param fieldName Name of variable holding struct - */ -void t_cocoa_generator::generate_serialize_struct(ostream& out, - t_struct* tstruct, - string fieldName) { - (void)tstruct; - out << indent() << "if (![" << fieldName << " write: outProtocol error: __thriftError]) return NO;" << endl; -} - -/** - * Serializes a container by writing its size then the elements. - * - * @param ttype The type of container - * @param fieldName Name of variable holding container - */ -void t_cocoa_generator::generate_serialize_container(ostream& out, - t_type* ttype, - string fieldName) { - scope_up(out); - - if (ttype->is_map()) { - indent(out) << "if (![outProtocol writeMapBeginWithKeyType: " - << type_to_enum(((t_map*)ttype)->get_key_type()) - << " valueType: " << type_to_enum(((t_map*)ttype)->get_val_type()) << " size: (SInt32)[" - << fieldName << " count] error: __thriftError]) return NO;" << endl; - } else if (ttype->is_set()) { - indent(out) << "if (![outProtocol writeSetBeginWithElementType: " - << type_to_enum(((t_set*)ttype)->get_elem_type()) << " size: (SInt32)[" << fieldName - << " count] error: __thriftError]) return NO;" << endl; - } else if (ttype->is_list()) { - indent(out) << "if (![outProtocol writeListBeginWithElementType: " - << type_to_enum(((t_list*)ttype)->get_elem_type()) << " size: (SInt32)[" << fieldName - << " count] error: __thriftError]) return NO;" << endl; - } - - string iter = tmp("_iter"); - string key; - if (ttype->is_map()) { - key = tmp("key"); - indent(out) << "NSEnumerator * " << iter << " = [" << fieldName << " keyEnumerator];" << endl; - indent(out) << "id " << key << ";" << endl; - indent(out) << "while ((" << key << " = [" << iter << " nextObject]))" << endl; - } else if (ttype->is_set()) { - key = tmp("obj"); - indent(out) << "NSEnumerator * " << iter << " = [" << fieldName << " objectEnumerator];" - << endl; - indent(out) << "id " << key << ";" << endl; - indent(out) << "while ((" << key << " = [" << iter << " nextObject]))" << endl; - } else if (ttype->is_list()) { - key = tmp("idx"); - indent(out) << "int " << key << ";" << endl; - indent(out) << "for (" << key << " = 0; " << key << " < [" << fieldName << " count]; " << key - << "++)" << endl; - } - - scope_up(out); - - if (ttype->is_map()) { - generate_serialize_map_element(out, (t_map*)ttype, key, fieldName); - } else if (ttype->is_set()) { - generate_serialize_set_element(out, (t_set*)ttype, key); - } else if (ttype->is_list()) { - generate_serialize_list_element(out, (t_list*)ttype, key, fieldName); - } - - scope_down(out); - - if (ttype->is_map()) { - indent(out) << "if (![outProtocol writeMapEnd: __thriftError]) return NO;" << endl; - } else if (ttype->is_set()) { - indent(out) << "if (![outProtocol writeSetEnd: __thriftError]) return NO;" << endl; - } else if (ttype->is_list()) { - indent(out) << "if (![outProtocol writeListEnd: __thriftError]) return NO;" << endl; - } - - scope_down(out); -} - -/** - * Serializes the members of a map. - */ -void t_cocoa_generator::generate_serialize_map_element(ostream& out, - t_map* tmap, - string key, - string mapName) { - t_field kfield(tmap->get_key_type(), key); - generate_serialize_field(out, &kfield, unbox(kfield.get_type(), key)); - t_field vfield(tmap->get_val_type(), "[" + mapName + " objectForKey: " + key + "]"); - generate_serialize_field(out, &vfield, unbox(vfield.get_type(), vfield.get_name())); -} - -/** - * Serializes the members of a set. - */ -void t_cocoa_generator::generate_serialize_set_element(ostream& out, - t_set* tset, - string elementName) { - t_field efield(tset->get_elem_type(), elementName); - generate_serialize_field(out, &efield, unbox(efield.get_type(), elementName)); -} - -/** - * Serializes the members of a list. - */ -void t_cocoa_generator::generate_serialize_list_element(ostream& out, - t_list* tlist, - string index, - string listName) { - t_field efield(tlist->get_elem_type(), "[" + listName + " objectAtIndex: " + index + "]"); - generate_serialize_field(out, &efield, unbox(efield.get_type(), efield.get_name())); -} - -/** - * Returns an Objective-C name - * - * @param ttype The type - * @param class_ref Do we want a Class reference istead of a type reference? - * @return Objective-C type name, i.e. NSDictionary * - */ -string t_cocoa_generator::type_name(t_type* ttype, bool class_ref, bool needs_mutable) { - if (ttype->is_typedef()) { - string name = (needs_mutable && ttype->get_true_type()->is_container()) ? "Mutable" + ttype->get_name() : ttype->get_name(); - t_program* program = ttype->get_program(); - return program ? (program->get_namespace("cocoa") + name) : name; - } - - string result; - if (ttype->is_base_type()) { - return base_type_name((t_base_type*)ttype); - } else if (ttype->is_enum()) { - return cocoa_prefix_ + ttype->get_name(); - } else if (ttype->is_map()) { - t_map *map = (t_map *)ttype; - result = needs_mutable ? "NSMutableDictionary" : "NSDictionary"; - result += "<" + element_type_name(map->get_key_type()) + ", " + element_type_name(map->get_val_type()) + ">"; - } else if (ttype->is_set()) { - t_set *set = (t_set *)ttype; - result = needs_mutable ? "NSMutableSet" : "NSSet"; - result += "<" + element_type_name(set->get_elem_type()) + ">"; - } else if (ttype->is_list()) { - t_list *list = (t_list *)ttype; - result = needs_mutable ? "NSMutableArray" : "NSArray"; - result += "<" + element_type_name(list->get_elem_type()) + ">"; - } else { - // Check for prefix - t_program* program = ttype->get_program(); - if (program != NULL) { - result = program->get_namespace("cocoa") + ttype->get_name(); - } else { - result = ttype->get_name(); - } - } - - if (!class_ref) { - result += " *"; - } - return result; -} - -/** - * Returns an Objective-C type name for container types - * - * @param ttype the type - */ -string t_cocoa_generator::element_type_name(t_type* etype) { - - t_type* ttype = etype->get_true_type(); - - if (etype->is_typedef() && type_can_be_null(ttype)) { - return type_name(etype); - } - - string result; - if (ttype->is_base_type()) { - t_base_type* tbase = (t_base_type*)ttype; - switch (tbase->get_base()) { - case t_base_type::TYPE_STRING: - if (tbase->is_binary()) { - result = "NSData *"; - } - else { - result = "NSString *"; - } - break; - default: - result = "NSNumber *"; - break; - } - } else if (ttype->is_enum()) { - result = "NSNumber *"; - } else if (ttype->is_map()) { - t_map *map = (t_map *)ttype; - result = "NSDictionary<" + element_type_name(map->get_key_type()) + ", " + element_type_name(map->get_val_type()) + "> *"; - } else if (ttype->is_set()) { - t_set *set = (t_set *)ttype; - result = "NSSet<" + element_type_name(set->get_elem_type()) + "> *"; - } else if (ttype->is_list()) { - t_list *list = (t_list *)ttype; - result = "NSArray<" + element_type_name(list->get_elem_type()) + "> *"; - } else if (ttype->is_struct() || ttype->is_xception()) { - result = cocoa_prefix_ + ttype->get_name() + " *"; - } - - return result; -} - -/** - * Returns the Objective-C type that corresponds to the thrift type. - * - * @param tbase The base type - */ -string t_cocoa_generator::base_type_name(t_base_type* type) { - t_base_type::t_base tbase = type->get_base(); - - switch (tbase) { - case t_base_type::TYPE_VOID: - return "void"; - case t_base_type::TYPE_STRING: - if (type->is_binary()) { - return "NSData *"; - } else { - return "NSString *"; - } - case t_base_type::TYPE_BOOL: - return "BOOL"; - case t_base_type::TYPE_I8: - return "SInt8"; - case t_base_type::TYPE_I16: - return "SInt16"; - case t_base_type::TYPE_I32: - return "SInt32"; - case t_base_type::TYPE_I64: - return "SInt64"; - case t_base_type::TYPE_DOUBLE: - return "double"; - default: - throw "compiler error: no Objective-C name for base type " + t_base_type::t_base_name(tbase); - } -} - -/** - * Prints the value of a constant with the given type. Note that type checking - * is NOT performed in this function as it is always run beforehand using the - * validate_types method in main.cc - */ -void t_cocoa_generator::print_const_value(ostream& out, - string name, - t_type* type, - t_const_value* value, - bool defval) { - type = get_true_type(type); - - if (type->is_base_type()) { - string v2 = render_const_value(out, type, value); - indent(out); - if (defval) - out << type_name(type) << " "; - out << name << " = " << v2 << ";" << endl << endl; - } else if (type->is_enum()) { - indent(out); - if (defval) - out << type_name(type) << " "; - out << name << " = " << render_const_value(out, type, value) << ";" << endl << endl; - } else if (type->is_struct() || type->is_xception()) { - indent(out); - const vector& fields = ((t_struct*)type)->get_members(); - vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; - if (defval) - out << type_name(type) << " "; - out << name << " = [" << type_name(type, true) << " new];" - << endl; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - t_type* field_type = NULL; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if ((*f_iter)->get_name() == v_iter->first->get_string()) { - field_type = (*f_iter)->get_type(); - } - } - if (field_type == NULL) { - throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); - } - string val = render_const_value(out, field_type, v_iter->second); - std::string cap_name = capitalize(v_iter->first->get_string()); - indent(out) << "[" << name << " set" << cap_name << ":" << val << "];" << endl; - } - } else if (type->is_map()) { - ostringstream mapout; - indent(mapout); - t_type* ktype = ((t_map*)type)->get_key_type(); - t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; - if (defval) - mapout << type_name(type) << " "; - mapout << name << " = @{"; - for (v_iter = val.begin(); v_iter != val.end();) { - mapout << render_const_value(out, ktype, v_iter->first, true) << ": " - << render_const_value(out, vtype, v_iter->second, true); - if (++v_iter != val.end()) { - mapout << ", "; - } - } - mapout << "}"; - out << mapout.str(); - } else if (type->is_list()) { - ostringstream listout; - indent(listout); - t_type* etype = ((t_list*)type)->get_elem_type(); - const vector& val = value->get_list(); - vector::const_iterator v_iter; - if (defval) - listout << type_name(type) << " "; - listout << name << " = @["; - for (v_iter = val.begin(); v_iter != val.end();) { - listout << render_const_value(out, etype, *v_iter, true); - if (++v_iter != val.end()) { - listout << ", "; - } - } - listout << "]"; - out << listout.str(); - } else if (type->is_set()) { - ostringstream setout; - indent(setout); - t_type* etype = ((t_set*)type)->get_elem_type(); - const vector& val = value->get_list(); - vector::const_iterator v_iter; - if (defval) - setout << type_name(type) << " "; - setout << name << " = [NSSet setWithArray:@["; - for (v_iter = val.begin(); v_iter != val.end();) { - setout << render_const_value(out, etype, *v_iter, true); - if (++v_iter != val.end()) { - setout << ", "; - } - } - setout << "]]"; - out << setout.str(); - } else { - throw "compiler error: no const of type " + type->get_name(); - } -} - -string t_cocoa_generator::render_const_value(ostream& out, - t_type* type, - t_const_value* value, - bool box_it) { - type = get_true_type(type); - std::ostringstream render; - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_STRING: - // We must handle binary constant but the syntax of IDL defines - // nothing about binary constant. - // if type->is_binary()) - // // binary code - render << "@\"" << get_escaped_string(value) << '"'; - break; - case t_base_type::TYPE_BOOL: - render << ((value->get_integer() > 0) ? "YES" : "NO"); - break; - case t_base_type::TYPE_I8: - case t_base_type::TYPE_I16: - case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: - render << value->get_integer(); - break; - case t_base_type::TYPE_DOUBLE: - if (value->get_type() == t_const_value::CV_INTEGER) { - render << value->get_integer(); - } else { - render << value->get_double(); - } - break; - default: - throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); - } - } else if (type->is_enum()) { - render << value->get_integer(); - } else { - string t = tmp("tmp"); - print_const_value(out, t, type, value, true); - out << ";" << endl; - render << t; - } - - if (box_it) { - return box(type, render.str()); - } - return render.str(); -} - -#if 0 -/** -ORIGINAL - * Spit out code that evaluates to the specified constant value. - */ -string t_cocoa_generator::render_const_value(string name, - t_type* type, - t_const_value* value, - bool box_it) { - type = get_true_type(type); - std::ostringstream render; - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_STRING: - render << "@\"" << get_escaped_string(value) << '"'; - break; - case t_base_type::TYPE_BOOL: - render << ((value->get_integer() > 0) ? "YES" : "NO"); - break; - case t_base_type::TYPE_I8: - case t_base_type::TYPE_I16: - case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: - render << value->get_integer(); - break; - case t_base_type::TYPE_DOUBLE: - if (value->get_type() == t_const_value::CV_INTEGER) { - render << value->get_integer(); - } else { - render << value->get_double(); - } - break; - default: - throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); - } - } else if (type->is_enum()) { - render << value->get_integer(); - } else if (type->is_struct() || type->is_xception()) { - const vector& fields = ((t_struct*)type)->get_members(); - vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; - if (val.size() > 0) - render << "[[" << type_name(type, true) << " alloc] initWith"; - else - render << "[[" << type_name(type, true) << " alloc] init"; - bool first = true; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - // FIXME The generated code does not match with initWithXXX - // initializer and causes compile error. - // Try: test/DebugProtoTest.thrift and test/SmallTest.thrift - t_type* field_type = NULL; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if ((*f_iter)->get_name() == v_iter->first->get_string()) { - field_type = (*f_iter)->get_type(); - } - } - if (field_type == NULL) { - throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); - } - if (first) { - render << capitalize(v_iter->first->get_string()); - first = false; - } else { - render << " " << v_iter->first->get_string(); - } - render << ": " << render_const_value(name, field_type, v_iter->second); - } - render << "]"; - } else if (type->is_map()) { - render << "[[NSDictionary alloc] initWithObjectsAndKeys: "; - t_type* ktype = ((t_map*)type)->get_key_type(); - t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; - bool first = true; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - string key = render_const_value(name, ktype, v_iter->first, true); - string val = render_const_value(name, vtype, v_iter->second, true); - if (first) { - first = false; - } else { - render << ", "; - } - render << val << ", " << key; - } - if (first) - render << " nil]"; - else - render << ", nil]"; - } else if (type->is_list()) { - render << "[[NSArray alloc] initWithObjects: "; - t_type * etype = ((t_list*)type)->get_elem_type(); - const vector& val = value->get_list(); - bool first = true; - vector::const_iterator v_iter; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - if (first) { - first = false; - } else { - render << ", "; - } - render << render_const_value(name, etype, *v_iter, true); - } - if (first) - render << " nil]"; - else - render << ", nil]"; - } else if (type->is_set()) { - render << "[[NSSet alloc] initWithObjects: "; - t_type * etype = ((t_set*)type)->get_elem_type(); - const vector& val = value->get_list(); - bool first = true; - vector::const_iterator v_iter; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - if (first) { - first = false; - } else { - render << ", "; - } - render << render_const_value(name, etype, *v_iter, true); - } - if (first) - render << " nil]"; - else - render << ", nil]"; - } else { - throw "don't know how to render constant for type: " + type->get_name(); - } - - if (box_it) { - return box(type, render.str()); - } - - return render.str(); -} -#endif - -/** - * Declares an Objective-C 2.0 property. - * - * @param tfield The field to declare a property for - */ -string t_cocoa_generator::declare_property(t_field* tfield) { - std::ostringstream render; - render << "@property ("; - - if (type_can_be_copy(tfield->get_type())) { - render << "copy, "; - } else if (type_can_be_null(tfield->get_type())) { - render << "strong, "; - } else { - render << "assign, "; - } - - render << "nonatomic) " << type_name(tfield->get_type(), false, true) << " " - << tfield->get_name() << ";"; - - // Check if the property name is an Objective-C return +1 count signal - if ((tfield->get_name().length() >= 3 && tfield->get_name().substr(0,3) == "new") || - (tfield->get_name().length() >= 6 && tfield->get_name().substr(0,6) == "create") || - (tfield->get_name().length() >= 5 && tfield->get_name().substr(0,5) == "alloc")) { - // Let Objective-C know not to return +1 for object pointers - if (type_can_be_null(tfield->get_type())) { - render << endl; - render << "- (" + type_name(tfield->get_type()) + ") " + decapitalize(tfield->get_name()) + " __attribute__((objc_method_family(none)));"; - } - } - - return render.str(); -} - -/** - * Declares an Objective-C 2.0 property. - * - * @param tfield The field to declare a property for - */ -string t_cocoa_generator::declare_property_isset(t_field* tfield) { - return "@property (assign, nonatomic) BOOL " + decapitalize(tfield->get_name()) + "IsSet;"; -} - -/** - * Declares property unset method. - * - * @param tfield The field to declare a property for - */ -string t_cocoa_generator::declare_property_unset(t_field* tfield) { - return "- (void) unset" + capitalize(tfield->get_name()) + ";"; -} - -/** - * Renders the early out return statement - * - * @param tfunction Function definition - * @return String of rendered invalid return statment - */ -string t_cocoa_generator::invalid_return_statement(t_function *tfunction) { - if ((tfunction->get_returntype()->is_void())) { - return "return NO;"; - } - return "return nil;"; -} - -/** - * Renders a function signature - * - * @param tfunction Function definition - * @return String of rendered function definition - */ -string t_cocoa_generator::function_signature(t_function* tfunction, bool include_error) { - t_type* ttype = tfunction->get_returntype(); - string result; - if (ttype->is_void()) { - result = "(BOOL)"; - } - else if (type_can_be_null(ttype)) { - result = "(" + type_name(ttype) + ")"; - } - else { - result = "(NSNumber *)"; - } - result += " " + tfunction->get_name() + argument_list(tfunction->get_arglist(), "", include_error); - return result; -} - -/** - * Renders a function signature that returns asynchronously instead of - * literally returning. - * - * @param tfunction Function definition - * @return String of rendered function definition - */ -string t_cocoa_generator::async_function_signature(t_function* tfunction, bool include_error) { - t_type* ttype = tfunction->get_returntype(); - t_struct* targlist = tfunction->get_arglist(); - string response_param = "void (^)(" + ((ttype->is_void()) ? "" : type_name(ttype)) + ")"; - std::string result = "(void) " + tfunction->get_name() + argument_list(tfunction->get_arglist(), "", include_error) - + (targlist->get_members().size() ? " response" : "") + ": (" - + response_param + ") responseBlock " - + "failure : (TAsyncFailureBlock) failureBlock"; - return result; -} - -/** - * Renders a function signature that returns a promise instead of - * literally returning. - * - * @param tfunction Function definition - * @return String of rendered function definition - */ -string t_cocoa_generator::promise_function_signature(t_function* tfunction) { - return "(AnyPromise *) " + tfunction->get_name() + argument_list(tfunction->get_arglist(), "", false); -} - -/** - * Renders a colon separated list of types and names, suitable for an - * objective-c parameter list - */ -string t_cocoa_generator::argument_list(t_struct* tstruct, string protocol_name, bool include_error) { - string result = ""; - bool include_protocol = !protocol_name.empty(); - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - bool first = true; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - string argPrefix = ""; - if (first) { - first = false; - } else { - argPrefix = (*f_iter)->get_name(); - result += " "; - } - result += argPrefix + ": (" + type_name((*f_iter)->get_type()) + ") " + (*f_iter)->get_name(); - } - if (include_protocol) { - if (!first) { - result += " protocol"; - } - result += ": (id) " + protocol_name; - first = false; - } - if (include_error) { - if (!first) { - result += " error"; - } - result += ": (NSError *__autoreleasing *)__thriftError"; - first = false; - } - return result; -} - -/** - * Converts the parse type to an Objective-C enum string for the given type. - */ -string t_cocoa_generator::type_to_enum(t_type* type) { - type = get_true_type(type); - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "NO T_VOID CONSTRUCT"; - case t_base_type::TYPE_STRING: - return "TTypeSTRING"; - case t_base_type::TYPE_BOOL: - return "TTypeBOOL"; - case t_base_type::TYPE_I8: - return "TTypeBYTE"; - case t_base_type::TYPE_I16: - return "TTypeI16"; - case t_base_type::TYPE_I32: - return "TTypeI32"; - case t_base_type::TYPE_I64: - return "TTypeI64"; - case t_base_type::TYPE_DOUBLE: - return "TTypeDOUBLE"; - } - } else if (type->is_enum()) { - return "TTypeI32"; - } else if (type->is_struct() || type->is_xception()) { - return "TTypeSTRUCT"; - } else if (type->is_map()) { - return "TTypeMAP"; - } else if (type->is_set()) { - return "TTypeSET"; - } else if (type->is_list()) { - return "TTypeLIST"; - } - - throw "INVALID TYPE IN type_to_enum: " + type->get_name(); -} - -/** - * Returns a format string specifier for the supplied parse type. - */ -string t_cocoa_generator::format_string_for_type(t_type* type) { - type = get_true_type(type); - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "NO T_VOID CONSTRUCT"; - case t_base_type::TYPE_STRING: - return "\\\"%@\\\""; - case t_base_type::TYPE_BOOL: - return "%i"; - case t_base_type::TYPE_I8: - return "%i"; - case t_base_type::TYPE_I16: - return "%hi"; - case t_base_type::TYPE_I32: - return "%i"; - case t_base_type::TYPE_I64: - return "%qi"; - case t_base_type::TYPE_DOUBLE: - return "%f"; - } - } else if (type->is_enum()) { - return "%i"; - } else if (type->is_struct() || type->is_xception()) { - return "%@"; - } else if (type->is_map()) { - return "%@"; - } else if (type->is_set()) { - return "%@"; - } else if (type->is_list()) { - return "%@"; - } - - throw "INVALID TYPE IN format_string_for_type: " + type->get_name(); -} - -/** - * Returns a format cast for the supplied parse type. - */ -string t_cocoa_generator::format_cast_for_type(t_type* type) { - type = get_true_type(type); - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "NO T_VOID CONSTRUCT"; - case t_base_type::TYPE_STRING: - return ""; // "\\\"%@\\\""; - case t_base_type::TYPE_BOOL: - return ""; // "%i"; - case t_base_type::TYPE_I8: - return ""; // "%i"; - case t_base_type::TYPE_I16: - return ""; // "%hi"; - case t_base_type::TYPE_I32: - return "(int)"; // "%i"; - case t_base_type::TYPE_I64: - return ""; // "%qi"; - case t_base_type::TYPE_DOUBLE: - return ""; // "%f"; - } - } else if (type->is_enum()) { - return "(int)"; // "%i"; - } else if (type->is_struct() || type->is_xception()) { - return ""; // "%@"; - } else if (type->is_map()) { - return ""; // "%@"; - } else if (type->is_set()) { - return ""; // "%@"; - } else if (type->is_list()) { - return ""; // "%@"; - } - - throw "INVALID TYPE IN format_cast_for_type: " + type->get_name(); -} - -/** - * Generate a call to a field's setter. - * - * @param tfield Field the setter is being called on - * @param fieldName Name of variable to pass to setter - */ - -string t_cocoa_generator::call_field_setter(t_field* tfield, string fieldName) { - return "self." + tfield->get_name() + " = " + fieldName + ";"; -} - -THRIFT_REGISTER_GENERATOR( - cocoa, - "Cocoa", - " log_unexpected: Log every time an unexpected field ID or type is encountered.\n" - " debug_descriptions:\n" - " Allow use of debugDescription so the app can add description via a cateogory/extension\n" - " validate_required:\n" - " Throws exception if any required field is not set.\n" - " async_clients: Generate clients which invoke asynchronously via block syntax.\n" - " pods: Generate imports in Cocopods framework format.\n" - " promise_kit: Generate clients which invoke asynchronously via promises.\n") diff --git a/compiler/cpp/src/thrift/thriftl.ll b/compiler/cpp/src/thrift/thriftl.ll index 4f783be96f8..282e0309ca2 100644 --- a/compiler/cpp/src/thrift/thriftl.ll +++ b/compiler/cpp/src/thrift/thriftl.ll @@ -207,15 +207,14 @@ literal_begin (['\"]) "cpp_include" { return tok_cpp_include; } "cpp_type" { return tok_cpp_type; } "java_package" { error_unsupported_namespace_decl("java_package", "java"); /* do nothing */ } -"cocoa_prefix" { error_unsupported_namespace_decl("cocoa_prefix", "cocoa"); /* do nothing */ } "csharp_namespace" { error_unsupported_namespace_decl("csharp"); /* do nothing */ } "delphi_namespace" { error_unsupported_namespace_decl("delphi"); /* do nothing */ } "php_namespace" { error_unsupported_namespace_decl("php"); /* do nothing */ } "py_module" { error_unsupported_namespace_decl("py_module", "py"); /* do nothing */ } "perl_package" { error_unsupported_namespace_decl("perl_package", "perl"); /* do nothing */ } "ruby_namespace" { error_unsupported_namespace_decl("ruby"); /* do nothing */ } -"smalltalk_category" { error_unsupported_namespace_decl("smalltalk_category", "smalltalk.category"); /* do nothing */ } -"smalltalk_prefix" { error_unsupported_namespace_decl("smalltalk_category", "smalltalk.category"); /* do nothing */ } +"smalltalk_category" { error_unsupported_namespace_decl("smalltalk_category", "st"); /* do nothing */ } +"smalltalk_prefix" { error_unsupported_namespace_decl("smalltalk_prefix", "st"); /* do nothing */ } "xsd_all" { return tok_xsd_all; } "xsd_optional" { return tok_xsd_optional; } "xsd_nillable" { return tok_xsd_nillable; } diff --git a/compiler/cpp/tests/CMakeLists.txt b/compiler/cpp/tests/CMakeLists.txt index e2b100c7a4b..fde9073cad2 100644 --- a/compiler/cpp/tests/CMakeLists.txt +++ b/compiler/cpp/tests/CMakeLists.txt @@ -96,36 +96,36 @@ macro(THRIFT_ADD_COMPILER name description initial) endmacro() # The following compiler with unit tests can be enabled or disabled +THRIFT_ADD_COMPILER(as3 "Enable compiler for ActionScript 3" OFF) THRIFT_ADD_COMPILER(c_glib "Enable compiler for C with Glib" OFF) +THRIFT_ADD_COMPILER(cl "Enable compiler for Common LISP" OFF) THRIFT_ADD_COMPILER(cpp "Enable compiler for C++" OFF) -THRIFT_ADD_COMPILER(java "Enable compiler for Java" OFF) -THRIFT_ADD_COMPILER(as3 "Enable compiler for ActionScript 3" OFF) -THRIFT_ADD_COMPILER(dart "Enable compiler for Dart" OFF) -THRIFT_ADD_COMPILER(haxe "Enable compiler for Haxe" OFF) THRIFT_ADD_COMPILER(csharp "Enable compiler for C#" OFF) -THRIFT_ADD_COMPILER(netcore "Enable compiler for .NET Core" ON) -THRIFT_ADD_COMPILER(py "Enable compiler for Python 2.0" OFF) -THRIFT_ADD_COMPILER(rb "Enable compiler for Ruby" OFF) -THRIFT_ADD_COMPILER(perl "Enable compiler for Perl" OFF) -THRIFT_ADD_COMPILER(php "Enable compiler for PHP" OFF) +THRIFT_ADD_COMPILER(d "Enable compiler for D" OFF) +THRIFT_ADD_COMPILER(dart "Enable compiler for Dart" OFF) +THRIFT_ADD_COMPILER(delphi "Enable compiler for Delphi" OFF) THRIFT_ADD_COMPILER(erl "Enable compiler for Erlang" OFF) -THRIFT_ADD_COMPILER(cocoa "Enable compiler for Cocoa Objective-C" OFF) -THRIFT_ADD_COMPILER(swift "Enable compiler for Cocoa Swift" OFF) -THRIFT_ADD_COMPILER(st "Enable compiler for Smalltalk" OFF) -THRIFT_ADD_COMPILER(ocaml "Enable compiler for OCaml" OFF) +THRIFT_ADD_COMPILER(go "Enable compiler for Go" OFF) +THRIFT_ADD_COMPILER(gv "Enable compiler for GraphViz" OFF) +THRIFT_ADD_COMPILER(haxe "Enable compiler for Haxe" OFF) THRIFT_ADD_COMPILER(hs "Enable compiler for Haskell" OFF) -THRIFT_ADD_COMPILER(xsd "Enable compiler for XSD" OFF) THRIFT_ADD_COMPILER(html "Enable compiler for HTML Documentation" OFF) +THRIFT_ADD_COMPILER(java "Enable compiler for Java" OFF) +THRIFT_ADD_COMPILER(javame "Enable compiler for Java ME" OFF) THRIFT_ADD_COMPILER(js "Enable compiler for JavaScript" OFF) THRIFT_ADD_COMPILER(json "Enable compiler for JSON" OFF) -THRIFT_ADD_COMPILER(javame "Enable compiler for Java ME" OFF) -THRIFT_ADD_COMPILER(delphi "Enable compiler for Delphi" OFF) -THRIFT_ADD_COMPILER(go "Enable compiler for Go" OFF) -THRIFT_ADD_COMPILER(d "Enable compiler for D" OFF) THRIFT_ADD_COMPILER(lua "Enable compiler for Lua" OFF) -THRIFT_ADD_COMPILER(gv "Enable compiler for GraphViz" OFF) +THRIFT_ADD_COMPILER(netcore "Enable compiler for .NET Core" ON) +THRIFT_ADD_COMPILER(ocaml "Enable compiler for OCaml" OFF) +THRIFT_ADD_COMPILER(perl "Enable compiler for Perl" OFF) +THRIFT_ADD_COMPILER(php "Enable compiler for PHP" OFF) +THRIFT_ADD_COMPILER(py "Enable compiler for Python 2.0" OFF) +THRIFT_ADD_COMPILER(rb "Enable compiler for Ruby" OFF) THRIFT_ADD_COMPILER(rs "Enable compiler for Rust" OFF) +THRIFT_ADD_COMPILER(st "Enable compiler for Smalltalk" OFF) +THRIFT_ADD_COMPILER(swift "Enable compiler for Swift" OFF) THRIFT_ADD_COMPILER(xml "Enable compiler for XML" OFF) +THRIFT_ADD_COMPILER(xsd "Enable compiler for XSD" OFF) # Thrift is looking for include files in the src directory # we also add the current binary directory for generated files @@ -150,4 +150,4 @@ set_target_properties(thrift_compiler_tests PROPERTIES OUTPUT_NAME thrift_compil target_link_libraries(thrift_compiler_tests thrift_compiler) enable_testing() -add_test(NAME ThriftTests COMMAND thrift_compiler_tests) \ No newline at end of file +add_test(NAME ThriftTests COMMAND thrift_compiler_tests) diff --git a/contrib/thrift.spec b/contrib/thrift.spec index cc3c33c8ea1..ffdfab2ab49 100644 --- a/contrib/thrift.spec +++ b/contrib/thrift.spec @@ -58,8 +58,8 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Thrift is a software framework for scalable cross-language services development. It combines a powerful software stack with a code generation engine to build services that work efficiently and seamlessly between C++, -Java, C#, Python, Ruby, Perl, PHP, Objective C/Cocoa, Smalltalk, Erlang, -Objective Caml, and Haskell. +Java, C#, Python, Ruby, Perl, PHP, Smalltalk, Erlang, OCaml, Haskell, and +other languages. %files %defattr(-,root,root) diff --git a/debian/copyright b/debian/copyright index 850643c9aa4..3e6fcf72122 100644 --- a/debian/copyright +++ b/debian/copyright @@ -28,7 +28,6 @@ the Thrift Software License (see doc/old-thrift-license.txt), and relicensed under the Apache 2.0 License: compiler/cpp/Makefile.am - compiler/cpp/src/generate/t_cocoa_generator.cc compiler/cpp/src/generate/t_cpp_generator.cc compiler/cpp/src/generate/t_csharp_generator.cc compiler/cpp/src/generate/t_erl_generator.cc diff --git a/doap.rdf b/doap.rdf index cb76facfaf5..50b3491d658 100755 --- a/doap.rdf +++ b/doap.rdf @@ -27,7 +27,7 @@ Apache Thrift - Apache Thrift software provides a framework for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages. + Apache Thrift software provides a framework for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages. Apache Thrift allows you to define data types and service interfaces in a simple definition file. Taking that file as input, the compiler generates code to be used to easily build RPC clients and servers that communicate seamlessly across programming languages. Instead of writing a load of boilerplate code to serialize and transport your objects and invoke remote methods, you can get right down to business. @@ -36,7 +36,6 @@ C C# C++ - Cocoa D Dart Delphi diff --git a/doc/specs/idl.md b/doc/specs/idl.md index bf22f5477f2..069f2fc3759 100644 --- a/doc/specs/idl.md +++ b/doc/specs/idl.md @@ -1,10 +1,11 @@ ## Thrift interface description language + +For Thrift version 1.0.0. + The Thrift interface definition language (IDL) allows for the definition of [Thrift Types](/docs/types). A Thrift IDL file is processed by the Thrift code generator to produce code for the various target languages to support the defined structs and services in the IDL file. ## Description -*Under construction* - Here is a description of the Thrift IDL. ## Document @@ -35,32 +36,9 @@ A C++ include adds a custom C++ include to the output of the C++ code generator A namespace declares which namespaces/package/module/etc. the type definitions in this file will be declared in for the target languages. The namespace scope indicates which language the namespace applies to; a scope of '*' indicates that the namespace applies to all target languages. - [5] Namespace ::= ( 'namespace' ( NamespaceScope Identifier ) | - ( 'smalltalk.category' STIdentifier ) | - ( 'smalltalk.prefix' Identifier ) ) | - ( 'php_namespace' Literal ) | - ( 'xsd_namespace' Literal ) - - [6] NamespaceScope ::= '*' | 'cpp' | 'java' | 'py' | 'perl' | 'rb' | 'cocoa' | 'csharp' - -N.B.: Smalltalk has two distinct types of namespace commands: - -- smalltalk.prefix: Prepended to generated classnames. - - Smalltalk does not have namespaces for classes, so prefixes - are used to avoid class-name collisions. - Often, the prefix is the author's initials, like "KB" or "JWS", - or an abbreviation of the package name, like "MC" for "Monticello". -- smalltalk.category: Determines the category for generated classes. - Any dots in the identifier will be replaced with hyphens when generating - the category name. - If not provided, defaults to "Generated-" + the program name. - Methods will not be categorized beyond "as yet uncategorized". - - Smalltalk allows filing both classes and methods within classes into named - groups. These named groups of methods are called categories. - -N.B.: The `php_namespace` directive will be deprecated at some point in the future in favor of the scoped syntax, but the scoped syntax is not yet supported for PHP. + [5] Namespace ::= ( 'namespace' ( NamespaceScope Identifier ) ) -N.B.: The `xsd_namespace` directive has some purpose internal to Facebook but serves no purpose in Thrift itself. Use of this feature is strongly discouraged + [6] NamespaceScope ::= '*' | 'c_glib' | 'cpp' | 'csharp' | 'delphi' | 'go' | 'java' | 'js' | 'lua' | 'netcore' | 'perl' | 'php' | 'py' | 'py.twisted' | 'rb' | 'st' | 'xsd' ## Definition diff --git a/lib/Makefile.am b/lib/Makefile.am index b6ce20e3ca0..0c69019409e 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -110,7 +110,6 @@ endif # so they will end up in our release tarballs. EXTRA_DIST = \ as3 \ - cocoa \ d \ dart \ delphi \ diff --git a/lib/cocoa/README.md b/lib/cocoa/README.md deleted file mode 100644 index bbe3c934fba..00000000000 --- a/lib/cocoa/README.md +++ /dev/null @@ -1,21 +0,0 @@ -Thrift Cocoa Software Library - -License -======= - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. diff --git a/lib/cocoa/coding_standards.md b/lib/cocoa/coding_standards.md deleted file mode 100644 index fa0390bb577..00000000000 --- a/lib/cocoa/coding_standards.md +++ /dev/null @@ -1 +0,0 @@ -Please follow [General Coding Standards](/doc/coding_standards.md) diff --git a/lib/cocoa/src/TApplicationError.h b/lib/cocoa/src/TApplicationError.h deleted file mode 100644 index 079881a60a9..00000000000 --- a/lib/cocoa/src/TApplicationError.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TProtocol.h" - -extern NSString *TApplicationErrorDomain; - -typedef NS_ENUM (int, TApplicationError) { - TApplicationErrorUnknown = 0, - TApplicationErrorUnknownMethod = 1, - TApplicationErrorInvalidMessageType = 2, - TApplicationErrorWrongMethodName = 3, - TApplicationErrorBadSequenceId = 4, - TApplicationErrorMissingResult = 5, - TApplicationErrorInternalError = 6, - TApplicationErrorProtocolError = 7, - TApplicationErrorInvalidTransform = 8, - TApplicationErrorInvalidProtocol = 9, - TApplicationErrorUnsupportedClientType = 10, -}; - - -extern NSString *TApplicationErrorNameKey; -extern NSString *TApplicationErrorReasonKey; -extern NSString *TApplicationErrorMethodKey; - - -@interface NSError (TApplicationError) - -@property (readonly, copy) NSString *name; -@property (readonly, copy) NSString *reason; - -+(instancetype) errorWithType:(TApplicationError)type reason:(NSString *)reason; - -+(instancetype) read:(id)protocol; - --(BOOL) write:(id)outProtocol error:(NSError *__autoreleasing *)error; - -@end diff --git a/lib/cocoa/src/TApplicationError.m b/lib/cocoa/src/TApplicationError.m deleted file mode 100644 index 080bc0b7c70..00000000000 --- a/lib/cocoa/src/TApplicationError.m +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TApplicationError.h" -#import "TProtocolUtil.h" - - -NSString *TApplicationErrorDomain = @"TApplicationErrorDomain"; - - -NSString *TApplicationErrorNameKey = @"name"; -NSString *TApplicationErrorReasonKey = @"reason"; -NSString *TApplicationErrorMethodKey = @"method"; - - -@implementation NSError (TApplicationError) - --(NSString *) reason -{ - return self.userInfo[TApplicationErrorReasonKey]; -} - --(NSString *) name -{ - return self.userInfo[TApplicationErrorNameKey]; -} - -+(instancetype) errorWithType:(TApplicationError)type reason:(NSString *)reason -{ - NSString *name; - switch (type) { - case TApplicationErrorUnknownMethod: - name = @"Unknown Method"; - break; - - case TApplicationErrorInvalidMessageType: - name = @"Invalid Message Type"; - break; - - case TApplicationErrorWrongMethodName: - name = @"Wrong Method Name"; - break; - - case TApplicationErrorBadSequenceId: - name = @"Bad Sequence ID"; - break; - - case TApplicationErrorMissingResult: - name = @"Missing Result"; - break; - - case TApplicationErrorInternalError: - name = @"Internal Error"; - break; - - case TApplicationErrorProtocolError: - name = @"Protocol Error"; - break; - - case TApplicationErrorInvalidTransform: - name = @"Invalid Transform"; - break; - - case TApplicationErrorInvalidProtocol: - name = @"Invalid Protocol"; - break; - - case TApplicationErrorUnsupportedClientType: - name = @"Unsupported Client Type"; - break; - - default: - name = @"Unknown"; - break; - } - - NSDictionary *userInfo; - if (reason) { - userInfo = @{TApplicationErrorNameKey:name, - TApplicationErrorReasonKey:reason}; - } - else { - userInfo = @{TApplicationErrorNameKey:name}; - } - - return [NSError errorWithDomain:TApplicationErrorDomain - code:type - userInfo:userInfo]; -} - - -+(instancetype) read:(id)protocol -{ - NSString *reason = nil; - SInt32 type = TApplicationErrorUnknown; - SInt32 fieldType; - SInt32 fieldID; - - NSError *error; - if (![protocol readStructBeginReturningName:NULL error:&error]) { - return error; - } - - while (true) { - - if (![protocol readFieldBeginReturningName:NULL - type:&fieldType - fieldID:&fieldID - error:&error]) - { - return error; - } - - if (fieldType == TTypeSTOP) { - break; - } - - switch (fieldID) { - case 1: - if (fieldType == TTypeSTRING) { - if (![protocol readString:&reason error:&error]) { - return error; - } - } - else { - if (![TProtocolUtil skipType:fieldType onProtocol:protocol error:&error]) { - return error; - } - } - break; - - case 2: - if (fieldType == TTypeI32) { - if (![protocol readI32:&type error:&error]) { - return error; - } - } - else { - if (![TProtocolUtil skipType:fieldType onProtocol:protocol error:&error]) { - return error; - } - } - break; - - default: - if (![TProtocolUtil skipType:fieldType onProtocol:protocol error:&error]) { - return error; - } - break; - } - if (![protocol readFieldEnd:&error]) { - return error; - } - - } - - if (![protocol readStructEnd:&error]) { - return error; - } - - return [NSError errorWithType:type reason:reason]; -} - - --(BOOL) write:(id)protocol error:(NSError *__autoreleasing *)error -{ - if (![protocol writeStructBeginWithName:@"TApplicationException" error:error]) { - return NO; - } - - if (self.localizedDescription != nil) { - if (![protocol writeFieldBeginWithName:@"message" - type:TTypeSTRING - fieldID:1 error:error]) - { - return NO; - } - - if (![protocol writeString:self.localizedDescription error:error]) { - return NO; - } - - if (![protocol writeFieldEnd:error]) { - return NO; - } - } - - if (![protocol writeFieldBeginWithName:@"type" - type:TTypeI32 - fieldID:2 - error:error]) - { - return NO; - } - - if (![protocol writeI32:(SInt32)self.code error:error]) { - return NO; - } - - if (![protocol writeFieldEnd:error]) { - return NO; - } - - if (![protocol writeFieldStop:error]) { - return NO; - } - - if (![protocol writeStructEnd:error]) { - return NO; - } - - return YES; -} - -@end diff --git a/lib/cocoa/src/TBaseClient.h b/lib/cocoa/src/TBaseClient.h deleted file mode 100644 index 0f73aa027ca..00000000000 --- a/lib/cocoa/src/TBaseClient.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TProtocol.h" -#import "TApplicationError.h" - -@interface TBaseClient : NSObject - --(NSError *) checkIncomingMessageException:(id)protocol; - -@end diff --git a/lib/cocoa/src/TBaseClient.m b/lib/cocoa/src/TBaseClient.m deleted file mode 100644 index 249cae06666..00000000000 --- a/lib/cocoa/src/TBaseClient.m +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TBaseClient.h" -#import "TApplicationError.h" - - -@interface TBaseClient () -@end - - -@implementation TBaseClient - --(NSError *) checkIncomingMessageException:(id)inProtocol -{ - NSError *thriftError; - - SInt32 msgType = 0; - if (![inProtocol readMessageBeginReturningName:nil type:&msgType sequenceID:NULL error:&thriftError]) { - return thriftError; - } - - if (msgType == TMessageTypeEXCEPTION) { - - thriftError = [NSError read:inProtocol]; - - [inProtocol readMessageEnd:NULL]; - - return thriftError; - } - - return nil; -} - -@end diff --git a/lib/cocoa/src/TBinary.swift b/lib/cocoa/src/TBinary.swift deleted file mode 100644 index c8a366075a7..00000000000 --- a/lib/cocoa/src/TBinary.swift +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Foundation - - -public struct TBinary : TSerializable { - - public static var thriftType : TType { return .STRING } - - private var storage : NSData - - public init() { - self.storage = NSData() - } - - public init(contentsOfFile file: String, options: NSDataReadingOptions = []) throws { - self.storage = try NSData(contentsOfFile: file, options: options) - } - - public init(contentsOfURL URL: NSURL, options: NSDataReadingOptions = []) throws { - self.storage = try NSData(contentsOfURL: URL, options: options) - } - - public init?(base64EncodedData base64Data: NSData, options: NSDataBase64DecodingOptions = []) { - guard let storage = NSData(base64EncodedData: base64Data, options: options) else { - return nil - } - self.storage = storage - } - - public init(data: NSData) { - self.storage = data - } - - public var length : Int { - return storage.length - } - - public var hashValue : Int { - return storage.hashValue - } - - public var bytes : UnsafePointer { - return storage.bytes - } - - public func getBytes(buffer: UnsafeMutablePointer, length: Int) { - storage.getBytes(buffer, length: length) - } - - public func getBytes(buffer: UnsafeMutablePointer, range: Range) { - storage.getBytes(buffer, range: NSRange(range)) - } - - public func subBinaryWithRange(range: Range) -> TBinary { - return TBinary(data: storage.subdataWithRange(NSRange(range))) - } - - public func writeToFile(path: String, options: NSDataWritingOptions = []) throws { - try storage.writeToFile(path, options: options) - } - - public func writeToURL(url: NSURL, options: NSDataWritingOptions = []) throws { - try storage.writeToURL(url, options: options) - } - - public func rangeOfData(dataToFind data: NSData, options: NSDataSearchOptions, range: Range) -> Range? { - return storage.rangeOfData(data, options: options, range: NSRange(range)).toRange() - } - - public func enumerateByteRangesUsingBlock(block: (UnsafePointer, Range, inout Bool) -> Void) { - storage.enumerateByteRangesUsingBlock { bytes, range, stop in - var stopTmp = Bool(stop.memory) - block(bytes, range.toRange()!, &stopTmp) - stop.memory = ObjCBool(stopTmp) - } - } - - public static func readValueFromProtocol(proto: TProtocol) throws -> TBinary { - var data : NSData? - try proto.readBinary(&data) - return TBinary(data: data!) - } - - public static func writeValue(value: TBinary, toProtocol proto: TProtocol) throws { - try proto.writeBinary(value.storage) - } - -} - -extension TBinary : CustomStringConvertible, CustomDebugStringConvertible { - - public var description : String { - return storage.description - } - - public var debugDescription : String { - return storage.debugDescription - } - -} - -public func ==(lhs: TBinary, rhs: TBinary) -> Bool { - return lhs.storage == rhs.storage -} diff --git a/lib/cocoa/src/TEnum.swift b/lib/cocoa/src/TEnum.swift deleted file mode 100644 index 562a53ade9e..00000000000 --- a/lib/cocoa/src/TEnum.swift +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Foundation - - -public protocol TEnum : TSerializable { - -} - -public extension TEnum { - - public static var thriftType : TType { return TType.I32 } - -} diff --git a/lib/cocoa/src/TError.h b/lib/cocoa/src/TError.h deleted file mode 100644 index abb72c7ad1f..00000000000 --- a/lib/cocoa/src/TError.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import - - -extern NSString *TErrorDomain; diff --git a/lib/cocoa/src/TError.m b/lib/cocoa/src/TError.m deleted file mode 100644 index df7f92dc590..00000000000 --- a/lib/cocoa/src/TError.m +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TError.h" - - -NSString *TErrorDomain = @"TErrorDomain"; diff --git a/lib/cocoa/src/TList.swift b/lib/cocoa/src/TList.swift deleted file mode 100644 index 005bd817d03..00000000000 --- a/lib/cocoa/src/TList.swift +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Foundation - - - -public struct TList : MutableCollectionType, Hashable, ArrayLiteralConvertible, TSerializable { - - public static var thriftType : TType { return .LIST } - - typealias Storage = Array - - public typealias Index = Storage.Index - - private var storage = Storage() - - public var startIndex : Index { - return storage.startIndex - } - - public var endIndex : Index { - return storage.endIndex - } - - public subscript (position: Index) -> Element { - get { - return storage[position] - } - set { - storage[position] = newValue - } - } - - public var hashValue : Int { - let prime = 31 - var result = 1 - for element in storage { - result = prime * result + element.hashValue - } - return result - } - - public init(arrayLiteral elements: Element...) { - self.storage = Storage(storage) - } - - public init() { - self.storage = Storage() - } - - public mutating func append(newElement: Element) { - self.storage.append(newElement) - } - - public mutating func appendContentsOf(newstorage: C) { - self.storage.appendContentsOf(newstorage) - } - - public mutating func insert(newElement: Element, atIndex index: Int) { - self.storage.insert(newElement, atIndex: index) - } - - public mutating func insertContentsOf(newElements: C, at index: Int) { - self.storage.insertContentsOf(newElements, at: index) - } - - public mutating func removeAll(keepCapacity keepCapacity: Bool = true) { - self.storage.removeAll(keepCapacity: keepCapacity) - } - - public mutating func removeAtIndex(index: Index) { - self.storage.removeAtIndex(index) - } - - public mutating func removeFirst(n: Int = 0) { - self.storage.removeFirst(n) - } - - public mutating func removeLast() -> Element { - return self.storage.removeLast() - } - - public mutating func removeRange(subRange: Range) { - self.storage.removeRange(subRange) - } - - public mutating func reserveCapacity(minimumCapacity: Int) { - self.storage.reserveCapacity(minimumCapacity) - } - - public static func readValueFromProtocol(proto: TProtocol) throws -> TList { - let (elementType, size) = try proto.readListBegin() - if elementType != Element.thriftType { - throw NSError( - domain: TProtocolErrorDomain, - code: Int(TProtocolError.InvalidData.rawValue), - userInfo: [TProtocolErrorExtendedErrorKey: NSNumber(int: TProtocolExtendedError.UnexpectedType.rawValue)]) - } - var list = TList() - for _ in 0..(lhs: TList, rhs: TList) -> Bool { - return lhs.storage == rhs.storage -} diff --git a/lib/cocoa/src/TMap.swift b/lib/cocoa/src/TMap.swift deleted file mode 100644 index e96e7474e3a..00000000000 --- a/lib/cocoa/src/TMap.swift +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Foundation - - -public struct TMap : CollectionType, DictionaryLiteralConvertible, TSerializable { - - public static var thriftType : TType { return .MAP } - - typealias Storage = Dictionary - - public typealias Index = Storage.Index - - public typealias Element = Storage.Element - - private var storage : Storage - - public var startIndex : Index { - return storage.startIndex - } - - public var endIndex: Index { - return storage.endIndex - } - - public var keys: LazyMapCollection<[Key : Value], Key> { - return storage.keys - } - - public var values: LazyMapCollection<[Key : Value], Value> { - return storage.values - } - - public init() { - storage = Storage() - } - - public init(dictionaryLiteral elements: (Key, Value)...) { - storage = Storage() - for (key, value) in elements { - storage[key] = value - } - } - - public init(minimumCapacity: Int) { - storage = Storage(minimumCapacity: minimumCapacity) - } - - public subscript (position: Index) -> Element { - get { - return storage[position] - } - } - - public func indexForKey(key: Key) -> Index? { - return storage.indexForKey(key) - } - - public subscript (key: Key) -> Value? { - get { - return storage[key] - } - set { - storage[key] = newValue - } - } - - public mutating func updateValue(value: Value, forKey key: Key) -> Value? { - return updateValue(value, forKey: key) - } - - public mutating func removeAtIndex(index: DictionaryIndex) -> (Key, Value) { - return removeAtIndex(index) - } - - public mutating func removeValueForKey(key: Key) -> Value? { - return storage.removeValueForKey(key) - } - - public mutating func removeAll(keepCapacity keepCapacity: Bool = false) { - storage.removeAll(keepCapacity: keepCapacity) - } - - public var hashValue : Int { - let prime = 31 - var result = 1 - for (key, value) in storage { - result = prime * result + key.hashValue - result = prime * result + value.hashValue - } - return result - } - - public static func readValueFromProtocol(proto: TProtocol) throws -> TMap { - let (keyType, valueType, size) = try proto.readMapBegin() - if keyType != Key.thriftType || valueType != Value.thriftType { - throw NSError( - domain: TProtocolErrorDomain, - code: Int(TProtocolError.InvalidData.rawValue), - userInfo: [TProtocolErrorExtendedErrorKey: NSNumber(int: TProtocolExtendedError.UnexpectedType.rawValue)]) - } - var map = TMap() - for _ in 0..(lhs: TMap, rhs: TMap) -> Bool { - if lhs.count != rhs.count { - return false - } - return lhs.storage == rhs.storage -} diff --git a/lib/cocoa/src/TProcessor.h b/lib/cocoa/src/TProcessor.h deleted file mode 100644 index 20c72e2e1a4..00000000000 --- a/lib/cocoa/src/TProcessor.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TProtocol.h" - -NS_ASSUME_NONNULL_BEGIN - - -@protocol TProcessor - --(BOOL) processOnInputProtocol:(id )inProtocol - outputProtocol:(id )outProtocol - error:(NSError **)error; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/TProcessorFactory.h b/lib/cocoa/src/TProcessorFactory.h deleted file mode 100644 index 85020a59346..00000000000 --- a/lib/cocoa/src/TProcessorFactory.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TProcessor.h" - -NS_ASSUME_NONNULL_BEGIN - - -@protocol TProcessorFactory - --(id) processorForTransport:(id)transport; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/TProtocol.swift b/lib/cocoa/src/TProtocol.swift deleted file mode 100644 index 1775849790a..00000000000 --- a/lib/cocoa/src/TProtocol.swift +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Foundation - - -public extension TProtocol { - - public func readMessageBegin() throws -> (String, TMessageType, Int) { - - var name : NSString? - var type : Int32 = -1 - var sequenceID : Int32 = -1 - - try readMessageBeginReturningName(&name, type: &type, sequenceID: &sequenceID) - - return (name as String!, TMessageType(rawValue: type)!, Int(sequenceID)) - } - - public func writeMessageBeginWithName(name: String, type: TMessageType, sequenceID: Int) throws { - try writeMessageBeginWithName(name, type: type.rawValue, sequenceID: Int32(sequenceID)) - } - - public func readStructBegin() throws -> (String?) { - - var name : NSString? = nil - - try readStructBeginReturningName(&name) - - return (name as String?) - } - - public func readFieldBegin() throws -> (String?, TType, Int) { - - var name : NSString? = nil - var type : Int32 = -1 - var fieldID : Int32 = -1 - - try readFieldBeginReturningName(&name, type: &type, fieldID: &fieldID) - - return (name as String?, TType(rawValue: type)!, Int(fieldID)) - } - - public func writeFieldBeginWithName(name: String, type: TType, fieldID: Int) throws { - try writeFieldBeginWithName(name, type: type.rawValue, fieldID: Int32(fieldID)) - } - - public func readMapBegin() throws -> (TType, TType, Int32) { - - var keyType : Int32 = -1 - var valueType : Int32 = -1 - var size : Int32 = 0 - - try readMapBeginReturningKeyType(&keyType, valueType: &valueType, size: &size) - - return (TType(rawValue: keyType)!, TType(rawValue: valueType)!, size) - } - - public func writeMapBeginWithKeyType(keyType: TType, valueType: TType, size: Int) throws { - try writeMapBeginWithKeyType(keyType.rawValue, valueType: valueType.rawValue, size: Int32(size)) - } - - public func readSetBegin() throws -> (TType, Int32) { - - var elementType : Int32 = -1 - var size : Int32 = 0 - - try readSetBeginReturningElementType(&elementType, size: &size) - - return (TType(rawValue: elementType)!, size) - } - - public func writeSetBeginWithElementType(elementType: TType, size: Int) throws { - try writeSetBeginWithElementType(elementType.rawValue, size: Int32(size)) - } - - public func readListBegin() throws -> (TType, Int32) { - - var elementType : Int32 = -1 - var size : Int32 = 0 - - try readListBeginReturningElementType(&elementType, size: &size) - - return (TType(rawValue: elementType)!, size) - } - - public func writeListBeginWithElementType(elementType: TType, size: Int) throws { - try writeListBeginWithElementType(elementType.rawValue, size: Int32(size)) - } - - public func writeFieldValue(value: T, name: String, type: TType, id: Int32) throws { - try writeFieldBeginWithName(name, type: type.rawValue, fieldID: id) - try writeValue(value) - try writeFieldEnd() - } - - public func readValue() throws -> T { - return try T.readValueFromProtocol(self) - } - - public func writeValue(value: T) throws { - try T.writeValue(value, toProtocol: self) - } - - public func readResultMessageBegin() throws { - - let (_, type, _) = try readMessageBegin(); - - if type == .EXCEPTION { - let x = try readException() - throw x - } - - return - } - - public func validateValue(value: Any?, named name: String) throws { - - if value == nil { - throw NSError( - domain: TProtocolErrorDomain, - code: Int(TProtocolError.Unknown.rawValue), - userInfo: [TProtocolErrorFieldNameKey: name]) - } - - } - - public func readException() throws -> ErrorType { - - var reason : String? - var type = TApplicationError.Unknown - - try readStructBegin() - - fields: while (true) { - - let (_, fieldType, fieldID) = try readFieldBegin() - - switch (fieldID, fieldType) { - case (_, .STOP): - break fields - - case (1, .STRING): - reason = try readValue() as String - - case (2, .I32): - let typeVal = try readValue() as Int32 - if let tmp = TApplicationError(rawValue: typeVal) { - type = tmp - } - - case let (_, unknownType): - try skipType(unknownType) - } - - try readFieldEnd() - } - - try readStructEnd() - - return NSError(type:type, reason:reason ?? "") - } - - public func writeExceptionForMessageName(name: String, sequenceID: Int, ex: NSError) throws { - try writeMessageBeginWithName(name, type: .EXCEPTION, sequenceID: sequenceID) - try ex.write(self) - try writeMessageEnd() - } - - public func skipType(type: TType) throws { - try TProtocolUtil.skipType(type.rawValue, onProtocol: self) - } - -} diff --git a/lib/cocoa/src/TSerializable.swift b/lib/cocoa/src/TSerializable.swift deleted file mode 100644 index 3fdfd41b070..00000000000 --- a/lib/cocoa/src/TSerializable.swift +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Foundation - - -public protocol TSerializable : Hashable { - - static var thriftType : TType { get } - - init() - - static func readValueFromProtocol(proto: TProtocol) throws -> Self - - static func writeValue(value: Self, toProtocol proto: TProtocol) throws - -} - - - -infix operator ?== {} - -public func ?==(lhs: T?, rhs: T?) -> Bool { - if let l = lhs, r = rhs { - return l == r - } - return lhs == rhs -} - -public func ?==(lhs: T, rhs: T) -> Bool { - return lhs == rhs -} - - - -extension Bool : TSerializable { - - public static let thriftType = TType.BOOL - - public static func readValueFromProtocol(proto: TProtocol) throws -> Bool { - var value : ObjCBool = false - try proto.readBool(&value) - return value.boolValue - } - - public static func writeValue(value: Bool, toProtocol proto: TProtocol) throws { - try proto.writeBool(value) - } - -} - -extension Int8 : TSerializable { - - public static let thriftType = TType.BYTE - - public static func readValueFromProtocol(proto: TProtocol) throws -> Int8 { - var value = UInt8() - try proto.readByte(&value) - return Int8(value) - } - - public static func writeValue(value: Int8, toProtocol proto: TProtocol) throws { - try proto.writeByte(UInt8(value)) - } - -} - -extension Int16 : TSerializable { - - public static let thriftType = TType.I16 - - public static func readValueFromProtocol(proto: TProtocol) throws -> Int16 { - var value = Int16() - try proto.readI16(&value) - return value - } - - public static func writeValue(value: Int16, toProtocol proto: TProtocol) throws { - try proto.writeI16(value) - } - -} - -extension Int : TSerializable { - - public static let thriftType = TType.I32 - - public static func readValueFromProtocol(proto: TProtocol) throws -> Int { - var value = Int32() - try proto.readI32(&value) - return Int(value) - } - - public static func writeValue(value: Int, toProtocol proto: TProtocol) throws { - try proto.writeI32(Int32(value)) - } - -} - -extension Int32 : TSerializable { - - public static let thriftType = TType.I32 - - public static func readValueFromProtocol(proto: TProtocol) throws -> Int32 { - var value = Int32() - try proto.readI32(&value) - return value - } - - public static func writeValue(value: Int32, toProtocol proto: TProtocol) throws { - try proto.writeI32(value) - } - -} - -extension Int64 : TSerializable { - - public static let thriftType = TType.I64 - - public static func readValueFromProtocol(proto: TProtocol) throws -> Int64 { - var value = Int64() - try proto.readI64(&value) - return value - } - - public static func writeValue(value: Int64, toProtocol proto: TProtocol) throws { - try proto.writeI64(value) - } - -} - -extension Double : TSerializable { - - public static let thriftType = TType.DOUBLE - - public static func readValueFromProtocol(proto: TProtocol) throws -> Double { - var value = Double() - try proto.readDouble(&value) - return value - } - - public static func writeValue(value: Double, toProtocol proto: TProtocol) throws { - try proto.writeDouble(value) - } - -} - -extension String : TSerializable { - - public static let thriftType = TType.STRING - - public static func readValueFromProtocol(proto: TProtocol) throws -> String { - var value : NSString? - try proto.readString(&value) - return value as! String - } - - public static func writeValue(value: String, toProtocol proto: TProtocol) throws { - try proto.writeString(value) - } - -} diff --git a/lib/cocoa/src/TSet.swift b/lib/cocoa/src/TSet.swift deleted file mode 100644 index 85833e5c078..00000000000 --- a/lib/cocoa/src/TSet.swift +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Foundation - - -public struct TSet : CollectionType, ArrayLiteralConvertible, TSerializable { - - public static var thriftType : TType { return .SET } - - public typealias Index = Storage.Index - - typealias Storage = Set - - private var storage : Storage - - public init() { - storage = Storage() - } - - public init(arrayLiteral elements: Element...) { - storage = Storage(elements) - } - - public init(_ sequence: S) { - storage = Storage(sequence) - } - - public var startIndex : Index { return storage.startIndex } - - public var endIndex : Index { return storage.endIndex } - - public mutating func insert(member: Element) { - return storage.insert(member) - } - - public mutating func remove(element: Element) -> Element? { - return storage.remove(element) - } - - public mutating func removeAll(keepCapacity keepCapacity: Bool = false) { - return storage.removeAll(keepCapacity: keepCapacity) - } - - public mutating func removeAtIndex(index: SetIndex) -> Element { - return storage.removeAtIndex(index) - } - - public subscript (position: SetIndex) -> Element { - return storage[position] - } - - public func union(other: TSet) -> TSet { - return TSet(storage.union(other)) - } - - public func intersect(other: TSet) -> TSet { - return TSet(storage.intersect(other)) - } - - public func exclusiveOr(other: TSet) -> TSet { - return TSet(storage.exclusiveOr(other)) - } - - public func subtract(other: TSet) -> TSet { - return TSet(storage.subtract(other)) - } - - public mutating func intersectInPlace(other: TSet) { - storage.intersectInPlace(other) - } - - public mutating func exclusiveOrInPlace(other: TSet) { - storage.exclusiveOrInPlace(other) - } - - public mutating func subtractInPlace(other: TSet) { - storage.subtractInPlace(other) - } - - public func isSubsetOf(other: TSet) -> Bool { - return storage.isSubsetOf(other) - } - - public func isDisjointWith(other: TSet) -> Bool { - return storage.isDisjointWith(other) - } - - public func isSupersetOf(other: TSet) -> Bool { - return storage.isSupersetOf(other) - } - - public var isEmpty: Bool { return storage.isEmpty } - - public var hashValue : Int { - let prime = 31 - var result = 1 - for element in storage { - result = prime * result + element.hashValue - } - return result - } - - public static func readValueFromProtocol(proto: TProtocol) throws -> TSet { - let (elementType, size) = try proto.readSetBegin() - if elementType != Element.thriftType { - throw NSError( - domain: TProtocolErrorDomain, - code: Int(TProtocolError.InvalidData.rawValue), - userInfo: [TProtocolErrorExtendedErrorKey: NSNumber(int: elementType.rawValue)]) - } - var set = TSet() - for _ in 0..(lhs: TSet, rhs: TSet) -> Bool { - return lhs.storage == rhs.storage -} diff --git a/lib/cocoa/src/TSharedProcessorFactory.h b/lib/cocoa/src/TSharedProcessorFactory.h deleted file mode 100644 index c75fad1ee47..00000000000 --- a/lib/cocoa/src/TSharedProcessorFactory.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TProcessorFactory.h" - - -@interface TSharedProcessorFactory : NSObject - --(id) initWithSharedProcessor:(id)sharedProcessor; - -@end diff --git a/lib/cocoa/src/TSharedProcessorFactory.m b/lib/cocoa/src/TSharedProcessorFactory.m deleted file mode 100644 index 3d55f479319..00000000000 --- a/lib/cocoa/src/TSharedProcessorFactory.m +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -#import "TSharedProcessorFactory.h" - - -@interface TSharedProcessorFactory () - -@property(strong, nonatomic) id sharedProcessor; - -@end - - -@implementation TSharedProcessorFactory - - --(id) initWithSharedProcessor:(id)sharedProcessor -{ - self = [super init]; - if (self) { - _sharedProcessor = sharedProcessor; - } - - return self; -} - --(id) processorForTransport:(id)transport -{ - return _sharedProcessor; -} - -@end diff --git a/lib/cocoa/src/TStruct.swift b/lib/cocoa/src/TStruct.swift deleted file mode 100644 index cea72e752b7..00000000000 --- a/lib/cocoa/src/TStruct.swift +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import Foundation - - -public protocol TStruct : TSerializable { -} - - -public extension TStruct { - - public static var thriftType : TType { return TType.STRUCT } - -} diff --git a/lib/cocoa/src/Thrift.h b/lib/cocoa/src/Thrift.h deleted file mode 100644 index d01826dbe65..00000000000 --- a/lib/cocoa/src/Thrift.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#define ThriftVersion @"1.0.0" diff --git a/lib/cocoa/src/protocol/TBase.h b/lib/cocoa/src/protocol/TBase.h deleted file mode 100644 index 9935d506842..00000000000 --- a/lib/cocoa/src/protocol/TBase.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import - -#import "TProtocol.h" - -@protocol TBase - -/** - * De-serialize object from the given input protocol - * - * @param inProtocol protocol used for reading - */ --(BOOL) read:(id )inProtocol error:(NSError **)error; - -/** - * Serialize object to the given protocol - * - * @param outProtocol output protocol used for writing - */ --(BOOL) write:(id )outProtocol error:(NSError **)error; - - -/** - * Validate required fields - */ --(BOOL) validate:(NSError *__autoreleasing *)__thriftError; - -@end diff --git a/lib/cocoa/src/protocol/TBinaryProtocol.h b/lib/cocoa/src/protocol/TBinaryProtocol.h deleted file mode 100644 index bb90fadcb1b..00000000000 --- a/lib/cocoa/src/protocol/TBinaryProtocol.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TProtocol.h" -#import "TTransport.h" -#import "TProtocolFactory.h" - -NS_ASSUME_NONNULL_BEGIN - - -@interface TBinaryProtocol : NSObject - -@property (assign, nonatomic) UInt32 messageSizeLimit; - --(id) initWithTransport:(id )transport; - --(id) initWithTransport:(id )transport - strictRead:(BOOL)strictRead - strictWrite:(BOOL)strictWrite; - -@end; - - -@interface TBinaryProtocolFactory : NSObject - -+(TBinaryProtocolFactory *) sharedFactory; - --(TBinaryProtocol *) newProtocolOnTransport:(id )transport; - -@end - - -NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/lib/cocoa/src/protocol/TBinaryProtocol.m b/lib/cocoa/src/protocol/TBinaryProtocol.m deleted file mode 100644 index 1f9e57ac8be..00000000000 --- a/lib/cocoa/src/protocol/TBinaryProtocol.m +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TBinaryProtocol.h" -#import "TProtocolError.h" - - -static SInt32 VERSION_1 = 0x80010000; -static SInt32 VERSION_MASK = 0xffff0000; - - -static TBinaryProtocolFactory *gSharedFactory = nil; - - -@implementation TBinaryProtocolFactory - -+(TBinaryProtocolFactory *) sharedFactory -{ - if (gSharedFactory == nil) { - gSharedFactory = [[TBinaryProtocolFactory alloc] init]; - } - - return gSharedFactory; -} - --(NSString *) protocolName -{ - return @"binary"; -} - --(TBinaryProtocol *) newProtocolOnTransport:(id )transport -{ - return [[TBinaryProtocol alloc] initWithTransport:transport]; -} - -@end - - -@interface TBinaryProtocol () - -@property(strong, nonatomic) id transport; - -@property(assign, nonatomic) BOOL strictRead; -@property(assign, nonatomic) BOOL strictWrite; - -@property(strong, nonatomic) NSString *currentMessageName; -@property(strong, nonatomic) NSString *currentFieldName; - -@end - - -@implementation TBinaryProtocol - --(id) initWithTransport:(id )aTransport -{ - return [self initWithTransport:aTransport strictRead:NO strictWrite:YES]; -} - --(id) initWithTransport:(id )transport - strictRead:(BOOL)strictRead - strictWrite:(BOOL)strictWrite -{ - self = [super init]; - if (self) { - _transport = transport; - _strictRead = strictRead; - _strictWrite = strictWrite; - } - return self; -} - --(id ) transport -{ - return _transport; -} - --(NSString *) readStringBody:(int)size error:(NSError **)error -{ - NSMutableData *data = [NSMutableData dataWithLength:size]; - if (!data) { - PROTOCOL_ERROR(nil, Unknown, @"Unable to allocate %d bytes", size); - } - - if (![_transport readAll:data.mutableBytes offset:0 length:size error:error]) { - PROTOCOL_TRANSPORT_ERROR(nil, error, @"Transport read failed"); - } - - return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; -} - - --(BOOL) readMessageBeginReturningName:(NSString **)name - type:(SInt32 *)type - sequenceID:(SInt32 *)sequenceID - error:(NSError *__autoreleasing *)error -{ - SInt32 size; - if (![self readI32:&size error:error]) { - return NO; - } - ; - - if (size < 0) { - int version = size & VERSION_MASK; - if (version != VERSION_1) { - PROTOCOL_ERROR(NO, BadVersion, @"Bad message version"); - } - if (type != NULL) { - *type = size & 0x00FF; - } - NSString *messageName; - if (![self readString:&messageName error:error]) { - return NO; - } - if (name != nil) { - *name = messageName; - } - } - else { - - if (_strictRead) { - PROTOCOL_ERROR(NO, InvalidData, @"Missing message version, old client?"); - } - - if (_messageSizeLimit > 0 && size > _messageSizeLimit) { - PROTOCOL_ERROR(NO, SizeLimit, @"Message exceeeds size limit of %d", (int)size); - } - - NSString *messageName = [self readStringBody:size error:error]; - if (!messageName) { - return NO; - } - - if (name != NULL) { - *name = messageName; - } - - UInt8 messageType; - if (![self readByte:&messageType error:error]) { - return NO; - } - - if (type != NULL) { - *type = messageType; - } - } - - SInt32 seqID; - if (![self readI32:&seqID error:error]) { - return NO; - } - if (sequenceID != NULL) { - *sequenceID = seqID; - } - - return YES; -} - - --(BOOL) readMessageEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - - --(BOOL) readStructBeginReturningName:(NSString *__autoreleasing *)name error:(NSError *__autoreleasing *)error -{ - return YES; -} - - --(BOOL) readStructEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - - --(BOOL) readFieldBeginReturningName:(NSString *__autoreleasing *)name - type:(SInt32 *)fieldType - fieldID:(SInt32 *)fieldID - error:(NSError *__autoreleasing *)error -{ - if (name != nil) { - *name = nil; - } - - UInt8 ft; - if (![self readByte:&ft error:error]) { - return NO; - } - if (fieldType != NULL) { - *fieldType = ft; - } - if (ft != TTypeSTOP) { - SInt16 fid; - if (![self readI16:&fid error:error]) { - return NO; - } - if (fieldID != NULL) { - *fieldID = fid; - } - } - return YES; -} - - --(BOOL) readFieldEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - - --(BOOL) readString:(NSString *__autoreleasing *)value error:(NSError *__autoreleasing *)error -{ - SInt32 size; - if (![self readI32:&size error:error]) { - return NO; - } - - NSString *string = [self readStringBody:size error:error]; - if (!string) { - return NO; - } - - *value = string; - - return YES; -} - - --(BOOL) readBool:(BOOL *)value error:(NSError *__autoreleasing *)error -{ - UInt8 byte; - if (![self readByte:&byte error:error]) { - return NO; - } - - *value = byte == 1; - - return YES; -} - - --(BOOL) readByte:(UInt8 *)value error:(NSError *__autoreleasing *)error -{ - UInt8 buff[1]; - if (![_transport readAll:buff offset:0 length:1 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed"); - } - - *value = buff[0]; - - return YES; -} - - --(BOOL) readI16:(SInt16 *)value error:(NSError *__autoreleasing *)error -{ - UInt8 buff[2]; - if (![_transport readAll:buff offset:0 length:2 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed"); - } - - *value = - ((SInt16)(buff[0] & 0xff) << 8) | - ((SInt16)(buff[1] & 0xff)); - - return YES; -} - - --(BOOL) readI32:(SInt32 *)value error:(NSError *__autoreleasing *)error -{ - UInt8 i32rd[4]; - if (![_transport readAll:i32rd offset:0 length:4 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed"); - } - - *value = - ((i32rd[0] & 0xff) << 24) | - ((i32rd[1] & 0xff) << 16) | - ((i32rd[2] & 0xff) << 8) | - ((i32rd[3] & 0xff)); - - return YES; -} - - --(BOOL) readI64:(SInt64 *)value error:(NSError *__autoreleasing *)error -{ - UInt8 buff[8]; - if (![_transport readAll:buff offset:0 length:8 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed"); - } - - *value = - ((SInt64)(buff[0] & 0xff) << 56) | - ((SInt64)(buff[1] & 0xff) << 48) | - ((SInt64)(buff[2] & 0xff) << 40) | - ((SInt64)(buff[3] & 0xff) << 32) | - ((SInt64)(buff[4] & 0xff) << 24) | - ((SInt64)(buff[5] & 0xff) << 16) | - ((SInt64)(buff[6] & 0xff) << 8) | - ((SInt64)(buff[7] & 0xff)); - - return YES; -} - - --(BOOL) readDouble:(double *)value error:(NSError *__autoreleasing *)error -{ - // FIXME - will this get us into trouble on PowerPC? - return [self readI64:(SInt64 *)value error:error]; -} - - --(BOOL) readBinary:(NSData *__autoreleasing *)value error:(NSError *__autoreleasing *)error -{ - SInt32 size; - if (![self readI32:&size error:error]) { - return NO; - } - - NSMutableData *data = [NSMutableData dataWithLength:size]; - if (!data) { - PROTOCOL_ERROR(NO, Unknown, @"Unable to allocate %d bytes", (int)size); - } - - if (![_transport readAll:data.mutableBytes offset:0 length:size error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed"); - } - - *value = data; - - return YES; -} - - --(BOOL) readMapBeginReturningKeyType:(SInt32 *)keyType - valueType:(SInt32 *)valueType - size:(SInt32 *)size - error:(NSError *__autoreleasing *)error -{ - UInt8 kt; - if (![self readByte:&kt error:error]) { - return NO; - } - - UInt8 vt; - if (![self readByte:&vt error:error]) { - return NO; - } - - SInt32 s; - if (![self readI32:&s error:error]) { - return NO; - } - - if (keyType != NULL) { - *keyType = kt; - } - - if (valueType != NULL) { - *valueType = vt; - } - - if (size != NULL) { - *size = s; - } - - return YES; -} - - --(BOOL) readMapEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - - --(BOOL) readSetBeginReturningElementType:(SInt32 *)elementType - size:(SInt32 *)size - error:(NSError *__autoreleasing *)error -{ - UInt8 et; - if (![self readByte:&et error:error]) { - return NO; - } - - SInt32 s; - if (![self readI32:&s error:error]) { - return NO; - } - - if (elementType != NULL) { - *elementType = et; - } - - if (size != NULL) { - *size = s; - } - - return YES; -} - - --(BOOL) readSetEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - - --(BOOL) readListBeginReturningElementType:(SInt32 *)elementType - size:(SInt32 *)size - error:(NSError *__autoreleasing *)error -{ - UInt8 et; - if (![self readByte:&et error:error]) { - return NO; - } - - SInt32 s; - if (![self readI32:&s error:error]) { - return NO; - } - - if (elementType != NULL) { - *elementType = et; - } - - if (size != NULL) { - *size = s; - } - - return YES; -} - - --(BOOL) readListEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - - - --(BOOL) writeMessageBeginWithName:(NSString *)name - type:(SInt32)messageType - sequenceID:(SInt32)sequenceID - error:(NSError *__autoreleasing *)error -{ - if (_strictWrite) { - - int version = VERSION_1 | messageType; - - if (![self writeI32:version error:error]) { - return NO; - } - - if (![self writeString:name error:error]) { - return NO; - } - - if (![self writeI32:sequenceID error:error]) { - return NO; - } - } - else { - - if (![self writeString:name error:error]) { - return NO; - } - - if (![self writeByte:messageType error:error]) { - return NO; - } - - if (![self writeI32:sequenceID error:error]) { - return NO; - } - } - - _currentMessageName = name; - - return YES; -} - - --(BOOL) writeMessageEnd:(NSError *__autoreleasing *)error -{ - _currentMessageName = nil; - return YES; -} - - --(BOOL) writeStructBeginWithName:(NSString *)name - error:(NSError *__autoreleasing *)error -{ - return YES; -} - - --(BOOL) writeStructEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - - --(BOOL) writeFieldBeginWithName:(NSString *)name - type:(SInt32)fieldType - fieldID:(SInt32)fieldID - error:(NSError *__autoreleasing *)error -{ - if (![self writeByte:fieldType error:error]) { - return NO; - } - - if (![self writeI16:fieldID error:error]) { - return NO; - } - - return YES; -} - - --(BOOL) writeBool:(BOOL)value error:(NSError *__autoreleasing *)error -{ - return [self writeByte:(value ? 1 : 0) error:error]; -} - - --(BOOL) writeByte:(UInt8)value error:(NSError *__autoreleasing *)error -{ - if (![_transport write:&value offset:0 length:1 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed"); - } - return YES; -} - - --(BOOL) writeI16:(short)value error:(NSError *__autoreleasing *)error -{ - UInt8 buff[2]; - buff[0] = 0xff & (value >> 8); - buff[1] = 0xff & value; - - if (![_transport write:buff offset:0 length:2 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed"); - } - - return YES; -} - - --(BOOL) writeI32:(SInt32)value error:(NSError *__autoreleasing *)error -{ - UInt8 buff[4]; - buff[0] = 0xFF & (value >> 24); - buff[1] = 0xFF & (value >> 16); - buff[2] = 0xFF & (value >> 8); - buff[3] = 0xFF & value; - - if (![_transport write:buff offset:0 length:4 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed"); - } - - return YES; -} - - --(BOOL) writeI64:(SInt64)value error:(NSError *__autoreleasing *)error -{ - UInt8 buff[8]; - buff[0] = 0xFF & (value >> 56); - buff[1] = 0xFF & (value >> 48); - buff[2] = 0xFF & (value >> 40); - buff[3] = 0xFF & (value >> 32); - buff[4] = 0xFF & (value >> 24); - buff[5] = 0xFF & (value >> 16); - buff[6] = 0xFF & (value >> 8); - buff[7] = 0xFF & value; - - if (![_transport write:buff offset:0 length:8 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed"); - } - - return YES; -} - - --(BOOL) writeDouble:(double)value error:(NSError *__autoreleasing *)error -{ - // FIXME - will this get us in trouble on PowerPC? - if (![self writeI64:*(SInt64 *)&value error:error]) { - return NO; - } - - return YES; -} - - --(BOOL) writeString:(NSString *)value error:(NSError *__autoreleasing *)error -{ - if (value != nil) { - - const char *utf8Bytes = [value UTF8String]; - - SInt32 length = (SInt32)strlen(utf8Bytes); - if (![self writeI32:length error:error]) { - return NO; - } - - if (![_transport write:(UInt8 *)utf8Bytes offset:0 length:(int)length error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed"); - } - - } - else { - - // instead of crashing when we get null, let's write out a zero - // length string - if (![self writeI32:0 error:error]) { - return NO; - } - - } - - return YES; -} - - --(BOOL) writeBinary:(NSData *)data error:(NSError *__autoreleasing *)error -{ - if (![self writeI32:(SInt32)data.length error:error]) { - return NO; - } - - if (![_transport write:data.bytes offset:0 length:(UInt32)data.length error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed"); - } - - return YES; -} - - --(BOOL) writeFieldStop:(NSError *__autoreleasing *)error -{ - if (![self writeByte:TTypeSTOP error:error]) { - return NO; - } - - return YES; -} - - --(BOOL) writeFieldEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - - --(BOOL) writeMapBeginWithKeyType:(SInt32)keyType - valueType:(SInt32)valueType - size:(SInt32)size - error:(NSError *__autoreleasing *)error -{ - if (![self writeByte:keyType error:error]) { - return NO; - } - if (![self writeByte:valueType error:error]) { - return NO; - } - if (![self writeI32:(int)size error:error]) { - return NO; - } - return YES; -} - - --(BOOL) writeMapEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - - --(BOOL) writeSetBeginWithElementType:(SInt32)elementType - size:(SInt32)size - error:(NSError *__autoreleasing *)error -{ - if (![self writeByte:elementType error:error]) { - return NO; - } - if (![self writeI32:size error:error]) { - return NO; - } - return YES; -} - - --(BOOL) writeSetEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - - --(BOOL) writeListBeginWithElementType:(SInt32)elementType - size:(SInt32)size - error:(NSError *__autoreleasing *)error -{ - if (![self writeByte:elementType error:error]) { - return NO; - } - if (![self writeI32:size error:error]) { - return NO; - } - return YES; -} - - --(BOOL) writeListEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - -@end diff --git a/lib/cocoa/src/protocol/TCompactProtocol.h b/lib/cocoa/src/protocol/TCompactProtocol.h deleted file mode 100644 index 3f6accc5aa9..00000000000 --- a/lib/cocoa/src/protocol/TCompactProtocol.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TProtocol.h" -#import "TTransport.h" -#import "TProtocolFactory.h" - -NS_ASSUME_NONNULL_BEGIN - - -@interface TCompactProtocol : NSObject - --(id) initWithTransport:(id )transport; - -@end - -@interface TCompactProtocolFactory : NSObject - -+(TCompactProtocolFactory *) sharedFactory; - --(TCompactProtocol *) newProtocolOnTransport:(id )transport; - -@end - - -NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/lib/cocoa/src/protocol/TCompactProtocol.m b/lib/cocoa/src/protocol/TCompactProtocol.m deleted file mode 100644 index 9b0ebb2a78a..00000000000 --- a/lib/cocoa/src/protocol/TCompactProtocol.m +++ /dev/null @@ -1,983 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TCompactProtocol.h" -#import "TProtocolError.h" - -static const UInt8 COMPACT_PROTOCOL_ID = 0x82; -static const UInt8 COMPACT_VERSION = 1; -static const UInt8 COMPACT_VERSION_MASK = 0x1F; // 0001 1111 -static const UInt8 COMPACT_TYPE_MASK = 0xE0; // 1110 0000 -static const UInt8 COMPACT_TYPE_BITS = 0x07; // 0000 0111 -static const int COMPACT_TYPE_SHIFT_AMOUNT = 5; - -enum { - TCType_STOP = 0x00, - TCType_BOOLEAN_TRUE = 0x01, - TCType_BOOLEAN_FALSE = 0x02, - TCType_BYTE = 0x03, - TCType_I16 = 0x04, - TCType_I32 = 0x05, - TCType_I64 = 0x06, - TCType_DOUBLE = 0x07, - TCType_BINARY = 0x08, - TCType_LIST = 0x09, - TCType_SET = 0x0A, - TCType_MAP = 0x0B, - TCType_STRUCT = 0x0C, -}; - -@implementation TCompactProtocolFactory - -+(TCompactProtocolFactory *) sharedFactory -{ - static TCompactProtocolFactory *gSharedFactory = nil; - if (gSharedFactory == nil) { - gSharedFactory = [[TCompactProtocolFactory alloc] init]; - } - - return gSharedFactory; -} - --(NSString *) protocolName -{ - return @"compact"; -} - --(TCompactProtocol *) newProtocolOnTransport:(id )transport -{ - return [[TCompactProtocol alloc] initWithTransport:transport]; -} - -@end - - -@interface TCompactProtocol () - -@property(strong, nonatomic) id transport; - -@property(strong, nonatomic) NSMutableArray *lastField; -@property(assign, nonatomic) short lastFieldId; - -@property(strong, nonatomic) NSString *boolFieldName; -@property(strong, nonatomic) NSNumber *boolFieldType; -@property(strong, nonatomic) NSNumber *boolFieldId; -@property(strong, nonatomic) NSNumber *booleanValue; - -@property(strong, nonatomic) NSString *currentMessageName; - -@end - - -@implementation TCompactProtocol - --(id) init -{ - self = [super init]; - - if (self != nil) { - _lastField = [[NSMutableArray alloc] init]; - } - - return self; -} - --(id) initWithTransport:(id )aTransport -{ - self = [self init]; - - if (self != nil) { - _transport = aTransport; - } - - return self; -} - --(id ) transport -{ - return _transport; -} - --(BOOL) writeByteDirect:(UInt8)n error:(NSError *__autoreleasing *)error -{ - if (![_transport write:(UInt8 *)&n offset:0 length:1 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed"); - } - return YES; -} - --(BOOL) writeVarint32:(UInt32)n error:(NSError *__autoreleasing *)error -{ - UInt8 i32buf[5] = {0}; - UInt32 idx = 0; - - while (true) { - if ((n & ~0x7F) == 0) { - i32buf[idx++] = (UInt8)n; - break; - } - else { - i32buf[idx++] = (UInt8)((n & 0x7F) | 0x80); - n >>= 7; - } - } - - if (![_transport write:i32buf offset:0 length:idx error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed"); - } - - return YES; -} - --(BOOL) writeMessageBeginWithName:(NSString *)name - type:(SInt32)messageType - sequenceID:(SInt32)sequenceID - error:(NSError *__autoreleasing *)error -{ - if (![self writeByteDirect:COMPACT_PROTOCOL_ID error:error]) { - return NO; - } - if (![self writeByteDirect:(UInt8)((COMPACT_VERSION & COMPACT_VERSION_MASK) | - ((((UInt32)messageType) << COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_MASK)) error:error]) - { - return NO; - } - if (![self writeVarint32:(UInt32)sequenceID error:error]) { - return NO; - } - if (![self writeString:name error:error]) { - return NO; - } - - _currentMessageName = name; - - return YES; -} - --(BOOL) writeStructBeginWithName:(NSString *)name error:(NSError *__autoreleasing *)error -{ - [_lastField addObject:@(_lastFieldId)]; - _lastFieldId = 0; - return YES; -} - --(BOOL) writeStructEnd:(NSError *__autoreleasing *)error -{ - _lastFieldId = [_lastField.lastObject shortValue]; - [_lastField removeLastObject]; - return YES; -} - --(BOOL) writeFieldBeginWithName:(NSString *)name - type:(SInt32)fieldType - fieldID:(SInt32)fieldID - error:(NSError *__autoreleasing *)error -{ - if (fieldType == TTypeBOOL) { - _boolFieldName = [name copy]; - _boolFieldType = @(fieldType); - _boolFieldId = @(fieldID); - return YES; - } - else { - return [self writeFieldBeginInternalWithName:name - type:fieldType - fieldID:fieldID - typeOverride:0xFF - error:error]; - } -} - --(BOOL) writeFieldBeginInternalWithName:(NSString *)name - type:(SInt32)fieldType - fieldID:(SInt32)fieldID - typeOverride:(UInt8)typeOverride - error:(NSError *__autoreleasing *)error -{ - UInt8 typeToWrite = typeOverride == 0xFF ? [self compactTypeForTType:fieldType] : typeOverride; - - // check if we can use delta encoding for the field id - if (fieldID > _lastFieldId && fieldID - _lastFieldId <= 15) { - // Write them together - if (![self writeByteDirect:(fieldID - _lastFieldId) << 4 | typeToWrite error:error]) { - return NO; - } - } - else { - // Write them separate - if (![self writeByteDirect:typeToWrite error:error]) { - return NO; - } - if (![self writeI16:fieldID error:error]) { - return NO; - } - } - - _lastFieldId = fieldID; - - return YES; -} - --(BOOL) writeFieldStop:(NSError *__autoreleasing *)error -{ - return [self writeByteDirect:TCType_STOP error:error]; -} - --(BOOL) writeMapBeginWithKeyType:(SInt32)keyType - valueType:(SInt32)valueType - size:(SInt32)size - error:(NSError *__autoreleasing *)error -{ - if (size == 0) { - if (![self writeByteDirect:0 error:error]) { - return NO; - } - } - else { - if (![self writeVarint32:(UInt32)size error:error]) { - return NO; - } - if (![self writeByteDirect:[self compactTypeForTType:keyType] << 4 | [self compactTypeForTType:valueType] error:error]) { - return NO; - } - } - return YES; -} - --(BOOL) writeListBeginWithElementType:(SInt32)elementType - size:(SInt32)size - error:(NSError *__autoreleasing *)error -{ - return [self writeCollectionBeginWithElementType:elementType size:size error:error]; -} - --(BOOL) writeSetBeginWithElementType:(SInt32)elementType - size:(SInt32)size - error:(NSError *__autoreleasing *)error -{ - return [self writeCollectionBeginWithElementType:elementType size:size error:error]; -} - --(BOOL) writeBool:(BOOL)b error:(NSError *__autoreleasing *)error -{ - BOOL result; - if (_boolFieldId != nil && _boolFieldName != nil && _boolFieldType != nil) { - // we haven't written the field header yet - result = [self writeFieldBeginInternalWithName:_boolFieldName - type:_boolFieldType.intValue - fieldID:_boolFieldId.intValue - typeOverride:b ? TCType_BOOLEAN_TRUE : TCType_BOOLEAN_FALSE - error:error]; - _boolFieldId = nil; - _boolFieldName = nil; - _boolFieldType = nil; - } - else { - // we're not part of a field, so just Write the value. - result = [self writeByteDirect:b ? TCType_BOOLEAN_TRUE : TCType_BOOLEAN_FALSE error:error]; - } - return result; -} - --(BOOL) writeByte:(UInt8)value error:(NSError *__autoreleasing *)error -{ - return [self writeByteDirect:value error:error]; -} - --(BOOL) writeI16:(SInt16)value error:(NSError *__autoreleasing *)error -{ - return [self writeVarint32:[self i32ToZigZag:value] error:error]; -} - --(BOOL) writeI32:(SInt32)value error:(NSError *__autoreleasing *)error -{ - return [self writeVarint32:[self i32ToZigZag:value] error:error]; -} - --(BOOL) writeI64:(SInt64)value error:(NSError *__autoreleasing *)error -{ - return [self writeVarint64:[self i64ToZigZag:value] error:error]; -} - --(BOOL) writeDouble:(double)value error:(NSError *__autoreleasing *)error -{ - // Safe bit-casting double->uint64 - - UInt64 bits = 0; - memcpy(&bits, &value, 8); - - bits = OSSwapHostToLittleInt64(bits); - - if (![_transport write:(UInt8 *)&bits offset:0 length:8 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed"); - } - - return YES; -} - --(BOOL) writeString:(NSString *)value error:(NSError *__autoreleasing *)error -{ - return [self writeBinary:[value dataUsingEncoding:NSUTF8StringEncoding] error:error]; -} - --(BOOL) writeBinary:(NSData *)data error:(NSError *__autoreleasing *)error -{ - if (![self writeVarint32:(UInt32)data.length error:error]) { - return NO; - } - if (![_transport write:data.bytes offset:0 length:(UInt32)data.length error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed"); - } - return YES; -} - --(BOOL) writeMessageEnd:(NSError *__autoreleasing *)error -{ - _currentMessageName = nil; - return YES; -} - --(BOOL) writeMapEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - --(BOOL) writeListEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - --(BOOL) writeSetEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - --(BOOL) writeFieldEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - --(BOOL) writeCollectionBeginWithElementType:(SInt32)elementType - size:(SInt32)size - error:(NSError *__autoreleasing *)error -{ - UInt8 ctypeElement = [self compactTypeForTType:elementType]; - - if (size <= 14) { - if (![self writeByteDirect:size << 4 | ctypeElement error:error]) { - return NO; - } - } - else { - if (![self writeByteDirect:0xf0 | ctypeElement error:error]) { - return NO; - } - if (![self writeVarint32:(UInt32)size error:error]) { - return NO; - } - } - return YES; -} - --(BOOL) writeVarint64:(UInt64)n error:(NSError *__autoreleasing *)error -{ - UInt8 varint64out[10] = {0}; - int idx = 0; - - while (true) { - if ((n & ~0x7FL) == 0) { - varint64out[idx++] = (UInt8)n; - break; - } - else { - varint64out[idx++] = (UInt8)((n & 0x7F) | 0x80); - n >>= 7; - } - } - - if (![_transport write:varint64out offset:0 length:idx error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport write failed"); - } - - return YES; -} - --(UInt32) i32ToZigZag:(SInt32)n -{ - /* - ZigZag encoding maps signed integers to unsigned integers so that - numbers with a small absolute value (for instance, -1) have - a small varint encoded value too. It does this in a way that - "zig-zags" back and forth through the positive and negative integers, - so that -1 is encoded as 1, 1 is encoded as 2, -2 is encoded as 3, and so - on - */ - return (UInt32)(n << 1) ^ (UInt32)(n >> 31); -} - --(UInt64) i64ToZigZag:(SInt64)n -{ - return (UInt64)(n << 1) ^ (UInt64)(n >> 63); -} - --(BOOL) readMessageBeginReturningName:(NSString **)pname - type:(SInt32 *)ptype - sequenceID:(SInt32 *)psequenceID - error:(NSError *__autoreleasing *)error -{ - UInt8 protocolId; - if (![self readByte:&protocolId error:error]) { - return NO; - } - - if (protocolId != COMPACT_PROTOCOL_ID) { - if (error) { - *error = [NSError errorWithDomain:TProtocolErrorDomain - code:TProtocolErrorUnknown - userInfo:@{TProtocolErrorExtendedErrorKey: @(TProtocolExtendedErrorMismatchedProtocol), - TProtocolErrorExpectedIdKey: @(COMPACT_PROTOCOL_ID)}]; - } - return NO; - } - - UInt8 versionAndType; - if (![self readByte:&versionAndType error:error]) { - return NO; - } - - UInt8 version = versionAndType & COMPACT_VERSION_MASK; - if (version != COMPACT_VERSION) { - if (error) { - *error = [NSError errorWithDomain:TProtocolErrorDomain - code:TProtocolErrorBadVersion - userInfo:@{TProtocolErrorExpectedVersionKey: @(COMPACT_VERSION)}]; - } - return NO; - } - - int type = (versionAndType >> COMPACT_TYPE_SHIFT_AMOUNT) & COMPACT_TYPE_BITS; - UInt32 sequenceID; - if (![self readVarint32:&sequenceID error:error]) { - return NO; - } - NSString *name; - if (![self readString:&name error:error]) { - return NO; - } - - if (ptype != NULL) { - *ptype = type; - } - if (psequenceID != NULL) { - *psequenceID = sequenceID; - } - if (pname != NULL) { - *pname = name; - } - return YES; -} - --(BOOL) readStructBeginReturningName:(NSString **)pname error:(NSError *__autoreleasing *)error -{ - [_lastField addObject:@(_lastFieldId)]; - _lastFieldId = 0; - - if (pname != NULL) { - *pname = @""; - } - - return YES; -} - --(BOOL) readStructEnd:(NSError *__autoreleasing *)error -{ - _lastFieldId = [_lastField.lastObject shortValue]; - [_lastField removeLastObject]; - return YES; -} - --(BOOL) readFieldBeginReturningName:(NSString **)pname - type:(SInt32 *)pfieldType - fieldID:(SInt32 *)pfieldID - error:(NSError *__autoreleasing *)error -{ - UInt8 byte; - if (![self readByte:&byte error:error]) { - return NO; - } - - UInt8 type = byte & 0x0f; - - // if it's a stop, then we can return immediately, as the struct is over. - if (type == TCType_STOP) { - if (pname != NULL) { - *pname = @""; - } - if (pfieldType != NULL) { - *pfieldType = TTypeSTOP; - } - if (pfieldID != NULL) { - *pfieldID = 0; - } - return YES; - } - - short fieldId = 0; - - // mask off the 4 MSB of the type header. it could contain a field id delta. - short modifier = (byte & 0xf0) >> 4; - if (modifier == 0) { - // not a delta. look ahead for the zigzag varint field id. - if (![self readI16:&fieldId error:error]) { - return NO; - } - } - else { - // has a delta. add the delta to the last Read field id. - fieldId = _lastFieldId + modifier; - } - - UInt8 fieldType; - if (![self ttype:&fieldType forCompactType:type error:error]) { - return NO; - } - - if (pname != NULL) { - *pname = @""; - } - if (pfieldType != NULL) { - *pfieldType = fieldType; - } - if (pfieldID != NULL) { - *pfieldID = fieldId; - } - - // if this happens to be a boolean field, the value is encoded in the type - if (type == TCType_BOOLEAN_TRUE || - type == TCType_BOOLEAN_FALSE) - { - // save the boolean value in a special instance variable. - _booleanValue = [NSNumber numberWithBool:type == TCType_BOOLEAN_TRUE]; - } - - // push the new field onto the field stack so we can keep the deltas going. - _lastFieldId = fieldId; - - return YES; -} - --(BOOL) readMapBeginReturningKeyType:(SInt32 *)pkeyType - valueType:(SInt32 *)pvalueType - size:(SInt32 *)psize - error:(NSError *__autoreleasing *)error -{ - UInt8 keyAndValueType = 0; - UInt32 size; - if (![self readVarint32:&size error:error]) { - return NO; - } - if (size != 0) { - if (![self readByte:&keyAndValueType error:error]) { - return NO; - } - } - - UInt8 keyType; - if (![self ttype:&keyType forCompactType:keyAndValueType >> 4 error:error]) { - return NO; - } - - UInt8 valueType; - if (![self ttype:&valueType forCompactType:keyAndValueType & 0xf error:error]) { - return NO; - } - - if (pkeyType != NULL) { - *pkeyType = keyType; - } - if (pvalueType != NULL) { - *pvalueType = valueType; - } - if (psize != NULL) { - *psize = size; - } - - return YES; -} - --(BOOL) readListBeginReturningElementType:(SInt32 *)pelementType - size:(SInt32 *)psize - error:(NSError *__autoreleasing *)error -{ - UInt8 sizeAndType; - if (![self readByte:&sizeAndType error:error]) { - return NO; - } - - UInt32 size = (sizeAndType >> 4) & 0x0f; - if (size == 15) { - if (![self readVarint32:&size error:error]) { - return NO; - } - } - - UInt8 elementType; - if (![self ttype:&elementType forCompactType:sizeAndType & 0x0f error:error]) { - return NO; - } - - if (pelementType != NULL) { - *pelementType = elementType; - } - if (psize != NULL) { - *psize = size; - } - - return YES; -} - --(BOOL) readSetBeginReturningElementType:(SInt32 *)pelementType - size:(SInt32 *)psize - error:(NSError *__autoreleasing *)error -{ - return [self readListBeginReturningElementType:pelementType size:psize error:error]; -} - --(BOOL) readBool:(BOOL *)value error:(NSError *__autoreleasing *)error -{ - if (_booleanValue != nil) { - - BOOL result = _booleanValue.boolValue; - _booleanValue = nil; - - *value = result; - } - else { - - UInt8 result; - if (![self readByte:&result error:error]) { - return NO; - } - - *value = result == TCType_BOOLEAN_TRUE; - } - - return YES; -} - --(BOOL) readByte:(UInt8 *)value error:(NSError *__autoreleasing *)error -{ - if (![_transport readAll:value offset:0 length:1 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed"); - } - return YES; -} - --(BOOL) readI16:(SInt16 *)value error:(NSError *__autoreleasing *)error -{ - UInt32 v; - if (![self readVarint32:&v error:error]) { - return NO; - } - - if (value) { - *value = (SInt16)[self zigZagToi32:v]; - } - - return YES; -} - --(BOOL) readI32:(SInt32 *)value error:(NSError *__autoreleasing *)error -{ - UInt32 v; - if (![self readVarint32:&v error:error]) { - return NO; - } - - if (value) { - *value = [self zigZagToi32:v]; - } - - return YES; -} - --(BOOL) readI64:(SInt64 *)value error:(NSError *__autoreleasing *)error -{ - UInt64 v; - if (![self readVarint64:&v error:error]) { - return NO; - } - - if (value) { - *value = [self zigZagToi64:v]; - } - - return YES; -} - --(BOOL) readDouble:(double *)value error:(NSError *__autoreleasing *)error -{ - UInt64 bits; - if (![_transport readAll:(UInt8 *)&bits offset:0 length:8 error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed"); - } - - bits = OSSwapLittleToHostInt64(bits); - - if (value) { - memcpy(value, &bits, sizeof(bits)); - } - - return YES; -} - --(BOOL) readString:(NSString *__autoreleasing *)value error:(NSError *__autoreleasing *)error -{ - UInt32 length; - if (![self readVarint32:&length error:error]) { - return NO; - } - - NSString *result; - - if (length != 0) { - - NSData *data; - if (![self readBinaryOfLength:length data:&data error:error]) { - return NO; - } - - result = [[NSString alloc] initWithData:data - encoding:NSUTF8StringEncoding]; - } - else { - result = @""; - } - - if (value) { - *value = result; - } - - return YES; -} - --(BOOL) readBinary:(NSData *__autoreleasing *)value error:(NSError *__autoreleasing *)error -{ - UInt32 length; - if (![self readVarint32:&length error:error]) { - return NO; - } - - return [self readBinaryOfLength:length data:value error:error]; -} - --(BOOL) readBinaryOfLength:(UInt32)length data:(NSData *__autoreleasing *)value error:(NSError *__autoreleasing *)error -{ - NSData *result; - - if (length != 0) { - - NSMutableData *buf = [NSMutableData dataWithLength:length]; - if (![_transport readAll:buf.mutableBytes offset:0 length:length error:error]) { - PROTOCOL_TRANSPORT_ERROR(NO, error, @"Transport read failed"); - } - - result = buf; - } - else { - - result = [NSData data]; - - } - - if (value) { - *value = result; - } - - return YES; -} - --(BOOL) readMessageEnd:(NSError *__autoreleasing *)error -{ - return YES; -} --(BOOL) readFieldEnd:(NSError *__autoreleasing *)error -{ - return YES; -} --(BOOL) readMapEnd:(NSError *__autoreleasing *)error -{ - return YES; -} --(BOOL) readListEnd:(NSError *__autoreleasing *)error -{ - return YES; -} --(BOOL) readSetEnd:(NSError *__autoreleasing *)error -{ - return YES; -} - --(BOOL) readVarint32:(UInt32 *)value error:(NSError *__autoreleasing *)error -{ - UInt32 result = 0; - int shift = 0; - - while (true) { - - UInt8 byte; - if (![self readByte:&byte error:error]) { - return NO; - } - - result |= (UInt32)(byte & 0x7f) << shift; - if (!(byte & 0x80)) { - break; - } - - shift += 7; - } - - if (value) { - *value = result; - } - - return YES; -} - --(BOOL) readVarint64:(UInt64 *)value error:(NSError *__autoreleasing *)error -{ - int shift = 0; - UInt64 result = 0; - - while (true) { - - UInt8 byte; - if (![self readByte:&byte error:error]) { - return NO; - } - - result |= (UInt64)(byte & 0x7f) << shift; - if (!(byte & 0x80)) { - break; - } - - shift += 7; - } - - if (value) { - *value = result; - } - - return YES; -} - --(SInt32) zigZagToi32:(UInt32)n -{ - return (SInt32)(n >> 1) ^ (-(SInt32)(n & 1)); -} - --(SInt64) zigZagToi64:(UInt64)n -{ - return (SInt64)(n >> 1) ^ (-(SInt64)(n & 1)); -} - --(BOOL) ttype:(UInt8 *)ttype forCompactType:(UInt8)ctype error:(NSError *__autoreleasing *)error -{ - switch (ctype & 0x0f) { - case TCType_STOP: - *ttype = TTypeSTOP; - return YES; - - case TCType_BOOLEAN_FALSE: - case TCType_BOOLEAN_TRUE: - *ttype = TTypeBOOL; - return YES; - - case TCType_BYTE: - *ttype = TTypeBYTE; - return YES; - - case TCType_I16: - *ttype = TTypeI16; - return YES; - - case TCType_I32: - *ttype = TTypeI32; - return YES; - - case TCType_I64: - *ttype = TTypeI64; - return YES; - - case TCType_DOUBLE: - *ttype = TTypeDOUBLE; - return YES; - - case TCType_BINARY: - *ttype = TTypeSTRING; - return YES; - - case TCType_LIST: - *ttype = TTypeLIST; - return YES; - - case TCType_SET: - *ttype = TTypeSET; - return YES; - - case TCType_MAP: - *ttype = TTypeMAP; - return YES; - - case TCType_STRUCT: - *ttype = TTypeSTRUCT; - return YES; - - default: - if (error) { - *error = [NSError errorWithDomain:TProtocolErrorDomain - code:TProtocolErrorUnknown - userInfo:@{TProtocolErrorTypeKey: @((UInt8)(ctype & 0x0F))}]; - } - return NO; - } -} - --(UInt8) compactTypeForTType:(UInt8)ttype -{ - static UInt8 ttypeToCompactType[] = { - [TTypeSTOP] = TCType_STOP, - [TTypeBOOL] = TCType_BOOLEAN_FALSE, - [TTypeBYTE] = TCType_BYTE, - [TTypeDOUBLE] = TCType_DOUBLE, - [TTypeI16] = TCType_I16, - [TTypeI32] = TCType_I32, - [TTypeI64] = TCType_I64, - [TTypeSTRING] = TCType_BINARY, - [TTypeSTRUCT] = TCType_STRUCT, - [TTypeMAP] = TCType_MAP, - [TTypeSET] = TCType_SET, - [TTypeLIST] = TCType_LIST - }; - - return ttypeToCompactType[ttype]; -} - -@end diff --git a/lib/cocoa/src/protocol/TMultiplexedProtocol.h b/lib/cocoa/src/protocol/TMultiplexedProtocol.h deleted file mode 100644 index b8ce361f513..00000000000 --- a/lib/cocoa/src/protocol/TMultiplexedProtocol.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import - -#import "TProtocolDecorator.h" - -NS_ASSUME_NONNULL_BEGIN - - -extern NSString *TMultiplexedProtocolSeperator; - - -@interface TMultiplexedProtocol : TProtocolDecorator - --(id) initWithProtocol:(id )protocol - serviceName:(NSString *)name; - -@end - - -NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/lib/cocoa/src/protocol/TMultiplexedProtocol.m b/lib/cocoa/src/protocol/TMultiplexedProtocol.m deleted file mode 100644 index 5838c576b05..00000000000 --- a/lib/cocoa/src/protocol/TMultiplexedProtocol.m +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TMultiplexedProtocol.h" - -#import "TProtocol.h" - -NSString *TMultiplexedProtocolSeperator = @":"; - - -@interface TMultiplexedProtocol () - -@property(strong, nonatomic) NSString *serviceName; - -@end - - -@implementation TMultiplexedProtocol - --(id) initWithProtocol:(id )protocol - serviceName:(NSString *)name -{ - self = [super initWithProtocol:protocol]; - if (self) { - _serviceName = name; - } - return self; -} - --(BOOL) writeMessageBeginWithName:(NSString *)name - type:(SInt32)messageType - sequenceID:(SInt32)sequenceID - error:(NSError *__autoreleasing *)error -{ - switch (messageType) { - case TMessageTypeCALL: - case TMessageTypeONEWAY: { - NSMutableString *serviceFunction = [[NSMutableString alloc] initWithString:_serviceName]; - [serviceFunction appendString:TMultiplexedProtocolSeperator]; - [serviceFunction appendString:name]; - return [super writeMessageBeginWithName:serviceFunction type:messageType sequenceID:sequenceID error:error]; - } - break; - - default: - return [super writeMessageBeginWithName:name type:messageType sequenceID:sequenceID error:error]; - } -} - -@end diff --git a/lib/cocoa/src/protocol/TProtocol.h b/lib/cocoa/src/protocol/TProtocol.h deleted file mode 100644 index 841059f5102..00000000000 --- a/lib/cocoa/src/protocol/TProtocol.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import - -#import "TTransport.h" - - -NS_ASSUME_NONNULL_BEGIN - - -typedef NS_ENUM (int, TMessageType) { - TMessageTypeCALL = 1, - TMessageTypeREPLY = 2, - TMessageTypeEXCEPTION = 3, - TMessageTypeONEWAY = 4 -}; - -typedef NS_ENUM (int, TType) { - TTypeSTOP = 0, - TTypeVOID = 1, - TTypeBOOL = 2, - TTypeBYTE = 3, - TTypeDOUBLE = 4, - TTypeI16 = 6, - TTypeI32 = 8, - TTypeI64 = 10, - TTypeSTRING = 11, - TTypeSTRUCT = 12, - TTypeMAP = 13, - TTypeSET = 14, - TTypeLIST = 15 -}; - - -@protocol TProtocol - --(id ) transport; - --(BOOL) readMessageBeginReturningName:(NSString *__nullable __autoreleasing *__nullable)name - type:(nullable SInt32 *)type - sequenceID:(nullable SInt32 *)sequenceID - error:(NSError *__autoreleasing *)error; --(BOOL) readMessageEnd:(NSError *__autoreleasing *)error; - --(BOOL) readStructBeginReturningName:(NSString *__nullable __autoreleasing *__nullable)name - error:(NSError *__autoreleasing *)error; --(BOOL) readStructEnd:(NSError *__autoreleasing *)error; - --(BOOL) readFieldBeginReturningName:(NSString *__nullable __autoreleasing *__nullable)name - type:(SInt32 *)fieldType - fieldID:(nullable SInt32 *)fieldID - error:(NSError *__autoreleasing *)error; --(BOOL) readFieldEnd:(NSError *__autoreleasing *)error; - --(BOOL) readString:(NSString *__nonnull __autoreleasing *__nonnull)value error:(NSError **)error; - --(BOOL) readBool:(BOOL *)value error:(NSError *__autoreleasing *)error; - --(BOOL) readByte:(UInt8 *)value error:(NSError *__autoreleasing *)error; - --(BOOL) readI16:(SInt16 *)value error:(NSError *__autoreleasing *)error; - --(BOOL) readI32:(SInt32 *)value error:(NSError *__autoreleasing *)error; - --(BOOL) readI64:(SInt64 *)value error:(NSError *__autoreleasing *)error; - --(BOOL) readDouble:(double *)value error:(NSError *__autoreleasing *)error; - --(BOOL) readBinary:(NSData *__nonnull __autoreleasing *__nonnull)value error:(NSError **)error; - --(BOOL) readMapBeginReturningKeyType:(nullable SInt32 *)keyType - valueType:(nullable SInt32 *)valueType - size:(SInt32 *)size - error:(NSError *__autoreleasing *)error; --(BOOL) readMapEnd:(NSError *__autoreleasing *)error; - - --(BOOL) readSetBeginReturningElementType:(nullable SInt32 *)elementType - size:(SInt32 *)size - error:(NSError *__autoreleasing *)error; --(BOOL) readSetEnd:(NSError *__autoreleasing *)error; - - --(BOOL) readListBeginReturningElementType:(nullable SInt32 *)elementType - size:(SInt32 *)size - error:(NSError *__autoreleasing *)error; --(BOOL) readListEnd:(NSError *__autoreleasing *)error; - - --(BOOL) writeMessageBeginWithName:(NSString *)name - type:(SInt32)messageType - sequenceID:(SInt32)sequenceID - error:(NSError *__autoreleasing *)error; --(BOOL) writeMessageEnd:(NSError *__autoreleasing *)error; - --(BOOL) writeStructBeginWithName:(NSString *)name error:(NSError **)error; --(BOOL) writeStructEnd:(NSError *__autoreleasing *)error; - --(BOOL) writeFieldBeginWithName:(NSString *)name - type:(SInt32)fieldType - fieldID:(SInt32)fieldID - error:(NSError *__autoreleasing *)error; - --(BOOL) writeI32:(SInt32)value error:(NSError *__autoreleasing *)error; - --(BOOL) writeI64:(SInt64)value error:(NSError *__autoreleasing *)error; - --(BOOL) writeI16:(short)value error:(NSError *__autoreleasing *)error; - --(BOOL) writeByte:(UInt8)value error:(NSError *__autoreleasing *)error; - --(BOOL) writeString:(NSString *)value error:(NSError *__autoreleasing *)error; - --(BOOL) writeDouble:(double)value error:(NSError *__autoreleasing *)error; - --(BOOL) writeBool:(BOOL)value error:(NSError *__autoreleasing *)error; - --(BOOL) writeBinary:(NSData *)data error:(NSError *__autoreleasing *)error; - --(BOOL) writeFieldStop:(NSError *__autoreleasing *)error; - --(BOOL) writeFieldEnd:(NSError *__autoreleasing *)error; - --(BOOL) writeMapBeginWithKeyType:(SInt32)keyType - valueType:(SInt32)valueType - size:(SInt32)size - error:(NSError *__autoreleasing *)error; --(BOOL) writeMapEnd:(NSError *__autoreleasing *)error; - - --(BOOL) writeSetBeginWithElementType:(SInt32)elementType - size:(SInt32)size - error:(NSError *__autoreleasing *)error; --(BOOL) writeSetEnd:(NSError *__autoreleasing *)error; - - --(BOOL) writeListBeginWithElementType:(SInt32)elementType - size:(SInt32)size - error:(NSError *__autoreleasing *)error; - --(BOOL) writeListEnd:(NSError *__autoreleasing *)error; - - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/protocol/TProtocolDecorator.h b/lib/cocoa/src/protocol/TProtocolDecorator.h deleted file mode 100644 index 369b6a2335b..00000000000 --- a/lib/cocoa/src/protocol/TProtocolDecorator.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import - -#import "TProtocol.h" - -NS_ASSUME_NONNULL_BEGIN - - -@interface TProtocolDecorator : NSObject - --(id) initWithProtocol:(id )protocol; - -@end - - -NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/lib/cocoa/src/protocol/TProtocolDecorator.m b/lib/cocoa/src/protocol/TProtocolDecorator.m deleted file mode 100644 index 218f900c41e..00000000000 --- a/lib/cocoa/src/protocol/TProtocolDecorator.m +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TProtocolDecorator.h" - - -@interface TProtocolDecorator () - -@property(strong, nonatomic) id concreteProtocol; - -@end - - -@implementation TProtocolDecorator - --(id) initWithProtocol:(id )protocol -{ - self = [super init]; - if (self) { - _concreteProtocol = protocol; - } - return self; -} - --(id ) transport -{ - return [_concreteProtocol transport]; -} - --(BOOL) readMessageBeginReturningName:(NSString **)name - type:(SInt32 *)type - sequenceID:(SInt32 *)sequenceID - error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readMessageBeginReturningName:name - type:type - sequenceID:sequenceID - error:error]; -} - --(BOOL) readMessageEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readMessageEnd:error]; -} - --(BOOL) readStructBeginReturningName:(NSString **)name - error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readStructBeginReturningName:name error:error]; -} - --(BOOL) readStructEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readStructEnd:error]; -} - --(BOOL) readFieldBeginReturningName:(NSString **)name - type:(SInt32 *)fieldType - fieldID:(SInt32 *)fieldID - error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readFieldBeginReturningName:name - type:fieldType - fieldID:fieldID - error:error]; -} --(BOOL) readFieldEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readFieldEnd:error]; -} - --(BOOL) readString:(NSString *__autoreleasing *)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readString:value error:error]; -} - --(BOOL) readBool:(BOOL *)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readBool:value error:error]; -} - --(BOOL) readByte:(UInt8 *)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readByte:value error:error]; -} - --(BOOL) readI16:(SInt16 *)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readI16:value error:error]; -} - --(BOOL) readI32:(SInt32 *)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readI32:value error:error]; -} - --(BOOL) readI64:(SInt64 *)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readI64:value error:error]; -} - --(BOOL) readDouble:(double *)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readDouble:value error:error]; -} - --(BOOL) readBinary:(NSData *__autoreleasing *)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readBinary:value error:error]; -} - --(BOOL) readMapBeginReturningKeyType:(SInt32 *)keyType - valueType:(SInt32 *)valueType - size:(SInt32 *)size - error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readMapBeginReturningKeyType:keyType - valueType:valueType - size:size - error:error]; -} --(BOOL) readMapEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readMapEnd:error]; -} - - --(BOOL) readSetBeginReturningElementType:(SInt32 *)elementType - size:(SInt32 *)size - error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readSetBeginReturningElementType:elementType - size:size - error:error]; -} --(BOOL) readSetEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readSetEnd:error]; -} - --(BOOL) readListBeginReturningElementType:(SInt32 *)elementType - size:(SInt32 *)size - error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readListBeginReturningElementType:elementType - size:size - error:error]; -} --(BOOL) readListEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol readListEnd:error]; -} - --(BOOL) writeMessageBeginWithName:(NSString *)name - type:(SInt32)messageType - sequenceID:(SInt32)sequenceID - error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeMessageBeginWithName:name - type:messageType - sequenceID:sequenceID - error:error]; -} --(BOOL) writeMessageEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeMessageEnd:error]; -} - --(BOOL) writeStructBeginWithName:(NSString *)name error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeStructBeginWithName:name error:error]; -} --(BOOL) writeStructEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeStructEnd:error]; -} - --(BOOL) writeFieldBeginWithName:(NSString *)name - type:(SInt32)fieldType - fieldID:(SInt32)fieldID - error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeFieldBeginWithName:name - type:fieldType - fieldID:fieldID - error:error]; -} - --(BOOL) writeI32:(SInt32)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeI32:value error:error]; -} - --(BOOL) writeI64:(SInt64)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeI64:value error:error]; -} - --(BOOL) writeI16:(SInt16)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeI16:value error:error]; -} - --(BOOL) writeByte:(UInt8)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeByte:value error:error]; -} - --(BOOL) writeString:(NSString *)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeString:value error:error]; -} - --(BOOL) writeDouble:(double)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeDouble:value error:error]; -} - --(BOOL) writeBool:(BOOL)value error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeBool:value error:error]; -} - --(BOOL) writeBinary:(NSData *)data error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeBinary:data error:error]; -} - --(BOOL) writeFieldStop:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeFieldStop:error]; -} - --(BOOL) writeFieldEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeFieldEnd:error]; -} - --(BOOL) writeMapBeginWithKeyType:(SInt32)keyType - valueType:(SInt32)valueType - size:(SInt32)size - error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeMapBeginWithKeyType:keyType - valueType:valueType - size:size - error:error]; -} - --(BOOL) writeMapEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeMapEnd:error]; -} - --(BOOL) writeSetBeginWithElementType:(SInt32)elementType - size:(SInt32)size - error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeSetBeginWithElementType:elementType size:size error:error]; -} - --(BOOL) writeSetEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeSetEnd:error]; -} - --(BOOL) writeListBeginWithElementType:(SInt32)elementType - size:(SInt32)size - error:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeListBeginWithElementType:elementType size:size error:error]; -} - --(BOOL) writeListEnd:(NSError *__autoreleasing *)error -{ - return [_concreteProtocol writeListEnd:error]; -} - -@end diff --git a/lib/cocoa/src/protocol/TProtocolError.h b/lib/cocoa/src/protocol/TProtocolError.h deleted file mode 100644 index ab0bc40dab0..00000000000 --- a/lib/cocoa/src/protocol/TProtocolError.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TError.h" - - -extern NSString *TProtocolErrorDomain; - -typedef NS_ENUM (int, TProtocolError) { - TProtocolErrorUnknown = 0, - TProtocolErrorInvalidData = 1, - TProtocolErrorNegativeSize = 2, - TProtocolErrorSizeLimit = 3, - TProtocolErrorBadVersion = 4, - TProtocolErrorNotImplemented = 5, - TProtocolErrorDepthLimit = 6, -}; - - -typedef NS_ENUM(int, TProtocolExtendedError) { - TProtocolExtendedErrorMissingRequiredField = 1001, - TProtocolExtendedErrorUnexpectedType = 1002, - TProtocolExtendedErrorMismatchedProtocol = 1003, -}; - -extern NSString *TProtocolErrorExtendedErrorKey; -extern NSString *TProtocolErrorFieldNameKey; -extern NSString *TProtocolErrorExpectedIdKey; -extern NSString *TProtocolErrorExpectedVersionKey; -extern NSString *TProtocolErrorTypeKey; -extern NSString *TProtocolErrorSourceLineKey; -extern NSString *TProtocolErrorSourceFileKey; -extern NSString *TProtocolErrorSourceMethodKey; -extern NSString *TProtocolErrorMessageNameKey; - - -#define PROTOCOL_ERROR(ret, err, ...) \ - if (error) { \ - *error = [NSError errorWithDomain:TProtocolErrorDomain \ - code:TProtocolError ## err \ - userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat:__VA_ARGS__], \ - @"SourceFile": [NSString stringWithUTF8String:__FILE__], \ - @"SourceLine": @(__LINE__), \ - @"SourceFunction": [NSString stringWithUTF8String:__PRETTY_FUNCTION__], \ - @"Message": self.currentMessageName ? self.currentMessageName : @""}]; \ - } \ - return ret - -#define PROTOCOL_TRANSPORT_ERROR(ret, errorPtr, ...) \ - if (errorPtr) { \ - *error = [NSError errorWithDomain:TProtocolErrorDomain \ - code:TProtocolErrorUnknown \ - userInfo:@{NSLocalizedDescriptionKey: [[NSString stringWithFormat:__VA_ARGS__] stringByAppendingFormat:@": %@", [(*errorPtr) localizedDescription]], \ - TProtocolErrorSourceFileKey: [NSString stringWithUTF8String:__FILE__], \ - TProtocolErrorSourceLineKey: @(__LINE__), \ - TProtocolErrorSourceMethodKey: [NSString stringWithUTF8String:__PRETTY_FUNCTION__], \ - TProtocolErrorMessageNameKey: self.currentMessageName ? self.currentMessageName : @"", \ - NSUnderlyingErrorKey: *errorPtr}]; \ - } \ - return ret diff --git a/lib/cocoa/src/protocol/TProtocolError.m b/lib/cocoa/src/protocol/TProtocolError.m deleted file mode 100644 index 953673b0afe..00000000000 --- a/lib/cocoa/src/protocol/TProtocolError.m +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TProtocolError.h" - - -NSString *TProtocolErrorDomain = @"TProtocolErrorDomain"; - -NSString *TProtocolErrorExtendedErrorKey = @"extendedError"; -NSString *TProtocolErrorFieldNameKey = @"field"; -NSString *TProtocolErrorExpectedIdKey = @"expectedId"; -NSString *TProtocolErrorExpectedVersionKey = @"expectedVersion"; -NSString *TProtocolErrorTypeKey = @"type"; -NSString *TProtocolErrorSourceLineKey = @"sourceLine"; -NSString *TProtocolErrorSourceFileKey = @"sourceFile"; -NSString *TProtocolErrorSourceMethodKey = @"sourceMethod"; -NSString *TProtocolErrorMessageNameKey = @"messageName"; diff --git a/lib/cocoa/src/protocol/TProtocolFactory.h b/lib/cocoa/src/protocol/TProtocolFactory.h deleted file mode 100644 index a022a7f9fe6..00000000000 --- a/lib/cocoa/src/protocol/TProtocolFactory.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TProtocol.h" -#import "TTransport.h" - -NS_ASSUME_NONNULL_BEGIN - - -@protocol TProtocolFactory - -@property (readonly, nonatomic) NSString *protocolName; - --(id) newProtocolOnTransport:(id)transport; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/protocol/TProtocolUtil.h b/lib/cocoa/src/protocol/TProtocolUtil.h deleted file mode 100644 index 82510cfca82..00000000000 --- a/lib/cocoa/src/protocol/TProtocolUtil.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TProtocol.h" -#import "TTransport.h" - -NS_ASSUME_NONNULL_BEGIN - - -@interface TProtocolUtil : NSObject - -+(BOOL) skipType:(int)type onProtocol:(id )protocol error:(NSError **)error; - -@end; - - -NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/lib/cocoa/src/protocol/TProtocolUtil.m b/lib/cocoa/src/protocol/TProtocolUtil.m deleted file mode 100644 index c0d65aceaf1..00000000000 --- a/lib/cocoa/src/protocol/TProtocolUtil.m +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TProtocolUtil.h" - -@implementation TProtocolUtil - -+(BOOL) skipType:(int)type onProtocol:(id )protocol error:(NSError **)error -{ - switch (type) { - case TTypeBOOL: { - BOOL val; - if (![protocol readBool:&val error:error]) { - return NO; - } - } - break; - - case TTypeBYTE: { - UInt8 val; - if (![protocol readByte:&val error:error]) { - return NO; - } - } - break; - - case TTypeI16: { - SInt16 val; - if (![protocol readI16:&val error:error]) { - return NO; - } - } - break; - - case TTypeI32: { - SInt32 val; - if (![protocol readI32:&val error:error]) { - return NO; - } - } - break; - - case TTypeI64: { - SInt64 val; - if (![protocol readI64:&val error:error]) { - return NO; - } - } - break; - - case TTypeDOUBLE: { - double val; - if (![protocol readDouble:&val error:error]) { - return NO; - } - } - break; - - case TTypeSTRING: { - NSString *val; - if (![protocol readString:&val error:error]) { - return NO; - } - } - break; - - case TTypeSTRUCT: { - if (![protocol readStructBeginReturningName:NULL error:error]) { - return NO; - } - while (true) { - SInt32 fieldType; - if (![protocol readFieldBeginReturningName:nil type:&fieldType fieldID:nil error:error]) { - return NO; - } - if (fieldType == TTypeSTOP) { - break; - } - if (![self skipType:fieldType onProtocol:protocol error:error]) { - return NO; - } - if (![protocol readFieldEnd:error]) { - return NO; - } - } - if (![protocol readStructEnd:error]) { - return NO; - } - } - break; - - case TTypeMAP: { - SInt32 keyType; - SInt32 valueType; - SInt32 size; - if (![protocol readMapBeginReturningKeyType:&keyType valueType:&valueType size:&size error:error]) { - return NO; - } - int i; - for (i = 0; i < size; i++) { - if (![TProtocolUtil skipType:keyType onProtocol:protocol error:error]) { - return NO; - } - if (![TProtocolUtil skipType:valueType onProtocol:protocol error:error]) { - return NO; - } - } - if (![protocol readMapEnd:error]) { - return NO; - } - } - break; - - case TTypeSET: { - SInt32 elemType; - SInt32 size; - if (![protocol readSetBeginReturningElementType:&elemType size:&size error:error]) { - return NO; - } - int i; - for (i = 0; i < size; i++) { - if (![TProtocolUtil skipType:elemType onProtocol:protocol error:error]) { - return NO; - } - } - if (![protocol readSetEnd:error]) { - return NO; - } - } - break; - - case TTypeLIST: { - SInt32 elemType; - SInt32 size; - if (![protocol readListBeginReturningElementType:&elemType size:&size error:error]) { - return NO; - } - int i; - for (i = 0; i < size; i++) { - if (![TProtocolUtil skipType:elemType onProtocol:protocol error:error]) { - return NO; - } - } - if (![protocol readListEnd:error]) { - return NO; - } - } - break; - - } - - return YES; -} - -@end diff --git a/lib/cocoa/src/server/TSocketServer.h b/lib/cocoa/src/server/TSocketServer.h deleted file mode 100644 index 95b0d3c1916..00000000000 --- a/lib/cocoa/src/server/TSocketServer.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TProtocolFactory.h" -#import "TProcessorFactory.h" - -#if !TARGET_OS_IPHONE -#import -#else -#import -#endif - -NS_ASSUME_NONNULL_BEGIN - - -extern NSString *const TSocketServerClientConnectionFinished; -extern NSString *const TSocketServerProcessorKey; -extern NSString *const TSockerServerTransportKey; - - -@interface TSocketServer : NSObject - --(instancetype) initWithPort:(int)port - protocolFactory:(id )protocolFactory - processorFactory:(id )processorFactory; - -- (instancetype) initWithPath: (NSString *) path - protocolFactory: (id ) protocolFactory - processorFactory: (id ) processorFactory; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/server/TSocketServer.m b/lib/cocoa/src/server/TSocketServer.m deleted file mode 100644 index 09b603cf4ad..00000000000 --- a/lib/cocoa/src/server/TSocketServer.m +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TSocketServer.h" -#import "TNSFileHandleTransport.h" -#import "TProtocol.h" -#import "TTransportError.h" - -#import -#include -#include - - -NSString *const TSocketServerClientConnectionFinished = @"TSocketServerClientConnectionFinished"; -NSString *const TSocketServerProcessorKey = @"TSocketServerProcessor"; -NSString *const TSockerServerTransportKey = @"TSockerServerTransport"; - - -@interface TSocketServer () - -@property(strong, nonatomic) id inputProtocolFactory; -@property(strong, nonatomic) id outputProtocolFactory; -@property(strong, nonatomic) id processorFactory; -@property(strong, nonatomic) NSFileHandle *socketFileHandle; -@property(strong, nonatomic) dispatch_queue_t processingQueue; -@property(strong, nonatomic) NSString *domainSocketPath; - -@end - - -@implementation TSocketServer - --(instancetype) initWithSocket:(CFSocketRef)socket - protocolFactory:(id )protocolFactory - processorFactory:(id )processorFactory; -{ - self = [super init]; - - _inputProtocolFactory = protocolFactory; - _outputProtocolFactory = protocolFactory; - _processorFactory = processorFactory; - - dispatch_queue_attr_t processingQueueAttr = - dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT, QOS_CLASS_BACKGROUND, 0); - - _processingQueue = dispatch_queue_create("TSocketServer.processing", processingQueueAttr); - - // create a socket. - int fd = CFSocketGetNative(socket); - - // wrap it in a file handle so we can get messages from it - _socketFileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fd - closeOnDealloc:YES]; - - // throw away our socket - CFSocketInvalidate(socket); - CFRelease(socket); - - // register for notifications of accepted incoming connections - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(connectionAccepted:) - name:NSFileHandleConnectionAcceptedNotification - object:_socketFileHandle]; - - // tell socket to listen - [_socketFileHandle acceptConnectionInBackgroundAndNotify]; - - return self; -} - -- (id) initWithPort: (int) port - protocolFactory: (id ) protocolFactory - processorFactory: (id ) processorFactory -{ - CFSocketRef socket = [[self class] createSocketWithPort:port]; - if (socket == NULL) { - return nil; - } - - if (self = [self initWithSocket:socket protocolFactory:protocolFactory processorFactory:processorFactory]) { - NSLog(@"TSocketServer: Listening on TCP port %d", port); - } - return self; -} - - -+(CFSocketRef) createSocketWithPort:(int)port -{ - CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL); - if (socket) { - CFSocketSetSocketFlags(socket, CFSocketGetSocketFlags(socket) & ~kCFSocketCloseOnInvalidate); - int fd = CFSocketGetNative(socket); - int yes = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); - - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_len = sizeof(addr); - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = htonl(INADDR_ANY); - NSData *address = [NSData dataWithBytes:&addr length:sizeof(addr)]; - if (CFSocketSetAddress(socket, (__bridge CFDataRef)address) != kCFSocketSuccess) { - CFSocketInvalidate(socket); - CFRelease(socket); - NSLog(@"TSocketServer: Could not bind to address"); - return NULL; - } - - return socket; - } - else { - NSLog(@"TSocketServer: No server socket"); - return NULL; - } -} - -- (id) initWithPath: (NSString *) path - protocolFactory: (id ) protocolFactory - processorFactory: (id ) processorFactory -{ - _domainSocketPath = path; - CFSocketRef socket = [[self class] createSocketWithPath:path]; - if (socket == NULL) { - return nil; - } - - if (self = [self initWithSocket:socket protocolFactory:protocolFactory processorFactory:processorFactory]) { - NSLog(@"TSocketServer: Listening on path %@", path); - } - return self; -} - -+ (CFSocketRef) createSocketWithPath: (NSString *) path -{ - CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault, PF_LOCAL, SOCK_STREAM, IPPROTO_IP, 0, NULL, NULL); - if (socket) { - CFSocketSetSocketFlags(socket, CFSocketGetSocketFlags(socket) & ~kCFSocketCloseOnInvalidate); - int fd = CFSocketGetNative(socket); - int yes = 1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)); - - size_t nullTerminatedPathLength = path.length + 1; - struct sockaddr_un addr; - if (nullTerminatedPathLength> sizeof(addr.sun_path)) { - NSLog(@"TSocketServer: Unable to create socket at path %@. Path is too long.", path); - return NULL; - } - - addr.sun_family = AF_LOCAL; - memcpy(addr.sun_path, path.UTF8String, nullTerminatedPathLength); - addr.sun_len = SUN_LEN(&addr); - - NSData *address = [NSData dataWithBytes:&addr length:sizeof(addr)]; - if (CFSocketSetAddress(socket, (__bridge CFDataRef)address) != kCFSocketSuccess) { - CFSocketInvalidate(socket); - CFRelease(socket); - NSLog(@"TSocketServer: Could not bind to address"); - return NULL; - } - - return socket; - } else { - NSLog(@"TSocketServer: No server socket"); - return NULL; - } -} - --(void) dealloc -{ - [[NSNotificationCenter defaultCenter] removeObserver:self]; - - if (_domainSocketPath != nil) { - unlink(_domainSocketPath.UTF8String); - } -} - - --(void) connectionAccepted:(NSNotification *)notification -{ - NSFileHandle *socket = [notification.userInfo objectForKey:NSFileHandleNotificationFileHandleItem]; - - // Now that we have a client connected, handle request on queue - dispatch_async(_processingQueue, ^{ - - [self handleClientConnection:socket]; - - }); - - // Continue accepting connections - [_socketFileHandle acceptConnectionInBackgroundAndNotify]; -} - - --(void) handleClientConnection:(NSFileHandle *)clientSocket -{ - @autoreleasepool { - - TNSFileHandleTransport *transport = [[TNSFileHandleTransport alloc] initWithFileHandle:clientSocket]; - id processor = [_processorFactory processorForTransport:transport]; - - id inProtocol = [_inputProtocolFactory newProtocolOnTransport:transport]; - id outProtocol = [_outputProtocolFactory newProtocolOnTransport:transport]; - - NSError *error; - if (![processor processOnInputProtocol:inProtocol outputProtocol:outProtocol error:&error]) { - // Handle error - NSLog(@"Error processing request: %@", error); - } - - dispatch_async(dispatch_get_main_queue(), ^{ - - [NSNotificationCenter.defaultCenter postNotificationName:TSocketServerClientConnectionFinished - object:self - userInfo:@{TSocketServerProcessorKey: processor, - TSockerServerTransportKey: transport}]; - }); - - } -} - -@end diff --git a/lib/cocoa/src/transport/TAsyncTransport.h b/lib/cocoa/src/transport/TAsyncTransport.h deleted file mode 100644 index bab4fbdcd2c..00000000000 --- a/lib/cocoa/src/transport/TAsyncTransport.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TTransport.h" - -NS_ASSUME_NONNULL_BEGIN - - -@protocol TAsyncTransport; - - -@protocol TAsyncTransportFactory - --(id) newTransport; - -@end - - -typedef void (^TAsyncCompletionBlock)(); -typedef void (^TAsyncFailureBlock)(NSError * __nonnull); - - -@protocol TAsyncTransport - --(void) flushWithCompletion:(TAsyncCompletionBlock)completed failure:(TAsyncFailureBlock)failure; - -@end - - -NS_ASSUME_NONNULL_END \ No newline at end of file diff --git a/lib/cocoa/src/transport/TFramedTransport.h b/lib/cocoa/src/transport/TFramedTransport.h deleted file mode 100644 index ea68ac44d5c..00000000000 --- a/lib/cocoa/src/transport/TFramedTransport.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TTransport.h" - -NS_ASSUME_NONNULL_BEGIN - - -@interface TFramedTransport : NSObject - --(id) initWithTransport:(id )transport; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/transport/TFramedTransport.m b/lib/cocoa/src/transport/TFramedTransport.m deleted file mode 100644 index 4db65c41c92..00000000000 --- a/lib/cocoa/src/transport/TFramedTransport.m +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TFramedTransport.h" -#import "TTransportError.h" - -#define HEADER_SIZE 4 -#define INIT_FRAME_SIZE 1024 - - -@interface TFramedTransport () - -@property(strong, nonatomic) id transport; -@property(strong, nonatomic) NSMutableData *writeBuffer; -@property(strong, nonatomic) NSMutableData *readBuffer; -@property(assign, nonatomic) NSUInteger readOffset; - -@end - - -@implementation TFramedTransport - --(id) initWithTransport:(id )aTransport -{ - if ((self = [self init])) { - _transport = aTransport; - _readBuffer = nil; - _readOffset = 0; - _writeBuffer = [NSMutableData dataWithLength:HEADER_SIZE]; - } - return self; -} - --(BOOL) flush:(NSError **)error -{ - int len = (int)[_writeBuffer length]; - int data_len = len - HEADER_SIZE; - if (data_len < 0) { - if (error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorUnknown - userInfo:@{}]; - } - return NO; - } - - UInt8 i32rd[HEADER_SIZE]; - i32rd[0] = (UInt8)(0xff & (data_len >> 24)); - i32rd[1] = (UInt8)(0xff & (data_len >> 16)); - i32rd[2] = (UInt8)(0xff & (data_len >> 8)); - i32rd[3] = (UInt8)(0xff & (data_len)); - - // should we make a copy of the writeBuffer instead? Better for threaded - // operations! - [_writeBuffer replaceBytesInRange:NSMakeRange(0, HEADER_SIZE) - withBytes:i32rd length:HEADER_SIZE]; - - if (![_transport write:_writeBuffer.mutableBytes offset:0 length:len error:error]) { - return NO; - } - - if (![_transport flush:error]) { - return NO; - } - - _writeBuffer.length = HEADER_SIZE; - - return YES; -} - --(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error -{ - [_writeBuffer appendBytes:data+offset length:length]; - - return YES; -} - --(BOOL) readAll:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error -{ - UInt32 got = [self readAvail:outBuffer offset:outBufferOffset maxLength:length error:error]; - if (got != length) { - - // Report underflow only if readAvail didn't report error already - if (error && !*error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorEndOfFile - userInfo:nil]; - } - - return NO; - } - - return YES; -} - --(UInt32) readAvail:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset maxLength:(UInt32)length error:(NSError *__autoreleasing *)error -{ - UInt32 got = 0; - while (got < length) { - - NSUInteger avail = _readBuffer.length - _readOffset; - if (avail == 0) { - if (![self readFrame:error]) { - return 0; - } - avail = _readBuffer.length; - } - - NSRange range; - range.location = _readOffset; - range.length = MIN(length - got, avail); - - [_readBuffer getBytes:outBuffer+outBufferOffset+got range:range]; - _readOffset += range.length; - got += range.length; - } - - return got; -} - --(BOOL) readFrame:(NSError **)error -{ - UInt8 i32rd[HEADER_SIZE]; - if (![_transport readAll:i32rd offset:0 length:HEADER_SIZE error:error]) { - return NO; - } - - SInt32 size = - ((i32rd[0] & 0xff) << 24) | - ((i32rd[1] & 0xff) << 16) | - ((i32rd[2] & 0xff) << 8) | - ((i32rd[3] & 0xff)); - - if (_readBuffer == nil) { - - _readBuffer = [NSMutableData dataWithLength:size]; - - } - else { - - SInt32 len = (SInt32)_readBuffer.length; - if (len >= size) { - - _readBuffer.length = size; - - } - else { - - // increase length of data buffer - [_readBuffer increaseLengthBy:size-len]; - - } - - } - - // copy into internal memory buffer - if (![_transport readAll:_readBuffer.mutableBytes offset:0 length:size error:error]) { - return NO; - } - - return YES; -} - -@end diff --git a/lib/cocoa/src/transport/THTTPSessionTransport.h b/lib/cocoa/src/transport/THTTPSessionTransport.h deleted file mode 100644 index 003499b80a6..00000000000 --- a/lib/cocoa/src/transport/THTTPSessionTransport.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TAsyncTransport.h" - -NS_ASSUME_NONNULL_BEGIN - - -typedef NSError *__nullable (^THTTPSessionTransportResponseValidateBlock) (NSHTTPURLResponse *response, NSData *responseData); - - -@interface THTTPSessionTransportFactory : NSObject - -@property (strong, nonatomic) THTTPSessionTransportResponseValidateBlock responseValidate; - -+(void) setupDefaultsForSessionConfiguration:(NSURLSessionConfiguration *)config - withProtocolName:(NSString *)protocolName; - --(id) initWithSession:(NSURLSession *)session - URL:(NSURL *)aURL; - -@end - - -@interface THTTPSessionTransport : NSObject - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/transport/THTTPSessionTransport.m b/lib/cocoa/src/transport/THTTPSessionTransport.m deleted file mode 100644 index c10b7fc3f6b..00000000000 --- a/lib/cocoa/src/transport/THTTPSessionTransport.m +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "THTTPSessionTransport.h" -#import "TTransportError.h" - - -@interface THTTPSessionTransportFactory () - -@property (strong, nonatomic) NSURLSession *session; -@property (strong, nonatomic) NSURL *url; - -@end - - -@interface THTTPSessionTransport () - -@property (strong, nonatomic) THTTPSessionTransportFactory *factory; -@property (strong, nonatomic) NSMutableData *requestData; -@property (strong, nonatomic) NSData *responseData; -@property (assign, nonatomic) NSUInteger responseDataOffset; - --(instancetype) initWithFactory:(THTTPSessionTransportFactory *)factory; - -@end - - -@implementation THTTPSessionTransportFactory - -+(void) setupDefaultsForSessionConfiguration:(NSURLSessionConfiguration *)config withProtocolName:(NSString *)protocolName -{ - NSString *thriftContentType = @"application/x-thrift"; - if (protocolName.length) { - thriftContentType = [thriftContentType stringByAppendingFormat:@"; p=%@", protocolName]; - } - - config.requestCachePolicy = NSURLRequestReloadIgnoringCacheData; - config.HTTPShouldUsePipelining = YES; - config.HTTPShouldSetCookies = NO; - config.URLCache = nil; - config.HTTPAdditionalHeaders = @{@"Content-Type":thriftContentType, - @"Accept":thriftContentType, - @"User-Agent":@"Thrift/Cocoa (Session)"}; -} - - --(id) initWithSession:(NSURLSession *)session URL:(NSURL *)url -{ - self = [super init]; - if (self) { - _session = session; - _url = url; - } - - return self; -} - --(id) newTransport -{ - return [[THTTPSessionTransport alloc] initWithFactory:self]; -} - --(NSURLSessionDataTask *) taskWithRequest:(NSURLRequest *)request - completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler - error:(NSError *__autoreleasing *)error -{ - NSURLSessionDataTask *newTask = [_session dataTaskWithRequest:request completionHandler:completionHandler]; - if (!newTask) { - if (error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorUnknown - userInfo:@{NSLocalizedDescriptionKey:@"Failed to create session data task"}]; - } - return nil; - } - - return newTask; -} - --(NSError *) validateResponse:(NSHTTPURLResponse *)response data:(NSData *)data -{ - if (_responseValidate) { - return _responseValidate(response, data); - } - return nil; -} - -@end - - - -@implementation THTTPSessionTransport - --(instancetype) initWithFactory:(THTTPSessionTransportFactory *)factory -{ - self = [super init]; - if (self) { - _factory = factory; - } - return self; -} - --(BOOL) readAll:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error -{ - UInt32 got = [self readAvail:outBuffer offset:outBufferOffset maxLength:length error:error]; - if (got != length) { - - // Report underflow only if readAvail didn't report error already - if (error && !*error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorEndOfFile - userInfo:nil]; - } - - return NO; - } - - return YES; -} - --(UInt32) readAvail:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset maxLength:(UInt32)maxLength error:(NSError *__autoreleasing *)error -{ - NSUInteger avail = _responseData.length - _responseDataOffset; - - NSRange range; - range.location = _responseDataOffset; - range.length = MIN(maxLength, avail); - - [_responseData getBytes:outBuffer+outBufferOffset range:range]; - _responseDataOffset += range.length; - - return (UInt32)range.length; -} - --(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error -{ - if (!_requestData) { - _requestData = [NSMutableData dataWithCapacity:256]; - } - - [_requestData appendBytes:data+offset length:length]; - - return YES; -} - --(void) flushWithCompletion:(TAsyncCompletionBlock)completed failure:(TAsyncFailureBlock)failure -{ - NSError *error; - - NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_factory.url]; - request.HTTPMethod = @"POST"; - request.HTTPBody = _requestData; - - _requestData = nil; - - NSURLSessionDataTask *task = [_factory taskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { - - // Check response type - if (!error && ![response isKindOfClass:NSHTTPURLResponse.class]) { - - error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorUnknown - userInfo:@{TTransportErrorHttpErrorKey: @(THttpTransportErrorInvalidResponse)}]; - - } - - // Check status code - NSHTTPURLResponse *httpResponse = (id)response; - if (!error && httpResponse.statusCode != 200) { - - THttpTransportError code; - if (httpResponse.statusCode == 401) { - code = THttpTransportErrorAuthentication; - } - else { - code = THttpTransportErrorInvalidStatus; - } - - error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorUnknown - userInfo:@{TTransportErrorHttpErrorKey: @(code), - @"statusCode":@(httpResponse.statusCode)}]; - } - - // Allow factory to check - if (!error) { - error = [_factory validateResponse:httpResponse data:data]; - } - - _responseDataOffset = 0; - - if (error) { - - _responseData = nil; - - failure(error); - - } - else { - - if (data == nil) { - data = [NSData data]; - } - - _responseData = data; - - completed(self); - } - - } error:&error]; - - if (!task) { - failure(error); - return; - } - - [task resume]; -} - --(BOOL) flush:(NSError *__autoreleasing *)error -{ - dispatch_semaphore_t completed = dispatch_semaphore_create(0); - - __block BOOL result; - __block NSError *internalError; - - [self flushWithCompletion:^(id < TAsyncTransport > transport) { - - result = YES; - - dispatch_semaphore_signal(completed); - - } failure:^(NSError *error) { - - internalError = error; - - result = NO; - - dispatch_semaphore_signal(completed); - - }]; - - dispatch_semaphore_wait(completed, DISPATCH_TIME_FOREVER); - - if (error) { - *error = internalError; - } - - return result; -} - -@end diff --git a/lib/cocoa/src/transport/THTTPTransport.h b/lib/cocoa/src/transport/THTTPTransport.h deleted file mode 100644 index 3c35daf9e75..00000000000 --- a/lib/cocoa/src/transport/THTTPTransport.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TTransport.h" - -NS_ASSUME_NONNULL_BEGIN - - -@interface THTTPTransport : NSObject - --(id) initWithURL:(NSURL *)aURL; - --(id) initWithURL:(NSURL *)aURL - userAgent:(nullable NSString *)userAgent - timeout:(int)timeout; - --(void) setURL:(NSURL *)aURL; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/transport/THTTPTransport.m b/lib/cocoa/src/transport/THTTPTransport.m deleted file mode 100644 index e4046c6ca23..00000000000 --- a/lib/cocoa/src/transport/THTTPTransport.m +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "THTTPTransport.h" -#import "TTransportError.h" - - -@interface THTTPTransport () - -@property (strong, nonatomic) NSURL *url; -@property (strong, nonatomic) NSMutableURLRequest *request; -@property (strong, nonatomic) NSMutableData *requestData; -@property (strong, nonatomic) NSData *responseData; -@property (assign, nonatomic) NSUInteger responseDataOffset; -@property (strong, nonatomic) NSString *userAgent; -@property (assign, nonatomic) NSTimeInterval timeout; - -@end - - -@implementation THTTPTransport - --(void) setupRequest -{ - // set up our request object that we'll use for each request - _request = [[NSMutableURLRequest alloc] initWithURL:_url]; - [_request setHTTPMethod:@"POST"]; - [_request setValue:@"application/x-thrift" forHTTPHeaderField:@"Content-Type"]; - [_request setValue:@"application/x-thrift" forHTTPHeaderField:@"Accept"]; - - NSString *userAgent = _userAgent; - if (!userAgent) { - userAgent = @"Thrift/Cocoa"; - } - [_request setValue:userAgent forHTTPHeaderField:@"User-Agent"]; - - [_request setCachePolicy:NSURLRequestReloadIgnoringCacheData]; - if (_timeout) { - [_request setTimeoutInterval:_timeout]; - } -} - - --(id) initWithURL:(NSURL *)aURL -{ - return [self initWithURL:aURL - userAgent:nil - timeout:0]; -} - - --(id) initWithURL:(NSURL *)aURL - userAgent:(NSString *)aUserAgent - timeout:(int)aTimeout -{ - self = [super init]; - if (!self) { - return nil; - } - - _timeout = aTimeout; - _userAgent = aUserAgent; - _url = aURL; - - [self setupRequest]; - - // create our request data buffer - _requestData = [[NSMutableData alloc] initWithCapacity:1024]; - - return self; -} - --(void) setURL:(NSURL *)aURL -{ - _url = aURL; - - [self setupRequest]; -} - --(BOOL) readAll:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error -{ - UInt32 got = [self readAvail:outBuffer offset:outBufferOffset maxLength:length error:error]; - if (got != length) { - - // Report underflow only if readAvail didn't report error already - if (error && !*error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorEndOfFile - userInfo:nil]; - } - - return NO; - } - - return YES; -} - --(UInt32) readAvail:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset maxLength:(UInt32)maxLength error:(NSError *__autoreleasing *)error -{ - NSUInteger avail = _responseData.length - _responseDataOffset; - - NSRange range; - range.location = _responseDataOffset; - range.length = MIN(maxLength, avail); - - [_responseData getBytes:outBuffer+outBufferOffset range:range]; - _responseDataOffset += range.length; - - return (UInt32)range.length; -} - --(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error -{ - [_requestData appendBytes:data+offset length:length]; - - return YES; -} - --(BOOL) flush:(NSError *__autoreleasing *)error -{ - [_request setHTTPBody:_requestData]; - - _responseDataOffset = 0; - - // make the HTTP request - NSURLResponse *response; - _responseData = [NSURLConnection sendSynchronousRequest:_request returningResponse:&response error:error]; - if (!_responseData) { - return NO; - } - - [_requestData setLength:0]; - - if (![response isKindOfClass:NSHTTPURLResponse.class]) { - if (error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorUnknown - userInfo:@{TTransportErrorHttpErrorKey: @(THttpTransportErrorInvalidResponse)}]; - } - return NO; - } - - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - if ([httpResponse statusCode] != 200) { - if (error) { - - THttpTransportError code; - if (httpResponse.statusCode == 401) { - code = THttpTransportErrorAuthentication; - } - else { - code = THttpTransportErrorInvalidStatus; - } - - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorUnknown - userInfo:@{TTransportErrorHttpErrorKey: @(code), - @"statusCode":@(httpResponse.statusCode)}]; - } - return NO; - } - - return YES; -} - -@end diff --git a/lib/cocoa/src/transport/TMemoryBuffer.h b/lib/cocoa/src/transport/TMemoryBuffer.h deleted file mode 100644 index 6249d3209e4..00000000000 --- a/lib/cocoa/src/transport/TMemoryBuffer.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TTransport.h" - -NS_ASSUME_NONNULL_BEGIN - - -@interface TMemoryBuffer : NSObject - --(NSData *) buffer; - --(id) initWithData:(NSData *)data; - --(id) initWithDataNoCopy:(NSMutableData *)data; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/transport/TMemoryBuffer.m b/lib/cocoa/src/transport/TMemoryBuffer.m deleted file mode 100644 index ec19cc8082c..00000000000 --- a/lib/cocoa/src/transport/TMemoryBuffer.m +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TMemoryBuffer.h" -#import "TTransportError.h" - - -#define GARBAGE_BUFFER_SIZE 4096 // 4KiB - - -@interface TMemoryBuffer () - -@property(strong, nonatomic) NSMutableData *buffer; -@property(assign, nonatomic) UInt32 bufferOffset; - -@end - - -@implementation TMemoryBuffer - --(id) init -{ - if ((self = [super init])) { - _buffer = [NSMutableData new]; - _bufferOffset = 0; - } - return self; -} - --(id) initWithData:(NSData *)data -{ - if (self = [super init]) { - _buffer = [data mutableCopy]; - _bufferOffset = 0; - } - return self; -} - --(id) initWithDataNoCopy:(NSMutableData *)data -{ - if (self = [super init]) { - _buffer = data; - _bufferOffset = 0; - } - return self; -} - --(BOOL) readAll:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error -{ - UInt32 got = [self readAvail:outBuffer offset:outBufferOffset maxLength:length error:error]; - if (got != length) { - - // Report underflow only if readAvail didn't report error already - if (error && !*error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorEndOfFile - userInfo:nil]; - } - - return NO; - } - - return YES; -} - --(UInt32) readAvail:(UInt8 *)outBuffer offset:(UInt32)outBufferOffset maxLength:(UInt32)maxLength error:(NSError *__autoreleasing *)error -{ - UInt32 avail = (UInt32)_buffer.length - _bufferOffset; - if (avail == 0) { - return 0; - } - - NSRange range; - range.location = _bufferOffset; - range.length = MIN(maxLength, avail); - - [_buffer getBytes:outBuffer + outBufferOffset range:range]; - _bufferOffset += range.length; - - if (_bufferOffset >= GARBAGE_BUFFER_SIZE) { - [_buffer replaceBytesInRange:NSMakeRange(0, _bufferOffset) withBytes:NULL length:0]; - _bufferOffset = 0; - } - - return (UInt32)range.length; -} - --(BOOL) write:(const UInt8 *)inBuffer offset:(UInt32)inBufferOffset length:(UInt32)length error:(NSError *__autoreleasing *)error -{ - [_buffer appendBytes:inBuffer + inBufferOffset length:length]; - - return YES; -} - --(NSData *) buffer -{ - return _buffer; -} - --(BOOL) flush:(NSError *__autoreleasing *)error -{ - return YES; -} - -@end diff --git a/lib/cocoa/src/transport/TNSFileHandleTransport.h b/lib/cocoa/src/transport/TNSFileHandleTransport.h deleted file mode 100644 index db6edf3832d..00000000000 --- a/lib/cocoa/src/transport/TNSFileHandleTransport.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -#import -#import "TTransport.h" - -NS_ASSUME_NONNULL_BEGIN - - -@interface TNSFileHandleTransport : NSObject - --(id) initWithFileHandle:(NSFileHandle *)fileHandle; - --(id) initWithInputFileHandle:(NSFileHandle *)inputFileHandle - outputFileHandle:(NSFileHandle *)outputFileHandle; - - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/transport/TNSFileHandleTransport.m b/lib/cocoa/src/transport/TNSFileHandleTransport.m deleted file mode 100644 index c907f87da85..00000000000 --- a/lib/cocoa/src/transport/TNSFileHandleTransport.m +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - - -#import "TNSFileHandleTransport.h" -#import "TTransportError.h" - - -@interface TNSFileHandleTransport () - -@property(strong, nonatomic) NSFileHandle *inputFileHandle; -@property(strong, nonatomic) NSFileHandle *outputFileHandle; - -@end - - -@implementation TNSFileHandleTransport - --(id) initWithFileHandle:(NSFileHandle *)fileHandle -{ - return [self initWithInputFileHandle:fileHandle - outputFileHandle:fileHandle]; -} - - --(id) initWithInputFileHandle:(NSFileHandle *)aInputFileHandle - outputFileHandle:(NSFileHandle *)aOutputFileHandle -{ - self = [super init]; - if (self) { - _inputFileHandle = aInputFileHandle; - _outputFileHandle = aOutputFileHandle; - } - return self; -} - - --(BOOL) readAll:(UInt8 *)buf offset:(UInt32)off length:(UInt32)len error:(NSError *__autoreleasing *)error -{ - UInt32 got = 0; - while (got < len) { - - NSData *d = [_inputFileHandle readDataOfLength:len-got]; - if (d.length == 0) { - if (error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorEndOfFile - userInfo:nil]; - } - return NO; - } - - [d getBytes:buf+got length:d.length]; - got += d.length; - } - return YES; -} - - --(UInt32) readAvail:(UInt8 *)buf offset:(UInt32)off maxLength:(UInt32)len error:(NSError *__autoreleasing *)error -{ - UInt32 got = 0; - while (got < len) { - - NSData *d = [_inputFileHandle readDataOfLength:len-got]; - if (d.length == 0) { - break; - } - - [d getBytes:buf+got length:d.length]; - got += d.length; - } - return got; -} - - --(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error -{ - void *pos = (void *)data + offset; - - @try { - [_outputFileHandle writeData:[NSData dataWithBytesNoCopy:pos length:length freeWhenDone:NO]]; - } - @catch (NSException *e) { - if (error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorNotOpen - userInfo:@{}]; - } - return NO; - } - - return YES; -} - - --(BOOL) flush:(NSError *__autoreleasing *)error -{ - return YES; -} - -@end diff --git a/lib/cocoa/src/transport/TNSStreamTransport.h b/lib/cocoa/src/transport/TNSStreamTransport.h deleted file mode 100644 index 54c48844471..00000000000 --- a/lib/cocoa/src/transport/TNSStreamTransport.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TTransport.h" - -NS_ASSUME_NONNULL_BEGIN - - -@interface TNSStreamTransport : NSObject - -@property (strong, nonatomic) NSInputStream *input; -@property (strong, nonatomic) NSOutputStream *output; - --(id) initWithInputStream:(nullable NSInputStream *)input - outputStream:(nullable NSOutputStream *)output; - --(id) initWithInputStream:(NSInputStream *)input; - --(id) initWithOutputStream:(NSOutputStream *)output; - --(void) close; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/transport/TNSStreamTransport.m b/lib/cocoa/src/transport/TNSStreamTransport.m deleted file mode 100644 index 18c41d3d9ca..00000000000 --- a/lib/cocoa/src/transport/TNSStreamTransport.m +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TNSStreamTransport.h" -#import "TTransportError.h" - - -@interface TNSStreamTransport () -@end - - -@implementation TNSStreamTransport - --(id) initWithInputStream:(NSInputStream *)input - outputStream:(NSOutputStream *)output -{ - self = [super init]; - if (self) { - _input = input; - _output = output; - } - return self; -} - --(id) initWithInputStream:(NSInputStream *)input -{ - return [self initWithInputStream:input outputStream:nil]; -} - --(id) initWithOutputStream:(NSOutputStream *)output -{ - return [self initWithInputStream:nil outputStream:output]; -} - --(void) dealloc -{ - [self close]; -} - --(BOOL) readAll:(UInt8 *)buf offset:(UInt32)off length:(UInt32)len error:(NSError *__autoreleasing *)error -{ - UInt32 got = 0; - while (got < len) { - - UInt32 read = (UInt32)[_input read:buf+off+got maxLength:len-got]; - if (read <= 0) { - if (error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorNotOpen - userInfo:@{}]; - } - return NO; - } - - got += read; - } - - return YES; -} - - --(UInt32) readAvail:(UInt8 *)buf offset:(UInt32)off maxLength:(UInt32)len error:(NSError *__autoreleasing *)error -{ - UInt32 got = 0; - while (got < len) { - - UInt32 read = (UInt32)[_input read:buf+off+got maxLength:len-got]; - if (read <= 0) { - break; - } - - got += read; - } - - return got; -} - - --(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error -{ - UInt32 got = 0; - NSInteger total = 0; - while (got < length) { - - total = [_output write:data+offset+got maxLength:length-got]; - if (total == -1) { - if (error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorNotOpen - userInfo:@{}]; - } - return NO; - } - else if (total == 0) { - if (error) { - *error = [NSError errorWithDomain:TTransportErrorDomain - code:TTransportErrorEndOfFile - userInfo:@{}]; - } - return NO; - } - - got += total; - } - - return YES; -} - --(BOOL) flush:(NSError *__autoreleasing *)error -{ - return YES; -} - --(void) close -{ - NSInputStream *input = self.input; - if (input) { - // Close and reset inputstream - CFReadStreamSetProperty((__bridge CFReadStreamRef)(input), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); - [input setDelegate:nil]; - [input close]; - [input removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - input = nil; - } - - NSOutputStream *output = self.output; - if (output) { - // Close and reset outputstream - CFWriteStreamSetProperty((__bridge CFWriteStreamRef)(output), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); - [output setDelegate:nil]; - [output close]; - [output removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - output = nil; - } -} - -@end diff --git a/lib/cocoa/src/transport/TSSLSocketTransport.h b/lib/cocoa/src/transport/TSSLSocketTransport.h deleted file mode 100644 index b606c4a33ff..00000000000 --- a/lib/cocoa/src/transport/TSSLSocketTransport.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TNSStreamTransport.h" - -NS_ASSUME_NONNULL_BEGIN - - -@interface TSSLSocketTransport : TNSStreamTransport - --(id) initWithHostname:(NSString *)hostname - port:(int)port - error:(NSError **)error; - --(BOOL) isOpen; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/transport/TSSLSocketTransport.m b/lib/cocoa/src/transport/TSSLSocketTransport.m deleted file mode 100644 index 1b1214fe476..00000000000 --- a/lib/cocoa/src/transport/TSSLSocketTransport.m +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#import -#import -#import "TSSLSocketTransport.h" -#import "TSSLSocketTransportError.h" -#include -#include -#include - -#if !TARGET_OS_IPHONE -#import -#else -#import -#endif - -@interface TSSLSocketTransport () - -@property(strong, nonatomic) NSString *sslHostname; -@property(assign, nonatomic) int sd; - -@end - - -@implementation TSSLSocketTransport - --(id) initWithHostname:(NSString *)hostname - port:(int)port - error:(NSError **)error -{ - _sslHostname = hostname; - CFReadStreamRef readStream = NULL; - CFWriteStreamRef writeStream = NULL; - - - /* create a socket structure */ - struct sockaddr_in pin; - struct hostent *hp = NULL; - for (int i = 0; i < 10; i++) { - - - - if ((hp = gethostbyname([hostname UTF8String])) == NULL) { - NSLog(@"failed to resolve hostname %@", hostname); - herror("resolv"); - if (i == 9) { - if (error) { - *error = [NSError errorWithDomain:TSSLSocketTransportErrorDomain - code:TSSLSocketTransportErrorHostanameResolution - userInfo:nil]; - } - return nil; - } - [NSThread sleepForTimeInterval:0.2]; - } - else { - break; - } - } - - memset(&pin, 0, sizeof(pin)); - pin.sin_family = AF_INET; - memcpy(&pin.sin_addr, hp->h_addr, sizeof(struct in_addr)); - pin.sin_port = htons(port); - - /* create the socket */ - if ((_sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - NSLog(@"failed to create socket for host %@:%d", hostname, port); - if (error) { - *error = [NSError errorWithDomain:TSSLSocketTransportErrorDomain - code:TSSLSocketTransportErrorSocketCreate - userInfo:nil]; - } - return nil; - } - - /* open a connection */ - if (connect(_sd, (struct sockaddr *)&pin, sizeof(pin)) == -1) { - NSLog(@"failed to create conenct to host %@:%d", hostname, port); - if (error) { - *error = [NSError errorWithDomain:TSSLSocketTransportErrorDomain - code:TSSLSocketTransportErrorConnect - userInfo:nil]; - } - return nil; - } - CFStreamCreatePairWithSocket(kCFAllocatorDefault, _sd, &readStream, &writeStream); - - CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); - CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); - - NSInputStream *inputStream; - NSOutputStream *outputStream; - - if (readStream && writeStream) { - - CFReadStreamSetProperty(readStream, - kCFStreamPropertySocketSecurityLevel, - kCFStreamSocketSecurityLevelTLSv1); - - NSDictionary *settings = @{(__bridge NSString *)kCFStreamSSLValidatesCertificateChain: @YES}; - - CFReadStreamSetProperty((CFReadStreamRef)readStream, - kCFStreamPropertySSLSettings, - (CFTypeRef)settings); - - CFWriteStreamSetProperty((CFWriteStreamRef)writeStream, - kCFStreamPropertySSLSettings, - (CFTypeRef)settings); - - inputStream = (__bridge NSInputStream *)readStream; - [inputStream setDelegate:self]; - [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - [inputStream open]; - - outputStream = (__bridge NSOutputStream *)writeStream; - [outputStream setDelegate:self]; - [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - [outputStream open]; - - CFRelease(readStream); - CFRelease(writeStream); - } - - self = [super initWithInputStream:inputStream outputStream:outputStream]; - - return self; -} - --(void) dealloc -{ - [self close]; -} - -#pragma mark - -#pragma mark NSStreamDelegate - --(void) stream:(NSStream *)aStream - handleEvent:(NSStreamEvent)eventCode -{ - switch (eventCode) { - case NSStreamEventNone: - break; - - case NSStreamEventHasBytesAvailable: - break; - - case NSStreamEventOpenCompleted: - break; - - case NSStreamEventHasSpaceAvailable: { - - BOOL proceed = NO; - SecTrustResultType trustResult = kSecTrustResultInvalid; - CFMutableArrayRef newPolicies = NULL; - - do { - - SecTrustRef trust = (__bridge SecTrustRef)[aStream propertyForKey:(NSString *)kCFStreamPropertySSLPeerTrust]; - - // Add new policy to current list of policies - SecPolicyRef policy = SecPolicyCreateSSL(NO, (__bridge CFStringRef)(_sslHostname)); - if (!policy) { - break; - } - - CFArrayRef policies; - if (SecTrustCopyPolicies(trust, &policies) != errSecSuccess) { - CFRelease(policy); - break; - } - - newPolicies = CFArrayCreateMutableCopy(NULL, 0, policies); - CFArrayAppendValue(newPolicies, policy); - - CFRelease(policies); - CFRelease(policy); - - // Update trust policies - if (SecTrustSetPolicies(trust, newPolicies) != errSecSuccess) { - break; - } - - // Evaluate the trust chain - if (SecTrustEvaluate(trust, &trustResult) != errSecSuccess) { - break; - } - - switch (trustResult) { - case kSecTrustResultProceed: - // NSLog(@"Trusted by USER"); - proceed = YES; - break; - - case kSecTrustResultUnspecified: - // NSLog(@"Trusted by OS"); - proceed = YES; - break; - - case kSecTrustResultRecoverableTrustFailure: - proceed = recoverFromTrustFailure(trust, trustResult); - break; - - case kSecTrustResultDeny: - // NSLog(@"Deny"); - break; - - case kSecTrustResultFatalTrustFailure: - // NSLog(@"FatalTrustFailure"); - break; - - case kSecTrustResultOtherError: - // NSLog(@"OtherError"); - break; - - case kSecTrustResultInvalid: - // NSLog(@"Invalid"); - break; - - default: - // NSLog(@"Default"); - break; - } - - } - while (NO); - - if (!proceed) { - NSLog(@"TSSLSocketTransport: Cannot trust certificate. Result: %u", trustResult); - [aStream close]; - } - - if (newPolicies) { - CFRelease(newPolicies); - } - - } - break; - - case NSStreamEventErrorOccurred: { - NSLog(@"TSSLSocketTransport: Error occurred opening stream: %@", [aStream streamError]); - break; - } - - case NSStreamEventEndEncountered: - break; - } -} - -BOOL recoverFromTrustFailure(SecTrustRef myTrust, SecTrustResultType lastTrustResult) -{ - CFAbsoluteTime trustTime = SecTrustGetVerifyTime(myTrust); - CFAbsoluteTime currentTime = CFAbsoluteTimeGetCurrent(); - - CFAbsoluteTime timeIncrement = 31536000; - CFAbsoluteTime newTime = currentTime - timeIncrement; - - if (trustTime - newTime) { - - CFDateRef newDate = CFDateCreate(NULL, newTime); - SecTrustSetVerifyDate(myTrust, newDate); - CFRelease(newDate); - - if (SecTrustEvaluate(myTrust, &lastTrustResult) != errSecSuccess) { - return NO; - } - - } - - if (lastTrustResult == kSecTrustResultProceed || lastTrustResult == kSecTrustResultUnspecified) { - return YES; - } - - NSLog(@"TSSLSocketTransport: Unable to recover certificate trust failure"); - return YES; -} - --(BOOL) isOpen -{ - if (_sd > 0) { - return TRUE; - } - else { - return FALSE; - } -} - -@end diff --git a/lib/cocoa/src/transport/TSSLSocketTransportError.h b/lib/cocoa/src/transport/TSSLSocketTransportError.h deleted file mode 100644 index e17f39e3276..00000000000 --- a/lib/cocoa/src/transport/TSSLSocketTransportError.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TTransportError.h" - - -extern NSString *TSSLSocketTransportErrorDomain; - - -typedef NS_ENUM (int, TSSLSocketTransportError) { - TSSLSocketTransportErrorHostanameResolution = -10000, - TSSLSocketTransportErrorSocketCreate = -10001, - TSSLSocketTransportErrorConnect = -10002, -}; diff --git a/lib/cocoa/src/transport/TSSLSocketTransportError.m b/lib/cocoa/src/transport/TSSLSocketTransportError.m deleted file mode 100644 index bcf941cc47d..00000000000 --- a/lib/cocoa/src/transport/TSSLSocketTransportError.m +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TSSLSocketTransportError.h" - - -NSString *TSSLSocketTransportErrorDomain = @"TSSLSocketTransportErrorDomain"; diff --git a/lib/cocoa/src/transport/TSocketTransport.h b/lib/cocoa/src/transport/TSocketTransport.h deleted file mode 100644 index a7b91a2c976..00000000000 --- a/lib/cocoa/src/transport/TSocketTransport.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import -#import "TNSStreamTransport.h" - -NS_ASSUME_NONNULL_BEGIN - - -@interface TSocketTransport : TNSStreamTransport - --(id) initWithHostname:(NSString *)hostname - port:(int)port; - --(id) initWithPath:(NSString *)path; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/transport/TSocketTransport.m b/lib/cocoa/src/transport/TSocketTransport.m deleted file mode 100644 index 9c58abb6d07..00000000000 --- a/lib/cocoa/src/transport/TSocketTransport.m +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#import "TSocketTransport.h" - -#if !TARGET_OS_IPHONE -#import -#else -#import -#endif - -#include -#include -#include - -@interface TSocketTransport () -@end - - -@implementation TSocketTransport - -- (id) initWithReadStream: (CFReadStreamRef) readStream writeStream: (CFWriteStreamRef) writeStream -{ - NSInputStream *inputStream = nil; - NSOutputStream *outputStream = nil; - - if (readStream && writeStream) { - - CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); - CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); - - inputStream = (__bridge NSInputStream *)readStream; - [inputStream setDelegate:self]; - [inputStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSDefaultRunLoopMode]; - [inputStream open]; - - outputStream = (__bridge NSOutputStream *)writeStream; - [outputStream setDelegate:self]; - [outputStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSDefaultRunLoopMode]; - [outputStream open]; - } - else { - - if (readStream) { - CFRelease(readStream); - } - - if (writeStream) { - CFRelease(writeStream); - } - - return nil; - } - - return [super initWithInputStream:inputStream outputStream:outputStream]; -} - -- (id) initWithHostname: (NSString *) hostname - port: (int) port -{ - CFReadStreamRef readStream = NULL; - CFWriteStreamRef writeStream = NULL; - CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (__bridge CFStringRef)hostname, port, &readStream, &writeStream); - return [self initWithReadStream:readStream writeStream:writeStream]; -} - -- (id) initWithPath: (NSString *) path -{ - CFSocketNativeHandle sockfd = socket(AF_LOCAL, SOCK_STREAM, IPPROTO_IP); - int yes = 1; - if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) - { - NSLog(@"TSocketTransport: Unable to set REUSEADDR property of socket."); - return nil; - } - - NSData *serverAddress = [[self class] createAddressWithPath:path]; - - CFReadStreamRef readStream = NULL; - CFWriteStreamRef writeStream = NULL; - CFStreamCreatePairWithSocket(kCFAllocatorDefault, sockfd, &readStream, &writeStream); - if (!readStream || !writeStream) - { - NSLog(@"TSocketTransport: Unable to create read/write stream pair for socket."); - return nil; - } - - if (connect(sockfd, (struct sockaddr *)serverAddress.bytes, (socklen_t) serverAddress.length) < 0) - { - NSLog(@"TSocketTransport: Connect error: %s\n", strerror(errno)); - return nil; - } - - return [self initWithReadStream:readStream writeStream:writeStream]; -} - -+ (NSData *) createAddressWithPath: (NSString *)path -{ - struct sockaddr_un servaddr; - - size_t nullTerminatedPathLength = path.length + 1; - if (nullTerminatedPathLength> sizeof(servaddr.sun_path)) { - NSLog(@"TSocketTransport: Unable to create socket at path %@. Path is too long.", path); - return nil; - } - - bzero(&servaddr,sizeof(servaddr)); - servaddr.sun_family = AF_LOCAL; - memcpy(servaddr.sun_path, path.UTF8String, nullTerminatedPathLength); - servaddr.sun_len = SUN_LEN(&servaddr); - - return [NSData dataWithBytes:&servaddr length:sizeof(servaddr)]; -} - - -@end diff --git a/lib/cocoa/src/transport/TTransport.h b/lib/cocoa/src/transport/TTransport.h deleted file mode 100644 index 558cf60fb46..00000000000 --- a/lib/cocoa/src/transport/TTransport.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import - - -NS_ASSUME_NONNULL_BEGIN - - -@protocol TTransport - -/** - * Guarantees that all of len bytes are read - * - * @param buf Buffer to read into - * @param off Index in buffer to start storing bytes at - * @param len Maximum number of bytes to read - * @return YES if succeeded, NO if failed - * @throws TTransportError if there was an error reading data - */ --(BOOL) readAll:(UInt8 *)buf offset:(UInt32)off length:(UInt32)len error:(NSError *__autoreleasing *)error; - --(UInt32) readAvail:(UInt8 *)buf offset:(UInt32)off maxLength:(UInt32)maxLen error:(NSError *__autoreleasing *)error; - --(BOOL) write:(const UInt8 *)data offset:(UInt32)offset length:(UInt32)length error:(NSError *__autoreleasing *)error; - --(BOOL) flush:(NSError *__autoreleasing *)error; - -@end - - -NS_ASSUME_NONNULL_END diff --git a/lib/cocoa/src/transport/TTransportError.h b/lib/cocoa/src/transport/TTransportError.h deleted file mode 100644 index c8c9f067fd3..00000000000 --- a/lib/cocoa/src/transport/TTransportError.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TError.h" - - -extern NSString *TTransportErrorDomain; - - -typedef NS_ENUM (int, TTransportError) { - TTransportErrorUnknown = 0, - TTransportErrorNotOpen = 1, - TTransportErrorAlreadyOpen = 2, - TTransportErrorTimedOut = 3, - TTransportErrorEndOfFile = 4, -}; - - -extern NSString *TTransportErrorExtendedErrorKey; -extern NSString *TTransportErrorHttpErrorKey; - - -typedef NS_ENUM(int, THttpTransportError) { - THttpTransportErrorInvalidResponse = 1001, - THttpTransportErrorInvalidStatus = 1002, - THttpTransportErrorAuthentication = 1003, -}; diff --git a/lib/cocoa/src/transport/TTransportError.m b/lib/cocoa/src/transport/TTransportError.m deleted file mode 100644 index b1af076b271..00000000000 --- a/lib/cocoa/src/transport/TTransportError.m +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "TTransportError.h" - - -NSString *TTransportErrorDomain = @"TTransportErrorDomain"; - - -NSString *TTransportErrorExtendedErrorKey = @"extendedError"; -NSString *TTransportErrorHttpErrorKey = @"httpError"; diff --git a/lib/cpp/test/OneWayTest.thrift b/lib/cpp/test/OneWayTest.thrift index 127e9ffa364..102cf26e5a6 100644 --- a/lib/cpp/test/OneWayTest.thrift +++ b/lib/cpp/test/OneWayTest.thrift @@ -34,7 +34,6 @@ namespace py.twisted OneWayTest namespace go onewaytest namespace php OneWayTest namespace delphi Onewaytest -namespace cocoa OneWayTest namespace lua OneWayTest namespace xsd test (uri = 'http://thrift.apache.org/ns/OneWayTest') namespace netcore ThriftAsync.OneWayTest diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift index 3499ab5f862..e025b7f54a6 100644 --- a/test/ThriftTest.thrift +++ b/test/ThriftTest.thrift @@ -22,22 +22,21 @@ */ namespace c_glib TTest -namespace java thrift.test namespace cpp thrift.test -namespace rb Thrift.Test -namespace perl ThriftTest namespace csharp Thrift.Test +namespace delphi Thrift.Test +namespace go thrifttest +namespace java thrift.test namespace js ThriftTest -namespace st ThriftTest +namespace lua ThriftTest +namespace netcore ThriftTest +namespace perl ThriftTest +namespace php ThriftTest namespace py ThriftTest namespace py.twisted ThriftTest -namespace go thrifttest -namespace php ThriftTest -namespace delphi Thrift.Test -namespace cocoa ThriftTest -namespace lua ThriftTest +namespace rb Thrift.Test +namespace st ThriftTest namespace xsd test (uri = 'http://thrift.apache.org/ns/ThriftTest') -namespace netcore ThriftTest // Presence of namespaces and sub-namespaces for which there is // no generator should compile with warnings only From 5c327d7bf629f6c5906759ccc919cf98d27ddf78 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 14 Jan 2019 08:15:33 -0500 Subject: [PATCH 138/756] update changes.md with cocoa info and fix a typo [ci skip] --- CHANGES.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 7d76413cc1d..4f842751771 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,19 +3,26 @@ ## 1.0.0 ### New Languages + ### Deprecated Languages + ### Removed Languages + +- [THRIFT-4719](https://issues.apache.org/jira/browse/THRIFT-4719) - Cocoa language was removed - use swift instead. + ### Breaking Changes + - [THRIFT-4702](https://issues.apache.org/jira/browse/THRIFT-4702) - Java class org.apache.thrift.AutoExpandingBuffer is no longer public - [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - Java changes to UTF-8 handling require JDK 1.7 at a minimum - [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - Java class org.apache.thrift.ShortStack is no longer public - [THRIFT-4720](https://issues.apache.org/jira/browse/THRIFT-4720) - C++03/C++98 support has been removed; also removed boost as a runtime dependency - [THRIFT-4730](https://issues.apache.org/jira/browse/THRIFT-4730) - C++: BoostThreadFactory, PosixThreadFactory, StdThreadFactory removed - [THRIFT-4732](https://issues.apache.org/jira/browse/THRIFT-4732) - C++: CMake build changed to use BUILD_SHARED_LIBS -- [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735] - C++: Removed Qt4 support +- [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735) - C++: Removed Qt4 support ### Known Isues (Blocker or Critical) + ## 0.12.0 Released 2019-JAN-04 From 4eac57abcfc5f6fb591d894fe446add243392557 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 14 Jan 2019 08:10:42 -0500 Subject: [PATCH 139/756] THRIFT-4487: replace gettimeofday implementation on windows --- lib/cpp/src/thrift/windows/GetTimeOfDay.cpp | 77 +++++++++------------ 1 file changed, 33 insertions(+), 44 deletions(-) diff --git a/lib/cpp/src/thrift/windows/GetTimeOfDay.cpp b/lib/cpp/src/thrift/windows/GetTimeOfDay.cpp index 820828f32c7..0a0292c7e34 100644 --- a/lib/cpp/src/thrift/windows/GetTimeOfDay.cpp +++ b/lib/cpp/src/thrift/windows/GetTimeOfDay.cpp @@ -25,12 +25,6 @@ #include #endif -#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 -#else -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL -#endif - #if !defined(__MINGW32__) struct timezone { int tz_minuteswest; /* minutes W of Greenwich */ @@ -43,50 +37,45 @@ int thrift_gettimeofday(struct timeval* tv, struct timezone* tz) { return gettimeofday(tv,tz); } #else -int thrift_gettimeofday(struct timeval* tv, struct timezone* tz) { - FILETIME ft; - unsigned __int64 tmpres(0); - static int tzflag; +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include - if (NULL != tv) { - GetSystemTimeAsFileTime(&ft); +// This code started from a "FREE implementation" posted to Stack Overflow at: +// https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows +// added: assert +// added: error handling +// added: C++ style casts +int thrift_gettimeofday(struct timeval * tp, struct timezone * tzp) +{ + // We don't fill it in so prove nobody is looking for the data + assert(tzp == NULL); - tmpres |= ft.dwHighDateTime; - tmpres <<= 32; - tmpres |= ft.dwLowDateTime; + // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's + // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) + // until 00:00:00 January 1, 1970 + static const uint64_t EPOCH = static_cast(116444736000000000ULL); - /*converting file time to unix epoch*/ - tmpres -= DELTA_EPOCH_IN_MICROSECS; - tmpres /= 10; /*convert into microseconds*/ - tv->tv_sec = (long)(tmpres / 1000000UL); - tv->tv_usec = (long)(tmpres % 1000000UL); - } + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; - if (NULL != tz) { - if (!tzflag) { - _tzset(); - tzflag++; + GetSystemTime( &system_time ); + if (!SystemTimeToFileTime( &system_time, &file_time )) { + DWORD lastError = GetLastError(); + std::stringstream ss; + ss << "SystemTimeToFileTime failed: 0x" << std::hex << lastError; + using apache::thrift::transport::TTransportException; + throw TTransportException(TTransportException::INTERNAL_ERROR, ss.str()); } + time = static_cast(file_time.dwLowDateTime ) ; + time += static_cast(file_time.dwHighDateTime) << 32; - long time_zone(0); - errno_t err(_get_timezone(&time_zone)); - if (err == NO_ERROR) { - tz->tz_minuteswest = time_zone / 60; - } else { - return -1; - } - - int day_light(0); - err = (_get_daylight(&day_light)); - if (err == NO_ERROR) { - tz->tz_dsttime = day_light; - return 0; - } else { - return -1; - } - } - - return 0; + tp->tv_sec = static_cast((time - EPOCH) / 10000000L); + tp->tv_usec = static_cast(system_time.wMilliseconds * 1000); + return 0; } #endif From e20ab3e2371803e69b321f13116e04a926ca39be Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Sun, 6 Jan 2019 15:08:58 -0500 Subject: [PATCH 140/756] THRIFT-4725: Change Return Type Signature of Process Methods --- CHANGES.md | 1 + lib/java/README.md | 5 +++++ lib/java/src/org/apache/thrift/TAsyncProcessor.java | 13 +++++++++---- .../src/org/apache/thrift/TBaseAsyncProcessor.java | 11 +++++------ lib/java/src/org/apache/thrift/TBaseProcessor.java | 7 +++---- .../org/apache/thrift/TMultiplexedProcessor.java | 7 ++++--- lib/java/src/org/apache/thrift/TProcessor.java | 4 +--- .../src/org/apache/thrift/server/TSimpleServer.java | 4 +--- .../org/apache/thrift/server/TThreadPoolServer.java | 3 ++- .../org/apache/thrift/TestMultiplexedProcessor.java | 3 +-- 10 files changed, 32 insertions(+), 26 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4f842751771..2dd7f0afcf2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -19,6 +19,7 @@ - [THRIFT-4730](https://issues.apache.org/jira/browse/THRIFT-4730) - C++: BoostThreadFactory, PosixThreadFactory, StdThreadFactory removed - [THRIFT-4732](https://issues.apache.org/jira/browse/THRIFT-4732) - C++: CMake build changed to use BUILD_SHARED_LIBS - [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735) - C++: Removed Qt4 support +- [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - Java change return type signature of 'process' methods ### Known Isues (Blocker or Critical) diff --git a/lib/java/README.md b/lib/java/README.md index 0b5f0d802de..505746508ce 100644 --- a/lib/java/README.md +++ b/lib/java/README.md @@ -164,6 +164,11 @@ http://gradle.org/ # Breaking Changes +## 1.0 + +The signature of the 'process' method in TAsyncProcessor and TProcessor has +changed to remove a boolean return type and to instead rely on Exceptions. + ## 0.12.0 The access modifier of the AutoExpandingBuffer class has been changed from diff --git a/lib/java/src/org/apache/thrift/TAsyncProcessor.java b/lib/java/src/org/apache/thrift/TAsyncProcessor.java index 533e74d86c7..66f76889626 100644 --- a/lib/java/src/org/apache/thrift/TAsyncProcessor.java +++ b/lib/java/src/org/apache/thrift/TAsyncProcessor.java @@ -21,8 +21,13 @@ import org.apache.thrift.server.AbstractNonblockingServer.AsyncFrameBuffer; public interface TAsyncProcessor { - /** - * Implementations must call fb.responseReady() once processing is complete - */ - public boolean process(final AsyncFrameBuffer fb) throws TException; + /** + * Process a single frame. + + * Note: Implementations must call fb.responseReady() once processing + * is complete + * + * @throws TException if the frame cannot be processed + */ + public void process(final AsyncFrameBuffer fb) throws TException; } diff --git a/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java b/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java index 0ab1827dc20..f13f068ef46 100644 --- a/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java +++ b/lib/java/src/org/apache/thrift/TBaseAsyncProcessor.java @@ -43,7 +43,7 @@ public TBaseAsyncProcessor(I iface, Map Date: Sat, 12 Jan 2019 02:15:05 +0800 Subject: [PATCH 141/756] THRIFT-4733: Fix test unix socket address already in use --- lib/py/test/test_sslsocket.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/py/test/test_sslsocket.py b/lib/py/test/test_sslsocket.py index f1344e57d24..598c174dcfe 100644 --- a/lib/py/test/test_sslsocket.py +++ b/lib/py/test/test_sslsocket.py @@ -213,6 +213,7 @@ def test_unix_domain_socket(self): return fd, path = tempfile.mkstemp() os.close(fd) + os.unlink(path) try: server = self._server_socket(unix_socket=path, keyfile=SERVER_KEY, certfile=SERVER_CERT) self._assert_connection_success(server, path=path, cert_reqs=ssl.CERT_NONE) From f61d9e52827ec14f35dde0f5c0740837a5572c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20B=C3=BCrckert?= Date: Mon, 14 Jan 2019 14:36:22 +0100 Subject: [PATCH 142/756] THRIFT-4737: fixed THRIFT-4737: [added beforeSend to add customHeaders to jqXHR in jqRequest] Client: [lib/js] locally tested - custom headers where missing when using jq. So I added these lines to fix it. --- lib/js/src/thrift.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 9bf8127dee5..fad24d68ef4 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -438,7 +438,12 @@ Thrift.TXHRTransport.prototype = { } }, context: client, - success: jQuery.makeArray(args).pop() + success: jQuery.makeArray(args).pop(), + beforeSend: function (xreq) { + Object.keys(thriftTransport.customHeaders).forEach(function (prop) { + xreq.setRequestHeader(prop, thriftTransport.customHeaders[prop]); + }); + } }); return jqXHR; From bbc137787496154fb794b210ad783899f2d3092f Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 14 Jan 2019 12:07:10 -0500 Subject: [PATCH 143/756] THRIFT-4691: ensure CPAN module runs unit tests --- configure.ac | 2 +- lib/perl/MANIFEST.SKIP | 5 +++-- lib/perl/Makefile.PL | 13 +++++++++++++ lib/perl/Makefile.am | 4 ++-- lib/perl/build-cpan-dist.sh | 5 ++++- lib/perl/{test => t}/Makefile.am | 0 lib/perl/{test => t}/memory_buffer.t | 0 lib/perl/{test => t}/multiplex.t | 0 lib/perl/{test => t}/processor.t | 0 9 files changed, 23 insertions(+), 6 deletions(-) rename lib/perl/{test => t}/Makefile.am (100%) rename lib/perl/{test => t}/memory_buffer.t (100%) rename lib/perl/{test => t}/multiplex.t (100%) rename lib/perl/{test => t}/processor.t (100%) diff --git a/configure.ac b/configure.ac index d229734a8ad..c5683ec7720 100755 --- a/configure.ac +++ b/configure.ac @@ -821,7 +821,7 @@ AC_CONFIG_FILES([ lib/nodejs/Makefile lib/nodets/Makefile lib/perl/Makefile - lib/perl/test/Makefile + lib/perl/t/Makefile lib/php/Makefile lib/php/test/Makefile lib/dart/Makefile diff --git a/lib/perl/MANIFEST.SKIP b/lib/perl/MANIFEST.SKIP index 7963b42ad80..9b044509e50 100644 --- a/lib/perl/MANIFEST.SKIP +++ b/lib/perl/MANIFEST.SKIP @@ -8,6 +8,7 @@ Makefile Makefile.am Makefile.in pm_to_blib -test/Makefile.am -test/Makefile.in +t/Makefile +t/Makefile.am +t/Makefile.in tools/FixupDist.pl diff --git a/lib/perl/Makefile.PL b/lib/perl/Makefile.PL index bdeaad2b7bc..5e60ab40aee 100644 --- a/lib/perl/Makefile.PL +++ b/lib/perl/Makefile.PL @@ -33,4 +33,17 @@ WriteMakefile( ABSTRACT => 'Apache Thrift is a software framework for scalable c 'Bit::Vector' => 0, 'Class::Accessor' => 0 }, +# SIGN => 1, VERSION_FROM => 'lib/Thrift.pm' ); + +# THRIFT-4691 +package MY; # so that "SUPER" works right +sub test { + # Adds gen-perl and gen-perl2 to the test execution as include paths + # Could not find anything in MakeMaker that would do this... + my @result; + for (@result = shift->SUPER::test(@_)) { + s/\$\(TEST_FILES\)/-Igen-perl -Igen-perl2 \$(TEST_FILES)/ig; + } + @result; +} diff --git a/lib/perl/Makefile.am b/lib/perl/Makefile.am index fa0f16b8af0..abae1e77fe4 100644 --- a/lib/perl/Makefile.am +++ b/lib/perl/Makefile.am @@ -17,7 +17,7 @@ # under the License. # -SUBDIRS = test +SUBDIRS = t Makefile-perl.mk : Makefile.PL $(PERL) Makefile.PL MAKEFILE=Makefile-perl.mk INSTALLDIRS=$(INSTALLDIRS) INSTALL_BASE=$(PERL_PREFIX) @@ -95,7 +95,7 @@ BUILT_SOURCES = $(PERL_GEN) check-local: $(PERL_GEN) $(PERL) -Iblib/lib -I@abs_srcdir@ -I@builddir@/gen-perl2 -I@builddir@/gen-perl \ - @abs_srcdir@/test.pl @abs_srcdir@/test/*.t + @abs_srcdir@/test.pl @abs_srcdir@/t/*.t $(THRIFTTEST_GEN): $(THRIFT_IF) $(THRIFT) $(THRIFT) --gen perl $< diff --git a/lib/perl/build-cpan-dist.sh b/lib/perl/build-cpan-dist.sh index ae22e7e623c..ac0ff0bc0b3 100755 --- a/lib/perl/build-cpan-dist.sh +++ b/lib/perl/build-cpan-dist.sh @@ -12,9 +12,10 @@ rm -rf Thrift-* # setup cpan without a prompt echo | cpan -cpan install HTTP::Date +cpan install HTTP::Date Log::Log4perl cpan install CPAN cpan install CPAN::Meta ExtUtils::MakeMaker JSON::PP +# cpan install Module::Signature perl Makefile.PL rm MYMETA.yml @@ -47,6 +48,8 @@ if [[ "$DISTDIR" != "$NEWDIR" ]]; then fi cd $DISTDIR cp -p ../Makefile.PL . +cp -pr ../gen-perl . +cp -pr ../gen-perl2 . perl ../tools/FixupDist.pl cd .. tar cvzf $DISTFILE $DISTDIR diff --git a/lib/perl/test/Makefile.am b/lib/perl/t/Makefile.am similarity index 100% rename from lib/perl/test/Makefile.am rename to lib/perl/t/Makefile.am diff --git a/lib/perl/test/memory_buffer.t b/lib/perl/t/memory_buffer.t similarity index 100% rename from lib/perl/test/memory_buffer.t rename to lib/perl/t/memory_buffer.t diff --git a/lib/perl/test/multiplex.t b/lib/perl/t/multiplex.t similarity index 100% rename from lib/perl/test/multiplex.t rename to lib/perl/t/multiplex.t diff --git a/lib/perl/test/processor.t b/lib/perl/t/processor.t similarity index 100% rename from lib/perl/test/processor.t rename to lib/perl/t/processor.t From ee006ecb0da884e7d70f6f1e87d6c4b27197e55c Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 14 Jan 2019 15:57:43 -0500 Subject: [PATCH 144/756] Fix languages file left column readme links. [ci skip] --- LANGUAGES.md | 56 ++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/LANGUAGES.md b/LANGUAGES.md index 4b5e200167d..67f55657ef0 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -34,7 +34,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u -ActionScript +ActionScript 0.3.0 ActionScript 3 @@ -45,7 +45,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u ActionScript -C (glib) +C (glib) 0.6.0 YesYes 2.48.22.56.0 @@ -56,7 +56,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u C (glib) -C++ +C++ 0.2.0 YesYes C++98 (through 0.12.0)C++11 (after 0.12.0) @@ -67,7 +67,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u C++ -C# +C# 0.2.0 Yes .NET 3.5 / mono 3.2.8.0.NET 4.6.1 / mono 4.6.2.7 @@ -78,7 +78,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u C# (.NET) -Cocoa +Cocoa 0.2.0 unknown @@ -89,7 +89,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Cocoa -Common LISP +Common LISP 0.12.0 Yes SBCL 1.4.5SBCL 1.4.15 @@ -100,7 +100,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Common LISP -Dlang +Dlang 0.9.0 Yes 2.075.12.083.2 @@ -111,7 +111,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u D -Dart +Dart 0.10.0 Yes 1.22.11.24.3 @@ -122,7 +122,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Dart -Delphi +Delphi 0.8.0 2010unknown @@ -133,7 +133,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Delphi -.NET Core +.NET Core 0.11.0 Yes 2.1.42.2.101 @@ -144,7 +144,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u .NET Core -Erlang +Erlang 0.3.0 Yes 18.320.0.4 @@ -155,7 +155,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Erlang -Go +Go 0.7.0 Yes 1.7.61.11.4 @@ -166,7 +166,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Go -Haskell +Haskell 0.5.0 YesYes 7.10.38.0.2 @@ -177,7 +177,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Haskell -Haxe +Haxe 0.9.3 Yes 3.2.13.4.4 @@ -188,7 +188,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Haxe -Java (SE) +Java (SE) 0.2.0 YesYes 1.8.0_1511.8.0_191 @@ -199,7 +199,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Java SE -Java (ME) +Java (ME) 0.5.0 unknown @@ -210,7 +210,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Java ME -Javascript +Javascript 0.3.0 Yes unknown @@ -221,7 +221,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Javascript -Lua +Lua 0.9.2 Yes 5.1.55.2.4 @@ -232,7 +232,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Lua -node.js +node.js 0.6.0 Yes 6.x8.x @@ -243,7 +243,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u node.js -node.ts +node.ts 0.12.0 Yes 3.1.6 @@ -254,7 +254,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u node.ts -OCaml +OCaml 0.2.0 4.04.0 @@ -265,7 +265,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u OCaml -Perl +Perl 0.2.0 Yes 5.22.15.26.1 @@ -276,7 +276,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Perl -PHP +PHP 0.2.0 Yes 7.0.227.2.10 @@ -287,7 +287,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u PHP -Python +Python 0.2.0 YesYes 2.7.12, 3.5.22.7.15rc1, 3.6.7 @@ -298,7 +298,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Python -Ruby +Ruby 0.2.0 Yes 2.3.1p1122.5.1p57 @@ -309,7 +309,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Ruby -Rust +Rust 0.11.0 Yes 1.17.01.30.0 @@ -320,7 +320,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Rust -Smalltalk +Smalltalk 0.2.0 unknown @@ -331,7 +331,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Smalltalk -Swift +Swift 0.12.0 Yes 4.2.1 From f86845e8ed622e7e3b7c87f00f16729ee6cc524d Mon Sep 17 00:00:00 2001 From: Mustafa Senol Cosar Date: Wed, 5 Dec 2018 17:50:18 +0300 Subject: [PATCH 145/756] THRIFT-4675: Generate Int64 constants for js --- CHANGES | 2924 ++++++++++ .../cpp/src/thrift/generate/t_js_generator.cc | 69 +- configure.ac | 1 + lib/js/Gruntfile.js | 54 +- lib/js/README.md | 5 + lib/js/package-lock.json | 1307 ++++- lib/js/package.json | 5 +- lib/js/src/thrift.js | 69 +- lib/js/test/build.xml | 5 +- lib/js/test/test-deep-constructor.html | 1 + lib/js/test/test-es6.html | 3 + lib/js/test/test-int64.html | 55 + lib/js/test/test-int64.js | 91 + lib/js/test/test-nojq.html | 3 + lib/js/test/test.html | 3 + lib/js/test/test.js | 40 +- lib/js/test/test_handler.js | 5 +- lib/js/test/testws.html | 3 + lib/nodejs/test/int64.test.js | 81 + lib/nodejs/test/testAll.sh | 3 + lib/nodets/Makefile.am | 1 + lib/nodets/test/int64.test.ts | 81 + lib/nodets/test/test-cases.ts | 9 +- lib/nodets/test/testAll.sh | 4 + lib/nodets/test/test_handler.ts | 5 +- lib/ts/.gitignore | 2 + lib/ts/Gruntfile.js | 163 + lib/ts/Makefile.am | 30 + lib/ts/dist/thrift.js | 0 lib/ts/dist/thrift.min.js | 1 + lib/ts/package-lock.json | 4962 +++++++++++++++++ lib/ts/package.json | 30 + lib/ts/test/build.xml | 250 + lib/ts/test/phantom-client.ts | 352 ++ lib/ts/test/server_http.js | 55 + lib/ts/test/test-int64.html | 46 + lib/ts/test/test-int64.ts | 94 + lib/ts/test/test.html | 53 + lib/ts/test/test.ts | 342 ++ lib/ts/test/test_handler.js | 202 + lib/ts/tsconfig.json | 31 + package-lock.json | 9 + package.json | 2 + test/Int64Test.thrift | 34 + 44 files changed, 11418 insertions(+), 67 deletions(-) create mode 100644 CHANGES create mode 100644 lib/js/test/test-int64.html create mode 100644 lib/js/test/test-int64.js create mode 100644 lib/nodejs/test/int64.test.js create mode 100644 lib/nodets/test/int64.test.ts create mode 100644 lib/ts/.gitignore create mode 100644 lib/ts/Gruntfile.js create mode 100644 lib/ts/Makefile.am create mode 100644 lib/ts/dist/thrift.js create mode 100644 lib/ts/dist/thrift.min.js create mode 100644 lib/ts/package-lock.json create mode 100644 lib/ts/package.json create mode 100755 lib/ts/test/build.xml create mode 100644 lib/ts/test/phantom-client.ts create mode 100644 lib/ts/test/server_http.js create mode 100644 lib/ts/test/test-int64.html create mode 100644 lib/ts/test/test-int64.ts create mode 100755 lib/ts/test/test.html create mode 100644 lib/ts/test/test.ts create mode 100644 lib/ts/test/test_handler.js create mode 100644 lib/ts/tsconfig.json create mode 100644 test/Int64Test.thrift diff --git a/CHANGES b/CHANGES new file mode 100644 index 00000000000..4b4997ef368 --- /dev/null +++ b/CHANGES @@ -0,0 +1,2924 @@ +Apache Thrift Changelog + +================================================================================ +Thrift 0.13.0 +-------------------------------------------------------------------------------- +## Breaking Changes (since 0.12.0) + * [THRIFT-4675] - Javascript now uses node-int64 for 64 bit integer constants + +================================================================================ +Thrift 0.12.0 +-------------------------------------------------------------------------------- +## New Languages + * Common LISP (cl) + * Swift + * Typescript (nodets) + +## Deprecated Languages + * Cocoa + +## Breaking Changes (since 0.11.0) + * [THRIFT-4529] - Rust enum variants are now camel-cased instead of uppercased to conform to Rust naming conventions + * [THRIFT-4448] - Support for golang 1.6 and earlier has been dropped. + * [THRIFT-4474] - PHP now uses the PSR-4 loader by default instead of class maps. + * [THRIFT-4532] - method signatures changed in the compiler's t_oop_generator. + * [THRIFT-4648] - The C (GLib) compiler's handling of namespaces has been improved. + +## Known Issues (Blocker or Critical) + * [THRIFT-4037] - build: use a single build system for thrift + * [THRIFT-4119] - build: bootstrap.sh is missing from source tarball + * [THRIFT-3289] - csharp: socket exhaustion in csharp implementation + * [THRIFT-3029] - cocoa: Getters for fields defined with uppercase names do not work + * [THRIFT-3325] - cocoa: Extended services aren't subclasses in generated Cocoa + * [THRIFT-4116] - cocoa: Thrift de-capitalizes the name of IsSet property in Cocoa + * [THRIFT-3877] - cpp: the http implementation is not standard; interop with other languages is spotty at best + * [THRIFT-4180] - cpp: Impossible to build Thrift C++ library for Android (NDK) + * [THRIFT-4384] - cpp: Using multiple async services simultaneously is not thread-safe + * [THRIFT-3108] - haskell: Defaulted struct parameters on a service generates invalid Haskell + * [THRIFT-3990] - nodejs: Exception swallowed by deserialization function + * [THRIFT-4214] - nodejs: map key treated as hex value in JavaScript + * [THRIFT-4602] - nodejs: ERROR in ./node_modules/thrift/lib/nodejs/lib/thrift/connection.js Module not found: Error: Can't resolve 'child_process' + * [THRIFT-4639] - nodejs: Sequence numbering for multiplexed protocol broken + * [THRIFT-1310] - php: sequence and reconnection management issues + * [THRIFT-1538] - php: Error during deserialization int64 on 32-bit architecture + * [THRIFT-1580] - php: thrift type i64 java to php serialize/deserealize not working + * [THRIFT-1950] - php: PHP gets stuck in infinite loop + * [THRIFT-2954] - python: sending int or float in a double field breaks the connection + * [THRIFT-4080] - python: unix sockets can get stuck forever + * [THRIFT-4281] - python: generated code is out of order and causes load issues + * [THRIFT-4677] - py3: UnicodeDecideError in Python3 + +## Build Process + * [THRIFT-4067] - Windows thrift compiler distributed on the apache web site has runtime dependencies + * [THRIFT-4308] - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang + * [THRIFT-4579] - Use Ubuntu Bionic (18.04 LTS) for CI builds instead of Artful (17.10) + * [THRIFT-4508] - Define CI operating system coverage rules for the project and (hopefully) simplify CI a little more + * [THRIFT-4397] - ubuntu install instructions broken on 16.04 + * [THRIFT-4545] - Appveyor builds are failing due to a haskell / cabal update in chocolatey + * [THRIFT-4452] - optimize Dockerfile (only onetime apt-get update) + * [THRIFT-4440] - rm `build/docker/ubuntu-trusty/Dockerfile.orig` + * [THRIFT-4352] - Ubuntu Artful doesn't appear to be compatible with Thrift and Haxe 3.4.2 + * [THRIFT-4666] - DLang Client Pool Test fails sporadically + * [THRIFT-4676] - CL tutorial build fails sporadically + * [THRIFT-4456] - Make haxelib download quiet so it doesn't blow up the build log + * [THRIFT-4605] - bootstrap.sh fails if automake=1.16.1 + +## c_glib + * [THRIFT-4648] - The C (GLib) compiler's handling of namespaces has been improved. + * [THRIFT-4622] - glibC compilation issue + * [THRIFT-4671] - c glib is unable to handle client close unexpectedly + +## cl (new language support in 0.12.0) + * [THRIFT-82] - Common Lisp support + +## csharp + * [THRIFT-4558] - reserved Csharp keywords are not escaped in some cases + * [THRIFT-4637] - C# async mode generates incorrect code with inherited services + * [THRIFT-4672] - IAsyncResult style methods not being supported by certain transports leads to issues in mixed ISync/IAsync use cases + * [THRIFT-4539] - Allow TBufferedTransport to be used as base class + * [THRIFT-4535] - XML docs; code cleanup (tabs->spaces; String->string) + * [THRIFT-4492] - protected ExceptionType type member of TApplicationException cannot be accessed + * [THRIFT-4446] - JSONProtocol Base64 Encoding Trims Padding + * [THRIFT-4455] - Missing dispose calls in ThreadedServer & ThreadpoolServer + * [THRIFT-4609] - keep InnerException wherever appropriate + * [THRIFT-4673] - IAsyncResult not supported by layered transports (buffered/framed) + +## cpp + * [THRIFT-4476] - Typecasting problem on list items + * [THRIFT-4465] - TNonblockingServer throwing THRIFT LOGGER: TConnection::workSocket(): THRIFT_EAGAIN (unavailable resources) + * [THRIFT-4680] - TBufferTransports.h does not compile under Visual Studio 2017 + * [THRIFT-4618] - TNonblockingServer crash because of limitation of select() + * [THRIFT-4620] - TZlibTransport.cpp doesn't ensure that there is enough space for the zlib flush marker in the buffer. + * [THRIFT-4571] - ZeroMQ contrib library needs a refresh + * [THRIFT-4559] - TSSLServerSocket incorrectly prints errors + * [THRIFT-4578] - Move `TAsyncProtocolProcessor` into main thrift library + * [THRIFT-4418] - evhttp_connection_new is deprecated; use evhttp_connection_base_new + +## compiler + * [THRIFT-4644] - Compiler cannot be compiled on macOS(maybe also on other platforms with clang) + * [THRIFT-4531] - Thrift generates wrong Python code for immutable structures with optional members + * [THRIFT-4513] - thrift generated code is not stable for constants + * [THRIFT-4532] - Avoid updating Thrift compiler generated code if the output has not changed + * [THRIFT-4400] - Visual Studio Compiler project should link runtime statically in release builds + * [THRIFT-4399] - plugin.thrift t_const_value is not used as a union in C++ code -- fix this + * [THRIFT-4496] - Dealing with language keywords in Thrift (e.g. service method names) + * [THRIFT-4393] - repeated runs of compiler produce different binary output at plugin interface + +## dlang + * [THRIFT-4478] - Thrift will not build with dlang 2.078 or later + * [THRIFT-4503] - dlang servers logError on normal client disconnection + * [THRIFT-4308] - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang + +## dart + * [THRIFT-4646] - Effective Dart and Exceptions + * [THRIFT-4439] - Shouldn't download dart.deb directly. + +## delphi + * [THRIFT-4562] - Calling wrong exception CTOR leads to "call failed: unknown result" instead of the real exception being thrown + * [THRIFT-4554] - uncompileable code with member names that are also types under specific conditions + * [THRIFT-4422] - Add Async implementation via IFuture + * [THRIFT-4485] - Possible invalid ptr AV with overlapped read/write on pipes + * [THRIFT-4549] - Thrift exceptions should derive from TException + * [THRIFT-4540] - buffered transport broken when trying to re-open a formerly closed transport + * [THRIFT-4473] - Move Thrift.Console.pas out of the Library + * [THRIFT-4490] - Allow a default service as fallback for multiplex processors connected by old clients + * [THRIFT-4454] - Large writes/reads may cause range check errors in debug mode + * [THRIFT-4461] - Compiler directive should match Delphi XE4 + * [THRIFT-4462] - First line in Console duplicated + * [THRIFT-4642] - FPU ctrl word settings may cause an unexpected "denormalized" error + * [THRIFT-4589] - HTTP client timeouts are a) incomplete and b) not used at all + * [THRIFT-4590] - running the test client using HTTP transport leads to "CoInitialize not called" + +## erlang + * [THRIFT-4497] - Erlang records should use map() for map type + * [THRIFT-4495] - Erlang records should allow 'undefined' for non-required fields + * [THRIFT-4580] - Fix erlang tutorial unpack on Windows + * [THRIFT-4582] - Ubuntu Xenial erlang 18.3 "make check" fails + +## golang + * [THRIFT-4448] - Support for golang 1.6 and earlier has been dropped. + * [THRIFT-4253] - Go generator assigns strings to field in const instead of pointers. + * [THRIFT-4573] - Unions Field Count Does Not Consider Binary + * [THRIFT-4447] - Golang: Panic on p.c.Call when using deprecated initializers + * [THRIFT-4650] - Required field incorrectly marked as set when fieldType does not match + * [THRIFT-4486] - Golang: -remote.go client cleanup + * [THRIFT-4537] - TSimpleServer can exit Accept loop with lock still acquired + * [THRIFT-4516] - Add support for go 1.10 + * [THRIFT-4421] - golang tests rely on gomock, which has change behaviour, causing tests to fail + * [THRIFT-4626] - Communication crash when using binary/compact protocol and zlib transport + * [THRIFT-4659] - golang race detected when closing listener socket + +## haskell + * [THRIFT-4634] - Haskell builds with older cabal cannot reconcile complex version requirements + +## java + * [THRIFT-4259] - Thrift does not compile due to Ant Maven task errors + * [THRIFT-1418] - Compiling Thrift from source: Class org.apache.tools.ant.taskdefs.ConditionTask doesn't support the nested "typefound" element + * [THRIFT-4530] - proposal: add nullability annotations to generated Java code + * [THRIFT-4614] - Generate missing @Nullable annotations for Java iterator getters + * [THRIFT-4555] - Getter of binary field in Java creates unnecessary copy + * [THRIFT-3983] - libthrift is deployed on central with pom packaging instead of jar + * [THRIFT-4294] - Java Configure Fails for Ant >= 1.10 + * [THRIFT-4178] - Java libraries missing from package when using cmake + * [THRIFT-4120] - pom files are not generated or provided in the build + * [THRIFT-1507] - Maven can't download resource from central when behind a proxy and won't use local repository + * [THRIFT-4556] - Optional rethrow of unhandled exceptions in java processor + * [THRIFT-4337] - Able to set keyStore and trustStore as InputStream in the TSSLTransportFactory.TSSLTransportParameters + * [THRIFT-4566] - Pass message of unhandled exception to optional rethrow. + * [THRIFT-4506] - Remove assertion in Java SASL code that would be ignored in release builds + * [THRIFT-4470] - Include popular IDE file templates to gitignore + * [THRIFT-4429] - Make TThreadPoolServer.executorService_ available in inherited classes and refactor methods to be able customization + * [THRIFT-3769] - Fix logic of THRIFT-2268 + * [THRIFT-4494] - Increase Java Socket Buffer Size + * [THRIFT-4499] - Remove Magic Number In TFIleTransport + +## js + * [THRIFT-4406] - JavaScript: Use modern Promise implementations + * [THRIFT-4625] - let / const variable decorators for es6 compiler + * [THRIFT-4653] - ES6 Classes + * [THRIFT-4592] - JS: readI32 performance on large arrays is very poor in Chrome + * [THRIFT-4509] - js and nodejs libraries need to be refreshed with current libraries + * [THRIFT-4403] - thrift.js: Incorrect usage of 'this' in TWebSocketTransport.__onOpen + * [THRIFT-4436] - Deserialization of nested list discards content + * [THRIFT-4437] - JS WebSocket client callbacks invoked twice on parallel requests + * [THRIFT-4679] - Duplicate declaration of InputBufferUnderrunError in lib/nodejs/lib/thrift/json_protocol.js + * [THRIFT-4551] - Add prettier for consistent JS code formatting + +## lua + * [THRIFT-4591] - lua client uses two write() calls per framed message send + * [THRIFT-3863] - Can't "make install" Lua Library + +## netcore + * [THRIFT-4524] - .NET Core Server doesn't close properly when cancelled + * [THRIFT-4434] - Update .NET Core components, add tests for .Net Core library and .Net Core compiler, fix bugs and build process + * [THRIFT-4446] - JSONProtocol Base64 Encoding Trims Padding + +## node.js + * [THRIFT-4225] - Error handling malformed arguments leaks memory, corrupts transport buffers causing next RPC to fail + * [THRIFT-3950] - Memory leak while calling oneway method + * [THRIFT-3143] - add typescript directory support + * [THRIFT-4564] - TBufferedTransport can leave corrupt data in the buffer + * [THRIFT-4647] - Node.js Fileserver webroot path + * [THRIFT-4489] - Unix domain socket support for NodeJS client + * [THRIFT-4443] - node.js json_protocol throws error in skip function + * [THRIFT-4604] - NodeJS: Expose Int64 from browser.js for consumption by browser + * [THRIFT-4480] - NodeJS warning on binary_protocol writeMessageEnd when seqid = 0 + +## perl + * [THRIFT-4382] - Replace the use of Perl Indirect Object Syntax calls to new() + * [THRIFT-4471] - Thrift CPAN release is missing Makefile.PL and the clients are unable to build the module + * [THRIFT-4416] - Perl CPAN Packaging Improvements + +## php + * [THRIFT-4474] - PHP generator use PSR-4 default + * [THRIFT-4463] - PHP generated code match PSR-2 + * [THRIFT-4373] - Extending Thrift class results in "Attempt serialize from non-Thrift object" + * [THRIFT-4354] - TSocket block on read + * [THRIFT-4423] - migrate php library to psr-4 + * [THRIFT-4656] - infinite loop in latest PHP library + * [THRIFT-4477] - TBufferedTransport must have underlying transport + * [THRIFT-4475] - lib/php/test should be checked for PSR-2 + * [THRIFT-4498] - add phpcs back + * [THRIFT-4460] - php library use PSR-2 + * [THRIFT-4641] - TCurlClient doesn't check for HTTP status code + * [THRIFT-4645] - TCurlClient: show actual error message when throwing TTransportException + * [THRIFT-4674] - Add stream context support into PHP/THttpClient + * [THRIFT-4459] - reduce php library directory depth + +## python + * [THRIFT-4670] - Twisted, slots, and void method fails with "object has no attribute 'success'" + * [THRIFT-4464] - Potentially server-crashing typo in Python TNonblockingServer + * [THRIFT-4548] - Supporting TBinaryProtocolAccelerated protocol when using TMultiplexedProcessor in Python + * [THRIFT-4577] - Outdated cipher string in python unit test + * [THRIFT-4505] - python build on Vagrant Windows boxes fails + * [THRIFT-4621] - THeader for Python + * [THRIFT-4668] - make socket backlog configurable for python + * [THRIFT-4561] - Python: cleanup socket timeout settings + +## ruby + * [THRIFT-4289] - Thrift RSpec test suite fails with Ruby 2.4.x due to Fixnum deprecation + * [THRIFT-4342] - Support ruby rspec 3 + * [THRIFT-4525] - Add ssl socket option to ruby cross tests + * [THRIFT-4450] - Add seek support to TCompactInputProtocol in Rust + * [THRIFT-4631] - Codegen Creates Invalid Ruby for Recursive Structs + * [THRIFT-4472] - Fix the genspec for ruby so it does not complain about an invalid license + +## rust + * [THRIFT-4662] - Rust const string calls function at compile time + * [THRIFT-4661] - Rust enum name wrong case in generated structs + * [THRIFT-4617] - Avoid generating conflicting struct names in Rust code + * [THRIFT-4529] - Rust generation should include #![allow(non_snake_case)] or force conform to Rust style guidelines + * [THRIFT-4390] - Rust binary protocol and buffered transport cannot handle writes above 4096 bytes + * [THRIFT-4419] - Rust framed transport cannot handle writes above 4096 bytes + * [THRIFT-4658] - Rust's TBinaryInputProtocol fails when strict is false + * [THRIFT-4187] - Dart -> Rust Framed cross tests fail + * [THRIFT-4664] - Rust cannot create ReadHalf/WriteHalf to implement custom tranports + * [THRIFT-4665] - Keep Rust library up-to-date on crates.io + +## swift (new language support in 0.12.0) + * [THRIFT-3773] - Swift Library + +## test suite + * [THRIFT-4515] - Gracefully shutdown cross-test servers to fully test teardown + * [THRIFT-4085] - Add .NET Core to the make cross standard test suite + * [THRIFT-4358] - Add unix domain sockets in ruby to cross test - code exists + +## typescript (new language support in 0.12.0) + * [THRIFT-3143] - add typescript directory support + +================================================================================ +Thrift 0.11.0 +-------------------------------------------------------------------------------- +## Sub-task + * [THRIFT-2733] - Erlang coding standards + * [THRIFT-2740] - Perl coding standards + * [THRIFT-3610] - Streamline exception handling in Python server handler + * [THRIFT-3686] - Java processor should report internal error on uncaught exception + * [THRIFT-4049] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4053] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types + * [THRIFT-4136] - Align is_binary() method with is_string() to simplify those checks + * [THRIFT-4137] - Fix remaining undefined behavior invalid vptr casts in Thrift Compiler + * [THRIFT-4138] - Fix remaining undefined behavior invalid vptr casts in C++ library + * [THRIFT-4296] - Fix Ubuntu Xenial build environment for the python language + * [THRIFT-4298] - Fix Ubuntu Xenial build environment for the go 1.6 language + * [THRIFT-4299] - Fix Ubuntu Xenial build environment for the D language + * [THRIFT-4300] - Fix make cross in Ubuntu Xenial docker environment, once all language support issues are fixed + * [THRIFT-4302] - Fix Ubuntu Xenial make cross testing for lua and php7 + * [THRIFT-4398] - Update EXTRA_DIST for "make dist" + +## Bug + * [THRIFT-381] - Fail fast if configure detects C++ problems + * [THRIFT-1677] - MinGW support broken + * [THRIFT-1805] - Thrift should not swallow ALL exceptions + * [THRIFT-2026] - Fix TCompactProtocol 64 bit builds + * [THRIFT-2642] - Recursive structs don't work in python + * [THRIFT-2889] - stable release 0.9.2, erlang tutorial broken + * [THRIFT-2913] - Ruby Server Thrift::ThreadPoolServer should serve inside a thread + * [THRIFT-2998] - Node.js: Missing header from http request + * [THRIFT-3000] - .NET implementation has trouble with mixed IP modes + * [THRIFT-3281] - Travis CI build passed but the log says BUILD FAILED + * [THRIFT-3358] - Makefile:1362: *** missing separator. Stop. + * [THRIFT-3600] - Make TTwisted server send exception on unexpected handler error + * [THRIFT-3602] - Make Tornado server send exception on unexpected handler error + * [THRIFT-3657] - D TFileWriterTransport close should use non-priority send + * [THRIFT-3700] - Go Map has wrong default value when optional + * [THRIFT-3703] - Unions Field Count Does Not Consider Map/Set/List Fields + * [THRIFT-3730] - server log error twice + * [THRIFT-3778] - go client can not pass method parameter to server of other language if no field_id is given + * [THRIFT-3784] - thrift-maven-plugin generates invalid include directories for IDL in dependency JARs + * [THRIFT-3801] - Node Thrift client throws exception with multiplexer and responses that are bigger than a single buffer + * [THRIFT-3821] - TMemoryBuffer buffer may overflow when resizing + * [THRIFT-3832] - Thrift version 0.9.3 example on Windows, Visual Studio, linking errors during compiling + * [THRIFT-3847] - thrift/config.h includes a #define for VERSION which will likely conflict with existing user environment or code + * [THRIFT-3873] - Fix various build warnings when using Visual Studio + * [THRIFT-3891] - TNonblockingServer configured with more than one IO threads does not always return from serve() upon stop() + * [THRIFT-3892] - Thrift uses TLS SNI extension provided by OpenSSL library. Older version of OpenSSL(< 0.9.8f) may create problem because they do not support 'SSL_set_tlsext_host_name()'. + * [THRIFT-3895] - Build fails using Java 1.8 with Ant < 1.9 + * [THRIFT-3896] - map data with number string key cannot access that deserialized by php extension + * [THRIFT-3938] - Python TNonblockingServer does not work with SSL + * [THRIFT-3944] - TSSLSocket has dead code in checkHandshake + * [THRIFT-3946] - Java 1.5 compatibility broken for binary fields (java5 option) + * [THRIFT-3960] - Inherited services in Lua generator are not named correctly + * [THRIFT-3962] - Ant build.xml broken on Windows for Java library + * [THRIFT-3963] - Thrift.cabal filename does not match module name + * [THRIFT-3967] - gobject/gparam.h:166:33: warning: enumerator value for ‘G_PARAM_DEPRECATED’ is not an integer constant expression + * [THRIFT-3968] - Deserializing empty string/binary fields + * [THRIFT-3974] - Using clang-3.8 and ThreadSanitizer on the concurrency_test claims bad PThread behavior + * [THRIFT-3984] - PHP7 extension causes segfault + * [THRIFT-4008] - broken ci due to upstream dependency versioning break + * [THRIFT-4009] - Use @implementer instead of implements in TTwisted.py + * [THRIFT-4010] - Q.fcall messing up with *this* pointer inside called function + * [THRIFT-4011] - Sets of Thrift structs generate Go code that can't be serialized to JSON + * [THRIFT-4012] - Python Twisted implementation uses implements, not compatible with Py3 + * [THRIFT-4014] - align C# meta data in AssemblyInfo.cs + * [THRIFT-4015] - Fix wrongly spelled "Thirft"s + * [THRIFT-4016] - testInsanity() impl does not conform to test spec in ThriftTest.thrift + * [THRIFT-4023] - Skip unexpected field types on read/write + * [THRIFT-4024] - Skip() should throw on unknown data types + * [THRIFT-4026] - TSSLSocket doesn't work with Python < 2.7.9 + * [THRIFT-4029] - Accelerated protocols do not build from thrift-py 0.10.0 on PyPI + * [THRIFT-4031] - Go plugin generates invalid code for lists of typedef'ed built-in types + * [THRIFT-4033] - Default build WITH_PLUGIN=ON for all builds results in packaging errors + * [THRIFT-4034] - CMake doesn't work to build compiler on MacOS + * [THRIFT-4036] - Add .NET Core environment/build support to the docker image + * [THRIFT-4038] - socket check: checking an unsigned number against >= 0 never fails + * [THRIFT-4042] - ExtractionError when using accelerated thrift in a multiprocess test + * [THRIFT-4043] - thrift perl debian package is placing files in the wrong place + * [THRIFT-4044] - Build job 17 failing on every pull request; hspec core (haskell) 2.4 issue + * [THRIFT-4046] - MinGW with gcc 6.2 does not compile on Windows + * [THRIFT-4060] - Thrift printTo ostream overload mechanism breaks down when types are nested + * [THRIFT-4062] - Remove debug print from TServiceClient + * [THRIFT-4065] - Document Perl ForkingServer signal restriction imposed by THRIFT-3848 and remove unnecessary code + * [THRIFT-4068] - A code comment in Java ServerSocket is wrong around accept() + * [THRIFT-4073] - enum files are still being generated with unused imports + * [THRIFT-4076] - Appveyor builds failing because ant 1.9.8 was removed from apache servers + * [THRIFT-4077] - AI_ADDRCONFIG redefined after recent change to PlatformSocket header + * [THRIFT-4079] - Generated perl code that returns structures from included thrift files is missing a necessary use clause + * [THRIFT-4087] - Spurious exception destroying TThreadedServer because of incorrect join() call + * [THRIFT-4102] - TBufferedTransport performance issue since 0.10.0 + * [THRIFT-4106] - concurrency_test fails randomly + * [THRIFT-4108] - c_glib thrift ssl has multiple bugs and deprecated functions + * [THRIFT-4109] - Configure Script uses string comparison for versions + * [THRIFT-4129] - C++ TNonblockingServer fd leak when failing to dispatch new connections + * [THRIFT-4131] - Javascript with WebSocket handles oneway methods wrong + * [THRIFT-4134] - Fix remaining undefined behavior invalid vptr casts + * [THRIFT-4140] - Use of non-thread-safe function gmtime() + * [THRIFT-4141] - Installation of haxe in docker files refers to a redirect link and fails + * [THRIFT-4147] - Rust: protocol should accept transports with non-static lifetime + * [THRIFT-4148] - [maven-thrift-plugin] compile error while import a thrift in dependency jar file. + * [THRIFT-4149] - System.out pollutes log files + * [THRIFT-4154] - PHP close() of a TSocket needs to close any type of socket + * [THRIFT-4158] - minor issue in README-MSYS2.md + * [THRIFT-4159] - Building tests fails on MSYS2 (MinGW64) due to a (small?) linker error + * [THRIFT-4160] - TNonblocking server fix use of closed/freed connections + * [THRIFT-4161] - TNonBlocking server using uninitialized event in error paths + * [THRIFT-4162] - TNonBlocking handling of TSockets in error state is incorrect after fd is closed + * [THRIFT-4164] - Core in TSSLSocket cleanupOpenSSL when destroying a mutex used by openssl + * [THRIFT-4165] - C++ build has many warnings under c++03 due to recent changes, cmake needs better platform-independent language level control + * [THRIFT-4166] - Recent fix to remove boost::lexical_cast usage broke VS2010 + * [THRIFT-4167] - Missing compile flag + * [THRIFT-4170] - Support lua 5.1 or earlier properly for object length determination + * [THRIFT-4172] - node.js tutorial client does not import assert, connection issues are not handled properly + * [THRIFT-4177] - Java compiler produces deep copy constructor that could make shallow copy instead + * [THRIFT-4184] - Building on Appveyor: invalid escape sequence \L + * [THRIFT-4185] - fb303 counter encoding fix + * [THRIFT-4189] - Framed/buffered transport Dispose() does not dispose the nested transport + * [THRIFT-4193] - Lower the default maxReadBufferBytes for non-blocking servers + * [THRIFT-4195] - Compilation to GO produces broken code + * [THRIFT-4196] - Cannot generate recursive Rust types + * [THRIFT-4204] - typo in compact spec + * [THRIFT-4206] - Strings in container fields are not decoded properly with py:dynamic and py:utf8strings + * [THRIFT-4208] - C# NamedPipesServer not really working in some scenarios + * [THRIFT-4211] - Fix GError glib management under Thrift + * [THRIFT-4212] - c_glib flush tries to close SSL even if socket is invalid + * [THRIFT-4213] - Travis build fails at curl -sSL https://www.npmjs.com/install.sh | sh + * [THRIFT-4215] - Golang TTransportFactory Pattern Squelches Errors + * [THRIFT-4216] - Golang Http Clients Do Not Respect User Options + * [THRIFT-4218] - Set TCP_NODELAY for PHP client socket + * [THRIFT-4219] - Golang HTTP clients created with Nil buffer + * [THRIFT-4231] - TJSONProtocol throws unexpected non-Thrift-exception on null strings + * [THRIFT-4232] - ./configure does bad ant version check + * [THRIFT-4234] - Travis build fails cross language tests with "Unsupported security protocol type" + * [THRIFT-4237] - Go TServerSocket Race Conditions + * [THRIFT-4240] - Go TSimpleServer does not close properly + * [THRIFT-4243] - Go TSimpleServer race on wait in Stop() method + * [THRIFT-4245] - Golang TFramedTransport's writeBuffer increases if writes to transport failed + * [THRIFT-4246] - Sequence number mismatch on multiplexed clients + * [THRIFT-4247] - Compile fails with openssl 1.1 + * [THRIFT-4248] - Compile fails - strncpy, memcmp, memset not declared in src/thrift/transport/TSSLSocket.cpp + * [THRIFT-4251] - Java Epoll Selector Bug + * [THRIFT-4257] - Typescript async callbacks do not provide the correct types + * [THRIFT-4258] - Boost/std thread wrapping faultiness + * [THRIFT-4260] - Go context generation issue. Context is parameter in Interface not in implementation + * [THRIFT-4261] - Go context generation issue: breaking change in generated code regarding thrift.TProcessorFunction interface + * [THRIFT-4262] - Invalid binding to InterlockedCompareExchange64() with 64-bit targets + * [THRIFT-4263] - Fix use after free bug for thrown exceptions + * [THRIFT-4266] - Erlang library throws during skipping fields of composite type (maps, lists, structs, sets) + * [THRIFT-4268] - Erlang library emits debugging output in transport layer + * [THRIFT-4273] - erlang:now/0: Deprecated BIF. + * [THRIFT-4274] - Python feature tests for SSL/TLS failing + * [THRIFT-4279] - Wrong path in include directive in generated Thrift sources + * [THRIFT-4283] - TNamedPipeServer race condition in interrupt + * [THRIFT-4284] - File contains a NBSP: lib/nodejs/lib/thrift/web_server.js + * [THRIFT-4290] - C# nullable option generates invalid code for non-required enum field with default value + * [THRIFT-4292] - TimerManager::remove() is not implemented + * [THRIFT-4307] - Make ssl-open timeout effective in golang client + * [THRIFT-4312] - Erlang client cannot connect to Python server: exception error: econnrefused + * [THRIFT-4313] - Program code of the Erlang tutorial files contain syntax errors + * [THRIFT-4316] - TByteBuffer.java will read too much data if a previous read returns fewer bytes than requested + * [THRIFT-4319] - command line switch for "evhttp" incorrectly resolved to anon pipes + * [THRIFT-4323] - range check errors or NPE in edge cases + * [THRIFT-4324] - field names can conflict with local vars in generated code + * [THRIFT-4328] - Travis CI builds are timing out (job 1) and haxe builds are failing since 9/11 + * [THRIFT-4329] - c_glib Doesn't have a multiplexed processor + * [THRIFT-4331] - C++: TSSLSockets bug in handling huge messages, bug in handling polling + * [THRIFT-4332] - Binary protocol has memory leaks + * [THRIFT-4334] - Perl indentation incorrect when defaulting field attribute to a struct + * [THRIFT-4339] - Thrift Framed Transport in Erlang crashes server when client disconnects + * [THRIFT-4340] - Erlang fix a crash on client close + * [THRIFT-4355] - Javascript indentation incorrect when defaulting field attribute to a struct + * [THRIFT-4356] - thrift_protocol call Transport cause Segmentation fault + * [THRIFT-4359] - Haxe compiler looks like it is producing incorrect code for map or set key that is binary type + * [THRIFT-4362] - Missing size-check can lead to huge memory allocation + * [THRIFT-4364] - Website contributing guide erroneously recommends submitting patches in JIRA + * [THRIFT-4365] - Perl generated code uses indirect object syntax, which occasionally causes compilation errors. + * [THRIFT-4367] - python TProcessor.process is missing "self" + * [THRIFT-4370] - Ubuntu Artful cppcheck and flake8 are more stringent and causing SCA build job failures + * [THRIFT-4372] - Pipe write operations across a network are limited to 65,535 bytes per write. + * [THRIFT-4374] - cannot load thrift_protocol due to undefined symbol: _ZTVN10__cxxabiv120__si_class_type_infoE + * [THRIFT-4375] - TMemory throw bad_alloc due to counter overflow + * [THRIFT-4376] - Coverity high impact issue resolution + * [THRIFT-4377] - haxe. socket handles leak in TSimpleServer + * [THRIFT-4381] - Wrong isset bitfield value after transmission + * [THRIFT-4385] - Go remote client -u flag is broken + * [THRIFT-4392] - compiler/..../plugin.thrift structs mis-ordered blows up ocaml generator + * [THRIFT-4395] - Unable to build in the ubuntu-xenial docker image: clap 2.28 requires Rust 1.20 + * [THRIFT-4396] - inconsistent (or plain wrong) version numbers in master/trunk + +## Documentation + * [THRIFT-4157] - outdated readme about Haxe installation on Linux + +## Improvement + * [THRIFT-105] - make a thrift_spec for a structures with negative tags + * [THRIFT-281] - Cocoa library code needs comments, badly + * [THRIFT-775] - performance improvements for Perl + * [THRIFT-2221] - Generate c++ code with std::shared_ptr instead of boost::shared_ptr. + * [THRIFT-2364] - OCaml: Use Oasis exclusively for build process + * [THRIFT-2504] - TMultiplexedProcessor should allow registering default processor called if no service name is present + * [THRIFT-3207] - Enable build with OpenSSL 1.1.0 series + * [THRIFT-3272] - Perl SSL Authentication Support + * [THRIFT-3357] - Generate EnumSet/EnumMap where elements/keys are enums + * [THRIFT-3369] - Implement SSL/TLS support on C with c_glib + * [THRIFT-3467] - Go Maps for Thrift Sets Should Have Values of Type struct{} + * [THRIFT-3580] - THeader for Haskell + * [THRIFT-3627] - Missing basic code style consistency of JavaScript. + * [THRIFT-3706] - There's no support for Multiplexed protocol on c_glib library + * [THRIFT-3766] - Add getUnderlyingTransport() to TZlibTransport + * [THRIFT-3776] - Go code from multiple thrift files with the same namespace + * [THRIFT-3823] - Escape documentation while generating non escaped documetation + * [THRIFT-3854] - allow users to clear read buffers + * [THRIFT-3859] - Unix Domain Socket Support in Objective-C + * [THRIFT-3921] - C++ code should print enums as strings + * [THRIFT-3926] - There should be an error emitted when http status code is not 200 + * [THRIFT-4007] - Micro-optimization of TTransport.py + * [THRIFT-4040] - Add real cause of TNonblockingServerSocket error to exception + * [THRIFT-4064] - Update node library dependencies + * [THRIFT-4069] - All perl packages should have proper namespace, version syntax, and use proper thrift exceptions + * [THRIFT-4071] - Consolidate the Travis CI jobs where possible to put less stress on the Apache Foundation's allocation of CI build slaves + * [THRIFT-4072] - Add the possibility to send custom headers in TCurlClient + * [THRIFT-4075] - Better MinGW support for headers-only boost (without thread library) + * [THRIFT-4081] - Provide a MinGW 64-bit Appveyor CI build for better pull request validation + * [THRIFT-4084] - Improve SSL security in thrift by adding a make cross client that checks to make sure SSLv3 protocol cannot be negotiated + * [THRIFT-4095] - Add multiplexed protocol to Travis CI for make cross + * [THRIFT-4099] - Auto-derive Hash for generated Rust structs + * [THRIFT-4110] - The debian build files do not produce a "-dbg" package for debug symbols of libthrift0 + * [THRIFT-4114] - Space after '///' in doc comments + * [THRIFT-4126] - Validate objects in php extension + * [THRIFT-4130] - Ensure Apache Http connection is released back to pool after use + * [THRIFT-4151] - Thrift Mutex Contention Profiling (pthreads) should be disabled by default + * [THRIFT-4176] - Implement a threaded and threadpool server type for Rust + * [THRIFT-4183] - Named pipe client blocks forever on Open() when there is no server at the other end + * [THRIFT-4190] - improve C# TThreadPoolServer defaults + * [THRIFT-4197] - Implement transparent gzip compression for HTTP transport + * [THRIFT-4198] - Ruby should log Thrift internal errors to global logger + * [THRIFT-4203] - thrift server stop gracefully + * [THRIFT-4205] - c_glib is not linking against glib + gobject + * [THRIFT-4209] - warning CS0414 in T[TLS]ServerSocket.cs + * [THRIFT-4210] - include Thrift.45.csproj into CI runs + * [THRIFT-4217] - HttpClient should support gzip and deflate + * [THRIFT-4222] - Support Unix Domain Sockets in Golang TServerSocket + * [THRIFT-4233] - Make THsHaServer.invoker available (get method only) in inherited classes + * [THRIFT-4236] - Support context in go generated code. + * [THRIFT-4238] - JSON generator: make annotation-aware + * [THRIFT-4269] - Don't append '.' to Erlang namespace if it ends in '_'. + * [THRIFT-4270] - Generate Erlang mapping functions for const maps and lists + * [THRIFT-4275] - Add support for zope.interface only, apart from twisted support. + * [THRIFT-4285] - Pull generated send/recv into library to allow behaviour to be customised + * [THRIFT-4287] - Add c++ compiler "no_skeleton" flag option + * [THRIFT-4288] - Implement logging levels properly for node.js + * [THRIFT-4295] - Refresh the Docker image file suite for Ubuntu, Debian, and CentOS + * [THRIFT-4305] - Emit ddoc for generated items + * [THRIFT-4306] - Thrift imports not replicated to D service output + * [THRIFT-4315] - Add default message for TApplicationException + * [THRIFT-4318] - Delphi performance improvements + * [THRIFT-4325] - Simplify automake cross compilation by relying on one global THRIFT compiler path + * [THRIFT-4327] - Improve TimerManager API to allow removing specific task + * [THRIFT-4330] - Allow unused crates in Rust files + * [THRIFT-4333] - Erlang tutorial examples are using a different port (9999) + * [THRIFT-4343] - Change CI builds to use node.js 8.x LTS once available + * [THRIFT-4345] - Create a docker build environment that uses the minimum supported language levels + * [THRIFT-4346] - Allow Zlib transport factory to wrap other transports + * [THRIFT-4348] - Perl HTTP Client custom HTTP headers + * [THRIFT-4350] - Update netcore build for dotnet 2.0 sdk and make cross validation + * [THRIFT-4351] - Use Travis CI Build Stages to optimize the CI build + * [THRIFT-4353] - cannot read via thrift_protocol at server side + * [THRIFT-4378] - add set stopTimeoutUnit method to TThreadPoolServer + +## New Feature + * [THRIFT-750] - C++ Compiler Virtual Function Option + * [THRIFT-2945] - Implement support for Rust language + * [THRIFT-3857] - thrift js:node complier support an object as parameter not an instance of struct + * [THRIFT-3933] - Port official C# .NET library for Thrift to C# .NET Core libary + * [THRIFT-4039] - Update of Apache Thrift .Net Core lib + * [THRIFT-4113] - Provide a buffer transport for reading/writing in memory byte stream + +## Question + * [THRIFT-2956] - autoconf - possibly undefined macro - AC_PROG_BISON + * [THRIFT-4223] - Add support to the isServing() method for the C++ library + +## Task + * [THRIFT-3622] - Fix deprecated uses of std::auto_ptr + * [THRIFT-4028] - Please remove System.out.format from the source code + * [THRIFT-4186] - Build and test rust client in Travis + +## Test + * [THRIFT-4264] - PHP - Support both shared & static linking of sockets library + +## Wish + * [THRIFT-4344] - Define and maintain the minimum language level for all languages in one place + + +Thrift 0.10.0 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-1840] - Thrift Generated Code Causes Global Variable Leaks + * [THRIFT-1828] - moc_TQTcpServer.cpp was removed from source tree but is in thrift-0.9.0.tar.gz + * [THRIFT-1790] - cocoa: Duplicate interface definition error + * [THRIFT-1776] - TPipeServer should implement "listen", so that TServerEventHandler preServe will work right + * [THRIFT-1351] - Compiler does not care about binary strings + * [THRIFT-1229] - Python fastbinary.c can not handle unicode as generated python code + * [THRIFT-749] - C++ TBufferedTransports do not flush their buffers on delete + * [THRIFT-747] - C++ TSocket->close calls shutdown breaking forked parent process + * [THRIFT-732] - server exits abnormally when client calls send_xxx function without calling recv_xxx function + * [THRIFT-3942] - TSSLSocket does not honor send and receive timeouts + * [THRIFT-3941] - WinXP version of thrift_poll() relies on undefined behavior by passing a destructed variable to select() + * [THRIFT-3940] - Visual Studio project file for compiler is broken + * [THRIFT-3943] - Coverity Scan identified some high severity defects + * [THRIFT-3929] - PHP "nsglobal" Option Results in Syntax Error in Generated Code (Trailing Backslash) + * [THRIFT-3936] - Cannot compile 0.10.0 development tip with VS2013 and earlier (snprintf, uint32_t) + * [THRIFT-3935] - Incorrect skipping of map and set + * [THRIFT-3920] - Ruby: Ensuring that HTTP failures will clear the http transport outbuf var + * [THRIFT-3919] - C# TTLSServerSocket does not use clientTimeout + * [THRIFT-3917] - Check backports.ssl_match_hostname module version + * [THRIFT-3909] - Fix c_glib static lib CMake build + * [THRIFT-3904] - Typo in node tutorial leads to wrong transport being used + * [THRIFT-3848] - As an implementer of a perl socket server, I do not want to have to remember to ignore SIGCHLD for it to work properly + * [THRIFT-3844] - thrift_protocol cannot compile in 7.0.7 + * [THRIFT-3843] - integer issues with Haxe PHP targets cause ZigZag encoding to fail + * [THRIFT-3842] - Dart generates incorrect code for a const struct + * [THRIFT-3841] - dart compact protocol incorrectly serializes/deserialized doubles + * [THRIFT-3708] - NameError: global name 'TProtocol' is not defined + * [THRIFT-3704] - "TConnectedClient died: Could not refill buffer" message shown when using HTTP Server + * [THRIFT-3678] - Fix javadoc errors on JDK 8 + * [THRIFT-3014] - AppVeyor support + * [THRIFT-2994] - Node.js TJSONProtocol cannot be used for object serialization. + * [THRIFT-2974] - writeToParcel throws NPE for optional enum fields + * [THRIFT-2948] - Python TJSONProtocol doesn't handle structs with binary fields containing invalid unicode. + * [THRIFT-2845] - ChildService.Plo: No such file or directory + * [THRIFT-3276] - Binary data does not decode correctly using the TJSONProtocol when the base64 encoded data is padded. + * [THRIFT-3253] - Using latest version of D gives deprecation notices + * [THRIFT-2883] - TTwisted.py, during ConnectionLost processing: exceptions.RuntimeError: dictionary changed size during iteration + * [THRIFT-2019] - Writing on a disconnected socket on Mac causes SIG PIPE + * [THRIFT-2020] - Thrift library has some empty files that haven't really been deleted + * [THRIFT-2049] - Go compiler doesn't build on native Windows + * [THRIFT-2024] - TServer.cpp warns on 64-bit platforms about truncating an rlim_t into an int + * [THRIFT-2023] - gettimeofday implementation on Windows errors when no time zone is passed in. + * [THRIFT-2022] - CoB and dense code generation still uses TR1 bind, even though that doesn't work with clang + * [THRIFT-2027] - Minor 64-bit and NOMINMAX issues in C++ library + * [THRIFT-2156] - TServerSocket::listen() is throwing exceptions with misleading information + * [THRIFT-2154] - Missing #deepCopy should return T + * [THRIFT-3157] - TBase signature should be TBase, F extends TFieldIdEnum> + * [THRIFT-3156] - Node TLS: server executes processing logic two full times + * [THRIFT-3154] - tutorial/py.tornado throw EOF exception + * [THRIFT-3063] - C++ build -Wunused-parameter warnings on processor_test, TransportTest + * [THRIFT-3056] - Add string/collection length limits for Python protocol readers + * [THRIFT-3237] - Fix TNamedPipeServer::createNamedPipe memory leak + * [THRIFT-3233] - Fix C++ ThreadManager::Impl::removeWorker worker join + * [THRIFT-3232] - Cannot deserialize json messages created with fieldNamesAsString + * [THRIFT-3206] - Fix Visual Studio build failure due 'pthread_self': identifier not found + * [THRIFT-3200] - JS and nodejs do not encode JSON protocol binary fields as base64 + * [THRIFT-3199] - Exception field has basic metadata + * [THRIFT-3182] - TFramedTransport is in an invalid state after frame size exception + * [THRIFT-2536] - new TSocket, uninitialised value reported by valgrind + * [THRIFT-2527] - Apache Thrift IDL Compiler code generated for Node.js should be jshint clean + * [THRIFT-2519] - "processor" class is not being generated + * [THRIFT-2431] - TFileTransportTest fails with "check delta < XXX failed" + * [THRIFT-2708] - Erlang library does not support "oneway" message type + * [THRIFT-3377] - Deep copy is actually shallow when using typedef members + * [THRIFT-3376] - C# and Python JSON protocol double values lose precision + * [THRIFT-3373] - Various fixes for cross test servers and clients + * [THRIFT-3370] - errno extern variable redefined. Not compiling for Android + * [THRIFT-3379] - Potential out of range panic in Go JSON protocols + * [THRIFT-3371] - Abstract namespace Unix domain sockets broken in C++ + * [THRIFT-3380] - nodejs: 0.9.2 -> 0.9.3 upgrade breaks Protocol and Transport requires + * [THRIFT-3367] - Fix bad links to coding_standards.md #634 + * [THRIFT-3401] - Nested collections emit Objective-C code that cannot compile + * [THRIFT-3403] - JSON String reader doesn't recognize UTF-16 surrogate pairs + * [THRIFT-3362] - make check fails for C++ at the SecurityTest + * [THRIFT-3395] - Cocoa compiler produces corrupt code when boxing enums inside map. + * [THRIFT-3394] - compiler generates uncompilable code + * [THRIFT-3388] - hash doesn't work on set/list + * [THRIFT-3391] - Wrong bool formatting in test server + * [THRIFT-3390] - TTornado server doesn't handle closed connections properly + * [THRIFT-3382] - TBase class for C++ Library + * [THRIFT-3392] - Java TZlibTransport does not close its wrapper streams upon close() + * [THRIFT-3383] - i64 related warnings + * [THRIFT-3386] - misc. warnings with make check + * [THRIFT-3385] - warning: format ‘%lu’ expects ‘long unsigned int’, but has type ‘std::basic_string::size_type {aka unsigned int} + * [THRIFT-3355] - npm WARN package.json thrift@1.0.0-dev No license field. + * [THRIFT-3360] - Improve cross test servers and clients further + * [THRIFT-3359] - Binary field incompatibilities + * [THRIFT-3354] - Fix word-extraction substr bug in initialism code + * [THRIFT-3350] - Python JSON protocol does not encode binary as Base64 + * [THRIFT-3577] - assertion failed at line 512 of testcontainertest.c + * [THRIFT-3576] - Boost test --log_format arg does not accept lowercase + * [THRIFT-3575] - Go compiler tries to use unexported library methods when using read_write_private + * [THRIFT-3574] - Cocoa generator makes uncompilable imports + * [THRIFT-3570] - Remove duplicate instances that are added by upstream + * [THRIFT-3571] - Make feature test result browsable + * [THRIFT-3569] - c_glib protocols do not check number of bytes read by transport + * [THRIFT-3568] - THeader server crashes on readSlow + * [THRIFT-3567] - GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed + * [THRIFT-3566] - C++/Qt: TQTcpServerTest::test_communicate() is never executed + * [THRIFT-3564] - C++/Qt: potential core dump in TQTcpServer in case an exception occurs in TAsyncProcessor::process() + * [THRIFT-3558] - typos in c_glib tests + * [THRIFT-3559] - Fix awkward extra semi-colons with Cocoa container literals + * [THRIFT-3555] - 'configure' script does not honor --with-openssl= for libcrypto for BN_init + * [THRIFT-3554] - Constant decls may lead to "Error: internal error: prepare_member_name_mapping() already active for different struct" + * [THRIFT-3552] - glib_c Memory Leak + * [THRIFT-3551] - Thrift perl library missing package declaration + * [THRIFT-3549] - Exceptions are not properly stringified in Perl library + * [THRIFT-3546] - NodeJS code should not be namespaced (and is currently not strict-mode compliant) + * [THRIFT-3545] - Container type literals do not compile + * [THRIFT-3538] - Remove UnboundMethodType in TProtocolDecorator + * [THRIFT-3536] - Error 'char' does not contain a definition for 'IsLowSurrogate' for WP7 target + * [THRIFT-3534] - Link error when building with Qt5 + * [THRIFT-3533] - Can not send nil pointer as service method argument + * [THRIFT-3507] - THttpClient does not use proxy from http_proxy, https_proxy environment variables + * [THRIFT-3502] - C++ TServerSocket passes small buffer to getsockname + * [THRIFT-3501] - Forward slash in comment causes compiler error + * [THRIFT-3498] - C++ library assumes optional function pthread_attr_setschedpolicy is available + * [THRIFT-3497] - Build fails with "invalid use of incomplete type" + * [THRIFT-3496] - C++: Cob style client fails when sending a consecutive request + * [THRIFT-3493] - libthrift does not compile on windows using visual studio + * [THRIFT-3488] - warning: unused variable 'program' + * [THRIFT-3489] - warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings] + * [THRIFT-3487] - Full support for newer Delphi versions + * [THRIFT-3528] - Fix warnings in thrift.ll + * [THRIFT-3527] - -gen py:dynamic,utf8strings ignores utf8strings option + * [THRIFT-3526] - Code generated by py:utf8strings does not work for Python3 + * [THRIFT-3524] - dcc32 warning "W1000 Symbol 'IsLowSurrogate' is deprecated: 'Use TCharHelper'" in Thrift.Protocol.JSON.pas + * [THRIFT-3525] - py:dynamic fails to handle binary list/set/map element + * [THRIFT-3521] - TSimpleJSONProtocolTest is not deterministic (fails when run on JDK 8) + * [THRIFT-3520] - Dart TSocket onError stream should be typed as Object + * [THRIFT-3519] - fastbinary does not work with -gen py:utf8strings + * [THRIFT-3518] - TConcurrentClientSyncInfo files were missing for Visual Studio + * [THRIFT-3512] - c_glib: Build fails due to missing features.h + * [THRIFT-3483] - Incorrect empty binary handling introduced by THRIFT-3359 + * [THRIFT-3479] - Oneway calls should not return exceptions to clients + * [THRIFT-3478] - Restore dropped method to THsHaServer.java + * [THRIFT-3477] - Parser fails on enum item that starts with 'E' letter and continues with number + * [THRIFT-3476] - Missing include in ./src/thrift/protocol/TJSONProtocol.cpp + * [THRIFT-3474] - Docker: thrift-compiler + * [THRIFT-3473] - When "optional' is used with a struct member, C++ server seems to not return it correctly + * [THRIFT-3468] - Dart TSocketTransport onError handler is too restrictive + * [THRIFT-3451] - thrift_protocol PHP extension missing config.m4 file + * [THRIFT-3456] - rounding issue in static assert + * [THRIFT-3455] - struct write method's return value is incorrect + * [THRIFT-3454] - Python Tornado tutorial is broken + * [THRIFT-3463] - Java can't be disabled in CMake build + * [THRIFT-3450] - NPE when using SSL + * [THRIFT-3449] - TBaseAsyncProcessor fb.responseReady() never called for oneway functions + * [THRIFT-3471] - Dart generator does not handle uppercase argument names + * [THRIFT-3470] - Sporadic timeouts with pipes + * [THRIFT-3465] - Go Code With Complex Const Initializer Compilation Depends On Struct Order + * [THRIFT-3464] - Fix several defects in c_glib code generator + * [THRIFT-3462] - Cocoa generates Incorrect #import header names + * [THRIFT-3453] - remove rat_exclude + * [THRIFT-3418] - Use of ciphers in ssl.wrap_socket() breaks python 2.6 compatibility + * [THRIFT-3417] - "namespace xsd" is not really working + * [THRIFT-3413] - Thrift code generation bug in Go when extending service + * [THRIFT-3420] - C++: TSSLSockets are not interruptable + * [THRIFT-3415] - include unistd.h conditionally + * [THRIFT-3414] - #include in THeaderTransport.h breaks windows build + * [THRIFT-3411] - Go generates remotes with wrong package qualifiers when including + * [THRIFT-3430] - Go THttpClient does not read HTTP response body to completion when closing + * [THRIFT-3423] - First call to thrift_transport:read_exact fails to dispatch correct function + * [THRIFT-3422] - Go TServerSocket doesn't close on Interrupt + * [THRIFT-3421] - rebar as dependency instead of bundling (was: rebar fails if PWD contains Unicode) + * [THRIFT-3428] - Go test fails when running make check + * [THRIFT-3445] - Throwable messages are hidden from JVM stack trace output + * [THRIFT-3443] - Thrift include can generate uncompilable code + * [THRIFT-3444] - Large 64 bit Integer does not preserve value through Node.js JSONProtocol + * [THRIFT-3436] - misc. cross test issues with UTF-8 path names + * [THRIFT-3435] - Put generated Java code for fullcamel tests in a separate package/namespace + * [THRIFT-3433] - Doubles aren't interpreted correctly + * [THRIFT-3437] - Mingw-w64 build fail + * [THRIFT-3434] - Dart generator produces empty name in pubspec.yaml for includes without namespaces + * [THRIFT-3408] - JSON generator emits incorrect types + * [THRIFT-3406] - Cocoa client should not schedule streams on main runloop + * [THRIFT-3404] - JSON String reader doesn't recognize UTF-16 surrogate pair + * [THRIFT-3636] - Double precision is not fully preserved in C++ TJSONProtocol + * [THRIFT-3632] - c_glib testserialization fails with glib assertion + * [THRIFT-3619] - Using Thrift 0.9.3 with googletest on Linux gcc 4.9 / C++11 + * [THRIFT-3617] - CMake does not build gv/xml generators + * [THRIFT-3615] - Fix Python SSL client resource leak on connection failure + * [THRIFT-3616] - lib/py/test/test_sslsocket.py is flaky + * [THRIFT-3643] - Perl SSL server crushes if a client disconnect without handshake + * [THRIFT-3639] - C# Thrift library forces TLS 1.0, thwarting TLS 1.2 usage + * [THRIFT-3633] - Travis "C C++ - GCC" build was using clang + * [THRIFT-3634] - Fix Python TSocket resource leak on connection failure + * [THRIFT-3630] - Debian/Ubuntu install docs need an update + * [THRIFT-3629] - Parser sets exitcode on errors, but generator does not + * [THRIFT-3608] - lib/cpp/test/SecurityTest is flaky in jenkins Thrift-precommit build. + * [THRIFT-3601] - Better conformance to PEP8 for generated code + * [THRIFT-3599] - Validate client IP address against cert's SubjectAltName + * [THRIFT-3598] - TBufferedTransport doesn't instantiate client connection + * [THRIFT-3597] - `make check` hangs in go tests + * [THRIFT-3589] - Dart generator uses wrong name in constructor for uppercase arguments with defaults + * [THRIFT-3588] - Using TypeScript with --noImplicitAny fails + * [THRIFT-3584] - boolean false value cannot be transferred + * [THRIFT-3578] - Make THeaderTransport detect TCompact framed and unframed + * [THRIFT-3323] - Python library does not handle escaped forward slash ("/") in JSON + * [THRIFT-3322] - CMake generated "make check" failes on python_test + * [THRIFT-3321] - Thrift can't be added as a subdirectory of another CMake-based project + * [THRIFT-3314] - Dots in file names of includes causes dots in javascript variable names + * [THRIFT-3307] - Segfault in Ruby serializer + * [THRIFT-3309] - Missing TConstant.php in /lib/php/Makefile.am + * [THRIFT-3810] - unresolved external symbol public: virtual void __cdecl apache::thrift::server::TServerFramework::serve(void) + * [THRIFT-3736] - C++ library build fails if OpenSSL does not surrpot SSLv3 + * [THRIFT-3878] - Compile error in TSSLSocket.cpp with new OpenSSL [CRYPTO_num_locks] + * [THRIFT-3949] - missing make dist entry for compiler/cpp/test + * [THRIFT-449] - The wire format of the JSON Protocol may not always be valid JSON if it contains non-UTF8 encoded strings + * [THRIFT-162] - Thrift structures are unhashable, preventing them from being used as set elements + * [THRIFT-3961] - TConnectedClient does not terminate the connection to the client if an exception while processing the received message occures. + * [THRIFT-3881] - Travis CI builds are failing due to docker failures (three retries, and gives up) + * [THRIFT-3937] - Cannot compile 0.10.0 development tip with gcc-4.6.x + * [THRIFT-3964] - Unsupported mechanism type ????? due to dependency on default OS-dependent charset + * [THRIFT-3038] - Use of volatile in cpp library + * [THRIFT-3301] - Java generated code uses imports that can lead to class name collisions with IDL defined types + * [THRIFT-3348] - PHP TCompactProtocol bool&int64 readvalue bug + * [THRIFT-3955] - TThreadedServer Memory Leak + * [THRIFT-3829] - Thrift does not install Python Libraries if Twisted is not installed + * [THRIFT-3932] - C++ ThreadManager has a rare termination race + * [THRIFT-3828] - cmake fails when Boost_INCLUDE_DIRS (and other variables passed to include_directories()) is empty + * [THRIFT-3958] - CMake WITH_MT option for windows static runtime linking does not support the cmake build type RelWithDebInfo + * [THRIFT-3957] - TConnectedClient does not disconnect from clients when their timeout is reached. + * [THRIFT-3953] - TSSLSocket::close should handle exceptions from waitForEvent because it is called by the destructor. + * [THRIFT-3977] - PHP extension creates undefined values when deserializing sets + * [THRIFT-3947] - sockaddr type isn't always large enough for the return of getsockname + * [THRIFT-2755] - ThreadSanitizer reports data race in ThreadManager::Impl::addWorker + * [THRIFT-3948] - errno is not the correct method of getting the error in windows + * [THRIFT-4008] - broken ci due to upstream dependency versioning break + * [THRIFT-3999] - Fix Debian & Ubuntu package dependencies + * [THRIFT-3886] - PHP cross test client returns 0 even when failing + * [THRIFT-3997] - building thrift libs does not support new openssl + +## Documentation + * [THRIFT-3867] - Specify BinaryProtocol and CompactProtocol + +## Epic + * [THRIFT-3049] - As an iOS developer, I want a generator and library that produces Swift code + * [THRIFT-2336] - UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + +## Improvement + * [THRIFT-1867] - Python client/server should support client-side certificates. + * [THRIFT-1313] - c_glib compact support + * [THRIFT-1385] - make install doesn't install java library in the setted folder + * [THRIFT-1437] - Update RPM spec + * [THRIFT-847] - Test Framework harmonization across all languages + * [THRIFT-819] - add Enumeration for protocol, transport and server types + * [THRIFT-3927] - Emit an error instead of throw an error in the async callback + * [THRIFT-3931] - TSimpleServer: If process request encounter UNKNOWN_METHOD, don't close transport. + * [THRIFT-3934] - Automatically resolve OpenSSL binary version on Windows CI + * [THRIFT-3918] - Run subset of make cross + * [THRIFT-3908] - Remove redundant dependencies from Dockerfile + * [THRIFT-3907] - Skip Docker image build on CI when unchanged + * [THRIFT-3868] - Java struct equals should do identity check before field comparison + * [THRIFT-3849] - Port Go serializer and deserializer to dart + * [THRIFT-2989] - Complete CMake build for Apache Thrift + * [THRIFT-2980] - ThriftMemoryBuffer doesn't have a constructor option to take an existing buffer + * [THRIFT-2856] - refactor erlang basic transports and unify interfaces + * [THRIFT-2877] - Optimize generated hashCode + * [THRIFT-2869] - JSON: run schema validation from tests + * [THRIFT-3112] - [Java] AsyncMethodCallback should be typed in generated AsyncIface + * [THRIFT-3263] - PHP jsonSerialize() should cast scalar types + * [THRIFT-2905] - Cocoa compiler should have option to produce "modern" Objective-C + * [THRIFT-2821] - Enable the use of custom HTTP-Header in the Transport + * [THRIFT-2093] - added the ability to set compression level in C++ zlib transport + * [THRIFT-2089] - Compiler ignores duplicate typenames + * [THRIFT-2056] - Moved all #include config.h statements to #include + * [THRIFT-2031] - Make SO_KEEPALIVE configurable for C++ lib + * [THRIFT-2021] - Improve large binary protocol string performance + * [THRIFT-2028] - Cleanup threading headers / libraries + * [THRIFT-2014] - Change C++ lib includes to use style throughout + * [THRIFT-2312] - travis.yml: build everything + * [THRIFT-1915] - Multiplexing Services + * [THRIFT-1736] - Visual Studio top level project files within msvc + * [THRIFT-1735] - integrate tutorial into regular build + * [THRIFT-1533] - Make TTransport should be Closeable + * [THRIFT-35] - Move language tests into their appropriate library directory + * [THRIFT-1079] - Support i64 in AS3 + * [THRIFT-1108] - SSL support for the Ruby library + * [THRIFT-3856] - update debian package deependencies + * [THRIFT-3833] - haxe http server implementation (by embeding into php web server) + * [THRIFT-3839] - Performance issue with big message deserialization using php extension + * [THRIFT-3820] - Erlang: Detect OTP >= 18 to use new time correction + * [THRIFT-3816] - Reduce docker build duration on Travis-CI + * [THRIFT-3815] - Put appveyor dependency versions to one place + * [THRIFT-3788] - Compatibility improvements and Win64 support + * [THRIFT-3792] - Timeouts for anonymous pipes should be configurable + * [THRIFT-3794] - Split Delphi application, protocol and transport exception subtypes into separate exceptions + * [THRIFT-3774] - The generated code should have exception_names meta info + * [THRIFT-3762] - Fix build warnings for deprecated Thrift "byte" fields + * [THRIFT-3756] - Improve requiredness documentation + * [THRIFT-3761] - Add debian package for Python3 + * [THRIFT-3742] - haxe php cli support + * [THRIFT-3733] - Socket timeout improvements + * [THRIFT-3728] - http transport for thrift-lua + * [THRIFT-3905] - Dart compiler does not initialize bool, int, and double properties + * [THRIFT-3911] - Loosen Ruby dev dependency version requirements + * [THRIFT-3906] - Run C# tests with make check + * [THRIFT-3900] - Add Python SSL flags + * [THRIFT-3897] - Provide meaningful exception type based on WebExceptionStatus in case of timeout + * [THRIFT-3808] - Missing `DOUBLE` in thrift type enumeration + * [THRIFT-3803] - Remove "file" attribute from XML generator + * [THRIFT-3660] - Add V4 mapped address to test client cert's altname + * [THRIFT-3661] - Use https to download meck in erlang test build + * [THRIFT-3659] - Check configure result of CMake on CI + * [THRIFT-3667] - Add TLS SNI support to clients + * [THRIFT-3651] - Make backports.match_hostname and ipaddress optional + * [THRIFT-3666] - Build D tutorial as part of Autotools build + * [THRIFT-3665] - Add D libevent and OpenSSL to docker images + * [THRIFT-3664] - Remove md5.c + * [THRIFT-3662] - Add Haskell to debian docker image + * [THRIFT-3711] - Add D to cross language test + * [THRIFT-3691] - Run flake8 Python style check on Travis-CI + * [THRIFT-3692] - (Re)enable Appveyor C++ and Python build + * [THRIFT-3677] - Improve CMake Java build + * [THRIFT-3679] - Add stdout log to testBinary in Java test server + * [THRIFT-3718] - Reduce size of docker image for build environment + * [THRIFT-3698] - [Travis-CI] Introduce retry to apt commands + * [THRIFT-3127] - switch -recurse to --recurse and reserve -r + * [THRIFT-3087] - Pass on errors like "connection closed" + * [THRIFT-3240] - Thrift Python client should support subjectAltName and wildcard certs in TSSLSocket + * [THRIFT-3213] - make cross should indicate when it skips a known failing test + * [THRIFT-3208] - Fix Visual Studio solution build failure due to missing source + * [THRIFT-3186] - Add TServerHTTP to Go library + * [THRIFT-2342] - Add __FILE__ and __LINE__ to Thrift C++ excpetions + * [THRIFT-3372] - Add dart generator to Visual Studio project + * [THRIFT-3366] - ThriftTest to implement standard return values + * [THRIFT-3402] - Provide a perl Unix Socket implementation + * [THRIFT-3361] - Improve C# library + * [THRIFT-3393] - Introduce i8 to provide consistent set of Thrift IDL integer types + * [THRIFT-3339] - Support for database/sql + * [THRIFT-3565] - C++: T[Async]Processor::getEventHandler() should be declared as const member functions + * [THRIFT-3563] - C++/Qt: removed usage of macro QT_PREPEND_NAMESPACE as it isn't consequently used for all references to Qt types. + * [THRIFT-3562] - Removed unused TAsyncProcessor::getAsyncServer() + * [THRIFT-3561] - C++/Qt: make use of Q_DISABLE_COPY() to get rid of copy ctor and assignment operator + * [THRIFT-3556] - c_glib file descriptor transport + * [THRIFT-3544] - Make cross test fail when server process died unexpectedly + * [THRIFT-3540] - Make python tutorial more in line with PEP8 + * [THRIFT-3535] - Dart generator argument to produce a file structure usable in parent library + * [THRIFT-3505] - Enhance Python TSSLSocket + * [THRIFT-3506] - Eliminate old style classes from library code + * [THRIFT-3503] - Enable py:utf8string by default + * [THRIFT-3499] - Add package_prefix to python generator + * [THRIFT-3495] - Minor enhancements and fixes for cross test + * [THRIFT-3486] - Java generated `getFieldValue` is incompatible with `setFieldValue` for binary values. + * [THRIFT-3484] - Consolidate temporary buffers in Java's TCompactProtocol + * [THRIFT-3516] - Add feature test for THeader TBinaryProtocol interop + * [THRIFT-3515] - Python 2.6 compatibility and test on CI + * [THRIFT-3514] - PHP 7 compatible version of binary protocol + * [THRIFT-3469] - Docker: Debian support + * [THRIFT-3416] - Retire old "xxx_namespace" declarations from the IDL + * [THRIFT-3426] - Align autogen comment in XSD + * [THRIFT-3424] - Add CMake android build option + * [THRIFT-3439] - Run make cross using Python3 when available + * [THRIFT-3440] - Python make check takes too much time + * [THRIFT-3441] - Stabilize Travis-CI builds + * [THRIFT-3431] - Avoid "schemes" HashMap lookups during struct reads/writes + * [THRIFT-3432] - Add a TByteBuffer transport to the Java library + * [THRIFT-3438] - Enable py:new_style by default + * [THRIFT-3405] - Go THttpClient misuses http.Client objects + * [THRIFT-3614] - Improve logging of test_sslsocket.py + * [THRIFT-3647] - Fix php extension build warnings + * [THRIFT-3642] - Speed up cross test runner + * [THRIFT-3637] - Implement compact protocol for dart + * [THRIFT-3613] - Port Python C extension to Python 3 + * [THRIFT-3612] - Add Python C extension for compact protocol + * [THRIFT-3611] - Add --regex filter to cross test runner + * [THRIFT-3631] - JSON protocol implementation for Lua + * [THRIFT-3609] - Remove or replace TestPortFixture.h + * [THRIFT-3605] - Have the compiler complain about invalid arguments and options + * [THRIFT-3596] - Better conformance to PEP8 + * [THRIFT-3585] - Compact protocol implementation for Lua + * [THRIFT-3582] - Erlang libraries should have service metadata + * [THRIFT-3579] - Introduce retry to make cross + * [THRIFT-3306] - Java: TBinaryProtocol: Use 1 temp buffer instead of allocating 8 + * [THRIFT-3910] - Do not invoke pip as part of build process + * [THRIFT-1857] - Python 3.X Support + * [THRIFT-1944] - Binding to zero port + * [THRIFT-3954] - Enable the usage of structs called "Object" in Java + * [THRIFT-3981] - Enable analyzer strong mode in Dart library + * [THRIFT-3998] - Document ability to add custom tags to thrift structs + * [THRIFT-4006] - Add a removeEventListener method on TSocket + +## New Feature + * [THRIFT-640] - Support deprecation + * [THRIFT-948] - SSL socket support for PHP + * [THRIFT-764] - add Support for Vala language + * [THRIFT-3046] - Allow PSR4 class loading for generated classes (PHP) + * [THRIFT-2113] - Erlang SSL Socket Support + * [THRIFT-1482] - Unix domain socket support under PHP + * [THRIFT-519] - Support collections of types without having to explicitly define it + * [THRIFT-468] - Rack Middleware Application for Rails + * [THRIFT-1708] - Add event handlers for processor events + * [THRIFT-3834] - Erlang namespacing and exception metadata + * [THRIFT-2510] - Implement TNonblockingServer's ability to listen on unix domain sockets + * [THRIFT-3397] - Implement TProcessorFactory in C# to enable per-client processors + * [THRIFT-3523] - XML Generator + * [THRIFT-3510] - Add HttpTaskAsyncHandler implementation + * [THRIFT-3318] - PHP: SimpleJSONProtocol Implementation + * [THRIFT-3299] - Dart language bindings in Thrift + * [THRIFT-2835] - Add possibility to distribute generators separately from thrift core, and load them dynamically + * [THRIFT-184] - Add OSGi Manifest headers to the libthrift java library to be able to use Thrift in the OSGi runtime + * [THRIFT-141] - If a required field is not present on serialization, throw an exception + * [THRIFT-1891] - Add Windows ALPC transport which is right counterpart of Unix domain sockets + +## Question + * [THRIFT-1808] - The Thrift struct should be considered self-contained? + * [THRIFT-2895] - Tutorial cpp + * [THRIFT-3860] - Elephant-bird application Test fails for Thrift + * [THRIFT-3811] - HTTPS Support for C++ applications + * [THRIFT-3509] - "make check" error + +## Story + * [THRIFT-3452] - .travis.yml: Migrating from legacy to container-based infrastructure + +## Sub-task + * [THRIFT-1811] - ruby tutorial as part of the regular build + * [THRIFT-2779] - PHP TJSONProtocol encode unicode into UCS-4LE which can't be parsed by other language bindings + * [THRIFT-2110] - Erlang: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-3852] - A Travis-CI job fails with "write error" + * [THRIFT-3740] - Fix haxelib.json classpath + * [THRIFT-3653] - incorrect union serialization + * [THRIFT-3652] - incorrect serialization of optionals + * [THRIFT-3655] - incorrect union serialization + * [THRIFT-3654] - incorrect serialization of optionals + * [THRIFT-3656] - incorrect serialization of optionals + * [THRIFT-3699] - Fix integer limit symbol includes in Python C extension + * [THRIFT-3693] - Fix include issue in C++ TSSLSocketInterruptTest on Windows + * [THRIFT-3694] - [Windows] Disable tests of a few servers that are not supported + * [THRIFT-3696] - Install pip to CentOS Docker images to fix Python builds + * [THRIFT-3638] - Fix haxelib.json + * [THRIFT-3251] - Add http transport for server to Go lib + * [THRIFT-2424] - Recursive Types + * [THRIFT-2423] - THeader + * [THRIFT-2413] - Python: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2409] - Java: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2412] - D: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2411] - C++: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2410] - JavaMe: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2668] - TestSuite: detailed result on passed tests by feature + * [THRIFT-2659] - python Test Server fails when throwing TException + * [THRIFT-3398] - Add CMake build for Haskell library and tests + * [THRIFT-3396] - DART: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-3364] - Fix ruby binary field encoding in TJSONProtocol + * [THRIFT-3381] - Fix for misc. codegen issues with THRIFT-2905 + * [THRIFT-3573] - No rule to make target `../../../test/c_glib/src/.deps/testthrifttest-thrift_test_handler.Po'. + * [THRIFT-3572] - "Unable to determine the behavior of a signed right shift" + * [THRIFT-3542] - Add length limit support to Java test server + * [THRIFT-3537] - Remove the (now obsolete) csharp:asyncctp flag + * [THRIFT-3532] - Add configurable string and container read size limit to Python protocols + * [THRIFT-3531] - Create cross lang feature test for string and container read length limit + * [THRIFT-3482] - Haskell JSON protocol does not encode binary field as Base64 + * [THRIFT-3425] - Minor fixes + simplification for CentOS Dockerfile + * [THRIFT-3442] - Run CMake tests on Appveyor + * [THRIFT-3409] - NodeJS binary field issues + * [THRIFT-3621] - Fix lib/cpp/test/SecurityTest.cpp to use ephemeral ports + * [THRIFT-3628] - Fix lib/cpp/test/TServerIntegrationTest.cpp to use ephemeral ports + * [THRIFT-3625] - Kill unused #include "TestPortFixture.h" in lib/cpp/test/TServerTransportTest.cpp. + * [THRIFT-3646] - Fix Python extension build warnings + * [THRIFT-3626] - Fix lib/cpp/test/TSocketInterruptTest.cpp to use ephemeral ports. + * [THRIFT-3624] - Fix lib/cpp/test/TServerSocketTest.cpp to use ephemeral ports + * [THRIFT-3623] - Fix Fix cpp/lib/test/TSSLSocketInterruptTest.cpp to use ephemeral ports + * [THRIFT-3592] - Add basic test client + * [THRIFT-3980] - add TExtendedBinaryProtocol.java + +## Task + * [THRIFT-1801] - Sync up TApplicationException codes across languages and thrift implementations + * [THRIFT-1259] - Automate versioning + +## Test + * [THRIFT-3400] - Add Erlang to cross test + * [THRIFT-3504] - Fix FastbinaryTest.py + +## Wish + * [THRIFT-3923] - Maybe remove Aereo from the "Powered by" list + * [THRIFT-2149] - Add an option to disable the generation of default operators + + + +Thrift 0.9.3 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-2441] - Cannot shutdown TThreadedServer when clients are still connected + * [THRIFT-2465] - TBinaryProtocolT breaks if copied/moved + * [THRIFT-2474] - thrift.h causes a compile failure + * [THRIFT-2540] - Running configure from outside the source directory fails + * [THRIFT-2598] - Add check for minimum Go version to configure.ac + * [THRIFT-2647] - compiler-hs: don't decapitalize field names, do decapitalize argument bindings + * [THRIFT-2773] - Generated Java code for 'oneway' methods is incorrect. + * [THRIFT-2789] - TNonblockingServer leaks socket FD's under load + * [THRIFT-2682] - TThreadedServer leaks per-thread memory + * [THRIFT-2674] - JavaScript: declare Accept: and Content-Type: in request + * [THRIFT-3078] - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket + * [THRIFT-3077] - C++ TFileTransport ignores return code from ftruncate + * [THRIFT-3067] - C++ cppcheck performance related warnings + * [THRIFT-3066] - C++ TDenseProtocol assert modifies instead of checks + * [THRIFT-3071] - bootstrap.sh on Ubuntu 12.04 (Precise) automake error + * [THRIFT-3069] - C++ TServerSocket leaks socket on fcntl get or set flags error + * [THRIFT-3079] - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket + * [THRIFT-3080] - C++ TNonblockingServer connection leak while accept huge number connections. + * [THRIFT-3086] - C++ Valgrind Error Cleanup + * [THRIFT-3085] - thrift_reconnecting_client never try to reconnect + * [THRIFT-3123] - Missing include in compiler/cpp/src/main.h breaks build in some environments + * [THRIFT-3125] - Fix the list of exported headers in automake input + * [THRIFT-3126] - PHP JSON serializer converts empty or int-indexed maps to lists + * [THRIFT-3132] - Properly format date in Java @Generated annotations + * [THRIFT-3137] - Travis build hangs after failure + * [THRIFT-3138] - "make check" parallel execution is underministic + * [THRIFT-3139] - JS library test is flaky + * [THRIFT-3140] - ConcurrentModificationException is thrown by JavaScript test server + * [THRIFT-3124] - Some signed/unsigned warnings while building compiler + * [THRIFT-3128] - Go generated code produces name collisions between services + * [THRIFT-3146] - Graphviz generates function name collisions between services + * [THRIFT-3147] - Segfault while receiving data + * [THRIFT-3148] - Markdown links to coding_standards are dead + * [THRIFT-3090] - cmake build is broken on MacOSX + * [THRIFT-3097] - cmake targets unconditionally depend on optional libraries + * [THRIFT-3094] - master as of 2015-APR-13 fails -DBOOST_THREADS cmake build + * [THRIFT-3099] - cmake build is broken on FreeBSD + * [THRIFT-3089] - Assigning default ENUM values results in non-compilable java code if java namespace is not defined + * [THRIFT-3093] - mingw compile fixes for c++ library 0.9.2 + * [THRIFT-3098] - Thrift does not pretty print binary typedefs the way it does binary fields + * [THRIFT-3091] - c_glib service method should return result from handler method + * [THRIFT-3088] - TThreadPoolServer with Sasl auth may leak CLOSE_WAIT socket + * [THRIFT-3109] - Cross test log file cannot be browsed when served in HTTP server + * [THRIFT-3113] - m4 C++11 macro issue + * [THRIFT-3105] - C++ libthriftnb library on Windows build failure + * [THRIFT-3115] - Uncompileable code due to name collision with predefined used types + * [THRIFT-3117] - Java TSSLTransportFactory can't load certificates within JAR archive + * [THRIFT-3102] - could not make check for Go Library + * [THRIFT-3120] - Minor spelling errors and an outdated URL + * [THRIFT-3121] - Librt does not exist on OS X + * [THRIFT-3152] - Compiler error on Mac OSX (missing #include ) + * [THRIFT-3162] - make fails for dmd 2.067 + * [THRIFT-3164] - Thrift C++ library SSL socket by default allows for unsecure SSLv3 negotiation + * [THRIFT-3168] - Fix Maven POM + * [THRIFT-3170] - Initialism code in the Go compiler causes chaos + * [THRIFT-3169] - Do not export thrift.TestStruct and thrift.TestEnum in thrift Go library + * [THRIFT-3191] - Perl compiler does not add support for unexpected exception handling + * [THRIFT-3178] - glib C does not compile + * [THRIFT-3189] - Perl ServerSocket should allow a specific interface to be listened to + * [THRIFT-3252] - Missing TConcurrentClientSyncInfo.h in cpp Makefile, so doesn't install + * [THRIFT-3255] - Thrift generator doesn't exclude 'package' keyword for thrift property names breaking java builds + * [THRIFT-3260] - multiple warnings in c_glib tutorial + * [THRIFT-3256] - Some D test timings are too aggressive for slow machines + * [THRIFT-3257] - warning: extra tokens at end of #endif directive + * [THRIFT-3184] - Thrift Go leaves file descriptors open + * [THRIFT-3203] - DOAP - please fix "Ocaml" => "OCaml" + * [THRIFT-3210] - (uncompileable) code generated for server events while are events not enabled + * [THRIFT-3215] - TJSONProtocol '(c++) uses "throw new" to throw exceptions instead of "throw" + * [THRIFT-3202] - Allow HSHAServer to configure min and max worker threads separately. + * [THRIFT-3205] - TCompactProtocol return a wrong error when the io.EOF happens + * [THRIFT-3209] - LGPL mentioned in license file + * [THRIFT-3197] - keepAliveTime is hard coded as 60 sec in TThreadPoolServer + * [THRIFT-3196] - Misspelling in lua TBinaryProtocol (stirctWrite => strictWrite) + * [THRIFT-3198] - Allow construction of TTransportFactory with a specified maxLength + * [THRIFT-3192] - Go import paths changed in 1.4, and expired June 1 + * [THRIFT-3271] - Could not find or load main class configtest_ax_javac_and_java on some non-english systems + * [THRIFT-3273] - c_glib: Generated code tries to convert between function and void pointers + * [THRIFT-3264] - Fix Erlang 16 namespaced types + * [THRIFT-3270] - reusing TNonblockingServer::TConnection cause dirty TSocket + * [THRIFT-3267] - c_glib: "Critical" failure during unit tests + * [THRIFT-3277] - THttpClient leaks connections if it's used for multiple requests + * [THRIFT-3278] - NodeJS: Fix exception stack traces and names + * [THRIFT-3279] - Fix a bug in retry_max_delay (NodeJS) + * [THRIFT-3280] - Initialize retry variables on construction + * [THRIFT-3283] - c_glib: Tutorial server always exits with warning + * [THRIFT-3284] - c_glib: Empty service produces unused-variable warning + * [THRIFT-1925] - c_glib generated code does not compile + * [THRIFT-1849] - after transport->open() opens isOpen returns true and next open() goes thru when it shall not + * [THRIFT-1866] - java compiler generates non-compiling code with const's defined in a thrift when name includes non-identifier chars + * [THRIFT-1938] - FunctionRunner.h -- uses wrong path for Thread.h when installed + * [THRIFT-1844] - Password string not cleared + * [THRIFT-2004] - Thrift::Union violates :== method contract and crashes + * [THRIFT-2073] - Thrift C++ THttpClient error: cannot refill buffer + * [THRIFT-2127] - Autoconf scripting does not properly account for cross-compile + * [THRIFT-2180] - Integer types issues in Cocoa lib on ARM64 + * [THRIFT-2189] - Go needs "isset" to fully support "union" type (and optionals) + * [THRIFT-2192] - autotools on Redhat based systems + * [THRIFT-2546] - cross language tests fails at 'TestMultiException' when using nodejs server + * [THRIFT-2547] - nodejs servers and clients fails to connect with cpp using compact protocol + * [THRIFT-2548] - Nodejs servers and clients does not work properly with -ssl + * [THRIFT-1471] - toString() does not print ByteBuffer values when nested in a List + * [THRIFT-1201] - getaddrinfo resource leak + * [THRIFT-615] - TThreadPoolServer doesn't call task_done after pulling tasks from it's clients queue + * [THRIFT-162] - Thrift structures are unhashable, preventing them from being used as set elements + * [THRIFT-810] - Crashed client on TSocket::close under loads + * [THRIFT-557] - charset problem with file Autogenerated by Thrift + * [THRIFT-233] - IDL doesn't support negative hex literals + * [THRIFT-1649] - contrib/zeromq does not build in 0.8.0 + * [THRIFT-1642] - Miscalculation lead to throw unexpected "TTransportException::TIMED_OUT"(or called "EAGAIN (timed out)") exception + * [THRIFT-1587] - TSocket::setRecvTimeout error + * [THRIFT-1248] - pointer subtraction in TMemoryBuffer relies on undefined behavior + * [THRIFT-1774] - Sasl Transport client would hang when trying to connect non-sasl transport server + * [THRIFT-1754] - RangeError in buffer handling + * [THRIFT-1618] - static structMap in FieldMetaData is not thread safe and can lead to deadlocks + * [THRIFT-2335] - thrift incompatibility with py:tornado as server, java as client + * [THRIFT-2803] - TCP_DEFER_ACCEPT not supported with domain sockets + * [THRIFT-2799] - Build Problem(s): ld: library not found for -l:libboost_unit_test_framework.a + * [THRIFT-2801] - C++ test suite compilation warnings + * [THRIFT-2802] - C++ tutorial compilation warnings + * [THRIFT-2795] - thrift_binary_protocol.c: 'dereferencing type-punned pointer will break strict-aliasing rules' + * [THRIFT-2817] - TSimpleJSONProtocol reads beyond end of message + * [THRIFT-2826] - html:standalone sometimes ignored + * [THRIFT-2829] - Support haxelib installation via github + * [THRIFT-2828] - slightly wrong help screen indent + * [THRIFT-2831] - Removes dead code in web_server.js introduced in THRIFT-2819 + * [THRIFT-2823] - All JS-tests are failing when run with grunt test + * [THRIFT-2827] - Thrift 0.9.2 fails to compile on Yosemite due to tr1/functional include in ProcessorTest.cpp + * [THRIFT-2843] - Automake configure.ac has possible typo related to Java + * [THRIFT-2813] - multiple haxe library fixes/improvements + * [THRIFT-2825] - Supplying unicode to python Thrift client can cause next request arguments to get overwritten + * [THRIFT-2840] - Cabal file points to LICENSE file outside the path of the Haskell project. + * [THRIFT-2818] - Trailing commas in array + * [THRIFT-2830] - Clean up ant warnings in tutorial dir + * [THRIFT-2842] - Erlang thrift client has infinite timeout + * [THRIFT-2810] - Do not leave the underlying ServerSocket open if construction of TServerSocket fails + * [THRIFT-2812] - Go server adding redundant buffering layer + * [THRIFT-2839] - TFramedTransport read bug + * [THRIFT-2844] - Nodejs support broken when running under Browserify + * [THRIFT-2814] - args/result classes not found when no namespace is set + * [THRIFT-2847] - function IfValue() is a duplicate of System.StrUtils.IfThen + * [THRIFT-2848] - certain Delphi tests do not build if TypeRegistry is used + * [THRIFT-2854] - Go Struct writer and reader looses important error information + * [THRIFT-2858] - Enable header field case insensitive match in THttpServer + * [THRIFT-2857] - C# generator creates uncompilable code for struct constants + * [THRIFT-2860] - Delphi server closes connection on unexpected exceptions + * [THRIFT-2868] - Enhance error handling in the Go client + * [THRIFT-2879] - TMemoryBuffer: using lua string in wrong way + * [THRIFT-2851] - Remove strange public Peek() from Go transports + * [THRIFT-2852] - Better Open/IsOpen/Close behavior for StreamTransport. + * [THRIFT-2871] - Missing semicolon in thrift.js + * [THRIFT-2872] - ThreadManager deadlock for task expiration + * [THRIFT-2881] - Handle errors from Accept() correctly + * [THRIFT-2849] - Spell errors reported by codespell tool + * [THRIFT-2870] - C++ TJSONProtocol using locale dependent formatting + * [THRIFT-2882] - Lua Generator: using string.len funtion to get struct(map,list,set) size + * [THRIFT-2864] - JSON generator missing from Visual Studio build project + * [THRIFT-2878] - Go validation support of required fields + * [THRIFT-2873] - TPipe and TPipeServer don't compile on Windows with UNICODE enabled + * [THRIFT-2888] - import of is missing in JSON generator + * [THRIFT-2900] - Python THttpClient does not reset socket timeout on exception + * [THRIFT-2907] - 'ntohll' macro redefined + * [THRIFT-2884] - Map does not serialize correctly for JSON protocol in Go library + * [THRIFT-2887] - --with-openssl configure flag is ignored + * [THRIFT-2894] - PHP json serializer skips maps with int/bool keys + * [THRIFT-2904] - json_protocol_test.go fails + * [THRIFT-2906] - library not found for -l:libboost_unit_test_framework.a + * [THRIFT-2890] - binary data may lose bytes with JSON transport under specific circumstances + * [THRIFT-2891] - binary data may cause a failure with JSON transport under specific circumstances + * [THRIFT-2901] - Fix for generated TypeScript functions + indentation of JavaScript maps + * [THRIFT-2916] - make check fails for D language + * [THRIFT-2918] - Race condition in Python TProcessPoolServer test + * [THRIFT-2920] - Erlang Thrift test uses wrong IDL file + * [THRIFT-2922] - $TRIAL is used with Python tests but not tested accordingly + * [THRIFT-2912] - Autotool build for C++ Qt library is invalid + * [THRIFT-2914] - explicit dependency to Lua5.2 fails on some systems + * [THRIFT-2910] - libevent is not really optional + * [THRIFT-2911] - fix c++ version zeromq transport, the old version cannot work + * [THRIFT-2915] - Lua generator missing from Visual Studio build project + * [THRIFT-2917] - "make clean" breaks test/c_glib + * [THRIFT-2919] - Haxe test server timeout too large + * [THRIFT-2923] - JavaScript client assumes a message being written + * [THRIFT-2924] - TNonblockingServer crashes when user-provided event_base is used + * [THRIFT-2925] - CMake build does not work with OpenSSL nor anything installed in non-system location + * [THRIFT-2931] - Access to undeclared static property: Thrift\Protocol\TProtocol::$TBINARYPROTOCOLACCELERATED + * [THRIFT-2893] - CMake build fails with boost thread or std thread + * [THRIFT-2902] - Generated c_glib code does not compile with clang + * [THRIFT-2903] - Qt4 library built with CMake does not work + * [THRIFT-2942] - CSharp generate invalid code for property named read or write + * [THRIFT-2932] - Node.js Thrift connection libraries throw Exceptions into event emitter + * [THRIFT-2933] - v0.9.2: doubles encoded in node with compact protocol cannot be decoded by python + * [THRIFT-2934] - createServer signature mismatch + * [THRIFT-2981] - IDL with no namespace produces unparsable PHP + * [THRIFT-2999] - Addition of .gitattributes text auto in THRIFT-2724 causes modified files on checkout + * [THRIFT-2949] - typo in compiler/cpp/README.md + * [THRIFT-2957] - warning: source file %s is in a subdirectory, but option 'subdir-objects' is disabled + * [THRIFT-2953] - TNamedPipeServerTransport is not Stop()able + * [THRIFT-2962] - Docker Thrift env for development and testing + * [THRIFT-2971] - C++ test and tutorial parallel build is unstable + * [THRIFT-2972] - Missing backslash in lib/cpp/test/Makefile.am + * [THRIFT-2951] - Fix Erlang name conflict test + * [THRIFT-2955] - Using list of typedefs does not compile on Go + * [THRIFT-2960] - namespace regression for Ruby + * [THRIFT-2959] - nodejs: fix binary unit tests + * [THRIFT-2966] - nodejs: Fix bad references to TProtocolException and TProtocolExceptionType + * [THRIFT-2970] - grunt-jsdoc fails due to dependency issues + * [THRIFT-3001] - C# Equals fails for binary fields (byte[]) + * [THRIFT-3003] - Missing LICENSE file prevents package from being installed + * [THRIFT-3008] - Node.js server does not fully support exception + * [THRIFT-3007] - Travis build is broken because of directory conflict + * [THRIFT-3009] - TSSLSocket does not use the correct hostname (breaks certificate checks) + * [THRIFT-3011] - C# test server testException() not implemented according to specs + * [THRIFT-3012] - Timing problems in NamedPipe implementation due to unnecessary open/close + * [THRIFT-3019] - Golang generator missing docstring for structs + * [THRIFT-3021] - Service remote tool does not import stub package with package prefix + * [THRIFT-3026] - TMultiplexedProcessor does not have a constructor + * [THRIFT-3028] - Regression caused by THRIFT-2180 + * [THRIFT-3017] - order of map key/value types incorrect for one CTOR + * [THRIFT-3020] - Cannot compile thrift as C++03 + * [THRIFT-3024] - User-Agent "BattleNet" used in some Thrift library files + * [THRIFT-3047] - Uneven calls to indent_up and indent_down in Cocoa generator + * [THRIFT-3048] - NodeJS decoding of I64 is inconsistent across protocols + * [THRIFT-3043] - go compiler generator uses non C++98 code + * [THRIFT-3044] - Docker README.md paths to Dockerfiles are incorrect + * [THRIFT-3040] - bower.json wrong "main" path + * [THRIFT-3051] - Go Thrift generator creates bad go code + * [THRIFT-3057] - Java compiler build is broken + * [THRIFT-3061] - C++ TSSLSocket shutdown delay/vulnerability + * [THRIFT-3062] - C++ TServerSocket invalid port number (over 999999) causes stack corruption + * [THRIFT-3065] - Update libthrift dependencies (slf4j, httpcore, httpclient) + * [THRIFT-3244] - TypeScript: fix namespace of included types + * [THRIFT-3246] - Reduce the number of trivial warnings in Windows C++ CMake builds + * [THRIFT-3224] - Fix TNamedPipeServer unpredictable behavior on accept + * [THRIFT-3230] - Python compiler generates wrong code if there is function throwing a typedef of exception with another namespace + * [THRIFT-3236] - MaxSkipDepth never checked + * [THRIFT-3239] - Limit recursion depth + * [THRIFT-3241] - fatal error: runtime: cannot map pages in arena address space + * [THRIFT-3242] - OSGi Import-Package directive is missing the Apache HTTP packages + * [THRIFT-3234] - Limit recursion depth + * [THRIFT-3222] - TypeScript: Generated Enums are quoted + * [THRIFT-3229] - unexpected Timeout exception when desired bytes are only partially available + * [THRIFT-3231] - CPP: Limit recursion depth to 64 + * [THRIFT-3235] - Limit recursion depth + * [THRIFT-3175] - fastbinary.c python deserialize can cause huge allocations from garbage + * [THRIFT-3176] - Union incorrectly implements == + * [THRIFT-3177] - Fails to run rake test + * [THRIFT-3180] - lua plugin: framed transport do not work + * [THRIFT-3179] - lua plugin cant connect to remote server because function l_socket_create_and_connect always bind socket to localhost + * [THRIFT-3248] - TypeScript: additional comma in method signature without parameters + * [THRIFT-3302] - Go JSON protocol should encode Thrift byte type as signed integer string + * [THRIFT-3297] - c_glib: an abstract base class is not generated + * [THRIFT-3294] - TZlibTransport for Java does not write data correctly + * [THRIFT-3296] - Go cross test does not conform to spec + * [THRIFT-3295] - C# library does not build on Mono 4.0.2.5 or later + * [THRIFT-3293] - JavaScript: null values turn into empty structs in constructor + * [THRIFT-3310] - lib/erl/README.md has incorrect formatting + * [THRIFT-3319] - CSharp tutorial will not build using the *.sln + * [THRIFT-3335] - Ruby server does not handle processor exception + * [THRIFT-3338] - Stray underscore in generated go when service name starts with "New" + * [THRIFT-3324] - Update Go Docs for pulling all packages + * [THRIFT-3345] - Clients blocked indefinitely when a java.lang.Error is thrown + * [THRIFT-3332] - make dist fails on clean build + * [THRIFT-3326] - Tests do not compile under *BSD + * [THRIFT-3334] - Markdown notation of protocol spec is malformed + * [THRIFT-3331] - warning: ‘etype’ may be used uninitialized in this function + * [THRIFT-3349] - Python server does not handle processor exception + * [THRIFT-3343] - Fix haskell README + * [THRIFT-3340] - Python: enable json tests again + * [THRIFT-3311] - Top level README.md has incorrect formmating + * [THRIFT-2936] - Minor memory leak in SSL + * [THRIFT-3290] - Using from in variable names causes the generated Python code to have errors + * [THRIFT-3225] - Fix TPipeServer unpredictable behavior on interrupt() + * [THRIFT-3354] - Fix word-extraction substr bug in initialism code + * [THRIFT-2006] - TBinaryProtocol message header call name length is not validated and can be used to core the server + * [THRIFT-3329] - C++ library unit tests don't compile against the new boost-1.59 unit test framework + * [THRIFT-2630] - windows7 64bit pc. ipv4 and ipv6 pc.can't use + * [THRIFT-3336] - Thrift generated streaming operators added in 0.9.2 cannot be overridden + * [THRIFT-2681] - Core of unwind_cleanup + * [THRIFT-3317] - cpp namespace org.apache issue appears in 0.9 + +## Documentation + * [THRIFT-3286] - Apache Ant is a necessary dependency + +## Improvement + * [THRIFT-227] - Byte[] in collections aren't pretty printed like regular binary fields + * [THRIFT-2744] - Vagrantfile for Centos 6.5 + * [THRIFT-2644] - Haxe support + * [THRIFT-2756] - register Media Type @ IANA + * [THRIFT-3076] - Compatibility with Haxe 3.2.0 + * [THRIFT-3081] - C++ Consolidate client processing loops in TServers + * [THRIFT-3083] - C++ Consolidate server processing loops in TSimpleServer, TThreadedServer, TThreadPoolServer + * [THRIFT-3084] - C++ add concurrent client limit to threaded servers + * [THRIFT-3074] - Add compiler/cpp/lex.yythriftl.cc to gitignore. + * [THRIFT-3134] - Remove use of deprecated "phantom.args" + * [THRIFT-3133] - Allow "make cross" and "make precross" to run without building all languages + * [THRIFT-3142] - Make JavaScript use downloaded libraries + * [THRIFT-3141] - Improve logging of JavaScript test + * [THRIFT-3144] - Proposal: make String representation of enums in generated go code less verbose + * [THRIFT-3130] - Remove the last vestiges of THRIFT_OVERLOAD_IF from THRIFT-1316 + * [THRIFT-3131] - Consolidate suggested import path for go thrift library to git.apache.org in docs and code + * [THRIFT-3092] - Generated Haskell types should derive Generic + * [THRIFT-3110] - Print error log after cross test failures on Travis + * [THRIFT-3114] - Using local temp variables to not pollute the global table + * [THRIFT-3106] - CMake summary should give more information why a library is set to off + * [THRIFT-3119] - Java's TThreadedSelectorServer has indistinguishable log messages in run() + * [THRIFT-3122] - Javascript struct constructor should properly initialize struct and container members from plain js arguments + * [THRIFT-3151] - Fix links to git-wip* - should be git.apache.org + * [THRIFT-3167] - Windows build from source instructions need to be revised + * [THRIFT-3155] - move contrib/mingw32-toolchain.cmake to build/cmake/ + * [THRIFT-3160] - Make generated go enums implement TextMarshaller and TextUnmarshaller interfaces + * [THRIFT-3150] - Add an option to thrift go generator to make Read and Write methods private + * [THRIFT-3149] - Make ReadFieldN methods in generated Go code private + * [THRIFT-3172] - Add tutorial to Thrift web site + * [THRIFT-3214] - Add Erlang option for using maps instead of dicts + * [THRIFT-3201] - Capture github test artifacts for failed builds + * [THRIFT-3266] - c_glib: Multiple compiler warnings building unit tests + * [THRIFT-3285] - c_glib: Build library with all warnings enabled, no warnings generated + * [THRIFT-1954] - Allow for a separate connection timeout value + * [THRIFT-2098] - Add support for Qt5+ + * [THRIFT-2199] - Remove Dense protocol (was: move to Contrib) + * [THRIFT-406] - C++ Test suite cleanup + * [THRIFT-902] - socket and connect timeout in TSocket should be distinguished + * [THRIFT-388] - Use a separate wire format for async calls + * [THRIFT-727] - support native C++ language specific exception message + * [THRIFT-1784] - pep-3110 compliance for exception handling + * [THRIFT-1025] - C++ ServerSocket should inherit from Socket with the necessary Ctor to listen on connections from a specific host + * [THRIFT-2269] - Can deploy libthrift-source.jar to maven center repository + * [THRIFT-2804] - Pull an interface out of TBaseAsyncProcessor + * [THRIFT-2806] - more whitespace fixups + * [THRIFT-2811] - Make remote socket address accessible + * [THRIFT-2809] - .gitignore update for compiler's visual project + * [THRIFT-2846] - Expose ciphers parameter from ssl.wrap_socket() + * [THRIFT-2859] - JSON generator: output complete descriptors + * [THRIFT-2861] - add buffered transport + * [THRIFT-2865] - Test case for Go: SeqId out of sequence + * [THRIFT-2866] - Go generator source code is hard to read and maintain + * [THRIFT-2880] - Read the network address from the listener if available. + * [THRIFT-2875] - Typo in TDenseProtocol.h comment + * [THRIFT-2874] - TBinaryProtocol member variable "string_buf_" is never used. + * [THRIFT-2855] - Move contributing.md to the root of the repository + * [THRIFT-2862] - Enable RTTI and/or build macros for generated code + * [THRIFT-2876] - Add test for THRIFT-2526 Assignment operators and copy constructors in c++ don't copy the __isset struct + * [THRIFT-2897] - Generate -isEqual: and -hash methods + * [THRIFT-2909] - Improve travis build + * [THRIFT-2921] - Make Erlang impl ready for OTP 18 release (dict/0 and set/0 are deprecated) + * [THRIFT-2928] - Rename the erlang test_server module + * [THRIFT-2940] - Allow installing Thrift from git as NPM module by providing package.json in top level directory + * [THRIFT-2937] - Allow setting a maximum frame size in TFramedTransport + * [THRIFT-2976] - nodejs: xhr and websocket support for browserify + * [THRIFT-2996] - Test for Haxe 3.1.3 or better + * [THRIFT-2969] - nodejs: DRY up library tests + * [THRIFT-2973] - Update Haxe lib readme regarding Haxe 3.1.3 + * [THRIFT-2952] - Improve handling of Server.Stop() + * [THRIFT-2964] - nodejs: move protocols and transports into separate files + * [THRIFT-2963] - nodejs - add test coverage + * [THRIFT-3006] - Attach 'omitempty' json tag for optional fields in Go + * [THRIFT-3027] - Go compiler does not ensure common initialisms have consistent case + * [THRIFT-3030] - TThreadedServer: Property for number of clientThreads + * [THRIFT-3023] - Go compiler is a little overly conservative with names of attributes + * [THRIFT-3018] - Compact protocol for Delphi + * [THRIFT-3025] - Change pure Int constants into @enums (where possible) + * [THRIFT-3031] - migrate "shouldStop" flag to TServer + * [THRIFT-3022] - Compact protocol for Haxe + * [THRIFT-3041] - Generate asynchronous clients for Cocoa + * [THRIFT-3053] - Perl SSL Socket Support (Encryption) + * [THRIFT-3247] - Generate a C++ thread-safe client + * [THRIFT-3217] - Provide a little endian variant of the binary protocol in C++ + * [THRIFT-3223] - TypeScript: Add initial support for Enum Maps + * [THRIFT-3220] - Option to suppress @Generated Annotation entirely + * [THRIFT-3300] - Reimplement TZlibTransport in Java using streams + * [THRIFT-3288] - c_glib: Build unit tests with all warnings enabled, no warnings generated + * [THRIFT-3347] - Improve cross test servers and clients + * [THRIFT-3342] - Improve ruby cross test client and server compatibility + * [THRIFT-2296] - Add C++ Base class for service + * [THRIFT-3337] - Add testBool method to cross tests + * [THRIFT-3303] - Disable concurrent cabal jobs on Travis to avoid GHC crash + * [THRIFT-2623] - Docker container for Thrift + * [THRIFT-3298] - thrift endian converters may conflict with other libraries + * [THRIFT-1559] - Provide memory pool for TBinaryProtocol to eliminate memory fragmentation + * [THRIFT-424] - Steal ProtocolBuffers' VarInt implementation for C++ + +## New Feature + * [THRIFT-3070] - Add ability to set the LocalCertificateSelectionCallback + * [THRIFT-1909] - Java: Add compiler flag to use the "option pattern" for optional fields + * [THRIFT-2099] - Stop TThreadPoolServer with alive connections. + * [THRIFT-123] - implement TZlibTransport in Java + * [THRIFT-2368] - New option: reuse-objects for Java generator + * [THRIFT-2836] - Optionally generate C++11 MoveConstructible types + * [THRIFT-2824] - Flag to disable html escaping doctext + * [THRIFT-2819] - Add WebsSocket client to node.js + * [THRIFT-3050] - Client certificate authentication for non-http TLS in C# + * [THRIFT-3292] - Implement TZlibTransport in Go + +## Question + * [THRIFT-2583] - Thrift on xPC target (SpeedGoat) + * [THRIFT-2592] - thrift server using c_glib + * [THRIFT-2832] - c_glib: Handle string lists correctly + * [THRIFT-3136] - thrift installation problem on mac + * [THRIFT-3346] - c_glib: Tutorials example crashes saying Calculator.ping implementation returned FALSE but did not set an error + +## Sub-task + * [THRIFT-2578] - Moving 'make cross' from test.sh to test.py + * [THRIFT-2734] - Go coding standards + * [THRIFT-2748] - Add Vagrantfile for Centos 6.5 + * [THRIFT-2753] - Misc. Haxe improvements + * [THRIFT-2640] - Compact Protocol in Cocoa + * [THRIFT-3262] - warning: overflow in implicit constant conversion in DenseProtoTest.cpp + * [THRIFT-3194] - Can't build with go enabled. gomock SCC path incorrect. + * [THRIFT-3275] - c_glib tutorial warnings in generated code + * [THRIFT-1125] - Multiplexing support for the Ruby Library + * [THRIFT-2807] - PHP Code Style + * [THRIFT-2841] - Add comprehensive integration tests for the whole Go stack + * [THRIFT-2815] - Haxe: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-2886] - Integrate binary type in standard Thrift cross test + * [THRIFT-2946] - Enhance usability of cross test framework + * [THRIFT-2967] - Add .editorconfig to root + * [THRIFT-3033] - Perl: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-3174] - Initialism code in the Go compiler doesn't check first word + * [THRIFT-3193] - Option to supress date value in @Generated annotation + * [THRIFT-3305] - Missing dist files for 0.9.3 release candidate + * [THRIFT-3341] - Add testBool methods + * [THRIFT-3308] - Fix broken test cases for 0.9.3 release candidate + +## Task + * [THRIFT-2834] - Remove semi-colons from python code generator + * [THRIFT-2853] - Adjust comments not applying anymore after THRIFT-2852 + +## Test + * [THRIFT-3211] - Add make cross support for php TCompactProtocol + +## Wish + * [THRIFT-2838] - TNonblockingServer can bind to port 0 (i.e., get an OS-assigned port) but there is no way to get the port number + + + +Thrift 0.9.2 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-2793] - Go compiler produces uncompilable code + * [THRIFT-1481] - Unix domain sockets in C++ do not support the abstract namespace + * [THRIFT-1455] - TBinaryProtocolT::writeString casts from size_t to uint32_t, which is not safe on 64-bit platforms + * [THRIFT-1579] - PHP Extention - function thrift_protocol_read_binary not working from TBinarySerializer::deserialize + * [THRIFT-1584] - Error: could not SetMinThreads in ThreadPool on single-core machines + * [THRIFT-1614] - Thrift build from svn repo sources fails with automake-1.12 + * [THRIFT-1047] - rb_thrift_memory_buffer_write treats arg as string without check, segfaults if you pass non-string + * [THRIFT-1639] - Java/Python: Serialization/Deserialization of double type using CompactProtocol + * [THRIFT-1647] - NodeJS BufferedTransport does not work beyond the hello-world example + * [THRIFT-2130] - Thrift's D library/test: parts of "make check" code do not compile with recent dmd-2.062 through dmd-2.064alpha + * [THRIFT-2140] - Error compiling cpp tutorials + * [THRIFT-2139] - MSVC 2012 Error - Cannot compile due to BoostThreadFactory + * [THRIFT-2138] - pkgconfig file created with wrong include path + * [THRIFT-2160] - Warning in thrift.h when compiling with -Wunused and NDEBUG + * [THRIFT-2158] - Compact, JSON, and SimpleJSON protocols are not working correctly + * [THRIFT-2167] - nodejs lib throws error if options argument isn't passed + * [THRIFT-2288] - Go impl of Thrift JSON protocol wrongly writes/expects true/false for bools + * [THRIFT-2147] - Thrift IDL grammar allows for dotted identifier names + * [THRIFT-2145] - Rack and Thin are not just development dependencies + * [THRIFT-2267] - Should be able to choose socket family in Python TSocket + * [THRIFT-2276] - java path in spec file needs updating + * [THRIFT-2281] - Generated send/recv code ignores errors returned by the underlying protocol + * [THRIFT-2280] - TJSONProtocol.Flush() does not really flush the transport + * [THRIFT-2274] - TNonblockingServer and TThreadedSelectorServer do not close their channel selectors on exit and leak file descriptors + * [THRIFT-2265] - php library doesn't build + * [THRIFT-2232] - IsSet* broken in Go + * [THRIFT-2246] - Unset enum value is printed by ToString() + * [THRIFT-2240] - thrift.vim (contrib) does not correctly handle 'union' + * [THRIFT-2243] - TNonblockingServer in thrift crashes when TFramedTransport opens + * [THRIFT-2230] - Cannot Build on RHEL/Centos/Amazon Linux 6.x + * [THRIFT-2247] - Go generator doesn't deal well with map keys of type binary + * [THRIFT-2253] - Python Tornado TTornadoServer base class change + * [THRIFT-2261] - java: error: unmappable character for encoding ASCII + * [THRIFT-2259] - C#: unexpected null logDelegate() pointer causes AV in TServer.serve() + * [THRIFT-2225] - SSLContext destroy before cleanupOpenSSL + * [THRIFT-2224] - TSSLSocket.h and TSSLServerSocket.h should use the platfromsocket too + * [THRIFT-2229] - thrift failed to build on OSX 10.9 GM + * [THRIFT-2227] - Thrift compiler generates spurious warnings with Xlint + * [THRIFT-2219] - Thrift gem fails to build on OS X Mavericks with 1.9.3 rubies + * [THRIFT-2226] - TServerSocket - keepAlive wrong initialization order + * [THRIFT-2285] - TJsonProtocol implementation for Java doesn't allow a slash (/) to be escaped (\/) + * [THRIFT-2216] - Extraneous semicolon in TProtocolUtil.h makes clang mad + * [THRIFT-2215] - Generated HTML/Graphviz lists referenced enum identifiers as UNKNOWN. + * [THRIFT-2211] - Exception constructor does not contain namespace prefix. + * [THRIFT-2210] - lib/java TSimpleJSONProtocol can emit invalid JSON + * [THRIFT-2209] - Ruby generator -- please namespace classes + * [THRIFT-2202] - Delphi TServerImpl.DefaultLogDelegate may stop the server with I/O-Error 105 + * [THRIFT-2201] - Ternary operator returns different types (build error for some compilers) + * [THRIFT-2200] - nested structs cause generate_fingerprint() to slow down at excessive CPU load + * [THRIFT-2197] - fix jar output directory in rpm spec file + * [THRIFT-2196] - Fix invalid dependency in Makefile.am + * [THRIFT-2194] - Node: Not actually prepending residual data in TFramedTransport.receiver + * [THRIFT-2193] - Java code generator emits spurious semicolon when deep copying binary data + * [THRIFT-2191] - Fix charp JSONProtocol.ReadJSONDouble (specify InvariantCulture) + * [THRIFT-2214] - System header sys/param.h is included inside the Thrift namespace + * [THRIFT-2178] - Thrift generator returns error exit code on --version + * [THRIFT-2171] - NodeJS implementation has extremely low test coverage + * [THRIFT-2183] - gem install fails on zsh + * [THRIFT-2182] - segfault in regression tests (GC bug in rb_thrift_memory_buffer_write) + * [THRIFT-2181] - oneway calls don't work in NodeJS + * [THRIFT-2169] - JavaME Thrift Library causes "java.io.IOException: No Response Entries Available" after using the Thrift client for some time + * [THRIFT-2168] - Node.js appears broken (at least, examples don't work as intended) + * [THRIFT-2293] - TSSLTransportFactory.createSSLContext() leaves files open + * [THRIFT-2279] - TSerializer only returns the first 1024 bytes serialized + * [THRIFT-2278] - Buffered transport doesn't support writes > buffer size + * [THRIFT-2275] - Fix memory leak in golang compact_protocol. + * [THRIFT-2282] - Incorect code generated for some typedefs + * [THRIFT-2009] - Go redeclaration error + * [THRIFT-1964] - 'Isset' causes problems with C#/.NET serializers + * [THRIFT-2026] - Fix TCompactProtocol 64 bit builds + * [THRIFT-2108] - Fix TAsyncClientManager timeout race + * [THRIFT-2068] - Multiple calls from same connection are not processed in node + * [THRIFT-1750] - Make compiler build cleanly under visual studio 10 + * [THRIFT-1755] - Comment parsing bug + * [THRIFT-1771] - "make check" fails on x64 for libboost_unit_test_framework.a + * [THRIFT-1841] - NodeJS Thrift incorrectly parses non-UTF8-string types + * [THRIFT-1908] - Using php thrift_protocol accelerated transfer causes core dump + * [THRIFT-1892] - Socket timeouts are declared in milli-seconds, but are actually set in micro-seconds + * [THRIFT-2303] - TBufferredTransport not properly closing underlying transport + * [THRIFT-2313] - nodejs server crash after processing the first request when using MultiplexedProcessor/FramedBuffer/BinaryProtocol + * [THRIFT-2311] - Go: invalid code generated when exception name is a go keyword + * [THRIFT-2308] - node: TJSONProtocol parse error when reading from buffered message + * [THRIFT-2316] - ccp: TFileTransportTest + * [THRIFT-2352] - msvc failed to compile thrift tests + * [THRIFT-2337] - Golang does not report TIMED_OUT exceptions + * [THRIFT-2340] - Generated server implementation does not send response type EXCEPTION on the Thrift.TApplicationExceptionType.UNKNOWN_METHOD exception + * [THRIFT-2354] - Connection errors can lead to case_clause exceptions + * [THRIFT-2339] - Uncaught exception in thrift c# driver + * [THRIFT-2356] - c++ thrift client not working with ssl (SSL_connect hangs) + * [THRIFT-2331] - Missing call to ReadStructBegin() in TApplicationException.Read() + * [THRIFT-2323] - Uncompileable Delphi code generated for typedef'd structs + * [THRIFT-2322] - Correctly show the number of times ExecutorService (java) has rejected the client. + * [THRIFT-2389] - namespaces handled wrongly in acrionscript 3.0 implementation + * [THRIFT-2388] - GoLang - Fix data races in simple_server and server_socket + * [THRIFT-2386] - Thrift refuses to link yylex + * [THRIFT-2375] - Excessive
's in generated HTML + * [THRIFT-2373] - warning CS0414 in THttpClient.cs: private field 'Thrift.Transport.THttpClient.connection' assigned but never used + * [THRIFT-2372] - thrift/json_protocol.go:160: function ends without a return statement + * [THRIFT-2371] - ruby bundler version fails on ~1.3.1, remove and take latest avail + * [THRIFT-2370] - Compiler SEGFAULTs generating HTML documentation for complex strucre + * [THRIFT-2384] - Binary map keys produce uncompilable code in go + * [THRIFT-2380] - unreachable code (CID 1174546, CID 1174679) + * [THRIFT-2378] - service method arguments of binary type lead to uncompileable Go code + * [THRIFT-2363] - Issue with character encoding of Success returned from Login using Thrift Proxy and NodeJS + * [THRIFT-2359] - TBufferedTransport doesn't clear it's buffer on a failed flush call + * [THRIFT-2428] - Python 3 setup.py support + * [THRIFT-2367] - Build failure: stdlib and boost both define uint64_t + * [THRIFT-2365] - C# decodes too many binary bytes from JSON + * [THRIFT-2402] - byte count of FrameBuffer in AWAITING_CLOSE state is not subtracted from readBufferBytesAllocated + * [THRIFT-2396] - Build Error on MacOSX + * [THRIFT-2395] - thrift Ruby gem requires development dependency 'thin' regardless of environment + * [THRIFT-2414] - c_glib fix several bug. + * [THRIFT-2420] - Go argument parser for methods without arguments does not skip fields + * [THRIFT-2439] - Bug in TProtocolDecorator Class causes parsing errors + * [THRIFT-2419] - golang - Fix fmt.Errorf in generated code + * [THRIFT-2418] - Go handler function panics on internal error + * [THRIFT-2405] - Node.js Multiplexer tests fail (silently) + * [THRIFT-2581] - TFDTransport destructor should not throw + * [THRIFT-2575] - Thrift includes siginfo_t within apache::thrift::protocol namespace + * [THRIFT-2577] - TFileTransport missuse of closesocket on windows platform + * [THRIFT-2576] - Implement Thrift.Protocol.prototype.skip method in JavaScript library + * [THRIFT-2588] - Thrift compiler is not buildable in Visual Studio 2010 + * [THRIFT-2594] - JS Compiler: Single quotes are not being escaped in constants. + * [THRIFT-2591] - TFramedTransport does not handle payloads split across packets correctly + * [THRIFT-2599] - Uncompileable Delphi code due to naming conflicts with IDL + * [THRIFT-2590] - C++ Visual Studio solution doesn't include Multiplexing support + * [THRIFT-2595] - Node.js: Fix global leaks and copy-paste errors + * [THRIFT-2565] - autoconf fails to find mingw-g++ cross compiler on travis CI + * [THRIFT-2555] - excessive "unused field" comments + * [THRIFT-2554] - double initialization in generated Read() method + * [THRIFT-2551] - OutOfMemoryError "unable to create new native thread" kills serve thread + * [THRIFT-2543] - Generated enum type in haskell should be qualified + * [THRIFT-2560] - Thrift compiler generator tries to concat ints with strings using + + * [THRIFT-2559] - Centos 6.5 unable to "make" with Thrift 0.9.1 + * [THRIFT-2526] - Assignment operators and copy constructors in c++ don't copy the __isset struct + * [THRIFT-2454] - c_glib: There is no gethostbyname_r() in some OS. + * [THRIFT-2451] - Do not use pointers for optional fields with defaults. Do not write such fields if its value set to default. Also, do not use pointers for any optional fields mapped to go map or slice. generate Get accessors + * [THRIFT-2450] - include HowToContribute in the src repo + * [THRIFT-2448] - thrift/test/test.sh has incorrect Node.js test path + * [THRIFT-2460] - unopened socket fd must be less than zero. + * [THRIFT-2459] - --version should not exit 1 + * [THRIFT-2468] - Timestamp handling + * [THRIFT-2467] - Unable to build contrib/fb303 on OSX 10.9.2 + * [THRIFT-2466] - Improper error handling for SSL/TLS connections that don't complete a handshake + * [THRIFT-2463] - test/py/RunClientServer.py fails sometimes + * [THRIFT-2458] - Generated golang server code for "oneway" methods is incorrect + * [THRIFT-2456] - THttpClient fails when using async support outside Silverlight + * [THRIFT-2524] - Visual Studio project is missing TThreadedServer files + * [THRIFT-2523] - Visual Studio project is missing OverlappedSubmissionThread files + * [THRIFT-2520] - cpp:cob_style generates incorrect .tcc file + * [THRIFT-2508] - Uncompileable C# code due to language keywords in IDL + * [THRIFT-2506] - Update TProtocolException error codes to be used consistently throughout the library + * [THRIFT-2505] - go: struct should always be a pointer to avoid copying of potentially size-unbounded structs + * [THRIFT-2515] - TLS Method error during make + * [THRIFT-2503] - C++: Fix name collision when a struct has a member named "val" + * [THRIFT-2477] - thrift --help text with misplaced comma + * [THRIFT-2492] - test/cpp does not compile on mac + * [THRIFT-2500] - sending random data crashes thrift(golang) service + * [THRIFT-2475] - c_glib: buffered_transport_write function return always TRUE. + * [THRIFT-2495] - JavaScript/Node string constants lack proper escaping + * [THRIFT-2491] - unable to import generated ThriftTest service + * [THRIFT-2490] - c_glib: if fail to read a exception from server, client may be occurred double free + * [THRIFT-2470] - THttpHandler swallows exceptions from processor + * [THRIFT-2533] - Boost version in requirements should be updated + * [THRIFT-2532] - Java version in installation requirements should be updated + * [THRIFT-2529] - TBufferedTransport split Tcp data bug in nodeJs + * [THRIFT-2537] - Path for "go get" does not work (pull request 115) + * [THRIFT-2443] - Node fails cross lang tests + * [THRIFT-2437] - Author fields in Python setup.py must be strings not lists. + * [THRIFT-2435] - Java compiler doesn't like struct member names that are identical to an existing enum or struct type + * [THRIFT-2434] - Missing namespace import for php TMultiplexedProcessor implementation + * [THRIFT-2432] - Flaky parallel build + * [THRIFT-2430] - Crash during TThreadPoolServer shutdown + * [THRIFT-667] - Period should not be allowed in identifier names + * [THRIFT-1212] - Members capital case conflict + * [THRIFT-2584] - Error handler not listened on javascript client + * [THRIFT-2294] - Incorrect Makefile generation + * [THRIFT-2601] - Fix vagrant to work again for builds again + * [THRIFT-2092] - TNonblocking server should release handler as soon as connection closes + * [THRIFT-2557] - CS0542 member names cannot be the same as their enclosing type + * [THRIFT-2605] - TSocket warning on gcc 4.8.3 + * [THRIFT-2607] - ThreadManager.cpp warning on clang++ 3.4 + * [THRIFT-1998] - TCompactProtocol.tcc - one more warning on Visual 2010 + * [THRIFT-2610] - MSVC warning in TSocket.cpp + * [THRIFT-2614] - TNonblockingServer.cpp warnings on MSVC + * [THRIFT-2608] - TNonblockingServer.cpp warnings on clang 3.4 + * [THRIFT-2606] - ThreadManager.h warning in clang++ 3.4 + * [THRIFT-2609] - TFileTransport.h unused field warning (clang 3.4) + * [THRIFT-2416] - Cannot use TCompactProtocol with MSVC + * [THRIFT-1803] - Ruby Thrift 0.9.0 tries to encode UUID to UTF8 and crashes + * [THRIFT-2385] - Problem with gethostbyname2 during make check + * [THRIFT-2262] - thrift server 'MutateRow' operation gives no indication of success / failure + * [THRIFT-2048] - Prefer boolean context to nullptr_t conversion + * [THRIFT-2528] - Thrift Erlang Library: Multiple thrift applications in one bundle + * [THRIFT-1999] - warning on gcc 4.7 while compiling BoostMutex.cpp + * [THRIFT-2104] - Structs lose binary data when transferred from server to client in Java + * [THRIFT-2184] - undefined method rspec_verify for Thrift::MemoryBufferTransport + * [THRIFT-2351] - PHP TCompactProtocol has fails to decode messages + * [THRIFT-2016] - Resource Leak in thrift struct under compiler/cpp/src/parse/t_function.h + * [THRIFT-2273] - Please delete old releases from mirroring system + * [THRIFT-2270] - Faulty library version numbering at build or documentation + * [THRIFT-2203] - Tests keeping failing on Jenkins and Travis CI + * [THRIFT-2399] - thrift.el: recognize "//"-style comments in emacs thrift-mode + * [THRIFT-2582] - "FileTransport error" exception is raised when trying to use Java's TFileTransport + * [THRIFT-1682] - Multiple thread calling a Service function unsafely causes message corruption and terminates with Broken Pipe + * [THRIFT-2357] - recurse option has no effect when generating php + * [THRIFT-2248] - Go generator doesn't deal well with map keys of type binary + * [THRIFT-2426] - clarify IP rights and contributions from fbthrift + * [THRIFT-2041] - TNonblocking server compilation on windows (ARITHMETIC_RIGHT_SHIFT) + * [THRIFT-2400] - thrift.el: recognize "//"-style comments in emacs thrift-mode + * [THRIFT-1717] - Fix deb build in jenkins + * [THRIFT-2266] - ThreadManager.h:24:10: fatal error: 'tr1/functional' file not found on Mac 10.9 (Mavericks) + * [THRIFT-1300] - Test failures with parallel builds (make -j) + * [THRIFT-2487] - Tutorial requires two IDL files but only one is linked from the Thrift web site + * [THRIFT-2329] - missing release tags within git + * [THRIFT-2306] - concurent client calls with nodejs + * [THRIFT-2222] - ruby gem cannot be compiled on OS X mavericks + * [THRIFT-2381] - code which generated by thrift2/hbase.thrift compile error + * [THRIFT-2390] - no close event when connection lost + * [THRIFT-2146] - Unable to pass multiple "--gen" options to the thrift compiler + * [THRIFT-2438] - Unexpected readFieldEnd call causes JSON Parsing errors + * [THRIFT-2498] - Error message "Invalid method name" while trying to call HBase Thrift API + * [THRIFT-841] - Build cruft + * [THRIFT-2570] - Wrong URL given in http://thrift.apache.org/developers + * [THRIFT-2604] - Fix debian packaging + * [THRIFT-2618] - Unignore /aclocal files required for build + * [THRIFT-2562] - ./configure create MakeFile in lib/d with errors + * [THRIFT-2593] - Unable to build thrift on ubuntu-12.04 (Precise) + * [THRIFT-2461] - Can't install thrift-0.8.0 on OS X 10.9.2 + * [THRIFT-2602] - Fix missing dist files + * [THRIFT-2620] - Fix python packaging + * [THRIFT-2545] - Test CPP fails to build (possibly typo) + +## Documentation + * [THRIFT-2155] - Adding one liner guide to rename the version.h.in and rename thrifty.cc.h + * [THRIFT-1991] - Add exceptions to examples + * [THRIFT-2334] - add a tutorial for node JS + * [THRIFT-2392] - Actionscript tutorial + * [THRIFT-2383] - contrib: sample for connecting Thrift with Rebus + * [THRIFT-2382] - contrib: sample for connecting Thrift with STOMP + +## Improvement + * [THRIFT-1457] - Capacity of TframedTransport write buffer is never reset + * [THRIFT-1135] - Node.js tutorial + * [THRIFT-1371] - Socket timeouts (SO_RCVTIMEO and SO_SNDTIMEO) not supported on Solaris + * [THRIFT-2142] - Minor tweaks to thrift.el for better emacs package compatibility + * [THRIFT-2268] - Modify TSaslTransport to ignore TCP health checks from loadbalancers + * [THRIFT-2264] - GitHub page incorrectly states that Thrift is still incubating + * [THRIFT-2263] - Always generate good hashCode for Java + * [THRIFT-2233] - Java compiler should defensively copy its binary inputs + * [THRIFT-2239] - Address FindBugs errors + * [THRIFT-2249] - Add SMP Build option to thrift.spec (and three config defines) + * [THRIFT-2254] - Exceptions generated by Go compiler should implement error interface + * [THRIFT-2260] - Thrift imposes unneeded dependency on commons-lang3 + * [THRIFT-2258] - Add TLS v1.1/1.2 support to TSSLSocket.cpp + * [THRIFT-2205] - Node.js Test Server to support test.js JavaScript Browser test and sundry fixes + * [THRIFT-2204] - SSL client for the cocoa client + * [THRIFT-2172] - Java compiler allocates optionals array for every struct with an optional field + * [THRIFT-2185] - use cabal instead of runhaskell in haskell library + * [THRIFT-1926] - PHP Constant Generation Refactoring + * [THRIFT-2029] - Port C++ tests to Windows + * [THRIFT-2054] - TSimpleFileTransport - Java Lib has no straight forward TTransport based file transport + * [THRIFT-2040] - "uninitialized variable" warnings on MSVC/windows + * [THRIFT-2034] - Give developers' C++ code direct access to socket FDs on server side + * [THRIFT-2095] - Use print function for Python 3 compatiblity + * [THRIFT-1868] - Make the TPC backlog configurable in the Java servers + * [THRIFT-1813] - Add @Generated annotation to generated classes + * [THRIFT-1815] - Code generators line buffer output + * [THRIFT-2305] - TFramedTransport empty constructor should probably be private + * [THRIFT-2304] - Move client assignments from construtor in method + * [THRIFT-2309] - Ruby (gem) & PHP RPM subpackages + * [THRIFT-2318] - perl: dependency Class::Accessor not checked + * [THRIFT-2317] - exclude tutorial from build + * [THRIFT-2320] - Program level doctext does not get attached by parser + * [THRIFT-2349] - Golang - improve tutorial + * [THRIFT-2348] - PHP Generator: add array typehint to functions + * [THRIFT-2344] - configure.ac: compiler-only option + * [THRIFT-2343] - Golang - Return a single error for all exceptions instead of multiple return values + * [THRIFT-2341] - Enable generation of Delphi XMLDoc comments (a.k.a. "Help Insight") + * [THRIFT-2355] - Add SSL and Web Socket Support to Node and JavaScript + * [THRIFT-2350] - Add async calls to normal JavaScript + * [THRIFT-2330] - Generate PHPDoc comments + * [THRIFT-2332] - RPMBUILD: run bootstrap (if needed) + * [THRIFT-2391] - simple socket transport for actionscript 3.0 + * [THRIFT-2376] - nodejs: allow Promise style calls for client and server + * [THRIFT-2369] - Add ssl support for nodejs implementation + * [THRIFT-2401] - Haskell tutorial compiles + * [THRIFT-2417] - C# Union classes are not partial + * [THRIFT-2415] - Named pipes server performance & message mode + * [THRIFT-2404] - emit warning on (typically inefficient) list + * [THRIFT-2398] - Improve Node Server Library + * [THRIFT-2397] - Add CORS and CSP support for JavaScript and Node.js libraries + * [THRIFT-2407] - use markdown (rename README => README.md) + * [THRIFT-2300] - D configure info output should follow same format as other languages + * [THRIFT-2579] - Windows CE support + * [THRIFT-2574] - Compiler option to generate namespace directories for Ruby + * [THRIFT-2571] - Simplify cross compilation using CMake + * [THRIFT-2569] - Introduce file to specify third party library locations on Windows + * [THRIFT-2568] - Implement own certificate handler + * [THRIFT-2552] - eliminate warning from configure.ac + * [THRIFT-2549] - Generate json tag for struct members. use go.tag annotation to override the default generated tag. + * [THRIFT-2544] - Add support for socket transport for c# library when using Windows Phone projects + * [THRIFT-2453] - haskell tutorial: fix up division by 0 example + * [THRIFT-2449] - Enhance typedef structure to distinguish between forwards and real typedefs + * [THRIFT-2446] - There is no way to handle server stream errors + * [THRIFT-2455] - Allow client certificates to be used with THttpClient + * [THRIFT-2511] - Node.js needs the compact protocol + * [THRIFT-2493] - Node.js lib needs HTTP client + * [THRIFT-2502] - Optimize go implementations of binary and compact protocols for speed + * [THRIFT-2494] - Add enum toString helper function in c_glib + * [THRIFT-2471] - Make cpp.ref annotation language agnostic + * [THRIFT-2497] - server and client for test/go, also several fixes and improvements + * [THRIFT-2535] - TJSONProtocol when serialized yields TField ids rather than names + * [THRIFT-2220] - Add a new struct structv? + * [THRIFT-1352] - Thrift server + * [THRIFT-989] - Push boost m4 macros upstream + * [THRIFT-1349] - Remove unnecessary print outs + * [THRIFT-2496] - server and client for test/go, also several fixes and improvements + * [THRIFT-1114] - Maven publish shouldn't require passwords hardcoded in settings.xml + * [THRIFT-2043] - visual 2010 warnings - unreachable code + * [THRIFT-1683] - Implement alternatives to Javascript Client side Transport protocol, just as NPAPI and WebSocket. + * [THRIFT-1746] - provide a SPDX file + * [THRIFT-1772] - Serialization does not check types of embedded structures. + * [THRIFT-2387] - nodejs: external imports should be centralized in index.js + * [THRIFT-2037] - More general macro THRIFT_UNUSED_VARIABLE + +## New Feature + * [THRIFT-1012] - Transport for DataInput DataOutput interface + * [THRIFT-2256] - Using c++11/c++0x std library replace boost library + * [THRIFT-2250] - JSON and MemoryBuffer for JavaME + * [THRIFT-2114] - Python Service Remote SSL Option + * [THRIFT-1719] - SASL client support for Python + * [THRIFT-1894] - Thrift multi-threaded async Java Server using Java 7 AsynchronousChannelGroup + * [THRIFT-1893] - HTTP/JSON server/client for node js + * [THRIFT-2347] - C# TLS Transport based on THRIFT-181 + * [THRIFT-2377] - Allow addition of custom HTTP Headers to an HTTP Transport + * [THRIFT-2408] - Named Pipe Transport Option for C# + * [THRIFT-2572] - Add string/collection length limit checks (from C++) to java protocol readers + * [THRIFT-2469] - "java:fullcamel" option to automatically camel-case underscored attribute names + * [THRIFT-795] - Importing service functions (simulation multiple inheritance) + * [THRIFT-2164] - Add a Get/Post Http Server to Node along with examples + * [THRIFT-2255] - add Parent Class for generated Struct class + +## Question + * [THRIFT-2539] - Tsocket.cpp addrinfo ai_flags = AI_ADDRCONFIG + * [THRIFT-2440] - how to connect as3 to java by thrift , + * [THRIFT-2379] - Memmory leaking while using multithreading in C++ server. + * [THRIFT-2277] - Thrift: installing fb303 error + * [THRIFT-2567] - Csharp slow ? + * [THRIFT-2573] - thrift 0.9.2 release + +## Sub-task + * [THRIFT-981] - cocoa: add version Info to the library + * [THRIFT-2132] - Go: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-2299] - TJsonProtocol implementation for Ruby does not allow for both possible slash (solidus) encodings + * [THRIFT-2298] - TJsonProtocol implementation for C# does not allow for both possible slash (solidus) encodings + * [THRIFT-2297] - TJsonProtocol implementation for Delphi does not allow for both possible slash (solidus) encodings + * [THRIFT-2271] - JavaScript: Support for Multiplexing Services + * [THRIFT-2251] - go test for compact protocol is not running + * [THRIFT-2195] - Delphi: Add event handlers for server and processing events + * [THRIFT-2176] - TSimpleJSONProtocol.ReadFieldBegin() does not return field type and ID + * [THRIFT-2175] - Wrong field type set for binary + * [THRIFT-2174] - Deserializing JSON fails in specific cases + * [THRIFT-2053] - NodeJS: Support for Multiplexing Services + * [THRIFT-1914] - Python: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-1810] - add ruby to test/test.sh + * [THRIFT-2310] - PHP: Client-side support for Multiplexing Services + * [THRIFT-2346] - C#: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2345] - Delphi: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol + * [THRIFT-2338] - First doctext wrongly interpreted as program doctext in some cases + * [THRIFT-2325] - SSL test certificates + * [THRIFT-2358] - C++: add compact protocol to cross language test suite + * [THRIFT-2425] - PHP: Server-side support for Multiplexing Services + * [THRIFT-2421] - Tree/Recursive struct support in thrift + * [THRIFT-2290] - Update Go tutorial to align with THRIFT-2232 + * [THRIFT-2558] - CSharp compiler generator tries to concat ints with strings using + + * [THRIFT-2507] - Additional LUA TProtocolException error code needed? + * [THRIFT-2499] - Compiler: allow annotations without "= value" + * [THRIFT-2534] - Cross language test results should recorded to a status.md or status.html file automatically + * [THRIFT-66] - Java: Allow multiplexing multiple services over a single TCP connection + * [THRIFT-1681] - Add Lua Support + * [THRIFT-1727] - Ruby-1.9: data loss: "binary" fields are re-encoded + * [THRIFT-1726] - Ruby-1.9: "binary" fields are represented by string whose encoding is "UTF-8" + * [THRIFT-988] - perl: add version Info to the library via configure + * [THRIFT-334] - Compact Protocol for PHP + * [THRIFT-2444] - pull request 88: thrift: clean up enum value assignment + +## Task + * [THRIFT-2223] - Spam links on wiki + * [THRIFT-2566] - Please create a DOAP file for your TLP + * [THRIFT-2237] - Update archive to contain all versions + * [THRIFT-962] - Tutorial page on our website is really unhelpful + +## Test + * [THRIFT-2327] - nodejs: nodejs test suite should be bundled with the library + * [THRIFT-2445] - THRIFT-2384 (code generation for go maps with binary keys) should be tested + * [THRIFT-2501] - C# The test parameters from the TestServer and TestClient are different from the http://thrift.apache.org/test/ + +## Wish + * [THRIFT-2190] - Add the JavaScript thrift.js lib to the Bower registry + * [THRIFT-2076] - boost::optional instead of __isset + + + +Thrift 0.9.1 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-1440] - debian packaging: minor-ish policy problems + * [THRIFT-1402] - Generated Y_types.js does not require() X_types.js when an include in the IDL file was used + * [THRIFT-1551] - 2 thrift file define only struct (no service), one include another, the gen nodejs file didn't have "requires" at the top + * [THRIFT-1264] - TSocketClient is queried by run loop after deallocation in Cocoa + * [THRIFT-1600] - Thrift Go Compiler and Library out of date with Go 1 Release. + * [THRIFT-1603] - Thrift IDL allows for multiple exceptions, args or struct member names to be the same + * [THRIFT-1062] - Problems with python tutorials + * [THRIFT-864] - default value fails if identifier is a struct + * [THRIFT-930] - Ruby and Haskell bindings don't properly support DESTDIR (makes packaging painful) + * [THRIFT-820] - The readLength attribute of TBinaryProtocol is used as an instance variable and is decremented on each call of checkReadLength + * [THRIFT-1640] - None of the tutorials linked on the website contain content + * [THRIFT-1637] - NPM registry does not include version 0.8 + * [THRIFT-1648] - NodeJS clients always receive 0 for 'double' values. + * [THRIFT-1660] - Python Thrift library can be installed with pip but not easy_install + * [THRIFT-1657] - Chrome browser sending OPTIONS method before POST in xmlHttpRequest + * [THRIFT-2118] - Certificate error handling still incorrect + * [THRIFT-2137] - Ruby test lib fails jenkins build #864 + * [THRIFT-2136] - Vagrant build not compiling java, ruby, php, go libs due to missing dependencies + * [THRIFT-2135] - GO lib leaves behind test files that are auto generated + * [THRIFT-2134] - mingw-cross-compile script failing with strip errors + * [THRIFT-2133] - java TestTBinaryProtocol.java test failing + * [THRIFT-2126] - lib/cpp/src/thrift/concurrency/STD* files missing from DIST + * [THRIFT-2125] - debian missing from DIST + * [THRIFT-2124] - .o, .so, .la, .deps, .libs, gen-* files left tutorials, test and lib/cpp when making DIST + * [THRIFT-2123] - GO lib missing files in DIST build + * [THRIFT-2121] - Compilation bug for Node.js + * [THRIFT-2129] - php ext missing from dist + * [THRIFT-2128] - lib GO tests fail with funct ends without a return statement + * [THRIFT-2286] - Failed to compile Thrift0.9.1 with boost1.55 by VS2010 if select Debug-mt&x64 mode. + * [THRIFT-1973] - TCompactProtocol in C# lib does not serialize and deserialize negative int32 and int64 number correctly + * [THRIFT-1992] - casts in TCompactProtocol.tcc causing "dereferencing type-punned pointer will break strict-aliasing rules" warnings from gcc + * [THRIFT-1930] - C# generates unsigned byte for Thrift "byte" type + * [THRIFT-1929] - Update website to use Mirrors for downloads + * [THRIFT-1928] - Race may still exist in TFileTransport::flush() + * [THRIFT-1934] - Tabs in Example section on main page are not working + * [THRIFT-1933] - Delphi generator crashes when a typedef references another typedef from an included file + * [THRIFT-1942] - Binary accelerated cpp extension does not use Thrift namespaces for Exceptions + * [THRIFT-1959] - C#: Add Union TMemoryBuffer support + * [THRIFT-1958] - C#: Use static Object.Equals instead of .Equals() calls in equals + * [THRIFT-1957] - NodeJS TFramedTransport and TBufferedTransport read bytes as unsigned + * [THRIFT-1955] - Union Type writer generated in C# does not WriteStructBegin + * [THRIFT-1952] - Travis CI + * [THRIFT-1949] - WP7 build broken + * [THRIFT-1943] - docstrings for enum values are ignored + * [THRIFT-2070] - Improper `HexChar' and 'HexVal' implementation in TJSONProtocol.cs + * [THRIFT-2017] - Resource Leak in thrift struct under compiler/cpp/src/parse/t_program.h + * [THRIFT-2032] - C# client leaks sockets/handles + * [THRIFT-1996] - JavaME Constants generation is broken / inconsistent with regular Java generation + * [THRIFT-2002] - Haskell: Test use Data.Maybe instead of Maybe + * [THRIFT-2051] - Vagrant fails to build erlang + * [THRIFT-2050] - Vagrant C# lib compile fails with TException missing + * [THRIFT-1978] - Ruby: Thrift should allow for the SSL verify mode to be set + * [THRIFT-1984] - namespace collision in python bindings + * [THRIFT-1988] - When trying to build a debian package it fails as the file NEWS doesn't exist + * [THRIFT-1975] - TBinaryProtocol CheckLength can't be used for a client + * [THRIFT-1995] - '.' allowed at end of identifier generates non-compilable code + * [THRIFT-2112] - Error in Go generator when using typedefs in map keys + * [THRIFT-2088] - Typos in Thrift compiler help text + * [THRIFT-2080] - C# multiplex processor does not catch IOException + * [THRIFT-2082] - Executing "gmake clean" is broken + * [THRIFT-2102] - constants are not referencing to correct type when included from another thrift file + * [THRIFT-2100] - typedefs are not correctly referenced when including from other thrift files + * [THRIFT-2066] - 'make install' does not install two headers required for C++ bindings + * [THRIFT-2065] - Not valid constants filename in Java + * [THRIFT-2047] - Thrift.Protocol.TCompactProtocol, intToZigZag data lost (TCompactProtocol.cs) + * [THRIFT-2036] - Thrift gem warns about class variable access from top level + * [THRIFT-2057] - Vagrant fails on php tests + * [THRIFT-2105] - Generated code for default values of collections ignores t_field::T_REQUIRED + * [THRIFT-2091] - Unnecessary 'friend' declaration causes warning in TWinsockSingleton + * [THRIFT-2090] - Go generator, fix including of other thrift files + * [THRIFT-2106] - Fix support for namespaces in GO generator + * [THRIFT-1783] - C# doesn't handle required fields correctly + * [THRIFT-1782] - async only defined in silverlight + * [THRIFT-1779] - Missing process_XXXX method in generated TProcessor implementation for all 'oneway' service functions + * [THRIFT-1692] - SO_REUSEADDR allows for socket hijacking on Windows + * [THRIFT-1720] - JRuby times out on successful connection + * [THRIFT-1713] - Named and Anonymous Pipe transport (Delphi) + * [THRIFT-1699] - Native Union#read has extra read_field_end call + * [THRIFT-1749] - Python TSSLSocket error handling obscures actual error + * [THRIFT-1748] - Guard and RWGuard macros defined in global namespace + * [THRIFT-1734] - Front webpage is still advertising v0.8 as current release + * [THRIFT-1729] - C glib refactor left empty folders in svn + * [THRIFT-1767] - unions can't have required fields (Delphi) + * [THRIFT-1765] - Incorrect error message printed for null or negative keys + * [THRIFT-1778] - Configure requires manual intervention due to tar failure + * [THRIFT-1777] - TPipeServer is UNSTOPPABLE + * [THRIFT-1753] - Multiple C++ Windows, OSX, and iOS portability issues + * [THRIFT-1756] - 'make -j 8' fails with "unterminated #ifdef" error + * [THRIFT-1773] - Python library should run on python 2.4 + * [THRIFT-1769] - unions can't have required fields (C++) + * [THRIFT-1768] - unions can't have required fields (Compiler) + * [THRIFT-1666] - htonll usage in TBinaryProtocol.tcc generates warning with MSVC2010 + * [THRIFT-1919] - libthrift depends on httpcore-4.1.3 (directly) and httpcore-4.1.4 (transitively) + * [THRIFT-1864] - implement event handler for non-blocking server + * [THRIFT-1859] - Generated error c++ code with -out and include_prefix param + * [THRIFT-1869] - TThreadPoolServer (java) dies when threadpool is consumed + * [THRIFT-1842] - Memory leak with Pipes + * [THRIFT-1838] - Can't build compiler on OS X because of missing thrifty.h + * [THRIFT-1846] - Restore socket.h header to support builds with Android NDK + * [THRIFT-1850] - make check hangs on TSocket tests in TransportTest.cpp + * [THRIFT-1873] - Binary protocol factory ignores struct read/write flags + * [THRIFT-1872] - issues with TBufferedTransport buffer + * [THRIFT-1904] - Incorrect code is generated for typedefs which use included types + * [THRIFT-1903] - PHP namespaces cause binary protocols to not be used + * [THRIFT-1895] - Delphi: reserved variable name "result" not detected properly + * [THRIFT-1881] - TNonblockingServer does not release open connections or threads on shutdown + * [THRIFT-1888] - Java Thrift client can't connect to Python Thrift server on same host + * [THRIFT-1831] - Bug in list deserializer + * [THRIFT-1824] - many compile warning, becase Thread.h includes config.h + * [THRIFT-1823] - Missing parenthesis breaks "IS_..." macro in generated code + * [THRIFT-1806] - Python generation always truncates __init__.py files + * [THRIFT-1795] - Race condition in TThreadedServerPool java implementation + * [THRIFT-1794] - C# asyncctp broken + * [THRIFT-1804] - Binary+compact protocol single byte error in Ruby library (ARM architecture): caused by different char signedness + * [THRIFT-1800] - Documentation text not always escaped correctly when rendered to HTML + * [THRIFT-1788] - C#: Constants static constructor does not compile + * [THRIFT-1816] - Need "require" included thrift files in "xxx_types.js" + * [THRIFT-1907] - Compiling namespace and sub-namespace directives for unrecognized generators should only be a warning + * [THRIFT-1913] - skipping unknown fields in java unions + * [THRIFT-2553] - C++ linker error - transport/TSocket + * [THRIFT-274] - Towards a working release/versioning process + +## Documentation + * [THRIFT-1971] - [Graphviz] Adds tutorial/general description documentation + * [THRIFT-2001] - http://thrift.apache.org/ Example "C++ Server" tab is broken + +## Improvement + * [THRIFT-1574] - Apache project branding requirements: DOAP file [PATCH] + * [THRIFT-1347] - Unify the exceptions returned in generated Go code + * [THRIFT-1353] - Switch to performance branch, get rid of BinaryParser + * [THRIFT-1629] - Ruby 1.9 Compatibility during Thrift configure, make, install + * [THRIFT-991] - Refactor Haskell code and generator + * [THRIFT-990] - Sanify gettimeofday usage codebase-wide + * [THRIFT-791] - Let C++ TSimpleServer be driven by an external main loop + * [THRIFT-2117] - Cocoa TBinaryProtocol strictWrite should be set to true by default + * [THRIFT-2014] - Change C++ lib includes to use style throughout + * [THRIFT-1972] - Add support for async processors + * [THRIFT-1970] - [Graphviz] Adds option to render exceptions relationships + * [THRIFT-1966] - Support different files for SSL certificates and keys + * [THRIFT-1965] - Adds Graphviz (graph description language) generator + * [THRIFT-1956] - Switch to Apache Commons Lang 3 + * [THRIFT-1962] - Multiplex processor should send any TApplicationException back to client + * [THRIFT-1960] - main() declares 22 unused gen bools + * [THRIFT-1951] - libthrift.jar has source files in it + * [THRIFT-1997] - Add accept backlog configuration method to TServerSocket + * [THRIFT-2003] - Deprecate senum + * [THRIFT-2052] - Vagrant machine image defaults to only 384MB of RAM + * [THRIFT-1980] - Modernize Go tooling, fix go client libary. + * [THRIFT-1977] - C# compiler should generate constant files prefixed with thrift file name + * [THRIFT-1985] - add a Vagrantfile to build and test Apache Thrift fully reproducable + * [THRIFT-1994] - Deprecate slist + * [THRIFT-1993] - Factory to create instances from known (generated) interface types with Delphi + * [THRIFT-2081] - Specified timeout should be used in TSocket.Open() + * [THRIFT-2084] - Delphi: Ability to create entity Thrift-generated instances based on TypeInfo + * [THRIFT-2083] - Improve the go lib: buffered Transport, save memory allocation, handle concurrent request + * [THRIFT-2109] - Secure connections should be supported in Go + * [THRIFT-2107] - minor Go generator fixes + * [THRIFT-1695] - allow warning-free compilation in VS 2012 and GNU 4.6 + * [THRIFT-1735] - integrate tutorial into regular build + * [THRIFT-1716] - max allowed connections should be PIPE_UNLIMITED_INSTANCES + * [THRIFT-1715] - Allow excluding python parts when building contrib/fb303 + * [THRIFT-1733] - Fix RPM build issues on RHEL6/OL6 systems + * [THRIFT-1728] - Upgradation of httpcomponents + * [THRIFT-1876] - Use enum names instead of casted integers in assignments + * [THRIFT-1874] - timeout for the server-side end of a named pipe + * [THRIFT-1897] - Support validation of required fields + * [THRIFT-1896] - Add TBase protocol for Cocoa + * [THRIFT-1880] - Make named pipes server work asynchronously (overlapped) to allow for clean server stops + * [THRIFT-1878] - Add the possibility to send custom headers + * [THRIFT-1882] - Use single include + * [THRIFT-1793] - C#: Use static read instead of instance read + * [THRIFT-1799] - Option to generate HTML in "standalone mode" + * [THRIFT-1815] - Code generators line buffer output + * [THRIFT-1890] - C++: Make named pipes server work asynchronously + * [THRIFT-474] - Generating Ruby on Rails friendly code + +## New Feature + * [THRIFT-801] - Provide an interactive shell (irb) when generating ruby bindings + * [THRIFT-2292] - Android Library Project + * [THRIFT-2012] - Modernizing Go + * [THRIFT-1969] - C#: Tests not properly linked from the solution + * [THRIFT-1785] - C#: Add TMemoryBuffer serializer/deserializer + * [THRIFT-1780] - Add option to generate nullable values + * [THRIFT-1786] - C# Union Typing + * [THRIFT-591] - Make the C++ runtime library be compatible with Windows and Visual Studio + * [THRIFT-514] - Add option to configure compiler output directory + +## Question + * [THRIFT-1764] - how to get the context of client when on a rpc call in server side? + * [THRIFT-1791] - thrift's namespace directive when generating haskell code + +## Sub-task + * [THRIFT-1594] - Java test clients should have a return codes that reflect whether it succeeds or not. + * [THRIFT-1595] - Java test server should follow the documented behavior as of THRIFT-1590 + * [THRIFT-986] - st: add version Info to the library + * [THRIFT-985] - php: add version Info to the library + * [THRIFT-984] - ocaml: add version Info to the library + * [THRIFT-1924] - Delphi: Inconsistency in serialization of optional fields + * [THRIFT-1922] - C#: Inconsistency in serialization of optional fields + * [THRIFT-1961] - C# tests should be in lib/csharp/test/... + * [THRIFT-1822] - PHP unit test does not work + * [THRIFT-1902] - C++: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-1901] - C#: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-1899] - Delphi: Support for Multiplexing Services on any Transport, Protocol and Server + * [THRIFT-563] - Support for Multiplexing Services on any Transport, Protocol and Server + + + +Thrift 0.9 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-1438] - lib/cpp/src/windows/config.h should read version from configure.ac rather than a #define + * [THRIFT-1446] - Compile error with Delphi 2009 in constant initializer + * [THRIFT-1450] - Problems building thrift 0.8.0 for Python and Ruby + * [THRIFT-1449] - Ruby client does not work on solaris (?) + * [THRIFT-1447] - NullpointerException in ProcessFunction.class :in "oneway" method + * [THRIFT-1433] - TServerSocket fix for MSVC + * [THRIFT-1429] - The nonblocking servers is supposed to use TransportFactory to read the data + * [THRIFT-1427] - PHP library uses non-multibyte safe functions with mbstring function overloading + * [THRIFT-1421] - Debian Packages can not be built + * [THRIFT-1394] - Treatment of optional fields is not consistent between C++ and Java + * [THRIFT-1511] - Server with oneway support ( JAVA ) + * [THRIFT-1496] - PHP compiler not namespacing enums + * [THRIFT-1495] - PHP TestClient fatals on missing class + * [THRIFT-1508] - TServerSocket does not allow for the user to specify the IP address to bind to + * [THRIFT-1504] - Cocoa Generator should use local file imports for base Thrift headers + * [THRIFT-1512] - Thrift socket support for Windows XP + * [THRIFT-1502] - TSimpleServer::serve(): Do not print out error message if server was stopped. + * [THRIFT-1501] - PHP old namespaces not generated for enums + * [THRIFT-1483] - java compiler does not generate type parameters for services in extended clauses + * [THRIFT-1479] - Compiled PHP process functions missing writeMessageEnd() + * [THRIFT-1492] - enabling c_glib render thrift unusable (even for C++ code) + * [THRIFT-1491] - Uninitialize processorFactory_ member in TServer.h + * [THRIFT-1475] - Incomplete records generation for Erlang + * [THRIFT-1486] - Javascript manual testserver not returning content types + * [THRIFT-1488] - src/concurrency/Thread.h:91:58: error: invalid conversion from 'pthread_t {aka _opaque_pthread_t*}' to 'apache::thrift::concurrency::Thread::id_t {aka long long unsigned int}' [-fpermissive] + * [THRIFT-1490] - Windows-specific header files - fixes & tweaks + * [THRIFT-1526] - Union TupleSchemeFactory returns StandardSchemes + * [THRIFT-1527] - Generated implementation of tupleReadStruct in unions return null when the setfield is unrecognized + * [THRIFT-1524] - TNonBlockingServer does not compile in Visual Studio 2010 + * [THRIFT-1529] - TupleProtocol can unintentionally include an extra byte in bit vectors when number of optional fields is an integral of 8 + * [THRIFT-1473] - JSON context stack may be left in an incorrect state when an exception is thrown during read or write operations + * [THRIFT-1456] - System.Net.HttpWebRequest' does not contain a definition for 'Proxy' + * [THRIFT-1468] - Memory leak in TSaslServerTransport + * [THRIFT-1461] - Recent TNonblockingServer changes broke --enable-boostthreads=yes, Windows + * [THRIFT-1460] - why not add unicode strings support to python directly? + * [THRIFT-1464] - AbstractNonblockingServer.FrameBuffer TNonblockingTransport accessor changed from public to private + * [THRIFT-1467] - Possible AV with empty strings when using JSON protocol + * [THRIFT-1523] - clientTimeout not worked as expected in TServerSocket created by TSSLTransportFactory + * [THRIFT-1537] - TFramedTransport issues + * [THRIFT-1519] - Thirft Build Failure referencing rb_intern2 symbol + * [THRIFT-1518] - Generated C++ code only sends the first optional field in the write() function for a struct. + * [THRIFT-1515] - NameError: global name 'TApplicationException' is not defined + * [THRIFT-1554] - Inherited service methods are not resolved in derived service implementations + * [THRIFT-1553] - thrift nodejs service side can't read map structure, key as enum, value as Object + * [THRIFT-1575] - Typo in server/TThreadPoolServer.h + * [THRIFT-1327] - Fix Spec Suite under Ruby-1.8.7 (works for MRI Ruby-1.9.2) + * [THRIFT-1326] - on some platforms, #include is necessary to be included in Thrift.h + * [THRIFT-1159] - THttpClient->Flush() issue (connection thru proxy) + * [THRIFT-1277] - Node.js serializes false booleans as null + * [THRIFT-1224] - Cannot insert UTF-8 text + * [THRIFT-1267] - Node.js can't throw exceptions. + * [THRIFT-1338] - Do not use an unpatched autoconf 2.65 to generate release tarball + * [THRIFT-1128] - MAC OS X: thrift.h incompatibility with Thrift.h + * [THRIFT-1631] - Fix C++ server constructor typos + * [THRIFT-1602] - PHP C Extension is not Compatible with PHP 5.4 + * [THRIFT-1610] - IWebProxy not available on WP7 platform + * [THRIFT-1606] - Race condition in BoostThreadFactory.cpp + * [THRIFT-1604] - Python exception handeling for changes from PEP 3110 + * [THRIFT-1607] - Incorrect file modes for several source files + * [THRIFT-1583] - c_glib leaks memory + * [THRIFT-1582] - Bad includes of nested thrift files in c_glib + * [THRIFT-1578] - C_GLib generated code does not compile + * [THRIFT-1597] - TJSONProtocol.php is missing from Makefile.am + * [THRIFT-1591] - Enable TCP_NODELAY for ruby gem + * [THRIFT-1624] - Isset Generated differently on different platforms + * [THRIFT-1622] - Incorrect size returned on read + * [THRIFT-1621] - Memory leaks + * [THRIFT-1612] - Base64 encoding is broken + * [THRIFT-1627] - compiler built using compilers.vcxproj cannot be used to build some test .thrift files + * [THRIFT-1571] - Update Ruby HTTP transport for recent Ruby versions + * [THRIFT-1023] - Thrift encoding (UTF-8) issue with Ruby 1.9.2 + * [THRIFT-1090] - Document the generation of a file called "Constants.java" + * [THRIFT-1082] - Thrift::FramedTransport sometimes calls close() on an undefined value + * [THRIFT-956] - Python module's version meta-data should be updated + * [THRIFT-973] - Cocoa library won't compile using clang + * [THRIFT-1632] - ruby: data corruption in thrift_native implementation of MemoryBufferTransport + * [THRIFT-1665] - TBinaryProtocol: exceeded message length raises generic TException + * [THRIFT-1664] - Reference to non-existing variable in build script + * [THRIFT-1663] - Java Thrift server is not throwing exceptions + * [THRIFT-1662] - "removeObject:" should be "removeObserver:" in [-TSocketServer dealloc]? + * [THRIFT-1643] - Denial of Service attack in TBinaryProtocol.readString + * [THRIFT-1674] - Update Thrift D library to be compatible with 2.060 + * [THRIFT-1673] - Ruby compile flags for extension for multi arch builds (os x) + * [THRIFT-1655] - Configure still trying to use thrift_generators in output + * [THRIFT-1654] - c_glib thrift_socket_read() returns corrupted data + * [THRIFT-1653] - TThreadedSelectorServer leaks CLOSE_WAIT sockets + * [THRIFT-1658] - Java thrift server is not throwing TApplicationException + * [THRIFT-1656] - Setting proper headers in THttpServer.cpp so that "Cross-Origin Resource Sharing" on js client can work. + * [THRIFT-1652] - TSaslTransport does not log the error when kerberos auth fails + * [THRIFT-2272] - CLONE - Denial of Service attack in TBinaryProtocol.readString + * [THRIFT-2086] - Invalid generated code for Node.JS when using namespaces + * [THRIFT-1686] - t_php_generator.cc uses "and" instead of "&&", and causes compiler errors with Visual Studio + * [THRIFT-1693] - libthrift has dependency on two different versions of httpcore + * [THRIFT-1689] - don't exit(-1) in TNonblockingServer + * [THRIFT-1679] - NodeJS: protocol readString() should treat string as utf8, not binary + * [THRIFT-1721] - Dist broken due to 0.8.0 to 0.9.0 changes + * [THRIFT-1710] - Minor issues in test case code + * [THRIFT-1709] - Warning "Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first" in TBinaryProtocol.cs at ReadInt64() + * [THRIFT-1707] - [ruby] Adjust server_spec.rb for RSpec 2.11.x and Ruby 1.9.3 + * [THRIFT-1671] - Cocoa code generator does not put keywords into generated method calls + * [THRIFT-1670] - Incompatibilities between different versions of a Thrift interface + * [THRIFT-1669] - NameError: global name 'TApplicationException' is not defined + * [THRIFT-1668] - Compile error in contrib/fb303, thrift/TDispatchProcessor.h: No such file or directory + * [THRIFT-1845] - Fix compiler warning caused by implicit string conversion with Xcode 4.6 + * [THRIFT-304] - Building the Python library requires development headers + * [THRIFT-369] - sets and maps break equality + * [THRIFT-556] - Ruby compiler does not correctly referred to top-level modules when a submodule masks the top-level name + * [THRIFT-481] - indentation of ruby classes is off by a few + +## Improvement + * [THRIFT-1498] - Allow TThreadedPoolServer.Args to pass a ExecutorService + * [THRIFT-1444] - FunctionRunner - add syntactic sugar to create shared_ptrs + * [THRIFT-1443] - define a TProcessor helper class to implement process() + * [THRIFT-1441] - Generate constructor with parameters for exception class to let it update message property automatically. + * [THRIFT-1520] - Embed version number in erlang .app file + * [THRIFT-1480] - python: remove tabs, adjust whitespace and address PEP8 warnings + * [THRIFT-1485] - Performance: pass large and/or refcounted arguments as "const" + * [THRIFT-1484] - Introduce phpunit test suite + * [THRIFT-1532] - The type specifications in the generated Erlang code should include "undefined" where it's used as a default value + * [THRIFT-1534] - Required fields in the Delphi code generator. + * [THRIFT-1469] - Java isset space optimization + * [THRIFT-1465] - Visibility of methods in generated java code + * [THRIFT-1453] - Don't change types of arguments when serializing with thrift php extension + * [THRIFT-1452] - generate a swap() method for all generated structs + * [THRIFT-1451] - FramedTransport: Prevent infinite loop when writing + * [THRIFT-1521] - Two patches for more Performance + * [THRIFT-1555] - Delphi version of the tutorial code + * [THRIFT-1535] - Why thrift don't use wrapped class for optional fields ? + * [THRIFT-1204] - Ruby autogenerated files should require 'thrift' gem + * [THRIFT-1344] - Using the httpc module directly rather than the deprecated http layer + * [THRIFT-1343] - no_auto_import min/2 to avoid compile warning + * [THRIFT-1340] - Add support of ARC to Objective-C + * [THRIFT-1611] - Improved code generation for typedefs + * [THRIFT-1593] - Pass on errors like "connection closed" to the handler module + * [THRIFT-1615] - PHP Namespace + * [THRIFT-1567] - Thrift/cpp: Allow alternate classes to be used for + * [THRIFT-1072] - Missing - (id) initWithSharedProcessor in TSharedProcessorFactory.h + * [THRIFT-1650] - [ruby] Update clean items and svn:ignore entries for OS X artifacts + * [THRIFT-1661] - [PATCH] Add --with-qt4 configure option + * [THRIFT-1675] - Do we have any plan to support scala? + * [THRIFT-1645] - Replace Object#tee with more conventional Object#tap in specs + * [THRIFT-1644] - Upgrade RSpec to 2.10.x and refactor specs as needed + * [THRIFT-1672] - MonoTouch (and Mono for Android) compatibility + * [THRIFT-1702] - a thrift manual + * [THRIFT-1694] - Re-Enable serialization for WP7 Silverlight + * [THRIFT-1691] - Serializer/deserializer support for Delphi + * [THRIFT-1688] - Update IDL page markup + * [THRIFT-1725] - Tutorial web pages for Delphi and C# + * [THRIFT-1714] - [ruby] Explicitly add CWD to Ruby test_suites.rb + * [THRIFT-317] - Issues with Java struct validation + * [THRIFT-164] - Build web tutorial on Incubator web site + * [THRIFT-541] - Cocoa code generator doesn't put keywords before all arguments. + * [THRIFT-681] - The HTML generator does not handle JavaDoc style comments very well + +## New Feature + * [THRIFT-1500] - D programming language support + * [THRIFT-1510] - There should be an implementation of the JsonProtocol for ruby + * [THRIFT-1115] - python TBase class for dynamic (de)serialization, and __slots__ option for memory savings + * [THRIFT-1953] - support for asp.net mvc 3 + +## Question + * [THRIFT-1235] - How could I use THttpServerTransportFactory withTNonBlockingServer + * [THRIFT-1368] - TNonblockingServer usage + * [THRIFT-1061] - Read an invalid frame size of 0. Are you using TFramedTransport on the client side? + * [THRIFT-491] - Ripping raw pthreads out of TFileTransport and associated test issues + +## Sub-task + * [THRIFT-1596] - Delphi: Test clients should have a return codes that reflect whether they succeeded or not + * [THRIFT-982] - javame: add version Info to the library + * [THRIFT-1722] - C# WP7 Assembly addition beaks mono build + * [THRIFT-336] - Compact Protocol in C# + +## Test + * [THRIFT-1613] - Add code back into empty source file ToStringTest.java + * [THRIFT-1718] - Incorrect check in TFileTransportTest + +## Wish + * [THRIFT-1463] - Decouple Thrift IDL from generators + * [THRIFT-1466] - Proper Documentation for Thrift C Glib + * [THRIFT-1539] - Build and distribute the fb303 python libraries along with thrift + * [THRIFT-1685] - Please add "aereo.com" to "Powered by Apache Thrift" list in about page + * [THRIFT-330] - TProcessor - additional method to called when connection is broken + + + +Thrift 0.8 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-1436] - pip install thrift fails on Windows with "Unable to find vcvarsall.bat" + * [THRIFT-1432] - Javascript struct constants declared in the same file as their struct definition will cause an error + * [THRIFT-1428] - shared.thrft does not include namespace for php, so thrift compiler generate incorrect name + * [THRIFT-1426] - Dist package missing files for release 0.8 + * [THRIFT-1425] - The Node package is incompatible with latest node (0.6) & npm (1.0.27) + * [THRIFT-1416] - Python Unit test is broken on ci + * [THRIFT-1419] - AbstractNonBlockingServer does not catch errors when invoking the processor + * [THRIFT-1424] - Ruby specs fail when run with rake + * [THRIFT-1420] - Nonblocking and HsHa server should make sure to close all their socket connections when the selector exits + * [THRIFT-1413] - Generated code does not read MapEnd / ListEnd / SetEnd + * [THRIFT-1409] - Name conflict check does not work properly for exception object(Delphi). + * [THRIFT-1408] - Delphi Test Server: Exception test case fails due to naming conflict with e.message + * [THRIFT-1407] - Typo in Python socket server causes Thrift to fail when we enable a global socket timout + * [THRIFT-1397] - CI server fails during build due to unused parameters in delphi generator + * [THRIFT-1404] - Delphi compiler generates struct reader code with problem. + * [THRIFT-1400] - Ruby native extension aborts with __stack_chk_fail in OSX + * [THRIFT-1399] - One of the TServerImpl.Create CTORs lacks implementation + * [THRIFT-1390] - Debian packages build fix for Squeeze (build from the official 0.7.0 tarball) + * [THRIFT-1393] - TTransportException's thrown from THttpClient contain superfluous slashes in the Exception message + * [THRIFT-1392] - Enabling both namespaces and autoloading in generated PHP code won't work. + * [THRIFT-1406] - Build error after applying THRIFT-1395 + * [THRIFT-1405] - Delphi compiler does not generates container serializer properly. + * [THRIFT-1411] - java generator does not provide type parameter for TBaseProcessor + * [THRIFT-1473] - JSON context stack may be left in an incorrect state when an exception is thrown during read or write operations + * [THRIFT-1331] - Ruby library deserializes an empty map to nil + * [THRIFT-1330] - PHP Namespaces no longer generated + * [THRIFT-1328] - TBaseHelper.toString(...) appends ByteBuffer data outside of valid buffer range + * [THRIFT-1322] - OCaml lib fail to compile: Thrift.ml line 305, int vs int32 mismatch + * [THRIFT-1143] - Build doesn't detect correct architecture type on 64bit osx + * [THRIFT-1205] - port server unduly fragile with arbitrary input + * [THRIFT-1279] - type set is handled incorrectly when writing object + * [THRIFT-1298] - Standard scheme doesn't read or write metadata along with field values + * [THRIFT-1265] - C++ container deserialize + * [THRIFT-1263] - publish ruby client to rubygems + * [THRIFT-1384] - Java help menu missing newline near javame flag + * [THRIFT-1382] - Bundle install doesnot work because thrift crashes + * [THRIFT-1381] - Thrift C++ libs have incorrectly versioned names + * [THRIFT-1350] - Go library code does not build as of r60 (most recent release) + * [THRIFT-1365] - TupleProtocol#writeBitSet unintentionally writes a variable length byte array + * [THRIFT-1359] - --gen-cob cpp:cob_style does not compile anymore + * [THRIFT-1319] - Mismatch between how a union reads and writes a container + * [THRIFT-1309] - libfb303-0.7.0.jar missing in maven repository + * [THRIFT-1238] - Thrift JS client cannot read map of structures + * [THRIFT-1254] - Code can't be compiled against a regular JRE: Object.clone() override has a different return type + * [THRIFT-1367] - Mac OSX build fails with "no such file to load -- spec/rake/spectask" + * [THRIFT-1355] - Running make in lib/rb doesn't build the native extensions + * [THRIFT-1370] - Debian packaging should Build-Depend on libglib2.0-dev + * [THRIFT-1342] - Compilation problem on Windows of fastbinary.c + * [THRIFT-1341] - TProtocol.h endian detection wrong with boost + * [THRIFT-1583] - c_glib leaks memory + * [THRIFT-1582] - Bad includes of nested thrift files in c_glib + * [THRIFT-1578] - C_GLib generated code does not compile + * [THRIFT-1027] - 'make -j 16' fails with "unterminated #ifdef" error + * [THRIFT-1121] - Java server performance regression in 0.6 + * [THRIFT-857] - tests run by "make install" fail if generators are disabled + * [THRIFT-380] - Use setuptools for python build + +## Dependency upgrade + * [THRIFT-1257] - thrift's dependency scope on javax.servlet:servlet-api should be 'provided' + +## Improvement + * [THRIFT-1445] - minor C++ generator variable cleanup + * [THRIFT-1435] - make TException.Message property conformant to the usual expectations + * [THRIFT-1431] - Rename 'sys' module to 'util' + * [THRIFT-1396] - Dephi generator has dependacy on boost 1.42 later. + * [THRIFT-1395] - Patch to prevent warnings for integer types in some cases + * [THRIFT-1275] - thrift: always prefix namespaces with " ::" + * [THRIFT-1274] - thrift: fail compilation if an unexpected token is + * [THRIFT-1271] - thrift: fix missing namespace in generated local + * [THRIFT-1270] - thrift: add --allow-neg-keys argument to allow + * [THRIFT-1345] - Allow building without tests + * [THRIFT-1286] - Modernize the Thrift Ruby Library Dev Environment + * [THRIFT-1284] - thrift: fix processor inheritance + * [THRIFT-1283] - thrift: wrap t_cpp_generator::generate_process_function() to 80 + * [THRIFT-1282] - Upgrade httpclient to 4.1.2 (from 4.0.1) + * [THRIFT-1281] - add @generated to the docblock + * [THRIFT-1280] - Thrift: Improve Monitor exception-free interfaces + * [THRIFT-1278] - javadoc warnings - compilation + * [THRIFT-1227] - Erlang implementation of thrift JSON protocol + * [THRIFT-1295] - Duplicate include in TSocket.cpp + * [THRIFT-1294] - thrift: fix log message typos in TSimpleServer + * [THRIFT-1293] - thrift: improve handling of exceptions thrown by + * [THRIFT-1292] - thrift: silence log spew from TThreadedServer + * [THRIFT-1288] - Allow typedefed exceptions in throws clauses + * [THRIFT-1290] - thrift: TNonblockingServer: clean up state in the + * [THRIFT-1287] - thrift: start refactoring some of the C++ processor + * [THRIFT-1289] - thrift: implement TNonblockingServer::stop() + * [THRIFT-1305] - thrift: make TConnection a private inner class of + * [THRIFT-1304] - TNonblockingServer: pass in the connection context to + * [THRIFT-1302] - thrift: raise an exception if send() times out in + * [THRIFT-1301] - thrift: consolidate common code in TNonblockingServer + * [THRIFT-1377] - abort PHP deserialization on unknown field type + * [THRIFT-1379] - fix uninitialized enum values in thrift C++ objects + * [THRIFT-1376] - Make port specification option in thrift remote + * [THRIFT-1375] - fixed a hex char conversion bug in TJSONProtocol + * [THRIFT-1373] - Fix user-defined exception generation in thrift (python) + * [THRIFT-1361] - Optional replacement of pthread by boost::thread + * [THRIFT-1320] - Consistency of configure generated config.h + * [THRIFT-1317] - Remove copy constructibility from + * [THRIFT-1316] - thrift: update server classes to accept + * [THRIFT-1315] - thrift: generate server interface factory classes + * [THRIFT-1314] - thrift: add TProcessorFactory + * [THRIFT-1335] - Add accept timeout to TServerSocket + * [THRIFT-1334] - Add more info to IllegalStateException + * [THRIFT-1333] - Make RWGuard not copyable + * [THRIFT-1332] - TSSLTransportParameters class uses hard coded value keyManagerType: SunX509 + * [THRIFT-1251] - Generated java code should indicate which fields are required and which are optional + * [THRIFT-1387] - Build MSVC libraries with Boost Threads instead of Pthreads + * [THRIFT-1339] - Extend Tuple Protocol to TUnions + * [THRIFT-1031] - Patch to compile Thrift for vc++ 9.0 and 10.0 + * [THRIFT-1130] - Add the ability to specify symbolic default value for optional boolean + * [THRIFT-1123] - Patch to compile Thrift server and client for vc++ 9.0 and 10.0 + * [THRIFT-386] - Make it possible to build the Python library without the extension + +## New Feature + * [THRIFT-1401] - JSON-protocol for Delphi XE Libraries + * [THRIFT-1167] - Java nonblocking server with more than one thread for select and handling IO + * [THRIFT-1366] - Delphi generator, lirbrary and unit test. + * [THRIFT-1354] - Add rake task to build just the gem file + * [THRIFT-769] - Pluggable Serializers + +## Sub-task + * [THRIFT-1415] - delphi: add version Info to the library + * [THRIFT-1391] - Improved Delphi XE test cases + + + +Thrift 0.7 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-1140] - Framed Transport Client using C (Glib) Library hangs when connecting to Ruby Server + * [THRIFT-1154] - HttpClient does not specify the connection close parameter + * [THRIFT-1153] - HttpClient does not specify the connection close parameter + * [THRIFT-1149] - Nonblocking server fails when client connection is reset + * [THRIFT-1146] - Android Incompatibility : in Android < 2.3 java.io.IOException doesn't support for Throwable parameter in constructor + * [THRIFT-1133] - Java and JavaScript tutorial is broken since we have Java maven deployment + * [THRIFT-1132] - Deserialization error in TApplicationException C# + * [THRIFT-1131] - C# JSON Protocol is unable to decode escaped characters in string + * [THRIFT-1208] - python TCompactProtocol.py writeBool and readBool not follow the compact-proto-spec-2.txt spec for CONTAINER_WRITE, CONTAINER_READ + * [THRIFT-1200] - JS compiler generates code that clobbers existing namespaces + * [THRIFT-1183] - Pure-ruby CompactProtocol raises ArgumentError when deserializing under Ruby 1.9 + * [THRIFT-1182] - Native deserializer segfaults on incorrect list element type + * [THRIFT-1181] - AS3 compiler generates incorrect code for setting default values in constructor + * [THRIFT-1234] - thrift --help is missing doc on py:utf8strings + * [THRIFT-1180] - AS3 compiler generates uncompilable code for binary types. + * [THRIFT-1194] - Java lib does not install artifacts to local dir correctly + * [THRIFT-1193] - Potential infinite loop in nonblocking_server + * [THRIFT-1192] - Typo: TProtocol.h tests for HAVE_SYS_PARAM_H_ + * [THRIFT-1190] - readBufferBytesAllocated in TNonblockingServer.java should be AtomicLong to fix FD leakage and general server malfunction + * [THRIFT-1187] - nonblocking_server shutdown race under Ruby 1.9 + * [THRIFT-1178] - Java: TBase signature should be T extends TBase + * [THRIFT-1164] - Segmentation fault on NULL pointer in t_js_generator::generate_const + * [THRIFT-1171] - Perl write/readDouble assumes little-endian platform + * [THRIFT-1222] - Unhandled exception for TEvhttpServer request + * [THRIFT-1220] - TProcessor::process never returns false + * [THRIFT-1285] - Stable 0.7.0 Windows compiler exe available on the webside is not the good one + * [THRIFT-1218] - c_glib uses wrong name in pkg-config + * [THRIFT-1215] - Undefined property Thirft in lib/js/thrift.js + * [THRIFT-1211] - When using THttpClient, non 200 responses leave the connection open + * [THRIFT-1228] - The php accelerator module calls flush incorrectly + * [THRIFT-1308] - libfb303-0.7.0.jar missing in maven repository + * [THRIFT-1255] - Mismatch of method name between JavaME's lib and generated code (compareTo/compareObjects) + * [THRIFT-1253] - Code generated for maps is not compiling + * [THRIFT-1252] - Segfault in Ruby deserializer + * [THRIFT-1094] - bug in TCompactProto python readMessageEnd method and updated test cases + * [THRIFT-1093] - several bugs in python TCompactProtocol + * [THRIFT-1092] - generated validate() method has wrong indentation + * [THRIFT-1011] - Error generating package imports when using classes from other packages + * [THRIFT-1050] - Declaring an argument named "manager" to a service method produces code that fails compile due to name conflicts with protected ivars in TAsyncClient + * [THRIFT-1074] - .keystore and .truststore are missing from the 0.6.0 distribution + * [THRIFT-1067] - Tons of bugs in php implementation + * [THRIFT-1065] - Unexpected exceptions not proper handled on JS + * [THRIFT-1076] - Erlang Thrift socket server has a bug that causes java thrift client of framed binary client to throw "out of sequence" exception + * [THRIFT-1057] - casts in TBinaryProtocol.tcc causing "dereferencing type-punned pointer will break strict-aliasing rules" warnings from gcc + * [THRIFT-1055] - csharp TServerSocket and TSocket do not disable Nagle via Socket.NoDelay = true like cpp and java do + * [THRIFT-1054] - explicit call to PKG_PROG_PKG_CONFIG is missing and first use of PKG_CHECK_MODULES may not happen, causes mono detection to fail + * [THRIFT-1117] - JavaScript Unit Test does not work anymore because libthrift*.jar where moved by Maven Deployment + * [THRIFT-1111] - The HTML generator does not distinguish between string and binary types + * [THRIFT-1032] - "make dist" fails due to c_glib problem + * [THRIFT-1036] - Auto-generated C++ code fails to compile with "-Werror -Wextra -Wall" g++ compiler flags + * [THRIFT-1041] - TDeserializer holds onto a reference of the array it reads after it is done deserializing + * [THRIFT-1106] - C++ code TAsyncProtocolProcessor.h & TAsyncBufferProcessor.h dont have virtual functions but no virtual destructor. Causes warnings on -Wall + * [THRIFT-1105] - OCaml generator does not prefix methods of included structs with their type + * [THRIFT-1104] - INSTALLDIRS should be included in configure script + * [THRIFT-1102] - typo in configure.ac: "==" operator in 'test' (instead of"'=") + * [THRIFT-1101] - bytebuffer length calculation in TBinaryProtocol writeBinary + * [THRIFT-1098] - Undefined properties in TBinaryProtocolFactory + * [THRIFT-1081] - PHP tests broken and somewhat incomplete + * [THRIFT-1080] - erlang test's 'make' fails on Mac OSX + * [THRIFT-1078] - ThriftTest.thrift generates invalid PHP library + * [THRIFT-1120] - proto.WriteListEnd being called in the wrong place + * [THRIFT-1119] - TJSONProtocol fails to UTF8 decode strings + * [THRIFT-867] - PHP accelerator module's output transport is incompatible with TFramedTransport + * [THRIFT-826] - PHP TSocket Write Timeout + * [THRIFT-835] - Bad AS3 syntax in constructors that set default values + * [THRIFT-788] - thrift_protocol.so: multiget/multiget_slice does not handle more than 17 keys correctly + * [THRIFT-125] - OCaml libraries don't compile with 32-bit ocaml + * [THRIFT-342] - PHP: can't have sets of complex types + * [THRIFT-731] - configure doesn't check for ant >= 1.7 + * [THRIFT-690] - Update TApplicationException codes + * [THRIFT-638] - BufferedTransport + C extensions block until recv timeout is reached on last fread call + +## Dependency upgrade + * [THRIFT-1177] - Update thrift to reflect changes in Go's networking libraries + +## Improvement + * [THRIFT-1155] - Remove log4j dependency from java client + * [THRIFT-1151] - Produce more informative runtime error in case of schema and data mismatch during serialization + * [THRIFT-1207] - Support DESTDIR on "make install" of ruby libs + * [THRIFT-1199] - Union structs should have generated methods to test whether a specific field is currently set + * [THRIFT-1233] - Remove unused include in generated C++ code + * [THRIFT-1189] - Ruby deserializer speed improvements + * [THRIFT-1170] - Thrift Generated Code and Java 5 + * [THRIFT-1174] - Publish as3 client implementation via Maven for use by flex-mojos users + * [THRIFT-1225] - TCompactProtocol for PHP + * [THRIFT-1221] - Remove SimpleCallback.h + * [THRIFT-1217] - Use evutil_socketpair instead of pipe (Windows port) + * [THRIFT-1216] - build Java Library behind a proxy + * [THRIFT-1231] - Remove bogus include + * [THRIFT-1213] - Membuffer should provide a way to get back the buffer + * [THRIFT-1237] - Java fb303 missing some methods + * [THRIFT-1063] - Fix Erlang Tutorial Files + * [THRIFT-1053] - Make remote client's IP address available for all socket related transports + * [THRIFT-1109] - Deploy fb303 along side libthrift to maven repo + * [THRIFT-1107] - improvement for compiler-generated python for 'None' object comparisons + * [THRIFT-1069] - Add command line option to prevent thrift from inserting gen-* directories + * [THRIFT-1049] - Allow for TServerSocket python library to bind to a specific host + * [THRIFT-1126] - Extending struct_info for erlang bindings + * [THRIFT-1100] - python TSSLSocket improvements, including certificate validation + * [THRIFT-994] - Don't try to invoke phpize if we don't have it + * [THRIFT-993] - Some improvements in C++ stubs for oneway operations + * [THRIFT-997] - Using valueOf for base types in getFieldValue + * [THRIFT-418] - Don't do runtime sorting of struct fields + * [THRIFT-151] - TSSLServerSocket and TSSLSocket implementation + * [THRIFT-27] - Generated erlang types don't contain default values for records + * [THRIFT-113] - to-string methods should omit optional null fields from output + * [THRIFT-363] - Maven Deploy + * [THRIFT-447] - Make an abstract base Client class so we can generate less code + * [THRIFT-627] - should c++ have setters for optional fields? + +## New Feature + * [THRIFT-1236] - Erlang Reconnecting Thrift Client + * [THRIFT-1021] - Framed transport support for OCaml + * [THRIFT-1068] - Python SSL Socket Support + * [THRIFT-1103] - TZlibTransport for python, a zlib compressed transport + * [THRIFT-1083] - Preforking python process pool server + * [THRIFT-999] - Add TForkingServer + +## Sub-task + * [THRIFT-1152] - Attributes from private to protected + * [THRIFT-1038] - Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable + +## Task + * [THRIFT-892] - Refactor erlang build system with rebar + +## Wish + * [THRIFT-625] - Add support for 'Go' + + + +Thrift 0.6.1 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-1133] - Java and JavaScript tutorial is broken since we have Java maven deployment + * [THRIFT-1131] - C# JSON Protocol is unable to decode escaped characters in string + * [THRIFT-1074] - .keystore and .truststore are missing from the 0.6.0 distribution + +## Improvement + * [THRIFT-1109] - Deploy fb303 along side libthrift to maven repo + * [THRIFT-363] - Maven Deploy + +## Question + * [THRIFT-1206] - did the THRIFT 0.6.1 merge THRIFT-563 ? + +## Sub-task + * [THRIFT-1163] - How can i use multi service in one program? + +## Task + * [THRIFT-1112] - Apply THRIFT-363 to 0.6 branch + * [THRIFT-1113] - Apply THRIFT-1074 to 0.6 branch + + + +Thrift 0.6 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-1020] - OCaml compiler generates invalid OCaml + * [THRIFT-1015] - TUnion does not handle ByteBuffer in toString + * [THRIFT-1013] - generated java code may have name clashes with thrift library + * [THRIFT-1009] - TUnion does not correctly deep copy a ByteBuffer + * [THRIFT-1032] - "make dist" fails due to c_glib problem + * [THRIFT-868] - Referencing constant values doesn't work with with typedef types + * [THRIFT-971] - java module can't be compiled without ivy and network connection + * [THRIFT-970] - Under heavy load, THttpClient may fail with "too many open files" + * [THRIFT-969] - Java Tutorial broken, move CalculatorHandler to a separate file + * [THRIFT-807] - JavaScript: Initialization of Base Types with 0 instead of null + * [THRIFT-955] - Thrift compiler for Windows uses lowercase names and directories which is inconsistent with compiling on other platforms + * [THRIFT-992] - Naming convention in C# constructor is not consistent with other fields causes compile errors + * [THRIFT-1008] - byte[] accessors throw NPE on unset field + * [THRIFT-1006] - Impossible to correctly qualify an enum constant in an external thrift file + * [THRIFT-950] - Haskell bindings treat 'byte' as unsigned 8-bit int (Data.Word.Word8), java/cpp as signed (byte/int8_t). + * [THRIFT-975] - lib/c_glib/README is missing => breaks make dist + * [THRIFT-944] - Support all version-4s of base + * [THRIFT-939] - optional binary fields throw NPE on default byte[] getters + * [THRIFT-935] - PHP Extension aborts the build if php-config is not installed + * [THRIFT-933] - Haskell's Thrift.cabal has warnings + * [THRIFT-932] - Haskell tests need to be run through 'make check' (and probably 'cabal check') too + * [THRIFT-904] - C# TSocket should disable nagle and linger + * [THRIFT-941] - Make PHP C Extension use the defined Protocol writeMessageBegin function + * [THRIFT-940] - 'make check' fails if boost is not in the std include and link paths + * [THRIFT-924] - Fix generated php structure constants + * [THRIFT-979] - ruby bindings used to work on jruby + * [THRIFT-977] - Hex Conversion Bug in C++ TJSONProtocol + * [THRIFT-347] - PHP TSocket Timeout Issues + * [THRIFT-517] - TExceptions thrown by server result in cryptic error message on client - Tried to read 4 bytes, but only got 0 bytes + +## Improvement + * [THRIFT-1024] - Add Python Twisted example to the Tutorial + * [THRIFT-958] - Change accessmodifer on trans_ field in the FrameBuffer class to public. + * [THRIFT-957] - THsHaServer: Change access modifier of the invoker field. + * [THRIFT-1002] - CodeStyle: t_c_glib_generator.cc + * [THRIFT-1005] - Give unions byte[] signature methods to go along with their ByteBuffer counterparts + * [THRIFT-951] - Add a new isServing() method to TServer + * [THRIFT-943] - Silly readme typo fix. + * [THRIFT-961] - JavaScript TestSuite using ant/ivy and Java's ServerTestBase Handler + * [THRIFT-960] - add TestServer, TestNonblockingServer and TestClient again + * [THRIFT-949] - Modify the TEnum interface so it defines a method similar to findByValue + * [THRIFT-946] - Augment FieldValueMetaData so it differentiates 'string' and 'binary' fields. + * [THRIFT-903] - custom ThreadFactory in THsHaServer + * [THRIFT-913] - Test Case for Url encoded strings + simple enhancement to lib/js/test/RunTestServer.sh + * [THRIFT-926] - Miscellaneous C++ improvements + * [THRIFT-929] - Improvements to the C++ test suite + * [THRIFT-893] - add JavaScript to the tutorial examples + * [THRIFT-1003] - Polishing c_glib code + * [THRIFT-71] - Debian packaging for thrift + +## New Feature + * [THRIFT-1033] - Node.js language target + * [THRIFT-947] - Provide a helper method to determine the TProtocol used to serialize some data. + * [THRIFT-928] - Make more statistics available in C++ servers + * [THRIFT-922] - Templatized [de]serialization code for C++ + * [THRIFT-923] - Event-driven client and server support for C++ + * [THRIFT-925] - Provide name<->value map for enums in C++ + * [THRIFT-927] - Add option to modify the PHP include path + * [THRIFT-377] - TFileTransport port in Java + * [THRIFT-106] - TSSLServerSocket + * [THRIFT-582] - C implementation of Thrift + * [THRIFT-745] - Make it easier to instantiate servers + +## Sub-task + * [THRIFT-1038] - Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable + +## Task + * [THRIFT-862] - Async client issues / improvements + +## Test + * [THRIFT-581] - Add a testsuite for txThrift (Twisted) + + + +Thrift 0.5.0 - Incubating +-------------------------------------------------------------------------------- +THRIFT-505 Build Make configure give a summary of the enabled components (David Reiss) +THRIFT-506 Build Allow Thrift to be built without the C++ library (David Reiss) +THRIFT-844 Build Build Requirements state autoconf 2.59+ is required, but 2.60+ is needed (Harlan Lieberman-Berg) +THRIFT-850 Build Perl runtime requires Bit::Vector which may not be installed by default, but configure does not fail (Michael Lum) +THRIFT-854 Build Provide configure option and make rules to build/install php extension (Anthony Molinaro) +THRIFT-858 Build Have bootstrap.sh check for a suitable autoconf version before running (David Reiss) +THRIFT-871 Build Thrift compiler for WIndows (binary distribution) (David Reiss) +THRIFT-323 C# TJSONProtocol (Roger Meier) +THRIFT-634 C# C# Compiler Generates Incorrect Code For Fields which begin with an uppercase letter (Jon S Akhtar) +THRIFT-881 C# add csharp to the tutorial (Roger Meier) +THRIFT-856 C++ Building cpp library fails on OS X with malloc and free not being declared in scope (James Clarke) +THRIFT-865 C++ C++ compiler build depends on libfl even when flex/lex not detected (David Reiss) +THRIFT-900 C++ Unix domain socket (Roger Meier) +THRIFT-920 C++ C++ Test and Tutorial does not compile anymore due to the change within Enum handling (Roger Meier) +THRIFT-567 C++ Can't immediately stop a TSimpleServer thread that is idle (Rush Manbert) +THRIFT-756 C++ Exposing TSocket(int) constructor to public (Rajat Goel) +THRIFT-798 C++ TNonblockingServer leaks resources when destroyed (David Reiss) +THRIFT-812 C++, Python Demo of Thrift over ZeroMQ (David Reiss) +THRIFT-629 Cocoa Unused Field In TSocketServer Appears To Break iPhone Build (Jon S Akhtar) +THRIFT-838 Cocoa Generated Cocoa classes have useless @dynamic declarations (Kevin Ballard) +THRIFT-805 Cocoa Don't generate process_XXXX methods for oneway methods (Brad Taylor) +THRIFT-507 Compiler Remove the compiler's dependency on Boost (David Reiss) +THRIFT-895 Compiler (General) Thrift compiler does not allow two different enumerations to have the same key name for one of the enum values (David Reiss) +THRIFT-852 Compiler (General) Missing newline causes many compiler warnings (Anthony Molinaro) +THRIFT-877 Compiler (General) smalltalk namespace doesn't work (Bruce Lowekamp) +THRIFT-897 Compiler (General) Don't allow unqualified constant access to enum values (Bryan Duxbury) +THRIFT-9 Compiler (General) Add a default namespace declaration for all languages (David Reiss) +THRIFT-599 Erlang Don't use unnecessary processes in the Erlang transports and clients (David Reiss) +THRIFT-646 Erlang Erlang library is missing install target (David Reiss) +THRIFT-698 Erlang Generated module list should contain atoms, not strings (Anthony Molinaro) +THRIFT-866 Erlang term() in spec definitions seems to not work in erlang R12 (Anthony Molinaro) +THRIFT-886 Erlang Dialyzer warning (Anthony Molinaro) +THRIFT-785 Erlang Framed transport server problems (Anthony Molinaro) +THRIFT-884 HTML HTML Generator: add Key attribute to the Data Types Tables (Roger Meier) +THRIFT-652 Haskell Generated field name for strut is not capitalized correctly (Christian Lavoie) +THRIFT-743 Haskell compile error with GHC 6.12.1 (Christian Lavoie) +THRIFT-901 Haskell Allow the bindings to compile without -fglasgow-exts and with -Wall -Werror (Christian Lavoie) +THRIFT-905 Haskell Make haskell thrift bindings use automake to compile and install (Christian Lavoie) +THRIFT-906 Haskell Improve type mappings (Christian Lavoie) +THRIFT-914 Haskell Make haskell bindings 'easily' compilable (Christian Lavoie) +THRIFT-918 Haskell Make haskell tests run again (Christian Lavoie) +THRIFT-919 Haskell Update Haskell bindings README (Christian Lavoie) +THRIFT-787 Haskell Enums are not read correctly (Christian Lavoie) +THRIFT-250 Java ExecutorService as a constructor parameter for TServer (Ed Ceaser) +THRIFT-693 Java Thrift compiler generated java code that throws compiler warnings about deprecated methods. (Bryan Duxbury) +THRIFT-843 Java TNonblockingSocket connects without a timeout (Bryan Duxbury) +THRIFT-845 Java async client does not respect timeout (Ning Liang) +THRIFT-870 Java Java constants don't get Javadoc comments (Bryan Duxbury) +THRIFT-873 Java Java tests fail due to Too many open files (Todd Lipcon) +THRIFT-876 Java Add SASL support (Aaron T. Myers) +THRIFT-879 Java Remove @Override from TUnion.clear (Dave Engberg) +THRIFT-882 Java deep copy of binary fields does not copy ByteBuffer characteristics (arrayOffset, position) (Bryan Duxbury) +THRIFT-888 Java async client should also have nonblocking connect (Eric Jensen) +THRIFT-890 Java Java tutorial doesn't work (Todd Lipcon) +THRIFT-894 Java Make default accessors for binary fields return byte[]; provide new accessors to get ByteBuffer version (Bryan Duxbury) +THRIFT-896 Java TNonblockingSocket.isOpen() returns true even after close() (Eric Jensen) +THRIFT-907 Java libfb303 doesn't compile in 0.4.0 (Todd Lipcon) +THRIFT-912 Java Improvements and bug fixes to SASL implementation (Todd Lipcon) +THRIFT-917 Java THsHaServer should not accept an ExecutorService without catching RejectedExecutionException (Ed Ceaser) +THRIFT-931 Java Use log4j for Java tests (Todd Lipcon) +THRIFT-880 JavaME JavaME code generator and runtime library (Dave Engberg) +THRIFT-846 JavaScript JavaScript Test Framwork: extended Testcases (Roger Meier) +THRIFT-885 JavaScript Url encoded strings never get decoded? How do we fix this? (T Jake Luciani) +THRIFT-911 JavaScript (JavaScript compiler) Const structs, maps, sets, and lists generate a trailing comma (T Jake Luciani) +THRIFT-860 OCaml copy method and reset method (Lev Walkin) +THRIFT-682 PHP PHP extension doesn't compile on Mac OS X (Bryan Duxbury) +THRIFT-851 PHP php extension fails to compile on centos 5.x (Todd Lipcon) +THRIFT-840 Perl Perl protocol handler could be more robust against unrecognised types (Conrad Hughes) +THRIFT-758 Perl incorrect deference in exception handling (Yann Kerherve) +THRIFT-257 Python Support validation of required fields (Esteve Fernandez) +THRIFT-335 Python Compact Protocol for Python (David Reiss) +THRIFT-596 Python Make Python's TBufferedTransport use a configurable input buffer (David Reiss) +THRIFT-597 Python Python THttpServer performance improvements (David Reiss) +THRIFT-598 Python Allow Python's threading servers to use daemon threads (David Reiss) +THRIFT-666 Python Allow the handler to override HTTP responses in THttpServer (David Reiss) +THRIFT-673 Python Generated Python code has whitespace issues (Ian Eure) +THRIFT-721 Python THttpClient ignores url parameters (Thomas Kho) +THRIFT-824 Python TApplicationException.__str__() refers to class constants as globals (Peter Schuller) +THRIFT-855 Python Include optimized compiled python objects in install (Anthony Molinaro) +THRIFT-859 Python Allow py:twisted to be generated in different namespace than py (Bruce Lowekamp) +THRIFT-869 Python TSocket.py on Mac (and FreeBSD) doesn't handle ECONNRESET from recv() (Steven Knight) +THRIFT-875 Python Include python setup.cfg in dist (Anthony Molinaro) +THRIFT-610 Ruby binary_protocol.rb segfaults [line 86] (Unassigned) +THRIFT-899 Ruby Ruby read timeouts can sometimes be 2x what they should be (Ryan King) +THRIFT-909 Ruby allow block argument to struct constructor (Michael Stockton) +THRIFT-456 Test Suite Bad IP address string in test/cpp/src/main.cpp (Rush Manbert) + + +Thrift 0.4.0 - Incubating +-------------------------------------------------------------------------------- +THRIFT-650 Build Make Check fails on Centos/OSX with 0.2.0 tarball (Anthony Molinaro) +THRIFT-770 Build Get 'make dist' to work without first compiling source code (Anthony Molinaro) +THRIFT-160 C# Created THttpTransport for the C# library based on WebHttpRequest (Michael Greene) +THRIFT-834 C# THttpClient resends contents of message after transport errors (Anatoly Fayngelerin) +THRIFT-247 C++ THttpServer Transport (Unassigned) +THRIFT-676 C++ Change C++ code generator so that generated classes can be wrapped with SWIG (Unassigned) +THRIFT-570 Compiler Thrift compiler does not error when duplicate method names are present (Bruce Simpson) +THRIFT-808 Compiler Segfault when constant declaration references a struct field that doesn't exist (Bryan Duxbury) +THRIFT-646 Erlang Erlang library is missing install target (Anthony Molinaro) +THRIFT-544 General multiple enums with the same key generate invalid code (Ben Taitelbaum) +THRIFT-434 General ruby compiler should warn when a reserved word is used (Michael Stockton) +THRIFT-799 General Files missing proper Apache license header (Bryan Duxbury) +THRIFT-832 HTML HTML generator shows unspecified struct fields as 'required' (Bryan Duxbury) +THRIFT-226 Java Collections with binary keys or values break equals() (Bryan Duxbury) +THRIFT-484 Java Ability to use a slice of a buffer instead of a direct byte[] for binary fields (Bryan Duxbury) +THRIFT-714 Java maxWorkerThreads parameter to THsHaServer has no effect (Bryan Duxbury) +THRIFT-751 Java Add clear() method to TBase (Bryan Duxbury) +THRIFT-765 Java Improved string encoding and decoding performance (Bryan Duxbury) +THRIFT-768 Java Async client for Java (Bryan Duxbury) +THRIFT-774 Java TDeserializer should provide a partialDeserialize method for primitive types (Piotr Kozikowski) +THRIFT-783 Java .equals java method is broken on structs containing binary-type fields (Unassigned) +THRIFT-804 Java CompareTo is broken for unions set to map, set, or list (Bryan Duxbury) +THRIFT-814 Java Include a TServlet in the standard Thrift distribution (Mathias Herberts) +THRIFT-818 Java Async client doesn't send method args (Bryan Duxbury) +THRIFT-830 Java Switch binary field implementation from byte[] to ByteBuffer (Bryan Duxbury) +THRIFT-831 Java FramedTransport implementation that reuses its buffers (Bryan Duxbury) +THRIFT-833 Java build.xml in lib/java is missing a classpathref attribute for the javadoc task (Bryan Duxbury) +THRIFT-836 Java Race condition causes CancelledKeyException in TAsyncClientManager (Bryan Duxbury) +THRIFT-842 Java Upgrade to current version of commons-lang (2.5 instead of 2.4) and/or change dependency in ivy.xml to not be exact (Bryan Duxbury) +THRIFT-815 JavaScript Deserialization of lists is critically broken. (T Jake Luciani) +THRIFT-827 OCaml OCaml generator to take default values into account (Lev Walkin) +THRIFT-647 PHP PHP library is missing install target (Anthony Molinaro) +THRIFT-682 PHP PHP extension doesn't compile on Mac OS X (Bryan Duxbury) +THRIFT-718 PHP Thrift PHP library includes closing tags and extraneous whitespace (Nicholas Telford) +THRIFT-778 PHP PHP socket listening server (Nick Jones) +THRIFT-780 PHP PHP extension sometimes causes an abort with two exceptions at the same time (David Reiss) +THRIFT-837 PHP PHP accelerator bug for writes > 8k (Thomas Kho) +THRIFT-782 Perl Perl code for writing containers doesn't count length of write*Begin or write*End (Conrad Hughes) +THRIFT-395 Python Python library + compiler does not support unicode strings (Unassigned) +THRIFT-133 Ruby 'namespace ruby' should error out, or be an alias to 'namespace rb' (Bryan Duxbury) +THRIFT-664 Ruby Ruby extension fails to build with Ruby 1.9.1 (Rajesh Malepati) +THRIFT-699 Ruby Excise unused "native protocol method table" stuff from thrift_native (Bryan Duxbury) +THRIFT-767 Ruby ruby compiler does not keep comments for enum values (Bryan Duxbury) +THRIFT-811 Ruby http_client_transport.rb: allow custom http headers (Tony Kamenick) +THRIFT-459 Ruby Ruby installation always tries to write to /Library/Ruby/site (Matthieu Imbert) + + +Thrift 0.1.0 - Incubating (not released) +-------------------------------------------------------------------------------- +Compatibility Breaking Changes: + C++: + * It's quite possible that regenerating code and rebuilding will be + required. Make sure your headers match your libs! + + Java: + + Python: + + Ruby: + * Generated files now have underscored names [THRIFT-421] + * The library has been rearranged to be more Ruby-like [THRIFT-276] + + Erlang: + * Generated code will have to be regenerated, and the new code will + have to be deployed atomically with the new library code [THRIFT-136] + +New Features and Bug Fixes: + C++: + * Support for TCompactProtocol [THRIFT-333] + + Java: + * Support for TCompactProtocol [THRIFT-110] + + Python: + * Support for Twisted [THRIFT-148] + + Ruby: + * Support for TCompactProtocol [THRIFT-332] + diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc index 61782b9d8bd..fc23e87358b 100644 --- a/compiler/cpp/src/thrift/generate/t_js_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc @@ -41,6 +41,10 @@ using std::stringstream; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes +// largest consecutive integer representable by a double (2 ^ 53 - 1) +static const long max_safe_integer = 0x1fffffffffffff; +// smallest consecutive number representable by a double (-2 ^ 53 + 1) +static const long min_safe_integer = -max_safe_integer; #include "thrift/generate/t_oop_generator.h" @@ -200,6 +204,7 @@ class t_js_generator : public t_oop_generator { std::string js_includes(); std::string ts_includes(); + std::string ts_service_includes(); std::string render_includes(); std::string declare_field(t_field* tfield, bool init = false, bool obj = false); std::string function_signature(t_function* tfunction, @@ -296,7 +301,7 @@ class t_js_generator : public t_oop_generator { * Returns "declare " if no module was defined. * @return string */ - string ts_declare() { return (ts_module_.empty() ? "declare " : ""); } + string ts_declare() { return (ts_module_.empty() ? (gen_node_ ? "declare " : "export declare ") : ""); } /** * Returns "?" if the given field is optional or has a default value. @@ -430,6 +435,8 @@ void t_js_generator::init_generator() { f_types_ << "if (typeof " << pns << " === 'undefined') {" << endl; f_types_ << " " << pns << " = {};" << endl; f_types_ << "}" << endl; + f_types_ << "" << "if (typeof module !== 'undefined' && module.exports) {" << endl; + f_types_ << " module.exports." << pns << " = " << pns << ";" << endl << "}" << endl; } if (gen_ts_) { ts_module_ = pns; @@ -448,10 +455,11 @@ string t_js_generator::js_includes() { if (!gen_es6_) { result += js_const_type_ + "Q = thrift.Q;\n"; } + result += js_const_type_ + "Int64 = require('node-int64');\n"; return result; } - - return ""; + string result = "if (typeof Int64 === 'undefined' && typeof require === 'function') {\n " + js_const_type_ + "Int64 = require('node-int64');\n}\n"; + return result; } /** @@ -462,10 +470,24 @@ string t_js_generator::ts_includes() { return string( "import thrift = require('thrift');\n" "import Thrift = thrift.Thrift;\n" - "import Q = thrift.Q;\n"); + "import Q = thrift.Q;\n" + "import Int64 = require('node-int64');"); } + return string("import Int64 = require('node-int64');"); +} - return ""; +/** + * Prints service ts imports + */ +string t_js_generator::ts_service_includes() { + if (gen_node_) { + return string( + "import thrift = require('thrift');\n" + "import Thrift = thrift.Thrift;\n" + "import Q = thrift.Q;\n" + "import Int64 = require('node-int64');"); + } + return string("import Int64 = require('node-int64');"); } /** @@ -593,9 +615,18 @@ string t_js_generator::render_const_value(t_type* type, t_const_value* value) { case t_base_type::TYPE_I8: case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: out << value->get_integer(); break; + case t_base_type::TYPE_I64: + { + int64_t const& integer_value = value->get_integer(); + if (integer_value <= max_safe_integer && integer_value >= min_safe_integer) { + out << "new Int64(" << integer_value << ")"; + } else { + out << "new Int64('" << std::hex << integer_value << std::dec << "')"; + } + } + break; case t_base_type::TYPE_DOUBLE: if (value->get_type() == t_const_value::CV_INTEGER) { out << value->get_integer(); @@ -1086,9 +1117,8 @@ void t_js_generator::generate_service(t_service* tservice) { f_service_ts_ << "/// get_extends()->get_name() << ".d.ts\" />" << endl; } - f_service_ts_ << autogen_comment() << endl; + f_service_ts_ << autogen_comment() << endl << ts_includes() << endl << endl; if (gen_node_) { - f_service_ts_ << ts_includes() << endl; f_service_ts_ << "import ttypes = require('./" + program_->get_name() + "_types');" << endl; // Generate type aliases // enum @@ -1119,9 +1149,18 @@ void t_js_generator::generate_service(t_service* tservice) { f_service_ts_ << "import " << (*s_iter)->get_name() << " = ttypes." << js_namespace(program_) << (*s_iter)->get_name() << endl; } + } else { + f_service_ts_ << "import { " << program_->get_name() << " } from \"./" << program_->get_name() << "_types\";" << endl << endl; } if (!ts_module_.empty()) { - f_service_ts_ << "declare module " << ts_module_ << " {"; + if (gen_node_) { + f_service_ts_ << "declare module " << ts_module_ << " {"; + } else { + f_service_ts_ << "declare module \"./" << program_->get_name() << "_types\" {" << endl; + indent_up(); + f_service_ts_ << ts_indent() << "module " << program_->get_name() << " {" << endl; + indent_up(); + } } } @@ -1149,7 +1188,13 @@ void t_js_generator::generate_service(t_service* tservice) { f_service_.close(); if (gen_ts_) { if (!ts_module_.empty()) { - f_service_ts_ << "}"; + if (gen_node_) { + f_service_ts_ << "}" << endl; + } else { + indent_down(); + f_service_ts_ << ts_indent() << "}" << endl; + f_service_ts_ << "}" << endl; + } } f_service_ts_.close(); } @@ -2572,10 +2617,12 @@ string t_js_generator::ts_get_type(t_type* type) { break; case t_base_type::TYPE_I16: case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: case t_base_type::TYPE_DOUBLE: ts_type = "number"; break; + case t_base_type::TYPE_I64: + ts_type = "Int64"; + break; case t_base_type::TYPE_VOID: ts_type = "void"; } diff --git a/configure.ac b/configure.ac index c5683ec7720..bdd1dd2a06c 100755 --- a/configure.ac +++ b/configure.ac @@ -831,6 +831,7 @@ AC_CONFIG_FILES([ lib/rs/test/Makefile lib/lua/Makefile lib/swift/Makefile + lib/ts/Makefile lib/xml/Makefile lib/xml/test/Makefile test/Makefile diff --git a/lib/js/Gruntfile.js b/lib/js/Gruntfile.js index b32a016b8e0..87b826fb159 100644 --- a/lib/js/Gruntfile.js +++ b/lib/js/Gruntfile.js @@ -68,6 +68,16 @@ module.exports = function(grunt) { ThriftGenDeepConstructor: { command: '../../compiler/cpp/thrift -gen js -o test ../../test/JsDeepConstructorTest.thrift' }, + ThriftBrowserifyNodeInt64: { + command: [ + './node_modules/browserify/bin/cmd.js ./node_modules/node-int64/Int64.js -s Int64 -o test/build/js/lib/Int64.js', + './node_modules/browserify/bin/cmd.js ../nodejs/lib/thrift/int64_util.js -s Int64Util -o test/build/js/lib/Int64Util.js', + './node_modules/browserify/bin/cmd.js ./node_modules/json-int64/index.js -s JSONInt64 -o test/build/js/lib/JSONInt64.js' + ].join(' && ') + }, + ThriftGenInt64: { + command: '../../compiler/cpp/thrift -gen js -o test ../../test/Int64Test.thrift' + }, ThriftGenDoubleConstants: { command: '../../compiler/cpp/thrift -gen js -o test ../../test/DoubleConstantsTest.thrift' }, @@ -147,6 +157,18 @@ module.exports = function(grunt) { }, } }, + ThriftJS_Int64: { + options: { + urls: [ + 'http://localhost:8089/test-int64.html' + ], + puppeteer: { + headless: true, + args: ['--no-sandbox'], + ignoreHTTPSErrors: true, + }, + } + }, ThriftWS: { options: { urls: [ @@ -218,7 +240,7 @@ module.exports = function(grunt) { } }, jshint: { - // The main thrift library file. not es6 yet :( + // The main Thrift library file. not es6 yet :( lib: { src: ['src/**/*.js'], }, @@ -261,7 +283,7 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-jsdoc'); grunt.loadNpmTasks('grunt-shell-spawn'); - grunt.registerTask('wait', 'Wait just one second for server to start', function () { + grunt.registerTask('wait', 'Wait just one second for the server to start', function () { var done = this.async(); setTimeout(function() { done(true); @@ -269,25 +291,37 @@ module.exports = function(grunt) { }); grunt.registerTask('installAndGenerate', [ - 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen', - 'shell:ThriftGenDeepConstructor', 'shell:ThriftGenDoubleConstants', + 'shell:InstallThriftJS', + 'shell:InstallThriftNodeJSDep', + 'shell:ThriftGen', + 'shell:ThriftGenDeepConstructor', + 'shell:ThriftGenDoubleConstants', 'shell:InstallTestLibs', + 'shell:ThriftBrowserifyNodeInt64', + 'shell:ThriftGenInt64' ]); grunt.registerTask('test', [ 'installAndGenerate', 'jshint', - 'shell:ThriftTestServer', 'shell:ThriftTestServer_TLS', - 'shell:ThriftTestServerES6', 'shell:ThriftTestServerES6_TLS', + 'shell:ThriftTestServer', + 'shell:ThriftTestServer_TLS', + 'shell:ThriftTestServerES6', + 'shell:ThriftTestServerES6_TLS', 'wait', 'qunit:ThriftDeepConstructor', - 'qunit:ThriftJS', 'qunit:ThriftJS_TLS', + 'qunit:ThriftJS', + 'qunit:ThriftJS_TLS', 'qunit:ThriftJS_DoubleRendering', 'qunit:ThriftWS', - 'qunit:ThriftJSJQ', 'qunit:ThriftJSJQ_TLS', + 'qunit:ThriftJSJQ', + 'qunit:ThriftJSJQ_TLS', 'qunit:ThriftWSES6', - 'shell:ThriftTestServer:kill', 'shell:ThriftTestServer_TLS:kill', - 'shell:ThriftTestServerES6:kill', 'shell:ThriftTestServerES6_TLS:kill', + 'qunit:ThriftJS_Int64', + 'shell:ThriftTestServer:kill', + 'shell:ThriftTestServer_TLS:kill', + 'shell:ThriftTestServerES6:kill', + 'shell:ThriftTestServerES6_TLS:kill', ]); grunt.registerTask('default', ['test', 'concat', 'uglify', 'jsdoc']); }; diff --git a/lib/js/README.md b/lib/js/README.md index 9d51e2a3ca3..5c7a1c23b84 100644 --- a/lib/js/README.md +++ b/lib/js/README.md @@ -138,3 +138,8 @@ TypeScript definition files can also be generated by running: thrift --gen js:ts file.thrift +# Breaking Changes + +## 0.13.0 + +1. 64-bit integer constants are now generatd using node-int64 e.g.: var x = new Int64("7fffffffffffffff"); diff --git a/lib/js/package-lock.json b/lib/js/package-lock.json index 63d81c3aa1c..19710dfe28a 100644 --- a/lib/js/package-lock.json +++ b/lib/js/package-lock.json @@ -4,11 +4,51 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "acorn": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz", + "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==", + "dev": true + }, + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "dev": true + }, + "acorn-node": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.6.2.tgz", + "integrity": "sha512-rIhNEZuNI8ibQcL7ANm/mGyPukIaZsRNX9psFNQURyJW0nu6k8wjSDld20z6v2mDBWqX13pIEnk9gGZJHIlEXg==", + "dev": true, + "requires": { + "acorn": "^6.0.2", + "acorn-dynamic-import": "^4.0.0", + "acorn-walk": "^6.1.0", + "xtend": "^4.0.1" + } + }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "dev": true + }, "agent-base": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", @@ -109,12 +149,30 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", @@ -137,6 +195,43 @@ "safer-buffer": "~2.1.0" } }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -254,6 +349,12 @@ } } }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -269,6 +370,12 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==" }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -308,6 +415,219 @@ } } }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + } + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + } + }, + "browserify": { + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.3.tgz", + "integrity": "sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^1.11.0", + "browserify-zlib": "~0.2.0", + "buffer": "^5.0.2", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.0", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^2.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.0.0", + "labeled-stream-splicer": "^2.0.0", + "mkdirp": "^0.5.0", + "module-deps": "^6.0.0", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "~0.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^2.0.0", + "stream-http": "^2.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.10.1", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "pako": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz", + "integrity": "sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "string_decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", + "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, "browserify-zlib": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", @@ -317,6 +637,16 @@ "pako": "~0.2.0" } }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -329,12 +659,24 @@ "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", "dev": true }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -352,6 +694,12 @@ "unset-value": "^1.0.0" } }, + "cached-path-relative": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", + "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==", + "dev": true + }, "camelcase": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", @@ -404,6 +752,16 @@ "supports-color": "^5.3.0" } }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -508,6 +866,18 @@ "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "dev": true }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "dev": true, + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } + }, "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", @@ -576,6 +946,18 @@ "date-now": "^0.1.4" } }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -588,6 +970,43 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -601,6 +1020,25 @@ "which": "^1.2.9" } }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -705,18 +1143,76 @@ } } }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, + "deps-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "shasum": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, "detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true }, + "detective": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.1.0.tgz", + "integrity": "sha512-TFHMqfOvxlgrfVzTEkNBSh9SvSNX/HfF4OFI2QFGCyPm02EsyILqnUeb5P6q7JZ3SFNTBL5t2sePRgrN4epUWQ==", + "dev": true, + "requires": { + "acorn-node": "^1.3.0", + "defined": "^1.0.0", + "minimist": "^1.1.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, "dom-serializer": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", @@ -741,6 +1237,12 @@ } } }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, "domelementtype": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", @@ -766,6 +1268,41 @@ "domelementtype": "1" } }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -777,6 +1314,21 @@ "safer-buffer": "^2.1.0" } }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, "entities": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", @@ -824,6 +1376,22 @@ "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", "dev": true }, + "events": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", + "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -1173,10 +1741,22 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, "get-value": { @@ -1539,6 +2119,15 @@ "har-schema": "^2.0.0" } }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", @@ -1586,6 +2175,26 @@ } } }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "hasha": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", @@ -1597,6 +2206,17 @@ "pinkie-promise": "^2.0.0" } }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "homedir-polyfill": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", @@ -1618,6 +2238,12 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, + "htmlescape": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "dev": true + }, "htmlparser2": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", @@ -1643,6 +2269,12 @@ "sshpk": "^1.7.0" } }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, "https-proxy-agent": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", @@ -1679,6 +2311,12 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "dev": true + }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", @@ -1710,6 +2348,33 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true, + "requires": { + "source-map": "~0.5.3" + } + }, + "insert-module-globals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", + "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + } + }, "interpret": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", @@ -2061,6 +2726,14 @@ } } }, + "json-int64": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-0.0.3.tgz", + "integrity": "sha512-6nAloOVry+klkifPKPqFLX/FI4L95oBfu5T5vKKt4L8gik8cy80wOtzC+kM1Vh2r60QdDqDr7u/XVk6VlfueEg==", + "requires": { + "node-int64": "0.4.0" + } + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -2075,6 +2748,15 @@ "dev": true, "optional": true }, + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -2092,6 +2774,18 @@ "graceful-fs": "^4.1.6" } }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -2126,6 +2820,25 @@ "graceful-fs": "^4.1.9" } }, + "labeled-stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", + "integrity": "sha512-MC94mHZRvJ3LfykJlTUipBqenZz1pacOZEMhhQ8dMGcDHs0SBE5GbsavUXV7YtP3icBW17W0Zy1I0lfASmo9Pg==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "isarray": "^2.0.4", + "stream-splicer": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", + "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==", + "dev": true + } + } + }, "lazy-cache": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", @@ -2181,6 +2894,12 @@ "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -2271,6 +2990,17 @@ } } }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "meow": { "version": "3.7.0", "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", @@ -2318,6 +3048,16 @@ "to-regex": "^3.0.2" } }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, "mime": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", @@ -2339,6 +3079,18 @@ "mime-db": "~1.37.0" } }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -2382,6 +3134,64 @@ "minimist": "0.0.8" } }, + "module-deps": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.0.tgz", + "integrity": "sha512-hKPmO06so6bL/ZvqVNVqdTVO8UAYsi3tQWlCa+z9KuWhoN4KDQtb5hcqQQv58qYiDE21wIvnttZEPiDgEbpwbA==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "cached-path-relative": "^1.0.0", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.0.2", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -2413,6 +3223,11 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" + }, "nopt": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", @@ -2533,6 +3348,12 @@ "wrappy": "1" } }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -2573,6 +3394,28 @@ "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", "dev": true }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" + } + }, "parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", @@ -2605,6 +3448,12 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", @@ -2626,6 +3475,18 @@ "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, "path-root": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", @@ -2652,6 +3513,19 @@ "pinkie-promise": "^2.0.0" } }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -2732,6 +3606,12 @@ "meow": "^3.1.0" } }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", @@ -2758,12 +3638,25 @@ "dev": true, "optional": true }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "punycode": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true, - "optional": true + "dev": true }, "puppeteer": { "version": "1.7.0", @@ -2811,6 +3704,72 @@ "dev": true, "optional": true }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -3002,6 +3961,16 @@ "glob": "^7.0.5" } }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -3052,6 +4021,26 @@ } } }, + "sha.js": { + "version": "2.4.11", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shasum": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true, + "requires": { + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" + } + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -3067,6 +4056,18 @@ "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", "dev": true }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } + }, "shelljs": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", @@ -3079,6 +4080,12 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -3314,6 +4321,153 @@ } } }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "http://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -3352,6 +4506,23 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "^1.1.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -3367,6 +4538,15 @@ "integrity": "sha1-cX0izFPwzh3vVZQ2LzqJouu5EQU=", "dev": true }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "requires": { + "acorn-node": "^1.2.0" + } + }, "taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", @@ -3383,8 +4563,58 @@ "version": "2.3.8", "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, - "optional": true + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "requires": { + "process": "~0.11.0" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true }, "to-object-path": { "version": "0.3.0", @@ -3445,6 +4675,12 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -3493,12 +4729,30 @@ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "dev": true }, + "umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", + "dev": true + }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", "dev": true }, + "undeclared-identifiers": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz", + "integrity": "sha512-13EaeocO4edF/3JKime9rD7oB6QI8llAGhgn5fKOPyfkJbRb6NFv9pYV6dFEmpa4uRjKeBqLZP8GpuzqHlKDMQ==", + "dev": true, + "requires": { + "acorn-node": "^1.3.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + } + }, "underscore": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", @@ -3622,12 +4876,39 @@ "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -3672,6 +4953,12 @@ "extsprintf": "^1.2.0" } }, + "vm-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", + "dev": true + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -3744,6 +5031,12 @@ "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=" }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, "yargs": { "version": "3.10.0", "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", diff --git a/lib/js/package.json b/lib/js/package.json index a59cdc484fa..c4bcc6d6c3b 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -2,6 +2,7 @@ "name": "thrift", "version": "1.0.0", "devDependencies": { + "browserify": "^16.2.3", "grunt": "^1.0.2", "grunt-cli": "^1.2.0", "grunt-contrib-concat": "^1.0.1", @@ -10,10 +11,12 @@ "grunt-contrib-uglify": "^1.0.1", "grunt-jsdoc": "^2.2.1", "grunt-shell-spawn": "^0.3.10", - "jslint": "^0.12.0" + "jslint": "^0.12.0", + "node-int64": "^0.4.0" }, "dependencies": { "jsdoc": "^3.5.5", + "json-int64": "^0.0.3", "nopt": "^4.0.1" } } diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index fad24d68ef4..b9fa62dd61b 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -1007,7 +1007,11 @@ Thrift.Protocol.prototype = { /** Serializes a number */ writeI64: function(i64) { - this.tstack.push(i64); + if (typeof i64 === 'number') { + this.tstack.push(i64); + } else { + this.tstack.push(Int64Util.toDecimalString(i64)); + } }, /** Serializes a number */ @@ -1078,12 +1082,16 @@ Thrift.Protocol.prototype = { this.rstack = []; this.rpos = []; - if (typeof JSON !== 'undefined' && typeof JSON.parse === 'function') { - this.robj = JSON.parse(this.transport.readAll()); + received = this.transport.readAll(); + + if (typeof JSONInt64 !== 'undefined' && typeof JSONInt64.parse === 'function') { + this.robj = JSONInt64.parse(received); + } else if (typeof JSON !== 'undefined' && typeof JSON.parse === 'function') { + this.robj = JSON.parse(received); } else if (typeof jQuery !== 'undefined') { - this.robj = jQuery.parseJSON(this.transport.readAll()); + this.robj = jQuery.parseJSON(received); } else { - this.robj = eval(this.transport.readAll()); + this.robj = eval(received); } var r = {}; @@ -1226,7 +1234,6 @@ Thrift.Protocol.prototype = { r.vtype = Thrift.Protocol.RType[map.shift()]; r.size = map.shift(); - this.rpos.push(this.rstack.length); this.rstack.push(map.shift()); @@ -1351,8 +1358,54 @@ Thrift.Protocol.prototype = { /** Returns the an object with a value property set to the next value found in the protocol buffer */ - readI64: function() { - return this.readI32(); + readI64: function(f) { + if (f === undefined) { + f = this.rstack[this.rstack.length - 1]; + } + + var r = {}; + + if (f instanceof Array) { + if (f.length === 0) { + r.value = undefined; + } else { + if (!f.isReversed) { + f.reverse(); + f.isReversed = true; + } + r.value = f.pop(); + } + } else if (f instanceof Object) { + var int64Object = true; + var objectKeys = Object.keys(f).sort(); + var int64Keys = ['buffer', 'offset']; + if (objectKeys.length !== int64Keys.length) { + int64Object = false; + } + for (var it=0; int64Object && it < objectKeys.length; ++it) { + if (objectKeys[it] !== int64Keys[it]) { + int64Object = false; + } + } + if (int64Object) { + r.value = f; + } else { + for (var i in f) { + if (i === null) { + continue; + } + this.rstack.push(f[i]); + delete f[i]; + + r.value = i; + break; + } + } + } else { + r.value = f; + this.rstack.pop(); + } + return r; }, /** Returns the an object with a value property set to the diff --git a/lib/js/test/build.xml b/lib/js/test/build.xml index 04c1360baa1..4795fd26751 100755 --- a/lib/js/test/build.xml +++ b/lib/js/test/build.xml @@ -28,13 +28,13 @@ - + - + @@ -187,7 +187,6 @@ --> - diff --git a/lib/js/test/test-deep-constructor.html b/lib/js/test/test-deep-constructor.html index dfc0da62d1a..462481a2daf 100755 --- a/lib/js/test/test-deep-constructor.html +++ b/lib/js/test/test-deep-constructor.html @@ -22,6 +22,7 @@ Thrift Javascript Bindings: Unit Test + diff --git a/lib/js/test/test-es6.html b/lib/js/test/test-es6.html index bf04901e045..f0b8dd9b5f1 100644 --- a/lib/js/test/test-es6.html +++ b/lib/js/test/test-es6.html @@ -22,6 +22,9 @@ Thrift Javascript Bindings: Unit Test + + + diff --git a/lib/js/test/test-int64.html b/lib/js/test/test-int64.html new file mode 100644 index 00000000000..620e6ff861d --- /dev/null +++ b/lib/js/test/test-int64.html @@ -0,0 +1,55 @@ ++ + + + + + Int64 Constants in JS: Unit Test + + + + + + + + + + + + + + + + + + +

Int64 Constants in JS: Unit Test

+

+
+

+
+ + + diff --git a/lib/js/test/test-int64.js b/lib/js/test/test-int64.js new file mode 100644 index 00000000000..4df87e1d398 --- /dev/null +++ b/lib/js/test/test-int64.js @@ -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. + */ + /* jshint -W100 */ + +// Work around for old API used by QUnitAdapter of jsTestDriver +if (typeof QUnit.log == 'function') { + // When using real QUnit (fron PhantomJS) log failures to console + QUnit.log(function(details) { + if (!details.result) { + console.log('======== FAIL ========'); + console.log('TestName: ' + details.name); + if (details.message) console.log(details.message); + console.log('Expected: ' + details.expected); + console.log('Actual : ' + details.actual); + console.log('======================'); + } + }); +} + +QUnit.module('Int64'); + + QUnit.test('Int64', function(assert) { + console.log('Int64 test -- starts'); + const EXPECTED_SMALL_INT64_AS_NUMBER = 42; + const EXPECTED_SMALL_INT64 = new Int64(42); + const EXPECTED_MAX_JS_SAFE_INT64 = new Int64(Number.MAX_SAFE_INTEGER); + const EXPECTED_MIN_JS_SAFE_INT64 = new Int64(Number.MIN_SAFE_INTEGER); + const EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64 = new Int64("0020000000000000"); // hex-encoded + const EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64 = new Int64("ffe0000000000000"); // hex-encoded 2's complement + const EXPECTED_MAX_SIGNED_INT64 = new Int64("7fffffffffffffff"); // hex-encoded + const EXPECTED_MIN_SIGNED_INT64 = new Int64("8000000000000000"); // hex-encoded 2's complement + const EXPECTED_INT64_LIST = [ + EXPECTED_SMALL_INT64, + EXPECTED_MAX_JS_SAFE_INT64, + EXPECTED_MIN_JS_SAFE_INT64, + EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64, + EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64, + EXPECTED_MAX_SIGNED_INT64, + EXPECTED_MIN_SIGNED_INT64 + ]; + + assert.ok(EXPECTED_SMALL_INT64.equals(Int64Test.SMALL_INT64)); + assert.ok(EXPECTED_MAX_JS_SAFE_INT64.equals(Int64Test.MAX_JS_SAFE_INT64)); + assert.ok(EXPECTED_MIN_JS_SAFE_INT64.equals(Int64Test.MIN_JS_SAFE_INT64)); + assert.ok( + EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64.equals( + Int64Test.MAX_JS_SAFE_PLUS_ONE_INT64 + ) + ); + assert.ok( + EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64.equals( + Int64Test.MIN_JS_SAFE_MINUS_ONE_INT64 + ) + ); + assert.ok(EXPECTED_MAX_SIGNED_INT64.equals(Int64Test.MAX_SIGNED_INT64)); + assert.ok(EXPECTED_MIN_SIGNED_INT64.equals(Int64Test.MIN_SIGNED_INT64)); + assert.equal( + EXPECTED_SMALL_INT64_AS_NUMBER, + Int64Test.SMALL_INT64.toNumber() + ); + assert.equal( + Number.MAX_SAFE_INTEGER, + Int64Test.MAX_JS_SAFE_INT64.toNumber() + ); + assert.equal( + Number.MIN_SAFE_INTEGER, + Int64Test.MIN_JS_SAFE_INT64.toNumber() + ); + + for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { + assert.ok(EXPECTED_INT64_LIST[i].equals(Int64Test.INT64_LIST[i])); + } + console.log('Int64 test -- ends'); + }); + diff --git a/lib/js/test/test-nojq.html b/lib/js/test/test-nojq.html index 408424ed572..37b3eb8d0e8 100644 --- a/lib/js/test/test-nojq.html +++ b/lib/js/test/test-nojq.html @@ -22,6 +22,9 @@ Thrift Javascript Bindings: Unit Test + + + diff --git a/lib/js/test/test.html b/lib/js/test/test.html index 8b67014bb9f..85c83956737 100755 --- a/lib/js/test/test.html +++ b/lib/js/test/test.html @@ -22,6 +22,9 @@ Thrift Javascript Bindings: Unit Test + + + diff --git a/lib/js/test/test.js b/lib/js/test/test.js index a86a50935c9..35ed6ffd284 100755 --- a/lib/js/test/test.js +++ b/lib/js/test/test.js @@ -51,6 +51,9 @@ const transport = new Thrift.Transport('/service'); const protocol = new Thrift.Protocol(transport); const client = new ThriftTest.ThriftTestClient(protocol); +const int64_2_pow_60 = new Int64('1000000000000000'); +const int64_minus_2_pow_60 = new Int64('f000000000000000'); + // Work around for old API used by QUnitAdapter of jsTestDriver if (typeof QUnit.log == 'function') { // When using real QUnit (fron PhantomJS) log failures to console @@ -132,9 +135,12 @@ QUnit.module('Base Types'); }); QUnit.test('I64', function(assert) { assert.equal(client.testI64(0), 0); - //This is usually 2^60 but JS cannot represent anything over 2^52 accurately - assert.equal(client.testI64(Math.pow(2, 52)), Math.pow(2, 52)); - assert.equal(client.testI64(-Math.pow(2, 52)), -Math.pow(2, 52)); + + let int64_2_pow_60_result = client.testI64(int64_2_pow_60); + assert.ok(int64_2_pow_60.equals(int64_2_pow_60_result)); + + let int64_minus_2_pow_60_result = client.testI64(int64_minus_2_pow_60); + assert.ok(int64_minus_2_pow_60.equals(int64_minus_2_pow_60_result)); }); @@ -145,15 +151,14 @@ QUnit.module('Structured Types'); structTestInput.string_thing = 'worked'; structTestInput.byte_thing = 0x01; structTestInput.i32_thing = Math.pow(2, 30); - //This is usually 2^60 but JS cannot represent anything over 2^52 accurately - structTestInput.i64_thing = Math.pow(2, 52); + structTestInput.i64_thing = int64_2_pow_60; const structTestOutput = client.testStruct(structTestInput); assert.equal(structTestOutput.string_thing, structTestInput.string_thing); assert.equal(structTestOutput.byte_thing, structTestInput.byte_thing); assert.equal(structTestOutput.i32_thing, structTestInput.i32_thing); - assert.equal(structTestOutput.i64_thing, structTestInput.i64_thing); + assert.ok(structTestOutput.i64_thing.equals(structTestInput.i64_thing)); assert.equal(JSON.stringify(structTestOutput), JSON.stringify(structTestInput)); }); @@ -163,8 +168,7 @@ QUnit.module('Structured Types'); xtrTestInput.string_thing = 'worked'; xtrTestInput.byte_thing = 0x01; xtrTestInput.i32_thing = Math.pow(2, 30); - //This is usually 2^60 but JS cannot represent anything over 2^52 accurately - xtrTestInput.i64_thing = Math.pow(2, 52); + xtrTestInput.i64_thing = int64_2_pow_60; const nestTestInput = new ThriftTest.Xtruct2(); nestTestInput.byte_thing = 0x02; @@ -177,7 +181,7 @@ QUnit.module('Structured Types'); assert.equal(nestTestOutput.struct_thing.string_thing, nestTestInput.struct_thing.string_thing); assert.equal(nestTestOutput.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing); assert.equal(nestTestOutput.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing); - assert.equal(nestTestOutput.struct_thing.i64_thing, nestTestInput.struct_thing.i64_thing); + assert.ok(nestTestOutput.struct_thing.i64_thing.equals(nestTestInput.struct_thing.i64_thing)); assert.equal(nestTestOutput.i32_thing, nestTestInput.i32_thing); assert.equal(JSON.stringify(nestTestOutput), JSON.stringify(nestTestInput)); @@ -252,7 +256,7 @@ QUnit.module('Structured Types'); structTestInput.string_thing = 'worked'; structTestInput.byte_thing = 0x01; structTestInput.i32_thing = Math.pow(2, 30); - structTestInput.i64_thing = Math.pow(2, 52); + structTestInput.i64_thing = int64_2_pow_60; const structTestOutput = modifiedClient.testStruct(structTestInput); @@ -260,7 +264,7 @@ QUnit.module('Structured Types'); assert.equal(structTestOutput.string_thing, structTestInput.string_thing); assert.equal(structTestOutput.changed, null); assert.equal(structTestOutput.i32_thing, structTestInput.i32_thing); - assert.equal(structTestOutput.i64_thing, structTestInput.i64_thing); + assert.ok(structTestOutput.i64_thing.equals(structTestInput.i64_thing)); }); @@ -332,13 +336,13 @@ QUnit.module('Insanity'); 'string_thing': 'Goodbye4', 'byte_thing': 4, 'i32_thing': 4, - 'i64_thing': 4 + 'i64_thing': new Int64(4) }, { 'string_thing': 'Hello2', 'byte_thing': 2, 'i32_thing': 2, - 'i64_thing': 2 + 'i64_thing': new Int64(2) }] }; QUnit.test('testInsanity', function(assert) { @@ -401,15 +405,13 @@ QUnit.module('Async'); assert.expect(2); const done = assert.async(2); - //This is usually 2^60 but JS cannot represent anything over 2^52 accurately - client.testI64(Math.pow(2, 52), function(result) { - assert.equal(result, Math.pow(2, 52)); + client.testI64(int64_2_pow_60, function(result) { + assert.ok(int64_2_pow_60.equals(result)); done(); }); - //This is usually 2^60 but JS cannot represent anything over 2^52 accurately - client.testI64(Math.pow(-2, 52), function(result) { - assert.equal(result, Math.pow(-2, 52)); + client.testI64(int64_minus_2_pow_60, function(result) { + assert.ok(int64_minus_2_pow_60.equals(result)); done(); }); }); diff --git a/lib/js/test/test_handler.js b/lib/js/test/test_handler.js index af5f7bd9c17..8ba296ba108 100644 --- a/lib/js/test/test_handler.js +++ b/lib/js/test/test_handler.js @@ -24,6 +24,7 @@ const es6Mode = process.argv.includes('--es6'); const genFolder = es6Mode ? 'gen-nodejs-es6' : 'gen-nodejs'; const ttypes = require(`./${genFolder}/ThriftTest_types`); const TException = require('../../nodejs/lib/thrift').TException; +const Int64 = require('node-int64'); exports.ThriftTestHandler = { testVoid: function(result) { @@ -122,13 +123,13 @@ exports.ThriftTestHandler = { hello.string_thing = 'Hello2'; hello.byte_thing = 2; hello.i32_thing = 2; - hello.i64_thing = 2; + hello.i64_thing = new Int64(2); const goodbye = new ttypes.Xtruct(); goodbye.string_thing = 'Goodbye4'; goodbye.byte_thing = 4; goodbye.i32_thing = 4; - goodbye.i64_thing = 4; + goodbye.i64_thing = new Int64(4); const crazy = new ttypes.Insanity(); crazy.userMap = []; diff --git a/lib/js/test/testws.html b/lib/js/test/testws.html index 184500ff97d..5ff9f22911e 100644 --- a/lib/js/test/testws.html +++ b/lib/js/test/testws.html @@ -22,6 +22,9 @@ Thrift Javascript Bindings: Unit Test + + + diff --git a/lib/nodejs/test/int64.test.js b/lib/nodejs/test/int64.test.js new file mode 100644 index 00000000000..106e446b11e --- /dev/null +++ b/lib/nodejs/test/int64.test.js @@ -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. + */ + +const Int64 = require("node-int64"); +const i64types = require("./gen-nodejs-es6/Int64Test_types.js"); +const test = require("tape"); + +const cases = { + "should correctly generate Int64 constants": function(assert) { + const EXPECTED_SMALL_INT64_AS_NUMBER = 42; + const EXPECTED_SMALL_INT64 = new Int64(42); + const EXPECTED_MAX_JS_SAFE_INT64 = new Int64(Number.MAX_SAFE_INTEGER); + const EXPECTED_MIN_JS_SAFE_INT64 = new Int64(Number.MIN_SAFE_INTEGER); + const EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64 = new Int64("0020000000000000"); // hex-encoded + const EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64 = new Int64("ffe0000000000000"); // hex-encoded 2's complement + const EXPECTED_MAX_SIGNED_INT64 = new Int64("7fffffffffffffff"); // hex-encoded + const EXPECTED_MIN_SIGNED_INT64 = new Int64("8000000000000000"); // hex-encoded 2's complement + const EXPECTED_INT64_LIST = [ + EXPECTED_SMALL_INT64, + EXPECTED_MAX_JS_SAFE_INT64, + EXPECTED_MIN_JS_SAFE_INT64, + EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64, + EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64, + EXPECTED_MAX_SIGNED_INT64, + EXPECTED_MIN_SIGNED_INT64 + ]; + + assert.ok(EXPECTED_SMALL_INT64.equals(i64types.SMALL_INT64)); + assert.ok(EXPECTED_MAX_JS_SAFE_INT64.equals(i64types.MAX_JS_SAFE_INT64)); + assert.ok(EXPECTED_MIN_JS_SAFE_INT64.equals(i64types.MIN_JS_SAFE_INT64)); + assert.ok( + EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64.equals( + i64types.MAX_JS_SAFE_PLUS_ONE_INT64 + ) + ); + assert.ok( + EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64.equals( + i64types.MIN_JS_SAFE_MINUS_ONE_INT64 + ) + ); + assert.ok(EXPECTED_MAX_SIGNED_INT64.equals(i64types.MAX_SIGNED_INT64)); + assert.ok(EXPECTED_MIN_SIGNED_INT64.equals(i64types.MIN_SIGNED_INT64)); + assert.equal( + EXPECTED_SMALL_INT64_AS_NUMBER, + i64types.SMALL_INT64.toNumber() + ); + assert.equal( + Number.MAX_SAFE_INTEGER, + i64types.MAX_JS_SAFE_INT64.toNumber() + ); + assert.equal( + Number.MIN_SAFE_INTEGER, + i64types.MIN_JS_SAFE_INT64.toNumber() + ); + + for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { + assert.ok(EXPECTED_INT64_LIST[i].equals(i64types.INT64_LIST[i])); + } + assert.end(); + } +}; + +Object.keys(cases).forEach(function(caseName) { + test(caseName, cases[caseName]); +}); diff --git a/lib/nodejs/test/testAll.sh b/lib/nodejs/test/testAll.sh index 24f1f2ea13b..e98b198be25 100755 --- a/lib/nodejs/test/testAll.sh +++ b/lib/nodejs/test/testAll.sh @@ -61,13 +61,16 @@ TESTOK=0 ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node ${DIR}/../../../test/ThriftTest.thrift ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node ${DIR}/../../../test/JsDeepConstructorTest.thrift +${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node ${DIR}/../../../test/Int64Test.thrift mkdir ${DIR}/gen-nodejs-es6 ${DIR}/../../../compiler/cpp/thrift -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${DIR}/../../../test/ThriftTest.thrift ${DIR}/../../../compiler/cpp/thrift -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${DIR}/../../../test/JsDeepConstructorTest.thrift +${DIR}/../../../compiler/cpp/thrift -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${DIR}/../../../test/Int64Test.thrift #unit tests node ${DIR}/binary.test.js || TESTOK=1 +node ${DIR}/int64.test.js || TESTOK=1 node ${DIR}/deep-constructor.test.js || TESTOK=1 #integration tests diff --git a/lib/nodets/Makefile.am b/lib/nodets/Makefile.am index ea640cf0e74..939dff2a5e3 100755 --- a/lib/nodets/Makefile.am +++ b/lib/nodets/Makefile.am @@ -20,6 +20,7 @@ stubs: $(top_srcdir)/test/ThriftTest.thrift mkdir -p test-compiled $(THRIFT) --gen js:node,ts -o test/ $(top_srcdir)/test/ThriftTest.thrift && $(THRIFT) --gen js:node,ts -o test-compiled $(top_srcdir)/test/ThriftTest.thrift + $(THRIFT) --gen js:node,ts -o test/ $(top_srcdir)/test/Int64Test.thrift && $(THRIFT) --gen js:node,ts -o test-compiled $(top_srcdir)/test/Int64Test.thrift ts-compile: stubs mkdir -p test-compiled diff --git a/lib/nodets/test/int64.test.ts b/lib/nodets/test/int64.test.ts new file mode 100644 index 00000000000..3ff0d85b470 --- /dev/null +++ b/lib/nodets/test/int64.test.ts @@ -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. + */ + +import Int64 = require("node-int64"); +import i64types = require("./gen-nodejs/Int64Test_types"); +import test = require("tape"); + +const cases = { + "should correctly generate Int64 constants": function(assert) { + const EXPECTED_SMALL_INT64_AS_NUMBER: number = 42; + const EXPECTED_SMALL_INT64: Int64 = new Int64(42); + const EXPECTED_MAX_JS_SAFE_INT64: Int64 = new Int64(Number.MAX_SAFE_INTEGER); + const EXPECTED_MIN_JS_SAFE_INT64: Int64 = new Int64(Number.MIN_SAFE_INTEGER); + const EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64: Int64 = new Int64("0020000000000000"); // hex-encoded + const EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64: Int64 = new Int64("ffe0000000000000"); // hex-encoded 2's complement + const EXPECTED_MAX_SIGNED_INT64: Int64 = new Int64("7fffffffffffffff"); // hex-encoded + const EXPECTED_MIN_SIGNED_INT64: Int64 = new Int64("8000000000000000"); // hex-encoded 2's complement + const EXPECTED_INT64_LIST: Int64[] = [ + EXPECTED_SMALL_INT64, + EXPECTED_MAX_JS_SAFE_INT64, + EXPECTED_MIN_JS_SAFE_INT64, + EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64, + EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64, + EXPECTED_MAX_SIGNED_INT64, + EXPECTED_MIN_SIGNED_INT64 + ]; + + assert.ok(EXPECTED_SMALL_INT64.equals(i64types.SMALL_INT64)); + assert.ok(EXPECTED_MAX_JS_SAFE_INT64.equals(i64types.MAX_JS_SAFE_INT64)); + assert.ok(EXPECTED_MIN_JS_SAFE_INT64.equals(i64types.MIN_JS_SAFE_INT64)); + assert.ok( + EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64.equals( + i64types.MAX_JS_SAFE_PLUS_ONE_INT64 + ) + ); + assert.ok( + EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64.equals( + i64types.MIN_JS_SAFE_MINUS_ONE_INT64 + ) + ); + assert.ok(EXPECTED_MAX_SIGNED_INT64.equals(i64types.MAX_SIGNED_INT64)); + assert.ok(EXPECTED_MIN_SIGNED_INT64.equals(i64types.MIN_SIGNED_INT64)); + assert.equal( + EXPECTED_SMALL_INT64_AS_NUMBER, + i64types.SMALL_INT64.toNumber() + ); + assert.equal( + Number.MAX_SAFE_INTEGER, + i64types.MAX_JS_SAFE_INT64.toNumber() + ); + assert.equal( + Number.MIN_SAFE_INTEGER, + i64types.MIN_JS_SAFE_INT64.toNumber() + ); + + for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { + assert.ok(EXPECTED_INT64_LIST[i].equals(i64types.INT64_LIST[i])); + } + assert.end(); + } +}; + +Object.keys(cases).forEach(function(caseName) { + test(caseName, cases[caseName]); +}); diff --git a/lib/nodets/test/test-cases.ts b/lib/nodets/test/test-cases.ts index ca740ec8262..44f254e9200 100644 --- a/lib/nodets/test/test-cases.ts +++ b/lib/nodets/test/test-cases.ts @@ -1,6 +1,7 @@ 'use strict'; import ttypes = require('./gen-nodejs/ThriftTest_types'); +import Int64 = require('node-int64'); //all Languages in UTF-8 /*jshint -W100 */ @@ -84,7 +85,7 @@ export var out = new ttypes.Xtruct({ string_thing: 'Zero', byte_thing: 1, i32_thing: -3, - i64_thing: 1000000 + i64_thing: new Int64(1000000) }); export var out2 = new ttypes.Xtruct2(); @@ -93,17 +94,17 @@ out2.struct_thing = out; out2.i32_thing = 5; export var crazy = new ttypes.Insanity({ - "userMap":{ "5":5, "8":8 }, + "userMap":{ "5":new Int64(5), "8":new Int64(8) }, "xtructs":[new ttypes.Xtruct({ "string_thing":"Goodbye4", "byte_thing":4, "i32_thing":4, - "i64_thing":4 + "i64_thing":new Int64(4) }), new ttypes.Xtruct({ "string_thing":"Hello2", "byte_thing":2, "i32_thing":2, - "i64_thing":2 + "i64_thing":new Int64(2) })] }); diff --git a/lib/nodets/test/testAll.sh b/lib/nodets/test/testAll.sh index a7c00bfd931..3be12c3622a 100755 --- a/lib/nodets/test/testAll.sh +++ b/lib/nodets/test/testAll.sh @@ -11,7 +11,9 @@ compile() { #generating thrift code ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node,ts ${DIR}/../../../test/ThriftTest.thrift + ${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node,ts ${DIR}/../../../test/Int64Test.thrift ${DIR}/../../../compiler/cpp/thrift -o ${COMPILEDDIR} --gen js:node,ts ${DIR}/../../../test/ThriftTest.thrift + ${DIR}/../../../compiler/cpp/thrift -o ${COMPILEDDIR} --gen js:node,ts ${DIR}/../../../test/Int64Test.thrift tsc --outDir $COMPILEDDIR --project $DIR/tsconfig.json } @@ -30,6 +32,8 @@ testServer() return $RET } +node ${COMPILEDDIR}/int64.test.js || TESTOK=1 + #integration tests testServer || TESTOK=1 diff --git a/lib/nodets/test/test_handler.ts b/lib/nodets/test/test_handler.ts index 1bc855a7099..996c32a5a32 100644 --- a/lib/nodets/test/test_handler.ts +++ b/lib/nodets/test/test_handler.ts @@ -24,6 +24,7 @@ import ttypes = require("./gen-nodejs/ThriftTest_types"); import thrift = require("thrift"); import Thrift = thrift.Thrift; import Q = require("q"); +import Int64 = require("node-int64"); export class SyncThriftTestHandler { @@ -62,7 +63,7 @@ export class SyncThriftTestHandler { return Q.resolve(insane); } - testMulti(arg0: any, arg1: number, arg2: number, arg3: { [k: number]: string; }, arg4: ttypes.Numberz, arg5: number) { + testMulti(arg0: any, arg1: number, arg2: Int64, arg3: { [k: number]: string; }, arg4: ttypes.Numberz, arg5: number) { var hello = new ttypes.Xtruct(); hello.string_thing = 'Hello2'; hello.byte_thing = arg0; @@ -196,7 +197,7 @@ export class AsyncThriftTestHandler { } return Q.resolve(); } - testMulti(arg0: any, arg1: number, arg2: number, arg3: { [k: number]: string; }, arg4: ttypes.Numberz, arg5: number, result: Function): Q.IPromise { + testMulti(arg0: any, arg1: number, arg2: Int64, arg3: { [k: number]: string; }, arg4: ttypes.Numberz, arg5: number, result: Function): Q.IPromise { var hello = this.syncHandler.testMulti(arg0, arg1, arg2, arg3, arg4, arg5); hello.then(hello => result(null, hello)); return Q.resolve(); diff --git a/lib/ts/.gitignore b/lib/ts/.gitignore new file mode 100644 index 00000000000..24f250ed05e --- /dev/null +++ b/lib/ts/.gitignore @@ -0,0 +1,2 @@ +test/build/ +test/gen-* diff --git a/lib/ts/Gruntfile.js b/lib/ts/Gruntfile.js new file mode 100644 index 00000000000..fcd79f8e543 --- /dev/null +++ b/lib/ts/Gruntfile.js @@ -0,0 +1,163 @@ +//To build dist/thrift.js, dist/thrift.min.js and doc/* +//run grunt at the command line in this directory. +//Prerequisites: +// Node Setup - nodejs.org +// Grunt Setup - npm install //reads the ./package.json and installs project dependencies +// Run grunt - npx grunt // uses project-local installed version of grunt (from package.json) + +module.exports = function(grunt) { + 'use strict'; + + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + concat: { + options: { + separator: ';' + }, + dist: { + src: ['src/**/*.js'], + dest: 'dist/<%= pkg.name %>.js' + } + }, + shell: { + InstallThriftJS: { + command: 'mkdir -p test/build/ts/lib; cp ../js/src/thrift.js test/build/ts/thrift.js' + }, + InstallThriftNodeJSDep: { + command: 'cd ../..; npm install' + }, + InstallTestLibs: { + command: 'cd test; ant download_jslibs' + }, + ThriftGen: { + command: [ + 'mkdir -p test/gen-js', + '../../compiler/cpp/thrift -gen js:ts --out test/gen-js ../../test/ThriftTest.thrift', + 'mkdir -p test/gen-nodejs', + '../../compiler/cpp/thrift -gen js:node,ts --out test/gen-nodejs ../../test/ThriftTest.thrift', + ].join(' && ') + }, + ThriftBrowserifyNodeInt64: { + command: [ + './node_modules/browserify/bin/cmd.js ./node_modules/node-int64/Int64.js -s Int64 -o test/build/js/lib/Int64.js', + './node_modules/browserify/bin/cmd.js ../nodejs/lib/thrift/int64_util.js -s Int64Util -o test/build/js/lib/Int64Util.js', + './node_modules/browserify/bin/cmd.js ./node_modules/json-int64/index.js -s JSONInt64 -o test/build/js/lib/JSONInt64.js' + ].join(' && ') + }, + ThriftGenInt64: { + command: '../../compiler/cpp/thrift -gen js:ts -o test ../../test/Int64Test.thrift' + }, + ThriftTestServer: { + options: { + async: true, + execOptions: { + cwd: "./test", + env: {NODE_PATH: "../../nodejs/lib:../../../node_modules"} + } + }, + command: "node server_http.js", + }, + BuildTS: { + options: { + execOptions: { + cwd: "./test", + } + }, + command : "../node_modules/typescript/bin/tsc --listFiles --outDir build/ts" + }, + BrowserifyCompiledTS: { + command: [ + "./node_modules/browserify/bin/cmd.js test/build/ts/test.js -o test/build/ts/lib/test.js --standalone test", + "./node_modules/browserify/bin/cmd.js test/build/ts/test-int64.js -o test/build/ts/lib/test-int64.js --standalone testInt64", + ].join(" && ") + }, + InstallGeneratedCode: { + command: [ + "mkdir -p test/build/ts", + "cp -r test/gen-js test/build/ts" + ].join(" && ") + }, + }, + qunit: { + ThriftJS: { + options: { + urls: [ + 'http://localhost:8089/test.html' + ], + puppeteer: { + headless: true, + args: ['--no-sandbox'], + }, + } + }, + ThriftJS_Int64: { + options: { + urls: [ + 'http://localhost:8089/test-int64.html' + ], + puppeteer: { + headless: true, + args: ['--no-sandbox'], + ignoreHTTPSErrors: true, + }, + } + }, + }, + jshint: { + // The main Thrift library file. not es6 yet :( + lib: { + src: ['../js/src/**/*.js'], + }, + // The test files use es6 + test: { + src: ['Gruntfile.js', 'test/*.js'], + options: { + esversion: 6, + } + }, + gen_js_code: { + src: ['test/gen-js/*.js'], + }, + gen_node_code: { + src: ['test/gen-nodejs/*.js'], + options: { + node: true, + } + }, + }, + }); + + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-qunit'); + grunt.loadNpmTasks('grunt-shell-spawn'); + + grunt.registerTask('wait', 'Wait just one second for the server to start', function () { + var done = this.async(); + setTimeout(function() { + done(true); + }, 1000); + }); + + grunt.registerTask('installAndGenerate', [ + 'shell:InstallThriftJS', + 'shell:InstallThriftNodeJSDep', + 'shell:ThriftGen', + 'shell:ThriftBrowserifyNodeInt64', + 'shell:ThriftGenInt64', + 'shell:InstallTestLibs', + 'shell:BuildTS', + 'shell:InstallGeneratedCode', + 'shell:BrowserifyCompiledTS', + ]); + + grunt.registerTask('test', [ + 'installAndGenerate', + 'jshint', + 'shell:ThriftTestServer', + 'wait', + 'qunit:ThriftJS', + 'qunit:ThriftJS_Int64', + 'shell:ThriftTestServer:kill', + ]); + grunt.registerTask('default', ['test']); +}; diff --git a/lib/ts/Makefile.am b/lib/ts/Makefile.am new file mode 100644 index 00000000000..9ea20a4ab8d --- /dev/null +++ b/lib/ts/Makefile.am @@ -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. +# + +# Make sure this doesn't fail if ant is not configured. +# We call install twice to work around npm issues +# +if HAVE_NPM +SUBDIRS = test + +check-local: all + $(NPM) install || $(NPM) install + $(NPM) list + ./node_modules/.bin/grunt +endif diff --git a/lib/ts/dist/thrift.js b/lib/ts/dist/thrift.js new file mode 100644 index 00000000000..e69de29bb2d diff --git a/lib/ts/dist/thrift.min.js b/lib/ts/dist/thrift.min.js new file mode 100644 index 00000000000..8e14f2d0716 --- /dev/null +++ b/lib/ts/dist/thrift.min.js @@ -0,0 +1 @@ +/*! thrift 07-01-2019 */ diff --git a/lib/ts/package-lock.json b/lib/ts/package-lock.json new file mode 100644 index 00000000000..a7dec9dd364 --- /dev/null +++ b/lib/ts/package-lock.json @@ -0,0 +1,4962 @@ +{ + "name": "thrift", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/node": { + "version": "10.12.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", + "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", + "dev": true + }, + "@types/node-int64": { + "version": "0.4.29", + "resolved": "https://registry.npmjs.org/@types/node-int64/-/node-int64-0.4.29.tgz", + "integrity": "sha512-rHXvenLTj/CcsmNAebaBOhxQ2MqEGl3yXZZcZ21XYR+gzGTTcpOy2N4IxpvTCz48loyQNatHvfn6GhIbbZ1R3Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/phantom": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/phantom/-/phantom-3.2.5.tgz", + "integrity": "sha512-7m36DoKSvZgBGWp0xiJ74eHnuotyrpDyQ6m+lers5iMvW4QX+RvBENn7PCjNix7OVqPWlBM+7AqzYVIQ7NrKrA==", + "dev": true + }, + "@types/qunit": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/@types/qunit/-/qunit-2.5.3.tgz", + "integrity": "sha512-b9xNH1wBOnY+yiCT2DiAC0yi7GCF5g6whiAFA/dpd9RtL/Jn2XR7e4yyeAQwH3TUeF00zikmYqYxS0K8+EKTKQ==", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "acorn": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz", + "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==", + "dev": true + }, + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "dev": true + }, + "acorn-node": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.6.2.tgz", + "integrity": "sha512-rIhNEZuNI8ibQcL7ANm/mGyPukIaZsRNX9psFNQURyJW0nu6k8wjSDld20z6v2mDBWqX13pIEnk9gGZJHIlEXg==", + "dev": true, + "requires": { + "acorn": "^6.0.2", + "acorn-dynamic-import": "^4.0.0", + "acorn-walk": "^6.1.0", + "xtend": "^4.0.1" + } + }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "dev": true + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "babylon": { + "version": "7.0.0-beta.19", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", + "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bluebird": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-pack": { + "version": "6.1.0", + "resolved": "http://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "combine-source-map": "~0.8.0", + "defined": "^1.0.0", + "safe-buffer": "^5.1.1", + "through2": "^2.0.0", + "umd": "^3.0.0" + } + }, + "browser-resolve": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz", + "integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "http://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify": { + "version": "16.2.3", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.3.tgz", + "integrity": "sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "assert": "^1.4.0", + "browser-pack": "^6.0.1", + "browser-resolve": "^1.11.0", + "browserify-zlib": "~0.2.0", + "buffer": "^5.0.2", + "cached-path-relative": "^1.0.0", + "concat-stream": "^1.6.0", + "console-browserify": "^1.1.0", + "constants-browserify": "~1.0.0", + "crypto-browserify": "^3.0.0", + "defined": "^1.0.0", + "deps-sort": "^2.0.0", + "domain-browser": "^1.2.0", + "duplexer2": "~0.1.2", + "events": "^2.0.0", + "glob": "^7.1.0", + "has": "^1.0.0", + "htmlescape": "^1.1.0", + "https-browserify": "^1.0.0", + "inherits": "~2.0.1", + "insert-module-globals": "^7.0.0", + "labeled-stream-splicer": "^2.0.0", + "mkdirp": "^0.5.0", + "module-deps": "^6.0.0", + "os-browserify": "~0.3.0", + "parents": "^1.0.1", + "path-browserify": "~0.0.0", + "process": "~0.11.0", + "punycode": "^1.3.2", + "querystring-es3": "~0.2.0", + "read-only-stream": "^2.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.1.4", + "shasum": "^1.0.0", + "shell-quote": "^1.6.1", + "stream-browserify": "^2.0.0", + "stream-http": "^2.0.0", + "string_decoder": "^1.1.1", + "subarg": "^1.0.0", + "syntax-error": "^1.1.1", + "through2": "^2.0.0", + "timers-browserify": "^1.0.1", + "tty-browserify": "0.0.1", + "url": "~0.11.0", + "util": "~0.10.1", + "vm-browserify": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "^4.1.1", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.2", + "elliptic": "^6.0.0", + "inherits": "^2.0.1", + "parse-asn1": "^5.0.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", + "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-shims": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", + "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "bufferutil": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", + "integrity": "sha512-xowrxvpxojqkagPcWRQVXZl0YXhRhAtBEIq3VoER1NH5Mw1n1o0ojdspp+GS2J//2gCVyrzQDApQ4unGF+QOoA==", + "requires": { + "node-gyp-build": "~3.7.0" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cached-path-relative": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.2.tgz", + "integrity": "sha512-5r2GqsoEb4qMTTN9J+WzXfjov+hjxT+j3u5K+kIVNIwAd99DLCJE9pBIMP1qVeybV6JiijL385Oz0DcYxfbOIg==", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "catharsis": { + "version": "0.8.9", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", + "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=", + "requires": { + "underscore-contrib": "~0.3.0" + } + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "^7.1.1" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "coffeescript": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz", + "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "dev": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "http://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "colorspace": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.1.tgz", + "integrity": "sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw==", + "dev": true, + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + } + }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "dev": true, + "requires": { + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" + } + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "create-ecdh": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", + "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.0.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "deps-sort": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "shasum": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detective": { + "version": "5.1.0", + "resolved": "http://registry.npmjs.org/detective/-/detective-5.1.0.tgz", + "integrity": "sha512-TFHMqfOvxlgrfVzTEkNBSh9SvSNX/HfF4OFI2QFGCyPm02EsyILqnUeb5P6q7JZ3SFNTBL5t2sePRgrN4epUWQ==", + "dev": true, + "requires": { + "acorn-node": "^1.3.0", + "defined": "^1.0.0", + "minimist": "^1.1.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "diagnostics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", + "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "dev": true, + "requires": { + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" + } + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "~1.1.1", + "entities": "~1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + } + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "elliptic": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", + "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + } + }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "dev": true, + "requires": { + "env-variable": "0.0.x" + } + }, + "entities": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + }, + "env-variable": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", + "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es6-promise": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "http://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "events": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz", + "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "extract-zip": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", + "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", + "dev": true, + "requires": { + "concat-stream": "1.6.2", + "debug": "2.6.9", + "mkdirp": "0.5.1", + "yauzl": "2.4.1" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", + "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==", + "dev": true + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "~5.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "fined": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz", + "integrity": "sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + } + }, + "flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0" + }, + "dependencies": { + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-assigned-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", + "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" + }, + "grunt": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.3.tgz", + "integrity": "sha512-/JzmZNPfKorlCrrmxWqQO4JVodO+DVd5XX4DkocL/1WlLlKVLE9+SdEIempOAxDhWPysLle6afvn/hg7Ck2k9g==", + "dev": true, + "requires": { + "coffeescript": "~1.10.0", + "dateformat": "~1.0.12", + "eventemitter2": "~0.4.13", + "exit": "~0.1.1", + "findup-sync": "~0.3.0", + "glob": "~7.0.0", + "grunt-cli": "~1.2.0", + "grunt-known-options": "~1.1.0", + "grunt-legacy-log": "~2.0.0", + "grunt-legacy-util": "~1.1.1", + "iconv-lite": "~0.4.13", + "js-yaml": "~3.5.2", + "minimatch": "~3.0.2", + "mkdirp": "~0.5.1", + "nopt": "~3.0.6", + "path-is-absolute": "~1.0.0", + "rimraf": "~2.6.2" + }, + "dependencies": { + "glob": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "grunt-cli": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", + "dev": true, + "requires": { + "findup-sync": "~0.3.0", + "grunt-known-options": "~1.1.0", + "nopt": "~3.0.6", + "resolve": "~1.1.0" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "http://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "grunt-cli": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.3.2.tgz", + "integrity": "sha512-8OHDiZZkcptxVXtMfDxJvmN7MVJNE8L/yIcPb4HB7TlyFD1kDvjHrb62uhySsU14wJx9ORMnTuhRMQ40lH/orQ==", + "dev": true, + "requires": { + "grunt-known-options": "~1.1.0", + "interpret": "~1.1.0", + "liftoff": "~2.5.0", + "nopt": "~4.0.1", + "v8flags": "~3.1.1" + } + }, + "grunt-contrib-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-concat/-/grunt-contrib-concat-1.0.1.tgz", + "integrity": "sha1-YVCYYwhOhx1+ht5IwBUlntl3Rb0=", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "source-map": "^0.5.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "grunt-contrib-jshint": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-1.1.0.tgz", + "integrity": "sha1-Np2QmyWTxA6L55lAshNAhQx5Oaw=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "hooker": "^0.2.3", + "jshint": "~2.9.4" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "grunt-contrib-qunit": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-3.0.1.tgz", + "integrity": "sha512-s994+ipKwc+oUUIWaGIw1soyID4pExSGMd/cHQN5h0p8KbIjR1Le3ZC3giSDDKXtZFE0i+Obf0uIjNvjftX2Cw==", + "dev": true, + "requires": { + "eventemitter2": "^5.0.1", + "p-each-series": "^1.0.0", + "puppeteer": "1.7.0" + }, + "dependencies": { + "eventemitter2": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", + "integrity": "sha1-YZegldX7a1folC9v1+qtY6CclFI=", + "dev": true + } + } + }, + "grunt-contrib-uglify": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-1.0.2.tgz", + "integrity": "sha1-rmekb5FT7dTLEYE6Vetpxw19svs=", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "lodash": "^4.0.1", + "maxmin": "^1.1.0", + "uglify-js": "~2.6.2", + "uri-path": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "grunt-jsdoc": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.3.0.tgz", + "integrity": "sha512-gC66TCRXeQMj3HIyqVSBJm8zdUz43e5vaG/PLO/627A1edbJnzxhJV7nF0KqLwMM0RDNu1istC6fvfnYqFKi3w==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.5", + "jsdoc": "~3.5.5", + "marked": "^0.5.0" + }, + "dependencies": { + "marked": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.5.2.tgz", + "integrity": "sha512-fdZvBa7/vSQIZCi4uuwo2N3q+7jJURpMVCcbaX0S1Mg65WZ5ilXvC67MviJAsdjqqgD+CEq4RKo5AYGgINkVAA==", + "dev": true + } + } + }, + "grunt-known-options": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz", + "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==", + "dev": true + }, + "grunt-legacy-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz", + "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==", + "dev": true, + "requires": { + "colors": "~1.1.2", + "grunt-legacy-log-utils": "~2.0.0", + "hooker": "~0.2.3", + "lodash": "~4.17.5" + } + }, + "grunt-legacy-log-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz", + "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==", + "dev": true, + "requires": { + "chalk": "~2.4.1", + "lodash": "~4.17.10" + } + }, + "grunt-legacy-util": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz", + "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==", + "dev": true, + "requires": { + "async": "~1.5.2", + "exit": "~0.1.1", + "getobject": "~0.1.0", + "hooker": "~0.2.3", + "lodash": "~4.17.10", + "underscore.string": "~3.3.4", + "which": "~1.3.0" + } + }, + "grunt-shell-spawn": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/grunt-shell-spawn/-/grunt-shell-spawn-0.3.10.tgz", + "integrity": "sha1-gbuNRX7EfTGCqH1jCO+EXd+5SI8=", + "dev": true, + "requires": { + "grunt": ">=0.4.x", + "sync-exec": "~0.6.2" + } + }, + "gzip-size": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz", + "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=", + "dev": true, + "requires": { + "browserify-zlib": "^0.1.4", + "concat-stream": "^1.4.1" + }, + "dependencies": { + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "~0.2.0" + } + }, + "pako": { + "version": "0.2.9", + "resolved": "http://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + } + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hasha": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", + "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", + "dev": true, + "requires": { + "is-stream": "^1.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "dev": true + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dev": true, + "requires": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "https-proxy-agent": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz", + "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", + "dev": true, + "requires": { + "agent-base": "^4.1.0", + "debug": "^3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true, + "requires": { + "source-map": "~0.5.3" + } + }, + "insert-module-globals": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.0.tgz", + "integrity": "sha512-VE6NlW+WGn2/AeOMd496AHFYmE7eLKkUY6Ty31k4og5vmA3Fjuwe9v6ifH6Xx/Hz27QvdoMoviw1/pqWRB09Sw==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "acorn-node": "^1.5.2", + "combine-source-map": "^0.8.0", + "concat-stream": "^1.6.1", + "is-buffer": "^1.1.0", + "path-is-absolute": "^1.0.1", + "process": "~0.11.0", + "through2": "^2.0.0", + "undeclared-identifiers": "^1.1.2", + "xtend": "^4.0.0" + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-yaml": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz", + "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=", + "dev": true, + "requires": { + "argparse": "^1.0.2", + "esprima": "^2.6.0" + } + }, + "js2xmlparser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", + "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=", + "requires": { + "xmlcreate": "^1.0.1" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsdoc": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", + "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==", + "requires": { + "babylon": "7.0.0-beta.19", + "bluebird": "~3.5.0", + "catharsis": "~0.8.9", + "escape-string-regexp": "~1.0.5", + "js2xmlparser": "~3.0.0", + "klaw": "~2.0.0", + "marked": "~0.3.6", + "mkdirp": "~0.5.1", + "requizzle": "~0.2.1", + "strip-json-comments": "~2.0.1", + "taffydb": "2.6.2", + "underscore": "~1.8.3" + } + }, + "jshint": { + "version": "2.9.7", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.7.tgz", + "integrity": "sha512-Q8XN38hGsVQhdlM+4gd1Xl7OB1VieSuCJf+fEJjpo59JH99bVJhXRXAh26qQ15wfdd1VPMuDWNeSWoNl53T4YA==", + "dev": true, + "requires": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.10", + "minimatch": "~3.0.2", + "shelljs": "0.3.x", + "strip-json-comments": "1.0.x" + }, + "dependencies": { + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + } + } + }, + "jslint": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/jslint/-/jslint-0.12.0.tgz", + "integrity": "sha512-RoCsyICcKA+6TFsbys9DpKTfPVaC71Mm5QSjvrWA0lDVN+LIvx6apa42FFisMqmCTvJ8DxkcoQGJ0j7m3kTVow==", + "dev": true, + "requires": { + "exit": "~0.1.2", + "glob": "~7.1.2", + "nopt": "~3.0.1", + "readable-stream": "~2.1.5" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.1.5", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.1.5.tgz", + "integrity": "sha1-ZvqLcg4UOLNkaB8q0aY8YYRIydA=", + "dev": true, + "requires": { + "buffer-shims": "^1.0.0", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "json-int64": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-0.0.3.tgz", + "integrity": "sha512-6nAloOVry+klkifPKPqFLX/FI4L95oBfu5T5vKKt4L8gik8cy80wOtzC+kM1Vh2r60QdDqDr7u/XVk6VlfueEg==", + "requires": { + "node-int64": "0.4.0" + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "klaw": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz", + "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=", + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "kuler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", + "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "dev": true, + "requires": { + "colornames": "^1.1.1" + } + }, + "labeled-stream-splicer": { + "version": "2.0.1", + "resolved": "http://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", + "integrity": "sha512-MC94mHZRvJ3LfykJlTUipBqenZz1pacOZEMhhQ8dMGcDHs0SBE5GbsavUXV7YtP3icBW17W0Zy1I0lfASmo9Pg==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "isarray": "^2.0.4", + "stream-splicer": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", + "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==", + "dev": true + } + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" + }, + "dependencies": { + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + } + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "logform": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz", + "integrity": "sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==", + "dev": true, + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^2.3.3", + "ms": "^2.1.1", + "triple-beam": "^1.2.0" + }, + "dependencies": { + "colors": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", + "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "marked": { + "version": "0.3.19", + "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz", + "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==" + }, + "maxmin": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz", + "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "figures": "^1.0.1", + "gzip-size": "^1.0.0", + "pretty-bytes": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "dev": true + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "dev": true + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "dev": true, + "requires": { + "mime-db": "~1.37.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "module-deps": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.0.tgz", + "integrity": "sha512-hKPmO06so6bL/ZvqVNVqdTVO8UAYsi3tQWlCa+z9KuWhoN4KDQtb5hcqQQv58qYiDE21wIvnttZEPiDgEbpwbA==", + "dev": true, + "requires": { + "JSONStream": "^1.0.3", + "browser-resolve": "^1.7.0", + "cached-path-relative": "^1.0.0", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.0.2", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + } + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==" + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "one-time": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=", + "dev": true + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "dev": true, + "requires": { + "p-reduce": "^1.0.0" + } + }, + "p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", + "dev": true + }, + "pako": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz", + "integrity": "sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ==", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "~0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "dev": true, + "requires": { + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pbkdf2": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", + "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "phantom": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/phantom/-/phantom-6.0.3.tgz", + "integrity": "sha512-8bb8urWoUiZ0E+JC4goaYBDPxljTnnxGwogz5cvash2SQovf//QAPoshXQz06kY/tpI+5caBVng0K0oZkVMNIQ==", + "dev": true, + "requires": { + "phantomjs-prebuilt": "^2.1.16", + "split": "^1.0.1", + "winston": "^3.0.0" + } + }, + "phantomjs-prebuilt": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", + "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3", + "extract-zip": "^1.6.5", + "fs-extra": "^1.0.0", + "hasha": "^2.2.0", + "kew": "^0.7.0", + "progress": "^1.1.8", + "request": "^2.81.0", + "request-progress": "^2.0.1", + "which": "^1.2.10" + }, + "dependencies": { + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + } + } + }, + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "pretty-bytes": { + "version": "1.0.4", + "resolved": "http://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.1.0" + } + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "proxy-from-env": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", + "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", + "dev": true + }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "puppeteer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.7.0.tgz", + "integrity": "sha512-f+1DxKHPqce6CXUBz2eVO2WcATeVeQSOPG9GYaGObEZDCiCEUwG+gogjMsrvn7he2wHTqNVb5p6RUrwmr8XFBA==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "extract-zip": "^1.6.6", + "https-proxy-agent": "^2.2.1", + "mime": "^2.0.3", + "progress": "^2.0.0", + "proxy-from-env": "^1.0.0", + "rimraf": "^2.6.1", + "ws": "^5.1.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", + "dev": true, + "requires": { + "throttleit": "^1.0.0" + } + }, + "requizzle": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", + "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=", + "requires": { + "underscore": "~1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "http://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } + } + }, + "resolve": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", + "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "sha.js": { + "version": "2.4.11", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shasum": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true, + "requires": { + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "~0.0.0", + "array-map": "~0.0.0", + "array-reduce": "~0.0.0", + "jsonify": "~0.0.0" + } + }, + "shelljs": { + "version": "0.3.0", + "resolved": "http://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", + "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", + "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", + "dev": true + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + }, + "sshpk": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz", + "integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "http://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-splicer": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "string_decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", + "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "^1.1.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "sync-exec": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.6.2.tgz", + "integrity": "sha1-cX0izFPwzh3vVZQ2LzqJouu5EQU=", + "dev": true + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "requires": { + "acorn-node": "^1.2.0" + } + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=" + }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "dev": true + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "http://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "requires": { + "process": "~0.11.0" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==", + "dev": true + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", + "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==", + "dev": true + }, + "uglify-js": { + "version": "2.6.4", + "resolved": "http://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", + "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", + "dev": true, + "requires": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "http://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "undeclared-identifiers": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz", + "integrity": "sha512-13EaeocO4edF/3JKime9rD7oB6QI8llAGhgn5fKOPyfkJbRb6NFv9pYV6dFEmpa4uRjKeBqLZP8GpuzqHlKDMQ==", + "dev": true, + "requires": { + "acorn-node": "^1.3.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "http://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "underscore-contrib": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz", + "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=", + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "http://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } + } + }, + "underscore.string": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", + "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", + "dev": true, + "requires": { + "sprintf-js": "^1.0.3", + "util-deprecate": "^1.0.2" + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "uri-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", + "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=", + "dev": true + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "v8flags": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", + "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", + "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "winston": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.1.0.tgz", + "integrity": "sha512-FsQfEE+8YIEeuZEYhHDk5cILo1HOcWkGwvoidLrDgPog0r4bser1lEIOco2dN9zpDJ1M88hfDgZvxe5z4xNcwg==", + "dev": true, + "requires": { + "async": "^2.6.0", + "diagnostics": "^1.1.1", + "is-stream": "^1.1.0", + "logform": "^1.9.1", + "one-time": "0.0.4", + "readable-stream": "^2.3.6", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.2.0" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "dev": true, + "requires": { + "lodash": "^4.17.10" + } + } + } + }, + "winston-transport": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", + "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", + "dev": true, + "requires": { + "readable-stream": "^2.3.6", + "triple-beam": "^1.2.0" + } + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xmlcreate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", + "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + } + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "~1.0.1" + } + } + } +} diff --git a/lib/ts/package.json b/lib/ts/package.json new file mode 100644 index 00000000000..47eec6277a8 --- /dev/null +++ b/lib/ts/package.json @@ -0,0 +1,30 @@ +{ + "name": "thrift", + "version": "1.0.0", + "devDependencies": { + "@types/node-int64": "^0.4.29", + "@types/phantom": "^3.2.5", + "@types/qunit": "^2.5.3", + "browserify": "^16.2.3", + "bufferutil": "^4.0.1", + "grunt": "^1.0.2", + "grunt-cli": "^1.2.0", + "grunt-contrib-concat": "^1.0.1", + "grunt-contrib-jshint": "^1.0.0", + "grunt-contrib-qunit": "^3.0.1", + "grunt-contrib-uglify": "^1.0.1", + "grunt-jsdoc": "^2.2.1", + "grunt-shell-spawn": "^0.3.10", + "jslint": "^0.12.0", + "node-int64": "^0.4.0", + "phantom": "^6.0.3", + "typescript": "^3.2.2" + }, + "dependencies": { + "bufferutil": "^4.0.1", + "jsdoc": "^3.5.5", + "json-int64": "^0.0.3", + "nopt": "^4.0.1" + }, + "types": "./thrift.d.ts" +} diff --git a/lib/ts/test/build.xml b/lib/ts/test/build.xml new file mode 100755 index 00000000000..5c3a4a87b92 --- /dev/null +++ b/lib/ts/test/build.xml @@ -0,0 +1,250 @@ + + + + Java Script Test based on Thrift Java Library + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + You need libthrift*.jar and libthrift*test.jar located at + ${thrift.java.dir}/build/libs + Did you compile Thrift Java library and its test suite by "ant compile-test"? + + + + + + + + + + Thrift compiler is missing ! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + check if Xvfb is available: + + + + + + + check if phantomjs is available: + + + + + + + + + + + + + + + + Running Unit Tests with headless browser! + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + check if gjslint is available: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/ts/test/phantom-client.ts b/lib/ts/test/phantom-client.ts new file mode 100644 index 00000000000..55189372536 --- /dev/null +++ b/lib/ts/test/phantom-client.ts @@ -0,0 +1,352 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* jshint -W100 */ + +import { ThriftTest } from "./gen-js/ThriftTest_types"; +import "./gen-js/ThriftTest"; +var Int64 = require("node-int64"); +var phantom = require("phantom"); + +const int64_2_pow_60: typeof Int64 = new Int64('1000000000000000'); +const int64_minus_2_pow_60: typeof Int64 = new Int64('f000000000000000'); + + (function() { + 'use strict'; + + // Rudimentary test helper functions + // TODO: Return error code based on kind of errors rather than throw + var ok = function(t, msg) { + if (!t) { + console.log('*** FAILED ***'); + throw new Error(msg); + } + }; + var equal = function(a, b) { + if (a !== b) { + console.log('*** FAILED ***'); + throw new Error(); + } + }; + var test = function(name, f) { + console.log('TEST : ' + name); + f(); + console.log('OK\n'); + }; + + var parseArgs = function(args) { + var skips = [ + '--transport=http', + '--protocol=json' + ]; + var opts = { + port: '9090' + // protocol: 'json', + }; + var keys = {}; + for (var key in opts) { + keys['--' + key + '='] = key; + } + for (var i in args) { + var arg = args[i]; + if (skips.indexOf(arg) != -1) { + continue; + } + var hit = false; + for (var k in keys) { + if (arg.slice(0, k.length) === k) { + opts[keys[k]] = arg.slice(k.length); + hit = true; + break; + } + } + if (!hit) { + throw new Error('Unknown argument: ' + arg); + } + } + var portAsInt: number = parseInt(opts.port, 10); + if (!opts.port || portAsInt < 1 || portAsInt > 65535) { + throw new Error('Invalid port number'); + } + return opts; + }; + + var execute = function() { + console.log('### Apache Thrift Javascript standalone test client'); + console.log('------------------------------------------------------------'); + + phantom.page.injectJs('thrift.js'); + phantom.page.injectJs('gen-js/ThriftTest_types.js'); + phantom.page.injectJs('gen-js/ThriftTest.js'); + + var system = require('system'); + var opts = parseArgs(system.args.slice(1)); + var port = opts.port; + var transport = new Thrift.Transport('http://localhost:' + port + '/service'); + var protocol = new Thrift.Protocol(transport); + var client = new ThriftTest.ThriftTestClient(protocol); + + + // TODO: Remove duplicate code with test.js. + // all Languages in UTF-8 + var stringTest = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"; + + function checkRecursively(map1, map2) { + if (typeof map1 !== 'function' && typeof map2 !== 'function') { + if (!map1 || typeof map1 !== 'object') { + equal(map1, map2); + } else { + for (var key in map1) { + checkRecursively(map1[key], map2[key]); + } + } + } + } + + test('Void', function() { + equal(client.testVoid(), undefined); + }); + test('Binary (String)', function() { + var binary: string = ''; + for (var v = 255; v >= 0; --v) { + binary += String.fromCharCode(v); + } + equal(client.testBinary(binary), binary); + }); + test('Binary (Uint8Array)', function() { + var binary: string = ''; + for (var v = 255; v >= 0; --v) { + binary += String.fromCharCode(v); + } + var arr = new Uint8Array(binary.length); + for (var i = 0; i < binary.length; ++i) { + arr[i] = binary[i].charCodeAt(0); + } + const hexEncodedString = Array.from(arr, function(byte) { + return String.fromCharCode(byte); + }).join('') + equal(client.testBinary(hexEncodedString), binary); + }); + test('String', function() { + equal(client.testString(''), ''); + equal(client.testString(stringTest), stringTest); + + var specialCharacters = 'quote: \" backslash:' + + ' forwardslash-escaped: \/ ' + + ' backspace: \b formfeed: \f newline: \n return: \r tab: ' + + ' now-all-of-them-together: "\\\/\b\n\r\t' + + ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><'; + equal(client.testString(specialCharacters), specialCharacters); + }); + test('Double', function() { + equal(client.testDouble(0), 0); + equal(client.testDouble(-1), -1); + equal(client.testDouble(3.14), 3.14); + equal(client.testDouble(Math.pow(2, 60)), Math.pow(2, 60)); + }); + test('Bool', function() { + equal(client.testBool(true), true); + equal(client.testBool(false), false); + }); + test('I8', function() { + equal(client.testByte(0), 0); + equal(client.testByte(0x01), 0x01); + }); + test('I32', function() { + equal(client.testI32(0), 0); + equal(client.testI32(Math.pow(2, 30)), Math.pow(2, 30)); + equal(client.testI32(-Math.pow(2, 30)), -Math.pow(2, 30)); + }); + test('I64', function() { + equal(client.testI64(new Int64(0)), 0); + equal(client.testI64(int64_2_pow_60), Math.pow(2, 52)); + equal(client.testI64(int64_minus_2_pow_60), -Math.pow(2, 52)); + }); + + test('Struct', function() { + var structTestInput: ThriftTest.Xtruct = new ThriftTest.Xtruct(); + structTestInput.string_thing = 'worked'; + structTestInput.byte_thing = 0x01; + structTestInput.i32_thing = Math.pow(2, 30); + structTestInput.i64_thing = int64_2_pow_60; + + var structTestOutput: ThriftTest.Xtruct = client.testStruct(structTestInput); + + equal(structTestOutput.string_thing, structTestInput.string_thing); + equal(structTestOutput.byte_thing, structTestInput.byte_thing); + equal(structTestOutput.i32_thing, structTestInput.i32_thing); + equal(structTestOutput.i64_thing, structTestInput.i64_thing); + + equal(JSON.stringify(structTestOutput), JSON.stringify(structTestInput)); + }); + + test('Nest', function() { + var xtrTestInput: ThriftTest.Xtruct = new ThriftTest.Xtruct(); + xtrTestInput.string_thing = 'worked'; + xtrTestInput.byte_thing = 0x01; + xtrTestInput.i32_thing = Math.pow(2, 30); + xtrTestInput.i64_thing = int64_2_pow_60; + + var nestTestInput: ThriftTest.Xtruct2 = new ThriftTest.Xtruct2(); + nestTestInput.byte_thing = 0x02; + nestTestInput.struct_thing = xtrTestInput; + nestTestInput.i32_thing = Math.pow(2, 15); + + var nestTestOutput = client.testNest(nestTestInput); + + equal(nestTestOutput.byte_thing, nestTestInput.byte_thing); + equal(nestTestOutput.struct_thing.string_thing, nestTestInput.struct_thing.string_thing); + equal(nestTestOutput.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing); + equal(nestTestOutput.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing); + equal(nestTestOutput.struct_thing.i64_thing, nestTestInput.struct_thing.i64_thing); + equal(nestTestOutput.i32_thing, nestTestInput.i32_thing); + + equal(JSON.stringify(nestTestOutput), JSON.stringify(nestTestInput)); + }); + + test('Map', function() { + var mapTestInput: {[k: number]: number;} = {7: 77, 8: 88, 9: 99}; + + var mapTestOutput: {[k: number]: number;} = client.testMap(mapTestInput); + + for (var key in mapTestOutput) { + equal(mapTestOutput[key], mapTestInput[key]); + } + }); + + test('StringMap', function() { + var mapTestInput: {[k: string]: string;} = { + 'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key', + 'longValue': stringTest, stringTest: 'long key' + }; + + var mapTestOutput: {[k: string]: string;} = client.testStringMap(mapTestInput); + + for (var key in mapTestOutput) { + equal(mapTestOutput[key], mapTestInput[key]); + } + }); + + test('Set', function() { + var setTestInput: number[] = [1, 2, 3]; + ok(client.testSet(setTestInput), setTestInput); + }); + + test('List', function() { + var listTestInput: number[] = [1, 2, 3]; + ok(client.testList(listTestInput), listTestInput); + }); + + test('Enum', function() { + equal(client.testEnum(ThriftTest.Numberz.ONE), ThriftTest.Numberz.ONE); + }); + + test('TypeDef', function() { + equal(client.testTypedef(new Int64(69)), 69); + }); + + test('MapMap', function() { + var mapMapTestExpectedResult: {[K: number]: {[k: number]: number}} = { + '4': {'1': 1, '2': 2, '3': 3, '4': 4}, + '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1} + }; + + var mapMapTestOutput = client.testMapMap(1); + + + for (var key in mapMapTestOutput) { + for (var key2 in mapMapTestOutput[key]) { + equal(mapMapTestOutput[key][key2], mapMapTestExpectedResult[key][key2]); + } + } + + checkRecursively(mapMapTestOutput, mapMapTestExpectedResult); + }); + + test('Xception', function() { + try { + client.testException('Xception'); + ok(false, "expected an exception but there was no exception"); + } catch (e) { + equal(e.errorCode, 1001); + equal(e.message, 'Xception'); + } + }); + + test('no Exception', function() { + try { + client.testException('no Exception'); + } catch (e) { + ok(false, "expected no exception but here was an exception"); + } + }); + + test('TException', function() { + try { + client.testException('TException'); + ok(false, "expected an exception but there was no exception"); + } catch (e) { + ok(ok, "succesfully got exception"); + } + }); + + const crazy: ThriftTest.Insanity = { + 'userMap': { '5': new Int64(5), '8': new Int64(8) }, + 'xtructs': [{ + 'string_thing': 'Goodbye4', + 'byte_thing': 4, + 'i32_thing': 4, + 'i64_thing': new Int64(4) + }, + { + 'string_thing': 'Hello2', + 'byte_thing': 2, + 'i32_thing': 2, + 'i64_thing': new Int64(2) + }] + }; + test('Insanity', function() { + const insanity: {[k: number]: (ThriftTest.Insanity | {[k:number]: ThriftTest.Insanity})} = { + '1': { + '2': crazy, + '3': crazy + }, + '2': { '6': new ThriftTest.Insanity() } + }; + var res = client.testInsanity(new ThriftTest.Insanity(crazy)); + ok(res, JSON.stringify(res)); + ok(insanity, JSON.stringify(insanity)); + + checkRecursively(res, insanity); + }); + + console.log('------------------------------------------------------------'); + console.log('### All tests succeeded.'); + return 0; + }; + + try { + var ret = execute(); + phantom.exit(ret); + } catch (err) { + // Catch all and exit to avoid hang. + console.error(err); + phantom.exit(1); + } + })(); + \ No newline at end of file diff --git a/lib/ts/test/server_http.js b/lib/ts/test/server_http.js new file mode 100644 index 00000000000..8380c3a7732 --- /dev/null +++ b/lib/ts/test/server_http.js @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// This HTTP server is designed to serve the test.html browser +// based JavaScript test page (which must be in the current directory). +// This server also supplies the Thrift based test service, which depends +// on the standard ThriftTest.thrift IDL service (which must be compiled +// for Node and browser based JavaScript in ./gen-nodejs and ./gen-js +// respectively). +// +// Using the command flag --es6, this server can be run using nodejs code built +// for the es6 environment or for pre-es6 environment. +// + +const thrift = require('../../nodejs/lib/thrift'); +const es6Mode = process.argv.includes('--es6'); +const genFolder = es6Mode ? 'gen-nodejs-es6' : 'gen-nodejs'; +const ThriftTestSvc = require(`./${genFolder}/ThriftTest.js`); +const ThriftTestHandler = require('./test_handler').ThriftTestHandler; + +const ThriftTestSvcOpt = { + transport: thrift.TBufferedTransport, + protocol: thrift.TJSONProtocol, + processor: ThriftTestSvc, + handler: ThriftTestHandler +}; + +const ThriftWebServerOptions = { + files: __dirname, + services: { + '/service': ThriftTestSvcOpt + } +}; + +const server = thrift.createWebServer(ThriftWebServerOptions); +const port = es6Mode ? 8088 : 8089; +server.listen(port); +console.log(`Serving files from: ${__dirname}`); +console.log(`Http/Thrift Server (ES6 mode ${es6Mode}) running on port: ${port}`); diff --git a/lib/ts/test/test-int64.html b/lib/ts/test/test-int64.html new file mode 100644 index 00000000000..75ac27839ef --- /dev/null +++ b/lib/ts/test/test-int64.html @@ -0,0 +1,46 @@ ++ + + + + + Int64 Constants in JS: Unit Test + + + + + + + + + +

Int64 Constants in JS: Unit Test

+

+
+

+
+ + + diff --git a/lib/ts/test/test-int64.ts b/lib/ts/test/test-int64.ts new file mode 100644 index 00000000000..3ea7919e2c8 --- /dev/null +++ b/lib/ts/test/test-int64.ts @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + /* jshint -W100 */ + +var Int64 = require("node-int64"); +import { Int64Test } from "./gen-js/Int64Test_types"; + + +// Work around for old API used by QUnitAdapter of jsTestDriver +if (typeof QUnit.log == 'function') { + // When using real QUnit (fron PhantomJS) log failures to console + QUnit.log(function(details) { + if (!details.result) { + console.log('======== FAIL ========'); + console.log('TestName: ' + details.name); + if (details.message) console.log(details.message); + console.log('Expected: ' + details.expected); + console.log('Actual : ' + details.actual); + console.log('======================'); + } + }); +} + +QUnit.module('Int64'); + + QUnit.test('Int64', function(assert) { + console.log('Int64 test -- starts'); + const EXPECTED_SMALL_INT64_AS_NUMBER: number = 42; + const EXPECTED_SMALL_INT64: typeof Int64 = new Int64(42); + const EXPECTED_MAX_JS_SAFE_INT64: typeof Int64 = new Int64(Number.MAX_SAFE_INTEGER); + const EXPECTED_MIN_JS_SAFE_INT64: typeof Int64 = new Int64(Number.MIN_SAFE_INTEGER); + const EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64: typeof Int64 = new Int64("0020000000000000"); // hex-encoded + const EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64: typeof Int64 = new Int64("ffe0000000000000"); // hex-encoded 2's complement + const EXPECTED_MAX_SIGNED_INT64: typeof Int64 = new Int64("7fffffffffffffff"); // hex-encoded + const EXPECTED_MIN_SIGNED_INT64: typeof Int64 = new Int64("8000000000000000"); // hex-encoded 2's complement + const EXPECTED_INT64_LIST = [ + EXPECTED_SMALL_INT64, + EXPECTED_MAX_JS_SAFE_INT64, + EXPECTED_MIN_JS_SAFE_INT64, + EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64, + EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64, + EXPECTED_MAX_SIGNED_INT64, + EXPECTED_MIN_SIGNED_INT64 + ]; + assert.ok(EXPECTED_SMALL_INT64.equals(Int64Test.SMALL_INT64)); + assert.ok(EXPECTED_MAX_JS_SAFE_INT64.equals(Int64Test.MAX_JS_SAFE_INT64)); + assert.ok(EXPECTED_MIN_JS_SAFE_INT64.equals(Int64Test.MIN_JS_SAFE_INT64)); + assert.ok( + EXPECTED_MAX_JS_SAFE_PLUS_ONE_INT64.equals( + Int64Test.MAX_JS_SAFE_PLUS_ONE_INT64 + ) + ); + assert.ok( + EXPECTED_MIN_JS_SAFE_MINUS_ONE_INT64.equals( + Int64Test.MIN_JS_SAFE_MINUS_ONE_INT64 + ) + ); + assert.ok(EXPECTED_MAX_SIGNED_INT64.equals(Int64Test.MAX_SIGNED_INT64)); + assert.ok(EXPECTED_MIN_SIGNED_INT64.equals(Int64Test.MIN_SIGNED_INT64)); + assert.equal( + EXPECTED_SMALL_INT64_AS_NUMBER, + Int64Test.SMALL_INT64.toNumber() + ); + assert.equal( + Number.MAX_SAFE_INTEGER, + Int64Test.MAX_JS_SAFE_INT64.toNumber() + ); + assert.equal( + Number.MIN_SAFE_INTEGER, + Int64Test.MIN_JS_SAFE_INT64.toNumber() + ); + + for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { + assert.ok(EXPECTED_INT64_LIST[i].equals(Int64Test.INT64_LIST[i])); + } + console.log('Int64 test -- ends'); + }); + diff --git a/lib/ts/test/test.html b/lib/ts/test/test.html new file mode 100755 index 00000000000..ec7d7ebe403 --- /dev/null +++ b/lib/ts/test/test.html @@ -0,0 +1,53 @@ + + + + + + Thrift Javascript Bindings: Unit Test + + + + + + + + + + + + + + + + +

Thrift Javascript Bindings: Unit Test (ThriftTest.thrift)

+

+
+

+
+ + + diff --git a/lib/ts/test/test.ts b/lib/ts/test/test.ts new file mode 100644 index 00000000000..31fdcbff8bc --- /dev/null +++ b/lib/ts/test/test.ts @@ -0,0 +1,342 @@ +import { ThriftTest } from "./gen-js/ThriftTest_types"; +import "./gen-js/ThriftTest"; + +var Int64 = require("node-int64"); +var JSONInt64 = require("json-int64"); +var QUnit = require("./qunit"); + +const transport: Thrift.Transport = new Thrift.Transport("/service"); +const protocol: Thrift.Protocol = new Thrift.Protocol(transport); +const client: ThriftTest.ThriftTestClient = new ThriftTest.ThriftTestClient(protocol); + +const int64_2_pow_60: typeof Int64 = new Int64('1000000000000000'); +const int64_minus_2_pow_60: typeof Int64 = new Int64('f000000000000000'); + +// Work around for old API used by QUnitAdapter of jsTestDriver +if (typeof QUnit.log == 'function') { + // When using real QUnit (fron PhantomJS) log failures to console + QUnit.log(function(details) { + if (!details.result) { + console.log('======== FAIL ========'); + console.log('TestName: ' + details.name); + if (details.message) console.log(details.message); + console.log('Expected: ' + JSONInt64.stringify(details.expected)); + console.log('Actual : ' + JSONInt64.stringify(details.actual)); + console.log('======================'); + } + }); +} + +// all Languages in UTF-8 +const stringTest: string = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語"; + + +function checkRecursively(assert, map1: Object, map2: Object): void { + if (typeof map1 !== 'function' && typeof map2 !== 'function') { + if (!map1 || typeof map1 !== 'object') { + assert.equal(map1, map2); + } else { + for (let key in map1) { + checkRecursively(assert, map1[key], map2[key]); + } + } + } +} + + +QUnit.module('Base Types'); + + QUnit.test('Void', function(assert) { + assert.equal(client.testVoid(), undefined); + }); + QUnit.test('Binary (String)', function(assert) { + let binary: string = ''; + for (let v = 255; v >= 0; --v) { + binary += String.fromCharCode(v); + } + assert.equal(client.testBinary(binary), binary); + }); + QUnit.test('Binary (Uint8Array)', function(assert) { + let binary: string = ''; + for (let v = 255; v >= 0; --v) { + binary += String.fromCharCode(v); + } + const arr: Uint8Array = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; ++i) { + arr[i] = binary[i].charCodeAt(0); + } + const hexEncodedString = Array.from(arr, function(byte) { + return String.fromCharCode(byte); + }).join('') + assert.equal(client.testBinary(hexEncodedString), binary); + }); + QUnit.test('String', function(assert) { + assert.equal(client.testString(''), ''); + assert.equal(client.testString(stringTest), stringTest); + + const specialCharacters: string = 'quote: \" backslash:' + + ' forwardslash-escaped: \/ ' + + ' backspace: \b formfeed: \f newline: \n return: \r tab: ' + + ' now-all-of-them-together: "\\\/\b\n\r\t' + + ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><'; + assert.equal(client.testString(specialCharacters), specialCharacters); + }); + QUnit.test('Double', function(assert) { + assert.equal(client.testDouble(0), 0); + assert.equal(client.testDouble(-1), -1); + assert.equal(client.testDouble(3.14), 3.14); + assert.equal(client.testDouble(Math.pow(2, 60)), Math.pow(2, 60)); + }); + QUnit.test('Byte', function(assert) { + assert.equal(client.testByte(0), 0); + assert.equal(client.testByte(0x01), 0x01); + }); + QUnit.test('I32', function(assert) { + assert.equal(client.testI32(0), 0); + assert.equal(client.testI32(Math.pow(2, 30)), Math.pow(2, 30)); + assert.equal(client.testI32(-Math.pow(2, 30)), -Math.pow(2, 30)); + }); + QUnit.test('I64', function(assert) { + assert.equal(client.testI64(new Int64(0)), 0); + + let int64_2_pow_60_result: typeof Int64 = client.testI64(int64_2_pow_60); + assert.ok(int64_2_pow_60.equals(int64_2_pow_60_result)); + + let int64_minus_2_pow_60_result: typeof Int64 = client.testI64(int64_minus_2_pow_60); + assert.ok(int64_minus_2_pow_60.equals(int64_minus_2_pow_60_result)); + }); + + +QUnit.module('Structured Types'); + + QUnit.test('Struct', function(assert) { + const structTestInput: ThriftTest.Xtruct = new ThriftTest.Xtruct(); + structTestInput.string_thing = 'worked'; + structTestInput.byte_thing = 0x01; + structTestInput.i32_thing = Math.pow(2, 30); + structTestInput.i64_thing = int64_2_pow_60; + + const structTestOutput: ThriftTest.Xtruct = client.testStruct(structTestInput); + + assert.equal(structTestOutput.string_thing, structTestInput.string_thing); + assert.equal(structTestOutput.byte_thing, structTestInput.byte_thing); + assert.equal(structTestOutput.i32_thing, structTestInput.i32_thing); + assert.ok(structTestOutput.i64_thing.equals(structTestInput.i64_thing)); + assert.ok(structTestInput.i64_thing.equals(structTestOutput.i64_thing)); + + assert.equal(JSONInt64.stringify(structTestOutput), JSONInt64.stringify(structTestInput)); + }); + + QUnit.test('Nest', function(assert) { + const xtrTestInput: ThriftTest.Xtruct = new ThriftTest.Xtruct(); + xtrTestInput.string_thing = 'worked'; + xtrTestInput.byte_thing = 0x01; + xtrTestInput.i32_thing = Math.pow(2, 30); + xtrTestInput.i64_thing = int64_2_pow_60; + + const nestTestInput: ThriftTest.Xtruct2 = new ThriftTest.Xtruct2(); + nestTestInput.byte_thing = 0x02; + nestTestInput.struct_thing = xtrTestInput; + nestTestInput.i32_thing = Math.pow(2, 15); + + const nestTestOutput: ThriftTest.Xtruct2 = client.testNest(nestTestInput); + + assert.equal(nestTestOutput.byte_thing, nestTestInput.byte_thing); + assert.equal(nestTestOutput.struct_thing.string_thing, nestTestInput.struct_thing.string_thing); + assert.equal(nestTestOutput.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing); + assert.equal(nestTestOutput.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing); + assert.ok(nestTestOutput.struct_thing.i64_thing.equals(nestTestInput.struct_thing.i64_thing)); + assert.equal(nestTestOutput.i32_thing, nestTestInput.i32_thing); + + assert.equal(JSONInt64.stringify(nestTestOutput), JSONInt64.stringify(nestTestInput)); + }); + + QUnit.test('Map', function(assert) { + const mapTestInput: {[k: number]: number;} = {7: 77, 8: 88, 9: 99}; + + const mapTestOutput: {[k: number]: number;} = client.testMap(mapTestInput); + + for (let key in mapTestOutput) { + assert.equal(mapTestOutput[key], mapTestInput[key]); + } + }); + + QUnit.test('StringMap', function(assert) { + const mapTestInput: {[k: string]: string;} = { + 'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key', + 'longValue': stringTest, stringTest: 'long key' + }; + + const mapTestOutput: {[k: string]: string;} = client.testStringMap(mapTestInput); + + for (let key in mapTestOutput) { + assert.equal(mapTestOutput[key], mapTestInput[key]); + } + }); + + QUnit.test('Set', function(assert) { + const setTestInput: number[] = [1, 2, 3]; + assert.ok(client.testSet(setTestInput), setTestInput); + }); + + QUnit.test('List', function(assert) { + const listTestInput: number[] = [1, 2, 3]; + assert.ok(client.testList(listTestInput), listTestInput); + }); + + QUnit.test('Enum', function(assert) { + assert.equal(client.testEnum(ThriftTest.Numberz.ONE), ThriftTest.Numberz.ONE); + }); + + QUnit.test('TypeDef', function(assert) { + assert.equal(client.testTypedef(new Int64(69)), 69); + }); + + +QUnit.module('deeper!'); + + QUnit.test('MapMap', function(assert) { + const mapMapTestExpectedResult: {[K: number]: {[k: number]: number}} = { + '4': {'1': 1, '2': 2, '3': 3, '4': 4}, + '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1} + }; + + const mapMapTestOutput = client.testMapMap(1); + + + for (let key in mapMapTestOutput) { + for (let key2 in mapMapTestOutput[key]) { + assert.equal(mapMapTestOutput[key][key2], mapMapTestExpectedResult[key][key2]); + } + } + + checkRecursively(assert, mapMapTestOutput, mapMapTestExpectedResult); + }); + + +QUnit.module('Exception'); + + QUnit.test('Xception', function(assert) { + assert.expect(2); + const done = assert.async(); + try { + client.testException('Xception'); + assert.ok(false); + }catch (e) { + assert.equal(e.errorCode, 1001); + assert.equal(e.message, 'Xception'); + done(); + } + }); + + QUnit.test('no Exception', function(assert) { + assert.expect(1); + try { + client.testException('no Exception'); + assert.ok(true); + }catch (e) { + assert.ok(false); + } + }); + + QUnit.test('TException', function(assert) { + //ThriftTest does not list TException as a legal exception so it will + // generate an exception on the server that does not propagate back to + // the client. This test has been modified to equate to "no exception" + assert.expect(1); + try { + client.testException('TException'); + } catch (e) { + //assert.ok(false); + } + assert.ok(true); + }); + + +QUnit.module('Insanity'); + + const crazy: ThriftTest.Insanity = { + 'userMap': { '5': new Int64(5), '8': new Int64(8) }, + 'xtructs': [{ + 'string_thing': 'Goodbye4', + 'byte_thing': 4, + 'i32_thing': 4, + 'i64_thing': new Int64(4) + }, + { + 'string_thing': 'Hello2', + 'byte_thing': 2, + 'i32_thing': 2, + 'i64_thing': new Int64(2) + }] + }; + QUnit.test('testInsanity', function(assert) { + const insanity: {[k: number]: (ThriftTest.Insanity | {[k:number]: ThriftTest.Insanity})} = { + '1': { + '2': crazy, + '3': crazy + }, + '2': { '6': new ThriftTest.Insanity() } + }; + const res = client.testInsanity(new ThriftTest.Insanity(crazy)); + assert.ok(res, JSONInt64.stringify(res)); + assert.ok(insanity, JSONInt64.stringify(insanity)); + + checkRecursively(assert, res, insanity); + }); + + +////////////////////////////////// +//Run same tests asynchronously + +QUnit.module('Async'); + + QUnit.test('Double', function(assert) { + assert.expect(1); + + const done = assert.async(); + client.testDouble(3.14159265, function(result) { + assert.equal(result, 3.14159265); + done(); + }); + }); + + QUnit.test('Byte', function(assert) { + assert.expect(1); + + const done = assert.async(); + client.testByte(0x01, function(result) { + assert.equal(result, 0x01); + done(); + }); + }); + + QUnit.test('I32', function(assert) { + assert.expect(2); + + const done = assert.async(2); + client.testI32(Math.pow(2, 30), function(result) { + assert.equal(result, Math.pow(2, 30)); + done(); + }); + + client.testI32(Math.pow(-2, 31), function(result) { + assert.equal(result, Math.pow(-2, 31)); + done(); + }); + }); + + QUnit.test('I64', function(assert) { + assert.expect(2); + + const done = assert.async(2); + client.testI64(int64_2_pow_60, function(result) { + assert.ok(int64_2_pow_60.equals(result)); + done(); + }); + + client.testI64(int64_minus_2_pow_60, function(result) { + assert.ok(int64_minus_2_pow_60.equals(result)); + done(); + }); + }); diff --git a/lib/ts/test/test_handler.js b/lib/ts/test/test_handler.js new file mode 100644 index 00000000000..8ba296ba108 --- /dev/null +++ b/lib/ts/test/test_handler.js @@ -0,0 +1,202 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * 'License'); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +//This is the server side Node test handler for the standard +// Apache Thrift test service. + +const es6Mode = process.argv.includes('--es6'); +const genFolder = es6Mode ? 'gen-nodejs-es6' : 'gen-nodejs'; +const ttypes = require(`./${genFolder}/ThriftTest_types`); +const TException = require('../../nodejs/lib/thrift').TException; +const Int64 = require('node-int64'); + +exports.ThriftTestHandler = { + testVoid: function(result) { + console.log('testVoid()'); + result(null); + }, + testString: function(thing, result) { + console.log('testString(\'' + thing + '\')'); + result(null, thing); + }, + testByte: function(thing, result) { + console.log('testByte(' + thing + ')'); + result(null, thing); + }, + testI32: function(thing, result) { + console.log('testI32(' + thing + ')'); + result(null, thing); + }, + testI64: function(thing, result) { + console.log('testI64(' + thing + ')'); + result(null, thing); + }, + testDouble: function(thing, result) { + console.log('testDouble(' + thing + ')'); + result(null, thing); + }, + testBinary: function(thing, result) { + console.log('testBinary(\'' + thing + '\')'); + result(null, thing); + }, + testStruct: function(thing, result) { + console.log('testStruct('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + testNest: function(nest, result) { + console.log('testNest('); + console.log(nest); + console.log(')'); + result(null, nest); + }, + testMap: function(thing, result) { + console.log('testMap('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + testStringMap: function(thing, result) { + console.log('testStringMap('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + testSet: function(thing, result) { + console.log('testSet('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + testList: function(thing, result) { + console.log('testList('); + console.log(thing); + console.log(')'); + result(null, thing); + }, + testEnum: function(thing, result) { + console.log('testEnum(' + thing + ')'); + result(null, thing); + }, + testTypedef: function(thing, result) { + console.log('testTypedef(' + thing + ')'); + result(null, thing); + }, + testMapMap: function(hello, result) { + console.log('testMapMap(' + hello + ')'); + + const mapmap = []; + const pos = []; + const neg = []; + for (let i = 1; i < 5; i++) { + pos[i] = i; + neg[-i] = -i; + } + mapmap[4] = pos; + mapmap[-4] = neg; + + result(null, mapmap); + }, + testInsanity: function(argument, result) { + console.log('testInsanity('); + console.log(argument); + console.log(')'); + + const hello = new ttypes.Xtruct(); + hello.string_thing = 'Hello2'; + hello.byte_thing = 2; + hello.i32_thing = 2; + hello.i64_thing = new Int64(2); + + const goodbye = new ttypes.Xtruct(); + goodbye.string_thing = 'Goodbye4'; + goodbye.byte_thing = 4; + goodbye.i32_thing = 4; + goodbye.i64_thing = new Int64(4); + + const crazy = new ttypes.Insanity(); + crazy.userMap = []; + crazy.userMap[ttypes.Numberz.EIGHT] = 8; + crazy.userMap[ttypes.Numberz.FIVE] = 5; + crazy.xtructs = [goodbye, hello]; + + const first_map = []; + const second_map = []; + + first_map[ttypes.Numberz.TWO] = crazy; + first_map[ttypes.Numberz.THREE] = crazy; + + const looney = new ttypes.Insanity(); + second_map[ttypes.Numberz.SIX] = looney; + + const insane = []; + insane[1] = first_map; + insane[2] = second_map; + + console.log('insane result:'); + console.log(insane); + result(null, insane); + }, + testMulti: function(arg0, arg1, arg2, arg3, arg4, arg5, result) { + console.log('testMulti()'); + + const hello = new ttypes.Xtruct(); + hello.string_thing = 'Hello2'; + hello.byte_thing = arg0; + hello.i32_thing = arg1; + hello.i64_thing = arg2; + result(null, hello); + }, + testException: function(arg, result) { + console.log('testException(' + arg + ')'); + if (arg === 'Xception') { + const x = new ttypes.Xception(); + x.errorCode = 1001; + x.message = arg; + result(x); + } else if (arg === 'TException') { + result(new TException(arg)); + } else { + result(null); + } + }, + testMultiException: function(arg0, arg1, result) { + console.log('testMultiException(' + arg0 + ', ' + arg1 + ')'); + if (arg0 === ('Xception')) { + const x = new ttypes.Xception(); + x.errorCode = 1001; + x.message = 'This is an Xception'; + result(x); + } else if (arg0 === ('Xception2')) { + const x2 = new ttypes.Xception2(); + x2.errorCode = 2002; + x2.struct_thing = new ttypes.Xtruct(); + x2.struct_thing.string_thing = 'This is an Xception2'; + result(x2); + } + + const res = new ttypes.Xtruct(); + res.string_thing = arg1; + result(null, res); + }, + testOneway: function(sleepFor, result) { + console.log('testOneway(' + sleepFor + ') => JavaScript (like Rust) never sleeps!'); + } +}; //ThriftTestSvcHandler diff --git a/lib/ts/tsconfig.json b/lib/ts/tsconfig.json new file mode 100644 index 00000000000..97fa2258e19 --- /dev/null +++ b/lib/ts/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + "allowJs": false, + "alwaysStrict": true, + "baseUrl": ".", + "declaration": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "module": "commonjs", + "moduleResolution": "node", + "noImplicitThis": true, + "noUnusedLocals": true, + "preserveConstEnums": true, + "removeComments": true, + "strictFunctionTypes": true, + "strictNullChecks": true, + "target": "es6", + "paths": { + "*": [ + "*", + "test/", + "test/gen-js/*" + + ] + }, + }, + "exclude": [ + "./test/gen-nodejs/", + "./test/build/", + ] +} diff --git a/package-lock.json b/package-lock.json index b265aa6f299..1e089d94eb3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,15 @@ "integrity": "sha512-+ZWB5Ec1iki99xQFzBlivlKxSZQ+fuUKBott8StBOnLN4dWbRHlgdg1XknpW6g0tweniN5DcOqA64CJyOUPSAw==", "dev": true }, + "@types/node-int64": { + "version": "0.4.29", + "resolved": "https://registry.npmjs.org/@types/node-int64/-/node-int64-0.4.29.tgz", + "integrity": "sha512-rHXvenLTj/CcsmNAebaBOhxQ2MqEGl3yXZZcZ21XYR+gzGTTcpOy2N4IxpvTCz48loyQNatHvfn6GhIbbZ1R3Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.1.tgz", diff --git a/package.json b/package.json index 99553eee73b..97b7abf9a1d 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "directories": { "lib": "./lib/nodejs/lib/thrift" }, + "browser": "./lib/nodejs/lib/thrift/browser.js", "main": "./lib/nodejs/lib/thrift", "engines": { "node": ">= 4.1.0" @@ -53,6 +54,7 @@ "utf-8-validate": "^4.0.0", "typescript": "^3.1.6", "@types/node": "^10.12.6", + "@types/node-int64": "^0.4.29", "@types/q": "^1.5.1" }, "scripts": { diff --git a/test/Int64Test.thrift b/test/Int64Test.thrift new file mode 100644 index 00000000000..7a9ed2ffc64 --- /dev/null +++ b/test/Int64Test.thrift @@ -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. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +namespace js Int64Test + +const i64 SMALL_INT64 = 42 +const i64 MAX_JS_SAFE_INT64 = 9007199254740991 +const i64 MIN_JS_SAFE_INT64 = -9007199254740991 +const i64 MAX_JS_SAFE_PLUS_ONE_INT64 = 9007199254740992 +const i64 MIN_JS_SAFE_MINUS_ONE_INT64 = -9007199254740992 +const i64 MAX_SIGNED_INT64 = 9223372036854775807 +const i64 MIN_SIGNED_INT64 = -9223372036854775808 + +const list INT64_LIST = [SMALL_INT64, MAX_JS_SAFE_INT64, MIN_JS_SAFE_INT64, MAX_JS_SAFE_PLUS_ONE_INT64, MIN_JS_SAFE_MINUS_ONE_INT64, MAX_SIGNED_INT64, MIN_SIGNED_INT64] From ac9e9b1227074f6ae152468471fcfdca6f51fb2a Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 17 Jan 2019 00:41:02 +0100 Subject: [PATCH 146/756] THRIFT-4741 Missing "inner" argument from one CTOR Client: C# Patch: Jens Geyer This closes #1696 --- lib/csharp/src/Protocol/TProtocolException.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/csharp/src/Protocol/TProtocolException.cs b/lib/csharp/src/Protocol/TProtocolException.cs index c0f007e0ce1..b81db1a429e 100644 --- a/lib/csharp/src/Protocol/TProtocolException.cs +++ b/lib/csharp/src/Protocol/TProtocolException.cs @@ -42,8 +42,8 @@ public TProtocolException() { } - public TProtocolException(int type) - : base() + public TProtocolException(int type, Exception inner = null) + : base(inner) { type_ = type; } From 67df34afa782be67154034b31e4ad7cb3834fed1 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 17 Jan 2019 00:41:33 +0100 Subject: [PATCH 147/756] THRIFT-4742 Typo "cannot read from null input stream" on write Client: netcore Patch: Jens Geyer This closes #1697 --- lib/netcore/Thrift/Transports/Client/TStreamClientTransport.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/netcore/Thrift/Transports/Client/TStreamClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TStreamClientTransport.cs index f7164f0454f..be2011e83bc 100644 --- a/lib/netcore/Thrift/Transports/Client/TStreamClientTransport.cs +++ b/lib/netcore/Thrift/Transports/Client/TStreamClientTransport.cs @@ -82,7 +82,7 @@ public override async Task WriteAsync(byte[] buffer, int offset, int length, Can if (OutputStream == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen, - "Cannot read from null inputstream"); + "Cannot write to null outputstream"); } await OutputStream.WriteAsync(buffer, offset, length, cancellationToken); From 8630eb9cf23bd734b1b979cebef83186cb5c1e24 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 20 Jan 2019 11:33:35 +0100 Subject: [PATCH 148/756] THRIFT-4741 Missing "inner" argument from one CTOR Client: C# Patch: Jens Geyer This closes #1696 --- lib/csharp/src/Protocol/TProtocolException.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/csharp/src/Protocol/TProtocolException.cs b/lib/csharp/src/Protocol/TProtocolException.cs index b81db1a429e..41c26a39bb4 100644 --- a/lib/csharp/src/Protocol/TProtocolException.cs +++ b/lib/csharp/src/Protocol/TProtocolException.cs @@ -43,7 +43,7 @@ public TProtocolException() } public TProtocolException(int type, Exception inner = null) - : base(inner) + : base(string.Empty,inner) { type_ = type; } From 3b280d1ee2ce1467333289c733980cda423abf82 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 20 Jan 2019 12:38:21 +0100 Subject: [PATCH 149/756] THRIFT-4744 Erlang help intendation not aligned Client: Erlang Patch: Jens Geyer --- compiler/cpp/src/thrift/generate/t_erl_generator.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_erl_generator.cc b/compiler/cpp/src/thrift/generate/t_erl_generator.cc index 12d91a70649..d4fe12c3160 100644 --- a/compiler/cpp/src/thrift/generate/t_erl_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_erl_generator.cc @@ -1276,6 +1276,6 @@ std::string t_erl_generator::type_module(t_type* ttype) { THRIFT_REGISTER_GENERATOR( erl, "Erlang", - " legacynames: Output files retain naming conventions of Thrift 0.9.1 and earlier.\n" - " maps: Generate maps instead of dicts.\n" - " otp16: Generate non-namespaced dict and set instead of dict:dict and sets:set.\n") + " legacynames: Output files retain naming conventions of Thrift 0.9.1 and earlier.\n" + " maps: Generate maps instead of dicts.\n" + " otp16: Generate non-namespaced dict and set instead of dict:dict and sets:set.\n") From 1ad08ca91b62701bf2989f52e73e6642aee1f7f0 Mon Sep 17 00:00:00 2001 From: Christoph Herold Date: Tue, 15 Jan 2019 10:23:51 +0100 Subject: [PATCH 150/756] THRIFT-3587 TTLSSocket now also uses ConnectHelper to allow for timeouts when opening the connection. Client: C# Patch: Christoph Herold This closes #1698 --- lib/csharp/src/Transport/TTLSSocket.cs | 76 +++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/lib/csharp/src/Transport/TTLSSocket.cs b/lib/csharp/src/Transport/TTLSSocket.cs index fd019c372fa..06286dc8b50 100644 --- a/lib/csharp/src/Transport/TTLSSocket.cs +++ b/lib/csharp/src/Transport/TTLSSocket.cs @@ -295,7 +295,33 @@ public override void Open() InitSocket(); } - client.Connect(host, port); + if (timeout == 0) // no timeout -> infinite + { + client.Connect(host, port); + } + else // we have a timeout -> use it + { + ConnectHelper hlp = new ConnectHelper(client); + IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp); + bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected; + if (!bConnected) + { + lock (hlp.Mutex) + { + if (hlp.CallbackDone) + { + asyncres.AsyncWaitHandle.Close(); + client.Close(); + } + else + { + hlp.DoCleanup = true; + client = null; + } + } + throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out"); + } + } setupTLS(); } @@ -348,6 +374,54 @@ public void setupTLS() inputStream = this.secureStream; outputStream = this.secureStream; } + + static void ConnectCallback(IAsyncResult asyncres) + { + ConnectHelper hlp = asyncres.AsyncState as ConnectHelper; + lock (hlp.Mutex) + { + hlp.CallbackDone = true; + + try + { + if (hlp.Client.Client != null) + hlp.Client.EndConnect(asyncres); + } + catch (Exception) + { + // catch that away + } + + if (hlp.DoCleanup) + { + try + { + asyncres.AsyncWaitHandle.Close(); + } + catch (Exception) { } + + try + { + if (hlp.Client is IDisposable) + ((IDisposable)hlp.Client).Dispose(); + } + catch (Exception) { } + hlp.Client = null; + } + } + } + + private class ConnectHelper + { + public object Mutex = new object(); + public bool DoCleanup = false; + public bool CallbackDone = false; + public TcpClient Client; + public ConnectHelper(TcpClient client) + { + Client = client; + } + } /// /// Closes the SSL Socket From ef32bc10b70aa2926957fd8f35691563234f08b6 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 17 Jan 2019 14:08:44 -0500 Subject: [PATCH 151/756] THRIFT-4163: update cmake build type handling --- build/cmake/BuildType.cmake | 36 +++++++++++++++++++ build/cmake/DefineCMakeDefaults.cmake | 11 ++---- build/cmake/DefineOptions.cmake | 3 ++ lib/csharp/src/Protocol/TProtocolException.cs | 2 +- lib/csharp/src/TException.cs | 2 +- lib/hs/CMakeLists.txt | 2 +- 6 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 build/cmake/BuildType.cmake diff --git a/build/cmake/BuildType.cmake b/build/cmake/BuildType.cmake new file mode 100644 index 00000000000..b3bf353064a --- /dev/null +++ b/build/cmake/BuildType.cmake @@ -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. +# + +# originally from: +# https://raw.githubusercontent.com/OpenChemistry/tomviz/master/cmake/BuildType.cmake + +# Set a default build type if none was specified +set(default_build_type "RelWithDebInfo") +if(EXISTS "${CMAKE_SOURCE_DIR}/.git") + set(default_build_type "Debug") +endif() + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to '${default_build_type}' as none was specified.") + set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE + STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" + "MinSizeRel" "RelWithDebInfo") +endif() diff --git a/build/cmake/DefineCMakeDefaults.cmake b/build/cmake/DefineCMakeDefaults.cmake index 7ae21362da1..67143575103 100644 --- a/build/cmake/DefineCMakeDefaults.cmake +++ b/build/cmake/DefineCMakeDefaults.cmake @@ -34,17 +34,12 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) # since cmake 2.4.0 set(CMAKE_COLOR_MAKEFILE ON) -# Set the default build type to release with debug info -if (NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE RelWithDebInfo - CACHE STRING - "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." - ) -endif (NOT CMAKE_BUILD_TYPE) - # Create the compile command database for clang by default set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +# Set the CMAKE_BUILD_TYPE if it is not already defined +include(BuildType) + # Put the libraries and binaries that get built into directories at the # top of the build tree rather than in hard-to-find leaf # directories. This simplifies manual testing and the use of the build diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index e9b094c7bdc..8e334d9c23f 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -145,6 +145,9 @@ message(STATUS "----------------------------------------------------------") message(STATUS "Thrift version: ${thrift_VERSION} (${thrift_VERSION_MAJOR}.${thrift_VERSION_MINOR}.${thrift_VERSION_PATCH})") message(STATUS "Thrift package version: ${PACKAGE_VERSION}") message(STATUS "Build configuration Summary") +if (UNIX) + message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") +endif () message(STATUS " Build Thrift compiler: ${BUILD_COMPILER}") message(STATUS " Build compiler plugin support: ${WITH_PLUGIN}") message(STATUS " Build with unit tests: ${BUILD_TESTING}") diff --git a/lib/csharp/src/Protocol/TProtocolException.cs b/lib/csharp/src/Protocol/TProtocolException.cs index 41c26a39bb4..7bef236857b 100644 --- a/lib/csharp/src/Protocol/TProtocolException.cs +++ b/lib/csharp/src/Protocol/TProtocolException.cs @@ -43,7 +43,7 @@ public TProtocolException() } public TProtocolException(int type, Exception inner = null) - : base(string.Empty,inner) + : base(string.Empty, inner) { type_ = type; } diff --git a/lib/csharp/src/TException.cs b/lib/csharp/src/TException.cs index aa9a210c977..b9fae6e9f19 100644 --- a/lib/csharp/src/TException.cs +++ b/lib/csharp/src/TException.cs @@ -31,7 +31,7 @@ public TException() { } - public TException(string message, Exception inner) + public TException(string message, Exception inner = null) : base(message, inner) { } diff --git a/lib/hs/CMakeLists.txt b/lib/hs/CMakeLists.txt index a20a319e277..1a5b8fd32eb 100644 --- a/lib/hs/CMakeLists.txt +++ b/lib/hs/CMakeLists.txt @@ -60,7 +60,7 @@ endforeach() if(CMAKE_BUILD_TYPE STREQUAL "Debug") set(hs_optimize -O0) -elseif(CMAKE_BUILD_TYPE STREQUAL "Release") +else() set(hs_optimize -O1) endif() From f83d3f90d60365aa9898e57991f051e88e8094c6 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 12 Jan 2019 12:53:12 +0800 Subject: [PATCH 152/756] add const to member functions --- lib/cpp/src/thrift/concurrency/Thread.h | 2 +- lib/cpp/src/thrift/concurrency/ThreadManager.cpp | 2 +- lib/cpp/src/thrift/concurrency/ThreadManager.h | 3 +-- lib/cpp/src/thrift/transport/TTransport.h | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/cpp/src/thrift/concurrency/Thread.h b/lib/cpp/src/thrift/concurrency/Thread.h index 729d11a48e3..cacd401d348 100644 --- a/lib/cpp/src/thrift/concurrency/Thread.h +++ b/lib/cpp/src/thrift/concurrency/Thread.h @@ -153,7 +153,7 @@ class Thread final : public std::enable_shared_from_this { /** * Gets the thread's platform-specific ID */ - Thread::id_t getId() { return thread_.get() ? thread_->get_id() : std::thread::id(); } + Thread::id_t getId() const { return thread_.get() ? thread_->get_id() : std::thread::id(); } /** * Gets the runnable object this thread is hosting diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp index 58025f9d519..5e883270b3e 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp +++ b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp @@ -110,7 +110,7 @@ class ThreadManager::Impl : public ThreadManager { return pendingTaskCountMax_; } - size_t expiredTaskCount() { + size_t expiredTaskCount() const { Guard g(mutex_); return expiredCount_; } diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.h b/lib/cpp/src/thrift/concurrency/ThreadManager.h index 4b4b3d49188..605e36326da 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadManager.h +++ b/lib/cpp/src/thrift/concurrency/ThreadManager.h @@ -22,7 +22,6 @@ #include #include -#include #include namespace apache { @@ -141,7 +140,7 @@ class ThreadManager { * Gets the number of tasks which have been expired without being run * since start() was called. */ - virtual size_t expiredTaskCount() = 0; + virtual size_t expiredTaskCount() const = 0; /** * Adds a task to be executed at some time in the future by a worker thread. diff --git a/lib/cpp/src/thrift/transport/TTransport.h b/lib/cpp/src/thrift/transport/TTransport.h index d844239a8c2..d300f6bdc38 100644 --- a/lib/cpp/src/thrift/transport/TTransport.h +++ b/lib/cpp/src/thrift/transport/TTransport.h @@ -63,7 +63,7 @@ class TTransport { /** * Whether this transport is open. */ - virtual bool isOpen() { return false; } + virtual bool isOpen() const { return false; } /** * Tests whether there is more data to read or if the remote side is @@ -73,7 +73,7 @@ class TTransport { * This is used by a server to check if it should listen for another * request. */ - virtual bool peek() { return isOpen(); } + virtual bool peek() const { return isOpen(); } /** * Opens the transport for communications. From 7190ca7a3d8d259730580a9979519ddd6a344619 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 12 Jan 2019 13:09:25 +0800 Subject: [PATCH 153/756] remove unused headers --- lib/cpp/src/thrift/concurrency/Mutex.h | 1 - lib/cpp/src/thrift/concurrency/ThreadFactory.h | 5 ----- lib/cpp/src/thrift/concurrency/TimerManager.h | 1 - 3 files changed, 7 deletions(-) diff --git a/lib/cpp/src/thrift/concurrency/Mutex.h b/lib/cpp/src/thrift/concurrency/Mutex.h index 123ae785d39..5e0f85b0265 100644 --- a/lib/cpp/src/thrift/concurrency/Mutex.h +++ b/lib/cpp/src/thrift/concurrency/Mutex.h @@ -22,7 +22,6 @@ #include #include -#include namespace apache { namespace thrift { diff --git a/lib/cpp/src/thrift/concurrency/ThreadFactory.h b/lib/cpp/src/thrift/concurrency/ThreadFactory.h index f317afcde78..a1547a6e07a 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadFactory.h +++ b/lib/cpp/src/thrift/concurrency/ThreadFactory.h @@ -65,11 +65,6 @@ class ThreadFactory final { */ Thread::id_t getCurrentThreadId() const; - /** - * For code readability define the unknown/undefined thread id - */ - static const Thread::id_t unknown_thread_id; - private: bool detached_; }; diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.h b/lib/cpp/src/thrift/concurrency/TimerManager.h index 4d73b002db5..e09ecf2047f 100644 --- a/lib/cpp/src/thrift/concurrency/TimerManager.h +++ b/lib/cpp/src/thrift/concurrency/TimerManager.h @@ -26,7 +26,6 @@ #include #include -#include namespace apache { namespace thrift { From d12dbed670acb9fbe65662fb72d2069e5ee6d0a0 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 12 Jan 2019 13:18:24 +0800 Subject: [PATCH 154/756] remove unused headers --- lib/cpp/src/thrift/concurrency/Monitor.h | 6 ------ lib/cpp/src/thrift/concurrency/Thread.h | 2 -- lib/cpp/src/thrift/concurrency/TimerManager.h | 1 - 3 files changed, 9 deletions(-) diff --git a/lib/cpp/src/thrift/concurrency/Monitor.h b/lib/cpp/src/thrift/concurrency/Monitor.h index 2399a987986..11a145d5571 100644 --- a/lib/cpp/src/thrift/concurrency/Monitor.h +++ b/lib/cpp/src/thrift/concurrency/Monitor.h @@ -20,15 +20,9 @@ #ifndef _THRIFT_CONCURRENCY_MONITOR_H_ #define _THRIFT_CONCURRENCY_MONITOR_H_ 1 -#ifdef HAVE_SYS_TIME_H -#include -#endif - #include #include -#include - namespace apache { namespace thrift { namespace concurrency { diff --git a/lib/cpp/src/thrift/concurrency/Thread.h b/lib/cpp/src/thrift/concurrency/Thread.h index cacd401d348..f8a3f51571a 100644 --- a/lib/cpp/src/thrift/concurrency/Thread.h +++ b/lib/cpp/src/thrift/concurrency/Thread.h @@ -20,11 +20,9 @@ #ifndef _THRIFT_CONCURRENCY_THREAD_H_ #define _THRIFT_CONCURRENCY_THREAD_H_ 1 -#include #include #include -#include #include namespace apache { diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.h b/lib/cpp/src/thrift/concurrency/TimerManager.h index e09ecf2047f..4e291e3cbce 100644 --- a/lib/cpp/src/thrift/concurrency/TimerManager.h +++ b/lib/cpp/src/thrift/concurrency/TimerManager.h @@ -20,7 +20,6 @@ #ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_ #define _THRIFT_CONCURRENCY_TIMERMANAGER_H_ 1 -#include #include #include From bfdbd0344bd3ddf348985b51e02212e8092859d4 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 12 Jan 2019 14:38:28 +0800 Subject: [PATCH 155/756] use chrono --- lib/cpp/CMakeLists.txt | 1 - lib/cpp/Makefile.am | 4 +- lib/cpp/src/thrift/concurrency/Monitor.cpp | 54 ++----- lib/cpp/src/thrift/concurrency/Monitor.h | 23 ++- .../src/thrift/concurrency/ThreadManager.cpp | 28 ++-- .../src/thrift/concurrency/TimerManager.cpp | 91 ++++------- lib/cpp/src/thrift/concurrency/TimerManager.h | 20 +-- lib/cpp/src/thrift/concurrency/Util.cpp | 44 ----- lib/cpp/src/thrift/concurrency/Util.h | 151 ------------------ .../src/thrift/transport/TFileTransport.cpp | 26 +-- lib/cpp/src/thrift/transport/TFileTransport.h | 4 +- lib/cpp/test/concurrency/Tests.cpp | 8 +- lib/cpp/test/concurrency/ThreadFactoryTests.h | 5 +- lib/cpp/test/concurrency/ThreadManagerTests.h | 13 +- lib/cpp/test/concurrency/TimerManagerTests.h | 5 +- test/cpp/src/StressTest.cpp | 9 +- test/cpp/src/StressTestNonBlocking.cpp | 9 +- 17 files changed, 111 insertions(+), 384 deletions(-) delete mode 100644 lib/cpp/src/thrift/concurrency/Util.cpp delete mode 100644 lib/cpp/src/thrift/concurrency/Util.h diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index 90a6c28855c..f4e810461d3 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -36,7 +36,6 @@ set( thriftcpp_SOURCES src/thrift/async/TConcurrentClientSyncInfo.cpp src/thrift/concurrency/ThreadManager.cpp src/thrift/concurrency/TimerManager.cpp - src/thrift/concurrency/Util.cpp src/thrift/processor/PeekProcessor.cpp src/thrift/protocol/TBase64Utils.cpp src/thrift/protocol/TDebugProtocol.cpp diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index de0c058c1ce..db9d751e457 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -67,7 +67,6 @@ libthrift_la_SOURCES = src/thrift/TApplicationException.cpp \ src/thrift/async/TConcurrentClientSyncInfo.cpp \ src/thrift/concurrency/ThreadManager.cpp \ src/thrift/concurrency/TimerManager.cpp \ - src/thrift/concurrency/Util.cpp \ src/thrift/processor/PeekProcessor.cpp \ src/thrift/protocol/TDebugProtocol.cpp \ src/thrift/protocol/TJSONProtocol.cpp \ @@ -155,8 +154,7 @@ include_concurrency_HEADERS = \ src/thrift/concurrency/Thread.h \ src/thrift/concurrency/ThreadManager.h \ src/thrift/concurrency/TimerManager.h \ - src/thrift/concurrency/FunctionRunner.h \ - src/thrift/concurrency/Util.h + src/thrift/concurrency/FunctionRunner.h include_protocoldir = $(include_thriftdir)/protocol include_protocol_HEADERS = \ diff --git a/lib/cpp/src/thrift/concurrency/Monitor.cpp b/lib/cpp/src/thrift/concurrency/Monitor.cpp index 7b3b209a74d..99d52b3e351 100644 --- a/lib/cpp/src/thrift/concurrency/Monitor.cpp +++ b/lib/cpp/src/thrift/concurrency/Monitor.cpp @@ -21,7 +21,6 @@ #include #include -#include #include #include @@ -61,8 +60,8 @@ class Monitor::Impl { * If the condition occurs, this function returns cleanly; on timeout or * error an exception is thrown. */ - void wait(int64_t timeout_ms) { - int result = waitForTimeRelative(timeout_ms); + void wait(const std::chrono::milliseconds &timeout) { + int result = waitForTimeRelative(timeout); if (result == THRIFT_ETIMEDOUT) { throw TimedOutException(); } else if (result != 0) { @@ -72,12 +71,12 @@ class Monitor::Impl { /** * Waits until the specified timeout in milliseconds for the condition to - * occur, or waits forever if timeout_ms == 0. + * occur, or waits forever if timeout is zero. * * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. */ - int waitForTimeRelative(int64_t timeout_ms) { - if (timeout_ms == 0LL) { + int waitForTimeRelative(const std::chrono::milliseconds &timeout) { + if (timeout.count() == 0) { return waitForever(); } @@ -86,46 +85,23 @@ class Monitor::Impl { assert(mutexImpl); std::unique_lock lock(*mutexImpl, std::adopt_lock); - bool timedout = (conditionVariable_.wait_for(lock, std::chrono::milliseconds(timeout_ms)) + bool timedout = (conditionVariable_.wait_for(lock, timeout) == std::cv_status::timeout); lock.release(); return (timedout ? THRIFT_ETIMEDOUT : 0); } /** - * Waits until the absolute time specified using struct THRIFT_TIMESPEC. + * Waits until the absolute time specified by abstime. * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. */ - int waitForTime(const THRIFT_TIMESPEC* abstime) { - struct timeval temp; - temp.tv_sec = static_cast(abstime->tv_sec); - temp.tv_usec = static_cast(abstime->tv_nsec) / 1000; - return waitForTime(&temp); - } - - /** - * Waits until the absolute time specified using struct timeval. - * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. - */ - int waitForTime(const struct timeval* abstime) { + int waitForTime(const std::chrono::time_point& abstime) { assert(mutex_); std::timed_mutex* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); assert(mutexImpl); - struct timeval currenttime; - Util::toTimeval(currenttime, Util::currentTime()); - - long tv_sec = static_cast(abstime->tv_sec - currenttime.tv_sec); - long tv_usec = static_cast(abstime->tv_usec - currenttime.tv_usec); - if (tv_sec < 0) - tv_sec = 0; - if (tv_usec < 0) - tv_usec = 0; - std::unique_lock lock(*mutexImpl, std::adopt_lock); - bool timedout = (conditionVariable_.wait_for(lock, - std::chrono::seconds(tv_sec) - + std::chrono::microseconds(tv_usec)) + bool timedout = (conditionVariable_.wait_until(lock, abstime) == std::cv_status::timeout); lock.release(); return (timedout ? THRIFT_ETIMEDOUT : 0); @@ -181,20 +157,16 @@ void Monitor::unlock() const { const_cast(impl_)->unlock(); } -void Monitor::wait(int64_t timeout) const { +void Monitor::wait(const std::chrono::milliseconds &timeout) const { const_cast(impl_)->wait(timeout); } -int Monitor::waitForTime(const THRIFT_TIMESPEC* abstime) const { - return const_cast(impl_)->waitForTime(abstime); -} - -int Monitor::waitForTime(const timeval* abstime) const { +int Monitor::waitForTime(const std::chrono::time_point& abstime) const { return const_cast(impl_)->waitForTime(abstime); } -int Monitor::waitForTimeRelative(int64_t timeout_ms) const { - return const_cast(impl_)->waitForTimeRelative(timeout_ms); +int Monitor::waitForTimeRelative(const std::chrono::milliseconds &timeout) const { + return const_cast(impl_)->waitForTimeRelative(timeout); } int Monitor::waitForever() const { diff --git a/lib/cpp/src/thrift/concurrency/Monitor.h b/lib/cpp/src/thrift/concurrency/Monitor.h index 11a145d5571..c70fc86161e 100644 --- a/lib/cpp/src/thrift/concurrency/Monitor.h +++ b/lib/cpp/src/thrift/concurrency/Monitor.h @@ -20,6 +20,7 @@ #ifndef _THRIFT_CONCURRENCY_MONITOR_H_ #define _THRIFT_CONCURRENCY_MONITOR_H_ 1 +#include #include #include @@ -67,23 +68,19 @@ class Monitor : boost::noncopyable { /** * Waits a maximum of the specified timeout in milliseconds for the condition - * to occur, or waits forever if timeout_ms == 0. + * to occur, or waits forever if timeout is zero. * * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. */ - int waitForTimeRelative(int64_t timeout_ms) const; + int waitForTimeRelative(const std::chrono::milliseconds &timeout) const; - /** - * Waits until the absolute time specified using struct THRIFT_TIMESPEC. - * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. - */ - int waitForTime(const THRIFT_TIMESPEC* abstime) const; + int waitForTimeRelative(int64_t timeout_ms) const { return waitForTimeRelative(std::chrono::milliseconds(timeout_ms)); } /** - * Waits until the absolute time specified using struct timeval. + * Waits until the absolute time specified by abstime. * Returns 0 if condition occurs, THRIFT_ETIMEDOUT on timeout, or an error code. */ - int waitForTime(const struct timeval* abstime) const; + int waitForTime(const std::chrono::time_point& abstime) const; /** * Waits forever until the condition occurs. @@ -93,12 +90,14 @@ class Monitor : boost::noncopyable { /** * Exception-throwing version of waitForTimeRelative(), called simply - * wait(int64) for historical reasons. Timeout is in milliseconds. + * wait(std::chrono::milliseconds) for historical reasons. Timeout is in milliseconds. * - * If the condition occurs, this function returns cleanly; on timeout or + * If the condition occurs, this function returns cleanly; on timeout or * error an exception is thrown. */ - void wait(int64_t timeout_ms = 0LL) const; + void wait(const std::chrono::milliseconds &timeout) const; + + void wait(int64_t timeout_ms = 0LL) const { this->wait(std::chrono::milliseconds(timeout_ms)); } /** Wakes up one thread waiting on this monitor. */ virtual void notify() const; diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp index 5e883270b3e..4c7c372afb0 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp +++ b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include @@ -35,6 +34,7 @@ namespace thrift { namespace concurrency { using std::shared_ptr; +using std::unique_ptr; using std::dynamic_pointer_cast; /** @@ -180,10 +180,13 @@ class ThreadManager::Task : public Runnable { public: enum STATE { WAITING, EXECUTING, TIMEDOUT, COMPLETE }; - Task(shared_ptr runnable, int64_t expiration = 0LL) + Task(shared_ptr runnable, uint64_t expiration = 0ULL) : runnable_(runnable), - state_(WAITING), - expireTime_(expiration != 0LL ? Util::currentTime() + expiration : 0LL) {} + state_(WAITING) { + if (expiration != 0ULL) { + expireTime_.reset(new std::chrono::steady_clock::time_point(std::chrono::steady_clock::now() + std::chrono::milliseconds(expiration))); + } + } ~Task() {} @@ -196,13 +199,13 @@ class ThreadManager::Task : public Runnable { shared_ptr getRunnable() { return runnable_; } - int64_t getExpireTime() const { return expireTime_; } + const unique_ptr & getExpireTime() const { return expireTime_; } private: shared_ptr runnable_; friend class ThreadManager::Worker; STATE state_; - int64_t expireTime_; + unique_ptr expireTime_; }; class ThreadManager::Worker : public Runnable { @@ -280,7 +283,7 @@ class ThreadManager::Worker : public Runnable { // If the state is changed to anything other than EXECUTING or TIMEDOUT here // then the execution loop needs to be changed below. task->state_ = - (task->getExpireTime() && task->getExpireTime() < Util::currentTime()) ? + (task->getExpireTime() && *(task->getExpireTime()) < std::chrono::steady_clock::now()) ? ThreadManager::Task::TIMEDOUT : ThreadManager::Task::EXECUTING; } @@ -524,15 +527,14 @@ std::shared_ptr ThreadManager::Impl::removeNextPending() { void ThreadManager::Impl::removeExpired(bool justOne) { // this is always called under a lock - int64_t now = 0LL; + if (tasks_.empty()) { + return; + } + auto now = std::chrono::steady_clock::now(); for (TaskQueue::iterator it = tasks_.begin(); it != tasks_.end(); ) { - if (now == 0LL) { - now = Util::currentTime(); - } - - if ((*it)->getExpireTime() > 0LL && (*it)->getExpireTime() < now) { + if ((*it)->getExpireTime() && *((*it)->getExpireTime()) < now) { if (expireCallback_) { expireCallback_((*it)->getRunnable()); } diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.cpp b/lib/cpp/src/thrift/concurrency/TimerManager.cpp index 61a34ff694f..edd336be07c 100644 --- a/lib/cpp/src/thrift/concurrency/TimerManager.cpp +++ b/lib/cpp/src/thrift/concurrency/TimerManager.cpp @@ -19,7 +19,6 @@ #include #include -#include #include #include @@ -90,21 +89,22 @@ class TimerManager::Dispatcher : public Runnable { { Synchronized s(manager_->monitor_); task_iterator expiredTaskEnd; - int64_t now = Util::currentTime(); + auto now = std::chrono::steady_clock::now(); while (manager_->state_ == TimerManager::STARTED && (expiredTaskEnd = manager_->taskMap_.upper_bound(now)) == manager_->taskMap_.begin()) { - int64_t timeout = 0LL; + std::chrono::milliseconds timeout(0); if (!manager_->taskMap_.empty()) { - timeout = manager_->taskMap_.begin()->first - now; - } - assert((timeout != 0 && manager_->taskCount_ > 0) - || (timeout == 0 && manager_->taskCount_ == 0)); - try { - manager_->monitor_.wait(timeout); - } catch (TimedOutException&) { + timeout = std::chrono::duration_cast(manager_->taskMap_.begin()->first - now); + //because the unit of steady_clock is smaller than millisecond,timeout may be 0. + if (timeout.count() == 0) { + timeout = std::chrono::milliseconds(1); + } + manager_->monitor_.waitForTimeRelative(timeout); + } else { + manager_->monitor_.waitForTimeRelative(0); } - now = Util::currentTime(); + now = std::chrono::steady_clock::now(); } if (manager_->state_ == TimerManager::STARTED) { @@ -239,64 +239,39 @@ size_t TimerManager::taskCount() const { return taskCount_; } -TimerManager::Timer TimerManager::add(shared_ptr task, int64_t timeout) { - int64_t now = Util::currentTime(); - timeout += now; - - { - Synchronized s(monitor_); - if (state_ != TimerManager::STARTED) { - throw IllegalStateException(); - } - - // If the task map is empty, we will kick the dispatcher for sure. Otherwise, we kick him - // if the expiration time is shorter than the current value. Need to test before we insert, - // because the new task might insert at the front. - bool notifyRequired = (taskCount_ == 0) ? true : timeout < taskMap_.begin()->first; - - shared_ptr timer(new Task(task)); - taskCount_++; - timer->it_ = taskMap_.insert(std::pair >(timeout, timer)); - - // If the task map was empty, or if we have an expiration that is earlier - // than any previously seen, kick the dispatcher so it can update its - // timeout - if (notifyRequired) { - monitor_.notify(); - } - - return timer; - } +TimerManager::Timer TimerManager::add(shared_ptr task, const std::chrono::milliseconds &timeout) { + return add(task, std::chrono::steady_clock::now() + timeout); } TimerManager::Timer TimerManager::add(shared_ptr task, - const struct THRIFT_TIMESPEC& value) { + const std::chrono::time_point& abstime) { + auto now = std::chrono::steady_clock::now(); - int64_t expiration; - Util::toMilliseconds(expiration, value); - - int64_t now = Util::currentTime(); - - if (expiration < now) { + if (abstime < now) { throw InvalidArgumentException(); } + Synchronized s(monitor_); + if (state_ != TimerManager::STARTED) { + throw IllegalStateException(); + } - return add(task, expiration - now); -} - -TimerManager::Timer TimerManager::add(shared_ptr task, - const struct timeval& value) { - - int64_t expiration; - Util::toMilliseconds(expiration, value); + // If the task map is empty, we will kick the dispatcher for sure. Otherwise, we kick him + // if the expiration time is shorter than the current value. Need to test before we insert, + // because the new task might insert at the front. + bool notifyRequired = (taskCount_ == 0) ? true : abstime < taskMap_.begin()->first; - int64_t now = Util::currentTime(); + shared_ptr timer(new Task(task)); + taskCount_++; + timer->it_ = taskMap_.emplace(abstime, timer); - if (expiration < now) { - throw InvalidArgumentException(); + // If the task map was empty, or if we have an expiration that is earlier + // than any previously seen, kick the dispatcher so it can update its + // timeout + if (notifyRequired) { + monitor_.notify(); } - return add(task, expiration - now); + return timer; } void TimerManager::remove(shared_ptr task) { diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.h b/lib/cpp/src/thrift/concurrency/TimerManager.h index 4e291e3cbce..44d4738d5f2 100644 --- a/lib/cpp/src/thrift/concurrency/TimerManager.h +++ b/lib/cpp/src/thrift/concurrency/TimerManager.h @@ -72,25 +72,17 @@ class TimerManager { * @param timeout Time in milliseconds to delay before executing task * @return Handle of the timer, which can be used to remove the timer. */ - virtual Timer add(std::shared_ptr task, int64_t timeout); + virtual Timer add(std::shared_ptr task, const std::chrono::milliseconds &timeout); + Timer add(std::shared_ptr task, uint64_t timeout) { return add(task,std::chrono::milliseconds(timeout)); } /** * Adds a task to be executed at some time in the future by a worker thread. * * @param task The task to execute - * @param timeout Absolute time in the future to execute task. + * @param abstime Absolute time in the future to execute task. * @return Handle of the timer, which can be used to remove the timer. */ - virtual Timer add(std::shared_ptr task, const struct THRIFT_TIMESPEC& timeout); - - /** - * Adds a task to be executed at some time in the future by a worker thread. - * - * @param task The task to execute - * @param timeout Absolute time in the future to execute task. - * @return Handle of the timer, which can be used to remove the timer. - */ - virtual Timer add(std::shared_ptr task, const struct timeval& timeout); + virtual Timer add(std::shared_ptr task, const std::chrono::time_point& abstime); /** * Removes a pending task @@ -127,7 +119,7 @@ class TimerManager { private: std::shared_ptr threadFactory_; friend class Task; - std::multimap > taskMap_; + std::multimap, std::shared_ptr > taskMap_; size_t taskCount_; Monitor monitor_; STATE state_; @@ -135,7 +127,7 @@ class TimerManager { friend class Dispatcher; std::shared_ptr dispatcher_; std::shared_ptr dispatcherThread_; - typedef std::multimap >::iterator task_iterator; + using task_iterator = decltype(taskMap_)::iterator; typedef std::pair task_range; }; } diff --git a/lib/cpp/src/thrift/concurrency/Util.cpp b/lib/cpp/src/thrift/concurrency/Util.cpp deleted file mode 100644 index dd6d19f971a..00000000000 --- a/lib/cpp/src/thrift/concurrency/Util.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include - -#include -#include - -#if defined(HAVE_SYS_TIME_H) -#include -#endif - -namespace apache { -namespace thrift { -namespace concurrency { - -int64_t Util::currentTimeTicks(int64_t ticksPerSec) { - int64_t result; - struct timeval now; - int ret = THRIFT_GETTIMEOFDAY(&now, NULL); - assert(ret == 0); - THRIFT_UNUSED_VARIABLE(ret); // squelching "unused variable" warning - toTicks(result, now, ticksPerSec); - return result; -} -} -} -} // apache::thrift::concurrency diff --git a/lib/cpp/src/thrift/concurrency/Util.h b/lib/cpp/src/thrift/concurrency/Util.h deleted file mode 100644 index 1a915993f39..00000000000 --- a/lib/cpp/src/thrift/concurrency/Util.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef _THRIFT_CONCURRENCY_UTIL_H_ -#define _THRIFT_CONCURRENCY_UTIL_H_ 1 - -#include -#include -#include -#include - -#ifdef HAVE_SYS_TIME_H -#include -#endif - -#include - -namespace apache { -namespace thrift { -namespace concurrency { - -/** - * Utility methods - * - * This class contains basic utility methods for converting time formats, - * and other common platform-dependent concurrency operations. - * It should not be included in API headers for other concurrency library - * headers, since it will, by definition, pull in all sorts of horrid - * platform dependent stuff. Rather it should be inluded directly in - * concurrency library implementation source. - * - * @version $Id:$ - */ -class Util { - - static const int64_t NS_PER_S = 1000000000LL; - static const int64_t US_PER_S = 1000000LL; - static const int64_t MS_PER_S = 1000LL; - - static const int64_t NS_PER_MS = NS_PER_S / MS_PER_S; - static const int64_t NS_PER_US = NS_PER_S / US_PER_S; - static const int64_t US_PER_MS = US_PER_S / MS_PER_S; - -public: - /** - * Converts millisecond timestamp into a THRIFT_TIMESPEC struct - * - * @param struct THRIFT_TIMESPEC& result - * @param time or duration in milliseconds - */ - static void toTimespec(struct THRIFT_TIMESPEC& result, int64_t value) { - result.tv_sec = value / MS_PER_S; // ms to s - result.tv_nsec = (value % MS_PER_S) * NS_PER_MS; // ms to ns - } - - static void toTimeval(struct timeval& result, int64_t value) { - result.tv_sec = static_cast(value / MS_PER_S); // ms to s - result.tv_usec = static_cast((value % MS_PER_S) * US_PER_MS); // ms to us - } - - static void toTicks(int64_t& result, - int64_t secs, - int64_t oldTicks, - int64_t oldTicksPerSec, - int64_t newTicksPerSec) { - result = secs * newTicksPerSec; - result += oldTicks * newTicksPerSec / oldTicksPerSec; - - int64_t oldPerNew = oldTicksPerSec / newTicksPerSec; - if (oldPerNew && ((oldTicks % oldPerNew) >= (oldPerNew / 2))) { - ++result; - } - } - /** - * Converts struct THRIFT_TIMESPEC to arbitrary-sized ticks since epoch - */ - static void toTicks(int64_t& result, const struct THRIFT_TIMESPEC& value, int64_t ticksPerSec) { - return toTicks(result, value.tv_sec, value.tv_nsec, NS_PER_S, ticksPerSec); - } - - /** - * Converts struct timeval to arbitrary-sized ticks since epoch - */ - static void toTicks(int64_t& result, const struct timeval& value, int64_t ticksPerSec) { - return toTicks(result, (unsigned long)value.tv_sec, (unsigned long)value.tv_usec, US_PER_S, ticksPerSec); - } - - /** - * Converts struct THRIFT_TIMESPEC to milliseconds - */ - static void toMilliseconds(int64_t& result, const struct THRIFT_TIMESPEC& value) { - return toTicks(result, value, MS_PER_S); - } - - /** - * Converts struct timeval to milliseconds - */ - static void toMilliseconds(int64_t& result, const struct timeval& value) { - return toTicks(result, value, MS_PER_S); - } - - /** - * Converts struct THRIFT_TIMESPEC to microseconds - */ - static void toUsec(int64_t& result, const struct THRIFT_TIMESPEC& value) { - return toTicks(result, value, US_PER_S); - } - - /** - * Converts struct timeval to microseconds - */ - static void toUsec(int64_t& result, const struct timeval& value) { - return toTicks(result, value, US_PER_S); - } - - /** - * Get current time as a number of arbitrary-size ticks from epoch - */ - static int64_t currentTimeTicks(int64_t ticksPerSec); - - /** - * Get current time as milliseconds from epoch - */ - static int64_t currentTime() { return currentTimeTicks(MS_PER_S); } - - /** - * Get current time as micros from epoch - */ - static int64_t currentTimeUsec() { return currentTimeTicks(US_PER_S); } -}; -} -} -} // apache::thrift::concurrency - -#endif // #ifndef _THRIFT_CONCURRENCY_UTIL_H_ diff --git a/lib/cpp/src/thrift/transport/TFileTransport.cpp b/lib/cpp/src/thrift/transport/TFileTransport.cpp index afb441198f6..19058094c57 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.cpp +++ b/lib/cpp/src/thrift/transport/TFileTransport.cpp @@ -264,7 +264,7 @@ void TFileTransport::enqueueEvent(const uint8_t* buf, uint32_t eventLen) { // it is probably a non-factor for the time being } -bool TFileTransport::swapEventBuffers(struct timeval* deadline) { +bool TFileTransport::swapEventBuffers(const std::chrono::time_point *deadline) { bool swap; Guard g(mutex_); @@ -277,7 +277,7 @@ bool TFileTransport::swapEventBuffers(struct timeval* deadline) { } else { if (deadline != NULL) { // if we were handed a deadline time struct, do a timed wait - notEmpty_.waitForTime(deadline); + notEmpty_.waitForTime(*deadline); } else { // just wait until the buffer gets an item notEmpty_.wait(); @@ -336,8 +336,7 @@ void TFileTransport::writerThread() { } // Figure out the next time by which a flush must take place - struct timeval ts_next_flush; - getNextFlushTime(&ts_next_flush); + auto ts_next_flush = getNextFlushTime(); uint32_t unflushed = 0; while (1) { @@ -492,15 +491,13 @@ void TFileTransport::writerThread() { } else { struct timeval current_time; THRIFT_GETTIMEOFDAY(¤t_time, NULL); - if (current_time.tv_sec > ts_next_flush.tv_sec - || (current_time.tv_sec == ts_next_flush.tv_sec - && current_time.tv_usec > ts_next_flush.tv_usec)) { + if (std::chrono::steady_clock::now() > ts_next_flush) { if (unflushed > 0) { flush = true; } else { // If there is no new data since the last fsync, // don't perform the fsync, but do reset the timer. - getNextFlushTime(&ts_next_flush); + ts_next_flush = getNextFlushTime(); } } } @@ -509,7 +506,7 @@ void TFileTransport::writerThread() { // sync (force flush) file to disk THRIFT_FSYNC(fd_); unflushed = 0; - getNextFlushTime(&ts_next_flush); + ts_next_flush = getNextFlushTime(); // notify anybody waiting for flush completion if (forced_flush) { @@ -908,15 +905,8 @@ void TFileTransport::openLogFile() { } } -void TFileTransport::getNextFlushTime(struct timeval* ts_next_flush) { - THRIFT_GETTIMEOFDAY(ts_next_flush, NULL); - - ts_next_flush->tv_usec += flushMaxUs_; - if (ts_next_flush->tv_usec > 1000000) { - long extra_secs = ts_next_flush->tv_usec / 1000000; - ts_next_flush->tv_usec %= 1000000; - ts_next_flush->tv_sec += extra_secs; - } +std::chrono::time_point TFileTransport::getNextFlushTime() { + return std::chrono::steady_clock::now() + std::chrono::microseconds(flushMaxUs_); } TFileTransportBuffer::TFileTransportBuffer(uint32_t size) diff --git a/lib/cpp/src/thrift/transport/TFileTransport.h b/lib/cpp/src/thrift/transport/TFileTransport.h index ece271aae4d..4290eaa6682 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.h +++ b/lib/cpp/src/thrift/transport/TFileTransport.h @@ -267,7 +267,7 @@ class TFileTransport : public TFileReaderTransport, public TFileWriterTransport private: // helper functions for writing to a file void enqueueEvent(const uint8_t* buf, uint32_t eventLen); - bool swapEventBuffers(struct timeval* deadline); + bool swapEventBuffers(const std::chrono::time_point *deadline); bool initBufferAndWriteThread(); // control for writer thread @@ -286,7 +286,7 @@ class TFileTransport : public TFileReaderTransport, public TFileWriterTransport // Utility functions void openLogFile(); - void getNextFlushTime(struct timeval* ts_next_flush); + std::chrono::time_point getNextFlushTime(); // Class variables readState readState_; diff --git a/lib/cpp/test/concurrency/Tests.cpp b/lib/cpp/test/concurrency/Tests.cpp index fc0ba7f1567..019ae67f299 100644 --- a/lib/cpp/test/concurrency/Tests.cpp +++ b/lib/cpp/test/concurrency/Tests.cpp @@ -94,18 +94,18 @@ int main(int argc, char** argv) { std::cout << "\t\tUtil minimum time" << std::endl; - int64_t time00 = Util::currentTime(); - int64_t time01 = Util::currentTime(); + int64_t time00 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + int64_t time01 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); std::cout << "\t\t\tMinimum time: " << time01 - time00 << "ms" << std::endl; - time00 = Util::currentTime(); + time00 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); time01 = time00; size_t count = 0; while (time01 < time00 + 10) { count++; - time01 = Util::currentTime(); + time01 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); } std::cout << "\t\t\tscall per ms: " << count / (time01 - time00) << std::endl; diff --git a/lib/cpp/test/concurrency/ThreadFactoryTests.h b/lib/cpp/test/concurrency/ThreadFactoryTests.h index 8ab754c8980..ad1613ba9f0 100644 --- a/lib/cpp/test/concurrency/ThreadFactoryTests.h +++ b/lib/cpp/test/concurrency/ThreadFactoryTests.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -221,7 +220,7 @@ class ThreadFactoryTests { Monitor monitor; - int64_t startTime = Util::currentTime(); + int64_t startTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); for (int64_t ix = 0; ix < count; ix++) { { @@ -233,7 +232,7 @@ class ThreadFactoryTests { } } - int64_t endTime = Util::currentTime(); + int64_t endTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); bool success = (endTime - startTime) >= (count * timeout); diff --git a/lib/cpp/test/concurrency/ThreadManagerTests.h b/lib/cpp/test/concurrency/ThreadManagerTests.h index b3a319a5710..e9ed75653bc 100644 --- a/lib/cpp/test/concurrency/ThreadManagerTests.h +++ b/lib/cpp/test/concurrency/ThreadManagerTests.h @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -66,11 +65,11 @@ class ThreadManagerTests { void run() { - _startTime = Util::currentTime(); + _startTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); sleep_(_timeout); - _endTime = Util::currentTime(); + _endTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); _done = true; @@ -123,7 +122,7 @@ class ThreadManagerTests { new ThreadManagerTests::Task(monitor, activeCount, timeout))); } - int64_t time00 = Util::currentTime(); + int64_t time00 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); for (std::set >::iterator ix = tasks.begin(); ix != tasks.end(); @@ -143,7 +142,7 @@ class ThreadManagerTests { } } - int64_t time01 = Util::currentTime(); + int64_t time01 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); int64_t firstTime = 9223372036854775807LL; int64_t lastTime = 0; @@ -387,9 +386,9 @@ class ThreadManagerTests { bool apiTest() { // prove currentTime has milliseconds granularity since many other things depend on it - int64_t a = Util::currentTime(); + int64_t a = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); sleep_(100); - int64_t b = Util::currentTime(); + int64_t b = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); if (b - a < 50 || b - a > 150) { std::cerr << "\t\t\texpected 100ms gap, found " << (b-a) << "ms gap instead." << std::endl; return false; diff --git a/lib/cpp/test/concurrency/TimerManagerTests.h b/lib/cpp/test/concurrency/TimerManagerTests.h index c15b14b8099..24d829acf9b 100644 --- a/lib/cpp/test/concurrency/TimerManagerTests.h +++ b/lib/cpp/test/concurrency/TimerManagerTests.h @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -39,7 +38,7 @@ class TimerManagerTests { public: Task(Monitor& monitor, int64_t timeout) : _timeout(timeout), - _startTime(Util::currentTime()), + _startTime(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count()), _endTime(0), _monitor(monitor), _success(false), @@ -49,7 +48,7 @@ class TimerManagerTests { void run() { - _endTime = Util::currentTime(); + _endTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); _success = (_endTime - _startTime) >= _timeout; { diff --git a/test/cpp/src/StressTest.cpp b/test/cpp/src/StressTest.cpp index f4c281c7f72..930261e4611 100644 --- a/test/cpp/src/StressTest.cpp +++ b/test/cpp/src/StressTest.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -133,7 +132,7 @@ class ClientThread : public Runnable { } } - _startTime = Util::currentTime(); + _startTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); if(_behavior == OpenAndCloseTransportInThread) { _transport->open(); } @@ -159,7 +158,7 @@ class ClientThread : public Runnable { break; } - _endTime = Util::currentTime(); + _endTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); if(_behavior == OpenAndCloseTransportInThread) { _transport->close(); @@ -540,7 +539,7 @@ int main(int argc, char** argv) { cerr << "Launch " << clientCount << " " << clientType << " client threads" << endl; - time00 = Util::currentTime(); + time00 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); monitor.notifyAll(); @@ -548,7 +547,7 @@ int main(int argc, char** argv) { monitor.wait(); } - time01 = Util::currentTime(); + time01 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); } int64_t firstTime = 9223372036854775807LL; diff --git a/test/cpp/src/StressTestNonBlocking.cpp b/test/cpp/src/StressTestNonBlocking.cpp index 5f0b293b9b3..ead2df57020 100644 --- a/test/cpp/src/StressTestNonBlocking.cpp +++ b/test/cpp/src/StressTestNonBlocking.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -132,7 +131,7 @@ class ClientThread : public Runnable { } } - _startTime = Util::currentTime(); + _startTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); _transport->open(); @@ -157,7 +156,7 @@ class ClientThread : public Runnable { break; } - _endTime = Util::currentTime(); + _endTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); _transport->close(); @@ -478,7 +477,7 @@ int main(int argc, char** argv) { cerr << "Launch " << clientCount << " client threads" << endl; - time00 = Util::currentTime(); + time00 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); monitor.notifyAll(); @@ -486,7 +485,7 @@ int main(int argc, char** argv) { monitor.wait(); } - time01 = Util::currentTime(); + time01 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); } int64_t firstTime = 9223372036854775807LL; From 6a01d46df606c239e59ed37e723f9bb1309870b4 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 12 Jan 2019 20:11:08 +0800 Subject: [PATCH 156/756] remove unused code --- .../src/thrift/transport/TFileTransport.cpp | 2 -- lib/cpp/src/thrift/windows/config.h | 19 ------------------- 2 files changed, 21 deletions(-) diff --git a/lib/cpp/src/thrift/transport/TFileTransport.cpp b/lib/cpp/src/thrift/transport/TFileTransport.cpp index 19058094c57..5df2778e5e2 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.cpp +++ b/lib/cpp/src/thrift/transport/TFileTransport.cpp @@ -489,8 +489,6 @@ void TFileTransport::writerThread() { if (forced_flush || unflushed > flushMaxBytes_) { flush = true; } else { - struct timeval current_time; - THRIFT_GETTIMEOFDAY(¤t_time, NULL); if (std::chrono::steady_clock::now() > ts_next_flush) { if (unflushed > 0) { flush = true; diff --git a/lib/cpp/src/thrift/windows/config.h b/lib/cpp/src/thrift/windows/config.h index 14a3f4f3691..6a5fd195b24 100644 --- a/lib/cpp/src/thrift/windows/config.h +++ b/lib/cpp/src/thrift/windows/config.h @@ -31,11 +31,6 @@ // Something that defines PRId64 is required to build #define HAVE_INTTYPES_H 1 -// VS2010 or later has stdint.h as does MinGW -#if (_MSC_VER >= 1600) || defined(__MINGW32__) -#define HAVE_STDINT_H 1 -#endif - #ifndef TARGET_WIN_XP #define TARGET_WIN_XP 1 #endif @@ -65,21 +60,7 @@ #define HAVE_GETTIMEOFDAY 1 #define HAVE_SYS_STAT_H 1 -// Must be using VS2010 or later, or boost, so that C99 types are defined in the global namespace -#ifdef HAVE_STDINT_H #include -#else -#include - -typedef boost::int64_t int64_t; -typedef boost::uint64_t uint64_t; -typedef boost::int32_t int32_t; -typedef boost::uint32_t uint32_t; -typedef boost::int16_t int16_t; -typedef boost::uint16_t uint16_t; -typedef boost::int8_t int8_t; -typedef boost::uint8_t uint8_t; -#endif #include #include From c1bfe3d7182c6e61879cfe9568c898c402654962 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 12 Jan 2019 20:15:12 +0800 Subject: [PATCH 157/756] remove WIN XP macros --- lib/cpp/src/thrift/windows/config.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/lib/cpp/src/thrift/windows/config.h b/lib/cpp/src/thrift/windows/config.h index 6a5fd195b24..063a92ad86b 100644 --- a/lib/cpp/src/thrift/windows/config.h +++ b/lib/cpp/src/thrift/windows/config.h @@ -31,19 +31,6 @@ // Something that defines PRId64 is required to build #define HAVE_INTTYPES_H 1 -#ifndef TARGET_WIN_XP -#define TARGET_WIN_XP 1 -#endif - -#if TARGET_WIN_XP -#ifndef WINVER -#define WINVER 0x0501 -#endif -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#endif -#endif - #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0601 #endif From fc222b3a8741eda6f4ec874cf7e7d7b5c69ee630 Mon Sep 17 00:00:00 2001 From: cyy Date: Sat, 12 Jan 2019 23:08:26 +0800 Subject: [PATCH 158/756] remove useless assert code --- lib/cpp/src/thrift/windows/TWinsockSingleton.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp b/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp index d2683b08abb..a502cbdc602 100644 --- a/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp +++ b/lib/cpp/src/thrift/windows/TWinsockSingleton.cpp @@ -20,7 +20,6 @@ #include // boost -#include #include namespace apache { @@ -37,7 +36,6 @@ TWinsockSingleton::TWinsockSingleton(void) { int error(WSAStartup(version, &data)); if (error != 0) { - BOOST_ASSERT(false); throw std::runtime_error("Failed to initialise Winsock."); } } From c349cdb2952497c5a1ecbf1dae84e2ce5aa6db1d Mon Sep 17 00:00:00 2001 From: cyy Date: Sun, 13 Jan 2019 16:01:43 +0800 Subject: [PATCH 159/756] add override and const --- .../src/thrift/transport/TBufferTransports.h | 12 ++++---- lib/cpp/src/thrift/transport/TFileTransport.h | 10 +++---- .../src/thrift/transport/THeaderTransport.h | 4 +-- lib/cpp/src/thrift/transport/THttpClient.h | 2 +- lib/cpp/src/thrift/transport/THttpServer.h | 4 +-- .../transport/TNonblockingServerSocket.h | 4 +-- lib/cpp/src/thrift/transport/TPipe.cpp | 2 +- lib/cpp/src/thrift/transport/TPipe.h | 8 +++--- lib/cpp/src/thrift/transport/TPipeServer.h | 6 ++-- lib/cpp/src/thrift/transport/TSocket.cpp | 2 +- lib/cpp/src/thrift/transport/TSocket.h | 8 +++--- lib/cpp/src/thrift/transport/TTransport.h | 2 +- .../src/thrift/transport/TTransportUtils.cpp | 2 +- .../src/thrift/transport/TTransportUtils.h | 28 +++++++++---------- .../src/thrift/transport/TVirtualTransport.h | 10 +++---- lib/cpp/src/thrift/transport/TZlibTransport.h | 2 +- 16 files changed, 53 insertions(+), 53 deletions(-) diff --git a/lib/cpp/src/thrift/transport/TBufferTransports.h b/lib/cpp/src/thrift/transport/TBufferTransports.h index c423f9cf467..70122753505 100644 --- a/lib/cpp/src/thrift/transport/TBufferTransports.h +++ b/lib/cpp/src/thrift/transport/TBufferTransports.h @@ -235,7 +235,7 @@ class TBufferedTransport : public TVirtualTransport getTransport(std::shared_ptr trans) { + std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new TBufferedTransport(trans)); } }; @@ -354,11 +354,11 @@ class TFramedTransport : public TVirtualTransport transport_->close(); } - virtual uint32_t readSlow(uint8_t* buf, uint32_t len); + uint32_t readSlow(uint8_t* buf, uint32_t len) override; - virtual void writeSlow(const uint8_t* buf, uint32_t len); + void writeSlow(const uint8_t* buf, uint32_t len) override; - virtual void flush(); + void flush() override; uint32_t readEnd(); @@ -430,7 +430,7 @@ class TFramedTransportFactory : public TTransportFactory { /** * Wraps the transport into a framed one. */ - virtual std::shared_ptr getTransport(std::shared_ptr trans) { + std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new TFramedTransport(trans)); } }; diff --git a/lib/cpp/src/thrift/transport/TFileTransport.h b/lib/cpp/src/thrift/transport/TFileTransport.h index 4290eaa6682..e7c1ca626a5 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.h +++ b/lib/cpp/src/thrift/transport/TFileTransport.h @@ -178,14 +178,14 @@ class TFileTransport : public TFileReaderTransport, public TFileWriterTransport // TODO: what is the correct behaviour for this? // the log file is generally always open - bool isOpen() { return true; } + bool isOpen() const override { return true; } void write(const uint8_t* buf, uint32_t len); void flush(); uint32_t readAll(uint8_t* buf, uint32_t len); uint32_t read(uint8_t* buf, uint32_t len); - bool peek(); + bool peek() override; // log-file specific functions void seekToChunk(int32_t chunk); @@ -260,9 +260,9 @@ class TFileTransport : public TFileReaderTransport, public TFileWriterTransport * We cannot use TVirtualTransport to provide these, since we need to inherit * virtually from TTransport. */ - virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { return this->read(buf, len); } - virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { return this->readAll(buf, len); } - virtual void write_virt(const uint8_t* buf, uint32_t len) { this->write(buf, len); } + uint32_t read_virt(uint8_t* buf, uint32_t len) override { return this->read(buf, len); } + uint32_t readAll_virt(uint8_t* buf, uint32_t len) override { return this->readAll(buf, len); } + void write_virt(const uint8_t* buf, uint32_t len) override { this->write(buf, len); } private: // helper functions for writing to a file diff --git a/lib/cpp/src/thrift/transport/THeaderTransport.h b/lib/cpp/src/thrift/transport/THeaderTransport.h index e6c57e67f6a..350702dcf51 100644 --- a/lib/cpp/src/thrift/transport/THeaderTransport.h +++ b/lib/cpp/src/thrift/transport/THeaderTransport.h @@ -103,7 +103,7 @@ class THeaderTransport : public TVirtualTransport getTransport(std::shared_ptr trans) { + std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new THeaderTransport(trans)); } }; diff --git a/lib/cpp/src/thrift/transport/THttpClient.h b/lib/cpp/src/thrift/transport/THttpClient.h index f4fb12a11eb..31f593fcc2f 100644 --- a/lib/cpp/src/thrift/transport/THttpClient.h +++ b/lib/cpp/src/thrift/transport/THttpClient.h @@ -34,7 +34,7 @@ class THttpClient : public THttpTransport { virtual ~THttpClient(); - virtual void flush(); + void flush() override; protected: std::string host_; diff --git a/lib/cpp/src/thrift/transport/THttpServer.h b/lib/cpp/src/thrift/transport/THttpServer.h index c38606f497e..d72cb13cd67 100644 --- a/lib/cpp/src/thrift/transport/THttpServer.h +++ b/lib/cpp/src/thrift/transport/THttpServer.h @@ -32,7 +32,7 @@ class THttpServer : public THttpTransport { virtual ~THttpServer(); - virtual void flush(); + void flush() override; protected: void readHeaders(); @@ -53,7 +53,7 @@ class THttpServerTransportFactory : public TTransportFactory { /** * Wraps the transport into a buffered one. */ - virtual std::shared_ptr getTransport(std::shared_ptr trans) { + std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new THttpServer(trans)); } }; diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h index 1586ff0bc9b..8466512ab57 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h +++ b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h @@ -103,8 +103,8 @@ class TNonblockingServerSocket : public TNonblockingServerTransport { int getListenPort(); - void listen(); - void close(); + void listen() override; + void close() override; protected: std::shared_ptr acceptImpl(); diff --git a/lib/cpp/src/thrift/transport/TPipe.cpp b/lib/cpp/src/thrift/transport/TPipe.cpp index 8a84457db0a..72af4fcd68a 100644 --- a/lib/cpp/src/thrift/transport/TPipe.cpp +++ b/lib/cpp/src/thrift/transport/TPipe.cpp @@ -254,7 +254,7 @@ TPipe::~TPipe() { //--------------------------------------------------------- // Transport callbacks //--------------------------------------------------------- -bool TPipe::isOpen() { +bool TPipe::isOpen() const { return impl_.get() != NULL; } diff --git a/lib/cpp/src/thrift/transport/TPipe.h b/lib/cpp/src/thrift/transport/TPipe.h index aa14f95588c..ba149b109a7 100644 --- a/lib/cpp/src/thrift/transport/TPipe.h +++ b/lib/cpp/src/thrift/transport/TPipe.h @@ -63,16 +63,16 @@ class TPipe : public TVirtualTransport { virtual ~TPipe(); // Returns whether the pipe is open & valid. - virtual bool isOpen(); + bool isOpen() const override; // Checks whether more data is available in the pipe. - virtual bool peek(); + bool peek() override; // Creates and opens the named/anonymous pipe. - virtual void open(); + void open() override; // Shuts down communications on the pipe. - virtual void close(); + void close() override; // Reads from the pipe. virtual uint32_t read(uint8_t* buf, uint32_t len); diff --git a/lib/cpp/src/thrift/transport/TPipeServer.h b/lib/cpp/src/thrift/transport/TPipeServer.h index c9b13e5a6d0..871b6afabd5 100644 --- a/lib/cpp/src/thrift/transport/TPipeServer.h +++ b/lib/cpp/src/thrift/transport/TPipeServer.h @@ -60,9 +60,9 @@ class TPipeServer : public TServerTransport { virtual ~TPipeServer(); // Standard transport callbacks - virtual void interrupt(); - virtual void close(); - virtual void listen(); + void interrupt() override; + void close() override; + void listen() override; // Accessors std::string getPipename(); diff --git a/lib/cpp/src/thrift/transport/TSocket.cpp b/lib/cpp/src/thrift/transport/TSocket.cpp index c6c2bfa0074..6d5f932c511 100644 --- a/lib/cpp/src/thrift/transport/TSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSocket.cpp @@ -190,7 +190,7 @@ bool TSocket::hasPendingDataToRead() { return numBytesAvailable > 0; } -bool TSocket::isOpen() { +bool TSocket::isOpen() const { return (socket_ != THRIFT_INVALID_SOCKET); } diff --git a/lib/cpp/src/thrift/transport/TSocket.h b/lib/cpp/src/thrift/transport/TSocket.h index 4030d4646de..9dcd2d63e14 100644 --- a/lib/cpp/src/thrift/transport/TSocket.h +++ b/lib/cpp/src/thrift/transport/TSocket.h @@ -81,26 +81,26 @@ class TSocket : public TVirtualTransport { * * @return Is the socket alive? */ - virtual bool isOpen(); + bool isOpen() const override; /** * Checks whether there is more data available in the socket to read. * * This call blocks until at least one byte is available or the socket is closed. */ - virtual bool peek(); + bool peek() override; /** * Creates and opens the UNIX socket. * * @throws TTransportException If the socket could not connect */ - virtual void open(); + void open() override; /** * Shuts down communications on the socket. */ - virtual void close(); + void close() override; /** * Determines whether there is pending data to read or not. diff --git a/lib/cpp/src/thrift/transport/TTransport.h b/lib/cpp/src/thrift/transport/TTransport.h index d300f6bdc38..0f922779997 100644 --- a/lib/cpp/src/thrift/transport/TTransport.h +++ b/lib/cpp/src/thrift/transport/TTransport.h @@ -73,7 +73,7 @@ class TTransport { * This is used by a server to check if it should listen for another * request. */ - virtual bool peek() const { return isOpen(); } + virtual bool peek() { return isOpen(); } /** * Opens the transport for communications. diff --git a/lib/cpp/src/thrift/transport/TTransportUtils.cpp b/lib/cpp/src/thrift/transport/TTransportUtils.cpp index 6f47c797295..eedcde1a748 100644 --- a/lib/cpp/src/thrift/transport/TTransportUtils.cpp +++ b/lib/cpp/src/thrift/transport/TTransportUtils.cpp @@ -111,7 +111,7 @@ TPipedFileReaderTransport::TPipedFileReaderTransport( TPipedFileReaderTransport::~TPipedFileReaderTransport() { } -bool TPipedFileReaderTransport::isOpen() { +bool TPipedFileReaderTransport::isOpen() const { return TPipedTransport::isOpen(); } diff --git a/lib/cpp/src/thrift/transport/TTransportUtils.h b/lib/cpp/src/thrift/transport/TTransportUtils.h index 4c82dd3befb..8d67763f8bb 100644 --- a/lib/cpp/src/thrift/transport/TTransportUtils.h +++ b/lib/cpp/src/thrift/transport/TTransportUtils.h @@ -112,9 +112,9 @@ class TPipedTransport : virtual public TTransport { std::free(wBuf_); } - bool isOpen() { return srcTrans_->isOpen(); } + bool isOpen() const override { return srcTrans_->isOpen(); } - bool peek() { + bool peek() override { if (rPos_ >= rLen_) { // Double the size of the underlying buffer if it is full if (rLen_ == rBufSize_) { @@ -132,9 +132,9 @@ class TPipedTransport : virtual public TTransport { return (rLen_ > rPos_); } - void open() { srcTrans_->open(); } + void open() override { srcTrans_->open(); } - void close() { srcTrans_->close(); } + void close() override { srcTrans_->close(); } void setPipeOnRead(bool pipeVal) { pipeOnRead_ = pipeVal; } @@ -181,8 +181,8 @@ class TPipedTransport : virtual public TTransport { * We cannot use TVirtualTransport to provide these, since we need to inherit * virtually from TTransport. */ - virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { return this->read(buf, len); } - virtual void write_virt(const uint8_t* buf, uint32_t len) { this->write(buf, len); } + uint32_t read_virt(uint8_t* buf, uint32_t len) override { return this->read(buf, len); } + void write_virt(const uint8_t* buf, uint32_t len) override { this->write(buf, len); } protected: std::shared_ptr srcTrans_; @@ -216,7 +216,7 @@ class TPipedTransportFactory : public TTransportFactory { /** * Wraps the base transport into a piped transport. */ - virtual std::shared_ptr getTransport(std::shared_ptr srcTrans) { + std::shared_ptr getTransport(std::shared_ptr srcTrans) override { return std::shared_ptr(new TPipedTransport(srcTrans, dstTrans_)); } @@ -246,10 +246,10 @@ class TPipedFileReaderTransport : public TPipedTransport, public TFileReaderTran ~TPipedFileReaderTransport(); // TTransport functions - bool isOpen(); - bool peek(); - void open(); - void close(); + bool isOpen() const override; + bool peek() override; + void open() override; + void close() override; uint32_t read(uint8_t* buf, uint32_t len); uint32_t readAll(uint8_t* buf, uint32_t len); uint32_t readEnd(); @@ -270,9 +270,9 @@ class TPipedFileReaderTransport : public TPipedTransport, public TFileReaderTran * We cannot use TVirtualTransport to provide these, since we need to inherit * virtually from TTransport. */ - virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { return this->read(buf, len); } - virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { return this->readAll(buf, len); } - virtual void write_virt(const uint8_t* buf, uint32_t len) { this->write(buf, len); } + uint32_t read_virt(uint8_t* buf, uint32_t len) override { return this->read(buf, len); } + uint32_t readAll_virt(uint8_t* buf, uint32_t len) override { return this->readAll(buf, len); } + void write_virt(const uint8_t* buf, uint32_t len) override { this->write(buf, len); } protected: // shouldn't be used diff --git a/lib/cpp/src/thrift/transport/TVirtualTransport.h b/lib/cpp/src/thrift/transport/TVirtualTransport.h index 0cacf61d0b7..b5518cc752a 100644 --- a/lib/cpp/src/thrift/transport/TVirtualTransport.h +++ b/lib/cpp/src/thrift/transport/TVirtualTransport.h @@ -84,23 +84,23 @@ class TVirtualTransport : public Super_ { * Implementations of the *_virt() functions, to call the subclass's * non-virtual implementation function. */ - virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { + uint32_t read_virt(uint8_t* buf, uint32_t len) override { return static_cast(this)->read(buf, len); } - virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { + uint32_t readAll_virt(uint8_t* buf, uint32_t len) override { return static_cast(this)->readAll(buf, len); } - virtual void write_virt(const uint8_t* buf, uint32_t len) { + void write_virt(const uint8_t* buf, uint32_t len) override { static_cast(this)->write(buf, len); } - virtual const uint8_t* borrow_virt(uint8_t* buf, uint32_t* len) { + const uint8_t* borrow_virt(uint8_t* buf, uint32_t* len) override { return static_cast(this)->borrow(buf, len); } - virtual void consume_virt(uint32_t len) { static_cast(this)->consume(len); } + void consume_virt(uint32_t len) override { static_cast(this)->consume(len); } /* * Provide a default readAll() implementation that invokes diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.h b/lib/cpp/src/thrift/transport/TZlibTransport.h index b45ec4356da..a9b26642d6f 100644 --- a/lib/cpp/src/thrift/transport/TZlibTransport.h +++ b/lib/cpp/src/thrift/transport/TZlibTransport.h @@ -231,7 +231,7 @@ class TZlibTransportFactory : public TTransportFactory { virtual ~TZlibTransportFactory() {} - virtual std::shared_ptr getTransport(std::shared_ptr trans) { + std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new TZlibTransport(trans)); } }; From 72a878ebe39c3b4611dc2915dbc2080bafa082b3 Mon Sep 17 00:00:00 2001 From: cyy Date: Tue, 15 Jan 2019 14:02:54 +0800 Subject: [PATCH 160/756] change timeous_ms to unsigned type --- lib/cpp/src/thrift/concurrency/Monitor.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cpp/src/thrift/concurrency/Monitor.h b/lib/cpp/src/thrift/concurrency/Monitor.h index c70fc86161e..b3939cb019b 100644 --- a/lib/cpp/src/thrift/concurrency/Monitor.h +++ b/lib/cpp/src/thrift/concurrency/Monitor.h @@ -74,7 +74,7 @@ class Monitor : boost::noncopyable { */ int waitForTimeRelative(const std::chrono::milliseconds &timeout) const; - int waitForTimeRelative(int64_t timeout_ms) const { return waitForTimeRelative(std::chrono::milliseconds(timeout_ms)); } + int waitForTimeRelative(uint64_t timeout_ms) const { return waitForTimeRelative(std::chrono::milliseconds(timeout_ms)); } /** * Waits until the absolute time specified by abstime. @@ -97,7 +97,7 @@ class Monitor : boost::noncopyable { */ void wait(const std::chrono::milliseconds &timeout) const; - void wait(int64_t timeout_ms = 0LL) const { this->wait(std::chrono::milliseconds(timeout_ms)); } + void wait(uint64_t timeout_ms = 0ULL) const { this->wait(std::chrono::milliseconds(timeout_ms)); } /** Wakes up one thread waiting on this monitor. */ virtual void notify() const; From f6460fa00b0d9705ad1b88435aebc5aad9f0da7d Mon Sep 17 00:00:00 2001 From: cyy Date: Tue, 15 Jan 2019 14:30:30 +0800 Subject: [PATCH 161/756] change doc --- CHANGES.md | 1 + lib/cpp/README.md | 12 +++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2dd7f0afcf2..172e9578398 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ ### Breaking Changes +- [THRIFT-4740](https://issues.apache.org/jira/browse/THRIFT-4740) - Uses std::chrono::duration for timeouts in C++ runtime library. - [THRIFT-4702](https://issues.apache.org/jira/browse/THRIFT-4702) - Java class org.apache.thrift.AutoExpandingBuffer is no longer public - [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - Java changes to UTF-8 handling require JDK 1.7 at a minimum - [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - Java class org.apache.thrift.ShortStack is no longer public diff --git a/lib/cpp/README.md b/lib/cpp/README.md index ce46319b915..af37627d2a2 100755 --- a/lib/cpp/README.md +++ b/lib/cpp/README.md @@ -96,13 +96,7 @@ http://monkey.org/~provos/libevent/ ## Windows version compatibility -The Thrift library targets Windows XP for broadest compatbility. A notable -difference is in the Windows-specific implementation of the socket poll -function. To target Vista, Win7 or other versions, comment out the line - - #define TARGET_WIN_XP. - -See Apache Jira THRIFT-2798 for more about TARGET_WIN_XP. +The Thrift library targets Windows 7 or latter versions. The supports for windows XP and Vista are avaiable until 0.12.0. ## Named Pipes @@ -232,6 +226,10 @@ Support for Boost at runtime was deprecated. ## 1.0.0 THRIFT-4720: +The classes Monitor and TimerManager now use std::chrono::milliseconds for timeout, the methods and functions involving THRIFT_TIMESPEC and timeval have been removed, the related tests have been modified. + +Support for Windows XP/Vista has been dropped. + Support for C++03/C++98 has been dropped. Use version 0.12.0 to support that language level. As a consequence, boost is no longer required as a runtime library depenedency, but is is still required to build the runtime library From f7a4ead00d7988e76d2a22758f9e674644582620 Mon Sep 17 00:00:00 2001 From: cyy Date: Wed, 16 Jan 2019 13:40:46 +0800 Subject: [PATCH 162/756] fix warings --- lib/cpp/test/concurrency/TimerManagerTests.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/cpp/test/concurrency/TimerManagerTests.h b/lib/cpp/test/concurrency/TimerManagerTests.h index 24d829acf9b..a922826e93b 100644 --- a/lib/cpp/test/concurrency/TimerManagerTests.h +++ b/lib/cpp/test/concurrency/TimerManagerTests.h @@ -36,7 +36,7 @@ class TimerManagerTests { public: class Task : public Runnable { public: - Task(Monitor& monitor, int64_t timeout) + Task(Monitor& monitor, uint64_t timeout) : _timeout(timeout), _startTime(std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count()), _endTime(0), @@ -72,7 +72,7 @@ class TimerManagerTests { * properly clean up itself and the remaining orphaned timeout task when the * manager goes out of scope and its destructor is called. */ - bool test00(int64_t timeout = 1000LL) { + bool test00(uint64_t timeout = 1000LL) { shared_ptr orphanTask = shared_ptr(new TimerManagerTests::Task(_monitor, 10 * timeout)); @@ -94,7 +94,7 @@ class TimerManagerTests { Synchronized s(_monitor); timerManager.add(orphanTask, 10 * timeout); - THRIFT_SLEEP_USEC(timeout * 1000); + std::this_thread::sleep_for(std::chrono::milliseconds(timeout)); task.reset(new TimerManagerTests::Task(_monitor, timeout)); timerManager.add(task, timeout); @@ -122,7 +122,7 @@ class TimerManagerTests { * verifies that the timer manager properly clean up itself and the remaining orphaned timeout * task when the manager goes out of scope and its destructor is called. */ - bool test01(int64_t timeout = 1000LL) { + bool test01(uint64_t timeout = 1000LL) { TimerManager timerManager; timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); @@ -155,7 +155,7 @@ class TimerManagerTests { * clean up itself and the remaining orphaned timeout task when the manager goes out of scope * and its destructor is called. */ - bool test02(int64_t timeout = 1000LL) { + bool test02(uint64_t timeout = 1000LL) { TimerManager timerManager; timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); @@ -188,7 +188,7 @@ class TimerManagerTests { * verifies that the timer manager properly clean up itself and the remaining orphaned timeout * task when the manager goes out of scope and its destructor is called. */ - bool test03(int64_t timeout = 1000LL) { + bool test03(uint64_t timeout = 1000LL) { TimerManager timerManager; timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); @@ -225,7 +225,7 @@ class TimerManagerTests { /** * This test creates one tasks, and tries to remove it after it has expired. */ - bool test04(int64_t timeout = 1000LL) { + bool test04(uint64_t timeout = 1000LL) { TimerManager timerManager; timerManager.threadFactory(shared_ptr(new ThreadFactory())); timerManager.start(); From 9fed90104ce08b85f7b7d2b9d707cb07562968ff Mon Sep 17 00:00:00 2001 From: cyy Date: Wed, 16 Jan 2019 14:43:51 +0800 Subject: [PATCH 163/756] fix static analyzer warings --- compiler/cpp/src/thrift/generate/t_delphi_generator.cc | 2 -- lib/cpp/src/thrift/server/TNonblockingServer.cpp | 2 +- lib/cpp/test/AllProtocolTests.tcc | 2 +- lib/cpp/test/OneWayHTTPTest.cpp | 2 +- lib/cpp/test/TransportTest.cpp | 2 -- 5 files changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc index 8bd77e84279..737aa5aaab7 100644 --- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc @@ -670,10 +670,8 @@ void t_delphi_generator::create_keywords() { delphi_reserved_method["instancesize"] = 1; delphi_reserved_method["inheritsfrom"] = 1; delphi_reserved_method["methodaddress"] = 1; - delphi_reserved_method["methodaddress"] = 1; delphi_reserved_method["methodname"] = 1; delphi_reserved_method["fieldaddress"] = 1; - delphi_reserved_method["fieldaddress"] = 1; delphi_reserved_method["getinterface"] = 1; delphi_reserved_method["getinterfaceentry"] = 1; delphi_reserved_method["getinterfacetable"] = 1; diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.cpp b/lib/cpp/src/thrift/server/TNonblockingServer.cpp index 31ff2a96a49..bee3e3b4938 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.cpp +++ b/lib/cpp/src/thrift/server/TNonblockingServer.cpp @@ -1285,7 +1285,7 @@ void TNonblockingIOThread::registerEvents() { } bool TNonblockingIOThread::notify(TNonblockingServer::TConnection* conn) { - THRIFT_SOCKET fd = getNotificationSendFD(); + auto fd = getNotificationSendFD(); if (fd < 0) { return false; } diff --git a/lib/cpp/test/AllProtocolTests.tcc b/lib/cpp/test/AllProtocolTests.tcc index a7eab07ca27..80a4ea097ab 100644 --- a/lib/cpp/test/AllProtocolTests.tcc +++ b/lib/cpp/test/AllProtocolTests.tcc @@ -216,7 +216,7 @@ void testProtocol(const char* protoname) { testMessage(); printf("%s => OK\n", protoname); - } catch (TException e) { + } catch (const TException &e) { THRIFT_SNPRINTF(errorMessage, ERR_LEN, "%s => Test FAILED: %s", protoname, e.what()); throw TException(errorMessage); } diff --git a/lib/cpp/test/OneWayHTTPTest.cpp b/lib/cpp/test/OneWayHTTPTest.cpp index 89fa1643106..f369d8ce16f 100644 --- a/lib/cpp/test/OneWayHTTPTest.cpp +++ b/lib/cpp/test/OneWayHTTPTest.cpp @@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE( JSON_BufferedHTTP ) blockable_transport->flush() ; try { client.recv_roundTripRPC() ; - } catch (TTransportException e) { + } catch (const TTransportException &e) { BOOST_ERROR( "we should not get a transport exception -- this means we failed: " + std::string(e.what()) ) ; } transport->close(); diff --git a/lib/cpp/test/TransportTest.cpp b/lib/cpp/test/TransportTest.cpp index 387207142b4..0d900d9dae8 100644 --- a/lib/cpp/test/TransportTest.cpp +++ b/lib/cpp/test/TransportTest.cpp @@ -726,9 +726,7 @@ void test_read_none_available() { BOOST_REQUIRE(transports.in != NULL); BOOST_REQUIRE(transports.out != NULL); - uint8_t write_buf[16]; uint8_t read_buf[16]; - memset(write_buf, 'a', sizeof(write_buf)); // Attempting to read when no data is available should either block until // some data is available, or fail immediately. (e.g., TSocket blocks, From f1eadad76edb3c680b9b964601d440ea05df02ca Mon Sep 17 00:00:00 2001 From: Rob Becker Date: Mon, 21 Jan 2019 20:24:01 -0700 Subject: [PATCH 164/756] THRIFT-4654 Minor fixes for dart 1 & 2 compatibility (backwards compatible) (#1617) * THRIFT-4654 Minor fixes for dart 1 & 2 compatibility * update dockerfiles for CI to test dart 2 * THRIFT-4654 update pubspec for tests * THRIFT-4654 update dart test generator and readme to 1.24.3 * THRIFT-4654 update generated dart sdk to a range * fix the dart tutorials * Add .dart_tool directories to .gitignore * THRIFT-4654: use dart 2.1.0 and fix cross test dart client timeout --- .gitignore | 2 ++ build/docker/ubuntu-bionic/Dockerfile | 4 ++-- build/docker/ubuntu-xenial/Dockerfile | 6 ++--- .../src/thrift/generate/t_dart_generator.cc | 2 +- lib/dart/README.md | 2 +- lib/dart/lib/src/browser/t_web_socket.dart | 7 +++--- lib/dart/lib/src/console/t_web_socket.dart | 7 +++--- .../lib/src/protocol/t_compact_protocol.dart | 4 ++-- .../lib/src/protocol/t_json_protocol.dart | 8 +++---- .../lib/src/serializer/t_deserializer.dart | 4 ++-- lib/dart/lib/src/serializer/t_serializer.dart | 2 +- .../lib/src/transport/t_http_transport.dart | 5 ++--- lib/dart/lib/thrift.dart | 5 +++-- lib/dart/pubspec.yaml | 15 +++++-------- lib/dart/test/protocol/t_protocol_test.dart | 6 ++--- .../transport/t_framed_transport_test.dart | 14 ++++++------ .../test/transport/t_http_transport_test.dart | 12 +++++----- .../transport/t_socket_transport_test.dart | 22 +++++++++---------- test/dart/test_client/pubspec.yaml | 6 ++--- test/tests.json | 2 ++ tutorial/dart/client/pubspec.yaml | 3 +-- tutorial/dart/client/web/index.html | 3 +-- tutorial/dart/console_client/pubspec.yaml | 4 ++-- tutorial/dart/server/pubspec.yaml | 4 ++-- 24 files changed, 72 insertions(+), 77 deletions(-) diff --git a/.gitignore b/.gitignore index b3a5920f2ba..82d3d482da5 100644 --- a/.gitignore +++ b/.gitignore @@ -196,6 +196,7 @@ project.lock.json /lib/d/test/transport_test /lib/d/unittest/ /lib/dart/coverage +/lib/dart/**/.dart_tool /lib/dart/**/.packages /lib/dart/**/packages /lib/dart/**/.pub/ @@ -305,6 +306,7 @@ project.lock.json /test/cpp/TestServer /test/csharp/obj /test/csharp/bin +/test/dart/**/.dart_tool /test/dart/**/.packages /test/dart/**/packages /test/dart/**/.pub/ diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index 43c99a95174..db19112e89f 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -15,7 +15,7 @@ # Using all stock Ubuntu Bionic packaging except for: # - cl: want latest # - d: dmd does not come with Ubuntu -# - dart: does not come with Ubuntu. Pinned to last 1.x release +# - dart: does not come with Ubuntu - we use 2.x here # - dotnet: does not come with Ubuntu # - go: want latest # - nodejs: want v8, bionic comes with v6 @@ -46,7 +46,6 @@ RUN apt-get update && \ RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ /etc/apt/sources.list.d/dart_stable.list -ENV DART_VERSION 1.24.3-1 # dotnet (netcore) RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ @@ -118,6 +117,7 @@ RUN \ mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-openssl-1.1.0h +ENV DART_VERSION 2.1.0-1 RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart=$DART_VERSION diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index 3372b4dbdbb..88895a0c423 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -14,7 +14,7 @@ # Apache Thrift Docker build environment for Ubuntu Xenial # Using all stock Ubuntu Xenial packaging except for: # - d: does not come with Ubuntu so we're installing 2.075.1 for coverage -# - dart: does not come with Ubuntu so we're installing 1.22.1 for coverage +# - dart: does not come with Ubuntu so we're installing 1.24.3 for coverage # - dotnet: does not come with Ubuntu # - go: Xenial comes with 1.6, but we need 1.7 or later # - nodejs: Xenial comes with 4.2.6 which exits LTS April 2018, so we're installing 6.x @@ -50,7 +50,6 @@ RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EBCF975E5BA24D5E && RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ /etc/apt/sources.list.d/dart_stable.list -ENV DART_VERSION 1.22.1-1 # dotnet (core) RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ @@ -120,6 +119,7 @@ RUN curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/v1.1.6+1.0 mv openssl-1.1.6-1.0.1g/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf openssl-1.1.6-1.0.1g +ENV DART_VERSION 1.24.3-1 RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart=$DART_VERSION @@ -127,7 +127,7 @@ ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ - dotnet-sdk-2.1.4 + dotnet-sdk-2.1 RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ diff --git a/compiler/cpp/src/thrift/generate/t_dart_generator.cc b/compiler/cpp/src/thrift/generate/t_dart_generator.cc index 414c333b4b7..c82d26c1017 100644 --- a/compiler/cpp/src/thrift/generate/t_dart_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_dart_generator.cc @@ -423,7 +423,7 @@ void t_dart_generator::generate_dart_pubspec() { indent(f_pubspec) << "environment:" << endl; indent_up(); - indent(f_pubspec) << "sdk: ^1.12.0" << endl; + indent(f_pubspec) << "sdk: '>=1.24.3 <3.0.0'" << endl; indent_down(); f_pubspec << endl; diff --git a/lib/dart/README.md b/lib/dart/README.md index 2be168ba00a..4c30291242a 100644 --- a/lib/dart/README.md +++ b/lib/dart/README.md @@ -23,4 +23,4 @@ under the License. Using Thrift with Dart ==================== -Dart 1.12.0 or newer is required +Dart 1.24.3 or newer is required diff --git a/lib/dart/lib/src/browser/t_web_socket.dart b/lib/dart/lib/src/browser/t_web_socket.dart index 17693b300af..dac9ffddeca 100644 --- a/lib/dart/lib/src/browser/t_web_socket.dart +++ b/lib/dart/lib/src/browser/t_web_socket.dart @@ -18,7 +18,7 @@ library thrift.src.browser; import 'dart:async'; -import 'dart:convert' show BASE64; +import 'package:dart2_constant/convert.dart' show base64; import 'dart:html' show CloseEvent; import 'dart:html' show Event; import 'dart:html' show MessageEvent; @@ -90,7 +90,7 @@ class TWebSocket implements TSocket { void _sendRequests() { while (isOpen && _requests.isNotEmpty) { Uint8List data = _requests.removeAt(0); - _socket.sendString(BASE64.encode(data)); + _socket.sendString(base64.encode(data)); } } @@ -113,8 +113,7 @@ class TWebSocket implements TSocket { void _onMessage(MessageEvent message) { try { - Uint8List data = - new Uint8List.fromList(BASE64.decode(message.data)); + Uint8List data = new Uint8List.fromList(base64.decode(message.data)); _onMessageController.add(data); } on FormatException catch (_) { var error = new TProtocolError(TProtocolErrorType.INVALID_DATA, diff --git a/lib/dart/lib/src/console/t_web_socket.dart b/lib/dart/lib/src/console/t_web_socket.dart index 4ed728444cd..c938a966f4e 100644 --- a/lib/dart/lib/src/console/t_web_socket.dart +++ b/lib/dart/lib/src/console/t_web_socket.dart @@ -18,7 +18,7 @@ library thrift.src.console.t_web_socket; import 'dart:async'; -import 'dart:convert' show BASE64; +import 'package:dart2_constant/convert.dart' show base64; import 'dart:io'; import 'dart:typed_data' show Uint8List; @@ -67,13 +67,12 @@ class TWebSocket implements TSocket { } void send(Uint8List data) { - _socket.add(BASE64.encode(data)); + _socket.add(base64.encode(data)); } void _onMessage(String message) { try { - Uint8List data = - new Uint8List.fromList(BASE64.decode(message)); + Uint8List data = new Uint8List.fromList(base64.decode(message)); _onMessageController.add(data); } on FormatException catch (_) { var error = new TProtocolError(TProtocolErrorType.INVALID_DATA, diff --git a/lib/dart/lib/src/protocol/t_compact_protocol.dart b/lib/dart/lib/src/protocol/t_compact_protocol.dart index 72d7641feeb..ee8094f8e90 100644 --- a/lib/dart/lib/src/protocol/t_compact_protocol.dart +++ b/lib/dart/lib/src/protocol/t_compact_protocol.dart @@ -187,7 +187,7 @@ class TCompactProtocol extends TProtocol { void writeDouble(double d) { if (d == null) d = 0.0; - tempBD.setFloat64(0, d, Endianness.LITTLE_ENDIAN); + tempBD.setFloat64(0, d, Endianness.little); transport.write(tempBD.buffer.asUint8List(), 0, 8); } @@ -364,7 +364,7 @@ class TCompactProtocol extends TProtocol { double readDouble() { transport.readAll(tempList, 0, 8); - return tempList.buffer.asByteData().getFloat64(0, Endianness.LITTLE_ENDIAN); + return tempList.buffer.asByteData().getFloat64(0, Endianness.little); } String readString() { diff --git a/lib/dart/lib/src/protocol/t_json_protocol.dart b/lib/dart/lib/src/protocol/t_json_protocol.dart index 7fbb7c443cc..180568ddf40 100644 --- a/lib/dart/lib/src/protocol/t_json_protocol.dart +++ b/lib/dart/lib/src/protocol/t_json_protocol.dart @@ -155,8 +155,8 @@ class TJsonProtocol extends TProtocol { _context.write(); transport.writeAll(_Constants.QUOTE_BYTES); - String base64 = BASE64.encode(bytes); - transport.writeAll(utf8Codec.encode(base64)); + String base64text = base64.encode(bytes); + transport.writeAll(utf8Codec.encode(base64text)); transport.writeAll(_Constants.QUOTE_BYTES); } @@ -421,9 +421,9 @@ class TJsonProtocol extends TProtocol { Uint8List _readJsonBase64() { // convert UTF-8 bytes of a Base 64 encoded string to binary bytes Uint8List base64Bytes = _readJsonString(); - String base64 = utf8Codec.decode(base64Bytes); + String base64text = utf8Codec.decode(base64Bytes); - return new Uint8List.fromList(BASE64.decode(base64)); + return new Uint8List.fromList(base64.decode(base64text)); } void _readJsonObjectStart() { diff --git a/lib/dart/lib/src/serializer/t_deserializer.dart b/lib/dart/lib/src/serializer/t_deserializer.dart index ed1d139aa2a..aefbee25b52 100644 --- a/lib/dart/lib/src/serializer/t_deserializer.dart +++ b/lib/dart/lib/src/serializer/t_deserializer.dart @@ -26,7 +26,7 @@ class TDeserializer { this.transport = new TBufferedTransport(); if (protocolFactory == null) { - protocolFactory = new TBinaryProtocolFactory(); + protocolFactory = new TBinaryProtocolFactory(); } this.protocol = protocolFactory.getProtocol(this.transport); @@ -41,8 +41,8 @@ class TDeserializer { } void readString(TBase base, String data) { - transport.writeAll(BASE64.decode(data)); + transport.writeAll(base64.decode(data)); transport.flush(); base.read(protocol); diff --git a/lib/dart/lib/src/serializer/t_serializer.dart b/lib/dart/lib/src/serializer/t_serializer.dart index 20ddb6d9725..feec8226d49 100644 --- a/lib/dart/lib/src/serializer/t_serializer.dart +++ b/lib/dart/lib/src/serializer/t_serializer.dart @@ -43,6 +43,6 @@ class TSerializer { Uint8List bytes = transport.consumeWriteBuffer(); - return BASE64.encode(bytes); + return base64.encode(bytes); } } diff --git a/lib/dart/lib/src/transport/t_http_transport.dart b/lib/dart/lib/src/transport/t_http_transport.dart index aa78e9c1587..630213fbfc1 100644 --- a/lib/dart/lib/src/transport/t_http_transport.dart +++ b/lib/dart/lib/src/transport/t_http_transport.dart @@ -44,7 +44,7 @@ class THttpClientTransport extends TBufferedTransport { } Future flush() { - var requestBody = BASE64.encode(consumeWriteBuffer()); + var requestBody = base64.encode(consumeWriteBuffer()); // Use a sync completer to ensure that the buffer can be read immediately // after the read buffer is set, and avoid a race condition where another @@ -56,8 +56,7 @@ class THttpClientTransport extends TBufferedTransport { .then((response) { Uint8List data; try { - data = new Uint8List.fromList( - BASE64.decode(response.body)); + data = new Uint8List.fromList(base64.decode(response.body)); } on FormatException catch (_) { throw new TProtocolError(TProtocolErrorType.INVALID_DATA, "Expected a Base 64 encoded string."); diff --git a/lib/dart/lib/thrift.dart b/lib/dart/lib/thrift.dart index 3d9bb016c27..c429d773cc5 100644 --- a/lib/dart/lib/thrift.dart +++ b/lib/dart/lib/thrift.dart @@ -19,11 +19,12 @@ library thrift; import 'dart:async'; import 'dart:collection'; -import 'dart:convert' show Utf8Codec, BASE64; +import 'dart:convert' show Utf8Codec; import 'dart:typed_data' show ByteData; -import 'dart:typed_data' show Endianness; import 'dart:typed_data' show Uint8List; +import 'package:dart2_constant/convert.dart' show base64; +import 'package:dart2_constant/typed_data.dart' show Endianness; import 'package:fixnum/fixnum.dart'; import 'package:http/http.dart' show Client; import 'package:logging/logging.dart'; diff --git a/lib/dart/pubspec.yaml b/lib/dart/pubspec.yaml index fdc4a0dec39..ded0269c954 100644 --- a/lib/dart/pubspec.yaml +++ b/lib/dart/pubspec.yaml @@ -24,20 +24,15 @@ homepage: http://thrift.apache.org documentation: http://thrift.apache.org environment: - sdk: ">=1.13.0 <2.0.0" + sdk: ">=1.24.3 <3.0.0" dependencies: + dart2_constant: ^1.0.0 fixnum: ^0.10.2 http: ^0.11.3 logging: ^0.11.0 dev_dependencies: - # test - mockito: ^1.0.0 - test: ^0.12.0 - - # dart_dev - https://github.com/Workiva/dart_dev - dart_dev: ^1.5.0 - coverage: ^0.7.3 - dart_style: ">=0.2.4 <0.3.0" - dartdoc: ^0.9.0 + dart_dev: ^2.0.0 + mockito: ">=2.2.2 <4.0.0" + test: ">=0.12.30 <2.0.0" diff --git a/lib/dart/test/protocol/t_protocol_test.dart b/lib/dart/test/protocol/t_protocol_test.dart index 0e6cde50d4a..dc63dbb71c0 100644 --- a/lib/dart/test/protocol/t_protocol_test.dart +++ b/lib/dart/test/protocol/t_protocol_test.dart @@ -18,9 +18,9 @@ library thrift.test.transport.t_json_protocol_test; import 'dart:async'; -import 'dart:convert' show UTF8; import 'dart:typed_data' show Uint8List; +import 'package:dart2_constant/convert.dart' show utf8; import 'package:test/test.dart'; import 'package:thrift/thrift.dart'; @@ -362,7 +362,7 @@ void main() { UTF-8: 0xF0 0x9D 0x84 0x9E UTF-16: 0xD834 0xDD1E */ - var buffer = UTF8.encode(r'"\u0001\u0e01 \ud834\udd1e"'); + var buffer = utf8.encode(r'"\u0001\u0e01 \ud834\udd1e"'); var transport = new TBufferedTransport(); transport.writeAll(buffer); @@ -372,7 +372,7 @@ void main() { var subject = protocol.readString(); expect(subject, - UTF8.decode([0x01, 0xE0, 0xB8, 0x81, 0x20, 0xF0, 0x9D, 0x84, 0x9E])); + utf8.decode([0x01, 0xE0, 0xB8, 0x81, 0x20, 0xF0, 0x9D, 0x84, 0x9E])); }); group('shared tests', sharedTests); diff --git a/lib/dart/test/transport/t_framed_transport_test.dart b/lib/dart/test/transport/t_framed_transport_test.dart index e072e6877ab..7ab4905398e 100644 --- a/lib/dart/test/transport/t_framed_transport_test.dart +++ b/lib/dart/test/transport/t_framed_transport_test.dart @@ -18,9 +18,9 @@ library thrift.test.transport.t_framed_transport_test; import 'dart:async'; -import 'dart:convert'; import 'dart:typed_data' show Uint8List; +import 'package:dart2_constant/convert.dart' show utf8; import 'package:test/test.dart'; import 'package:thrift/thrift.dart'; @@ -66,14 +66,14 @@ void main() { expectNoReadableBytes(); // write first batch of body - socket.messageController.add(new Uint8List.fromList(UTF8.encode("He"))); + socket.messageController.add(new Uint8List.fromList(utf8.encode("He"))); // you shouldn't be able to get any bytes from the read, // because the frame has been consumed internally expectNoReadableBytes(); // write second batch of body - socket.messageController.add(new Uint8List.fromList(UTF8.encode("llo!"))); + socket.messageController.add(new Uint8List.fromList(utf8.encode("llo!"))); // have to wait for the flush to complete, // because it's only then that the frame is available for reading @@ -83,7 +83,7 @@ void main() { // at this point the frame is complete, so we expect the read to complete readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes); expect(readBytes, 6); - expect(readBuffer.sublist(0, 6), UTF8.encode("Hello!")); + expect(readBuffer.sublist(0, 6), utf8.encode("Hello!")); }); test('Test transport reads messages where header is sent in pieces ' @@ -112,14 +112,14 @@ void main() { readBytes = expectNoReadableBytes(); // write first batch of body - socket.messageController.add(new Uint8List.fromList(UTF8.encode("H"))); + socket.messageController.add(new Uint8List.fromList(utf8.encode("H"))); // you shouldn't be able to get any bytes from the read, // because the frame has been consumed internally expectNoReadableBytes(); // write second batch of body - socket.messageController.add(new Uint8List.fromList(UTF8.encode("i!"))); + socket.messageController.add(new Uint8List.fromList(utf8.encode("i!"))); // have to wait for the flush to complete, // because it's only then that the frame is available for reading @@ -129,7 +129,7 @@ void main() { // at this point the frame is complete, so we expect the read to complete readBytes = transport.read(readBuffer, 0, readBuffer.lengthInBytes); expect(readBytes, 3); - expect(readBuffer.sublist(0, 3), UTF8.encode("Hi!")); + expect(readBuffer.sublist(0, 3), utf8.encode("Hi!")); }); }); } diff --git a/lib/dart/test/transport/t_http_transport_test.dart b/lib/dart/test/transport/t_http_transport_test.dart index 66f3d054bed..03ccede9ab5 100644 --- a/lib/dart/test/transport/t_http_transport_test.dart +++ b/lib/dart/test/transport/t_http_transport_test.dart @@ -19,9 +19,10 @@ library thrift.test.transport.t_socket_transport_test; import 'dart:async'; import 'dart:convert' show Encoding; -import 'dart:convert' show Utf8Codec, BASE64; +import 'dart:convert' show Utf8Codec; import 'dart:typed_data' show Uint8List; +import 'package:dart2_constant/convert.dart' show base64; import 'package:http/http.dart' show BaseRequest; import 'package:http/http.dart' show Client; import 'package:http/http.dart' show Response; @@ -52,15 +53,14 @@ void main() { expect(client.postRequest, isNotEmpty); - var requestText = - utf8Codec.decode(BASE64.decode(client.postRequest)); + var requestText = utf8Codec.decode(base64.decode(client.postRequest)); expect(requestText, expectedText); }); test('Test transport receives response', () async { var expectedText = 'my response'; var expectedBytes = utf8Codec.encode(expectedText); - client.postResponse = BASE64.encode(expectedBytes); + client.postResponse = base64.encode(expectedBytes); transport.writeAll(utf8Codec.encode('my request')); expect(transport.hasReadData, isFalse); @@ -94,7 +94,7 @@ void main() { // prepare a response transport.writeAll(utf8Codec.encode('request 1')); - client.postResponse = BASE64.encode(expectedBytes); + client.postResponse = base64.encode(expectedBytes); Future responseReady = transport.flush().then((_) { var buffer = new Uint8List(expectedBytes.length); @@ -105,7 +105,7 @@ void main() { // prepare a second response transport.writeAll(utf8Codec.encode('request 2')); var response2Bytes = utf8Codec.encode('response 2'); - client.postResponse = BASE64.encode(response2Bytes); + client.postResponse = base64.encode(response2Bytes); await transport.flush(); await responseReady; diff --git a/lib/dart/test/transport/t_socket_transport_test.dart b/lib/dart/test/transport/t_socket_transport_test.dart index 929ab17b1a7..90bffbe5434 100644 --- a/lib/dart/test/transport/t_socket_transport_test.dart +++ b/lib/dart/test/transport/t_socket_transport_test.dart @@ -18,9 +18,11 @@ library thrift.test.transport.t_socket_transport_test; import 'dart:async'; -import 'dart:convert' show Utf8Codec, BASE64; +import 'dart:convert' show Utf8Codec; import 'dart:typed_data' show Uint8List; +import 'package:dart2_constant/convert.dart' show base64; +import 'package:dart2_constant/core.dart' as core; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; import 'package:thrift/thrift.dart'; @@ -30,14 +32,13 @@ void main() { final requestText = 'my test request'; final requestBytes = new Uint8List.fromList(utf8Codec.encode(requestText)); - final requestBase64 = BASE64.encode(requestBytes); + final requestBase64 = base64.encode(requestBytes); final responseText = 'response 1'; final responseBytes = new Uint8List.fromList(utf8Codec.encode(responseText)); - final responseBase64 = BASE64.encode(responseBytes); + final responseBase64 = base64.encode(responseBytes); - final framedResponseBase64 = - BASE64.encode(_getFramedResponse(responseBytes)); + final framedResponseBase64 = base64.encode(_getFramedResponse(responseBytes)); group('TClientSocketTransport', () { FakeSocket socket; @@ -117,7 +118,7 @@ void main() { protocolFactory.message = new TMessage('foo', TMessageType.CALL, 123); transport = new TAsyncClientSocketTransport( socket, new TMessageReader(protocolFactory), - responseTimeout: Duration.ZERO); + responseTimeout: core.Duration.zero); await transport.open(); transport.writeAll(requestBytes); }); @@ -139,7 +140,7 @@ void main() { var response2Text = 'response 2'; var response2Bytes = new Uint8List.fromList(utf8Codec.encode(response2Text)); - var response2Base64 = BASE64.encode(response2Bytes); + var response2Base64 = base64.encode(response2Bytes); protocolFactory.message = new TMessage('foo2', TMessageType.REPLY, 124); socket.receiveFakeMessage(response2Base64); @@ -169,7 +170,7 @@ void main() { transport = new TFramedTransport(new TAsyncClientSocketTransport( socket, messageReader, - responseTimeout: Duration.ZERO)); + responseTimeout: core.Duration.zero)); await transport.open(); transport.writeAll(requestBytes); }); @@ -275,11 +276,10 @@ class FakeSocket extends TSocket { _sendPayload = data; } - void receiveFakeMessage(String base64) { + void receiveFakeMessage(String base64text) { if (!isOpen) throw new StateError('The socket is not open'); - var message = - new Uint8List.fromList(BASE64.decode(base64)); + var message = new Uint8List.fromList(base64.decode(base64text)); _onMessageController.add(message); } } diff --git a/test/dart/test_client/pubspec.yaml b/test/dart/test_client/pubspec.yaml index d1642f88b70..113054a24cf 100644 --- a/test/dart/test_client/pubspec.yaml +++ b/test/dart/test_client/pubspec.yaml @@ -22,10 +22,10 @@ author: Apache Thrift Developers homepage: http://thrift.apache.org environment: - sdk: ">=1.13.0 <2.0.0" + sdk: ">=1.24.3 <3.0.0" dependencies: - args: ^0.13.0 + args: ">=0.13.0 <2.0.0" http: ^0.11.0 thrift: path: ../../../lib/dart @@ -33,4 +33,4 @@ dependencies: path: ../gen-dart/thrift_test dev_dependencies: - test: "^0.12.0" + test: ">=0.12.30 <2.0.0" diff --git a/test/tests.json b/test/tests.json index 43d6dedae20..3381a1faf87 100644 --- a/test/tests.json +++ b/test/tests.json @@ -562,6 +562,7 @@ { "name": "dart", "client": { + "timeout": 15, "transports": [ "buffered", "framed", @@ -577,6 +578,7 @@ ], "command": [ "dart", + "--enable-asserts", "test_client/bin/main.dart" ] }, diff --git a/tutorial/dart/client/pubspec.yaml b/tutorial/dart/client/pubspec.yaml index d8ede14409a..109db0f65e7 100644 --- a/tutorial/dart/client/pubspec.yaml +++ b/tutorial/dart/client/pubspec.yaml @@ -22,10 +22,9 @@ author: Apache Thrift Developers homepage: http://thrift.apache.org environment: - sdk: ">=1.13.0 <2.0.0" + sdk: ">=1.13.0 <3.0.0" dependencies: - browser: ^0.10.0 shared: path: ../gen-dart/shared thrift: diff --git a/tutorial/dart/client/web/index.html b/tutorial/dart/client/web/index.html index 64b184e5561..9d36b4388a5 100644 --- a/tutorial/dart/client/web/index.html +++ b/tutorial/dart/client/web/index.html @@ -24,8 +24,7 @@ Thrift Tutorial - - + diff --git a/tutorial/dart/console_client/pubspec.yaml b/tutorial/dart/console_client/pubspec.yaml index a34e26f607e..602bb5e1036 100644 --- a/tutorial/dart/console_client/pubspec.yaml +++ b/tutorial/dart/console_client/pubspec.yaml @@ -23,10 +23,10 @@ author: Apache Thrift Developers homepage: http://thrift.apache.org environment: - sdk: ">=1.13.0 <2.0.0" + sdk: ">=1.13.0 <3.0.0" dependencies: - args: ^0.13.0 + args: ">=0.13.0 <2.0.0" collection: ^1.1.0 shared: path: ../gen-dart/shared diff --git a/tutorial/dart/server/pubspec.yaml b/tutorial/dart/server/pubspec.yaml index 18d0737f314..b0b012d09af 100644 --- a/tutorial/dart/server/pubspec.yaml +++ b/tutorial/dart/server/pubspec.yaml @@ -22,10 +22,10 @@ author: Apache Thrift Developers homepage: http://thrift.apache.org environment: - sdk: ">=1.13.0 <2.0.0" + sdk: ">=1.13.0 <3.0.0" dependencies: - args: ^0.13.0 + args: ">=0.13.0 <2.0.0" shared: path: ../gen-dart/shared thrift: From c28a739b8cb62fca9ea869d8d157c0b1d64565b8 Mon Sep 17 00:00:00 2001 From: Renan Cakirerk Date: Mon, 21 Jan 2019 16:25:10 -0800 Subject: [PATCH 165/756] THRIFT-4747: The 'omitempty' tag should not be appended to optional fields that have a default value --- compiler/cpp/src/thrift/generate/t_go_generator.cc | 8 +++++++- lib/go/test/GoTagTest.thrift | 1 + lib/go/test/tests/gotag_test.go | 9 +++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index ec16b87b87b..11246f36247 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -1338,7 +1338,13 @@ void t_go_generator::generate_go_struct_definition(ostream& out, t_type* fieldType = (*m_iter)->get_type(); string goType = type_to_go_type_with_opt(fieldType, is_pointer_field(*m_iter)); string gotag = "db:\"" + escape_string((*m_iter)->get_name()) + "\" "; - if ((*m_iter)->get_req() == t_field::T_OPTIONAL) { + + // Only add the `omitempty` tag if this field is optional and has no default value. + // Otherwise a proper value like `false` for a bool field will be ommitted from + // the JSON output since Go Marshal won't output `zero values`. + bool has_default = (*m_iter)->get_value(); + bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL; + if (is_optional && !has_default) { gotag += "json:\"" + escape_string((*m_iter)->get_name()) + ",omitempty\""; } else { gotag += "json:\"" + escape_string((*m_iter)->get_name()) + "\""; diff --git a/lib/go/test/GoTagTest.thrift b/lib/go/test/GoTagTest.thrift index 508b3b6c3ec..5667c6e54ed 100644 --- a/lib/go/test/GoTagTest.thrift +++ b/lib/go/test/GoTagTest.thrift @@ -21,4 +21,5 @@ struct tagged { 1: string string_thing, 2: i64 int_thing (go.tag = "json:\"int_thing,string\""), 3: optional i64 optional_int_thing + 4: optional bool optional_bool_thing = false } diff --git a/lib/go/test/tests/gotag_test.go b/lib/go/test/tests/gotag_test.go index 32f056ff6e6..ff2f14ecf34 100644 --- a/lib/go/test/tests/gotag_test.go +++ b/lib/go/test/tests/gotag_test.go @@ -51,3 +51,12 @@ func TestOptionalTag(t *testing.T) { t.Error("Unexpected default tag value for optional field") } } + +func TestOptionalTagWithDefaultValue(t *testing.T) { + s := gotagtest.Tagged{} + st := reflect.TypeOf(s) + field, ok := st.FieldByName("OptionalBoolThing") + if !ok || field.Tag.Get("json") != "optional_bool_thing" { + t.Error("Unexpected default tag value for optional field that has a default value") + } +} From cd9e8c9bf75d7aaae7fed1cf3e19f8d25e49a2cf Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 22 Jan 2019 00:00:53 -0500 Subject: [PATCH 166/756] update docker readme file [ci skip] --- build/docker/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build/docker/README.md b/build/docker/README.md index d00f87d66fd..56b98a9ded7 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -167,7 +167,7 @@ Last updated: October 1, 2017 | Language | ubuntu-xenial | ubuntu-bionic | Notes | | :-------- | :------------ | :------------ | :---- | -| as of | Mar 06, 2018 | Jan 4, 2019 | | +| as of | Mar 06, 2018 | Jan 21, 2019 | | | as3 | | | Not in CI | | C++ gcc | 5.4.0 | 7.3.0 | | | C++ clang | 3.8 | 6.0 | | @@ -175,23 +175,23 @@ Last updated: October 1, 2017 | c_glib | 2.48.2 | 2.56.0 | | | cl (sbcl) | | 1.4.15 | | | d | 2.075.1 | 2.083.1 | | -| dart | 1.22.1 | 1.24.3 | | +| dart | 1.24.3 | 2.1.0 | | | delphi | | | Not in CI | -| dotnet | 2.1.4 | 2.2.101 | | +| dotnet | 2.1.503 | 2.2.103 | | | erlang | 18.3 | 20.2.2 | | | go | 1.7.6 | 1.11.4 | | | haskell | 7.10.3 | 8.0.2 | | | haxe | 3.2.1 | 3.4.4 | THRIFT-4352: avoid 3.4.2 | -| java | 1.8.0_151 | 1.8.0_191 | | +| java | 1.8.0_191 | 1.8.0_191 | | | js | | | Unsure how to look for version info? | | lua | 5.2.4 | 5.2.4 | Lua 5.3: see THRIFT-4386 | -| nodejs | 6.13.0 | 8.15.0 | | +| nodejs | 6.16.0 | 8.15.0 | | | ocaml | | 4.05.0 | THRIFT-4517: ocaml 4.02.3 on xenial appears broken | | perl | 5.22.1 | 5.26.1 | | -| php | 7.0.22 | 7.2.10 | | +| php | 7.0.32 | 7.2.10 | | | python | 2.7.12 | 2.7.15rc1 | | | python3 | 3.5.2 | 3.6.7 | | | ruby | 2.3.1p112 | 2.5.1p57 | | -| rust | 1.17.0 | 1.30.0 | | +| rust | 1.30.0 | 1.30.0 | | | smalltalk | | | Not in CI | | swift | | 4.2.1 | | From 8cd3f92ff7c0104c6b460c19c16aca3cefcf517a Mon Sep 17 00:00:00 2001 From: cyy Date: Tue, 22 Jan 2019 16:28:15 +0800 Subject: [PATCH 167/756] fix c++17 building on windows --- build/cmake/DefineCMakeDefaults.cmake | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build/cmake/DefineCMakeDefaults.cmake b/build/cmake/DefineCMakeDefaults.cmake index 67143575103..2b0cdbb94b3 100644 --- a/build/cmake/DefineCMakeDefaults.cmake +++ b/build/cmake/DefineCMakeDefaults.cmake @@ -79,3 +79,14 @@ endif() if (NOT DEFINED CMAKE_CXX_EXTENSIONS) set(CMAKE_CXX_EXTENSIONS OFF) # use standards compliant language level for portability endif() + +if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + include(CheckCXXCompilerFlag) + set(CMAKE_REQUIRED_QUIET ON) + check_cxx_compiler_flag("/Zc:__cplusplus" res_var) + if (res_var) + # Make MSVC reporting correct value for __cplusplus + # See https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/ + add_compile_options("/Zc:__cplusplus") + endif() +endif() From 5870cc81e8c716cf938c8f077549548885d30dcd Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 22 Jan 2019 09:37:31 -0500 Subject: [PATCH 168/756] Change Travis CI to use three cross test jobs again as we hit the 90 minute limit we had negotiated. --- .travis.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 75685d55e32..255f1d93b1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,15 +68,6 @@ jobs: # ========================= stage: thrift ======================= # ------------------------- phase: cross ------------------------ - # apache/thrift official PR builds can exceed 50 minutes per job so combine all cross tests - - stage: thrift - script: build/docker/run.sh - if: repo = apache/thrift - env: - - JOB="Cross Language Tests" - - SCRIPT="cross-test.sh" - - # fork based PR builds cannot exceed 50 minutes per job - stage: thrift script: build/docker/run.sh if: repo != apache/thrift From b2a4afec2ac11ee78bc4f094e552150191316258 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 22 Jan 2019 09:38:17 -0500 Subject: [PATCH 169/756] fix travis CI cross --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 255f1d93b1e..5b931406adf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -70,7 +70,6 @@ jobs: # ------------------------- phase: cross ------------------------ - stage: thrift script: build/docker/run.sh - if: repo != apache/thrift env: - JOB="Cross Language Tests (Binary Protocol)" - SCRIPT="cross-test.sh" @@ -78,7 +77,6 @@ jobs: - stage: thrift script: build/docker/run.sh - if: repo != apache/thrift env: - JOB="Cross Language Tests (Header, JSON Protocols)" - SCRIPT="cross-test.sh" @@ -86,7 +84,6 @@ jobs: - stage: thrift script: build/docker/run.sh - if: repo != apache/thrift env: - JOB="Cross Language Tests (Compact and Multiplexed Protocols)" - SCRIPT="cross-test.sh" From 0cd2099fa327caca294f4bf83ac85aa924e2db47 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 22 Jan 2019 09:50:26 -0500 Subject: [PATCH 170/756] THRIFT-4748: add jitpack support [ci skip] --- jitpack.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 jitpack.yml diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 00000000000..a640d5d8edf --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,2 @@ +install: + - gradle -Prelease=true -p lib/java/ clean install From 0c93bb69032e7dd234a15efc75c19e9eecd27276 Mon Sep 17 00:00:00 2001 From: Mustafa Senol Cosar Date: Wed, 16 Jan 2019 15:03:12 +0300 Subject: [PATCH 171/756] THRIFT-4738: Fix typescript declaration generation --- .../cpp/src/thrift/generate/t_js_generator.cc | 62 +++++++++++++------ 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc index fc23e87358b..f8f1beed89a 100644 --- a/compiler/cpp/src/thrift/generate/t_js_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc @@ -206,6 +206,7 @@ class t_js_generator : public t_oop_generator { std::string ts_includes(); std::string ts_service_includes(); std::string render_includes(); + std::string render_ts_includes(); std::string declare_field(t_field* tfield, bool init = false, bool obj = false); std::string function_signature(t_function* tfunction, std::string prefix = "", @@ -287,7 +288,7 @@ class t_js_generator : public t_oop_generator { * TypeScript Definition File helper functions */ - string ts_function_signature(t_function* tfunction, bool include_callback, bool optional_callback); + string ts_function_signature(t_function* tfunction, bool include_callback); string ts_get_type(t_type* type); /** @@ -510,6 +511,27 @@ string t_js_generator::render_includes() { return result; } +/** + * Renders all the imports necessary for including another Thrift program + */ +string t_js_generator::render_ts_includes() { + string result; + + if (!gen_node_) { + return result; + } + const vector& includes = program_->get_includes(); + for (size_t i = 0; i < includes.size(); ++i) { + result += "import " + make_valid_nodeJs_identifier(includes[i]->get_name()) + "_ttypes = require('./" + includes[i]->get_name() + + "_types');\n"; + } + if (includes.size() > 0) { + result += "\n"; + } + + return result; +} + /** * Close up (or down) some filez. */ @@ -1117,7 +1139,7 @@ void t_js_generator::generate_service(t_service* tservice) { f_service_ts_ << "/// get_extends()->get_name() << ".d.ts\" />" << endl; } - f_service_ts_ << autogen_comment() << endl << ts_includes() << endl << endl; + f_service_ts_ << autogen_comment() << endl << ts_includes() << endl << render_ts_includes() << endl; if (gen_node_) { f_service_ts_ << "import ttypes = require('./" + program_->get_name() + "_types');" << endl; // Generate type aliases @@ -1219,9 +1241,9 @@ void t_js_generator::generate_service_processor(t_service* tservice) { } f_service_ts_ << "{" << endl; indent_up(); - f_service_ts_ << ts_indent() << "private _handler: Object;" << endl << endl; - f_service_ts_ << ts_indent() << "constructor(handler: Object);" << endl; - f_service_ts_ << ts_indent() << "process(input: Thrift.TJSONProtocol, output: Thrift.TJSONProtocol): void;" << endl; + f_service_ts_ << ts_indent() << "private _handler: object;" << endl << endl; + f_service_ts_ << ts_indent() << "constructor(handler: object);" << endl; + f_service_ts_ << ts_indent() << "process(input: thrift.TProtocol, output: thrift.TProtocol): void;" << endl; indent_down(); } } else { @@ -1325,7 +1347,7 @@ void t_js_generator::generate_process_function(t_service* tservice, t_function* } if (gen_ts_) { indent_up(); - f_service_ts_ << ts_indent() << "process_" << tfunction->get_name() << "(seqid: number, input: Thrift.TJSONProtocol, output: Thrift.TJSONProtocol): void;" << endl; + f_service_ts_ << ts_indent() << "process_" << tfunction->get_name() << "(seqid: number, input: thrift.TProtocol, output: thrift.TProtocol): void;" << endl; indent_down(); } @@ -1645,10 +1667,11 @@ void t_js_generator::generate_service_client(t_service* tservice) { indent(f_service_) << "this._seqid = 0;" << endl; indent(f_service_) << "this._reqs = {};" << endl; if (gen_ts_) { - f_service_ts_ << ts_indent() << "private input: Thrift.TJSONProtocol;" << endl << ts_indent() - << "private output: Thrift.TJSONProtocol;" << endl << ts_indent() << "private seqid: number;" - << endl << endl << ts_indent() - << "constructor(input: Thrift.TJSONProtocol, output?: Thrift.TJSONProtocol);" + f_service_ts_ << ts_indent() << "private output: thrift.TTransport;" << endl + << ts_indent() << "private pClass: thrift.TProtocol;" << endl + << ts_indent() << "private _seqid: number;" << endl + << endl + << ts_indent() << "constructor(output: thrift.TTransport, pClass: { new(trans: thrift.TTransport): thrift.TProtocol });" << endl; } } else { @@ -1719,13 +1742,13 @@ void t_js_generator::generate_service_client(t_service* tservice) { if (gen_ts_) { // function definition without callback - f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, false, false) << endl; + f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, false) << endl; if (!gen_es6_) { // overload with callback - f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, true, false) << endl; + f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, true) << endl; } else { // overload with callback - f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, true, true) << endl; + f_service_ts_ << ts_print_doc(*f_iter) << ts_indent() << ts_function_signature(*f_iter, true) << endl; } } @@ -2669,7 +2692,7 @@ string t_js_generator::ts_get_type(t_type* type) { * @param bool in-/exclude the callback argument * @return String of rendered function definition */ -std::string t_js_generator::ts_function_signature(t_function* tfunction, bool include_callback, bool optional_callback) { +std::string t_js_generator::ts_function_signature(t_function* tfunction, bool include_callback) { string str; const vector& fields = tfunction->get_arglist()->get_members(); vector::const_iterator f_iter; @@ -2685,7 +2708,6 @@ std::string t_js_generator::ts_function_signature(t_function* tfunction, bool in } if (include_callback) { - string callback_optional_string = optional_callback ? "?" : ""; if (gen_node_) { t_struct* exceptions = tfunction->get_xceptions(); string exception_types; @@ -2694,19 +2716,19 @@ std::string t_js_generator::ts_function_signature(t_function* tfunction, bool in for (vector::const_iterator it = members.begin(); it != members.end(); ++it) { t_type* t = get_true_type((*it)->get_type()); if (it == members.begin()) { - exception_types = t->get_name(); + exception_types = js_type_namespace(t->get_program()) + t->get_name(); } else { - exception_types += " | " + t->get_name(); + exception_types += " | " + js_type_namespace(t->get_program()) + t->get_name(); } } } if (exception_types == "") { - str += "callback" + callback_optional_string + ": (error: void, response: " + ts_get_type(tfunction->get_returntype()) + ")=>void): "; + str += "callback?: (error: void, response: " + ts_get_type(tfunction->get_returntype()) + ")=>void): "; } else { - str += "callback" + callback_optional_string + ": (error: " + exception_types + ", response: " + ts_get_type(tfunction->get_returntype()) + ")=>void): "; + str += "callback?: (error: " + exception_types + ", response: " + ts_get_type(tfunction->get_returntype()) + ")=>void): "; } } else { - str += "callback" + callback_optional_string + ": (data: " + ts_get_type(tfunction->get_returntype()) + ")=>void): "; + str += "callback?: (data: " + ts_get_type(tfunction->get_returntype()) + ")=>void): "; } if (gen_jquery_) { From 98f379ece17c8acb6a91cb3fd5b16acc3f0d1698 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 22 Jan 2019 09:22:04 -0500 Subject: [PATCH 172/756] THRIFT-4746: changes for publishing java library to maven; fix java debug vs. release build with cmake --- .travis.yml | 6 ++++++ lib/java/CMakeLists.txt | 17 ++++++++++++----- lib/java/README.md | 6 +++++- lib/java/build.gradle | 11 +++++------ lib/java/gradle.properties | 6 +++--- lib/java/gradle/publishing.gradle | 4 ++-- .../gradle/wrapper/gradle-wrapper.properties | 2 +- test/dart/test_client/bin/main.dart | 2 +- test/tests.json | 7 ++++--- 9 files changed, 39 insertions(+), 22 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5b931406adf..aecdd130ac0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -123,6 +123,12 @@ jobs: - script: build/docker/run.sh env: - JOB="CMake" + - BUILD_ARG="-DCMAKE_BUILD_TYPE=Debug" + + - script: build/docker/run.sh + env: + - JOB="CMake" + - BUILD_ARG="-DCMAKE_BUILD_TYPE=Release" # C++ specific options: compiler plug-in, threading model - script: build/docker/run.sh diff --git a/lib/java/CMakeLists.txt b/lib/java/CMakeLists.txt index 46064e6008a..a67845aba5d 100644 --- a/lib/java/CMakeLists.txt +++ b/lib/java/CMakeLists.txt @@ -18,6 +18,7 @@ # if(ANDROID) + set(THRIFT_AAR outputs/aar/thrift-debug.aar outputs/aar/thrift-release.aar) add_custom_command( OUTPUT ${THRIFT_AAR} @@ -27,7 +28,7 @@ if(ANDROID) ) add_custom_target(thrift_aar ALL DEPENDS ${THRIFT_AAR}) -else(ANDROID) +else() if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") set(JAVA_INSTALL_DIR "${LIB_INSTALL_DIR}/java") @@ -41,11 +42,16 @@ else(ANDROID) set(JAVA_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}/java") endif() + set(PRELEASE "true") + if (CMAKE_BUILD_TYPE MATCHES DEBUG) + set(PRELEASE "false") + endif () + add_custom_target(ThriftJava ALL COMMENT "Building Java library using Gradle Wrapper" COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} assemble --console=plain --no-daemon - -Prelease=true + -Prelease=${PRELEASE} -Pthrift.version=${thrift_VERSION} "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} @@ -56,7 +62,7 @@ else(ANDROID) COMMENT "Publishing Java Library to Apache Maven staging" COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} clean uploadArchives --console=plain --no-daemon - -Prelease=true + -Prelease=${PRELEASE} -Pthrift.version=${thrift_VERSION} "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} @@ -78,10 +84,11 @@ else(ANDROID) add_test(NAME JavaTest COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} test --console=plain --no-daemon - -Prelease=true + -Prelease=${PRELEASE} -Pthrift.version=${thrift_VERSION} "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" "-Pthrift.compiler=${THRIFT_COMPILER}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endif() -endif(ANDROID) + +endif() diff --git a/lib/java/README.md b/lib/java/README.md index 505746508ce..7dca456204f 100644 --- a/lib/java/README.md +++ b/lib/java/README.md @@ -138,11 +138,15 @@ properties to it. mavenUser=meMyselfAndI mavenPassword=MySuperAwesomeSecretPassword +NOTE: If you do not have a secring.gpg file, see the +[gradle signing docs](https://docs.gradle.org/current/userguide/signing_plugin.html) +for instructions on how to generate it. + It is also possible to manually publish using the Gradle build directly. With the key information and credentials in place the following will generate if needed the build artifacts and proceed to publish the results. - ./gradlew -Prelease=true -Pthrift.version=0.11.0 uploadArchives + ./gradlew -Prelease=true uploadArchives It is also possible to override the target repository for the Maven Publication by using a Gradle property, for example you can publish signed JAR files to your diff --git a/lib/java/build.gradle b/lib/java/build.gradle index 4302f779db4..5f0d2782bee 100644 --- a/lib/java/build.gradle +++ b/lib/java/build.gradle @@ -20,13 +20,14 @@ // Using the legacy plugin classpath for Clover so it can be loaded optionally buildscript { repositories { + mavenCentral() google() jcenter() gradlePluginPortal() } dependencies { - classpath 'com.bmuschko:gradle-clover-plugin:2.2.0' + classpath 'com.bmuschko:gradle-clover-plugin:2.2.1' } } @@ -34,7 +35,7 @@ plugins { id 'java' id 'maven' id 'signing' - id 'com.github.johnrengelman.shadow' version '2.0.2' + id 'com.github.johnrengelman.shadow' version '4.0.4' } description = 'Apache Thrift Java Library' @@ -44,12 +45,10 @@ defaultTasks 'build' // Version components for this project group = property('thrift.groupid') -// Drop the -dev suffix, we use the SNAPSHOT suffix for non-release versions -def parsedVersion = property('thrift.version').toString().replace('-dev', '') if (Boolean.parseBoolean(project.release)) { - version = parsedVersion + version = property('thrift.version') } else { - version = parsedVersion + '-SNAPSHOT' + version = property('thrift.version') + '-SNAPSHOT' } // Keeping the rest of the build logic in functional named scripts for clarity diff --git a/lib/java/gradle.properties b/lib/java/gradle.properties index 056a96e8d7c..55256104f3b 100644 --- a/lib/java/gradle.properties +++ b/lib/java/gradle.properties @@ -3,7 +3,7 @@ # the properties to minimize the changes in the dependencies. thrift.version=1.0.0 thrift.groupid=org.apache.thrift -release=true +release=false # Local Install paths install.path=/usr/local/lib @@ -25,9 +25,9 @@ maven-repository-url=https://repository.apache.org/service/local/staging/deploy/ maven-repository-id=apache.releases.https # Dependency versions -httpclient.version=4.4.1 +httpclient.version=4.5.6 httpcore.version=4.4.1 -slf4j.version=1.7.12 +slf4j.version=1.7.25 servlet.version=2.5 junit.version=4.12 mockito.version=1.9.5 diff --git a/lib/java/gradle/publishing.gradle b/lib/java/gradle/publishing.gradle index 6b0404373d1..029bff93d77 100644 --- a/lib/java/gradle/publishing.gradle +++ b/lib/java/gradle/publishing.gradle @@ -61,9 +61,9 @@ def configurePom(pom) { url 'http://thrift.apache.org' scm { - url 'https://github.com/apache/thrift.git' + url 'https://github.com/apache/thrift' connection 'scm:git:https://github.com/apache/thrift.git' - developerConnection 'scm:git:https://github.com/apache/thrift.git' + developerConnection 'scm:git:git@github.com:apache/thrift.git' } licenses { diff --git a/lib/java/gradle/wrapper/gradle-wrapper.properties b/lib/java/gradle/wrapper/gradle-wrapper.properties index 2c2bbe5f9a8..826c82f1217 100644 --- a/lib/java/gradle/wrapper/gradle-wrapper.properties +++ b/lib/java/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip diff --git a/test/dart/test_client/bin/main.dart b/test/dart/test_client/bin/main.dart index 996844b5bf4..feba6129930 100644 --- a/test/dart/test_client/bin/main.dart +++ b/test/dart/test_client/bin/main.dart @@ -120,7 +120,7 @@ ArgResults _parseArgs(List args) { 'compact': 'TCompactProtocol', 'json': 'TJsonProtocol' }); - parser.addFlag('verbose', defaultsTo: false); + parser.addFlag('verbose', defaultsTo: true); ArgResults results; try { diff --git a/test/tests.json b/test/tests.json index 3381a1faf87..1d4ba66d158 100644 --- a/test/tests.json +++ b/test/tests.json @@ -562,7 +562,7 @@ { "name": "dart", "client": { - "timeout": 15, + "timeout": 20, "transports": [ "buffered", "framed", @@ -578,8 +578,9 @@ ], "command": [ "dart", - "--enable-asserts", - "test_client/bin/main.dart" + "--checked", + "test_client/bin/main.dart", + "--verbose" ] }, "workdir": "dart" From 022b8bf91c83bd63f637f88a178a095d5d04b85f Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Wed, 23 Jan 2019 14:09:06 -0500 Subject: [PATCH 173/756] update NOTICE [ci skip] --- NOTICE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE b/NOTICE index 902dc8d3140..37824e7fb66 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache Thrift -Copyright 2006-2017 The Apache Software Foundation. +Copyright (C) 2006 - 2019, The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). From 328e437f2653ddd40259c41959d806f7c0a074b9 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 24 Jan 2019 07:46:13 -0500 Subject: [PATCH 174/756] THRIFT-4698: add releading instructions to the haskell readme [ci skip] --- lib/hs/README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/hs/README.md b/lib/hs/README.md index eea0a73821c..10bdeff1e77 100644 --- a/lib/hs/README.md +++ b/lib/hs/README.md @@ -97,3 +97,17 @@ Processor Just a function that takes a handler label, protocols. It calls the superclasses process if there is a superclass. + +Releasing to Hackage +==================== + +Using the [Docker Container for Ubuntu Bionic](../../build/docker/README.md), run: + + root@e941f5311545:/thrift/src# ./bootstrap.sh && ./configure + root@e941f5311545:/thrift/src# cd lib/hs && make dist-local + +This will produce a `lib/hs/dist/thrift-.tar.gz` file. Take this +file and upload it as a Haskell Hackage +[package candidate](https://hackage.haskell.org/upload#candidates) and +check to make sure all the information is correct. Assuming all is satisfactory, +you can upload the package as official using the link at the top of the page. From 22749ac376b10982eb5fa5a32ba336b20e1e6344 Mon Sep 17 00:00:00 2001 From: Florian Lonqueu-Brochard Date: Thu, 24 Jan 2019 11:46:11 +0100 Subject: [PATCH 175/756] THRIFT-4751: Missing imports in TProtocol (phpdoc related only) Client: php --- lib/php/lib/Protocol/TProtocol.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/php/lib/Protocol/TProtocol.php b/lib/php/lib/Protocol/TProtocol.php index 81aceb623cf..f7b581f7bef 100644 --- a/lib/php/lib/Protocol/TProtocol.php +++ b/lib/php/lib/Protocol/TProtocol.php @@ -22,6 +22,8 @@ namespace Thrift\Protocol; +use Thrift\Exception\TException; +use Thrift\Transport\TTransport; use Thrift\Type\TType; use Thrift\Exception\TProtocolException; @@ -38,7 +40,7 @@ abstract class TProtocol protected $trans_; /** - * Constructor + * @param TTransport $trans */ protected function __construct($trans) { From b1d63e7190fb1e4a2d87a9be42f3d4b7f17305fd Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 22 Jan 2019 14:16:39 -0500 Subject: [PATCH 176/756] THRIFT-4750: as3 changes to build and publish to maven central --- .gitignore | 2 + CMakeLists.txt | 4 + LANGUAGES.md | 2 +- build/cmake/DefineOptions.cmake | 25 ++- build/docker/README.md | 2 +- build/docker/ubuntu-bionic/Dockerfile | 8 + build/veralign.sh | 1 + compiler/cpp/README.md | 4 +- configure.ac | 29 +++ doc/ReleaseManagement.md | 4 +- lib/Makefile.am | 4 + lib/as3/CMakeLists.txt | 68 +++++++ lib/as3/Makefile.am | 56 ++++++ lib/as3/README.md | 37 ++++ lib/as3/build.gradle | 56 ++++++ lib/as3/build.properties | 5 - lib/as3/build.xml | 182 ------------------ lib/as3/gradle.properties | 23 +++ lib/as3/gradle/publishing.gradle | 96 +++++++++ lib/as3/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55190 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + lib/as3/gradlew | 172 +++++++++++++++++ lib/as3/gradlew.bat | 84 ++++++++ lib/as3/settings.gradle | 20 ++ test/tests.json | 2 +- 25 files changed, 687 insertions(+), 204 deletions(-) create mode 100644 lib/as3/CMakeLists.txt create mode 100644 lib/as3/Makefile.am create mode 100644 lib/as3/README.md create mode 100644 lib/as3/build.gradle delete mode 100644 lib/as3/build.properties delete mode 100755 lib/as3/build.xml create mode 100644 lib/as3/gradle.properties create mode 100644 lib/as3/gradle/publishing.gradle create mode 100644 lib/as3/gradle/wrapper/gradle-wrapper.jar create mode 100644 lib/as3/gradle/wrapper/gradle-wrapper.properties create mode 100755 lib/as3/gradlew create mode 100644 lib/as3/gradlew.bat create mode 100644 lib/as3/settings.gradle diff --git a/.gitignore b/.gitignore index 82d3d482da5..cd98fa778a8 100644 --- a/.gitignore +++ b/.gitignore @@ -105,6 +105,8 @@ project.lock.json /contrib/fb303/py/fb303/ttypes.py /depcomp /install-sh +/lib/as3/.gradle/ +/lib/as3/build/ /lib/cl/backport-update.zip /lib/cl/lib /lib/cl/run-tests diff --git a/CMakeLists.txt b/CMakeLists.txt index e67916465b3..e9ebbab9388 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,10 @@ if(BUILD_CPP) endif() endif() +if(BUILD_AS3) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/as3) +endif() + if(BUILD_C_GLIB) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/c_glib) endif() diff --git a/LANGUAGES.md b/LANGUAGES.md index 67f55657ef0..c610d15d06b 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -37,7 +37,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u ActionScript 0.3.0 -ActionScript 3 +FLEX SDK 4.6 Yes Yes Yes diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 8e334d9c23f..2c8ea505031 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -28,7 +28,6 @@ option(BUILD_COMPILER "Build Thrift compiler" ON) if(BUILD_COMPILER OR EXISTS ${THRIFT_COMPILER}) set(HAVE_COMPILER ON) endif() -CMAKE_DEPENDENT_OPTION(BUILD_EXAMPLES "Build examples" ON "HAVE_COMPILER" OFF) CMAKE_DEPENDENT_OPTION(BUILD_TESTING "Build with unit tests" ON "HAVE_COMPILER" OFF) CMAKE_DEPENDENT_OPTION(BUILD_TUTORIALS "Build Thrift tutorials" ON "HAVE_COMPILER" OFF) option(BUILD_LIBRARIES "Build Thrift libraries" ON) @@ -45,6 +44,15 @@ if (NOT Boost_USE_STATIC_LIBS) add_definitions(-DBOOST_TEST_DYN_LINK) endif() +# as3 +option(WITH_AS3 "Build ActionScript 3 Thrift Library" ON) +if (WITH_AS3) + set(POSSIBLE_PATHS "${FLEX_HOME}/bin" "$ENV{FLEX_HOME}/bin") + find_program(HAVE_COMPC NAMES compc HINTS ${POSSIBLE_PATHS}) +endif () +CMAKE_DEPENDENT_OPTION(BUILD_AS3 "Build as3 library" ON + "BUILD_LIBRARIES;WITH_AS3;HAVE_COMPC" OFF) + # C++ option(WITH_CPP "Build C++ Thrift library" ON) if(WITH_CPP) @@ -82,10 +90,6 @@ endif() CMAKE_DEPENDENT_OPTION(BUILD_C_GLIB "Build C (GLib) library" ON "BUILD_LIBRARIES;WITH_C_GLIB;GLIB_FOUND" OFF) - #if(BUILD_C_GLIB AND BUILD_TESTING) - # find_package(Boost 1.53 REQUIRED) - #endif() - # Java option(WITH_JAVA "Build Java Thrift library" ON) if(ANDROID) @@ -148,14 +152,15 @@ message(STATUS "Build configuration Summary") if (UNIX) message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") endif () -message(STATUS " Build Thrift compiler: ${BUILD_COMPILER}") +message(STATUS " Build compiler: ${BUILD_COMPILER}") message(STATUS " Build compiler plugin support: ${WITH_PLUGIN}") -message(STATUS " Build with unit tests: ${BUILD_TESTING}") -MESSAGE_DEP(HAVE_COMPILER "Disabled because BUILD_THRIFT=OFF and no valid THRIFT_COMPILER is given") -message(STATUS " Build examples: ${BUILD_EXAMPLES}") +message(STATUS " Build libraries: ${BUILD_LIBRARIES}") +message(STATUS " Build tests: ${BUILD_TESTING}") MESSAGE_DEP(HAVE_COMPILER "Disabled because BUILD_THRIFT=OFF and no valid THRIFT_COMPILER is given") -message(STATUS " Build Thrift libraries: ${BUILD_LIBRARIES}") message(STATUS " Language libraries:") +message(STATUS " Build as3 library: ${BUILD_AS3}") +MESSAGE_DEP(WITH_AS3 "Disabled by WITH_AS3=OFF") +MESSAGE_DEP(HAVE_COMPC "Adobe Flex compc was not found - did you set env var FLEX_HOME?") message(STATUS " Build C++ library: ${BUILD_CPP}") MESSAGE_DEP(WITH_CPP "Disabled by WITH_CPP=OFF") message(STATUS " C++ Language Level: ${CXX_LANGUAGE_LEVEL}") diff --git a/build/docker/README.md b/build/docker/README.md index 56b98a9ded7..b65f74be5c5 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -168,7 +168,7 @@ Last updated: October 1, 2017 | Language | ubuntu-xenial | ubuntu-bionic | Notes | | :-------- | :------------ | :------------ | :---- | | as of | Mar 06, 2018 | Jan 21, 2019 | | -| as3 | | | Not in CI | +| as3 | | 4.6.0 | | | C++ gcc | 5.4.0 | 7.3.0 | | | C++ clang | 3.8 | 6.0 | | | C# (mono) | 4.2.1.0 | 4.6.2.7 | | diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index db19112e89f..a75af31c3e9 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -71,10 +71,18 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ llvm \ ninja-build \ pkg-config \ + unzip \ valgrind \ vim ENV PATH /usr/lib/llvm-6.0/bin:$PATH +# lib/as3 (ActionScript) +RUN mkdir -p /usr/local/adobe/flex/4.6 && \ + cd /usr/local/adobe/flex/4.6 && \ + wget -q "http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip" && \ + unzip flex_sdk_4.6.zip +ENV FLEX_HOME /usr/local/adobe/flex/4.6 + RUN apt-get install -y --no-install-recommends \ `# C++ dependencies` \ libboost-all-dev \ diff --git a/build/veralign.sh b/build/veralign.sh index c54de538b12..05039dc5d80 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -56,6 +56,7 @@ FILES[bower.json]=jsonReplace FILES[configure.ac]=configureReplace FILES[contrib/thrift.spec]=simpleReplace FILES[doc/specs/idl.md]=simpleReplace +FILES[lib/as3/gradle.properties]=simpleReplace FILES[lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs]=simpleReplace FILES[lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj]=simpleReplace FILES[lib/csharp/src/Properties/AssemblyInfo.cs]=simpleReplace diff --git a/compiler/cpp/README.md b/compiler/cpp/README.md index 32eac9fbc7d..355191293ec 100644 --- a/compiler/cpp/README.md +++ b/compiler/cpp/README.md @@ -115,7 +115,7 @@ cmake -G "Visual Studio 15 2017" -DWITH_PLUGIN=OFF .. ``` mkdir cmake-mingw32 && cd cmake-mingw32 -cmake -DCMAKE_TOOLCHAIN_FILE=../build/cmake/mingw32-toolchain.cmake -DBUILD_COMPILER=ON -DBUILD_LIBRARIES=OFF -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF .. +cmake -DCMAKE_TOOLCHAIN_FILE=../build/cmake/mingw32-toolchain.cmake -DBUILD_COMPILER=ON -DBUILD_LIBRARIES=OFF -DBUILD_TESTING=OFF .. cpack ``` @@ -172,4 +172,4 @@ Added generic way to cover code by tests for many languages (you just need to ma - pls check **tests** folder -# Have a Happy free time and holidays \ No newline at end of file +# Have a Happy free time and holidays diff --git a/configure.ac b/configure.ac index bdd1dd2a06c..a299785fc34 100755 --- a/configure.ac +++ b/configure.ac @@ -116,6 +116,7 @@ AC_ARG_ENABLE([libs], have_libs=yes if test "$enable_libs" = "no"; then have_libs="no" + with_as3="no" with_cpp="no" with_c_glib="no" with_cl="no" @@ -141,6 +142,18 @@ if test "$enable_libs" = "no"; then with_swift="no" fi +AX_THRIFT_LIB(as3, [as3], yes) +have_as3=no +if test "$with_as3" = "yes"; then + if test "${FLEX_HOME+set}" = set; then + AC_PATH_PROGS([FLEX_COMPC], [compc], "fail", [$PATH$PATH_SEPARATOR$FLEX_HOME/bin]) + if test "$FLEX_COMPC" != "fail"; then + have_as3="yes" + fi + fi +fi +AM_CONDITIONAL(WITH_AS3, [test "$have_as3" = "yes"]) + AX_THRIFT_LIB(cpp, [C++], yes) have_cpp=no if test "$with_cpp" = "yes"; then @@ -187,6 +200,7 @@ if test "$with_c_glib" = "yes"; then PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.0], have_glib2=yes, have_glib2=no) PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.0], have_gobject2=yes, have_gobject2=no) if test "$have_glib2" = "yes" -a "$have_gobject2" = "yes" ; then + AC_PATH_PROG([GSETTINGS], [gsettings]) have_c_glib="yes" fi fi @@ -793,6 +807,7 @@ AC_CONFIG_FILES([ compiler/cpp/test/Makefile compiler/cpp/src/thrift/version.h lib/Makefile + lib/as3/Makefile lib/cl/Makefile lib/cpp/Makefile lib/cpp/test/Makefile @@ -874,6 +889,8 @@ AC_CONFIG_FILES([ tutorial/rs/Makefile ]) +if test "$have_as3" = "yes" ; then MAYBE_AS3="as3" ; else MAYBE_AS3="" ; fi +AC_SUBST([MAYBE_AS3]) if test "$have_cpp" = "yes" ; then MAYBE_CPP="cpp" ; else MAYBE_CPP="" ; fi AC_SUBST([MAYBE_CPP]) if test "$have_c_glib" = "yes" ; then MAYBE_C_GLIB="c_glib" ; else MAYBE_C_GLIB="" ; fi @@ -923,6 +940,7 @@ AC_OUTPUT echo echo "$PACKAGE $VERSION" echo +echo "Building ActionScript3 Library : $have_as3" echo "Building C (GLib) Library .... : $have_c_glib" echo "Building C# (Mono) Library ... : $have_csharp" echo "Building C++ Library ......... : $have_cpp" @@ -946,6 +964,17 @@ echo "Building Ruby Library ........ : $have_ruby" echo "Building Rust Library ........ : $have_rs" echo "Building Swift Library ....... : $have_swift" +if test "$have_as3" = "yes" ; then + echo + echo "ActionScript Library:" + echo " FLEX_HOME ................. : $FLEX_HOME" + echo " Using compc version ....... : $($FLEX_COMPC --version)" +fi +if test "$have_c_glib" = "yes" ; then + echo + echo "C (glib):" + echo " Using glib version ........ : $($GSETTINGS --version)" +fi if test "$have_csharp" = "yes" ; then echo echo "C# Library:" diff --git a/doc/ReleaseManagement.md b/doc/ReleaseManagement.md index a7b2369d155..9cf02da8a0d 100644 --- a/doc/ReleaseManagement.md +++ b/doc/ReleaseManagement.md @@ -176,7 +176,7 @@ All Apache Thrift releases go through a 72-hour final release candidate voting p 1. Install chocolatey and install winflexbison with chocolatey. 1. Run cmake to generate an out-of-tree build environment: ```cmd - C:\build> cmake ..\thrift -DBISON_EXECUTABLE=c:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe -DFLEX_EXECUTABLE=c:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe -DWITH_MT=ON -DWITH_SHARED_LIB=OFF -DWITH_CPP=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DBUILD_TESTING=OFF -DBUILD_EXAMPLES=OFF -DBUILD_TUTORIALS=OFF -DBUILD_COMPILER=ON + C:\build> cmake ..\thrift -DBISON_EXECUTABLE=c:\ProgramData\chocolatey\lib\winflexbison\tools\win_bison.exe -DFLEX_EXECUTABLE=c:\ProgramData\chocolatey\lib\winflexbison\tools\win_flex.exe -DWITH_MT=ON -DWITH_SHARED_LIB=OFF -DWITH_CPP=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DBUILD_TESTING=OFF -DBUILD_TUTORIALS=OFF -DBUILD_COMPILER=ON C:\build> cmake --build . --config Release ``` @@ -392,4 +392,4 @@ See https://thrift.apache.org/lib/ for the current status of each external packa https://issues.apache.org/jira/browse/THRIFT-4687 * [rust] Any thrift project committer is allowed to upload a new crate. -If you have any questions email `dev@thrift.apache.org`. \ No newline at end of file +If you have any questions email `dev@thrift.apache.org`. diff --git a/lib/Makefile.am b/lib/Makefile.am index 0c69019409e..901c3ef02f0 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -20,6 +20,10 @@ SUBDIRS = json xml PRECROSS_TARGET = +if WITH_AS3 +SUBDIRS += as3 +endif + if WITH_CPP # cpp dir is picked directly by plugin build if !WITH_PLUGIN diff --git a/lib/as3/CMakeLists.txt b/lib/as3/CMakeLists.txt new file mode 100644 index 00000000000..999905da0aa --- /dev/null +++ b/lib/as3/CMakeLists.txt @@ -0,0 +1,68 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +if (IS_ABSOLUTE "${LIB_INSTALL_DIR}") + set(AS3_INSTALL_DIR "${LIB_INSTALL_DIR}/as3") +else () + set(AS3_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/as3") +endif () + +set(PRELEASE "true") +if (CMAKE_BUILD_TYPE MATCHES DEBUG) + set(PRELEASE "false") +endif () + +add_custom_target(ThriftAs3 ALL + COMMENT "Building as3 library using Gradle Wrapper" + COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} compileFlex + --console=plain --no-daemon + -Prelease=${PRELEASE} + "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + +# Enable publishing from CMake if the publishing information is provided +if (NOT CMAKE_BUILD_TYPE MATCHES DEBUG) + add_custom_target(MavenPublishAs3 + COMMENT "Publishing as3 library to Apache Maven staging" + COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} clean publishMavenPublicationToMavenRepository + --console=plain --no-daemon + -Prelease=${PRELEASE} + -Psign=${PRELEASE} + "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) +endif () + +# Hook the CMake install process to the results from make ALL. +# This works best when 'make all && sudo make install/fast' is used. +# Using slash to end the source location to avoid copying the directory path. +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build/libs/ + DESTINATION ${AS3_INSTALL_DIR} + FILES_MATCHING PATTERN "libthrift-as3.swc") + +if (BUILD_TESTING) + add_test(NAME As3Test + COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} test + --console=plain --no-daemon + -Prelease=${PRELEASE} + "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" + "-Pthrift.compiler=${THRIFT_COMPILER}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +endif () diff --git a/lib/as3/Makefile.am b/lib/as3/Makefile.am new file mode 100644 index 00000000000..5a078c6ff38 --- /dev/null +++ b/lib/as3/Makefile.am @@ -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. +# + +all-local: + ./gradlew $(GRADLE_OPTS) compile \ + -Prelease=true \ + --console=plain + +install-exec-hook: + ./gradlew $(GRADLE_OPTS) publishToMavenLocal \ + -Prelease=true \ + --console=plain + +clean-local: + ./gradlew $(GRADLE_OPTS) clean \ + -Prelease=true \ + --console=plain + +check-local: $(THRIFT) + ./gradlew $(GRADLE_OPTS) test \ + -Prelease=true \ + --console=plain + +maven-publish: + ./gradlew $(GRADLE_OPTS) publishMavenPublicationToMavenRepository \ + -Prelease=true \ + -Psign=true \ + --console=plain + +EXTRA_DIST = \ + CMakeLists.txt \ + README.md \ + build.gradle \ + coding_standards.md \ + gradle \ + gradle.properties \ + gradlew \ + gradlew.bat \ + settings.gradle \ + src diff --git a/lib/as3/README.md b/lib/as3/README.md new file mode 100644 index 00000000000..c14f8c78b68 --- /dev/null +++ b/lib/as3/README.md @@ -0,0 +1,37 @@ +# Apache Thrift ActionScript Library + +## Building + +We use gradle and gradlefx to build the as3 library. Unfortunately gradlefx requires +an older version of gradle (2.5) but it still works - for now. If you use the docker +container to do the build, the Adobe Flex SDK 4.6 is installed and the FLEX_HOME +environment variable is configured: + + dev@ubuntu:~/thrift$ docker run -v $(pwd):/thrift/src:rw -it thrift/thrift-build:ubuntu-bionic /bin/bash + root@7624b61bbf84:/thrift/src# cd lib/as3 + root@7624b61bbf84:/thrift/src/lib/as3# ./gradlew -Prelease=true compileFlex + + ... + + :compileFlex UP-TO-DATE + + BUILD SUCCESSFUL + + Total time: 10.784 secs + + root@7624b61bbf84:/thrift/src/lib/as3# ls -ls build/ + total 4 + 4 -rw-r--r-- 1 root root 1379 Jan 22 19:23 libthrift-as3.swc + +## Publishing + +We use a similar gradle-based signing and publishing mechanism as in the java +library. See the java library [README.md](../java/README.md) for more details. + +To publish into a local .m2 repository you can mount a directory into the docker container, +for example: + + dev@ubuntu:~/thrift$ docker run -v~/.m2:/root/.m2 -v $(pwd):/thrift/src:rw -it thrift/thrift-build:ubuntu-bionic /bin/bash + root@7624b61bbf84:/thrift/src/lib/as3# ./gradlew -Prelease=true publishToMavenLocal + +You will find your `~/.m2` directory is now populated with a release build `swc`. diff --git a/lib/as3/build.gradle b/lib/as3/build.gradle new file mode 100644 index 00000000000..78534996ada --- /dev/null +++ b/lib/as3/build.gradle @@ -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. + */ + +buildscript { + repositories { + mavenLocal() + mavenCentral() + } + dependencies { + classpath group: 'org.gradlefx', name: 'gradlefx', version: '1.5.0' + } +} + +plugins { + id 'maven-publish' + id 'signing' +} + +apply plugin: 'gradlefx' + +description = 'Apache Thrift ActionScript Library' +frameworkLinkage = 'none' +group = property('thrift.groupid') +srcDirs = ['src'] +type = 'swc' + +// We use the SNAPSHOT suffix for non-release versions +if (Boolean.parseBoolean(project.release)) { + additionalCompilerOptions = ['-compiler.debug=false', '-compiler.strict=true'] + version = property('thrift.version') +} else { + additionalCompilerOptions = ['-compiler.debug=true', '-compiler.strict=true'] + version = property('thrift.version') + '-SNAPSHOT' +} + +defaultTasks 'compile' + +// Keeping the rest of the build logic in functional named scripts for clarity +apply from: 'gradle/publishing.gradle' + diff --git a/lib/as3/build.properties b/lib/as3/build.properties deleted file mode 100644 index 84636683c94..00000000000 --- a/lib/as3/build.properties +++ /dev/null @@ -1,5 +0,0 @@ -# Maven Ant tasks Jar details -mvn.ant.task.version=2.1.3 -mvn.repo=http://repo1.maven.org/maven2 -mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version} -mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar diff --git a/lib/as3/build.xml b/lib/as3/build.xml deleted file mode 100755 index b0c4c858ddf..00000000000 --- a/lib/as3/build.xml +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/as3/gradle.properties b/lib/as3/gradle.properties new file mode 100644 index 00000000000..8c8755efb0a --- /dev/null +++ b/lib/as3/gradle.properties @@ -0,0 +1,23 @@ +# This file is shared currently between this Gradle build and the +# Ant builds for fd303 and JavaScript. Keep the dotted notation for +# the properties to minimize the changes in the dependencies. +thrift.version=1.0.0 +thrift.groupid=org.apache.thrift +release=false +sign=false + +# Local Install paths +install.path=/usr/local/lib +install.javadoc.path=/usr/local/lib + +# Test execution properties +testPort=9090 + +# Maven dependency download locations +mvn.repo=http://repo1.maven.org/maven2 +apache.repo=https://repository.apache.org/content/repositories/releases + +# Apache Maven publish +license=http://www.apache.org/licenses/LICENSE-2.0.txt +maven-repository-url=https://repository.apache.org/service/local/staging/deploy/maven2 +maven-repository-id=apache.releases.https diff --git a/lib/as3/gradle/publishing.gradle b/lib/as3/gradle/publishing.gradle new file mode 100644 index 00000000000..3e0ecf3192d --- /dev/null +++ b/lib/as3/gradle/publishing.gradle @@ -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. + */ + +// Following Gradle best practices to keep build logic organized + +model { + tasks.signMavenPublication { + dependsOn compileFlex + } +} + +publishing { + publications { + maven(MavenPublication) { + + groupId = "$group" + artifactId = "${project.name}" + version = "$version" + + def swcFile = file("$buildDir/libthrift-as3.swc") + artifact(swcFile) + + pom { + description = 'Thrift is a software framework for scalable cross-language services development.' + packaging = 'swc' + + // older gradle doesn't recognize all the properties, so we inject them.. + withXml { + asNode().with { + appendNode('name', 'Apache Thrift') + appendNode('url', 'http://thrift.apache.org/') + appendNode('scm').with { + appendNode('url', 'https://github.com/apache/thrift/') + appendNode('connection', 'scm:git:https://github.com/apache/thrift.git') + appendNode('developerConnection', 'scm:git:git@github.com:apache/thrift.git') + } + appendNode('issueManagement').with { + appendNode('url', 'https://issues.apache.org/jira/projects/THRIFT/') + appendNode('system', 'Jira') + } + appendNode('licenses').with { + appendNode('license').with { + appendNode('name', 'The Apache Software License, Version 2.0') + appendNode('url', "${project.license}") + } + } + appendNode('organization').with { + appendNode('name', 'The Apache Software Foundation') + appendNode('url', 'http://www.apache.org/') + } + appendNode('developers').with { + appendNode('developer').with { + appendNode('id', 'dev') + appendNode('name', 'Apache Thrift Developers') + appendNode('email', 'dev@thrift.apache.org') + } + } + } + } + } + } + } + repositories { + maven { + url = property('maven-repository-url') + + if (project.hasProperty('mavenUser') && project.hasProperty('mavenPassword')) { + credentials { + username = property('mavenUser') + password = property('mavenPassword') + } + } + } + } +} + +signing { + required { property('sign') } + sign publishing.publications.maven +} diff --git a/lib/as3/gradle/wrapper/gradle-wrapper.jar b/lib/as3/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..87b738cbd051603d91cc39de6cb000dd98fe6b02 GIT binary patch literal 55190 zcmafaW0WS*vSoFbZQHhO+s0S6%`V%vZQJa!ZQHKus_B{g-pt%P_q|ywBQt-*Stldc z$+IJ3?^KWm27v+sf`9-50uuadKtMnL*BJ;1^6ynvR7H?hQcjE>7)art9Bu0Pcm@7C z@c%WG|JzYkP)<@zR9S^iR_sA`azaL$mTnGKnwDyMa;8yL_0^>Ba^)phg0L5rOPTbm7g*YIRLg-2^{qe^`rb!2KqS zk~5wEJtTdD?)3+}=eby3x6%i)sb+m??NHC^u=tcG8p$TzB<;FL(WrZGV&cDQb?O0GMe6PBV=V z?tTO*5_HTW$xea!nkc~Cnx#cL_rrUGWPRa6l+A{aiMY=<0@8y5OC#UcGeE#I>nWh}`#M#kIn-$A;q@u-p71b#hcSItS!IPw?>8 zvzb|?@Ahb22L(O4#2Sre&l9H(@TGT>#Py)D&eW-LNb!=S;I`ZQ{w;MaHW z#to!~TVLgho_Pm%zq@o{K3Xq?I|MVuVSl^QHnT~sHlrVxgsqD-+YD?Nz9@HA<;x2AQjxP)r6Femg+LJ-*)k%EZ}TTRw->5xOY z9#zKJqjZgC47@AFdk1$W+KhTQJKn7e>A&?@-YOy!v_(}GyV@9G#I?bsuto4JEp;5|N{orxi_?vTI4UF0HYcA( zKyGZ4<7Fk?&LZMQb6k10N%E*$gr#T&HsY4SPQ?yerqRz5c?5P$@6dlD6UQwZJ*Je9 z7n-@7!(OVdU-mg@5$D+R%gt82Lt%&n6Yr4=|q>XT%&^z_D*f*ug8N6w$`woqeS-+#RAOfSY&Rz z?1qYa5xi(7eTCrzCFJfCxc%j{J}6#)3^*VRKF;w+`|1n;Xaojr2DI{!<3CaP`#tXs z*`pBQ5k@JLKuCmovFDqh_`Q;+^@t_;SDm29 zCNSdWXbV?9;D4VcoV`FZ9Ggrr$i<&#Dx3W=8>bSQIU_%vf)#(M2Kd3=rN@^d=QAtC zI-iQ;;GMk|&A++W5#hK28W(YqN%?!yuW8(|Cf`@FOW5QbX|`97fxmV;uXvPCqxBD zJ9iI37iV)5TW1R+fV16y;6}2tt~|0J3U4E=wQh@sx{c_eu)t=4Yoz|%Vp<#)Qlh1V z0@C2ZtlT>5gdB6W)_bhXtcZS)`9A!uIOa`K04$5>3&8An+i9BD&GvZZ=7#^r=BN=k za+=Go;qr(M)B~KYAz|<^O3LJON}$Q6Yuqn8qu~+UkUKK~&iM%pB!BO49L+?AL7N7o z(OpM(C-EY753=G=WwJHE`h*lNLMNP^c^bBk@5MyP5{v7x>GNWH>QSgTe5 z!*GPkQ(lcbEs~)4ovCu!Zt&$${9$u(<4@9%@{U<-ksAqB?6F`bQ;o-mvjr)Jn7F&j$@`il1Mf+-HdBs<-`1FahTxmPMMI)@OtI&^mtijW6zGZ67O$UOv1Jj z;a3gmw~t|LjPkW3!EZ=)lLUhFzvO;Yvj9g`8hm%6u`;cuek_b-c$wS_0M4-N<@3l|88 z@V{Sd|M;4+H6guqMm4|v=C6B7mlpP(+It%0E;W`dxMOf9!jYwWj3*MRk`KpS_jx4c z=hrKBkFK;gq@;wUV2eqE3R$M+iUc+UD0iEl#-rECK+XmH9hLKrC={j@uF=f3UiceB zU5l$FF7#RKjx+6!JHMG5-!@zI-eG=a-!Bs^AFKqN_M26%cIIcSs61R$yuq@5a3c3& z4%zLs!g}+C5%`ja?F`?5-og0lv-;(^e<`r~p$x%&*89_Aye1N)9LNVk?9BwY$Y$$F^!JQAjBJvywXAesj7lTZ)rXuxv(FFNZVknJha99lN=^h`J2> zl5=~(tKwvHHvh|9-41@OV`c;Ws--PE%{7d2sLNbDp;A6_Ka6epzOSFdqb zBa0m3j~bT*q1lslHsHqaHIP%DF&-XMpCRL(v;MV#*>mB^&)a=HfLI7efblG z(@hzN`|n+oH9;qBklb=d^S0joHCsArnR1-h{*dIUThik>ot^!6YCNjg;J_i3h6Rl0ji)* zo(tQ~>xB!rUJ(nZjCA^%X;)H{@>uhR5|xBDA=d21p@iJ!cH?+%U|VSh2S4@gv`^)^ zNKD6YlVo$%b4W^}Rw>P1YJ|fTb$_(7C;hH+ z1XAMPb6*p^h8)e5nNPKfeAO}Ik+ZN_`NrADeeJOq4Ak;sD~ zTe77no{Ztdox56Xi4UE6S7wRVxJzWxKj;B%v7|FZ3cV9MdfFp7lWCi+W{}UqekdpH zdO#eoOuB3Fu!DU`ErfeoZWJbWtRXUeBzi zBTF-AI7yMC^ntG+8%mn(I6Dw}3xK8v#Ly{3w3_E?J4(Q5JBq~I>u3!CNp~Ekk&YH` z#383VO4O42NNtcGkr*K<+wYZ>@|sP?`AQcs5oqX@-EIqgK@Pmp5~p6O6qy4ml~N{D z{=jQ7k(9!CM3N3Vt|u@%ssTw~r~Z(}QvlROAkQQ?r8OQ3F0D$aGLh zny+uGnH5muJ<67Z=8uilKvGuANrg@s3Vu_lU2ajb?rIhuOd^E@l!Kl0hYIxOP1B~Q zggUmXbh$bKL~YQ#!4fos9UUVG#}HN$lIkM<1OkU@r>$7DYYe37cXYwfK@vrHwm;pg zbh(hEU|8{*d$q7LUm+x&`S@VbW*&p-sWrplWnRM|I{P;I;%U`WmYUCeJhYc|>5?&& zj}@n}w~Oo=l}iwvi7K6)osqa;M8>fRe}>^;bLBrgA;r^ZGgY@IC^ioRmnE&H4)UV5 zO{7egQ7sBAdoqGsso5q4R(4$4Tjm&&C|7Huz&5B0wXoJzZzNc5Bt)=SOI|H}+fbit z-PiF5(NHSy>4HPMrNc@SuEMDuKYMQ--G+qeUPqO_9mOsg%1EHpqoX^yNd~~kbo`cH zlV0iAkBFTn;rVb>EK^V6?T~t~3vm;csx+lUh_%ROFPy0(omy7+_wYjN!VRDtwDu^h4n|xpAMsLepm% zggvs;v8+isCW`>BckRz1MQ=l>K6k^DdT`~sDXTWQ<~+JtY;I~I>8XsAq3yXgxe>`O zZdF*{9@Z|YtS$QrVaB!8&`&^W->_O&-JXn1n&~}o3Z7FL1QE5R*W2W@=u|w~7%EeC1aRfGtJWxImfY-D3t!!nBkWM> zafu>^Lz-ONgT6ExjV4WhN!v~u{lt2-QBN&UxwnvdH|I%LS|J-D;o>@@sA62@&yew0 z)58~JSZP!(lX;da!3`d)D1+;K9!lyNlkF|n(UduR-%g>#{`pvrD^ClddhJyfL7C-(x+J+9&7EsC~^O`&}V%)Ut8^O_7YAXPDpzv8ir4 zl`d)(;imc6r16k_d^)PJZ+QPxxVJS5e^4wX9D=V2zH&wW0-p&OJe=}rX`*->XT=;_qI&)=WHkYnZx6bLoUh_)n-A}SF_ z9z7agNTM5W6}}ui=&Qs@pO5$zHsOWIbd_&%j^Ok5PJ3yUWQw*i4*iKO)_er2CDUME ztt+{Egod~W-fn^aLe)aBz)MOc_?i-stTj}~iFk7u^-gGSbU;Iem06SDP=AEw9SzuF zeZ|hKCG3MV(z_PJg0(JbqTRf4T{NUt%kz&}4S`)0I%}ZrG!jgW2GwP=WTtkWS?DOs znI9LY!dK+1_H0h+i-_~URb^M;4&AMrEO_UlDV8o?E>^3x%ZJyh$JuDMrtYL8|G3If zPf2_Qb_W+V?$#O; zydKFv*%O;Y@o_T_UAYuaqx1isMKZ^32JtgeceA$0Z@Ck0;lHbS%N5)zzAW9iz; z8tTKeK7&qw!8XVz-+pz>z-BeIzr*#r0nB^cntjQ9@Y-N0=e&ZK72vlzX>f3RT@i7@ z=z`m7jNk!9%^xD0ug%ptZnM>F;Qu$rlwo}vRGBIymPL)L|x}nan3uFUw(&N z24gdkcb7!Q56{0<+zu zEtc5WzG2xf%1<@vo$ZsuOK{v9gx^0`gw>@h>ZMLy*h+6ueoie{D#}}` zK2@6Xxq(uZaLFC%M!2}FX}ab%GQ8A0QJ?&!vaI8Gv=vMhd);6kGguDmtuOElru()) zuRk&Z{?Vp!G~F<1#s&6io1`poBqpRHyM^p;7!+L??_DzJ8s9mYFMQ0^%_3ft7g{PD zZd}8E4EV}D!>F?bzcX=2hHR_P`Xy6?FOK)mCj)Ym4s2hh z0OlOdQa@I;^-3bhB6mpw*X5=0kJv8?#XP~9){G-+0ST@1Roz1qi8PhIXp1D$XNqVG zMl>WxwT+K`SdO1RCt4FWTNy3!i?N>*-lbnn#OxFJrswgD7HjuKpWh*o@QvgF&j+CT z{55~ZsUeR1aB}lv#s_7~+9dCix!5(KR#c?K?e2B%P$fvrsZxy@GP#R#jwL{y#Ld$} z7sF>QT6m|}?V;msb?Nlohj7a5W_D$y+4O6eI;Zt$jVGymlzLKscqer9#+p2$0It&u zWY!dCeM6^B^Z;ddEmhi?8`scl=Lhi7W%2|pT6X6^%-=q90DS(hQ-%c+E*ywPvmoF(KqDoW4!*gmQIklm zk#!GLqv|cs(JRF3G?=AYY19{w@~`G3pa z@xR9S-Hquh*&5Yas*VI};(%9%PADn`kzm zeWMJVW=>>wap*9|R7n#!&&J>gq04>DTCMtj{P^d12|2wXTEKvSf?$AvnE!peqV7i4 zE>0G%CSn%WCW1yre?yi9*aFP{GvZ|R4JT}M%x_%Hztz2qw?&28l&qW<6?c6ym{f$d z5YCF+k#yEbjCN|AGi~-NcCG8MCF1!MXBFL{#7q z)HO+WW173?kuI}^Xat;Q^gb4Hi0RGyB}%|~j8>`6X4CPo+|okMbKy9PHkr58V4bX6<&ERU)QlF8%%huUz&f+dwTN|tk+C&&o@Q1RtG`}6&6;ncQuAcfHoxd5AgD7`s zXynq41Y`zRSiOY@*;&1%1z>oNcWTV|)sjLg1X8ijg1Y zbIGL0X*Sd}EXSQ2BXCKbJmlckY(@EWn~Ut2lYeuw1wg?hhj@K?XB@V_ZP`fyL~Yd3n3SyHU-RwMBr6t-QWE5TinN9VD4XVPU; zonIIR!&pGqrLQK)=#kj40Im%V@ij0&Dh0*s!lnTw+D`Dt-xmk-jmpJv$1-E-vfYL4 zqKr#}Gm}~GPE+&$PI@4ag@=M}NYi7Y&HW82Q`@Y=W&PE31D110@yy(1vddLt`P%N^ z>Yz195A%tnt~tvsSR2{m!~7HUc@x<&`lGX1nYeQUE(%sphTi>JsVqSw8xql*Ys@9B z>RIOH*rFi*C`ohwXjyeRBDt8p)-u{O+KWP;$4gg||%*u{$~yEj+Al zE(hAQRQ1k7MkCq9s4^N3ep*$h^L%2Vq?f?{+cicpS8lo)$Cb69b98au+m2J_e7nYwID0@`M9XIo1H~|eZFc8Hl!qly612ADCVpU zY8^*RTMX(CgehD{9v|^9vZ6Rab`VeZ2m*gOR)Mw~73QEBiktViBhR!_&3l$|be|d6 zupC`{g89Y|V3uxl2!6CM(RNpdtynaiJ~*DqSTq9Mh`ohZnb%^3G{k;6%n18$4nAqR zjPOrP#-^Y9;iw{J@XH9=g5J+yEVh|e=4UeY<^65`%gWtdQ=-aqSgtywM(1nKXh`R4 zzPP&7r)kv_uC7X9n=h=!Zrf<>X=B5f<9~Q>h#jYRD#CT7D~@6@RGNyO-#0iq0uHV1 zPJr2O4d_xLmg2^TmG7|dpfJ?GGa`0|YE+`2Rata9!?$j#e9KfGYuLL(*^z z!SxFA`$qm)q-YKh)WRJZ@S+-sD_1E$V?;(?^+F3tVcK6 z2fE=8hV*2mgiAbefU^uvcM?&+Y&E}vG=Iz!%jBF7iv){lyC`)*yyS~D8k+Mx|N3bm zI~L~Z$=W9&`x)JnO;8c>3LSDw!fzN#X3qi|0`sXY4?cz{*#xz!kvZ9bO=K3XbN z5KrgN=&(JbXH{Wsu9EdmQ-W`i!JWEmfI;yVTT^a-8Ch#D8xf2dtyi?7p z%#)W3n*a#ndFpd{qN|+9Jz++AJQO#-Y7Z6%*%oyEP5zs}d&kKIr`FVEY z;S}@d?UU=tCdw~EJ{b}=9x}S2iv!!8<$?d7VKDA8h{oeD#S-$DV)-vPdGY@x08n)@ zag?yLF_E#evvRTj4^CcrLvBL=fft&@HOhZ6Ng4`8ijt&h2y}fOTC~7GfJi4vpomA5 zOcOM)o_I9BKz}I`q)fu+Qnfy*W`|mY%LO>eF^a z;$)?T4F-(X#Q-m}!-k8L_rNPf`Mr<9IWu)f&dvt=EL+ESYmCvErd@8B9hd)afc(ZL94S z?rp#h&{7Ah5IJftK4VjATklo7@hm?8BX*~oBiz)jyc9FuRw!-V;Uo>p!CWpLaIQyt zAs5WN)1CCeux-qiGdmbIk8LR`gM+Qg=&Ve}w?zA6+sTL)abU=-cvU`3E?p5$Hpkxw znu0N659qR=IKnde*AEz_7z2pdi_Bh-sb3b=PdGO1Pdf_q2;+*Cx9YN7p_>rl``knY zRn%aVkcv1(W;`Mtp_DNOIECtgq%ufk-mu_<+Fu3Q17Tq4Rr(oeq)Yqk_CHA7LR@7@ zIZIDxxhS&=F2IQfusQ+Nsr%*zFK7S4g!U0y@3H^Yln|i;0a5+?RPG;ZSp6Tul>ezM z`40+516&719qT)mW|ArDSENle5hE2e8qY+zfeZoy12u&xoMgcP)4=&P-1Ib*-bAy` zlT?>w&B|ei-rCXO;sxo7*G;!)_p#%PAM-?m$JP(R%x1Hfas@KeaG%LO?R=lmkXc_MKZW}3f%KZ*rAN?HYvbu2L$ zRt_uv7~-IejlD1x;_AhwGXjB94Q=%+PbxuYzta*jw?S&%|qb=(JfJ?&6P=R7X zV%HP_!@-zO*zS}46g=J}#AMJ}rtWBr21e6hOn&tEmaM%hALH7nlm2@LP4rZ>2 zebe5aH@k!e?ij4Zwak#30|}>;`bquDQK*xmR=zc6vj0yuyC6+U=LusGnO3ZKFRpen z#pwzh!<+WBVp-!$MAc<0i~I%fW=8IO6K}bJ<-Scq>e+)951R~HKB?Mx2H}pxPHE@} zvqpq5j81_jtb_WneAvp<5kgdPKm|u2BdQx9%EzcCN&U{l+kbkhmV<1}yCTDv%&K^> zg;KCjwh*R1f_`6`si$h6`jyIKT7rTv5#k~x$mUyIw)_>Vr)D4fwIs@}{FSX|5GB1l z4vv;@oS@>Bu7~{KgUa_8eg#Lk6IDT2IY$41$*06{>>V;Bwa(-@N;ex4;D`(QK*b}{ z{#4$Hmt)FLqERgKz=3zXiV<{YX6V)lvYBr3V>N6ajeI~~hGR5Oe>W9r@sg)Na(a4- zxm%|1OKPN6^%JaD^^O~HbLSu=f`1px>RawOxLr+1b2^28U*2#h*W^=lSpSY4(@*^l z{!@9RSLG8Me&RJYLi|?$c!B0fP=4xAM4rerxX{xy{&i6=AqXueQAIBqO+pmuxy8Ib z4X^}r!NN3-upC6B#lt7&x0J;)nb9O~xjJMemm$_fHuP{DgtlU3xiW0UesTzS30L+U zQzDI3p&3dpONhd5I8-fGk^}@unluzu%nJ$9pzoO~Kk!>dLxw@M)M9?pNH1CQhvA`z zV;uacUtnBTdvT`M$1cm9`JrT3BMW!MNVBy%?@ZX%;(%(vqQAz<7I!hlDe|J3cn9=} zF7B;V4xE{Ss76s$W~%*$JviK?w8^vqCp#_G^jN0j>~Xq#Zru26e#l3H^{GCLEXI#n z?n~F-Lv#hU(bZS`EI9(xGV*jT=8R?CaK)t8oHc9XJ;UPY0Hz$XWt#QyLBaaz5+}xM zXk(!L_*PTt7gwWH*HLWC$h3Ho!SQ-(I||nn_iEC{WT3S{3V{8IN6tZ1C+DiFM{xlI zeMMk{o5;I6UvaC)@WKp9D+o?2Vd@4)Ue-nYci()hCCsKR`VD;hr9=vA!cgGL%3k^b(jADGyPi2TKr(JNh8mzlIR>n(F_hgiV(3@Ds(tjbNM7GoZ;T|3 zWzs8S`5PrA!9){jBJuX4y`f<4;>9*&NY=2Sq2Bp`M2(fox7ZhIDe!BaQUb@P(ub9D zlP8!p(AN&CwW!V&>H?yPFMJ)d5x#HKfwx;nS{Rr@oHqpktOg)%F+%1#tsPtq7zI$r zBo-Kflhq-=7_eW9B2OQv=@?|y0CKN77)N;z@tcg;heyW{wlpJ1t`Ap!O0`Xz{YHqO zI1${8Hag^r!kA<2_~bYtM=<1YzQ#GGP+q?3T7zYbIjN6Ee^V^b&9en$8FI*NIFg9G zPG$OXjT0Ku?%L7fat8Mqbl1`azf1ltmKTa(HH$Dqlav|rU{zP;Tbnk-XkGFQ6d+gi z-PXh?_kEJl+K98&OrmzgPIijB4!Pozbxd0H1;Usy!;V>Yn6&pu*zW8aYx`SC!$*ti zSn+G9p=~w6V(fZZHc>m|PPfjK6IN4(o=IFu?pC?+`UZAUTw!e`052{P=8vqT^(VeG z=psASIhCv28Y(;7;TuYAe>}BPk5Qg=8$?wZj9lj>h2kwEfF_CpK=+O6Rq9pLn4W)# zeXCKCpi~jsfqw7Taa0;!B5_C;B}e56W1s8@p*)SPzA;Fd$Slsn^=!_&!mRHV*Lmt| zBGIDPuR>CgS4%cQ4wKdEyO&Z>2aHmja;Pz+n|7(#l%^2ZLCix%>@_mbnyPEbyrHaz z>j^4SIv;ZXF-Ftzz>*t4wyq)ng8%0d;(Z_ExZ-cxwei=8{(br-`JYO(f23Wae_MqE z3@{Mlf^%M5G1SIN&en1*| zH~ANY1h3&WNsBy$G9{T=`kcxI#-X|>zLX2r*^-FUF+m0{k)n#GTG_mhG&fJfLj~K& zU~~6othMlvMm9<*SUD2?RD+R17|Z4mgR$L*R3;nBbo&Vm@39&3xIg;^aSxHS>}gwR zmzs?h8oPnNVgET&dx5^7APYx6Vv6eou07Zveyd+^V6_LzI$>ic+pxD_8s~ zC<}ucul>UH<@$KM zT4oI=62M%7qQO{}re-jTFqo9Z;rJKD5!X5$iwUsh*+kcHVhID08MB5cQD4TBWB(rI zuWc%CA}}v|iH=9gQ?D$1#Gu!y3o~p7416n54&Hif`U-cV?VrUMJyEqo_NC4#{puzU zzXEE@UppeeRlS9W*^N$zS`SBBi<@tT+<%3l@KhOy^%MWB9(A#*J~DQ;+MK*$rxo6f zcx3$3mcx{tly!q(p2DQrxcih|)0do_ZY77pyHGE#Q(0k*t!HUmmMcYFq%l$-o6%lS zDb49W-E?rQ#Hl``C3YTEdGZjFi3R<>t)+NAda(r~f1cT5jY}s7-2^&Kvo&2DLTPYP zhVVo-HLwo*vl83mtQ9)PR#VBg)FN}+*8c-p8j`LnNUU*Olm1O1Qqe62D#$CF#?HrM zy(zkX|1oF}Z=T#3XMLWDrm(|m+{1&BMxHY7X@hM_+cV$5-t!8HT(dJi6m9{ja53Yw z3f^`yb6Q;(e|#JQIz~B*=!-GbQ4nNL-NL z@^NWF_#w-Cox@h62;r^;Y`NX8cs?l^LU;5IWE~yvU8TqIHij!X8ydbLlT0gwmzS9} z@5BccG?vO;rvCs$mse1*ANi-cYE6Iauz$Fbn3#|ToAt5v7IlYnt6RMQEYLldva{~s zvr>1L##zmeoYgvIXJ#>bbuCVuEv2ZvZ8I~PQUN3wjP0UC)!U+wn|&`V*8?)` zMSCuvnuGec>QL+i1nCPGDAm@XSMIo?A9~C?g2&G8aNKjWd2pDX{qZ?04+2 zeyLw}iEd4vkCAWwa$ zbrHlEf3hfN7^1g~aW^XwldSmx1v~1z(s=1az4-wl} z`mM+G95*N*&1EP#u3}*KwNrPIgw8Kpp((rdEOO;bT1;6ea~>>sK+?!;{hpJ3rR<6UJb`O8P4@{XGgV%63_fs%cG8L zk9Fszbdo4tS$g0IWP1>t@0)E%-&9yj%Q!fiL2vcuL;90fPm}M==<>}Q)&sp@STFCY z^p!RzmN+uXGdtPJj1Y-khNyCb6Y$Vs>eZyW zPaOV=HY_T@FwAlleZCFYl@5X<<7%5DoO(7S%Lbl55?{2vIr_;SXBCbPZ(up;pC6Wx={AZL?shYOuFxLx1*>62;2rP}g`UT5+BHg(ju z&7n5QSvSyXbioB9CJTB#x;pexicV|9oaOpiJ9VK6EvKhl4^Vsa(p6cIi$*Zr0UxQ z;$MPOZnNae2Duuce~7|2MCfhNg*hZ9{+8H3?ts9C8#xGaM&sN;2lriYkn9W>&Gry! z3b(Xx1x*FhQkD-~V+s~KBfr4M_#0{`=Yrh90yj}Ph~)Nx;1Y^8<418tu!$1<3?T*~ z7Dl0P3Uok-7w0MPFQexNG1P5;y~E8zEvE49>$(f|XWtkW2Mj`udPn)pb%} zrA%wRFp*xvDgC767w!9`0vx1=q!)w!G+9(-w&p*a@WXg{?T&%;qaVcHo>7ca%KX$B z^7|KBPo<2;kM{2mRnF8vKm`9qGV%|I{y!pKm8B(q^2V;;x2r!1VJ^Zz8bWa)!-7a8 zSRf@dqEPlsj!7}oNvFFAA)75})vTJUwQ03hD$I*j6_5xbtd_JkE2`IJD_fQ;a$EkO z{fQ{~e%PKgPJsD&PyEvDmg+Qf&p*-qu!#;1k2r_(H72{^(Z)htgh@F?VIgK#_&eS- z$~(qInec>)XIkv@+{o6^DJLpAb>!d}l1DK^(l%#OdD9tKK6#|_R?-%0V!`<9Hj z3w3chDwG*SFte@>Iqwq`J4M&{aHXzyigT620+Vf$X?3RFfeTcvx_e+(&Q*z)t>c0e zpZH$1Z3X%{^_vylHVOWT6tno=l&$3 z9^eQ@TwU#%WMQaFvaYp_we%_2-9=o{+ck zF{cKJCOjpW&qKQquyp2BXCAP920dcrZ}T1@piukx_NY;%2W>@Wca%=Ch~x5Oj58Hv z;D-_ALOZBF(Mqbcqjd}P3iDbek#Dwzu`WRs`;hRIr*n0PV7vT+%Io(t}8KZ zpp?uc2eW!v28ipep0XNDPZt7H2HJ6oey|J3z!ng#1H~x_k%35P+Cp%mqXJ~cV0xdd z^4m5^K_dQ^Sg?$P`))ccV=O>C{Ds(C2WxX$LMC5vy=*44pP&)X5DOPYfqE${)hDg< z3hcG%U%HZ39=`#Ko4Uctg&@PQLf>?0^D|4J(_1*TFMOMB!Vv1_mnOq$BzXQdOGqgy zOp#LBZ!c>bPjY1NTXksZmbAl0A^Y&(%a3W-k>bE&>K?px5Cm%AT2E<&)Y?O*?d80d zgI5l~&Mve;iXm88Q+Fw7{+`PtN4G7~mJWR^z7XmYQ>uoiV!{tL)hp|= zS(M)813PM`d<501>{NqaPo6BZ^T{KBaqEVH(2^Vjeq zgeMeMpd*1tE@@);hGjuoVzF>Cj;5dNNwh40CnU+0DSKb~GEMb_# zT8Z&gz%SkHq6!;_6dQFYE`+b`v4NT7&@P>cA1Z1xmXy<2htaDhm@XXMp!g($ zw(7iFoH2}WR`UjqjaqOQ$ecNt@c|K1H1kyBArTTjLp%-M`4nzOhkfE#}dOpcd;b#suq8cPJ&bf5`6Tq>ND(l zib{VrPZ>{KuaIg}Y$W>A+nrvMg+l4)-@2jpAQ5h(Tii%Ni^-UPVg{<1KGU2EIUNGaXcEkOedJOusFT9X3%Pz$R+-+W+LlRaY-a$5r?4V zbPzgQl22IPG+N*iBRDH%l{Zh$fv9$RN1sU@Hp3m=M}{rX%y#;4(x1KR2yCO7Pzo>rw(67E{^{yUR`91nX^&MxY@FwmJJbyPAoWZ9Z zcBS$r)&ogYBn{DOtD~tIVJUiq|1foX^*F~O4hlLp-g;Y2wKLLM=?(r3GDqsPmUo*? zwKMEi*%f)C_@?(&&hk>;m07F$X7&i?DEK|jdRK=CaaNu-)pX>n3}@%byPKVkpLzBq z{+Py&!`MZ^4@-;iY`I4#6G@aWMv{^2VTH7|WF^u?3vsB|jU3LgdX$}=v7#EHRN(im zI(3q-eU$s~r=S#EWqa_2!G?b~ z<&brq1vvUTJH380=gcNntZw%7UT8tLAr-W49;9y^=>TDaTC|cKA<(gah#2M|l~j)w zY8goo28gj$n&zcNgqX1Qn6=<8?R0`FVO)g4&QtJAbW3G#D)uNeac-7cH5W#6i!%BH z=}9}-f+FrtEkkrQ?nkoMQ1o-9_b+&=&C2^h!&mWFga#MCrm85hW;)1pDt;-uvQG^D zntSB?XA*0%TIhtWDS!KcI}kp3LT>!(Nlc(lQN?k^bS8Q^GGMfo}^|%7s;#r+pybl@?KA++|FJ zr%se9(B|g*ERQU96az%@4gYrxRRxaM2*b}jNsG|0dQi;Rw{0WM0E>rko!{QYAJJKY z)|sX0N$!8d9E|kND~v|f>3YE|uiAnqbkMn)hu$if4kUkzKqoNoh8v|S>VY1EKmgO} zR$0UU2o)4i4yc1inx3}brso+sio{)gfbLaEgLahj8(_Z#4R-v) zglqwI%`dsY+589a8$Mu7#7_%kN*ekHupQ#48DIN^uhDxblDg3R1yXMr^NmkR z7J_NWCY~fhg}h!_aXJ#?wsZF$q`JH>JWQ9`jbZzOBpS`}-A$Vgkq7+|=lPx9H7QZG z8i8guMN+yc4*H*ANr$Q-3I{FQ-^;8ezWS2b8rERp9TMOLBxiG9J*g5=?h)mIm3#CGi4JSq1ohFrcrxx@`**K5%T}qbaCGldV!t zVeM)!U3vbf5FOy;(h08JnhSGxm)8Kqxr9PsMeWi=b8b|m_&^@#A3lL;bVKTBx+0v8 zLZeWAxJ~N27lsOT2b|qyp$(CqzqgW@tyy?CgwOe~^i;ZH zlL``i4r!>i#EGBNxV_P@KpYFQLz4Bdq{#zA&sc)*@7Mxsh9u%e6Ke`?5Yz1jkTdND zR8!u_yw_$weBOU}24(&^Bm|(dSJ(v(cBct}87a^X(v>nVLIr%%D8r|&)mi+iBc;B;x;rKq zd8*X`r?SZsTNCPQqoFOrUz8nZO?225Z#z(B!4mEp#ZJBzwd7jW1!`sg*?hPMJ$o`T zR?KrN6OZA1H{9pA;p0cSSu;@6->8aJm1rrO-yDJ7)lxuk#npUk7WNER1Wwnpy%u zF=t6iHzWU(L&=vVSSc^&D_eYP3TM?HN!Tgq$SYC;pSIPWW;zeNm7Pgub#yZ@7WPw#f#Kl)W4%B>)+8%gpfoH1qZ;kZ*RqfXYeGXJ_ zk>2otbp+1By`x^1V!>6k5v8NAK@T;89$`hE0{Pc@Q$KhG0jOoKk--Qx!vS~lAiypV zCIJ&6B@24`!TxhJ4_QS*S5;;Pk#!f(qIR7*(c3dN*POKtQe)QvR{O2@QsM%ujEAWEm) z+PM=G9hSR>gQ`Bv2(k}RAv2+$7qq(mU`fQ+&}*i%-RtSUAha>70?G!>?w%F(b4k!$ zvm;E!)2`I?etmSUFW7WflJ@8Nx`m_vE2HF#)_BiD#FaNT|IY@!uUbd4v$wTglIbIX zblRy5=wp)VQzsn0_;KdM%g<8@>#;E?vypTf=F?3f@SSdZ;XpX~J@l1;p#}_veWHp>@Iq_T z@^7|h;EivPYv1&u0~l9(a~>dV9Uw10QqB6Dzu1G~-l{*7IktljpK<_L8m0|7VV_!S zRiE{u97(%R-<8oYJ{molUd>vlGaE-C|^<`hppdDz<7OS13$#J zZ+)(*rZIDSt^Q$}CRk0?pqT5PN5TT`Ya{q(BUg#&nAsg6apPMhLTno!SRq1e60fl6GvpnwDD4N> z9B=RrufY8+g3_`@PRg+(+gs2(bd;5#{uTZk96CWz#{=&h9+!{_m60xJxC%r&gd_N! z>h5UzVX%_7@CUeAA1XFg_AF%(uS&^1WD*VPS^jcC!M2v@RHZML;e(H-=(4(3O&bX- zI6>usJOS+?W&^S&DL{l|>51ZvCXUKlH2XKJPXnHjs*oMkNM#ZDLx!oaM5(%^)5XaP zk6&+P16sA>vyFe9v`Cp5qnbE#r#ltR5E+O3!WnKn`56Grs2;sqr3r# zp@Zp<^q`5iq8OqOlJ`pIuyK@3zPz&iJ0Jcc`hDQ1bqos2;}O|$i#}e@ua*x5VCSx zJAp}+?Hz++tm9dh3Fvm_bO6mQo38al#>^O0g)Lh^&l82+&x)*<n7^Sw-AJo9tEzZDwyJ7L^i7|BGqHu+ea6(&7jKpBq>~V z8CJxurD)WZ{5D0?s|KMi=e7A^JVNM6sdwg@1Eg_+Bw=9j&=+KO1PG|y(mP1@5~x>d z=@c{EWU_jTSjiJl)d(>`qEJ;@iOBm}alq8;OK;p(1AdH$)I9qHNmxxUArdzBW0t+Qeyl)m3?D09770g z)hzXEOy>2_{?o%2B%k%z4d23!pZcoxyW1Ik{|m7Q1>fm4`wsRrl)~h z_=Z*zYL+EG@DV1{6@5@(Ndu!Q$l_6Qlfoz@79q)Kmsf~J7t1)tl#`MD<;1&CAA zH8;i+oBm89dTTDl{aH`cmTPTt@^K-%*sV+t4X9q0Z{A~vEEa!&rRRr=0Rbz4NFCJr zLg2u=0QK@w9XGE=6(-JgeP}G#WG|R&tfHRA3a9*zh5wNTBAD;@YYGx%#E4{C#Wlfo z%-JuW9=FA_T6mR2-Vugk1uGZvJbFvVVWT@QOWz$;?u6+CbyQsbK$>O1APk|xgnh_8 zc)s@Mw7#0^wP6qTtyNq2G#s?5j~REyoU6^lT7dpX{T-rhZWHD%dik*=EA7bIJgOVf_Ga!yC8V^tkTOEHe+JK@Fh|$kfNxO^= z#lpV^(ZQ-3!^_BhV>aXY~GC9{8%1lOJ}6vzXDvPhC>JrtXwFBC+!3a*Z-%#9}i z#<5&0LLIa{q!rEIFSFc9)>{-_2^qbOg5;_A9 ztQ))C6#hxSA{f9R3Eh^`_f${pBJNe~pIQ`tZVR^wyp}=gLK}e5_vG@w+-mp#Fu>e| z*?qBp5CQ5zu+Fi}xAs)YY1;bKG!htqR~)DB$ILN6GaChoiy%Bq@i+1ZnANC0U&D z_4k$=YP47ng+0NhuEt}6C;9-JDd8i5S>`Ml==9wHDQFOsAlmtrVwurYDw_)Ihfk35 zJDBbe!*LUpg%4n>BExWz>KIQ9vexUu^d!7rc_kg#Bf= z7TLz|l*y*3d2vi@c|pX*@ybf!+Xk|2*z$@F4K#MT8Dt4zM_EcFmNp31#7qT6(@GG? zdd;sSY9HHuDb=w&|K%sm`bYX#%UHKY%R`3aLMO?{T#EI@FNNFNO>p@?W*i0z(g2dt z{=9Ofh80Oxv&)i35AQN>TPMjR^UID-T7H5A?GI{MD_VeXZ%;uo41dVm=uT&ne2h0i zv*xI%9vPtdEK@~1&V%p1sFc2AA`9?H)gPnRdlO~URx!fiSV)j?Tf5=5F>hnO=$d$x zzaIfr*wiIc!U1K*$JO@)gP4%xp!<*DvJSv7p}(uTLUb=MSb@7_yO+IsCj^`PsxEl& zIxsi}s3L?t+p+3FXYqujGhGwTx^WXgJ1}a@Yq5mwP0PvGEr*qu7@R$9j>@-q1rz5T zriz;B^(ex?=3Th6h;7U`8u2sDlfS{0YyydK=*>-(NOm9>S_{U|eg(J~C7O zIe{|LK=Y`hXiF_%jOM8Haw3UtaE{hWdzo3BbD6ud7br4cODBtN(~Hl+odP0SSWPw;I&^m)yLw+nd#}3#z}?UIcX3=SssI}`QwY=% zAEXTODk|MqTx}2DVG<|~(CxgLyi*A{m>M@1h^wiC)4Hy>1K7@|Z&_VPJsaQoS8=ex zDL&+AZdQa>ylxhT_Q$q=60D5&%pi6+qlY3$3c(~rsITX?>b;({FhU!7HOOhSP7>bmTkC8KM%!LRGI^~y3Ug+gh!QM=+NZXznM)?L3G=4=IMvFgX3BAlyJ z`~jjA;2z+65D$j5xbv9=IWQ^&-K3Yh`vC(1Qz2h2`o$>Cej@XRGff!it$n{@WEJ^N z41qk%Wm=}mA*iwCqU_6}Id!SQd13aFER3unXaJJXIsSnxvG2(hSCP{i&QH$tL&TPx zDYJsuk+%laN&OvKb-FHK$R4dy%M7hSB*yj#-nJy?S9tVoxAuDei{s}@+pNT!vLOIC z8g`-QQW8FKp3cPsX%{)0B+x+OhZ1=L7F-jizt|{+f1Ga7%+!BXqjCjH&x|3%?UbN# zh?$I1^YokvG$qFz5ySK+Ja5=mkR&p{F}ev**rWdKMko+Gj^?Or=UH?SCg#0F(&a_y zXOh}dPv0D9l0RVedq1~jCNV=8?vZfU-Xi|nkeE->;ohG3U7z+^0+HV17~-_Mv#mV` zzvwUJJ15v5wwKPv-)i@dsEo@#WEO9zie7mdRAbgL2kjbW4&lk$vxkbq=w5mGKZK6@ zjXWctDkCRx58NJD_Q7e}HX`SiV)TZMJ}~zY6P1(LWo`;yDynY_5_L?N-P`>ALfmyl z8C$a~FDkcwtzK9m$tof>(`Vu3#6r#+v8RGy#1D2)F;vnsiL&P-c^PO)^B-4VeJteLlT@25sPa z%W~q5>YMjj!mhN})p$47VA^v$Jo6_s{!y?}`+h+VM_SN`!11`|;C;B};B&Z<@%FOG z_YQVN+zFF|q5zKab&e4GH|B;sBbKimHt;K@tCH+S{7Ry~88`si7}S)1E{21nldiu5 z_4>;XTJa~Yd$m4A9{Qbd)KUAm7XNbZ4xHbg3a8-+1uf*$1PegabbmCzgC~1WB2F(W zYj5XhVos!X!QHuZXCatkRsdEsSCc+D2?*S7a+(v%toqyxhjz|`zdrUvsxQS{J>?c& zvx*rHw^8b|v^7wq8KWVofj&VUitbm*a&RU_ln#ZFA^3AKEf<#T%8I!Lg3XEsdH(A5 zlgh&M_XEoal)i#0tcq8c%Gs6`xu;vvP2u)D9p!&XNt z!TdF_H~;`g@fNXkO-*t<9~;iEv?)Nee%hVe!aW`N%$cFJ(Dy9+Xk*odyFj72T!(b%Vo5zvCGZ%3tkt$@Wcx8BWEkefI1-~C_3y*LjlQ5%WEz9WD8i^ z2MV$BHD$gdPJV4IaV)G9CIFwiV=ca0cfXdTdK7oRf@lgyPx;_7*RRFk=?@EOb9Gcz zg~VZrzo*Snp&EE{$CWr)JZW)Gr;{B2ka6B!&?aknM-FENcl%45#y?oq9QY z3^1Y5yn&^D67Da4lI}ljDcphaEZw2;tlYuzq?uB4b9Mt6!KTW&ptxd^vF;NbX=00T z@nE1lIBGgjqs?ES#P{ZfRb6f!At51vk%<0X%d_~NL5b8UyfQMPDtfU@>ijA0NP3UU zh{lCf`Wu7cX!go`kUG`1K=7NN@SRGjUKuo<^;@GS!%iDXbJs`o6e`v3O8-+7vRkFm z)nEa$sD#-v)*Jb>&Me+YIW3PsR1)h=-Su)))>-`aRcFJG-8icomO4J@60 zw10l}BYxi{eL+Uu0xJYk-Vc~BcR49Qyyq!7)PR27D`cqGrik=?k1Of>gY7q@&d&Ds zt7&WixP`9~jjHO`Cog~RA4Q%uMg+$z^Gt&vn+d3&>Ux{_c zm|bc;k|GKbhZLr-%p_f%dq$eiZ;n^NxoS-Nu*^Nx5vm46)*)=-Bf<;X#?`YC4tLK; z?;u?shFbXeks+dJ?^o$l#tg*1NA?(1iFff@I&j^<74S!o;SWR^Xi);DM%8XiWpLi0 zQE2dL9^a36|L5qC5+&Pf0%>l&qQ&)OU4vjd)%I6{|H+pw<0(a``9w(gKD&+o$8hOC zNAiShtc}e~ob2`gyVZx59y<6Fpl*$J41VJ-H*e-yECWaDMmPQi-N8XI3 z%iI@ljc+d}_okL1CGWffeaejlxWFVDWu%e=>H)XeZ|4{HlbgC-Uvof4ISYQzZ0Um> z#Ov{k1c*VoN^f(gfiueuag)`TbjL$XVq$)aCUBL_M`5>0>6Ska^*Knk__pw{0I>jA zzh}Kzg{@PNi)fcAk7jMAdi-_RO%x#LQszDMS@_>iFoB+zJ0Q#CQJzFGa8;pHFdi`^ zxnTC`G$7Rctm3G8t8!SY`GwFi4gF|+dAk7rh^rA{NXzc%39+xSYM~($L(pJ(8Zjs* zYdN_R^%~LiGHm9|ElV4kVZGA*T$o@YY4qpJOxGHlUi*S*A(MrgQ{&xoZQo+#PuYRs zv3a$*qoe9gBqbN|y|eaH=w^LE{>kpL!;$wRahY(hhzRY;d33W)m*dfem@)>pR54Qy z ze;^F?mwdU?K+=fBabokSls^6_6At#1Sh7W*y?r6Ss*dmZP{n;VB^LDxM1QWh;@H0J z!4S*_5j_;+@-NpO1KfQd&;C7T`9ak;X8DTRz$hDNcjG}xAfg%gwZSb^zhE~O);NMO zn2$fl7Evn%=Lk!*xsM#(y$mjukN?A&mzEw3W5>_o+6oh62kq=4-`e3B^$rG=XG}Kd zK$blh(%!9;@d@3& zGFO60j1Vf54S}+XD?%*uk7wW$f`4U3F*p7@I4Jg7f`Il}2H<{j5h?$DDe%wG7jZQL zI{mj?t?Hu>$|2UrPr5&QyK2l3mas?zzOk0DV30HgOQ|~xLXDQ8M3o#;CNKO8RK+M; zsOi%)js-MU>9H4%Q)#K_me}8OQC1u;f4!LO%|5toa1|u5Q@#mYy8nE9IXmR}b#sZK z3sD395q}*TDJJA9Er7N`y=w*S&tA;mv-)Sx4(k$fJBxXva0_;$G6!9bGBw13c_Uws zXks4u(8JA@0O9g5f?#V~qR5*u5aIe2HQO^)RW9TTcJk28l`Syl>Q#ZveEE4Em+{?%iz6=V3b>rCm9F zPQQm@-(hfNdo2%n?B)u_&Qh7^^@U>0qMBngH8}H|v+Ejg*Dd(Y#|jgJ-A zQ_bQscil%eY}8oN7ZL+2r|qv+iJY?*l)&3W_55T3GU;?@Om*(M`u0DXAsQ7HSl56> z4P!*(%&wRCb?a4HH&n;lAmr4rS=kMZb74Akha2U~Ktni>>cD$6jpugjULq)D?ea%b zk;UW0pAI~TH59P+o}*c5Ei5L-9OE;OIBt>^(;xw`>cN2`({Rzg71qrNaE=cAH^$wP zNrK9Glp^3a%m+ilQj0SnGq`okjzmE7<3I{JLD6Jn^+oas=h*4>Wvy=KXqVBa;K&ri z4(SVmMXPG}0-UTwa2-MJ=MTfM3K)b~DzSVq8+v-a0&Dsv>4B65{dBhD;(d44CaHSM zb!0ne(*<^Q%|nuaL`Gb3D4AvyO8wyygm=1;9#u5x*k0$UOwx?QxR*6Od8>+ujfyo0 zJ}>2FgW_iv(dBK2OWC-Y=Tw!UwIeOAOUUC;h95&S1hn$G#if+d;*dWL#j#YWswrz_ zMlV=z+zjZJ%SlDhxf)vv@`%~$Afd)T+MS1>ZE7V$Rj#;J*<9Ld=PrK0?qrazRJWx) z(BTLF@Wk279nh|G%ZY7_lK7=&j;x`bMND=zgh_>>-o@6%8_#Bz!FnF*onB@_k|YCF z?vu!s6#h9bL3@tPn$1;#k5=7#s*L;FLK#=M89K^|$3LICYWIbd^qguQp02w5>8p-H z+@J&+pP_^iF4Xu>`D>DcCnl8BUwwOlq6`XkjHNpi@B?OOd`4{dL?kH%lt78(-L}eah8?36zw9d-dI6D{$s{f=M7)1 zRH1M*-82}DoFF^Mi$r}bTB5r6y9>8hjL54%KfyHxn$LkW=AZ(WkHWR;tIWWr@+;^^ zVomjAWT)$+rn%g`LHB6ZSO@M3KBA? z+W7ThSBgpk`jZHZUrp`F;*%6M5kLWy6AW#T{jFHTiKXP9ITrMlEdti7@&AT_a-BA!jc(Kt zWk>IdY-2Zbz?U1)tk#n_Lsl?W;0q`;z|t9*g-xE!(}#$fScX2VkjSiboKWE~afu5d z2B@9mvT=o2fB_>Mnie=TDJB+l`GMKCy%2+NcFsbpv<9jS@$X37K_-Y!cvF5NEY`#p z3sWEc<7$E*X*fp+MqsOyMXO=<2>o8)E(T?#4KVQgt=qa%5FfUG_LE`n)PihCz2=iNUt7im)s@;mOc9SR&{`4s9Q6)U31mn?}Y?$k3kU z#h??JEgH-HGt`~%)1ZBhT9~uRi8br&;a5Y3K_Bl1G)-y(ytx?ok9S*Tz#5Vb=P~xH z^5*t_R2It95=!XDE6X{MjLYn4Eszj9Y91T2SFz@eYlx9Z9*hWaS$^5r7=W5|>sY8}mS(>e9Ez2qI1~wtlA$yv2e-Hjn&K*P z2zWSrC~_8Wrxxf#%QAL&f8iH2%R)E~IrQLgWFg8>`Vnyo?E=uiALoRP&qT{V2{$79 z%9R?*kW-7b#|}*~P#cA@q=V|+RC9=I;aK7Pju$K-n`EoGV^-8Mk=-?@$?O37evGKn z3NEgpo_4{s>=FB}sqx21d3*=gKq-Zk)U+bM%Q_}0`XGkYh*+jRaP+aDnRv#Zz*n$pGp zEU9omuYVXH{AEx>=kk}h2iKt!yqX=EHN)LF}z1j zJx((`CesN1HxTFZ7yrvA2jTPmKYVij>45{ZH2YtsHuGzIRotIFj?(8T@ZWUv{_%AI zgMZlB03C&FtgJqv9%(acqt9N)`4jy4PtYgnhqev!r$GTIOvLF5aZ{tW5MN@9BDGu* zBJzwW3sEJ~Oy8is`l6Ly3an7RPtRr^1Iu(D!B!0O241Xua>Jee;Rc7tWvj!%#yX#m z&pU*?=rTVD7pF6va1D@u@b#V@bShFr3 zMyMbNCZwT)E-%L-{%$3?n}>EN>ai7b$zR_>=l59mW;tfKj^oG)>_TGCJ#HbLBsNy$ zqAqPagZ3uQ(Gsv_-VrZmG&hHaOD#RB#6J8&sL=^iMFB=gH5AIJ+w@sTf7xa&Cnl}@ zxrtzoNq>t?=(+8bS)s2p3>jW}tye0z2aY_Dh@(18-vdfvn;D?sv<>UgL{Ti08$1Q+ zZI3q}yMA^LK=d?YVg({|v?d1|R?5 zL0S3fw)BZazRNNX|7P4rh7!+3tCG~O8l+m?H} z(CB>8(9LtKYIu3ohJ-9ecgk+L&!FX~Wuim&;v$>M4 zUfvn<=Eok(63Ubc>mZrd8d7(>8bG>J?PtOHih_xRYFu1Hg{t;%+hXu2#x%a%qzcab zv$X!ccoj)exoOnaco_jbGw7KryOtuf(SaR-VJ0nAe(1*AA}#QV1lMhGtzD>RoUZ;WA?~!K{8%chYn?ttlz17UpDLlhTkGcVfHY6R<2r4E{mU zq-}D?+*2gAkQYAKrk*rB%4WFC-B!eZZLg4(tR#@kUQHIzEqV48$9=Q(~J_0 zy1%LSCbkoOhRO!J+Oh#;bGuXe;~(bIE*!J@i<%_IcB7wjhB5iF#jBn5+u~fEECN2* z!QFh!m<(>%49H12Y33+?$JxKV3xW{xSs=gxkxW-@Xds^|O1`AmorDKrE8N2-@ospk z=Au%h=f!`_X|G^A;XWL}-_L@D6A~*4Yf!5RTTm$!t8y&fp5_oqvBjW{FufS`!)5m% z2g(=9Ap6Y2y(9OYOWuUVGp-K=6kqQ)kM0P^TQT{X{V$*sN$wbFb-DaUuJF*!?EJPl zJev!UsOB^UHZ2KppYTELh+kqDw+5dPFv&&;;C~=u$Mt+Ywga!8YkL2~@g67}3wAQP zrx^RaXb1(c7vwU8a2se75X(cX^$M{FH4AHS7d2}heqqg4F0!1|Na>UtAdT%3JnS!B)&zelTEj$^b0>Oyfw=P-y-Wd^#dEFRUN*C{!`aJIHi<_YA2?piC%^ zj!p}+ZnBrM?ErAM+D97B*7L8U$K zo(IR-&LF(85p+fuct9~VTSdRjs`d-m|6G;&PoWvC&s8z`TotPSoksp;RsL4VL@CHf z_3|Tn%`ObgRhLmr60<;ya-5wbh&t z#ycN_)3P_KZN5CRyG%LRO4`Ot)3vY#dNX9!f!`_>1%4Q`81E*2BRg~A-VcN7pcX#j zrbl@7`V%n z6J53(m?KRzKb)v?iCuYWbH*l6M77dY4keS!%>}*8n!@ROE4!|7mQ+YS4dff1JJC(t z6Fnuf^=dajqHpH1=|pb(po9Fr8it^;2dEk|Ro=$fxqK$^Yix{G($0m-{RCFQJ~LqUnO7jJcjr zl*N*!6WU;wtF=dLCWzD6kW;y)LEo=4wSXQDIcq5WttgE#%@*m><@H;~Q&GniA-$in z`sjWFLgychS1kIJmPtd-w6%iKkj&dGhtB%0)pyy0M<4HZ@ZY0PWLAd7FCrj&i|NRh?>hZj*&FYnyu%Ur`JdiTu&+n z78d3n)Rl6q&NwVj_jcr#s5G^d?VtV8bkkYco5lV0LiT+t8}98LW>d)|v|V3++zLbHC(NC@X#Hx?21J0M*gP2V`Yd^DYvVIr{C zSc4V)hZKf|OMSm%FVqSRC!phWSyuUAu%0fredf#TDR$|hMZihJ__F!)Nkh6z)d=NC z3q4V*K3JTetxCPgB2_)rhOSWhuXzu+%&>}*ARxUaDeRy{$xK(AC0I=9%X7dmc6?lZNqe-iM(`?Xn3x2Ov>sej6YVQJ9Q42>?4lil?X zew-S>tm{=@QC-zLtg*nh5mQojYnvVzf3!4TpXPuobW_*xYJs;9AokrXcs!Ay z;HK>#;G$*TPN2M!WxdH>oDY6k4A6S>BM0Nimf#LfboKxJXVBC=RBuO&g-=+@O-#0m zh*aPG16zY^tzQLNAF7L(IpGPa+mDsCeAK3k=IL6^LcE8l0o&)k@?dz!79yxUquQIe($zm5DG z5RdXTv)AjHaOPv6z%99mPsa#8OD@9=URvHoJ1hYnV2bG*2XYBgB!-GEoP&8fLmWGg z9NG^xl5D&3L^io&3iYweV*qhc=m+r7C#Jppo$Ygg;jO2yaFU8+F*RmPL` zYxfGKla_--I}YUT353k}nF1zt2NO?+kofR8Efl$Bb^&llgq+HV_UYJUH7M5IoN0sT z4;wDA0gs55ZI|FmJ0}^Pc}{Ji-|#jdR$`!s)Di4^g3b_Qr<*Qu2rz}R6!B^;`Lj3sKWzjMYjexX)-;f5Y+HfkctE{PstO-BZan0zdXPQ=V8 zS8cBhnQyy4oN?J~oK0zl!#S|v6h-nx5to7WkdEk0HKBm;?kcNO*A+u=%f~l&aY*+J z>%^Dz`EQ6!+SEX$>?d(~|MNWU-}JTrk}&`IR|Ske(G^iMdk04)Cxd@}{1=P0U*%L5 zMFH_$R+HUGGv|ju2Z>5x(-aIbVJLcH1S+(E#MNe9g;VZX{5f%_|Kv7|UY-CM(>vf= z!4m?QS+AL+rUyfGJ;~uJGp4{WhOOc%2ybVP68@QTwI(8kDuYf?#^xv zBmOHCZU8O(x)=GVFn%tg@TVW1)qJJ_bU}4e7i>&V?r zh-03>d3DFj&@}6t1y3*yOzllYQ++BO-q!)zsk`D(z||)y&}o%sZ-tUF>0KsiYKFg6 zTONq)P+uL5Vm0w{D5Gms^>H1qa&Z##*X31=58*r%Z@Ko=IMXX{;aiMUp-!$As3{sq z0EEk02MOsgGm7$}E%H1ys2$yftNbB%1rdo@?6~0!a8Ym*1f;jIgfcYEF(I_^+;Xdr z2a>&oc^dF3pm(UNpazXgVzuF<2|zdPGjrNUKpdb$HOgNp*V56XqH`~$c~oSiqx;8_ zEz3fHoU*aJUbFJ&?W)sZB3qOSS;OIZ=n-*#q{?PCXi?Mq4aY@=XvlNQdA;yVC0Vy+ z{Zk6OO!lMYWd`T#bS8FV(`%flEA9El;~WjZKU1YmZpG#49`ku`oV{Bdtvzyz3{k&7 zlG>ik>eL1P93F zd&!aXluU_qV1~sBQf$F%sM4kTfGx5MxO0zJy<#5Z&qzNfull=k1_CZivd-WAuIQf> zBT3&WR|VD|=nKelnp3Q@A~^d_jN3@$x2$f@E~e<$dk$L@06Paw$);l*ewndzL~LuU zq`>vfKb*+=uw`}NsM}~oY}gW%XFwy&A>bi{7s>@(cu4NM;!%ieP$8r6&6jfoq756W z$Y<`J*d7nK4`6t`sZ;l%Oen|+pk|Ry2`p9lri5VD!Gq`U#Ms}pgX3ylAFr8(?1#&dxrtJgB>VqrlWZf61(r`&zMXsV~l{UGjI7R@*NiMJLUoK*kY&gY9kC@^}Fj* zd^l6_t}%Ku<0PY71%zQL`@}L}48M!@=r)Q^Ie5AWhv%#l+Rhu6fRpvv$28TH;N7Cl z%I^4ffBqx@Pxpq|rTJV)$CnxUPOIn`u278s9#ukn>PL25VMv2mff)-RXV&r`Dwid7}TEZxXX1q(h{R6v6X z&x{S_tW%f)BHc!jHNbnrDRjGB@cam{i#zZK*_*xlW@-R3VDmp)<$}S%t*@VmYX;1h zFWmpXt@1xJlc15Yjs2&e%)d`fimRfi?+fS^BoTcrsew%e@T^}wyVv6NGDyMGHSKIQ zC>qFr4GY?#S#pq!%IM_AOf`#}tPoMn7JP8dHXm(v3UTq!aOfEXNRtEJ^4ED@jx%le zvUoUs-d|2(zBsrN0wE(Pj^g5wx{1YPg9FL1)V1JupsVaXNzq4fX+R!oVX+q3tG?L= z>=s38J_!$eSzy0m?om6Wv|ZCbYVHDH*J1_Ndajoh&?L7h&(CVii&rmLu+FcI;1qd_ zHDb3Vk=(`WV?Uq;<0NccEh0s`mBXcEtmwt6oN99RQt7MNER3`{snV$qBTp={Hn!zz z1gkYi#^;P8s!tQl(Y>|lvz{5$uiXsitTD^1YgCp+1%IMIRLiSP`sJru0oY-p!FPbI)!6{XM%)(_Dolh1;$HlghB-&e><;zU&pc=ujpa-(+S&Jj zX1n4T#DJDuG7NP;F5TkoG#qjjZ8NdXxF0l58RK?XO7?faM5*Z17stidTP|a%_N z^e$D?@~q#Pf+708cLSWCK|toT1YSHfXVIs9Dnh5R(}(I;7KhKB7RD>f%;H2X?Z9eR z{lUMuO~ffT!^ew= z7u13>STI4tZpCQ?yb9;tSM-(EGb?iW$a1eBy4-PVejgMXFIV_Ha^XB|F}zK_gzdhM z!)($XfrFHPf&uyFQf$EpcAfk83}91Y`JFJOiQ;v5ca?)a!IxOi36tGkPk4S6EW~eq z>WiK`Vu3D1DaZ}515nl6>;3#xo{GQp1(=uTXl1~ z4gdWxr-8a$L*_G^UVd&bqW_nzMM&SlNW$8|$lAfo@zb+P>2q?=+T^qNwblP*RsN?N zdZE%^Zs;yAwero1qaoqMp~|KL=&npffh981>2om!fseU(CtJ=bW7c6l{U5(07*e0~ zJRbid6?&psp)ilmYYR3ZIg;t;6?*>hoZ3uq7dvyyq-yq$zH$yyImjfhpQb@WKENSP zl;KPCE+KXzU5!)mu12~;2trrLfs&nlEVOndh9&!SAOdeYd}ugwpE-9OF|yQs(w@C9 zoXVX`LP~V>%$<(%~tE*bsq(EFm zU5z{H@Fs^>nm%m%wZs*hRl=KD%4W3|(@j!nJr{Mmkl`e_uR9fZ-E{JY7#s6i()WXB0g-b`R{2r@K{2h3T+a>82>722+$RM*?W5;Bmo6$X3+Ieg9&^TU(*F$Q3 zT572!;vJeBr-)x?cP;^w1zoAM`nWYVz^<6N>SkgG3s4MrNtzQO|A?odKurb6DGZffo>DP_)S0$#gGQ_vw@a9JDXs2}hV&c>$ zUT0;1@cY5kozKOcbN6)n5v)l#>nLFL_x?2NQgurQH(KH@gGe>F|$&@ zq@2A!EXcIsDdzf@cWqElI5~t z4cL9gg7{%~4@`ANXnVAi=JvSsj95-7V& zME3o-%9~2?cvlH#twW~99=-$C=+b5^Yv}Zh4;Mg-!LS zw>gqc=}CzS9>v5C?#re>JsRY!w|Mtv#%O3%Ydn=S9cQarqkZwaM4z(gL~1&oJZ;t; zA5+g3O6itCsu93!G1J_J%Icku>b3O6qBW$1Ej_oUWc@MI)| zQ~eyS-EAAnVZp}CQnvG0N>Kc$h^1DRJkE7xZqJ0>p<>9*apXgBMI-v87E0+PeJ-K& z#(8>P_W^h_kBkI;&e_{~!M+TXt@z8Po*!L^8XBn{of)knd-xp{heZh~@EunB2W)gd zAVTw6ZZasTi>((qpBFh(r4)k zz&@Mc@ZcI-4d639AfcOgHOU+YtpZ)rC%Bc5gw5o~+E-i+bMm(A6!uE>=>1M;V!Wl4 z<#~muol$FsY_qQC{JDc8b=$l6Y_@_!$av^08`czSm!Xan{l$@GO-zPq1s>WF)G=wv zDD8j~Ht1pFj)*-b7h>W)@O&m&VyYci&}K|0_Z*w`L>1jnGfCf@6p}Ef*?wdficVe_ zmPRUZ(C+YJU+hIj@_#IiM7+$4kH#VS5tM!Ksz01siPc-WUe9Y3|pb4u2qnn zRavJiRpa zq?tr&YV?yKt<@-kAFl3s&Kq#jag$hN+Y%%kX_ytvpCsElgFoN3SsZLC>0f|m#&Jhu zp7c1dV$55$+k78FI2q!FT}r|}cIV;zp~#6X2&}22$t6cHx_95FL~T~1XW21VFuatb zpM@6w>c^SJ>Pq6{L&f9()uy)TAWf;6LyHH3BUiJ8A4}od)9sriz~e7}l7Vr0e%(=>KG1Jay zW0azuWC`(|B?<6;R)2}aU`r@mt_#W2VrO{LcX$Hg9f4H#XpOsAOX02x^w9+xnLVAt z^~hv2guE-DElBG+`+`>PwXn5kuP_ZiOO3QuwoEr)ky;o$n7hFoh}Aq0@Ar<8`H!n} zspCC^EB=6>$q*gf&M2wj@zzfBl(w_@0;h^*fC#PW9!-kT-dt*e7^)OIU{Uw%U4d#g zL&o>6`hKQUps|G4F_5AuFU4wI)(%9(av7-u40(IaI|%ir@~w9-rLs&efOR@oQy)}{ z&T#Qf`!|52W0d+>G!h~5A}7VJky`C3^fkJzt3|M&xW~x-8rSi-uz=qBsgODqbl(W#f{Ew#ui(K)(Hr&xqZs` zfrK^2)tF#|U=K|_U@|r=M_Hb;qj1GJG=O=d`~#AFAccecIaq3U`(Ds1*f*TIs=IGL zp_vlaRUtFNK8(k;JEu&|i_m39c(HblQkF8g#l|?hPaUzH2kAAF1>>Yykva0;U@&oRV8w?5yEK??A0SBgh?@Pd zJg{O~4xURt7!a;$rz9%IMHQeEZHR8KgFQixarg+MfmM_OeX#~#&?mx44qe!wt`~dd zqyt^~ML>V>2Do$huU<7}EF2wy9^kJJSm6HoAD*sRz%a|aJWz_n6?bz99h)jNMp}3k ztPVbos1$lC1nX_OK0~h>=F&v^IfgBF{#BIi&HTL}O7H-t4+wwa)kf3AE2-Dx@#mTA z!0f`>vz+d3AF$NH_-JqkuK1C+5>yns0G;r5ApsU|a-w9^j4c+FS{#+7- zH%skr+TJ~W_8CK_j$T1b;$ql_+;q6W|D^BNK*A+W5XQBbJy|)(IDA=L9d>t1`KX2b zOX(Ffv*m?e>! zS3lc>XC@IqPf1g-%^4XyGl*1v0NWnwZTW?z4Y6sncXkaA{?NYna3(n@(+n+#sYm}A zGQS;*Li$4R(Ff{obl3#6pUsA0fKuWurQo$mWXMNPV5K66V!XYOyc})^>889Hg3I<{V^Lj9($B4Zu$xRr=89-lDz9x`+I8q(vEAimx1K{sTbs|5x7S zZ+7o$;9&9>@3K;5-DVzGw=kp7ez%1*kxhGytdLS>Q)=xUWv3k_x(IsS8we39Tijvr z`GKk>gkZTHSht;5q%fh9z?vk%sWO}KR04G9^jleJ^@ovWrob7{1xy7V=;S~dDVt%S za$Q#Th%6g1(hiP>hDe}7lcuI94K-2~Q0R3A1nsb7Y*Z!DtQ(Ic<0;TDKvc6%1kBdJ z$hF!{uALB0pa?B^TC}#N5gZ|CKjy|BnT$7eaKj;f>Alqdb_FA3yjZ4CCvm)D&ibL) zZRi91HC!TIAUl<|`rK_6avGh`!)TKk=j|8*W|!vb9>HLv^E%t$`@r@piI(6V8pqDG zBON7~=cf1ZWF6jc{qkKm;oYBtUpIdau6s+<-o^5qNi-p%L%xAtn9OktFd{@EjVAT% z#?-MJ5}Q9QiK_jYYWs+;I4&!N^(mb!%4zx7qO6oCEDn=8oL6#*9XIJ&iJ30O`0vsFy|fEVkw}*jd&B6!IYi+~Y)qv6QlM&V9g0 zh)@^BVDB|P&#X{31>G*nAT}Mz-j~zd>L{v{9AxrxKFw8j;ccQ$NE0PZCc(7fEt1xd z`(oR2!gX6}R+Z77VkDz^{I)@%&HQT5q+1xlf*3R^U8q%;IT8-B53&}dNA7GW`Ki&= z$lrdH zDCu;j$GxW<&v_4Te7=AE2J0u1NM_7Hl9$u{z(8#%8vvrx2P#R7AwnY|?#LbWmROa; zOJzU_*^+n(+k;Jd{e~So9>OF>fPx$Hb$?~K1ul2xr>>o@**n^6IMu8+o3rDp(X$cC z`wQt9qIS>yjA$K~bg{M%kJ00A)U4L+#*@$8UlS#lN3YA{R{7{-zu#n1>0@(#^eb_% zY|q}2)jOEM8t~9p$X5fpT7BZQ1bND#^Uyaa{mNcFWL|MoYb@>y`d{VwmsF&haoJuS2W7azZU0{tu#Jj_-^QRc35tjW~ae&zhKk!wD}#xR1WHu z_7Fys#bp&R?VXy$WYa$~!dMxt2@*(>@xS}5f-@6eoT%rwH zv_6}M?+piNE;BqaKzm1kK@?fTy$4k5cqYdN8x-<(o6KelwvkTqC3VW5HEnr+WGQlF zs`lcYEm=HPpmM4;Ich7A3a5Mb3YyQs7(Tuz-k4O0*-YGvl+2&V(B&L1F8qfR0@vQM-rF<2h-l9T12eL}3LnNAVyY_z51xVr$%@VQ-lS~wf3mnHc zoM({3Z<3+PpTFCRn_Y6cbxu9v>_>eTN0>hHPl_NQQuaK^Mhrv zX{q#80ot;ptt3#js3>kD&uNs{G0mQp>jyc0GG?=9wb33hm z`y2jL=J)T1JD7eX3xa4h$bG}2ev=?7f>-JmCj6){Upo&$k{2WA=%f;KB;X5e;JF3IjQBa4e-Gp~xv- z|In&Rad7LjJVz*q*+splCj|{7=kvQLw0F@$vPuw4m^z=B^7=A4asK_`%lEf_oIJ-O z{L)zi4bd#&g0w{p1$#I&@bz3QXu%Y)j46HAJKWVfRRB*oXo4lIy7BcVl4hRs<%&iQ zr|)Z^LUJ>qn>{6y`JdabfNNFPX7#3`x|uw+z@h<`x{J4&NlDjnknMf(VW_nKWT!Jh zo1iWBqT6^BR-{T=4Ybe+?6zxP_;A5Uo{}Xel%*=|zRGm1)pR43K39SZ=%{MDCS2d$~}PE-xPw4ZK6)H;Zc&0D5p!vjCn0wCe&rVIhchR9ql!p2`g0b@JsC^J#n_r*4lZ~u0UHKwo(HaHUJDHf^gdJhTdTW z3i7Zp_`xyKC&AI^#~JMVZj^9WsW}UR#nc#o+ifY<4`M+?Y9NTBT~p`ONtAFf8(ltr*ER-Ig!yRs2xke#NN zkyFcaQKYv>L8mQdrL+#rjgVY>Z2_$bIUz(kaqL}cYENh-2S6BQK-a(VNDa_UewSW` zMgHi<3`f!eHsyL6*^e^W7#l?V|42CfAjsgyiJsA`yNfAMB*lAsJj^K3EcCzm1KT zDU2+A5~X%ax-JJ@&7>m`T;;}(-e%gcYQtj}?ic<*gkv)X2-QJI5I0tA2`*zZRX(;6 zJ0dYfMbQ+{9Rn3T@Iu4+imx3Y%bcf2{uT4j-msZ~eO)5Z_T7NC|Nr3)|NWjomhv=E zXaVin)MY)`1QtDyO7mUCjG{5+o1jD_anyKn73uflH*ASA8rm+S=gIfgJ);>Zx*hNG z!)8DDCNOrbR#9M7Ud_1kf6BP)x^p(|_VWCJ+(WGDbYmnMLWc?O4zz#eiP3{NfP1UV z(n3vc-axE&vko^f+4nkF=XK-mnHHQ7>w05$Q}iv(kJc4O3TEvuIDM<=U9@`~WdKN* zp4e4R1ncR_kghW}>aE$@OOc~*aH5OOwB5U*Z)%{LRlhtHuigxH8KuDwvq5{3Zg{Vr zrd@)KPwVKFP2{rXho(>MTZZfkr$*alm_lltPob4N4MmhEkv`J(9NZFzA>q0Ch;!Ut zi@jS_=0%HAlN+$-IZGPi_6$)ap>Z{XQGt&@ZaJ(es!Po5*3}>R4x66WZNsjE4BVgn z>}xm=V?F#tx#e+pimNPH?Md5hV7>0pAg$K!?mpt@pXg6UW9c?gvzlNe0 z3QtIWmw$0raJkjQcbv-7Ri&eX6Ks@@EZ&53N|g7HU<;V1pkc&$3D#8k!coJ=^{=vf z-pCP;vr2#A+i#6VA?!hs6A4P@mN62XYY$#W9;MwNia~89i`=1GoFESI+%Mbrmwg*0 zbBq4^bA^XT#1MAOum)L&ARDXJ6S#G>&*72f50M1r5JAnM1p7GFIv$Kf9eVR(u$KLt z9&hQ{t^i16zL1c(tRa~?qr?lbSN;1k;%;p*#gw_BwHJRjcYPTj6>y-rw*dFTnEs95 z`%-AoPL!P16{=#RI0 zUb6#`KR|v^?6uNnY`zglZ#Wd|{*rZ(x&Hk8N6ob6mpX~e^qu5kxvh$2TLJA$M=rx zc!#ot+sS+-!O<0KR6+Lx&~zgEhCsbFY{i_DQCihspM?e z-V}HemMAvFzXR#fV~a=Xf-;tJ1edd}Mry@^=9BxON;dYr8vDEK<<{ zW~rg(ZspxuC&aJo$GTM!9_sXu(EaQJNkV9AC(ob#uA=b4*!Uf}B*@TK=*dBvKKPAF z%14J$S)s-ws9~qKsf>DseEW(ssVQ9__YNg}r9GGx3AJiZR@w_QBlGP>yYh0lQCBtf zx+G;mP+cMAg&b^7J!`SiBwC81M_r0X9kAr2y$0(Lf1gZK#>i!cbww(hn$;fLIxRf? z!AtkSZc-h76KGSGz%48Oe`8ZBHkSXeVb!TJt_VC>$m<#}(Z}!(3h631ltKb3CDMw^fTRy%Ia!b&at`^g7Ew-%WLT9(#V0OP9CE?uj62s>`GI3NA z!`$U+i<`;IQyNBkou4|-7^9^ylac-Xu!M+V5p5l0Ve?J0wTSV+$gYtoc=+Ve*OJUJ z$+uIGALW?}+M!J9+M&#bT=Hz@{R2o>NtNGu1yS({pyteyb>*sg4N`KAD?`u3F#C1y z2K4FKOAPASGZTep54PqyCG(h3?kqQQAxDSW@>T2d!n;9C8NGS;3A8YMRcL>b=<<%M zMiWf$jY;`Ojq5S{kA!?28o)v$;)5bTL<4eM-_^h4)F#eeC2Dj*S`$jl^yn#NjJOYT zx%yC5Ww@eX*zsM)P(5#wRd=0+3~&3pdIH7CxF_2iZSw@>kCyd z%M}$1p((Bidw4XNtk&`BTkU{-PG)SXIZ)yQ!Iol6u8l*SQ1^%zC72FP zLvG>_Z0SReMvB%)1@+et0S{<3hV@^SY3V~5IY(KUtTR{*^xJ^2NN{sIMD9Mr9$~(C$GLNlSpzS=fsbw-DtHb_T|{s z9OR|sx!{?F``H!gVUltY7l~dx^a(2;OUV^)7 z%@hg`8+r&xIxmzZ;Q&v0X%9P)U0SE@r@(lKP%TO(>6I_iF{?PX(bez6v8Gp!W_nd5 z<8)`1jcT)ImNZp-9rr4_1MQ|!?#8sJQx{`~7)QZ75I=DPAFD9Mt{zqFrcrXCU9MG8 zEuGcy;nZ?J#M3!3DWW?Zqv~dnN6ijlIjPfJx(#S0cs;Z=jDjKY|$w2s4*Xa1Iz953sN2Lt!Vmk|%ZwOOqj`sA--5Hiaq8!C%LV zvWZ=bxeRV(&%BffMJ_F~~*FdcjhRVNUXu)MS(S#67rDe%Ler=GS+WysC1I2=Bmbh3s6wdS}o$0 zz%H08#SPFY9JPdL6blGD$D-AaYi;X!#zqib`(XX*i<*eh+2UEPzU4}V4RlC3{<>-~ zadGA8lSm>b7Z!q;D_f9DT4i)Q_}ByElGl*Cy~zX%IzHp)@g-itZB6xM70psn z;AY8II99e6P2drgtTG5>`^|7qg`9MTp%T~|1N3tBqV}2zgow3TFAH{XPor0%=HrkXnKyxyozHlJ6 zd3}OWkl?H$l#yZqOzZbMI+lDLoH48;s10!m1!K87g;t}^+A3f3e&w{EYhVPR0Km*- zh5-ku$Z|Ss{2?4pGm(Rz!0OQb^_*N`)rW{z)^Cw_`a(_L9j=&HEJl(!4rQy1IS)>- zeTIr>hOii`gc(fgYF(cs$R8l@q{mJzpoB5`5r>|sG zBpsY}RkY(g5`bj~D>(;F8v*DyjX(#nVLSs>)XneWI&%Wo>a0u#4A?N<1SK4D}&V1oN)76 z%S>a2n3n>G`YY1>0Hvn&AMtMuI_?`5?4y3w2Hnq4Qa2YH5 zxKdfM;k467djL31Y$0kd9FCPbU=pHBp@zaIi`Xkd80;%&66zvSqsq6%aY)jZacfvw ztkWE{ZV6V2WL9e}Dvz|!d96KqVkJU@5ryp#rReeWu>mSrOJxY^tWC9wd0)$+lZc%{ zY=c4#%OSyQJvQUuy^u}s8DN8|8T%TajOuaY^)R-&8s@r9D`(Ic4NmEu)fg1f!u`xUb;9t#rM z>}cY=648@d5(9A;J)d{a^*ORdVtJrZ77!g~^lZ9@)|-ojvW#>)Jhe8$7W3mhmQh@S zU=CSO+1gSsQ+Tv=x-BD}*py_Ox@;%#hPb&tqXqyUW9jV+fonnuCyVw=?HR>dAB~Fg z^vl*~y*4|)WUW*9RC%~O1gHW~*tJb^a-j;ae2LRNo|0S2`RX>MYqGKB^_ng7YRc@! zFxg1X!VsvXkNuv^3mI`F2=x6$(pZdw=jfYt1ja3FY7a41T07FPdCqFhU6%o|Yb6Z4 zpBGa=(ao3vvhUv#*S{li|EyujXQPUV;0sa5!0Ut)>tPWyC9e0_9(=v*z`TV5OUCcx zT=w=^8#5u~7<}8Mepqln4lDv*-~g^VoV{(+*4w(q{At6d^E-Usa2`JXty++Oh~on^ z;;WHkJsk2jvh#N|?(2PLl+g!M0#z_A;(#Uy=TzL&{Ei5G9#V{JbhKV$Qmkm%5tn!CMA? z@hM=b@2DZWTQ6>&F6WCq6;~~WALiS#@{|I+ucCmD6|tBf&e;$_)%JL8$oIQ%!|Xih1v4A$=7xNO zZVz$G8;G5)rxyD+M0$20L$4yukA_D+)xmK3DMTH3Q+$N&L%qB)XwYx&s1gkh=%qGCCPwnwhbT4p%*3R)I}S#w7HK3W^E%4w z2+7ctHPx3Q97MFYB48HfD!xKKb(U^K_4)Bz(5dvwyl*R?)k;uHEYVi|{^rvh)w7}t z`tnH{v9nlVHj2ign|1an_wz0vO)*`3RaJc#;(W-Q6!P&>+@#fptCgtUSn4!@b7tW0&pE2Qj@7}f#ugu4*C)8_}AMRuz^WG zc)XDcOPQjRaGptRD^57B83B-2NKRo!j6TBAJntJPHNQG;^Oz}zt5F^kId~miK3J@l ztc-IKp6qL!?u~q?qfGP0I~$5gvq#-0;R(oLU@sYayr*QH95fnrYA*E|n%&FP@Cz`a zSdJ~(c@O^>qaO`m9IQ8sd8!L<+)GPJDrL7{4{ko2gWOZel^3!($Gjt|B&$4dtfTmBmC>V`R&&6$wpgvdmns zxcmfS%9_ZoN>F~azvLFtA(9Q5HYT#A(byGkESnt{$Tu<73$W~reB4&KF^JBsoqJ6b zS?$D7DoUgzLO-?P`V?5_ub$nf1p0mF?I)StvPomT{uYjy!w&z$t~j&en=F~hw|O(1 zlV9$arQmKTc$L)Kupwz_zA~deT+-0WX6NzFPh&d+ly*3$%#?Ca9Z9lOJsGVoQ&1HNg+)tJ_sw)%oo*DK)iU~n zvL``LqTe=r=7SwZ@LB)9|3QB5`0(B9r(iR}0nUwJss-v=dXnwMRQFYSRK1blS#^g(3@z{`=8_CGDm!LESTWig zzm1{?AG&7`uYJ;PoFO$o8RWuYsV26V{>D-iYTnvq7igWx9@w$EC*FV^vpvDl@i9yp zPIqiX@hEZF4VqzI3Y)CHhR`xKN8poL&~ak|wgbE4zR%Dm(a@?bw%(7(!^>CM!^4@J z6Z)KhoQP;WBq_Z_&<@i2t2&xq>N>b;Np2rX?yK|-!14iE2T}E|jC+=wYe~`y38g3J z8QGZquvqBaG!vw&VtdXWX5*i5*% zJP~7h{?&E|<#l{klGPaun`IgAJ4;RlbRqgJz5rmHF>MtJHbfqyyZi53?Lhj=(Ku#& z__ubmZIxzSq3F90Xur!1)Vqe6b@!ueHA!93H~jdHmaS5Q^CULso}^poy)0Op6!{^9 zWyCyyIrdBP4fkliZ%*g+J-A!6VFSRF6Liu6G^^=W>cn81>4&7(c7(6vCGSAJ zQZ|S3mb|^Wf=yJ(h~rq`iiW~|n#$+KcblIR<@|lDtm!&NBzSG-1;7#YaU+-@=xIm4 zE}edTYd~e&_%+`dIqqgFntL-FxL3!m4yTNt<(^Vt9c6F(`?9`u>$oNxoKB29<}9FE zgf)VK!*F}nW?}l95%RRk8N4^Rf8)Xf;drT4<|lUDLPj^NPMrBPL;MX&0oGCsS za3}vWcF(IPx&W6{s%zwX{UxHX2&xLGfT{d9bWP!g;Lg#etpuno$}tHoG<4Kd*=kpU z;4%y(<^yj(UlG%l-7E9z_Kh2KoQ19qT3CR@Ghr>BAgr3Vniz3LmpC4g=g|A3968yD2KD$P7v$ zx9Q8`2&qH3&y-iv0#0+jur@}k`6C%7fKbCr|tHX2&O%r?rBpg`YNy~2m+ z*L7dP$RANzVUsG_Lb>=__``6vA*xpUecuGsL+AW?BeSwyoQfDlXe8R1*R1M{0#M?M zF+m19`3<`gM{+GpgW^=UmuK*yMh3}x)7P738wL8r@(Na6%ULPgbPVTa6gh5Q(SR0f znr6kdRpe^(LVM;6Rt(Z@Lsz3EX*ry6(WZ?w>#ZRelx)N%sE+MN>5G|Z8{%@b&D+Ov zPU{shc9}%;G7l;qbonIb_1m^Qc8ez}gTC-k02G8Rl?7={9zBz8uRX2{XJQ{vZhs67avlRn| zgRtWl0Lhjet&!YC47GIm%1gdq%T24_^@!W3pCywc89X4I5pnBCZDn(%!$lOGvS*`0!AoMtqxNPFgaMR zwoW$p;8l6v%a)vaNsesED3f}$%(>zICnoE|5JwP&+0XI}JxPccd+D^gx`g`=GsUc0 z9Uad|C+_@_0%JmcObGnS@3+J^0P!tg+fUZ_w#4rk#TlJYPXJiO>SBxzs9(J;XV9d{ zmTQE1(K8EYaz9p^XLbdWudyIPJlGPo0U*)fAh-jnbfm@SYD_2+?|DJ-^P+ojG{2{6 z>HJtedEjO@j_tqZ4;Zq1t5*5cWm~W?HGP!@_f6m#btM@46cEMhhK{(yI&jG)fwL1W z^n_?o@G8a-jYt!}$H*;{0#z8lANlo!9b@!c5K8<(#lPlpE!z86Yq#>WT&2} z;;G1$pD%iNoj#Z=&kij5&V1KHIhN-h<;{HC5wD)PvkF>CzlQOEx_0;-TJ*!#&{Wzt zKcvq^SZIdop}y~iouNqtU7K7+?eIz-v_rfNM>t#i+dD$s_`M;sjGubTdP)WI*uL@xPOLHt#~T<@Yz>xt50ZoTw;a(a}lNiDN-J${gOdE zx?8LOA|tv{Mb}=TTR=LcqMqbCJkKj+@;4Mu)Cu0{`~ohix6E$g&tff)aHeUAQQ%M? zIN4uSUTzC1iMEWL*W-in1y)C`E+R8j?4_?X4&2Zv5?QdkNMz(k} zw##^Ikx`#_s>i&CO_mu@vJJ*|3ePRDl5pq$9V^>D;g0R%l>lw;ttyM6Sy`NBF{)Lr zSk)V>mZr96+aHY%vTLLt%vO-+juw6^SO_ zYGJaGeWX6W(TOQx=5oTGXOFqMMU*uZyt>MR-Y`vxW#^&)H zk0!F8f*@v6NO@Z*@Qo)+hlX40EWcj~j9dGrLaq%1;DE_%#lffXCcJ;!ZyyyZTz74Q zb2WSly6sX{`gQeToQsi1-()5EJ1nJ*kXGD`xpXr~?F#V^sxE3qSOwRSaC9x9oa~jJ zTG9`E|q zC5Qs1xh}jzb5UPYF`3N9YuMnI7xsZ41P;?@c|%w zl=OxLr6sMGR+`LStLvh)g?fA5p|xbUD;yFAMQg&!PEDYxVYDfA>oTY;CFt`cg?Li1 z0b})!9Rvw&j#*&+D2))kXLL z0+j=?7?#~_}N-qdEIP>DQaZh#F(#e0WNLzwUAj@r694VJ8?Dr5_io2X49XYsG^ zREt0$HiNI~6VV!ycvao+0v7uT$_ilKCvsC+VDNg7yG1X+eNe^3D^S==F3ByiW0T^F zH6EsH^}Uj^VPIE&m)xlmOScYR(w750>hclqH~~dM2+;%GDXT`u4zG!p((*`Hwx41M z4KB+`hfT(YA%W)Ve(n+Gu9kuXWKzxg{1ff^xNQw>w%L-)RySTk9kAS92(X0Shg^Q? zx1YXg_TLC^?h6!4mBqZ9pKhXByu|u~gF%`%`vdoaGBN3^j4l!4x?Bw4Jd)Z4^di}! zXlG1;hFvc>H?bmmu1E7Vx=%vahd!P1#ZGJOJYNbaek^$DHt`EOE|Hlij+hX>ocQFSLVu|wz`|KVl@Oa;m2k6b*mNK2Vo{~l9>Qa3@B7G7#k?)aLx;w6U ze8bBq%vF?5v>#TspEoaII!N}sRT~>bh-VWJ7Q*1qsz%|G)CFmnttbq$Ogb{~YK_=! z{{0vhlW@g!$>|}$&4E3@k`KPElW6x#tSX&dfle>o!irek$NAbDzdd2pVeNzk4&qgJ zXvNF0$R96~g0x+R1igR=Xu&X_Hc5;!Ze&C)eUTB$9wW&?$&o8Yxhm5s(S`;?{> z*F?9Gr0|!OiKA>Rq-ae=_okB6&yMR?!JDer{@iQgIn=cGxs-u^!8Q$+N&pfg2WM&Z zulHu=Uh~U>fS{=Nm0x>ACvG*4R`Dx^kJ65&Vvfj`rSCV$5>c04N26Rt2S?*kh3JKq z9(3}5T?*x*AP(X2Ukftym0XOvg~r6Ms$2x&R&#}Sz23aMGU&7sU-cFvE3Eq`NBJe84VoftWF#v7PDAp`@V zRFCS24_k~;@~R*L)eCx@Q9EYmM)Sn}HLbVMyxx%{XnMBDc-YZ<(DXDBYUt8$u5Zh} zBK~=M9cG$?_m_M61YG+#|9Vef7LfbH>(C21&aC)x$^Lg}fa#SF){RX|?-xZjSOrn# z2ZAwUF)$VB<&S;R3FhNSQOV~8w%A`V9dWyLiy zgt7G=Z4t|zU3!dh5|s(@XyS|waBr$>@=^Dspmem8)@L`Ns{xl%rGdX!R(BiC5C7Vo zXetb$oC_iXS}2x_Hy}T(hUUNbO47Q@+^4Q`h>(R-;OxCyW#eoOeC51jzxnM1yxBrp zz6}z`(=cngs6X05e79o_B7@3K|Qpe3n38Py_~ zpi?^rj!`pq!7PHGliC$`-8A^Ib?2qgJJCW+(&TfOnFGJ+@-<<~`7BR0f4oSINBq&R z2CM`0%WLg_Duw^1SPwj-{?BUl2Y=M4e+7yL1{C&&f&zjF06#xf>VdLozgNye(BNgSD`=fFbBy0HIosLl@JwCQl^s;eTnc( z3!r8G=K>zb`|bLLI0N|eFJk%s)B>oJ^M@AQzqR;HUjLsOqW<0v>1ksT_#24*U@R3HJu*A^#1o#P3%3_jq>icD@<`tqU6ICEgZrME(xX#?i^Z z%Id$_uyQGlFD-CcaiRtRdGn|K`Lq5L-rx7`vYYGH7I=eLfHRozPiUtSe~Tt;IN2^gCXmf2#D~g2@9bhzK}3nphhG%d?V7+Zq{I2?Gt*!NSn_r~dd$ zqkUOg{U=MI?Ehx@`(X%rQB?LP=CjJ*V!rec{#0W2WshH$X#9zep!K)tzZoge*LYd5 z@g?-j5_mtMp>_WW`p*UNUZTFN{_+#m*bJzt{hvAdkF{W40{#L3w6gzPztnsA_4?&0 z(+>pv!zB16rR-(nm(^c>Z(its{ny677vT8sF564^mlZvJ!h65}OW%Hn|2OXbOQM%b z{6C54Z2v;^hyMQ;UH+HwFD2!F!VlQ}6Z{L0_9g5~CH0@Mqz?ZC`^QkhOU#$Lx<4`B zyZsa9uPF!rZDo8ZVfzzR#raQ>5|)k~_Ef*wDqG^76o)j!C4 zykvT*o$!-MBko@?{b~*Zf2*YMlImrK`cEp|#D7f%Twm<|C|dWD \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/lib/as3/gradlew.bat b/lib/as3/gradlew.bat new file mode 100644 index 00000000000..6d57edc706c --- /dev/null +++ b/lib/as3/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/lib/as3/settings.gradle b/lib/as3/settings.gradle new file mode 100644 index 00000000000..49323464190 --- /dev/null +++ b/lib/as3/settings.gradle @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +rootProject.name = 'libthrift-as3' diff --git a/test/tests.json b/test/tests.json index 1d4ba66d158..a022951ba9c 100644 --- a/test/tests.json +++ b/test/tests.json @@ -562,7 +562,7 @@ { "name": "dart", "client": { - "timeout": 20, + "timeout": 30, "transports": [ "buffered", "framed", From f5de98aab38d3460ee7339c47b1bcf3467e1fd9e Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 23 Jan 2019 00:13:15 +0100 Subject: [PATCH 177/756] THRIFT-4715 C# union "data" should be strongly-typed Client: C# Patch: Jens Geyer --- .../src/thrift/generate/t_csharp_generator.cc | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc index 9d1e29e156a..6e99a3e68cd 100644 --- a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc @@ -1254,10 +1254,10 @@ void t_csharp_generator::generate_csharp_union_definition(std::ostream& out, t_s indent_up(); indent(out) << "public abstract void Write(TProtocol protocol);" << endl; - indent(out) << "public readonly bool Isset;" << endl; + indent(out) << "public readonly int Isset;" << endl; indent(out) << "public abstract object Data { get; }" << endl; - indent(out) << "protected " << tunion->get_name() << "(bool isset) {" << endl; + indent(out) << "protected " << tunion->get_name() << "(int isset) {" << endl; indent_up(); indent(out) << "Isset = isset;" << endl; indent_down(); @@ -1268,7 +1268,7 @@ void t_csharp_generator::generate_csharp_union_definition(std::ostream& out, t_s indent(out) << "public override object Data { get { return null; } }" << endl; - indent(out) << "public ___undefined() : base(false) {}" << endl << endl; + indent(out) << "public ___undefined() : base(0) {}" << endl << endl; indent(out) << "public override void Write(TProtocol protocol) {" << endl; indent_up(); @@ -1298,13 +1298,27 @@ void t_csharp_generator::generate_csharp_union_definition(std::ostream& out, t_s void t_csharp_generator::generate_csharp_union_class(std::ostream& out, t_struct* tunion, t_field* tfield) { + indent(out) << "public " << type_name(tfield->get_type()) << " As_" << tfield->get_name() << endl; + indent(out) << "{" << endl; + indent_up(); + indent(out) << "get" << endl; + indent(out) << "{" << endl; + indent_up(); + indent(out) << "return (" << tfield->get_key() << " == Isset) ? (" << type_name(tfield->get_type()) << ")Data : default(" << type_name(tfield->get_type()) << ");" << endl; + indent_down(); + indent(out) << "}" << endl; + indent_down(); + indent(out) << "}" << endl + << endl; + + indent(out) << "public class " << tfield->get_name() << " : " << tunion->get_name() << " {" << endl; indent_up(); indent(out) << "private " << type_name(tfield->get_type()) << " _data;" << endl; indent(out) << "public override object Data { get { return _data; } }" << endl; indent(out) << "public " << tfield->get_name() << "(" << type_name(tfield->get_type()) - << " data) : base(true) {" << endl; + << " data) : base("<< tfield->get_key() <<") {" << endl; indent_up(); indent(out) << "this._data = data;" << endl; indent_down(); From 67fbc1f6159602fbb0d5859f67edf760d40d155d Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 23 Jan 2019 00:13:15 +0100 Subject: [PATCH 178/756] THRIFT-4722 Netcore union "data" should be strongly-typed Client: netcore Patch: Jens Geyer --- .../thrift/generate/t_netcore_generator.cc | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc b/compiler/cpp/src/thrift/generate/t_netcore_generator.cc index d2e7da0cb9f..6f346a3d7c6 100644 --- a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netcore_generator.cc @@ -1347,9 +1347,9 @@ void t_netcore_generator::generate_netcore_union_definition(ostream& out, t_stru indent_up(); out << indent() << "public abstract Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken);" << endl - << indent() << "public readonly bool Isset;" << endl + << indent() << "public readonly int Isset;" << endl << indent() << "public abstract object Data { get; }" << endl - << indent() << "protected " << tunion->get_name() << "(bool isset)" << endl + << indent() << "protected " << tunion->get_name() << "(int isset)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "Isset = isset;" << endl; @@ -1361,7 +1361,7 @@ void t_netcore_generator::generate_netcore_union_definition(ostream& out, t_stru indent_up(); out << indent() << "public override object Data { get { return null; } }" << endl - << indent() << "public ___undefined() : base(false) {}" << endl << endl; + << indent() << "public ___undefined() : base(0) {}" << endl << endl; out << indent() << "public override Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl << indent() << "{" << endl; @@ -1390,13 +1390,27 @@ void t_netcore_generator::generate_netcore_union_definition(ostream& out, t_stru void t_netcore_generator::generate_netcore_union_class(ostream& out, t_struct* tunion, t_field* tfield) { + out << indent() << "public " << type_name(tfield->get_type()) << " As_" << tfield->get_name() << endl; + out << indent() << "{" << endl; + indent_up(); + out << indent() << "get" << endl; + out << indent() << "{" << endl; + indent_up(); + out << indent() << "return (" << tfield->get_key() << " == Isset) ? (" << type_name(tfield->get_type()) << ")Data : default(" << type_name(tfield->get_type()) << ");" << endl; + indent_down(); + out << indent() << "}" << endl; + indent_down(); + out << indent() << "}" << endl + << endl; + + out << indent() << "public class " << tfield->get_name() << " : " << tunion->get_name() << endl << indent() << "{" << endl; indent_up(); out << indent() << "private " << type_name(tfield->get_type()) << " _data;" << endl << indent() << "public override object Data { get { return _data; } }" << endl - << indent() << "public " << tfield->get_name() << "(" << type_name(tfield->get_type()) << " data) : base(true)" << endl + << indent() << "public " << tfield->get_name() << "(" << type_name(tfield->get_type()) << " data) : base("<< tfield->get_key() <<")" << endl << indent() << "{" << endl; indent_up(); out << indent() << "this._data = data;" << endl; From 129bb3e10d7bf1a1965d31cb8f30c7ccd3f96ecb Mon Sep 17 00:00:00 2001 From: Mustafa Senol Cosar Date: Tue, 22 Jan 2019 17:33:09 +0300 Subject: [PATCH 179/756] THRIFT-4675: Fix int64 constants generation for map keys --- compiler/cpp/src/thrift/generate/t_js_generator.cc | 8 ++++++-- lib/js/package.json | 2 +- lib/js/test/test-int64.html | 1 + lib/js/test/test-int64.js | 6 ++++++ lib/nodejs/test/int64.test.js | 11 +++++++++++ lib/nodets/test/int64.test.ts | 7 +++++++ lib/ts/package.json | 2 +- lib/ts/test/test-int64.ts | 7 +++++++ package-lock.json | 9 +++++++++ package.json | 1 + test/Int64Test.thrift | 10 ++++++++++ 11 files changed, 60 insertions(+), 4 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc index f8f1beed89a..d30ce41537c 100644 --- a/compiler/cpp/src/thrift/generate/t_js_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc @@ -698,8 +698,12 @@ string t_js_generator::render_const_value(t_type* type, t_const_value* value) { for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { if (v_iter != val.begin()) out << "," << endl; - - out << indent() << render_const_value(ktype, v_iter->first); + + if (ktype->is_base_type() && ((t_base_type*)get_true_type(ktype))->get_base() == t_base_type::TYPE_I64){ + out << indent() << "\"" << v_iter->first->get_integer() << "\""; + } else { + out << indent() << render_const_value(ktype, v_iter->first); + } out << " : "; out << render_const_value(vtype, v_iter->second); diff --git a/lib/js/package.json b/lib/js/package.json index c4bcc6d6c3b..a35ac15a323 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -16,7 +16,7 @@ }, "dependencies": { "jsdoc": "^3.5.5", - "json-int64": "^0.0.3", + "json-int64": "^1.0.0", "nopt": "^4.0.1" } } diff --git a/lib/js/test/test-int64.html b/lib/js/test/test-int64.html index 620e6ff861d..bcb05fb371e 100644 --- a/lib/js/test/test-int64.html +++ b/lib/js/test/test-int64.html @@ -25,6 +25,7 @@ + diff --git a/lib/js/test/test-int64.js b/lib/js/test/test-int64.js index 4df87e1d398..cf7e8282b79 100644 --- a/lib/js/test/test-int64.js +++ b/lib/js/test/test-int64.js @@ -86,6 +86,12 @@ QUnit.module('Int64'); for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { assert.ok(EXPECTED_INT64_LIST[i].equals(Int64Test.INT64_LIST[i])); } + + for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i){ + let int64Object = EXPECTED_INT64_LIST[i]; + assert.ok(Int64Test.INT64_2_INT64_MAP[JSONInt64.toDecimalString(int64Object)].equals(int64Object)); + } + console.log('Int64 test -- ends'); }); diff --git a/lib/nodejs/test/int64.test.js b/lib/nodejs/test/int64.test.js index 106e446b11e..27ad28c003f 100644 --- a/lib/nodejs/test/int64.test.js +++ b/lib/nodejs/test/int64.test.js @@ -18,6 +18,7 @@ */ const Int64 = require("node-int64"); +const JSONInt64 = require("json-int64"); const i64types = require("./gen-nodejs-es6/Int64Test_types.js"); const test = require("tape"); @@ -72,6 +73,16 @@ const cases = { for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { assert.ok(EXPECTED_INT64_LIST[i].equals(i64types.INT64_LIST[i])); } + + for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { + const int64Object = EXPECTED_INT64_LIST[i]; + assert.ok( + i64types.INT64_2_INT64_MAP[ + JSONInt64.toDecimalString(int64Object) + ].equals(int64Object) + ); + } + assert.end(); } }; diff --git a/lib/nodets/test/int64.test.ts b/lib/nodets/test/int64.test.ts index 3ff0d85b470..d209234b50c 100644 --- a/lib/nodets/test/int64.test.ts +++ b/lib/nodets/test/int64.test.ts @@ -18,6 +18,7 @@ */ import Int64 = require("node-int64"); +import JSONInt64 = require('json-int64'); import i64types = require("./gen-nodejs/Int64Test_types"); import test = require("tape"); @@ -72,6 +73,12 @@ const cases = { for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { assert.ok(EXPECTED_INT64_LIST[i].equals(i64types.INT64_LIST[i])); } + + for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i){ + let int64Object = EXPECTED_INT64_LIST[i]; + assert.ok(i64types.INT64_2_INT64_MAP[JSONInt64.toDecimalString(int64Object)].equals(int64Object)); + } + assert.end(); } }; diff --git a/lib/ts/package.json b/lib/ts/package.json index 47eec6277a8..1a1ccdc85a8 100644 --- a/lib/ts/package.json +++ b/lib/ts/package.json @@ -23,7 +23,7 @@ "dependencies": { "bufferutil": "^4.0.1", "jsdoc": "^3.5.5", - "json-int64": "^0.0.3", + "json-int64": "^1.0.0", "nopt": "^4.0.1" }, "types": "./thrift.d.ts" diff --git a/lib/ts/test/test-int64.ts b/lib/ts/test/test-int64.ts index 3ea7919e2c8..254d8d7bfcc 100644 --- a/lib/ts/test/test-int64.ts +++ b/lib/ts/test/test-int64.ts @@ -19,6 +19,7 @@ /* jshint -W100 */ var Int64 = require("node-int64"); +var JSONInt64 = require("json-int64"); import { Int64Test } from "./gen-js/Int64Test_types"; @@ -89,6 +90,12 @@ QUnit.module('Int64'); for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i) { assert.ok(EXPECTED_INT64_LIST[i].equals(Int64Test.INT64_LIST[i])); } + + for (let i = 0; i < EXPECTED_INT64_LIST.length; ++i){ + let int64Object = EXPECTED_INT64_LIST[i]; + assert.ok(Int64Test.INT64_2_INT64_MAP[JSONInt64.toDecimalString(int64Object)].equals(int64Object)); + } + console.log('Int64 test -- ends'); }); diff --git a/package-lock.json b/package-lock.json index 1e089d94eb3..7c39c2a2b59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1223,6 +1223,15 @@ "underscore": "~1.8.3" } }, + "json-int64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-1.0.0.tgz", + "integrity": "sha512-yrTg9swToElhEPETLMdZkEzDhbXLs+cxkw/b2rglMPOBlM1DE0utH1EReSMLcnpYJk5iUvD12r0fP2/xHitF5Q==", + "dev": true, + "requires": { + "node-int64": "0.4.0" + } + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", diff --git a/package.json b/package.json index 97b7abf9a1d..b850a71b298 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "eslint-plugin-prettier": "^3.0.0", "istanbul": "^0.4.5", "jsdoc": "^3.5.5", + "json-int64": "^1.0.0", "prettier": "^1.14.3", "tape": "^4.9.0", "utf-8-validate": "^4.0.0", diff --git a/test/Int64Test.thrift b/test/Int64Test.thrift index 7a9ed2ffc64..348cc9c4753 100644 --- a/test/Int64Test.thrift +++ b/test/Int64Test.thrift @@ -32,3 +32,13 @@ const i64 MAX_SIGNED_INT64 = 9223372036854775807 const i64 MIN_SIGNED_INT64 = -9223372036854775808 const list INT64_LIST = [SMALL_INT64, MAX_JS_SAFE_INT64, MIN_JS_SAFE_INT64, MAX_JS_SAFE_PLUS_ONE_INT64, MIN_JS_SAFE_MINUS_ONE_INT64, MAX_SIGNED_INT64, MIN_SIGNED_INT64] + +const map INT64_2_INT64_MAP = { + SMALL_INT64: SMALL_INT64, + MAX_JS_SAFE_INT64: MAX_JS_SAFE_INT64, + MIN_JS_SAFE_INT64: MIN_JS_SAFE_INT64, + MAX_JS_SAFE_PLUS_ONE_INT64: MAX_JS_SAFE_PLUS_ONE_INT64, + MIN_JS_SAFE_MINUS_ONE_INT64: MIN_JS_SAFE_MINUS_ONE_INT64, + MAX_SIGNED_INT64: MAX_SIGNED_INT64, + MIN_SIGNED_INT64: MIN_SIGNED_INT64 + } From 8935c98046dbbdd36ede73c1525f1be9df8da5cd Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 25 Jan 2019 00:41:17 -0500 Subject: [PATCH 180/756] THRIFT-4753: re-version master to next release 0.13.0 --- ApacheThrift.nuspec | 8 ++++---- CMakeLists.txt | 2 +- Thrift.podspec | 4 ++-- appveyor.yml | 2 +- bower.json | 2 +- configure.ac | 2 +- contrib/thrift.spec | 2 +- doc/specs/idl.md | 2 +- lib/as3/gradle.properties | 2 +- .../ThriftMSBuildTask/Properties/AssemblyInfo.cs | 4 ++-- lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj | 2 +- lib/csharp/src/Properties/AssemblyInfo.cs | 4 ++-- lib/csharp/src/Thrift.csproj | 2 +- .../test/Multiplex/Client/MultiplexClient.csproj | 2 +- .../test/Multiplex/Client/Properties/AssemblyInfo.cs | 4 ++-- .../test/Multiplex/Server/MultiplexServer.csproj | 2 +- .../test/Multiplex/Server/Properties/AssemblyInfo.cs | 4 ++-- .../test/ThriftMVCTest/Properties/AssemblyInfo.cs | 4 ++-- lib/d/src/thrift/base.d | 2 +- lib/dart/pubspec.yaml | 2 +- lib/delphi/src/Thrift.pas | 2 +- lib/erl/src/thrift.app.src | 2 +- lib/haxe/haxelib.json | 2 +- lib/hs/thrift.cabal | 2 +- lib/java/gradle.properties | 2 +- lib/js/package-lock.json | 2 +- lib/js/package.json | 11 ++++++++++- lib/js/src/thrift.js | 2 +- lib/lua/Thrift.lua | 2 +- lib/netcore/Thrift/Properties/AssemblyInfo.cs | 4 ++-- .../Thrift/Transports/Client/THttpClientTransport.cs | 2 +- lib/ocaml/_oasis | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/py/setup.py | 2 +- lib/rb/thrift.gemspec | 2 +- lib/rs/Cargo.toml | 2 +- lib/st/package.xml | 2 +- lib/swift/Sources/Thrift.swift | 2 +- lib/swift/Tests/ThriftTests/ThriftTests.swift | 2 +- package.json | 2 +- sonar-project.properties | 6 +++--- test/csharp/Properties/AssemblyInfo.cs | 4 ++-- test/csharp/ThriftTest.csproj | 2 +- test/dart/test_client/pubspec.yaml | 2 +- test/erl/src/thrift_test.app.src | 2 +- .../csharp/CsharpClient/Properties/AssemblyInfo.cs | 4 ++-- .../csharp/CsharpServer/Properties/AssemblyInfo.cs | 4 ++-- tutorial/dart/client/pubspec.yaml | 2 +- tutorial/dart/console_client/pubspec.yaml | 2 +- tutorial/dart/server/pubspec.yaml | 2 +- tutorial/delphi/DelphiClient/DelphiClient.dproj | 4 ++-- tutorial/delphi/DelphiServer/DelphiServer.dproj | 4 ++-- tutorial/hs/ThriftTutorial.cabal | 2 +- tutorial/ocaml/_oasis | 2 +- 54 files changed, 80 insertions(+), 71 deletions(-) diff --git a/ApacheThrift.nuspec b/ApacheThrift.nuspec index 54ed2c64a94..8ed92361fc0 100644 --- a/ApacheThrift.nuspec +++ b/ApacheThrift.nuspec @@ -21,14 +21,14 @@ the "Thrift" project. 3. nuget setApiKey 3. nuget pack ApacheThrift.nuspec -Symbols -SymbolPackageFormat snupkg - 4. nuget push ApacheThrift.1.0.0.nupkg -Source https://api.nuget.org/v3/index.json + 4. nuget push ApacheThrift.0.13.0.nupkg -Source https://api.nuget.org/v3/index.json --> ApacheThrift - 1.0.0 - Apache Thrift 1.0.0 + 0.13.0 + Apache Thrift 0.13.0 Apache Thrift Developers Apache Software Foundation Apache-2.0 @@ -39,7 +39,7 @@ Contains runtime libraries from lib/csharp for net35 and net45 frameworks, and from lib/netcore for netstandard2.0 framework development. - + Apache Thrift RPC diff --git a/CMakeLists.txt b/CMakeLists.txt index e9ebbab9388..f0165f8f480 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ endif() # PACKAGE_VERSION is used by cpack scripts currently # Both thrift_VERSION and PACKAGE_VERSION should be the same for now -set(thrift_VERSION "1.0.0") +set(thrift_VERSION "0.13.0") set(PACKAGE_VERSION ${thrift_VERSION}) project("thrift" VERSION ${PACKAGE_VERSION}) diff --git a/Thrift.podspec b/Thrift.podspec index 126c00b24af..cb1c9b2922a 100644 --- a/Thrift.podspec +++ b/Thrift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Thrift-swift3" - s.version = "1.0.0" + s.version = "0.13.0" s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC." s.description = <<-DESC The Apache Thrift scalable cross-language software framework for networked services development combines a software stack with a code generation engine to build services that work efficiently and seamlessly between many programming languages. @@ -11,6 +11,6 @@ The Apache Thrift scalable cross-language software framework for networked servi s.ios.deployment_target = '9.0' s.osx.deployment_target = '10.10' s.requires_arc = true - s.source = { :git => "https://github.com/apache/thrift.git", :tag => "v1.0.0" } + s.source = { :git => "https://github.com/apache/thrift.git", :tag => "v0.13.0" } s.source_files = "lib/swift/Sources/*.swift" end diff --git a/appveyor.yml b/appveyor.yml index 977ade6eb01..6cbabf1eed9 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ # build Apache Thrift on AppVeyor - https://ci.appveyor.com -version: '1.0.0.{build}' +version: '0.13.0.{build}' shallow_clone: true diff --git a/bower.json b/bower.json index 853b8cbbf19..c602af15a3a 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "1.0.0", + "version": "0.13.0", "homepage": "https://github.com/apache/thrift.git", "authors": [ "Apache Thrift " diff --git a/configure.ac b/configure.ac index a299785fc34..1fcd2fb953a 100755 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ(2.65) AC_CONFIG_MACRO_DIR([./aclocal]) -AC_INIT([thrift], [1.0.0]) +AC_INIT([thrift], [0.13.0]) AC_CONFIG_AUX_DIR([.]) diff --git a/contrib/thrift.spec b/contrib/thrift.spec index ffdfab2ab49..cbb08fba5c0 100644 --- a/contrib/thrift.spec +++ b/contrib/thrift.spec @@ -28,7 +28,7 @@ Name: thrift License: Apache License v2.0 Group: Development Summary: RPC and serialization framework -Version: 1.0.0 +Version: 0.13.0 Release: 0 URL: http://thrift.apache.org Packager: Thrift Developers diff --git a/doc/specs/idl.md b/doc/specs/idl.md index 069f2fc3759..524f4e72f5a 100644 --- a/doc/specs/idl.md +++ b/doc/specs/idl.md @@ -1,6 +1,6 @@ ## Thrift interface description language -For Thrift version 1.0.0. +For Thrift version 0.13.0. The Thrift interface definition language (IDL) allows for the definition of [Thrift Types](/docs/types). A Thrift IDL file is processed by the Thrift code generator to produce code for the various target languages to support the defined structs and services in the IDL file. diff --git a/lib/as3/gradle.properties b/lib/as3/gradle.properties index 8c8755efb0a..02d5eefad6e 100644 --- a/lib/as3/gradle.properties +++ b/lib/as3/gradle.properties @@ -1,7 +1,7 @@ # This file is shared currently between this Gradle build and the # Ant builds for fd303 and JavaScript. Keep the dotted notation for # the properties to minimize the changes in the dependencies. -thrift.version=1.0.0 +thrift.version=0.13.0 thrift.groupid=org.apache.thrift release=false sign=false diff --git a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs index c741b724fda..6e99dd9fd5e 100644 --- a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs +++ b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs @@ -56,5 +56,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.*")] -[assembly: AssemblyFileVersion("1.0.0.*")] +[assembly: AssemblyVersion("0.13.0.*")] +[assembly: AssemblyFileVersion("0.13.0.*")] diff --git a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj index a319df2e00f..f4a26de45f7 100644 --- a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj +++ b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj @@ -45,7 +45,7 @@ false true 0 - 1.0.0.0 + 0.13.0.0 false false true diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs index 7e86781c8b0..ace031045f7 100644 --- a/lib/csharp/src/Properties/AssemblyInfo.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/lib/csharp/src/Thrift.csproj b/lib/csharp/src/Thrift.csproj index bf65569c908..0a1552ffbeb 100644 --- a/lib/csharp/src/Thrift.csproj +++ b/lib/csharp/src/Thrift.csproj @@ -45,7 +45,7 @@ false true 0 - 1.0.0.0 + 0.13.0.0 false false true diff --git a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj index 21e1ce17710..09d20f50326 100644 --- a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj +++ b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj @@ -46,7 +46,7 @@ false true 0 - 1.0.0.0 + 0.13.0.0 false true diff --git a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs index f686ded5c20..0b65c1e5257 100644 --- a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj index c4a4394af8d..23d32536289 100644 --- a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj +++ b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj @@ -46,7 +46,7 @@ false true 0 - 1.0.0.0 + 0.13.0.0 false true diff --git a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs index 5d405466a1b..2b8a6af2330 100644 --- a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs b/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs index cfe8894f55c..b812aaf1d1a 100644 --- a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs @@ -49,5 +49,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/lib/d/src/thrift/base.d b/lib/d/src/thrift/base.d index d5ece738ad1..150c3da8e74 100644 --- a/lib/d/src/thrift/base.d +++ b/lib/d/src/thrift/base.d @@ -50,7 +50,7 @@ class TCompoundOperationException : TException { /// The Thrift version string, used for informative purposes. // Note: This is currently hardcoded, but will likely be filled in by the build // system in future versions. -enum VERSION = "1.0.0"; +enum VERSION = "0.13.0"; /** * Functions used for logging inside Thrift. diff --git a/lib/dart/pubspec.yaml b/lib/dart/pubspec.yaml index ded0269c954..f406b9932cf 100644 --- a/lib/dart/pubspec.yaml +++ b/lib/dart/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: thrift -version: 1.0.0 +version: 0.13.0 description: > A Dart library for Apache Thrift author: Apache Thrift Developers diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index 62481e7ec3e..2ee83441b68 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -27,7 +27,7 @@ interface Thrift.Protocol; const - Version = '1.0.0'; + Version = '0.13.0'; type TException = Thrift.Exception.TException; // compatibility alias diff --git a/lib/erl/src/thrift.app.src b/lib/erl/src/thrift.app.src index b3b225fb70a..e5e6ed5cf2c 100644 --- a/lib/erl/src/thrift.app.src +++ b/lib/erl/src/thrift.app.src @@ -22,7 +22,7 @@ {description, "Thrift bindings"}, % The version of the applicaton - {vsn, "1.0.0"}, + {vsn, "0.13.0"}, % All modules used by the application. {modules, [ diff --git a/lib/haxe/haxelib.json b/lib/haxe/haxelib.json index 992ad901529..b3c15308df3 100644 --- a/lib/haxe/haxelib.json +++ b/lib/haxe/haxelib.json @@ -4,7 +4,7 @@ "license": "Apache", "tags": ["thrift", "rpc", "serialization", "cross", "framework"], "description": "Haxe bindings for the Apache Thrift RPC and serialization framework", - "version": "1.0.0", + "version": "0.13.0", "releasenote": "Licensed under Apache License, Version 2.0. The Apache Thrift compiler needs to be installed separately.", "contributors": ["Apache Software Foundation (ASF)"], "dependencies": { }, diff --git a/lib/hs/thrift.cabal b/lib/hs/thrift.cabal index 5515556db03..84a59acade0 100644 --- a/lib/hs/thrift.cabal +++ b/lib/hs/thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 1.0.0 +Version: 0.13.0 Cabal-Version: 1.24 License: OtherLicense Category: Foreign diff --git a/lib/java/gradle.properties b/lib/java/gradle.properties index 55256104f3b..a964675a34d 100644 --- a/lib/java/gradle.properties +++ b/lib/java/gradle.properties @@ -1,7 +1,7 @@ # This file is shared currently between this Gradle build and the # Ant builds for fd303 and JavaScript. Keep the dotted notation for # the properties to minimize the changes in the dependencies. -thrift.version=1.0.0 +thrift.version=0.13.0 thrift.groupid=org.apache.thrift release=false diff --git a/lib/js/package-lock.json b/lib/js/package-lock.json index 19710dfe28a..7c8374fd0d5 100644 --- a/lib/js/package-lock.json +++ b/lib/js/package-lock.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "1.0.0", + "version": "0.13.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/lib/js/package.json b/lib/js/package.json index a35ac15a323..b5c0238a1c5 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -1,6 +1,15 @@ { "name": "thrift", - "version": "1.0.0", + "version": "0.13.0", + "description": "Thrift is a software framework for scalable cross-language services development.", + "author": { + "name": "Apache Thrift Developers", + "email": "dev@thrift.apache.org" + }, + "bugs": "https://issues.apache.org/jira/projects/THRIFT/summary", + "homepage": "http://thrift.apache.org", + "repository": "https://github.com/apache/thrift", + "license": "Apache-2.0", "devDependencies": { "browserify": "^16.2.3", "grunt": "^1.0.2", diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index b9fa62dd61b..0b4a29241a6 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -46,7 +46,7 @@ var Thrift = { * @const {string} Version * @memberof Thrift */ - Version: '1.0.0', + Version: '0.13.0', /** * Thrift IDL type string to Id mapping. diff --git a/lib/lua/Thrift.lua b/lib/lua/Thrift.lua index 68d4ba8ecbd..a948b3dcb25 100644 --- a/lib/lua/Thrift.lua +++ b/lib/lua/Thrift.lua @@ -48,7 +48,7 @@ function ttable_size(t) return count end -version = '1.0.0' +version = '0.13.0' TType = { STOP = 0, diff --git a/lib/netcore/Thrift/Properties/AssemblyInfo.cs b/lib/netcore/Thrift/Properties/AssemblyInfo.cs index 83417238317..0f433b6003d 100644 --- a/lib/netcore/Thrift/Properties/AssemblyInfo.cs +++ b/lib/netcore/Thrift/Properties/AssemblyInfo.cs @@ -52,5 +52,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs index 797d3803e5d..949bee7ef88 100644 --- a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs +++ b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs @@ -149,7 +149,7 @@ private HttpClient CreateClient() } httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); - httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "1.0.0")); + httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "0.13.0")); if (CustomHeaders != null) { diff --git a/lib/ocaml/_oasis b/lib/ocaml/_oasis index 5ad90df2699..83566aaa9e8 100644 --- a/lib/ocaml/_oasis +++ b/lib/ocaml/_oasis @@ -1,5 +1,5 @@ Name: libthrift-ocaml -Version: 1.0.0 +Version: 0.13.0 OASISFormat: 0.3 Synopsis: OCaml bindings for the Apache Thrift RPC system Authors: Apache Thrift Developers diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm index ab40930d6bb..01985ea87c1 100644 --- a/lib/perl/lib/Thrift.pm +++ b/lib/perl/lib/Thrift.pm @@ -31,6 +31,6 @@ use warnings; # package Thrift; -use version 0.77; our $VERSION = version->declare("v1.0.0"); +use version 0.77; our $VERSION = version->declare("v0.13.0"); 1; diff --git a/lib/py/setup.py b/lib/py/setup.py index 3cf1469d399..2ba26915979 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -90,7 +90,7 @@ def run_setup(with_binary): twisted_deps = ['twisted'] setup(name='thrift', - version='1.0.0', + version='0.13.0', description='Python bindings for the Apache Thrift RPC system', author='Apache Thrift Developers', author_email='dev@thrift.apache.org', diff --git a/lib/rb/thrift.gemspec b/lib/rb/thrift.gemspec index e53194ee789..869e5d95d88 100644 --- a/lib/rb/thrift.gemspec +++ b/lib/rb/thrift.gemspec @@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__) Gem::Specification.new do |s| s.name = 'thrift' - s.version = '1.0.0' + s.version = '0.13.0' s.authors = ['Apache Thrift Developers'] s.email = ['dev@thrift.apache.org'] s.homepage = 'http://thrift.apache.org' diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml index ed32179af2b..3a25b16d4b0 100644 --- a/lib/rs/Cargo.toml +++ b/lib/rs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "thrift" description = "Rust bindings for the Apache Thrift RPC system" -version = "1.0.0" +version = "0.13.0" license = "Apache-2.0" authors = ["Apache Thrift Developers "] homepage = "http://thrift.apache.org" diff --git a/lib/st/package.xml b/lib/st/package.xml index f83936aca03..21b7adcd2eb 100644 --- a/lib/st/package.xml +++ b/lib/st/package.xml @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. --> - + libthrift-st thrift.st diff --git a/lib/swift/Sources/Thrift.swift b/lib/swift/Sources/Thrift.swift index 4898c77e775..45c68f2e535 100644 --- a/lib/swift/Sources/Thrift.swift +++ b/lib/swift/Sources/Thrift.swift @@ -1,3 +1,3 @@ class Thrift { - let version = "1.0.0" + let version = "0.13.0" } diff --git a/lib/swift/Tests/ThriftTests/ThriftTests.swift b/lib/swift/Tests/ThriftTests/ThriftTests.swift index 8f0b1fe183b..ae47f388cbb 100644 --- a/lib/swift/Tests/ThriftTests/ThriftTests.swift +++ b/lib/swift/Tests/ThriftTests/ThriftTests.swift @@ -3,7 +3,7 @@ import XCTest class ThriftTests: XCTestCase { func testVersion() { - XCTAssertEqual(Thrift().version, "1.0.0") + XCTAssertEqual(Thrift().version, "0.13.0") } func test_in_addr_extension() { diff --git a/package.json b/package.json index b850a71b298..729e9bfc1d9 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://github.com/apache/thrift.git" }, - "version": "1.0.0", + "version": "0.13.0", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", diff --git a/sonar-project.properties b/sonar-project.properties index bd5ecc2ad92..a238197cb18 100755 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -16,7 +16,7 @@ development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between all major languages. # Apache Thrift Version -sonar.projectVersion=1.0.0 +sonar.projectVersion=0.13.0 # use this to set another version string # $ sonar-runner -D sonar.projectVersion=`git rev-parse HEAD` # set projectDate in combination with projectVersion for imports of old releases @@ -54,7 +54,7 @@ module1.sonar.projectName=Apache Thrift - Java Library module1.sonar.projectBaseDir=lib/java module1.sonar.sources=src module1.sonar.tests=test -module1.sonar.binaries=build/libs/libthrift-1.0.0.jar +module1.sonar.binaries=build/libs/libthrift-0.13.0.jar module1.sonar.libraries=build/deps/*.jar module1.sonar.language=java @@ -62,7 +62,7 @@ module2.sonar.projectName=Apache Thrift - Java Tutorial module2.sonar.projectBaseDir=. module2.sonar.sources=tutorial/java/src, tutorial/java/gen-java module2.sonar.binaries=tutorial/java/tutorial.jar -module2.sonar.libraries=lib/java/build/deps/*.jar,lib/java/build/libs/libthrift-1.0.0.jar +module2.sonar.libraries=lib/java/build/deps/*.jar,lib/java/build/libs/libthrift-0.13.0.jar module2.sonar.language=java module3.sonar.projectName=Apache Thrift - JavaScript Library diff --git a/test/csharp/Properties/AssemblyInfo.cs b/test/csharp/Properties/AssemblyInfo.cs index b1101a15f01..76c9a80dd43 100644 --- a/test/csharp/Properties/AssemblyInfo.cs +++ b/test/csharp/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/test/csharp/ThriftTest.csproj b/test/csharp/ThriftTest.csproj index 63629eb7ca5..effec197940 100644 --- a/test/csharp/ThriftTest.csproj +++ b/test/csharp/ThriftTest.csproj @@ -46,7 +46,7 @@ false true 0 - 1.0.0.0 + 0.13.0.0 false true diff --git a/test/dart/test_client/pubspec.yaml b/test/dart/test_client/pubspec.yaml index 113054a24cf..c86225eeea6 100644 --- a/test/dart/test_client/pubspec.yaml +++ b/test/dart/test_client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: thrift_test_client -version: 1.0.0 +version: 0.13.0 description: A client integration test for the Dart Thrift library author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/test/erl/src/thrift_test.app.src b/test/erl/src/thrift_test.app.src index 80ef996e513..ffbad58835a 100644 --- a/test/erl/src/thrift_test.app.src +++ b/test/erl/src/thrift_test.app.src @@ -22,7 +22,7 @@ {description, "Thrift cross language test"}, % The version of the applicaton - {vsn, "1.0.0"}, + {vsn, "0.13.0"}, % All modules used by the application. {modules, [ diff --git a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs index 1ff658c39bb..bae5e70c983 100644 --- a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs +++ b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs index 74fa476e74d..e3ed39a9c62 100644 --- a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs +++ b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/tutorial/dart/client/pubspec.yaml b/tutorial/dart/client/pubspec.yaml index 109db0f65e7..6581b4d2180 100644 --- a/tutorial/dart/client/pubspec.yaml +++ b/tutorial/dart/client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_client -version: 1.0.0 +version: 0.13.0 description: A Dart client implementation of the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/tutorial/dart/console_client/pubspec.yaml b/tutorial/dart/console_client/pubspec.yaml index 602bb5e1036..ca122d2fde4 100644 --- a/tutorial/dart/console_client/pubspec.yaml +++ b/tutorial/dart/console_client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_console_client -version: 1.0.0 +version: 0.13.0 description: > A Dart console client to implementation of the Apache Thrift tutorial author: Apache Thrift Developers diff --git a/tutorial/dart/server/pubspec.yaml b/tutorial/dart/server/pubspec.yaml index b0b012d09af..e09465e704a 100644 --- a/tutorial/dart/server/pubspec.yaml +++ b/tutorial/dart/server/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_server -version: 1.0.0 +version: 0.13.0 description: A Dart server to support the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/tutorial/delphi/DelphiClient/DelphiClient.dproj b/tutorial/delphi/DelphiClient/DelphiClient.dproj index d067992b932..0680be28d73 100644 --- a/tutorial/delphi/DelphiClient/DelphiClient.dproj +++ b/tutorial/delphi/DelphiClient/DelphiClient.dproj @@ -97,13 +97,13 @@ Thrift Tutorial - 1.0.0.0 + 0.13.0.0 DelphiClient Copyright © 2012 The Apache Software Foundation DelphiClient.exe Thrift - 1.0.0.0 + 0.13.0.0 diff --git a/tutorial/delphi/DelphiServer/DelphiServer.dproj b/tutorial/delphi/DelphiServer/DelphiServer.dproj index e34a6a10119..97d5617a301 100644 --- a/tutorial/delphi/DelphiServer/DelphiServer.dproj +++ b/tutorial/delphi/DelphiServer/DelphiServer.dproj @@ -96,13 +96,13 @@ Thrift Tutorial - 1.0.0.0 + 0.13.0.0 DelphiServer Copyright © 2012 The Apache Software Foundation DelphiServer.exe Thrift - 1.0.0.0 + 0.13.0.0 diff --git a/tutorial/hs/ThriftTutorial.cabal b/tutorial/hs/ThriftTutorial.cabal index 62e682fbb65..b6a612216e4 100755 --- a/tutorial/hs/ThriftTutorial.cabal +++ b/tutorial/hs/ThriftTutorial.cabal @@ -18,7 +18,7 @@ -- Name: ThriftTutorial -Version: 1.0.0 +Version: 0.13.0 Cabal-Version: >= 1.4 License: OtherLicense Category: Foreign diff --git a/tutorial/ocaml/_oasis b/tutorial/ocaml/_oasis index 745c096ae5b..4a4f337b3a6 100644 --- a/tutorial/ocaml/_oasis +++ b/tutorial/ocaml/_oasis @@ -1,5 +1,5 @@ Name: tutorial -Version: 1.0.0 +Version: 0.13.0 OASISFormat: 0.3 Synopsis: OCaml Tutorial example Authors: Apache Thrift Developers From b96c43892a9e89dfa61834505bb25357e80287da Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 24 Jan 2019 17:45:07 -0500 Subject: [PATCH 181/756] THRIFT-4717: fix up make clean with autoconf --- CHANGES | 2924 ----------------- CHANGES.md | 21 +- Makefile.am | 50 +- bootstrap.sh | 5 +- .../docker/{ => old}/ubuntu-artful/Dockerfile | 0 cleanup.sh | 89 - configure.ac | 4 +- debian/rules | 2 - lib/as3/Makefile.am | 4 + lib/csharp/Makefile.am | 13 +- lib/csharp/test/Multiplex/Makefile.am | 13 +- lib/d/Makefile.am | 8 +- lib/dart/Makefile.am | 10 +- lib/erl/Makefile.am | 22 +- lib/js/Makefile.am | 36 +- lib/js/test/build.xml | 2 +- lib/json/Makefile.am | 10 +- lib/netcore/Makefile.am | 23 +- lib/nodejs/Makefile.am | 2 +- lib/php/Makefile.am | 6 +- lib/php/test/Makefile.am | 2 + lib/py/Makefile.am | 12 +- lib/rb/Makefile.am | 4 + package-lock.json | 2 +- test/Makefile.am | 20 +- test/c_glib/Makefile.am | 18 +- test/cpp/Makefile.am | 2 +- test/dart/Makefile.am | 12 +- test/erl/Makefile.am | 14 +- test/hs/Makefile.am | 11 +- test/lua/Makefile.am | 5 +- test/netcore/Makefile.am | 13 +- test/perl/Makefile.am | 4 +- test/php/Makefile.am | 7 +- test/py.tornado/Makefile.am | 10 +- test/py.twisted/Makefile.am | 10 +- test/py/Makefile.am | 10 +- test/rb/Makefile.am | 5 + test/rs/Makefile.am | 2 +- tutorial/d/Makefile.am | 7 + tutorial/dart/Makefile.am | 10 +- tutorial/hs/Makefile.am | 7 +- tutorial/netcore/Makefile.am | 9 + 43 files changed, 344 insertions(+), 3096 deletions(-) delete mode 100644 CHANGES rename build/docker/{ => old}/ubuntu-artful/Dockerfile (100%) delete mode 100755 cleanup.sh diff --git a/CHANGES b/CHANGES deleted file mode 100644 index 4b4997ef368..00000000000 --- a/CHANGES +++ /dev/null @@ -1,2924 +0,0 @@ -Apache Thrift Changelog - -================================================================================ -Thrift 0.13.0 --------------------------------------------------------------------------------- -## Breaking Changes (since 0.12.0) - * [THRIFT-4675] - Javascript now uses node-int64 for 64 bit integer constants - -================================================================================ -Thrift 0.12.0 --------------------------------------------------------------------------------- -## New Languages - * Common LISP (cl) - * Swift - * Typescript (nodets) - -## Deprecated Languages - * Cocoa - -## Breaking Changes (since 0.11.0) - * [THRIFT-4529] - Rust enum variants are now camel-cased instead of uppercased to conform to Rust naming conventions - * [THRIFT-4448] - Support for golang 1.6 and earlier has been dropped. - * [THRIFT-4474] - PHP now uses the PSR-4 loader by default instead of class maps. - * [THRIFT-4532] - method signatures changed in the compiler's t_oop_generator. - * [THRIFT-4648] - The C (GLib) compiler's handling of namespaces has been improved. - -## Known Issues (Blocker or Critical) - * [THRIFT-4037] - build: use a single build system for thrift - * [THRIFT-4119] - build: bootstrap.sh is missing from source tarball - * [THRIFT-3289] - csharp: socket exhaustion in csharp implementation - * [THRIFT-3029] - cocoa: Getters for fields defined with uppercase names do not work - * [THRIFT-3325] - cocoa: Extended services aren't subclasses in generated Cocoa - * [THRIFT-4116] - cocoa: Thrift de-capitalizes the name of IsSet property in Cocoa - * [THRIFT-3877] - cpp: the http implementation is not standard; interop with other languages is spotty at best - * [THRIFT-4180] - cpp: Impossible to build Thrift C++ library for Android (NDK) - * [THRIFT-4384] - cpp: Using multiple async services simultaneously is not thread-safe - * [THRIFT-3108] - haskell: Defaulted struct parameters on a service generates invalid Haskell - * [THRIFT-3990] - nodejs: Exception swallowed by deserialization function - * [THRIFT-4214] - nodejs: map key treated as hex value in JavaScript - * [THRIFT-4602] - nodejs: ERROR in ./node_modules/thrift/lib/nodejs/lib/thrift/connection.js Module not found: Error: Can't resolve 'child_process' - * [THRIFT-4639] - nodejs: Sequence numbering for multiplexed protocol broken - * [THRIFT-1310] - php: sequence and reconnection management issues - * [THRIFT-1538] - php: Error during deserialization int64 on 32-bit architecture - * [THRIFT-1580] - php: thrift type i64 java to php serialize/deserealize not working - * [THRIFT-1950] - php: PHP gets stuck in infinite loop - * [THRIFT-2954] - python: sending int or float in a double field breaks the connection - * [THRIFT-4080] - python: unix sockets can get stuck forever - * [THRIFT-4281] - python: generated code is out of order and causes load issues - * [THRIFT-4677] - py3: UnicodeDecideError in Python3 - -## Build Process - * [THRIFT-4067] - Windows thrift compiler distributed on the apache web site has runtime dependencies - * [THRIFT-4308] - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang - * [THRIFT-4579] - Use Ubuntu Bionic (18.04 LTS) for CI builds instead of Artful (17.10) - * [THRIFT-4508] - Define CI operating system coverage rules for the project and (hopefully) simplify CI a little more - * [THRIFT-4397] - ubuntu install instructions broken on 16.04 - * [THRIFT-4545] - Appveyor builds are failing due to a haskell / cabal update in chocolatey - * [THRIFT-4452] - optimize Dockerfile (only onetime apt-get update) - * [THRIFT-4440] - rm `build/docker/ubuntu-trusty/Dockerfile.orig` - * [THRIFT-4352] - Ubuntu Artful doesn't appear to be compatible with Thrift and Haxe 3.4.2 - * [THRIFT-4666] - DLang Client Pool Test fails sporadically - * [THRIFT-4676] - CL tutorial build fails sporadically - * [THRIFT-4456] - Make haxelib download quiet so it doesn't blow up the build log - * [THRIFT-4605] - bootstrap.sh fails if automake=1.16.1 - -## c_glib - * [THRIFT-4648] - The C (GLib) compiler's handling of namespaces has been improved. - * [THRIFT-4622] - glibC compilation issue - * [THRIFT-4671] - c glib is unable to handle client close unexpectedly - -## cl (new language support in 0.12.0) - * [THRIFT-82] - Common Lisp support - -## csharp - * [THRIFT-4558] - reserved Csharp keywords are not escaped in some cases - * [THRIFT-4637] - C# async mode generates incorrect code with inherited services - * [THRIFT-4672] - IAsyncResult style methods not being supported by certain transports leads to issues in mixed ISync/IAsync use cases - * [THRIFT-4539] - Allow TBufferedTransport to be used as base class - * [THRIFT-4535] - XML docs; code cleanup (tabs->spaces; String->string) - * [THRIFT-4492] - protected ExceptionType type member of TApplicationException cannot be accessed - * [THRIFT-4446] - JSONProtocol Base64 Encoding Trims Padding - * [THRIFT-4455] - Missing dispose calls in ThreadedServer & ThreadpoolServer - * [THRIFT-4609] - keep InnerException wherever appropriate - * [THRIFT-4673] - IAsyncResult not supported by layered transports (buffered/framed) - -## cpp - * [THRIFT-4476] - Typecasting problem on list items - * [THRIFT-4465] - TNonblockingServer throwing THRIFT LOGGER: TConnection::workSocket(): THRIFT_EAGAIN (unavailable resources) - * [THRIFT-4680] - TBufferTransports.h does not compile under Visual Studio 2017 - * [THRIFT-4618] - TNonblockingServer crash because of limitation of select() - * [THRIFT-4620] - TZlibTransport.cpp doesn't ensure that there is enough space for the zlib flush marker in the buffer. - * [THRIFT-4571] - ZeroMQ contrib library needs a refresh - * [THRIFT-4559] - TSSLServerSocket incorrectly prints errors - * [THRIFT-4578] - Move `TAsyncProtocolProcessor` into main thrift library - * [THRIFT-4418] - evhttp_connection_new is deprecated; use evhttp_connection_base_new - -## compiler - * [THRIFT-4644] - Compiler cannot be compiled on macOS(maybe also on other platforms with clang) - * [THRIFT-4531] - Thrift generates wrong Python code for immutable structures with optional members - * [THRIFT-4513] - thrift generated code is not stable for constants - * [THRIFT-4532] - Avoid updating Thrift compiler generated code if the output has not changed - * [THRIFT-4400] - Visual Studio Compiler project should link runtime statically in release builds - * [THRIFT-4399] - plugin.thrift t_const_value is not used as a union in C++ code -- fix this - * [THRIFT-4496] - Dealing with language keywords in Thrift (e.g. service method names) - * [THRIFT-4393] - repeated runs of compiler produce different binary output at plugin interface - -## dlang - * [THRIFT-4478] - Thrift will not build with dlang 2.078 or later - * [THRIFT-4503] - dlang servers logError on normal client disconnection - * [THRIFT-4308] - D language docker images need demios for libevent and openssl fixed to re-enable make cross on dlang - -## dart - * [THRIFT-4646] - Effective Dart and Exceptions - * [THRIFT-4439] - Shouldn't download dart.deb directly. - -## delphi - * [THRIFT-4562] - Calling wrong exception CTOR leads to "call failed: unknown result" instead of the real exception being thrown - * [THRIFT-4554] - uncompileable code with member names that are also types under specific conditions - * [THRIFT-4422] - Add Async implementation via IFuture - * [THRIFT-4485] - Possible invalid ptr AV with overlapped read/write on pipes - * [THRIFT-4549] - Thrift exceptions should derive from TException - * [THRIFT-4540] - buffered transport broken when trying to re-open a formerly closed transport - * [THRIFT-4473] - Move Thrift.Console.pas out of the Library - * [THRIFT-4490] - Allow a default service as fallback for multiplex processors connected by old clients - * [THRIFT-4454] - Large writes/reads may cause range check errors in debug mode - * [THRIFT-4461] - Compiler directive should match Delphi XE4 - * [THRIFT-4462] - First line in Console duplicated - * [THRIFT-4642] - FPU ctrl word settings may cause an unexpected "denormalized" error - * [THRIFT-4589] - HTTP client timeouts are a) incomplete and b) not used at all - * [THRIFT-4590] - running the test client using HTTP transport leads to "CoInitialize not called" - -## erlang - * [THRIFT-4497] - Erlang records should use map() for map type - * [THRIFT-4495] - Erlang records should allow 'undefined' for non-required fields - * [THRIFT-4580] - Fix erlang tutorial unpack on Windows - * [THRIFT-4582] - Ubuntu Xenial erlang 18.3 "make check" fails - -## golang - * [THRIFT-4448] - Support for golang 1.6 and earlier has been dropped. - * [THRIFT-4253] - Go generator assigns strings to field in const instead of pointers. - * [THRIFT-4573] - Unions Field Count Does Not Consider Binary - * [THRIFT-4447] - Golang: Panic on p.c.Call when using deprecated initializers - * [THRIFT-4650] - Required field incorrectly marked as set when fieldType does not match - * [THRIFT-4486] - Golang: -remote.go client cleanup - * [THRIFT-4537] - TSimpleServer can exit Accept loop with lock still acquired - * [THRIFT-4516] - Add support for go 1.10 - * [THRIFT-4421] - golang tests rely on gomock, which has change behaviour, causing tests to fail - * [THRIFT-4626] - Communication crash when using binary/compact protocol and zlib transport - * [THRIFT-4659] - golang race detected when closing listener socket - -## haskell - * [THRIFT-4634] - Haskell builds with older cabal cannot reconcile complex version requirements - -## java - * [THRIFT-4259] - Thrift does not compile due to Ant Maven task errors - * [THRIFT-1418] - Compiling Thrift from source: Class org.apache.tools.ant.taskdefs.ConditionTask doesn't support the nested "typefound" element - * [THRIFT-4530] - proposal: add nullability annotations to generated Java code - * [THRIFT-4614] - Generate missing @Nullable annotations for Java iterator getters - * [THRIFT-4555] - Getter of binary field in Java creates unnecessary copy - * [THRIFT-3983] - libthrift is deployed on central with pom packaging instead of jar - * [THRIFT-4294] - Java Configure Fails for Ant >= 1.10 - * [THRIFT-4178] - Java libraries missing from package when using cmake - * [THRIFT-4120] - pom files are not generated or provided in the build - * [THRIFT-1507] - Maven can't download resource from central when behind a proxy and won't use local repository - * [THRIFT-4556] - Optional rethrow of unhandled exceptions in java processor - * [THRIFT-4337] - Able to set keyStore and trustStore as InputStream in the TSSLTransportFactory.TSSLTransportParameters - * [THRIFT-4566] - Pass message of unhandled exception to optional rethrow. - * [THRIFT-4506] - Remove assertion in Java SASL code that would be ignored in release builds - * [THRIFT-4470] - Include popular IDE file templates to gitignore - * [THRIFT-4429] - Make TThreadPoolServer.executorService_ available in inherited classes and refactor methods to be able customization - * [THRIFT-3769] - Fix logic of THRIFT-2268 - * [THRIFT-4494] - Increase Java Socket Buffer Size - * [THRIFT-4499] - Remove Magic Number In TFIleTransport - -## js - * [THRIFT-4406] - JavaScript: Use modern Promise implementations - * [THRIFT-4625] - let / const variable decorators for es6 compiler - * [THRIFT-4653] - ES6 Classes - * [THRIFT-4592] - JS: readI32 performance on large arrays is very poor in Chrome - * [THRIFT-4509] - js and nodejs libraries need to be refreshed with current libraries - * [THRIFT-4403] - thrift.js: Incorrect usage of 'this' in TWebSocketTransport.__onOpen - * [THRIFT-4436] - Deserialization of nested list discards content - * [THRIFT-4437] - JS WebSocket client callbacks invoked twice on parallel requests - * [THRIFT-4679] - Duplicate declaration of InputBufferUnderrunError in lib/nodejs/lib/thrift/json_protocol.js - * [THRIFT-4551] - Add prettier for consistent JS code formatting - -## lua - * [THRIFT-4591] - lua client uses two write() calls per framed message send - * [THRIFT-3863] - Can't "make install" Lua Library - -## netcore - * [THRIFT-4524] - .NET Core Server doesn't close properly when cancelled - * [THRIFT-4434] - Update .NET Core components, add tests for .Net Core library and .Net Core compiler, fix bugs and build process - * [THRIFT-4446] - JSONProtocol Base64 Encoding Trims Padding - -## node.js - * [THRIFT-4225] - Error handling malformed arguments leaks memory, corrupts transport buffers causing next RPC to fail - * [THRIFT-3950] - Memory leak while calling oneway method - * [THRIFT-3143] - add typescript directory support - * [THRIFT-4564] - TBufferedTransport can leave corrupt data in the buffer - * [THRIFT-4647] - Node.js Fileserver webroot path - * [THRIFT-4489] - Unix domain socket support for NodeJS client - * [THRIFT-4443] - node.js json_protocol throws error in skip function - * [THRIFT-4604] - NodeJS: Expose Int64 from browser.js for consumption by browser - * [THRIFT-4480] - NodeJS warning on binary_protocol writeMessageEnd when seqid = 0 - -## perl - * [THRIFT-4382] - Replace the use of Perl Indirect Object Syntax calls to new() - * [THRIFT-4471] - Thrift CPAN release is missing Makefile.PL and the clients are unable to build the module - * [THRIFT-4416] - Perl CPAN Packaging Improvements - -## php - * [THRIFT-4474] - PHP generator use PSR-4 default - * [THRIFT-4463] - PHP generated code match PSR-2 - * [THRIFT-4373] - Extending Thrift class results in "Attempt serialize from non-Thrift object" - * [THRIFT-4354] - TSocket block on read - * [THRIFT-4423] - migrate php library to psr-4 - * [THRIFT-4656] - infinite loop in latest PHP library - * [THRIFT-4477] - TBufferedTransport must have underlying transport - * [THRIFT-4475] - lib/php/test should be checked for PSR-2 - * [THRIFT-4498] - add phpcs back - * [THRIFT-4460] - php library use PSR-2 - * [THRIFT-4641] - TCurlClient doesn't check for HTTP status code - * [THRIFT-4645] - TCurlClient: show actual error message when throwing TTransportException - * [THRIFT-4674] - Add stream context support into PHP/THttpClient - * [THRIFT-4459] - reduce php library directory depth - -## python - * [THRIFT-4670] - Twisted, slots, and void method fails with "object has no attribute 'success'" - * [THRIFT-4464] - Potentially server-crashing typo in Python TNonblockingServer - * [THRIFT-4548] - Supporting TBinaryProtocolAccelerated protocol when using TMultiplexedProcessor in Python - * [THRIFT-4577] - Outdated cipher string in python unit test - * [THRIFT-4505] - python build on Vagrant Windows boxes fails - * [THRIFT-4621] - THeader for Python - * [THRIFT-4668] - make socket backlog configurable for python - * [THRIFT-4561] - Python: cleanup socket timeout settings - -## ruby - * [THRIFT-4289] - Thrift RSpec test suite fails with Ruby 2.4.x due to Fixnum deprecation - * [THRIFT-4342] - Support ruby rspec 3 - * [THRIFT-4525] - Add ssl socket option to ruby cross tests - * [THRIFT-4450] - Add seek support to TCompactInputProtocol in Rust - * [THRIFT-4631] - Codegen Creates Invalid Ruby for Recursive Structs - * [THRIFT-4472] - Fix the genspec for ruby so it does not complain about an invalid license - -## rust - * [THRIFT-4662] - Rust const string calls function at compile time - * [THRIFT-4661] - Rust enum name wrong case in generated structs - * [THRIFT-4617] - Avoid generating conflicting struct names in Rust code - * [THRIFT-4529] - Rust generation should include #![allow(non_snake_case)] or force conform to Rust style guidelines - * [THRIFT-4390] - Rust binary protocol and buffered transport cannot handle writes above 4096 bytes - * [THRIFT-4419] - Rust framed transport cannot handle writes above 4096 bytes - * [THRIFT-4658] - Rust's TBinaryInputProtocol fails when strict is false - * [THRIFT-4187] - Dart -> Rust Framed cross tests fail - * [THRIFT-4664] - Rust cannot create ReadHalf/WriteHalf to implement custom tranports - * [THRIFT-4665] - Keep Rust library up-to-date on crates.io - -## swift (new language support in 0.12.0) - * [THRIFT-3773] - Swift Library - -## test suite - * [THRIFT-4515] - Gracefully shutdown cross-test servers to fully test teardown - * [THRIFT-4085] - Add .NET Core to the make cross standard test suite - * [THRIFT-4358] - Add unix domain sockets in ruby to cross test - code exists - -## typescript (new language support in 0.12.0) - * [THRIFT-3143] - add typescript directory support - -================================================================================ -Thrift 0.11.0 --------------------------------------------------------------------------------- -## Sub-task - * [THRIFT-2733] - Erlang coding standards - * [THRIFT-2740] - Perl coding standards - * [THRIFT-3610] - Streamline exception handling in Python server handler - * [THRIFT-3686] - Java processor should report internal error on uncaught exception - * [THRIFT-4049] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4053] - Skip() should throw TProtocolException.INVALID_DATA on unknown data types - * [THRIFT-4136] - Align is_binary() method with is_string() to simplify those checks - * [THRIFT-4137] - Fix remaining undefined behavior invalid vptr casts in Thrift Compiler - * [THRIFT-4138] - Fix remaining undefined behavior invalid vptr casts in C++ library - * [THRIFT-4296] - Fix Ubuntu Xenial build environment for the python language - * [THRIFT-4298] - Fix Ubuntu Xenial build environment for the go 1.6 language - * [THRIFT-4299] - Fix Ubuntu Xenial build environment for the D language - * [THRIFT-4300] - Fix make cross in Ubuntu Xenial docker environment, once all language support issues are fixed - * [THRIFT-4302] - Fix Ubuntu Xenial make cross testing for lua and php7 - * [THRIFT-4398] - Update EXTRA_DIST for "make dist" - -## Bug - * [THRIFT-381] - Fail fast if configure detects C++ problems - * [THRIFT-1677] - MinGW support broken - * [THRIFT-1805] - Thrift should not swallow ALL exceptions - * [THRIFT-2026] - Fix TCompactProtocol 64 bit builds - * [THRIFT-2642] - Recursive structs don't work in python - * [THRIFT-2889] - stable release 0.9.2, erlang tutorial broken - * [THRIFT-2913] - Ruby Server Thrift::ThreadPoolServer should serve inside a thread - * [THRIFT-2998] - Node.js: Missing header from http request - * [THRIFT-3000] - .NET implementation has trouble with mixed IP modes - * [THRIFT-3281] - Travis CI build passed but the log says BUILD FAILED - * [THRIFT-3358] - Makefile:1362: *** missing separator. Stop. - * [THRIFT-3600] - Make TTwisted server send exception on unexpected handler error - * [THRIFT-3602] - Make Tornado server send exception on unexpected handler error - * [THRIFT-3657] - D TFileWriterTransport close should use non-priority send - * [THRIFT-3700] - Go Map has wrong default value when optional - * [THRIFT-3703] - Unions Field Count Does Not Consider Map/Set/List Fields - * [THRIFT-3730] - server log error twice - * [THRIFT-3778] - go client can not pass method parameter to server of other language if no field_id is given - * [THRIFT-3784] - thrift-maven-plugin generates invalid include directories for IDL in dependency JARs - * [THRIFT-3801] - Node Thrift client throws exception with multiplexer and responses that are bigger than a single buffer - * [THRIFT-3821] - TMemoryBuffer buffer may overflow when resizing - * [THRIFT-3832] - Thrift version 0.9.3 example on Windows, Visual Studio, linking errors during compiling - * [THRIFT-3847] - thrift/config.h includes a #define for VERSION which will likely conflict with existing user environment or code - * [THRIFT-3873] - Fix various build warnings when using Visual Studio - * [THRIFT-3891] - TNonblockingServer configured with more than one IO threads does not always return from serve() upon stop() - * [THRIFT-3892] - Thrift uses TLS SNI extension provided by OpenSSL library. Older version of OpenSSL(< 0.9.8f) may create problem because they do not support 'SSL_set_tlsext_host_name()'. - * [THRIFT-3895] - Build fails using Java 1.8 with Ant < 1.9 - * [THRIFT-3896] - map data with number string key cannot access that deserialized by php extension - * [THRIFT-3938] - Python TNonblockingServer does not work with SSL - * [THRIFT-3944] - TSSLSocket has dead code in checkHandshake - * [THRIFT-3946] - Java 1.5 compatibility broken for binary fields (java5 option) - * [THRIFT-3960] - Inherited services in Lua generator are not named correctly - * [THRIFT-3962] - Ant build.xml broken on Windows for Java library - * [THRIFT-3963] - Thrift.cabal filename does not match module name - * [THRIFT-3967] - gobject/gparam.h:166:33: warning: enumerator value for ‘G_PARAM_DEPRECATED’ is not an integer constant expression - * [THRIFT-3968] - Deserializing empty string/binary fields - * [THRIFT-3974] - Using clang-3.8 and ThreadSanitizer on the concurrency_test claims bad PThread behavior - * [THRIFT-3984] - PHP7 extension causes segfault - * [THRIFT-4008] - broken ci due to upstream dependency versioning break - * [THRIFT-4009] - Use @implementer instead of implements in TTwisted.py - * [THRIFT-4010] - Q.fcall messing up with *this* pointer inside called function - * [THRIFT-4011] - Sets of Thrift structs generate Go code that can't be serialized to JSON - * [THRIFT-4012] - Python Twisted implementation uses implements, not compatible with Py3 - * [THRIFT-4014] - align C# meta data in AssemblyInfo.cs - * [THRIFT-4015] - Fix wrongly spelled "Thirft"s - * [THRIFT-4016] - testInsanity() impl does not conform to test spec in ThriftTest.thrift - * [THRIFT-4023] - Skip unexpected field types on read/write - * [THRIFT-4024] - Skip() should throw on unknown data types - * [THRIFT-4026] - TSSLSocket doesn't work with Python < 2.7.9 - * [THRIFT-4029] - Accelerated protocols do not build from thrift-py 0.10.0 on PyPI - * [THRIFT-4031] - Go plugin generates invalid code for lists of typedef'ed built-in types - * [THRIFT-4033] - Default build WITH_PLUGIN=ON for all builds results in packaging errors - * [THRIFT-4034] - CMake doesn't work to build compiler on MacOS - * [THRIFT-4036] - Add .NET Core environment/build support to the docker image - * [THRIFT-4038] - socket check: checking an unsigned number against >= 0 never fails - * [THRIFT-4042] - ExtractionError when using accelerated thrift in a multiprocess test - * [THRIFT-4043] - thrift perl debian package is placing files in the wrong place - * [THRIFT-4044] - Build job 17 failing on every pull request; hspec core (haskell) 2.4 issue - * [THRIFT-4046] - MinGW with gcc 6.2 does not compile on Windows - * [THRIFT-4060] - Thrift printTo ostream overload mechanism breaks down when types are nested - * [THRIFT-4062] - Remove debug print from TServiceClient - * [THRIFT-4065] - Document Perl ForkingServer signal restriction imposed by THRIFT-3848 and remove unnecessary code - * [THRIFT-4068] - A code comment in Java ServerSocket is wrong around accept() - * [THRIFT-4073] - enum files are still being generated with unused imports - * [THRIFT-4076] - Appveyor builds failing because ant 1.9.8 was removed from apache servers - * [THRIFT-4077] - AI_ADDRCONFIG redefined after recent change to PlatformSocket header - * [THRIFT-4079] - Generated perl code that returns structures from included thrift files is missing a necessary use clause - * [THRIFT-4087] - Spurious exception destroying TThreadedServer because of incorrect join() call - * [THRIFT-4102] - TBufferedTransport performance issue since 0.10.0 - * [THRIFT-4106] - concurrency_test fails randomly - * [THRIFT-4108] - c_glib thrift ssl has multiple bugs and deprecated functions - * [THRIFT-4109] - Configure Script uses string comparison for versions - * [THRIFT-4129] - C++ TNonblockingServer fd leak when failing to dispatch new connections - * [THRIFT-4131] - Javascript with WebSocket handles oneway methods wrong - * [THRIFT-4134] - Fix remaining undefined behavior invalid vptr casts - * [THRIFT-4140] - Use of non-thread-safe function gmtime() - * [THRIFT-4141] - Installation of haxe in docker files refers to a redirect link and fails - * [THRIFT-4147] - Rust: protocol should accept transports with non-static lifetime - * [THRIFT-4148] - [maven-thrift-plugin] compile error while import a thrift in dependency jar file. - * [THRIFT-4149] - System.out pollutes log files - * [THRIFT-4154] - PHP close() of a TSocket needs to close any type of socket - * [THRIFT-4158] - minor issue in README-MSYS2.md - * [THRIFT-4159] - Building tests fails on MSYS2 (MinGW64) due to a (small?) linker error - * [THRIFT-4160] - TNonblocking server fix use of closed/freed connections - * [THRIFT-4161] - TNonBlocking server using uninitialized event in error paths - * [THRIFT-4162] - TNonBlocking handling of TSockets in error state is incorrect after fd is closed - * [THRIFT-4164] - Core in TSSLSocket cleanupOpenSSL when destroying a mutex used by openssl - * [THRIFT-4165] - C++ build has many warnings under c++03 due to recent changes, cmake needs better platform-independent language level control - * [THRIFT-4166] - Recent fix to remove boost::lexical_cast usage broke VS2010 - * [THRIFT-4167] - Missing compile flag - * [THRIFT-4170] - Support lua 5.1 or earlier properly for object length determination - * [THRIFT-4172] - node.js tutorial client does not import assert, connection issues are not handled properly - * [THRIFT-4177] - Java compiler produces deep copy constructor that could make shallow copy instead - * [THRIFT-4184] - Building on Appveyor: invalid escape sequence \L - * [THRIFT-4185] - fb303 counter encoding fix - * [THRIFT-4189] - Framed/buffered transport Dispose() does not dispose the nested transport - * [THRIFT-4193] - Lower the default maxReadBufferBytes for non-blocking servers - * [THRIFT-4195] - Compilation to GO produces broken code - * [THRIFT-4196] - Cannot generate recursive Rust types - * [THRIFT-4204] - typo in compact spec - * [THRIFT-4206] - Strings in container fields are not decoded properly with py:dynamic and py:utf8strings - * [THRIFT-4208] - C# NamedPipesServer not really working in some scenarios - * [THRIFT-4211] - Fix GError glib management under Thrift - * [THRIFT-4212] - c_glib flush tries to close SSL even if socket is invalid - * [THRIFT-4213] - Travis build fails at curl -sSL https://www.npmjs.com/install.sh | sh - * [THRIFT-4215] - Golang TTransportFactory Pattern Squelches Errors - * [THRIFT-4216] - Golang Http Clients Do Not Respect User Options - * [THRIFT-4218] - Set TCP_NODELAY for PHP client socket - * [THRIFT-4219] - Golang HTTP clients created with Nil buffer - * [THRIFT-4231] - TJSONProtocol throws unexpected non-Thrift-exception on null strings - * [THRIFT-4232] - ./configure does bad ant version check - * [THRIFT-4234] - Travis build fails cross language tests with "Unsupported security protocol type" - * [THRIFT-4237] - Go TServerSocket Race Conditions - * [THRIFT-4240] - Go TSimpleServer does not close properly - * [THRIFT-4243] - Go TSimpleServer race on wait in Stop() method - * [THRIFT-4245] - Golang TFramedTransport's writeBuffer increases if writes to transport failed - * [THRIFT-4246] - Sequence number mismatch on multiplexed clients - * [THRIFT-4247] - Compile fails with openssl 1.1 - * [THRIFT-4248] - Compile fails - strncpy, memcmp, memset not declared in src/thrift/transport/TSSLSocket.cpp - * [THRIFT-4251] - Java Epoll Selector Bug - * [THRIFT-4257] - Typescript async callbacks do not provide the correct types - * [THRIFT-4258] - Boost/std thread wrapping faultiness - * [THRIFT-4260] - Go context generation issue. Context is parameter in Interface not in implementation - * [THRIFT-4261] - Go context generation issue: breaking change in generated code regarding thrift.TProcessorFunction interface - * [THRIFT-4262] - Invalid binding to InterlockedCompareExchange64() with 64-bit targets - * [THRIFT-4263] - Fix use after free bug for thrown exceptions - * [THRIFT-4266] - Erlang library throws during skipping fields of composite type (maps, lists, structs, sets) - * [THRIFT-4268] - Erlang library emits debugging output in transport layer - * [THRIFT-4273] - erlang:now/0: Deprecated BIF. - * [THRIFT-4274] - Python feature tests for SSL/TLS failing - * [THRIFT-4279] - Wrong path in include directive in generated Thrift sources - * [THRIFT-4283] - TNamedPipeServer race condition in interrupt - * [THRIFT-4284] - File contains a NBSP: lib/nodejs/lib/thrift/web_server.js - * [THRIFT-4290] - C# nullable option generates invalid code for non-required enum field with default value - * [THRIFT-4292] - TimerManager::remove() is not implemented - * [THRIFT-4307] - Make ssl-open timeout effective in golang client - * [THRIFT-4312] - Erlang client cannot connect to Python server: exception error: econnrefused - * [THRIFT-4313] - Program code of the Erlang tutorial files contain syntax errors - * [THRIFT-4316] - TByteBuffer.java will read too much data if a previous read returns fewer bytes than requested - * [THRIFT-4319] - command line switch for "evhttp" incorrectly resolved to anon pipes - * [THRIFT-4323] - range check errors or NPE in edge cases - * [THRIFT-4324] - field names can conflict with local vars in generated code - * [THRIFT-4328] - Travis CI builds are timing out (job 1) and haxe builds are failing since 9/11 - * [THRIFT-4329] - c_glib Doesn't have a multiplexed processor - * [THRIFT-4331] - C++: TSSLSockets bug in handling huge messages, bug in handling polling - * [THRIFT-4332] - Binary protocol has memory leaks - * [THRIFT-4334] - Perl indentation incorrect when defaulting field attribute to a struct - * [THRIFT-4339] - Thrift Framed Transport in Erlang crashes server when client disconnects - * [THRIFT-4340] - Erlang fix a crash on client close - * [THRIFT-4355] - Javascript indentation incorrect when defaulting field attribute to a struct - * [THRIFT-4356] - thrift_protocol call Transport cause Segmentation fault - * [THRIFT-4359] - Haxe compiler looks like it is producing incorrect code for map or set key that is binary type - * [THRIFT-4362] - Missing size-check can lead to huge memory allocation - * [THRIFT-4364] - Website contributing guide erroneously recommends submitting patches in JIRA - * [THRIFT-4365] - Perl generated code uses indirect object syntax, which occasionally causes compilation errors. - * [THRIFT-4367] - python TProcessor.process is missing "self" - * [THRIFT-4370] - Ubuntu Artful cppcheck and flake8 are more stringent and causing SCA build job failures - * [THRIFT-4372] - Pipe write operations across a network are limited to 65,535 bytes per write. - * [THRIFT-4374] - cannot load thrift_protocol due to undefined symbol: _ZTVN10__cxxabiv120__si_class_type_infoE - * [THRIFT-4375] - TMemory throw bad_alloc due to counter overflow - * [THRIFT-4376] - Coverity high impact issue resolution - * [THRIFT-4377] - haxe. socket handles leak in TSimpleServer - * [THRIFT-4381] - Wrong isset bitfield value after transmission - * [THRIFT-4385] - Go remote client -u flag is broken - * [THRIFT-4392] - compiler/..../plugin.thrift structs mis-ordered blows up ocaml generator - * [THRIFT-4395] - Unable to build in the ubuntu-xenial docker image: clap 2.28 requires Rust 1.20 - * [THRIFT-4396] - inconsistent (or plain wrong) version numbers in master/trunk - -## Documentation - * [THRIFT-4157] - outdated readme about Haxe installation on Linux - -## Improvement - * [THRIFT-105] - make a thrift_spec for a structures with negative tags - * [THRIFT-281] - Cocoa library code needs comments, badly - * [THRIFT-775] - performance improvements for Perl - * [THRIFT-2221] - Generate c++ code with std::shared_ptr instead of boost::shared_ptr. - * [THRIFT-2364] - OCaml: Use Oasis exclusively for build process - * [THRIFT-2504] - TMultiplexedProcessor should allow registering default processor called if no service name is present - * [THRIFT-3207] - Enable build with OpenSSL 1.1.0 series - * [THRIFT-3272] - Perl SSL Authentication Support - * [THRIFT-3357] - Generate EnumSet/EnumMap where elements/keys are enums - * [THRIFT-3369] - Implement SSL/TLS support on C with c_glib - * [THRIFT-3467] - Go Maps for Thrift Sets Should Have Values of Type struct{} - * [THRIFT-3580] - THeader for Haskell - * [THRIFT-3627] - Missing basic code style consistency of JavaScript. - * [THRIFT-3706] - There's no support for Multiplexed protocol on c_glib library - * [THRIFT-3766] - Add getUnderlyingTransport() to TZlibTransport - * [THRIFT-3776] - Go code from multiple thrift files with the same namespace - * [THRIFT-3823] - Escape documentation while generating non escaped documetation - * [THRIFT-3854] - allow users to clear read buffers - * [THRIFT-3859] - Unix Domain Socket Support in Objective-C - * [THRIFT-3921] - C++ code should print enums as strings - * [THRIFT-3926] - There should be an error emitted when http status code is not 200 - * [THRIFT-4007] - Micro-optimization of TTransport.py - * [THRIFT-4040] - Add real cause of TNonblockingServerSocket error to exception - * [THRIFT-4064] - Update node library dependencies - * [THRIFT-4069] - All perl packages should have proper namespace, version syntax, and use proper thrift exceptions - * [THRIFT-4071] - Consolidate the Travis CI jobs where possible to put less stress on the Apache Foundation's allocation of CI build slaves - * [THRIFT-4072] - Add the possibility to send custom headers in TCurlClient - * [THRIFT-4075] - Better MinGW support for headers-only boost (without thread library) - * [THRIFT-4081] - Provide a MinGW 64-bit Appveyor CI build for better pull request validation - * [THRIFT-4084] - Improve SSL security in thrift by adding a make cross client that checks to make sure SSLv3 protocol cannot be negotiated - * [THRIFT-4095] - Add multiplexed protocol to Travis CI for make cross - * [THRIFT-4099] - Auto-derive Hash for generated Rust structs - * [THRIFT-4110] - The debian build files do not produce a "-dbg" package for debug symbols of libthrift0 - * [THRIFT-4114] - Space after '///' in doc comments - * [THRIFT-4126] - Validate objects in php extension - * [THRIFT-4130] - Ensure Apache Http connection is released back to pool after use - * [THRIFT-4151] - Thrift Mutex Contention Profiling (pthreads) should be disabled by default - * [THRIFT-4176] - Implement a threaded and threadpool server type for Rust - * [THRIFT-4183] - Named pipe client blocks forever on Open() when there is no server at the other end - * [THRIFT-4190] - improve C# TThreadPoolServer defaults - * [THRIFT-4197] - Implement transparent gzip compression for HTTP transport - * [THRIFT-4198] - Ruby should log Thrift internal errors to global logger - * [THRIFT-4203] - thrift server stop gracefully - * [THRIFT-4205] - c_glib is not linking against glib + gobject - * [THRIFT-4209] - warning CS0414 in T[TLS]ServerSocket.cs - * [THRIFT-4210] - include Thrift.45.csproj into CI runs - * [THRIFT-4217] - HttpClient should support gzip and deflate - * [THRIFT-4222] - Support Unix Domain Sockets in Golang TServerSocket - * [THRIFT-4233] - Make THsHaServer.invoker available (get method only) in inherited classes - * [THRIFT-4236] - Support context in go generated code. - * [THRIFT-4238] - JSON generator: make annotation-aware - * [THRIFT-4269] - Don't append '.' to Erlang namespace if it ends in '_'. - * [THRIFT-4270] - Generate Erlang mapping functions for const maps and lists - * [THRIFT-4275] - Add support for zope.interface only, apart from twisted support. - * [THRIFT-4285] - Pull generated send/recv into library to allow behaviour to be customised - * [THRIFT-4287] - Add c++ compiler "no_skeleton" flag option - * [THRIFT-4288] - Implement logging levels properly for node.js - * [THRIFT-4295] - Refresh the Docker image file suite for Ubuntu, Debian, and CentOS - * [THRIFT-4305] - Emit ddoc for generated items - * [THRIFT-4306] - Thrift imports not replicated to D service output - * [THRIFT-4315] - Add default message for TApplicationException - * [THRIFT-4318] - Delphi performance improvements - * [THRIFT-4325] - Simplify automake cross compilation by relying on one global THRIFT compiler path - * [THRIFT-4327] - Improve TimerManager API to allow removing specific task - * [THRIFT-4330] - Allow unused crates in Rust files - * [THRIFT-4333] - Erlang tutorial examples are using a different port (9999) - * [THRIFT-4343] - Change CI builds to use node.js 8.x LTS once available - * [THRIFT-4345] - Create a docker build environment that uses the minimum supported language levels - * [THRIFT-4346] - Allow Zlib transport factory to wrap other transports - * [THRIFT-4348] - Perl HTTP Client custom HTTP headers - * [THRIFT-4350] - Update netcore build for dotnet 2.0 sdk and make cross validation - * [THRIFT-4351] - Use Travis CI Build Stages to optimize the CI build - * [THRIFT-4353] - cannot read via thrift_protocol at server side - * [THRIFT-4378] - add set stopTimeoutUnit method to TThreadPoolServer - -## New Feature - * [THRIFT-750] - C++ Compiler Virtual Function Option - * [THRIFT-2945] - Implement support for Rust language - * [THRIFT-3857] - thrift js:node complier support an object as parameter not an instance of struct - * [THRIFT-3933] - Port official C# .NET library for Thrift to C# .NET Core libary - * [THRIFT-4039] - Update of Apache Thrift .Net Core lib - * [THRIFT-4113] - Provide a buffer transport for reading/writing in memory byte stream - -## Question - * [THRIFT-2956] - autoconf - possibly undefined macro - AC_PROG_BISON - * [THRIFT-4223] - Add support to the isServing() method for the C++ library - -## Task - * [THRIFT-3622] - Fix deprecated uses of std::auto_ptr - * [THRIFT-4028] - Please remove System.out.format from the source code - * [THRIFT-4186] - Build and test rust client in Travis - -## Test - * [THRIFT-4264] - PHP - Support both shared & static linking of sockets library - -## Wish - * [THRIFT-4344] - Define and maintain the minimum language level for all languages in one place - - -Thrift 0.10.0 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1840] - Thrift Generated Code Causes Global Variable Leaks - * [THRIFT-1828] - moc_TQTcpServer.cpp was removed from source tree but is in thrift-0.9.0.tar.gz - * [THRIFT-1790] - cocoa: Duplicate interface definition error - * [THRIFT-1776] - TPipeServer should implement "listen", so that TServerEventHandler preServe will work right - * [THRIFT-1351] - Compiler does not care about binary strings - * [THRIFT-1229] - Python fastbinary.c can not handle unicode as generated python code - * [THRIFT-749] - C++ TBufferedTransports do not flush their buffers on delete - * [THRIFT-747] - C++ TSocket->close calls shutdown breaking forked parent process - * [THRIFT-732] - server exits abnormally when client calls send_xxx function without calling recv_xxx function - * [THRIFT-3942] - TSSLSocket does not honor send and receive timeouts - * [THRIFT-3941] - WinXP version of thrift_poll() relies on undefined behavior by passing a destructed variable to select() - * [THRIFT-3940] - Visual Studio project file for compiler is broken - * [THRIFT-3943] - Coverity Scan identified some high severity defects - * [THRIFT-3929] - PHP "nsglobal" Option Results in Syntax Error in Generated Code (Trailing Backslash) - * [THRIFT-3936] - Cannot compile 0.10.0 development tip with VS2013 and earlier (snprintf, uint32_t) - * [THRIFT-3935] - Incorrect skipping of map and set - * [THRIFT-3920] - Ruby: Ensuring that HTTP failures will clear the http transport outbuf var - * [THRIFT-3919] - C# TTLSServerSocket does not use clientTimeout - * [THRIFT-3917] - Check backports.ssl_match_hostname module version - * [THRIFT-3909] - Fix c_glib static lib CMake build - * [THRIFT-3904] - Typo in node tutorial leads to wrong transport being used - * [THRIFT-3848] - As an implementer of a perl socket server, I do not want to have to remember to ignore SIGCHLD for it to work properly - * [THRIFT-3844] - thrift_protocol cannot compile in 7.0.7 - * [THRIFT-3843] - integer issues with Haxe PHP targets cause ZigZag encoding to fail - * [THRIFT-3842] - Dart generates incorrect code for a const struct - * [THRIFT-3841] - dart compact protocol incorrectly serializes/deserialized doubles - * [THRIFT-3708] - NameError: global name 'TProtocol' is not defined - * [THRIFT-3704] - "TConnectedClient died: Could not refill buffer" message shown when using HTTP Server - * [THRIFT-3678] - Fix javadoc errors on JDK 8 - * [THRIFT-3014] - AppVeyor support - * [THRIFT-2994] - Node.js TJSONProtocol cannot be used for object serialization. - * [THRIFT-2974] - writeToParcel throws NPE for optional enum fields - * [THRIFT-2948] - Python TJSONProtocol doesn't handle structs with binary fields containing invalid unicode. - * [THRIFT-2845] - ChildService.Plo: No such file or directory - * [THRIFT-3276] - Binary data does not decode correctly using the TJSONProtocol when the base64 encoded data is padded. - * [THRIFT-3253] - Using latest version of D gives deprecation notices - * [THRIFT-2883] - TTwisted.py, during ConnectionLost processing: exceptions.RuntimeError: dictionary changed size during iteration - * [THRIFT-2019] - Writing on a disconnected socket on Mac causes SIG PIPE - * [THRIFT-2020] - Thrift library has some empty files that haven't really been deleted - * [THRIFT-2049] - Go compiler doesn't build on native Windows - * [THRIFT-2024] - TServer.cpp warns on 64-bit platforms about truncating an rlim_t into an int - * [THRIFT-2023] - gettimeofday implementation on Windows errors when no time zone is passed in. - * [THRIFT-2022] - CoB and dense code generation still uses TR1 bind, even though that doesn't work with clang - * [THRIFT-2027] - Minor 64-bit and NOMINMAX issues in C++ library - * [THRIFT-2156] - TServerSocket::listen() is throwing exceptions with misleading information - * [THRIFT-2154] - Missing #deepCopy should return T - * [THRIFT-3157] - TBase signature should be TBase, F extends TFieldIdEnum> - * [THRIFT-3156] - Node TLS: server executes processing logic two full times - * [THRIFT-3154] - tutorial/py.tornado throw EOF exception - * [THRIFT-3063] - C++ build -Wunused-parameter warnings on processor_test, TransportTest - * [THRIFT-3056] - Add string/collection length limits for Python protocol readers - * [THRIFT-3237] - Fix TNamedPipeServer::createNamedPipe memory leak - * [THRIFT-3233] - Fix C++ ThreadManager::Impl::removeWorker worker join - * [THRIFT-3232] - Cannot deserialize json messages created with fieldNamesAsString - * [THRIFT-3206] - Fix Visual Studio build failure due 'pthread_self': identifier not found - * [THRIFT-3200] - JS and nodejs do not encode JSON protocol binary fields as base64 - * [THRIFT-3199] - Exception field has basic metadata - * [THRIFT-3182] - TFramedTransport is in an invalid state after frame size exception - * [THRIFT-2536] - new TSocket, uninitialised value reported by valgrind - * [THRIFT-2527] - Apache Thrift IDL Compiler code generated for Node.js should be jshint clean - * [THRIFT-2519] - "processor" class is not being generated - * [THRIFT-2431] - TFileTransportTest fails with "check delta < XXX failed" - * [THRIFT-2708] - Erlang library does not support "oneway" message type - * [THRIFT-3377] - Deep copy is actually shallow when using typedef members - * [THRIFT-3376] - C# and Python JSON protocol double values lose precision - * [THRIFT-3373] - Various fixes for cross test servers and clients - * [THRIFT-3370] - errno extern variable redefined. Not compiling for Android - * [THRIFT-3379] - Potential out of range panic in Go JSON protocols - * [THRIFT-3371] - Abstract namespace Unix domain sockets broken in C++ - * [THRIFT-3380] - nodejs: 0.9.2 -> 0.9.3 upgrade breaks Protocol and Transport requires - * [THRIFT-3367] - Fix bad links to coding_standards.md #634 - * [THRIFT-3401] - Nested collections emit Objective-C code that cannot compile - * [THRIFT-3403] - JSON String reader doesn't recognize UTF-16 surrogate pairs - * [THRIFT-3362] - make check fails for C++ at the SecurityTest - * [THRIFT-3395] - Cocoa compiler produces corrupt code when boxing enums inside map. - * [THRIFT-3394] - compiler generates uncompilable code - * [THRIFT-3388] - hash doesn't work on set/list - * [THRIFT-3391] - Wrong bool formatting in test server - * [THRIFT-3390] - TTornado server doesn't handle closed connections properly - * [THRIFT-3382] - TBase class for C++ Library - * [THRIFT-3392] - Java TZlibTransport does not close its wrapper streams upon close() - * [THRIFT-3383] - i64 related warnings - * [THRIFT-3386] - misc. warnings with make check - * [THRIFT-3385] - warning: format ‘%lu’ expects ‘long unsigned int’, but has type ‘std::basic_string::size_type {aka unsigned int} - * [THRIFT-3355] - npm WARN package.json thrift@1.0.0-dev No license field. - * [THRIFT-3360] - Improve cross test servers and clients further - * [THRIFT-3359] - Binary field incompatibilities - * [THRIFT-3354] - Fix word-extraction substr bug in initialism code - * [THRIFT-3350] - Python JSON protocol does not encode binary as Base64 - * [THRIFT-3577] - assertion failed at line 512 of testcontainertest.c - * [THRIFT-3576] - Boost test --log_format arg does not accept lowercase - * [THRIFT-3575] - Go compiler tries to use unexported library methods when using read_write_private - * [THRIFT-3574] - Cocoa generator makes uncompilable imports - * [THRIFT-3570] - Remove duplicate instances that are added by upstream - * [THRIFT-3571] - Make feature test result browsable - * [THRIFT-3569] - c_glib protocols do not check number of bytes read by transport - * [THRIFT-3568] - THeader server crashes on readSlow - * [THRIFT-3567] - GLib-GObject-CRITICAL **: g_object_unref: assertion 'G_IS_OBJECT (object)' failed - * [THRIFT-3566] - C++/Qt: TQTcpServerTest::test_communicate() is never executed - * [THRIFT-3564] - C++/Qt: potential core dump in TQTcpServer in case an exception occurs in TAsyncProcessor::process() - * [THRIFT-3558] - typos in c_glib tests - * [THRIFT-3559] - Fix awkward extra semi-colons with Cocoa container literals - * [THRIFT-3555] - 'configure' script does not honor --with-openssl= for libcrypto for BN_init - * [THRIFT-3554] - Constant decls may lead to "Error: internal error: prepare_member_name_mapping() already active for different struct" - * [THRIFT-3552] - glib_c Memory Leak - * [THRIFT-3551] - Thrift perl library missing package declaration - * [THRIFT-3549] - Exceptions are not properly stringified in Perl library - * [THRIFT-3546] - NodeJS code should not be namespaced (and is currently not strict-mode compliant) - * [THRIFT-3545] - Container type literals do not compile - * [THRIFT-3538] - Remove UnboundMethodType in TProtocolDecorator - * [THRIFT-3536] - Error 'char' does not contain a definition for 'IsLowSurrogate' for WP7 target - * [THRIFT-3534] - Link error when building with Qt5 - * [THRIFT-3533] - Can not send nil pointer as service method argument - * [THRIFT-3507] - THttpClient does not use proxy from http_proxy, https_proxy environment variables - * [THRIFT-3502] - C++ TServerSocket passes small buffer to getsockname - * [THRIFT-3501] - Forward slash in comment causes compiler error - * [THRIFT-3498] - C++ library assumes optional function pthread_attr_setschedpolicy is available - * [THRIFT-3497] - Build fails with "invalid use of incomplete type" - * [THRIFT-3496] - C++: Cob style client fails when sending a consecutive request - * [THRIFT-3493] - libthrift does not compile on windows using visual studio - * [THRIFT-3488] - warning: unused variable 'program' - * [THRIFT-3489] - warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings] - * [THRIFT-3487] - Full support for newer Delphi versions - * [THRIFT-3528] - Fix warnings in thrift.ll - * [THRIFT-3527] - -gen py:dynamic,utf8strings ignores utf8strings option - * [THRIFT-3526] - Code generated by py:utf8strings does not work for Python3 - * [THRIFT-3524] - dcc32 warning "W1000 Symbol 'IsLowSurrogate' is deprecated: 'Use TCharHelper'" in Thrift.Protocol.JSON.pas - * [THRIFT-3525] - py:dynamic fails to handle binary list/set/map element - * [THRIFT-3521] - TSimpleJSONProtocolTest is not deterministic (fails when run on JDK 8) - * [THRIFT-3520] - Dart TSocket onError stream should be typed as Object - * [THRIFT-3519] - fastbinary does not work with -gen py:utf8strings - * [THRIFT-3518] - TConcurrentClientSyncInfo files were missing for Visual Studio - * [THRIFT-3512] - c_glib: Build fails due to missing features.h - * [THRIFT-3483] - Incorrect empty binary handling introduced by THRIFT-3359 - * [THRIFT-3479] - Oneway calls should not return exceptions to clients - * [THRIFT-3478] - Restore dropped method to THsHaServer.java - * [THRIFT-3477] - Parser fails on enum item that starts with 'E' letter and continues with number - * [THRIFT-3476] - Missing include in ./src/thrift/protocol/TJSONProtocol.cpp - * [THRIFT-3474] - Docker: thrift-compiler - * [THRIFT-3473] - When "optional' is used with a struct member, C++ server seems to not return it correctly - * [THRIFT-3468] - Dart TSocketTransport onError handler is too restrictive - * [THRIFT-3451] - thrift_protocol PHP extension missing config.m4 file - * [THRIFT-3456] - rounding issue in static assert - * [THRIFT-3455] - struct write method's return value is incorrect - * [THRIFT-3454] - Python Tornado tutorial is broken - * [THRIFT-3463] - Java can't be disabled in CMake build - * [THRIFT-3450] - NPE when using SSL - * [THRIFT-3449] - TBaseAsyncProcessor fb.responseReady() never called for oneway functions - * [THRIFT-3471] - Dart generator does not handle uppercase argument names - * [THRIFT-3470] - Sporadic timeouts with pipes - * [THRIFT-3465] - Go Code With Complex Const Initializer Compilation Depends On Struct Order - * [THRIFT-3464] - Fix several defects in c_glib code generator - * [THRIFT-3462] - Cocoa generates Incorrect #import header names - * [THRIFT-3453] - remove rat_exclude - * [THRIFT-3418] - Use of ciphers in ssl.wrap_socket() breaks python 2.6 compatibility - * [THRIFT-3417] - "namespace xsd" is not really working - * [THRIFT-3413] - Thrift code generation bug in Go when extending service - * [THRIFT-3420] - C++: TSSLSockets are not interruptable - * [THRIFT-3415] - include unistd.h conditionally - * [THRIFT-3414] - #include in THeaderTransport.h breaks windows build - * [THRIFT-3411] - Go generates remotes with wrong package qualifiers when including - * [THRIFT-3430] - Go THttpClient does not read HTTP response body to completion when closing - * [THRIFT-3423] - First call to thrift_transport:read_exact fails to dispatch correct function - * [THRIFT-3422] - Go TServerSocket doesn't close on Interrupt - * [THRIFT-3421] - rebar as dependency instead of bundling (was: rebar fails if PWD contains Unicode) - * [THRIFT-3428] - Go test fails when running make check - * [THRIFT-3445] - Throwable messages are hidden from JVM stack trace output - * [THRIFT-3443] - Thrift include can generate uncompilable code - * [THRIFT-3444] - Large 64 bit Integer does not preserve value through Node.js JSONProtocol - * [THRIFT-3436] - misc. cross test issues with UTF-8 path names - * [THRIFT-3435] - Put generated Java code for fullcamel tests in a separate package/namespace - * [THRIFT-3433] - Doubles aren't interpreted correctly - * [THRIFT-3437] - Mingw-w64 build fail - * [THRIFT-3434] - Dart generator produces empty name in pubspec.yaml for includes without namespaces - * [THRIFT-3408] - JSON generator emits incorrect types - * [THRIFT-3406] - Cocoa client should not schedule streams on main runloop - * [THRIFT-3404] - JSON String reader doesn't recognize UTF-16 surrogate pair - * [THRIFT-3636] - Double precision is not fully preserved in C++ TJSONProtocol - * [THRIFT-3632] - c_glib testserialization fails with glib assertion - * [THRIFT-3619] - Using Thrift 0.9.3 with googletest on Linux gcc 4.9 / C++11 - * [THRIFT-3617] - CMake does not build gv/xml generators - * [THRIFT-3615] - Fix Python SSL client resource leak on connection failure - * [THRIFT-3616] - lib/py/test/test_sslsocket.py is flaky - * [THRIFT-3643] - Perl SSL server crushes if a client disconnect without handshake - * [THRIFT-3639] - C# Thrift library forces TLS 1.0, thwarting TLS 1.2 usage - * [THRIFT-3633] - Travis "C C++ - GCC" build was using clang - * [THRIFT-3634] - Fix Python TSocket resource leak on connection failure - * [THRIFT-3630] - Debian/Ubuntu install docs need an update - * [THRIFT-3629] - Parser sets exitcode on errors, but generator does not - * [THRIFT-3608] - lib/cpp/test/SecurityTest is flaky in jenkins Thrift-precommit build. - * [THRIFT-3601] - Better conformance to PEP8 for generated code - * [THRIFT-3599] - Validate client IP address against cert's SubjectAltName - * [THRIFT-3598] - TBufferedTransport doesn't instantiate client connection - * [THRIFT-3597] - `make check` hangs in go tests - * [THRIFT-3589] - Dart generator uses wrong name in constructor for uppercase arguments with defaults - * [THRIFT-3588] - Using TypeScript with --noImplicitAny fails - * [THRIFT-3584] - boolean false value cannot be transferred - * [THRIFT-3578] - Make THeaderTransport detect TCompact framed and unframed - * [THRIFT-3323] - Python library does not handle escaped forward slash ("/") in JSON - * [THRIFT-3322] - CMake generated "make check" failes on python_test - * [THRIFT-3321] - Thrift can't be added as a subdirectory of another CMake-based project - * [THRIFT-3314] - Dots in file names of includes causes dots in javascript variable names - * [THRIFT-3307] - Segfault in Ruby serializer - * [THRIFT-3309] - Missing TConstant.php in /lib/php/Makefile.am - * [THRIFT-3810] - unresolved external symbol public: virtual void __cdecl apache::thrift::server::TServerFramework::serve(void) - * [THRIFT-3736] - C++ library build fails if OpenSSL does not surrpot SSLv3 - * [THRIFT-3878] - Compile error in TSSLSocket.cpp with new OpenSSL [CRYPTO_num_locks] - * [THRIFT-3949] - missing make dist entry for compiler/cpp/test - * [THRIFT-449] - The wire format of the JSON Protocol may not always be valid JSON if it contains non-UTF8 encoded strings - * [THRIFT-162] - Thrift structures are unhashable, preventing them from being used as set elements - * [THRIFT-3961] - TConnectedClient does not terminate the connection to the client if an exception while processing the received message occures. - * [THRIFT-3881] - Travis CI builds are failing due to docker failures (three retries, and gives up) - * [THRIFT-3937] - Cannot compile 0.10.0 development tip with gcc-4.6.x - * [THRIFT-3964] - Unsupported mechanism type ????? due to dependency on default OS-dependent charset - * [THRIFT-3038] - Use of volatile in cpp library - * [THRIFT-3301] - Java generated code uses imports that can lead to class name collisions with IDL defined types - * [THRIFT-3348] - PHP TCompactProtocol bool&int64 readvalue bug - * [THRIFT-3955] - TThreadedServer Memory Leak - * [THRIFT-3829] - Thrift does not install Python Libraries if Twisted is not installed - * [THRIFT-3932] - C++ ThreadManager has a rare termination race - * [THRIFT-3828] - cmake fails when Boost_INCLUDE_DIRS (and other variables passed to include_directories()) is empty - * [THRIFT-3958] - CMake WITH_MT option for windows static runtime linking does not support the cmake build type RelWithDebInfo - * [THRIFT-3957] - TConnectedClient does not disconnect from clients when their timeout is reached. - * [THRIFT-3953] - TSSLSocket::close should handle exceptions from waitForEvent because it is called by the destructor. - * [THRIFT-3977] - PHP extension creates undefined values when deserializing sets - * [THRIFT-3947] - sockaddr type isn't always large enough for the return of getsockname - * [THRIFT-2755] - ThreadSanitizer reports data race in ThreadManager::Impl::addWorker - * [THRIFT-3948] - errno is not the correct method of getting the error in windows - * [THRIFT-4008] - broken ci due to upstream dependency versioning break - * [THRIFT-3999] - Fix Debian & Ubuntu package dependencies - * [THRIFT-3886] - PHP cross test client returns 0 even when failing - * [THRIFT-3997] - building thrift libs does not support new openssl - -## Documentation - * [THRIFT-3867] - Specify BinaryProtocol and CompactProtocol - -## Epic - * [THRIFT-3049] - As an iOS developer, I want a generator and library that produces Swift code - * [THRIFT-2336] - UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - -## Improvement - * [THRIFT-1867] - Python client/server should support client-side certificates. - * [THRIFT-1313] - c_glib compact support - * [THRIFT-1385] - make install doesn't install java library in the setted folder - * [THRIFT-1437] - Update RPM spec - * [THRIFT-847] - Test Framework harmonization across all languages - * [THRIFT-819] - add Enumeration for protocol, transport and server types - * [THRIFT-3927] - Emit an error instead of throw an error in the async callback - * [THRIFT-3931] - TSimpleServer: If process request encounter UNKNOWN_METHOD, don't close transport. - * [THRIFT-3934] - Automatically resolve OpenSSL binary version on Windows CI - * [THRIFT-3918] - Run subset of make cross - * [THRIFT-3908] - Remove redundant dependencies from Dockerfile - * [THRIFT-3907] - Skip Docker image build on CI when unchanged - * [THRIFT-3868] - Java struct equals should do identity check before field comparison - * [THRIFT-3849] - Port Go serializer and deserializer to dart - * [THRIFT-2989] - Complete CMake build for Apache Thrift - * [THRIFT-2980] - ThriftMemoryBuffer doesn't have a constructor option to take an existing buffer - * [THRIFT-2856] - refactor erlang basic transports and unify interfaces - * [THRIFT-2877] - Optimize generated hashCode - * [THRIFT-2869] - JSON: run schema validation from tests - * [THRIFT-3112] - [Java] AsyncMethodCallback should be typed in generated AsyncIface - * [THRIFT-3263] - PHP jsonSerialize() should cast scalar types - * [THRIFT-2905] - Cocoa compiler should have option to produce "modern" Objective-C - * [THRIFT-2821] - Enable the use of custom HTTP-Header in the Transport - * [THRIFT-2093] - added the ability to set compression level in C++ zlib transport - * [THRIFT-2089] - Compiler ignores duplicate typenames - * [THRIFT-2056] - Moved all #include config.h statements to #include - * [THRIFT-2031] - Make SO_KEEPALIVE configurable for C++ lib - * [THRIFT-2021] - Improve large binary protocol string performance - * [THRIFT-2028] - Cleanup threading headers / libraries - * [THRIFT-2014] - Change C++ lib includes to use style throughout - * [THRIFT-2312] - travis.yml: build everything - * [THRIFT-1915] - Multiplexing Services - * [THRIFT-1736] - Visual Studio top level project files within msvc - * [THRIFT-1735] - integrate tutorial into regular build - * [THRIFT-1533] - Make TTransport should be Closeable - * [THRIFT-35] - Move language tests into their appropriate library directory - * [THRIFT-1079] - Support i64 in AS3 - * [THRIFT-1108] - SSL support for the Ruby library - * [THRIFT-3856] - update debian package deependencies - * [THRIFT-3833] - haxe http server implementation (by embeding into php web server) - * [THRIFT-3839] - Performance issue with big message deserialization using php extension - * [THRIFT-3820] - Erlang: Detect OTP >= 18 to use new time correction - * [THRIFT-3816] - Reduce docker build duration on Travis-CI - * [THRIFT-3815] - Put appveyor dependency versions to one place - * [THRIFT-3788] - Compatibility improvements and Win64 support - * [THRIFT-3792] - Timeouts for anonymous pipes should be configurable - * [THRIFT-3794] - Split Delphi application, protocol and transport exception subtypes into separate exceptions - * [THRIFT-3774] - The generated code should have exception_names meta info - * [THRIFT-3762] - Fix build warnings for deprecated Thrift "byte" fields - * [THRIFT-3756] - Improve requiredness documentation - * [THRIFT-3761] - Add debian package for Python3 - * [THRIFT-3742] - haxe php cli support - * [THRIFT-3733] - Socket timeout improvements - * [THRIFT-3728] - http transport for thrift-lua - * [THRIFT-3905] - Dart compiler does not initialize bool, int, and double properties - * [THRIFT-3911] - Loosen Ruby dev dependency version requirements - * [THRIFT-3906] - Run C# tests with make check - * [THRIFT-3900] - Add Python SSL flags - * [THRIFT-3897] - Provide meaningful exception type based on WebExceptionStatus in case of timeout - * [THRIFT-3808] - Missing `DOUBLE` in thrift type enumeration - * [THRIFT-3803] - Remove "file" attribute from XML generator - * [THRIFT-3660] - Add V4 mapped address to test client cert's altname - * [THRIFT-3661] - Use https to download meck in erlang test build - * [THRIFT-3659] - Check configure result of CMake on CI - * [THRIFT-3667] - Add TLS SNI support to clients - * [THRIFT-3651] - Make backports.match_hostname and ipaddress optional - * [THRIFT-3666] - Build D tutorial as part of Autotools build - * [THRIFT-3665] - Add D libevent and OpenSSL to docker images - * [THRIFT-3664] - Remove md5.c - * [THRIFT-3662] - Add Haskell to debian docker image - * [THRIFT-3711] - Add D to cross language test - * [THRIFT-3691] - Run flake8 Python style check on Travis-CI - * [THRIFT-3692] - (Re)enable Appveyor C++ and Python build - * [THRIFT-3677] - Improve CMake Java build - * [THRIFT-3679] - Add stdout log to testBinary in Java test server - * [THRIFT-3718] - Reduce size of docker image for build environment - * [THRIFT-3698] - [Travis-CI] Introduce retry to apt commands - * [THRIFT-3127] - switch -recurse to --recurse and reserve -r - * [THRIFT-3087] - Pass on errors like "connection closed" - * [THRIFT-3240] - Thrift Python client should support subjectAltName and wildcard certs in TSSLSocket - * [THRIFT-3213] - make cross should indicate when it skips a known failing test - * [THRIFT-3208] - Fix Visual Studio solution build failure due to missing source - * [THRIFT-3186] - Add TServerHTTP to Go library - * [THRIFT-2342] - Add __FILE__ and __LINE__ to Thrift C++ excpetions - * [THRIFT-3372] - Add dart generator to Visual Studio project - * [THRIFT-3366] - ThriftTest to implement standard return values - * [THRIFT-3402] - Provide a perl Unix Socket implementation - * [THRIFT-3361] - Improve C# library - * [THRIFT-3393] - Introduce i8 to provide consistent set of Thrift IDL integer types - * [THRIFT-3339] - Support for database/sql - * [THRIFT-3565] - C++: T[Async]Processor::getEventHandler() should be declared as const member functions - * [THRIFT-3563] - C++/Qt: removed usage of macro QT_PREPEND_NAMESPACE as it isn't consequently used for all references to Qt types. - * [THRIFT-3562] - Removed unused TAsyncProcessor::getAsyncServer() - * [THRIFT-3561] - C++/Qt: make use of Q_DISABLE_COPY() to get rid of copy ctor and assignment operator - * [THRIFT-3556] - c_glib file descriptor transport - * [THRIFT-3544] - Make cross test fail when server process died unexpectedly - * [THRIFT-3540] - Make python tutorial more in line with PEP8 - * [THRIFT-3535] - Dart generator argument to produce a file structure usable in parent library - * [THRIFT-3505] - Enhance Python TSSLSocket - * [THRIFT-3506] - Eliminate old style classes from library code - * [THRIFT-3503] - Enable py:utf8string by default - * [THRIFT-3499] - Add package_prefix to python generator - * [THRIFT-3495] - Minor enhancements and fixes for cross test - * [THRIFT-3486] - Java generated `getFieldValue` is incompatible with `setFieldValue` for binary values. - * [THRIFT-3484] - Consolidate temporary buffers in Java's TCompactProtocol - * [THRIFT-3516] - Add feature test for THeader TBinaryProtocol interop - * [THRIFT-3515] - Python 2.6 compatibility and test on CI - * [THRIFT-3514] - PHP 7 compatible version of binary protocol - * [THRIFT-3469] - Docker: Debian support - * [THRIFT-3416] - Retire old "xxx_namespace" declarations from the IDL - * [THRIFT-3426] - Align autogen comment in XSD - * [THRIFT-3424] - Add CMake android build option - * [THRIFT-3439] - Run make cross using Python3 when available - * [THRIFT-3440] - Python make check takes too much time - * [THRIFT-3441] - Stabilize Travis-CI builds - * [THRIFT-3431] - Avoid "schemes" HashMap lookups during struct reads/writes - * [THRIFT-3432] - Add a TByteBuffer transport to the Java library - * [THRIFT-3438] - Enable py:new_style by default - * [THRIFT-3405] - Go THttpClient misuses http.Client objects - * [THRIFT-3614] - Improve logging of test_sslsocket.py - * [THRIFT-3647] - Fix php extension build warnings - * [THRIFT-3642] - Speed up cross test runner - * [THRIFT-3637] - Implement compact protocol for dart - * [THRIFT-3613] - Port Python C extension to Python 3 - * [THRIFT-3612] - Add Python C extension for compact protocol - * [THRIFT-3611] - Add --regex filter to cross test runner - * [THRIFT-3631] - JSON protocol implementation for Lua - * [THRIFT-3609] - Remove or replace TestPortFixture.h - * [THRIFT-3605] - Have the compiler complain about invalid arguments and options - * [THRIFT-3596] - Better conformance to PEP8 - * [THRIFT-3585] - Compact protocol implementation for Lua - * [THRIFT-3582] - Erlang libraries should have service metadata - * [THRIFT-3579] - Introduce retry to make cross - * [THRIFT-3306] - Java: TBinaryProtocol: Use 1 temp buffer instead of allocating 8 - * [THRIFT-3910] - Do not invoke pip as part of build process - * [THRIFT-1857] - Python 3.X Support - * [THRIFT-1944] - Binding to zero port - * [THRIFT-3954] - Enable the usage of structs called "Object" in Java - * [THRIFT-3981] - Enable analyzer strong mode in Dart library - * [THRIFT-3998] - Document ability to add custom tags to thrift structs - * [THRIFT-4006] - Add a removeEventListener method on TSocket - -## New Feature - * [THRIFT-640] - Support deprecation - * [THRIFT-948] - SSL socket support for PHP - * [THRIFT-764] - add Support for Vala language - * [THRIFT-3046] - Allow PSR4 class loading for generated classes (PHP) - * [THRIFT-2113] - Erlang SSL Socket Support - * [THRIFT-1482] - Unix domain socket support under PHP - * [THRIFT-519] - Support collections of types without having to explicitly define it - * [THRIFT-468] - Rack Middleware Application for Rails - * [THRIFT-1708] - Add event handlers for processor events - * [THRIFT-3834] - Erlang namespacing and exception metadata - * [THRIFT-2510] - Implement TNonblockingServer's ability to listen on unix domain sockets - * [THRIFT-3397] - Implement TProcessorFactory in C# to enable per-client processors - * [THRIFT-3523] - XML Generator - * [THRIFT-3510] - Add HttpTaskAsyncHandler implementation - * [THRIFT-3318] - PHP: SimpleJSONProtocol Implementation - * [THRIFT-3299] - Dart language bindings in Thrift - * [THRIFT-2835] - Add possibility to distribute generators separately from thrift core, and load them dynamically - * [THRIFT-184] - Add OSGi Manifest headers to the libthrift java library to be able to use Thrift in the OSGi runtime - * [THRIFT-141] - If a required field is not present on serialization, throw an exception - * [THRIFT-1891] - Add Windows ALPC transport which is right counterpart of Unix domain sockets - -## Question - * [THRIFT-1808] - The Thrift struct should be considered self-contained? - * [THRIFT-2895] - Tutorial cpp - * [THRIFT-3860] - Elephant-bird application Test fails for Thrift - * [THRIFT-3811] - HTTPS Support for C++ applications - * [THRIFT-3509] - "make check" error - -## Story - * [THRIFT-3452] - .travis.yml: Migrating from legacy to container-based infrastructure - -## Sub-task - * [THRIFT-1811] - ruby tutorial as part of the regular build - * [THRIFT-2779] - PHP TJSONProtocol encode unicode into UCS-4LE which can't be parsed by other language bindings - * [THRIFT-2110] - Erlang: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-3852] - A Travis-CI job fails with "write error" - * [THRIFT-3740] - Fix haxelib.json classpath - * [THRIFT-3653] - incorrect union serialization - * [THRIFT-3652] - incorrect serialization of optionals - * [THRIFT-3655] - incorrect union serialization - * [THRIFT-3654] - incorrect serialization of optionals - * [THRIFT-3656] - incorrect serialization of optionals - * [THRIFT-3699] - Fix integer limit symbol includes in Python C extension - * [THRIFT-3693] - Fix include issue in C++ TSSLSocketInterruptTest on Windows - * [THRIFT-3694] - [Windows] Disable tests of a few servers that are not supported - * [THRIFT-3696] - Install pip to CentOS Docker images to fix Python builds - * [THRIFT-3638] - Fix haxelib.json - * [THRIFT-3251] - Add http transport for server to Go lib - * [THRIFT-2424] - Recursive Types - * [THRIFT-2423] - THeader - * [THRIFT-2413] - Python: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2409] - Java: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2412] - D: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2411] - C++: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2410] - JavaMe: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2668] - TestSuite: detailed result on passed tests by feature - * [THRIFT-2659] - python Test Server fails when throwing TException - * [THRIFT-3398] - Add CMake build for Haskell library and tests - * [THRIFT-3396] - DART: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-3364] - Fix ruby binary field encoding in TJSONProtocol - * [THRIFT-3381] - Fix for misc. codegen issues with THRIFT-2905 - * [THRIFT-3573] - No rule to make target `../../../test/c_glib/src/.deps/testthrifttest-thrift_test_handler.Po'. - * [THRIFT-3572] - "Unable to determine the behavior of a signed right shift" - * [THRIFT-3542] - Add length limit support to Java test server - * [THRIFT-3537] - Remove the (now obsolete) csharp:asyncctp flag - * [THRIFT-3532] - Add configurable string and container read size limit to Python protocols - * [THRIFT-3531] - Create cross lang feature test for string and container read length limit - * [THRIFT-3482] - Haskell JSON protocol does not encode binary field as Base64 - * [THRIFT-3425] - Minor fixes + simplification for CentOS Dockerfile - * [THRIFT-3442] - Run CMake tests on Appveyor - * [THRIFT-3409] - NodeJS binary field issues - * [THRIFT-3621] - Fix lib/cpp/test/SecurityTest.cpp to use ephemeral ports - * [THRIFT-3628] - Fix lib/cpp/test/TServerIntegrationTest.cpp to use ephemeral ports - * [THRIFT-3625] - Kill unused #include "TestPortFixture.h" in lib/cpp/test/TServerTransportTest.cpp. - * [THRIFT-3646] - Fix Python extension build warnings - * [THRIFT-3626] - Fix lib/cpp/test/TSocketInterruptTest.cpp to use ephemeral ports. - * [THRIFT-3624] - Fix lib/cpp/test/TServerSocketTest.cpp to use ephemeral ports - * [THRIFT-3623] - Fix Fix cpp/lib/test/TSSLSocketInterruptTest.cpp to use ephemeral ports - * [THRIFT-3592] - Add basic test client - * [THRIFT-3980] - add TExtendedBinaryProtocol.java - -## Task - * [THRIFT-1801] - Sync up TApplicationException codes across languages and thrift implementations - * [THRIFT-1259] - Automate versioning - -## Test - * [THRIFT-3400] - Add Erlang to cross test - * [THRIFT-3504] - Fix FastbinaryTest.py - -## Wish - * [THRIFT-3923] - Maybe remove Aereo from the "Powered by" list - * [THRIFT-2149] - Add an option to disable the generation of default operators - - - -Thrift 0.9.3 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-2441] - Cannot shutdown TThreadedServer when clients are still connected - * [THRIFT-2465] - TBinaryProtocolT breaks if copied/moved - * [THRIFT-2474] - thrift.h causes a compile failure - * [THRIFT-2540] - Running configure from outside the source directory fails - * [THRIFT-2598] - Add check for minimum Go version to configure.ac - * [THRIFT-2647] - compiler-hs: don't decapitalize field names, do decapitalize argument bindings - * [THRIFT-2773] - Generated Java code for 'oneway' methods is incorrect. - * [THRIFT-2789] - TNonblockingServer leaks socket FD's under load - * [THRIFT-2682] - TThreadedServer leaks per-thread memory - * [THRIFT-2674] - JavaScript: declare Accept: and Content-Type: in request - * [THRIFT-3078] - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket - * [THRIFT-3077] - C++ TFileTransport ignores return code from ftruncate - * [THRIFT-3067] - C++ cppcheck performance related warnings - * [THRIFT-3066] - C++ TDenseProtocol assert modifies instead of checks - * [THRIFT-3071] - bootstrap.sh on Ubuntu 12.04 (Precise) automake error - * [THRIFT-3069] - C++ TServerSocket leaks socket on fcntl get or set flags error - * [THRIFT-3079] - TNonblockingServerSocket's logger is not named after TNonblockingServerSocket - * [THRIFT-3080] - C++ TNonblockingServer connection leak while accept huge number connections. - * [THRIFT-3086] - C++ Valgrind Error Cleanup - * [THRIFT-3085] - thrift_reconnecting_client never try to reconnect - * [THRIFT-3123] - Missing include in compiler/cpp/src/main.h breaks build in some environments - * [THRIFT-3125] - Fix the list of exported headers in automake input - * [THRIFT-3126] - PHP JSON serializer converts empty or int-indexed maps to lists - * [THRIFT-3132] - Properly format date in Java @Generated annotations - * [THRIFT-3137] - Travis build hangs after failure - * [THRIFT-3138] - "make check" parallel execution is underministic - * [THRIFT-3139] - JS library test is flaky - * [THRIFT-3140] - ConcurrentModificationException is thrown by JavaScript test server - * [THRIFT-3124] - Some signed/unsigned warnings while building compiler - * [THRIFT-3128] - Go generated code produces name collisions between services - * [THRIFT-3146] - Graphviz generates function name collisions between services - * [THRIFT-3147] - Segfault while receiving data - * [THRIFT-3148] - Markdown links to coding_standards are dead - * [THRIFT-3090] - cmake build is broken on MacOSX - * [THRIFT-3097] - cmake targets unconditionally depend on optional libraries - * [THRIFT-3094] - master as of 2015-APR-13 fails -DBOOST_THREADS cmake build - * [THRIFT-3099] - cmake build is broken on FreeBSD - * [THRIFT-3089] - Assigning default ENUM values results in non-compilable java code if java namespace is not defined - * [THRIFT-3093] - mingw compile fixes for c++ library 0.9.2 - * [THRIFT-3098] - Thrift does not pretty print binary typedefs the way it does binary fields - * [THRIFT-3091] - c_glib service method should return result from handler method - * [THRIFT-3088] - TThreadPoolServer with Sasl auth may leak CLOSE_WAIT socket - * [THRIFT-3109] - Cross test log file cannot be browsed when served in HTTP server - * [THRIFT-3113] - m4 C++11 macro issue - * [THRIFT-3105] - C++ libthriftnb library on Windows build failure - * [THRIFT-3115] - Uncompileable code due to name collision with predefined used types - * [THRIFT-3117] - Java TSSLTransportFactory can't load certificates within JAR archive - * [THRIFT-3102] - could not make check for Go Library - * [THRIFT-3120] - Minor spelling errors and an outdated URL - * [THRIFT-3121] - Librt does not exist on OS X - * [THRIFT-3152] - Compiler error on Mac OSX (missing #include ) - * [THRIFT-3162] - make fails for dmd 2.067 - * [THRIFT-3164] - Thrift C++ library SSL socket by default allows for unsecure SSLv3 negotiation - * [THRIFT-3168] - Fix Maven POM - * [THRIFT-3170] - Initialism code in the Go compiler causes chaos - * [THRIFT-3169] - Do not export thrift.TestStruct and thrift.TestEnum in thrift Go library - * [THRIFT-3191] - Perl compiler does not add support for unexpected exception handling - * [THRIFT-3178] - glib C does not compile - * [THRIFT-3189] - Perl ServerSocket should allow a specific interface to be listened to - * [THRIFT-3252] - Missing TConcurrentClientSyncInfo.h in cpp Makefile, so doesn't install - * [THRIFT-3255] - Thrift generator doesn't exclude 'package' keyword for thrift property names breaking java builds - * [THRIFT-3260] - multiple warnings in c_glib tutorial - * [THRIFT-3256] - Some D test timings are too aggressive for slow machines - * [THRIFT-3257] - warning: extra tokens at end of #endif directive - * [THRIFT-3184] - Thrift Go leaves file descriptors open - * [THRIFT-3203] - DOAP - please fix "Ocaml" => "OCaml" - * [THRIFT-3210] - (uncompileable) code generated for server events while are events not enabled - * [THRIFT-3215] - TJSONProtocol '(c++) uses "throw new" to throw exceptions instead of "throw" - * [THRIFT-3202] - Allow HSHAServer to configure min and max worker threads separately. - * [THRIFT-3205] - TCompactProtocol return a wrong error when the io.EOF happens - * [THRIFT-3209] - LGPL mentioned in license file - * [THRIFT-3197] - keepAliveTime is hard coded as 60 sec in TThreadPoolServer - * [THRIFT-3196] - Misspelling in lua TBinaryProtocol (stirctWrite => strictWrite) - * [THRIFT-3198] - Allow construction of TTransportFactory with a specified maxLength - * [THRIFT-3192] - Go import paths changed in 1.4, and expired June 1 - * [THRIFT-3271] - Could not find or load main class configtest_ax_javac_and_java on some non-english systems - * [THRIFT-3273] - c_glib: Generated code tries to convert between function and void pointers - * [THRIFT-3264] - Fix Erlang 16 namespaced types - * [THRIFT-3270] - reusing TNonblockingServer::TConnection cause dirty TSocket - * [THRIFT-3267] - c_glib: "Critical" failure during unit tests - * [THRIFT-3277] - THttpClient leaks connections if it's used for multiple requests - * [THRIFT-3278] - NodeJS: Fix exception stack traces and names - * [THRIFT-3279] - Fix a bug in retry_max_delay (NodeJS) - * [THRIFT-3280] - Initialize retry variables on construction - * [THRIFT-3283] - c_glib: Tutorial server always exits with warning - * [THRIFT-3284] - c_glib: Empty service produces unused-variable warning - * [THRIFT-1925] - c_glib generated code does not compile - * [THRIFT-1849] - after transport->open() opens isOpen returns true and next open() goes thru when it shall not - * [THRIFT-1866] - java compiler generates non-compiling code with const's defined in a thrift when name includes non-identifier chars - * [THRIFT-1938] - FunctionRunner.h -- uses wrong path for Thread.h when installed - * [THRIFT-1844] - Password string not cleared - * [THRIFT-2004] - Thrift::Union violates :== method contract and crashes - * [THRIFT-2073] - Thrift C++ THttpClient error: cannot refill buffer - * [THRIFT-2127] - Autoconf scripting does not properly account for cross-compile - * [THRIFT-2180] - Integer types issues in Cocoa lib on ARM64 - * [THRIFT-2189] - Go needs "isset" to fully support "union" type (and optionals) - * [THRIFT-2192] - autotools on Redhat based systems - * [THRIFT-2546] - cross language tests fails at 'TestMultiException' when using nodejs server - * [THRIFT-2547] - nodejs servers and clients fails to connect with cpp using compact protocol - * [THRIFT-2548] - Nodejs servers and clients does not work properly with -ssl - * [THRIFT-1471] - toString() does not print ByteBuffer values when nested in a List - * [THRIFT-1201] - getaddrinfo resource leak - * [THRIFT-615] - TThreadPoolServer doesn't call task_done after pulling tasks from it's clients queue - * [THRIFT-162] - Thrift structures are unhashable, preventing them from being used as set elements - * [THRIFT-810] - Crashed client on TSocket::close under loads - * [THRIFT-557] - charset problem with file Autogenerated by Thrift - * [THRIFT-233] - IDL doesn't support negative hex literals - * [THRIFT-1649] - contrib/zeromq does not build in 0.8.0 - * [THRIFT-1642] - Miscalculation lead to throw unexpected "TTransportException::TIMED_OUT"(or called "EAGAIN (timed out)") exception - * [THRIFT-1587] - TSocket::setRecvTimeout error - * [THRIFT-1248] - pointer subtraction in TMemoryBuffer relies on undefined behavior - * [THRIFT-1774] - Sasl Transport client would hang when trying to connect non-sasl transport server - * [THRIFT-1754] - RangeError in buffer handling - * [THRIFT-1618] - static structMap in FieldMetaData is not thread safe and can lead to deadlocks - * [THRIFT-2335] - thrift incompatibility with py:tornado as server, java as client - * [THRIFT-2803] - TCP_DEFER_ACCEPT not supported with domain sockets - * [THRIFT-2799] - Build Problem(s): ld: library not found for -l:libboost_unit_test_framework.a - * [THRIFT-2801] - C++ test suite compilation warnings - * [THRIFT-2802] - C++ tutorial compilation warnings - * [THRIFT-2795] - thrift_binary_protocol.c: 'dereferencing type-punned pointer will break strict-aliasing rules' - * [THRIFT-2817] - TSimpleJSONProtocol reads beyond end of message - * [THRIFT-2826] - html:standalone sometimes ignored - * [THRIFT-2829] - Support haxelib installation via github - * [THRIFT-2828] - slightly wrong help screen indent - * [THRIFT-2831] - Removes dead code in web_server.js introduced in THRIFT-2819 - * [THRIFT-2823] - All JS-tests are failing when run with grunt test - * [THRIFT-2827] - Thrift 0.9.2 fails to compile on Yosemite due to tr1/functional include in ProcessorTest.cpp - * [THRIFT-2843] - Automake configure.ac has possible typo related to Java - * [THRIFT-2813] - multiple haxe library fixes/improvements - * [THRIFT-2825] - Supplying unicode to python Thrift client can cause next request arguments to get overwritten - * [THRIFT-2840] - Cabal file points to LICENSE file outside the path of the Haskell project. - * [THRIFT-2818] - Trailing commas in array - * [THRIFT-2830] - Clean up ant warnings in tutorial dir - * [THRIFT-2842] - Erlang thrift client has infinite timeout - * [THRIFT-2810] - Do not leave the underlying ServerSocket open if construction of TServerSocket fails - * [THRIFT-2812] - Go server adding redundant buffering layer - * [THRIFT-2839] - TFramedTransport read bug - * [THRIFT-2844] - Nodejs support broken when running under Browserify - * [THRIFT-2814] - args/result classes not found when no namespace is set - * [THRIFT-2847] - function IfValue() is a duplicate of System.StrUtils.IfThen - * [THRIFT-2848] - certain Delphi tests do not build if TypeRegistry is used - * [THRIFT-2854] - Go Struct writer and reader looses important error information - * [THRIFT-2858] - Enable header field case insensitive match in THttpServer - * [THRIFT-2857] - C# generator creates uncompilable code for struct constants - * [THRIFT-2860] - Delphi server closes connection on unexpected exceptions - * [THRIFT-2868] - Enhance error handling in the Go client - * [THRIFT-2879] - TMemoryBuffer: using lua string in wrong way - * [THRIFT-2851] - Remove strange public Peek() from Go transports - * [THRIFT-2852] - Better Open/IsOpen/Close behavior for StreamTransport. - * [THRIFT-2871] - Missing semicolon in thrift.js - * [THRIFT-2872] - ThreadManager deadlock for task expiration - * [THRIFT-2881] - Handle errors from Accept() correctly - * [THRIFT-2849] - Spell errors reported by codespell tool - * [THRIFT-2870] - C++ TJSONProtocol using locale dependent formatting - * [THRIFT-2882] - Lua Generator: using string.len funtion to get struct(map,list,set) size - * [THRIFT-2864] - JSON generator missing from Visual Studio build project - * [THRIFT-2878] - Go validation support of required fields - * [THRIFT-2873] - TPipe and TPipeServer don't compile on Windows with UNICODE enabled - * [THRIFT-2888] - import of is missing in JSON generator - * [THRIFT-2900] - Python THttpClient does not reset socket timeout on exception - * [THRIFT-2907] - 'ntohll' macro redefined - * [THRIFT-2884] - Map does not serialize correctly for JSON protocol in Go library - * [THRIFT-2887] - --with-openssl configure flag is ignored - * [THRIFT-2894] - PHP json serializer skips maps with int/bool keys - * [THRIFT-2904] - json_protocol_test.go fails - * [THRIFT-2906] - library not found for -l:libboost_unit_test_framework.a - * [THRIFT-2890] - binary data may lose bytes with JSON transport under specific circumstances - * [THRIFT-2891] - binary data may cause a failure with JSON transport under specific circumstances - * [THRIFT-2901] - Fix for generated TypeScript functions + indentation of JavaScript maps - * [THRIFT-2916] - make check fails for D language - * [THRIFT-2918] - Race condition in Python TProcessPoolServer test - * [THRIFT-2920] - Erlang Thrift test uses wrong IDL file - * [THRIFT-2922] - $TRIAL is used with Python tests but not tested accordingly - * [THRIFT-2912] - Autotool build for C++ Qt library is invalid - * [THRIFT-2914] - explicit dependency to Lua5.2 fails on some systems - * [THRIFT-2910] - libevent is not really optional - * [THRIFT-2911] - fix c++ version zeromq transport, the old version cannot work - * [THRIFT-2915] - Lua generator missing from Visual Studio build project - * [THRIFT-2917] - "make clean" breaks test/c_glib - * [THRIFT-2919] - Haxe test server timeout too large - * [THRIFT-2923] - JavaScript client assumes a message being written - * [THRIFT-2924] - TNonblockingServer crashes when user-provided event_base is used - * [THRIFT-2925] - CMake build does not work with OpenSSL nor anything installed in non-system location - * [THRIFT-2931] - Access to undeclared static property: Thrift\Protocol\TProtocol::$TBINARYPROTOCOLACCELERATED - * [THRIFT-2893] - CMake build fails with boost thread or std thread - * [THRIFT-2902] - Generated c_glib code does not compile with clang - * [THRIFT-2903] - Qt4 library built with CMake does not work - * [THRIFT-2942] - CSharp generate invalid code for property named read or write - * [THRIFT-2932] - Node.js Thrift connection libraries throw Exceptions into event emitter - * [THRIFT-2933] - v0.9.2: doubles encoded in node with compact protocol cannot be decoded by python - * [THRIFT-2934] - createServer signature mismatch - * [THRIFT-2981] - IDL with no namespace produces unparsable PHP - * [THRIFT-2999] - Addition of .gitattributes text auto in THRIFT-2724 causes modified files on checkout - * [THRIFT-2949] - typo in compiler/cpp/README.md - * [THRIFT-2957] - warning: source file %s is in a subdirectory, but option 'subdir-objects' is disabled - * [THRIFT-2953] - TNamedPipeServerTransport is not Stop()able - * [THRIFT-2962] - Docker Thrift env for development and testing - * [THRIFT-2971] - C++ test and tutorial parallel build is unstable - * [THRIFT-2972] - Missing backslash in lib/cpp/test/Makefile.am - * [THRIFT-2951] - Fix Erlang name conflict test - * [THRIFT-2955] - Using list of typedefs does not compile on Go - * [THRIFT-2960] - namespace regression for Ruby - * [THRIFT-2959] - nodejs: fix binary unit tests - * [THRIFT-2966] - nodejs: Fix bad references to TProtocolException and TProtocolExceptionType - * [THRIFT-2970] - grunt-jsdoc fails due to dependency issues - * [THRIFT-3001] - C# Equals fails for binary fields (byte[]) - * [THRIFT-3003] - Missing LICENSE file prevents package from being installed - * [THRIFT-3008] - Node.js server does not fully support exception - * [THRIFT-3007] - Travis build is broken because of directory conflict - * [THRIFT-3009] - TSSLSocket does not use the correct hostname (breaks certificate checks) - * [THRIFT-3011] - C# test server testException() not implemented according to specs - * [THRIFT-3012] - Timing problems in NamedPipe implementation due to unnecessary open/close - * [THRIFT-3019] - Golang generator missing docstring for structs - * [THRIFT-3021] - Service remote tool does not import stub package with package prefix - * [THRIFT-3026] - TMultiplexedProcessor does not have a constructor - * [THRIFT-3028] - Regression caused by THRIFT-2180 - * [THRIFT-3017] - order of map key/value types incorrect for one CTOR - * [THRIFT-3020] - Cannot compile thrift as C++03 - * [THRIFT-3024] - User-Agent "BattleNet" used in some Thrift library files - * [THRIFT-3047] - Uneven calls to indent_up and indent_down in Cocoa generator - * [THRIFT-3048] - NodeJS decoding of I64 is inconsistent across protocols - * [THRIFT-3043] - go compiler generator uses non C++98 code - * [THRIFT-3044] - Docker README.md paths to Dockerfiles are incorrect - * [THRIFT-3040] - bower.json wrong "main" path - * [THRIFT-3051] - Go Thrift generator creates bad go code - * [THRIFT-3057] - Java compiler build is broken - * [THRIFT-3061] - C++ TSSLSocket shutdown delay/vulnerability - * [THRIFT-3062] - C++ TServerSocket invalid port number (over 999999) causes stack corruption - * [THRIFT-3065] - Update libthrift dependencies (slf4j, httpcore, httpclient) - * [THRIFT-3244] - TypeScript: fix namespace of included types - * [THRIFT-3246] - Reduce the number of trivial warnings in Windows C++ CMake builds - * [THRIFT-3224] - Fix TNamedPipeServer unpredictable behavior on accept - * [THRIFT-3230] - Python compiler generates wrong code if there is function throwing a typedef of exception with another namespace - * [THRIFT-3236] - MaxSkipDepth never checked - * [THRIFT-3239] - Limit recursion depth - * [THRIFT-3241] - fatal error: runtime: cannot map pages in arena address space - * [THRIFT-3242] - OSGi Import-Package directive is missing the Apache HTTP packages - * [THRIFT-3234] - Limit recursion depth - * [THRIFT-3222] - TypeScript: Generated Enums are quoted - * [THRIFT-3229] - unexpected Timeout exception when desired bytes are only partially available - * [THRIFT-3231] - CPP: Limit recursion depth to 64 - * [THRIFT-3235] - Limit recursion depth - * [THRIFT-3175] - fastbinary.c python deserialize can cause huge allocations from garbage - * [THRIFT-3176] - Union incorrectly implements == - * [THRIFT-3177] - Fails to run rake test - * [THRIFT-3180] - lua plugin: framed transport do not work - * [THRIFT-3179] - lua plugin cant connect to remote server because function l_socket_create_and_connect always bind socket to localhost - * [THRIFT-3248] - TypeScript: additional comma in method signature without parameters - * [THRIFT-3302] - Go JSON protocol should encode Thrift byte type as signed integer string - * [THRIFT-3297] - c_glib: an abstract base class is not generated - * [THRIFT-3294] - TZlibTransport for Java does not write data correctly - * [THRIFT-3296] - Go cross test does not conform to spec - * [THRIFT-3295] - C# library does not build on Mono 4.0.2.5 or later - * [THRIFT-3293] - JavaScript: null values turn into empty structs in constructor - * [THRIFT-3310] - lib/erl/README.md has incorrect formatting - * [THRIFT-3319] - CSharp tutorial will not build using the *.sln - * [THRIFT-3335] - Ruby server does not handle processor exception - * [THRIFT-3338] - Stray underscore in generated go when service name starts with "New" - * [THRIFT-3324] - Update Go Docs for pulling all packages - * [THRIFT-3345] - Clients blocked indefinitely when a java.lang.Error is thrown - * [THRIFT-3332] - make dist fails on clean build - * [THRIFT-3326] - Tests do not compile under *BSD - * [THRIFT-3334] - Markdown notation of protocol spec is malformed - * [THRIFT-3331] - warning: ‘etype’ may be used uninitialized in this function - * [THRIFT-3349] - Python server does not handle processor exception - * [THRIFT-3343] - Fix haskell README - * [THRIFT-3340] - Python: enable json tests again - * [THRIFT-3311] - Top level README.md has incorrect formmating - * [THRIFT-2936] - Minor memory leak in SSL - * [THRIFT-3290] - Using from in variable names causes the generated Python code to have errors - * [THRIFT-3225] - Fix TPipeServer unpredictable behavior on interrupt() - * [THRIFT-3354] - Fix word-extraction substr bug in initialism code - * [THRIFT-2006] - TBinaryProtocol message header call name length is not validated and can be used to core the server - * [THRIFT-3329] - C++ library unit tests don't compile against the new boost-1.59 unit test framework - * [THRIFT-2630] - windows7 64bit pc. ipv4 and ipv6 pc.can't use - * [THRIFT-3336] - Thrift generated streaming operators added in 0.9.2 cannot be overridden - * [THRIFT-2681] - Core of unwind_cleanup - * [THRIFT-3317] - cpp namespace org.apache issue appears in 0.9 - -## Documentation - * [THRIFT-3286] - Apache Ant is a necessary dependency - -## Improvement - * [THRIFT-227] - Byte[] in collections aren't pretty printed like regular binary fields - * [THRIFT-2744] - Vagrantfile for Centos 6.5 - * [THRIFT-2644] - Haxe support - * [THRIFT-2756] - register Media Type @ IANA - * [THRIFT-3076] - Compatibility with Haxe 3.2.0 - * [THRIFT-3081] - C++ Consolidate client processing loops in TServers - * [THRIFT-3083] - C++ Consolidate server processing loops in TSimpleServer, TThreadedServer, TThreadPoolServer - * [THRIFT-3084] - C++ add concurrent client limit to threaded servers - * [THRIFT-3074] - Add compiler/cpp/lex.yythriftl.cc to gitignore. - * [THRIFT-3134] - Remove use of deprecated "phantom.args" - * [THRIFT-3133] - Allow "make cross" and "make precross" to run without building all languages - * [THRIFT-3142] - Make JavaScript use downloaded libraries - * [THRIFT-3141] - Improve logging of JavaScript test - * [THRIFT-3144] - Proposal: make String representation of enums in generated go code less verbose - * [THRIFT-3130] - Remove the last vestiges of THRIFT_OVERLOAD_IF from THRIFT-1316 - * [THRIFT-3131] - Consolidate suggested import path for go thrift library to git.apache.org in docs and code - * [THRIFT-3092] - Generated Haskell types should derive Generic - * [THRIFT-3110] - Print error log after cross test failures on Travis - * [THRIFT-3114] - Using local temp variables to not pollute the global table - * [THRIFT-3106] - CMake summary should give more information why a library is set to off - * [THRIFT-3119] - Java's TThreadedSelectorServer has indistinguishable log messages in run() - * [THRIFT-3122] - Javascript struct constructor should properly initialize struct and container members from plain js arguments - * [THRIFT-3151] - Fix links to git-wip* - should be git.apache.org - * [THRIFT-3167] - Windows build from source instructions need to be revised - * [THRIFT-3155] - move contrib/mingw32-toolchain.cmake to build/cmake/ - * [THRIFT-3160] - Make generated go enums implement TextMarshaller and TextUnmarshaller interfaces - * [THRIFT-3150] - Add an option to thrift go generator to make Read and Write methods private - * [THRIFT-3149] - Make ReadFieldN methods in generated Go code private - * [THRIFT-3172] - Add tutorial to Thrift web site - * [THRIFT-3214] - Add Erlang option for using maps instead of dicts - * [THRIFT-3201] - Capture github test artifacts for failed builds - * [THRIFT-3266] - c_glib: Multiple compiler warnings building unit tests - * [THRIFT-3285] - c_glib: Build library with all warnings enabled, no warnings generated - * [THRIFT-1954] - Allow for a separate connection timeout value - * [THRIFT-2098] - Add support for Qt5+ - * [THRIFT-2199] - Remove Dense protocol (was: move to Contrib) - * [THRIFT-406] - C++ Test suite cleanup - * [THRIFT-902] - socket and connect timeout in TSocket should be distinguished - * [THRIFT-388] - Use a separate wire format for async calls - * [THRIFT-727] - support native C++ language specific exception message - * [THRIFT-1784] - pep-3110 compliance for exception handling - * [THRIFT-1025] - C++ ServerSocket should inherit from Socket with the necessary Ctor to listen on connections from a specific host - * [THRIFT-2269] - Can deploy libthrift-source.jar to maven center repository - * [THRIFT-2804] - Pull an interface out of TBaseAsyncProcessor - * [THRIFT-2806] - more whitespace fixups - * [THRIFT-2811] - Make remote socket address accessible - * [THRIFT-2809] - .gitignore update for compiler's visual project - * [THRIFT-2846] - Expose ciphers parameter from ssl.wrap_socket() - * [THRIFT-2859] - JSON generator: output complete descriptors - * [THRIFT-2861] - add buffered transport - * [THRIFT-2865] - Test case for Go: SeqId out of sequence - * [THRIFT-2866] - Go generator source code is hard to read and maintain - * [THRIFT-2880] - Read the network address from the listener if available. - * [THRIFT-2875] - Typo in TDenseProtocol.h comment - * [THRIFT-2874] - TBinaryProtocol member variable "string_buf_" is never used. - * [THRIFT-2855] - Move contributing.md to the root of the repository - * [THRIFT-2862] - Enable RTTI and/or build macros for generated code - * [THRIFT-2876] - Add test for THRIFT-2526 Assignment operators and copy constructors in c++ don't copy the __isset struct - * [THRIFT-2897] - Generate -isEqual: and -hash methods - * [THRIFT-2909] - Improve travis build - * [THRIFT-2921] - Make Erlang impl ready for OTP 18 release (dict/0 and set/0 are deprecated) - * [THRIFT-2928] - Rename the erlang test_server module - * [THRIFT-2940] - Allow installing Thrift from git as NPM module by providing package.json in top level directory - * [THRIFT-2937] - Allow setting a maximum frame size in TFramedTransport - * [THRIFT-2976] - nodejs: xhr and websocket support for browserify - * [THRIFT-2996] - Test for Haxe 3.1.3 or better - * [THRIFT-2969] - nodejs: DRY up library tests - * [THRIFT-2973] - Update Haxe lib readme regarding Haxe 3.1.3 - * [THRIFT-2952] - Improve handling of Server.Stop() - * [THRIFT-2964] - nodejs: move protocols and transports into separate files - * [THRIFT-2963] - nodejs - add test coverage - * [THRIFT-3006] - Attach 'omitempty' json tag for optional fields in Go - * [THRIFT-3027] - Go compiler does not ensure common initialisms have consistent case - * [THRIFT-3030] - TThreadedServer: Property for number of clientThreads - * [THRIFT-3023] - Go compiler is a little overly conservative with names of attributes - * [THRIFT-3018] - Compact protocol for Delphi - * [THRIFT-3025] - Change pure Int constants into @enums (where possible) - * [THRIFT-3031] - migrate "shouldStop" flag to TServer - * [THRIFT-3022] - Compact protocol for Haxe - * [THRIFT-3041] - Generate asynchronous clients for Cocoa - * [THRIFT-3053] - Perl SSL Socket Support (Encryption) - * [THRIFT-3247] - Generate a C++ thread-safe client - * [THRIFT-3217] - Provide a little endian variant of the binary protocol in C++ - * [THRIFT-3223] - TypeScript: Add initial support for Enum Maps - * [THRIFT-3220] - Option to suppress @Generated Annotation entirely - * [THRIFT-3300] - Reimplement TZlibTransport in Java using streams - * [THRIFT-3288] - c_glib: Build unit tests with all warnings enabled, no warnings generated - * [THRIFT-3347] - Improve cross test servers and clients - * [THRIFT-3342] - Improve ruby cross test client and server compatibility - * [THRIFT-2296] - Add C++ Base class for service - * [THRIFT-3337] - Add testBool method to cross tests - * [THRIFT-3303] - Disable concurrent cabal jobs on Travis to avoid GHC crash - * [THRIFT-2623] - Docker container for Thrift - * [THRIFT-3298] - thrift endian converters may conflict with other libraries - * [THRIFT-1559] - Provide memory pool for TBinaryProtocol to eliminate memory fragmentation - * [THRIFT-424] - Steal ProtocolBuffers' VarInt implementation for C++ - -## New Feature - * [THRIFT-3070] - Add ability to set the LocalCertificateSelectionCallback - * [THRIFT-1909] - Java: Add compiler flag to use the "option pattern" for optional fields - * [THRIFT-2099] - Stop TThreadPoolServer with alive connections. - * [THRIFT-123] - implement TZlibTransport in Java - * [THRIFT-2368] - New option: reuse-objects for Java generator - * [THRIFT-2836] - Optionally generate C++11 MoveConstructible types - * [THRIFT-2824] - Flag to disable html escaping doctext - * [THRIFT-2819] - Add WebsSocket client to node.js - * [THRIFT-3050] - Client certificate authentication for non-http TLS in C# - * [THRIFT-3292] - Implement TZlibTransport in Go - -## Question - * [THRIFT-2583] - Thrift on xPC target (SpeedGoat) - * [THRIFT-2592] - thrift server using c_glib - * [THRIFT-2832] - c_glib: Handle string lists correctly - * [THRIFT-3136] - thrift installation problem on mac - * [THRIFT-3346] - c_glib: Tutorials example crashes saying Calculator.ping implementation returned FALSE but did not set an error - -## Sub-task - * [THRIFT-2578] - Moving 'make cross' from test.sh to test.py - * [THRIFT-2734] - Go coding standards - * [THRIFT-2748] - Add Vagrantfile for Centos 6.5 - * [THRIFT-2753] - Misc. Haxe improvements - * [THRIFT-2640] - Compact Protocol in Cocoa - * [THRIFT-3262] - warning: overflow in implicit constant conversion in DenseProtoTest.cpp - * [THRIFT-3194] - Can't build with go enabled. gomock SCC path incorrect. - * [THRIFT-3275] - c_glib tutorial warnings in generated code - * [THRIFT-1125] - Multiplexing support for the Ruby Library - * [THRIFT-2807] - PHP Code Style - * [THRIFT-2841] - Add comprehensive integration tests for the whole Go stack - * [THRIFT-2815] - Haxe: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-2886] - Integrate binary type in standard Thrift cross test - * [THRIFT-2946] - Enhance usability of cross test framework - * [THRIFT-2967] - Add .editorconfig to root - * [THRIFT-3033] - Perl: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-3174] - Initialism code in the Go compiler doesn't check first word - * [THRIFT-3193] - Option to supress date value in @Generated annotation - * [THRIFT-3305] - Missing dist files for 0.9.3 release candidate - * [THRIFT-3341] - Add testBool methods - * [THRIFT-3308] - Fix broken test cases for 0.9.3 release candidate - -## Task - * [THRIFT-2834] - Remove semi-colons from python code generator - * [THRIFT-2853] - Adjust comments not applying anymore after THRIFT-2852 - -## Test - * [THRIFT-3211] - Add make cross support for php TCompactProtocol - -## Wish - * [THRIFT-2838] - TNonblockingServer can bind to port 0 (i.e., get an OS-assigned port) but there is no way to get the port number - - - -Thrift 0.9.2 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-2793] - Go compiler produces uncompilable code - * [THRIFT-1481] - Unix domain sockets in C++ do not support the abstract namespace - * [THRIFT-1455] - TBinaryProtocolT::writeString casts from size_t to uint32_t, which is not safe on 64-bit platforms - * [THRIFT-1579] - PHP Extention - function thrift_protocol_read_binary not working from TBinarySerializer::deserialize - * [THRIFT-1584] - Error: could not SetMinThreads in ThreadPool on single-core machines - * [THRIFT-1614] - Thrift build from svn repo sources fails with automake-1.12 - * [THRIFT-1047] - rb_thrift_memory_buffer_write treats arg as string without check, segfaults if you pass non-string - * [THRIFT-1639] - Java/Python: Serialization/Deserialization of double type using CompactProtocol - * [THRIFT-1647] - NodeJS BufferedTransport does not work beyond the hello-world example - * [THRIFT-2130] - Thrift's D library/test: parts of "make check" code do not compile with recent dmd-2.062 through dmd-2.064alpha - * [THRIFT-2140] - Error compiling cpp tutorials - * [THRIFT-2139] - MSVC 2012 Error - Cannot compile due to BoostThreadFactory - * [THRIFT-2138] - pkgconfig file created with wrong include path - * [THRIFT-2160] - Warning in thrift.h when compiling with -Wunused and NDEBUG - * [THRIFT-2158] - Compact, JSON, and SimpleJSON protocols are not working correctly - * [THRIFT-2167] - nodejs lib throws error if options argument isn't passed - * [THRIFT-2288] - Go impl of Thrift JSON protocol wrongly writes/expects true/false for bools - * [THRIFT-2147] - Thrift IDL grammar allows for dotted identifier names - * [THRIFT-2145] - Rack and Thin are not just development dependencies - * [THRIFT-2267] - Should be able to choose socket family in Python TSocket - * [THRIFT-2276] - java path in spec file needs updating - * [THRIFT-2281] - Generated send/recv code ignores errors returned by the underlying protocol - * [THRIFT-2280] - TJSONProtocol.Flush() does not really flush the transport - * [THRIFT-2274] - TNonblockingServer and TThreadedSelectorServer do not close their channel selectors on exit and leak file descriptors - * [THRIFT-2265] - php library doesn't build - * [THRIFT-2232] - IsSet* broken in Go - * [THRIFT-2246] - Unset enum value is printed by ToString() - * [THRIFT-2240] - thrift.vim (contrib) does not correctly handle 'union' - * [THRIFT-2243] - TNonblockingServer in thrift crashes when TFramedTransport opens - * [THRIFT-2230] - Cannot Build on RHEL/Centos/Amazon Linux 6.x - * [THRIFT-2247] - Go generator doesn't deal well with map keys of type binary - * [THRIFT-2253] - Python Tornado TTornadoServer base class change - * [THRIFT-2261] - java: error: unmappable character for encoding ASCII - * [THRIFT-2259] - C#: unexpected null logDelegate() pointer causes AV in TServer.serve() - * [THRIFT-2225] - SSLContext destroy before cleanupOpenSSL - * [THRIFT-2224] - TSSLSocket.h and TSSLServerSocket.h should use the platfromsocket too - * [THRIFT-2229] - thrift failed to build on OSX 10.9 GM - * [THRIFT-2227] - Thrift compiler generates spurious warnings with Xlint - * [THRIFT-2219] - Thrift gem fails to build on OS X Mavericks with 1.9.3 rubies - * [THRIFT-2226] - TServerSocket - keepAlive wrong initialization order - * [THRIFT-2285] - TJsonProtocol implementation for Java doesn't allow a slash (/) to be escaped (\/) - * [THRIFT-2216] - Extraneous semicolon in TProtocolUtil.h makes clang mad - * [THRIFT-2215] - Generated HTML/Graphviz lists referenced enum identifiers as UNKNOWN. - * [THRIFT-2211] - Exception constructor does not contain namespace prefix. - * [THRIFT-2210] - lib/java TSimpleJSONProtocol can emit invalid JSON - * [THRIFT-2209] - Ruby generator -- please namespace classes - * [THRIFT-2202] - Delphi TServerImpl.DefaultLogDelegate may stop the server with I/O-Error 105 - * [THRIFT-2201] - Ternary operator returns different types (build error for some compilers) - * [THRIFT-2200] - nested structs cause generate_fingerprint() to slow down at excessive CPU load - * [THRIFT-2197] - fix jar output directory in rpm spec file - * [THRIFT-2196] - Fix invalid dependency in Makefile.am - * [THRIFT-2194] - Node: Not actually prepending residual data in TFramedTransport.receiver - * [THRIFT-2193] - Java code generator emits spurious semicolon when deep copying binary data - * [THRIFT-2191] - Fix charp JSONProtocol.ReadJSONDouble (specify InvariantCulture) - * [THRIFT-2214] - System header sys/param.h is included inside the Thrift namespace - * [THRIFT-2178] - Thrift generator returns error exit code on --version - * [THRIFT-2171] - NodeJS implementation has extremely low test coverage - * [THRIFT-2183] - gem install fails on zsh - * [THRIFT-2182] - segfault in regression tests (GC bug in rb_thrift_memory_buffer_write) - * [THRIFT-2181] - oneway calls don't work in NodeJS - * [THRIFT-2169] - JavaME Thrift Library causes "java.io.IOException: No Response Entries Available" after using the Thrift client for some time - * [THRIFT-2168] - Node.js appears broken (at least, examples don't work as intended) - * [THRIFT-2293] - TSSLTransportFactory.createSSLContext() leaves files open - * [THRIFT-2279] - TSerializer only returns the first 1024 bytes serialized - * [THRIFT-2278] - Buffered transport doesn't support writes > buffer size - * [THRIFT-2275] - Fix memory leak in golang compact_protocol. - * [THRIFT-2282] - Incorect code generated for some typedefs - * [THRIFT-2009] - Go redeclaration error - * [THRIFT-1964] - 'Isset' causes problems with C#/.NET serializers - * [THRIFT-2026] - Fix TCompactProtocol 64 bit builds - * [THRIFT-2108] - Fix TAsyncClientManager timeout race - * [THRIFT-2068] - Multiple calls from same connection are not processed in node - * [THRIFT-1750] - Make compiler build cleanly under visual studio 10 - * [THRIFT-1755] - Comment parsing bug - * [THRIFT-1771] - "make check" fails on x64 for libboost_unit_test_framework.a - * [THRIFT-1841] - NodeJS Thrift incorrectly parses non-UTF8-string types - * [THRIFT-1908] - Using php thrift_protocol accelerated transfer causes core dump - * [THRIFT-1892] - Socket timeouts are declared in milli-seconds, but are actually set in micro-seconds - * [THRIFT-2303] - TBufferredTransport not properly closing underlying transport - * [THRIFT-2313] - nodejs server crash after processing the first request when using MultiplexedProcessor/FramedBuffer/BinaryProtocol - * [THRIFT-2311] - Go: invalid code generated when exception name is a go keyword - * [THRIFT-2308] - node: TJSONProtocol parse error when reading from buffered message - * [THRIFT-2316] - ccp: TFileTransportTest - * [THRIFT-2352] - msvc failed to compile thrift tests - * [THRIFT-2337] - Golang does not report TIMED_OUT exceptions - * [THRIFT-2340] - Generated server implementation does not send response type EXCEPTION on the Thrift.TApplicationExceptionType.UNKNOWN_METHOD exception - * [THRIFT-2354] - Connection errors can lead to case_clause exceptions - * [THRIFT-2339] - Uncaught exception in thrift c# driver - * [THRIFT-2356] - c++ thrift client not working with ssl (SSL_connect hangs) - * [THRIFT-2331] - Missing call to ReadStructBegin() in TApplicationException.Read() - * [THRIFT-2323] - Uncompileable Delphi code generated for typedef'd structs - * [THRIFT-2322] - Correctly show the number of times ExecutorService (java) has rejected the client. - * [THRIFT-2389] - namespaces handled wrongly in acrionscript 3.0 implementation - * [THRIFT-2388] - GoLang - Fix data races in simple_server and server_socket - * [THRIFT-2386] - Thrift refuses to link yylex - * [THRIFT-2375] - Excessive
's in generated HTML - * [THRIFT-2373] - warning CS0414 in THttpClient.cs: private field 'Thrift.Transport.THttpClient.connection' assigned but never used - * [THRIFT-2372] - thrift/json_protocol.go:160: function ends without a return statement - * [THRIFT-2371] - ruby bundler version fails on ~1.3.1, remove and take latest avail - * [THRIFT-2370] - Compiler SEGFAULTs generating HTML documentation for complex strucre - * [THRIFT-2384] - Binary map keys produce uncompilable code in go - * [THRIFT-2380] - unreachable code (CID 1174546, CID 1174679) - * [THRIFT-2378] - service method arguments of binary type lead to uncompileable Go code - * [THRIFT-2363] - Issue with character encoding of Success returned from Login using Thrift Proxy and NodeJS - * [THRIFT-2359] - TBufferedTransport doesn't clear it's buffer on a failed flush call - * [THRIFT-2428] - Python 3 setup.py support - * [THRIFT-2367] - Build failure: stdlib and boost both define uint64_t - * [THRIFT-2365] - C# decodes too many binary bytes from JSON - * [THRIFT-2402] - byte count of FrameBuffer in AWAITING_CLOSE state is not subtracted from readBufferBytesAllocated - * [THRIFT-2396] - Build Error on MacOSX - * [THRIFT-2395] - thrift Ruby gem requires development dependency 'thin' regardless of environment - * [THRIFT-2414] - c_glib fix several bug. - * [THRIFT-2420] - Go argument parser for methods without arguments does not skip fields - * [THRIFT-2439] - Bug in TProtocolDecorator Class causes parsing errors - * [THRIFT-2419] - golang - Fix fmt.Errorf in generated code - * [THRIFT-2418] - Go handler function panics on internal error - * [THRIFT-2405] - Node.js Multiplexer tests fail (silently) - * [THRIFT-2581] - TFDTransport destructor should not throw - * [THRIFT-2575] - Thrift includes siginfo_t within apache::thrift::protocol namespace - * [THRIFT-2577] - TFileTransport missuse of closesocket on windows platform - * [THRIFT-2576] - Implement Thrift.Protocol.prototype.skip method in JavaScript library - * [THRIFT-2588] - Thrift compiler is not buildable in Visual Studio 2010 - * [THRIFT-2594] - JS Compiler: Single quotes are not being escaped in constants. - * [THRIFT-2591] - TFramedTransport does not handle payloads split across packets correctly - * [THRIFT-2599] - Uncompileable Delphi code due to naming conflicts with IDL - * [THRIFT-2590] - C++ Visual Studio solution doesn't include Multiplexing support - * [THRIFT-2595] - Node.js: Fix global leaks and copy-paste errors - * [THRIFT-2565] - autoconf fails to find mingw-g++ cross compiler on travis CI - * [THRIFT-2555] - excessive "unused field" comments - * [THRIFT-2554] - double initialization in generated Read() method - * [THRIFT-2551] - OutOfMemoryError "unable to create new native thread" kills serve thread - * [THRIFT-2543] - Generated enum type in haskell should be qualified - * [THRIFT-2560] - Thrift compiler generator tries to concat ints with strings using + - * [THRIFT-2559] - Centos 6.5 unable to "make" with Thrift 0.9.1 - * [THRIFT-2526] - Assignment operators and copy constructors in c++ don't copy the __isset struct - * [THRIFT-2454] - c_glib: There is no gethostbyname_r() in some OS. - * [THRIFT-2451] - Do not use pointers for optional fields with defaults. Do not write such fields if its value set to default. Also, do not use pointers for any optional fields mapped to go map or slice. generate Get accessors - * [THRIFT-2450] - include HowToContribute in the src repo - * [THRIFT-2448] - thrift/test/test.sh has incorrect Node.js test path - * [THRIFT-2460] - unopened socket fd must be less than zero. - * [THRIFT-2459] - --version should not exit 1 - * [THRIFT-2468] - Timestamp handling - * [THRIFT-2467] - Unable to build contrib/fb303 on OSX 10.9.2 - * [THRIFT-2466] - Improper error handling for SSL/TLS connections that don't complete a handshake - * [THRIFT-2463] - test/py/RunClientServer.py fails sometimes - * [THRIFT-2458] - Generated golang server code for "oneway" methods is incorrect - * [THRIFT-2456] - THttpClient fails when using async support outside Silverlight - * [THRIFT-2524] - Visual Studio project is missing TThreadedServer files - * [THRIFT-2523] - Visual Studio project is missing OverlappedSubmissionThread files - * [THRIFT-2520] - cpp:cob_style generates incorrect .tcc file - * [THRIFT-2508] - Uncompileable C# code due to language keywords in IDL - * [THRIFT-2506] - Update TProtocolException error codes to be used consistently throughout the library - * [THRIFT-2505] - go: struct should always be a pointer to avoid copying of potentially size-unbounded structs - * [THRIFT-2515] - TLS Method error during make - * [THRIFT-2503] - C++: Fix name collision when a struct has a member named "val" - * [THRIFT-2477] - thrift --help text with misplaced comma - * [THRIFT-2492] - test/cpp does not compile on mac - * [THRIFT-2500] - sending random data crashes thrift(golang) service - * [THRIFT-2475] - c_glib: buffered_transport_write function return always TRUE. - * [THRIFT-2495] - JavaScript/Node string constants lack proper escaping - * [THRIFT-2491] - unable to import generated ThriftTest service - * [THRIFT-2490] - c_glib: if fail to read a exception from server, client may be occurred double free - * [THRIFT-2470] - THttpHandler swallows exceptions from processor - * [THRIFT-2533] - Boost version in requirements should be updated - * [THRIFT-2532] - Java version in installation requirements should be updated - * [THRIFT-2529] - TBufferedTransport split Tcp data bug in nodeJs - * [THRIFT-2537] - Path for "go get" does not work (pull request 115) - * [THRIFT-2443] - Node fails cross lang tests - * [THRIFT-2437] - Author fields in Python setup.py must be strings not lists. - * [THRIFT-2435] - Java compiler doesn't like struct member names that are identical to an existing enum or struct type - * [THRIFT-2434] - Missing namespace import for php TMultiplexedProcessor implementation - * [THRIFT-2432] - Flaky parallel build - * [THRIFT-2430] - Crash during TThreadPoolServer shutdown - * [THRIFT-667] - Period should not be allowed in identifier names - * [THRIFT-1212] - Members capital case conflict - * [THRIFT-2584] - Error handler not listened on javascript client - * [THRIFT-2294] - Incorrect Makefile generation - * [THRIFT-2601] - Fix vagrant to work again for builds again - * [THRIFT-2092] - TNonblocking server should release handler as soon as connection closes - * [THRIFT-2557] - CS0542 member names cannot be the same as their enclosing type - * [THRIFT-2605] - TSocket warning on gcc 4.8.3 - * [THRIFT-2607] - ThreadManager.cpp warning on clang++ 3.4 - * [THRIFT-1998] - TCompactProtocol.tcc - one more warning on Visual 2010 - * [THRIFT-2610] - MSVC warning in TSocket.cpp - * [THRIFT-2614] - TNonblockingServer.cpp warnings on MSVC - * [THRIFT-2608] - TNonblockingServer.cpp warnings on clang 3.4 - * [THRIFT-2606] - ThreadManager.h warning in clang++ 3.4 - * [THRIFT-2609] - TFileTransport.h unused field warning (clang 3.4) - * [THRIFT-2416] - Cannot use TCompactProtocol with MSVC - * [THRIFT-1803] - Ruby Thrift 0.9.0 tries to encode UUID to UTF8 and crashes - * [THRIFT-2385] - Problem with gethostbyname2 during make check - * [THRIFT-2262] - thrift server 'MutateRow' operation gives no indication of success / failure - * [THRIFT-2048] - Prefer boolean context to nullptr_t conversion - * [THRIFT-2528] - Thrift Erlang Library: Multiple thrift applications in one bundle - * [THRIFT-1999] - warning on gcc 4.7 while compiling BoostMutex.cpp - * [THRIFT-2104] - Structs lose binary data when transferred from server to client in Java - * [THRIFT-2184] - undefined method rspec_verify for Thrift::MemoryBufferTransport - * [THRIFT-2351] - PHP TCompactProtocol has fails to decode messages - * [THRIFT-2016] - Resource Leak in thrift struct under compiler/cpp/src/parse/t_function.h - * [THRIFT-2273] - Please delete old releases from mirroring system - * [THRIFT-2270] - Faulty library version numbering at build or documentation - * [THRIFT-2203] - Tests keeping failing on Jenkins and Travis CI - * [THRIFT-2399] - thrift.el: recognize "//"-style comments in emacs thrift-mode - * [THRIFT-2582] - "FileTransport error" exception is raised when trying to use Java's TFileTransport - * [THRIFT-1682] - Multiple thread calling a Service function unsafely causes message corruption and terminates with Broken Pipe - * [THRIFT-2357] - recurse option has no effect when generating php - * [THRIFT-2248] - Go generator doesn't deal well with map keys of type binary - * [THRIFT-2426] - clarify IP rights and contributions from fbthrift - * [THRIFT-2041] - TNonblocking server compilation on windows (ARITHMETIC_RIGHT_SHIFT) - * [THRIFT-2400] - thrift.el: recognize "//"-style comments in emacs thrift-mode - * [THRIFT-1717] - Fix deb build in jenkins - * [THRIFT-2266] - ThreadManager.h:24:10: fatal error: 'tr1/functional' file not found on Mac 10.9 (Mavericks) - * [THRIFT-1300] - Test failures with parallel builds (make -j) - * [THRIFT-2487] - Tutorial requires two IDL files but only one is linked from the Thrift web site - * [THRIFT-2329] - missing release tags within git - * [THRIFT-2306] - concurent client calls with nodejs - * [THRIFT-2222] - ruby gem cannot be compiled on OS X mavericks - * [THRIFT-2381] - code which generated by thrift2/hbase.thrift compile error - * [THRIFT-2390] - no close event when connection lost - * [THRIFT-2146] - Unable to pass multiple "--gen" options to the thrift compiler - * [THRIFT-2438] - Unexpected readFieldEnd call causes JSON Parsing errors - * [THRIFT-2498] - Error message "Invalid method name" while trying to call HBase Thrift API - * [THRIFT-841] - Build cruft - * [THRIFT-2570] - Wrong URL given in http://thrift.apache.org/developers - * [THRIFT-2604] - Fix debian packaging - * [THRIFT-2618] - Unignore /aclocal files required for build - * [THRIFT-2562] - ./configure create MakeFile in lib/d with errors - * [THRIFT-2593] - Unable to build thrift on ubuntu-12.04 (Precise) - * [THRIFT-2461] - Can't install thrift-0.8.0 on OS X 10.9.2 - * [THRIFT-2602] - Fix missing dist files - * [THRIFT-2620] - Fix python packaging - * [THRIFT-2545] - Test CPP fails to build (possibly typo) - -## Documentation - * [THRIFT-2155] - Adding one liner guide to rename the version.h.in and rename thrifty.cc.h - * [THRIFT-1991] - Add exceptions to examples - * [THRIFT-2334] - add a tutorial for node JS - * [THRIFT-2392] - Actionscript tutorial - * [THRIFT-2383] - contrib: sample for connecting Thrift with Rebus - * [THRIFT-2382] - contrib: sample for connecting Thrift with STOMP - -## Improvement - * [THRIFT-1457] - Capacity of TframedTransport write buffer is never reset - * [THRIFT-1135] - Node.js tutorial - * [THRIFT-1371] - Socket timeouts (SO_RCVTIMEO and SO_SNDTIMEO) not supported on Solaris - * [THRIFT-2142] - Minor tweaks to thrift.el for better emacs package compatibility - * [THRIFT-2268] - Modify TSaslTransport to ignore TCP health checks from loadbalancers - * [THRIFT-2264] - GitHub page incorrectly states that Thrift is still incubating - * [THRIFT-2263] - Always generate good hashCode for Java - * [THRIFT-2233] - Java compiler should defensively copy its binary inputs - * [THRIFT-2239] - Address FindBugs errors - * [THRIFT-2249] - Add SMP Build option to thrift.spec (and three config defines) - * [THRIFT-2254] - Exceptions generated by Go compiler should implement error interface - * [THRIFT-2260] - Thrift imposes unneeded dependency on commons-lang3 - * [THRIFT-2258] - Add TLS v1.1/1.2 support to TSSLSocket.cpp - * [THRIFT-2205] - Node.js Test Server to support test.js JavaScript Browser test and sundry fixes - * [THRIFT-2204] - SSL client for the cocoa client - * [THRIFT-2172] - Java compiler allocates optionals array for every struct with an optional field - * [THRIFT-2185] - use cabal instead of runhaskell in haskell library - * [THRIFT-1926] - PHP Constant Generation Refactoring - * [THRIFT-2029] - Port C++ tests to Windows - * [THRIFT-2054] - TSimpleFileTransport - Java Lib has no straight forward TTransport based file transport - * [THRIFT-2040] - "uninitialized variable" warnings on MSVC/windows - * [THRIFT-2034] - Give developers' C++ code direct access to socket FDs on server side - * [THRIFT-2095] - Use print function for Python 3 compatiblity - * [THRIFT-1868] - Make the TPC backlog configurable in the Java servers - * [THRIFT-1813] - Add @Generated annotation to generated classes - * [THRIFT-1815] - Code generators line buffer output - * [THRIFT-2305] - TFramedTransport empty constructor should probably be private - * [THRIFT-2304] - Move client assignments from construtor in method - * [THRIFT-2309] - Ruby (gem) & PHP RPM subpackages - * [THRIFT-2318] - perl: dependency Class::Accessor not checked - * [THRIFT-2317] - exclude tutorial from build - * [THRIFT-2320] - Program level doctext does not get attached by parser - * [THRIFT-2349] - Golang - improve tutorial - * [THRIFT-2348] - PHP Generator: add array typehint to functions - * [THRIFT-2344] - configure.ac: compiler-only option - * [THRIFT-2343] - Golang - Return a single error for all exceptions instead of multiple return values - * [THRIFT-2341] - Enable generation of Delphi XMLDoc comments (a.k.a. "Help Insight") - * [THRIFT-2355] - Add SSL and Web Socket Support to Node and JavaScript - * [THRIFT-2350] - Add async calls to normal JavaScript - * [THRIFT-2330] - Generate PHPDoc comments - * [THRIFT-2332] - RPMBUILD: run bootstrap (if needed) - * [THRIFT-2391] - simple socket transport for actionscript 3.0 - * [THRIFT-2376] - nodejs: allow Promise style calls for client and server - * [THRIFT-2369] - Add ssl support for nodejs implementation - * [THRIFT-2401] - Haskell tutorial compiles - * [THRIFT-2417] - C# Union classes are not partial - * [THRIFT-2415] - Named pipes server performance & message mode - * [THRIFT-2404] - emit warning on (typically inefficient) list - * [THRIFT-2398] - Improve Node Server Library - * [THRIFT-2397] - Add CORS and CSP support for JavaScript and Node.js libraries - * [THRIFT-2407] - use markdown (rename README => README.md) - * [THRIFT-2300] - D configure info output should follow same format as other languages - * [THRIFT-2579] - Windows CE support - * [THRIFT-2574] - Compiler option to generate namespace directories for Ruby - * [THRIFT-2571] - Simplify cross compilation using CMake - * [THRIFT-2569] - Introduce file to specify third party library locations on Windows - * [THRIFT-2568] - Implement own certificate handler - * [THRIFT-2552] - eliminate warning from configure.ac - * [THRIFT-2549] - Generate json tag for struct members. use go.tag annotation to override the default generated tag. - * [THRIFT-2544] - Add support for socket transport for c# library when using Windows Phone projects - * [THRIFT-2453] - haskell tutorial: fix up division by 0 example - * [THRIFT-2449] - Enhance typedef structure to distinguish between forwards and real typedefs - * [THRIFT-2446] - There is no way to handle server stream errors - * [THRIFT-2455] - Allow client certificates to be used with THttpClient - * [THRIFT-2511] - Node.js needs the compact protocol - * [THRIFT-2493] - Node.js lib needs HTTP client - * [THRIFT-2502] - Optimize go implementations of binary and compact protocols for speed - * [THRIFT-2494] - Add enum toString helper function in c_glib - * [THRIFT-2471] - Make cpp.ref annotation language agnostic - * [THRIFT-2497] - server and client for test/go, also several fixes and improvements - * [THRIFT-2535] - TJSONProtocol when serialized yields TField ids rather than names - * [THRIFT-2220] - Add a new struct structv? - * [THRIFT-1352] - Thrift server - * [THRIFT-989] - Push boost m4 macros upstream - * [THRIFT-1349] - Remove unnecessary print outs - * [THRIFT-2496] - server and client for test/go, also several fixes and improvements - * [THRIFT-1114] - Maven publish shouldn't require passwords hardcoded in settings.xml - * [THRIFT-2043] - visual 2010 warnings - unreachable code - * [THRIFT-1683] - Implement alternatives to Javascript Client side Transport protocol, just as NPAPI and WebSocket. - * [THRIFT-1746] - provide a SPDX file - * [THRIFT-1772] - Serialization does not check types of embedded structures. - * [THRIFT-2387] - nodejs: external imports should be centralized in index.js - * [THRIFT-2037] - More general macro THRIFT_UNUSED_VARIABLE - -## New Feature - * [THRIFT-1012] - Transport for DataInput DataOutput interface - * [THRIFT-2256] - Using c++11/c++0x std library replace boost library - * [THRIFT-2250] - JSON and MemoryBuffer for JavaME - * [THRIFT-2114] - Python Service Remote SSL Option - * [THRIFT-1719] - SASL client support for Python - * [THRIFT-1894] - Thrift multi-threaded async Java Server using Java 7 AsynchronousChannelGroup - * [THRIFT-1893] - HTTP/JSON server/client for node js - * [THRIFT-2347] - C# TLS Transport based on THRIFT-181 - * [THRIFT-2377] - Allow addition of custom HTTP Headers to an HTTP Transport - * [THRIFT-2408] - Named Pipe Transport Option for C# - * [THRIFT-2572] - Add string/collection length limit checks (from C++) to java protocol readers - * [THRIFT-2469] - "java:fullcamel" option to automatically camel-case underscored attribute names - * [THRIFT-795] - Importing service functions (simulation multiple inheritance) - * [THRIFT-2164] - Add a Get/Post Http Server to Node along with examples - * [THRIFT-2255] - add Parent Class for generated Struct class - -## Question - * [THRIFT-2539] - Tsocket.cpp addrinfo ai_flags = AI_ADDRCONFIG - * [THRIFT-2440] - how to connect as3 to java by thrift , - * [THRIFT-2379] - Memmory leaking while using multithreading in C++ server. - * [THRIFT-2277] - Thrift: installing fb303 error - * [THRIFT-2567] - Csharp slow ? - * [THRIFT-2573] - thrift 0.9.2 release - -## Sub-task - * [THRIFT-981] - cocoa: add version Info to the library - * [THRIFT-2132] - Go: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-2299] - TJsonProtocol implementation for Ruby does not allow for both possible slash (solidus) encodings - * [THRIFT-2298] - TJsonProtocol implementation for C# does not allow for both possible slash (solidus) encodings - * [THRIFT-2297] - TJsonProtocol implementation for Delphi does not allow for both possible slash (solidus) encodings - * [THRIFT-2271] - JavaScript: Support for Multiplexing Services - * [THRIFT-2251] - go test for compact protocol is not running - * [THRIFT-2195] - Delphi: Add event handlers for server and processing events - * [THRIFT-2176] - TSimpleJSONProtocol.ReadFieldBegin() does not return field type and ID - * [THRIFT-2175] - Wrong field type set for binary - * [THRIFT-2174] - Deserializing JSON fails in specific cases - * [THRIFT-2053] - NodeJS: Support for Multiplexing Services - * [THRIFT-1914] - Python: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-1810] - add ruby to test/test.sh - * [THRIFT-2310] - PHP: Client-side support for Multiplexing Services - * [THRIFT-2346] - C#: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2345] - Delphi: UTF-8 sent by PHP as JSON is not understood by TJsonProtocol - * [THRIFT-2338] - First doctext wrongly interpreted as program doctext in some cases - * [THRIFT-2325] - SSL test certificates - * [THRIFT-2358] - C++: add compact protocol to cross language test suite - * [THRIFT-2425] - PHP: Server-side support for Multiplexing Services - * [THRIFT-2421] - Tree/Recursive struct support in thrift - * [THRIFT-2290] - Update Go tutorial to align with THRIFT-2232 - * [THRIFT-2558] - CSharp compiler generator tries to concat ints with strings using + - * [THRIFT-2507] - Additional LUA TProtocolException error code needed? - * [THRIFT-2499] - Compiler: allow annotations without "= value" - * [THRIFT-2534] - Cross language test results should recorded to a status.md or status.html file automatically - * [THRIFT-66] - Java: Allow multiplexing multiple services over a single TCP connection - * [THRIFT-1681] - Add Lua Support - * [THRIFT-1727] - Ruby-1.9: data loss: "binary" fields are re-encoded - * [THRIFT-1726] - Ruby-1.9: "binary" fields are represented by string whose encoding is "UTF-8" - * [THRIFT-988] - perl: add version Info to the library via configure - * [THRIFT-334] - Compact Protocol for PHP - * [THRIFT-2444] - pull request 88: thrift: clean up enum value assignment - -## Task - * [THRIFT-2223] - Spam links on wiki - * [THRIFT-2566] - Please create a DOAP file for your TLP - * [THRIFT-2237] - Update archive to contain all versions - * [THRIFT-962] - Tutorial page on our website is really unhelpful - -## Test - * [THRIFT-2327] - nodejs: nodejs test suite should be bundled with the library - * [THRIFT-2445] - THRIFT-2384 (code generation for go maps with binary keys) should be tested - * [THRIFT-2501] - C# The test parameters from the TestServer and TestClient are different from the http://thrift.apache.org/test/ - -## Wish - * [THRIFT-2190] - Add the JavaScript thrift.js lib to the Bower registry - * [THRIFT-2076] - boost::optional instead of __isset - - - -Thrift 0.9.1 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1440] - debian packaging: minor-ish policy problems - * [THRIFT-1402] - Generated Y_types.js does not require() X_types.js when an include in the IDL file was used - * [THRIFT-1551] - 2 thrift file define only struct (no service), one include another, the gen nodejs file didn't have "requires" at the top - * [THRIFT-1264] - TSocketClient is queried by run loop after deallocation in Cocoa - * [THRIFT-1600] - Thrift Go Compiler and Library out of date with Go 1 Release. - * [THRIFT-1603] - Thrift IDL allows for multiple exceptions, args or struct member names to be the same - * [THRIFT-1062] - Problems with python tutorials - * [THRIFT-864] - default value fails if identifier is a struct - * [THRIFT-930] - Ruby and Haskell bindings don't properly support DESTDIR (makes packaging painful) - * [THRIFT-820] - The readLength attribute of TBinaryProtocol is used as an instance variable and is decremented on each call of checkReadLength - * [THRIFT-1640] - None of the tutorials linked on the website contain content - * [THRIFT-1637] - NPM registry does not include version 0.8 - * [THRIFT-1648] - NodeJS clients always receive 0 for 'double' values. - * [THRIFT-1660] - Python Thrift library can be installed with pip but not easy_install - * [THRIFT-1657] - Chrome browser sending OPTIONS method before POST in xmlHttpRequest - * [THRIFT-2118] - Certificate error handling still incorrect - * [THRIFT-2137] - Ruby test lib fails jenkins build #864 - * [THRIFT-2136] - Vagrant build not compiling java, ruby, php, go libs due to missing dependencies - * [THRIFT-2135] - GO lib leaves behind test files that are auto generated - * [THRIFT-2134] - mingw-cross-compile script failing with strip errors - * [THRIFT-2133] - java TestTBinaryProtocol.java test failing - * [THRIFT-2126] - lib/cpp/src/thrift/concurrency/STD* files missing from DIST - * [THRIFT-2125] - debian missing from DIST - * [THRIFT-2124] - .o, .so, .la, .deps, .libs, gen-* files left tutorials, test and lib/cpp when making DIST - * [THRIFT-2123] - GO lib missing files in DIST build - * [THRIFT-2121] - Compilation bug for Node.js - * [THRIFT-2129] - php ext missing from dist - * [THRIFT-2128] - lib GO tests fail with funct ends without a return statement - * [THRIFT-2286] - Failed to compile Thrift0.9.1 with boost1.55 by VS2010 if select Debug-mt&x64 mode. - * [THRIFT-1973] - TCompactProtocol in C# lib does not serialize and deserialize negative int32 and int64 number correctly - * [THRIFT-1992] - casts in TCompactProtocol.tcc causing "dereferencing type-punned pointer will break strict-aliasing rules" warnings from gcc - * [THRIFT-1930] - C# generates unsigned byte for Thrift "byte" type - * [THRIFT-1929] - Update website to use Mirrors for downloads - * [THRIFT-1928] - Race may still exist in TFileTransport::flush() - * [THRIFT-1934] - Tabs in Example section on main page are not working - * [THRIFT-1933] - Delphi generator crashes when a typedef references another typedef from an included file - * [THRIFT-1942] - Binary accelerated cpp extension does not use Thrift namespaces for Exceptions - * [THRIFT-1959] - C#: Add Union TMemoryBuffer support - * [THRIFT-1958] - C#: Use static Object.Equals instead of .Equals() calls in equals - * [THRIFT-1957] - NodeJS TFramedTransport and TBufferedTransport read bytes as unsigned - * [THRIFT-1955] - Union Type writer generated in C# does not WriteStructBegin - * [THRIFT-1952] - Travis CI - * [THRIFT-1949] - WP7 build broken - * [THRIFT-1943] - docstrings for enum values are ignored - * [THRIFT-2070] - Improper `HexChar' and 'HexVal' implementation in TJSONProtocol.cs - * [THRIFT-2017] - Resource Leak in thrift struct under compiler/cpp/src/parse/t_program.h - * [THRIFT-2032] - C# client leaks sockets/handles - * [THRIFT-1996] - JavaME Constants generation is broken / inconsistent with regular Java generation - * [THRIFT-2002] - Haskell: Test use Data.Maybe instead of Maybe - * [THRIFT-2051] - Vagrant fails to build erlang - * [THRIFT-2050] - Vagrant C# lib compile fails with TException missing - * [THRIFT-1978] - Ruby: Thrift should allow for the SSL verify mode to be set - * [THRIFT-1984] - namespace collision in python bindings - * [THRIFT-1988] - When trying to build a debian package it fails as the file NEWS doesn't exist - * [THRIFT-1975] - TBinaryProtocol CheckLength can't be used for a client - * [THRIFT-1995] - '.' allowed at end of identifier generates non-compilable code - * [THRIFT-2112] - Error in Go generator when using typedefs in map keys - * [THRIFT-2088] - Typos in Thrift compiler help text - * [THRIFT-2080] - C# multiplex processor does not catch IOException - * [THRIFT-2082] - Executing "gmake clean" is broken - * [THRIFT-2102] - constants are not referencing to correct type when included from another thrift file - * [THRIFT-2100] - typedefs are not correctly referenced when including from other thrift files - * [THRIFT-2066] - 'make install' does not install two headers required for C++ bindings - * [THRIFT-2065] - Not valid constants filename in Java - * [THRIFT-2047] - Thrift.Protocol.TCompactProtocol, intToZigZag data lost (TCompactProtocol.cs) - * [THRIFT-2036] - Thrift gem warns about class variable access from top level - * [THRIFT-2057] - Vagrant fails on php tests - * [THRIFT-2105] - Generated code for default values of collections ignores t_field::T_REQUIRED - * [THRIFT-2091] - Unnecessary 'friend' declaration causes warning in TWinsockSingleton - * [THRIFT-2090] - Go generator, fix including of other thrift files - * [THRIFT-2106] - Fix support for namespaces in GO generator - * [THRIFT-1783] - C# doesn't handle required fields correctly - * [THRIFT-1782] - async only defined in silverlight - * [THRIFT-1779] - Missing process_XXXX method in generated TProcessor implementation for all 'oneway' service functions - * [THRIFT-1692] - SO_REUSEADDR allows for socket hijacking on Windows - * [THRIFT-1720] - JRuby times out on successful connection - * [THRIFT-1713] - Named and Anonymous Pipe transport (Delphi) - * [THRIFT-1699] - Native Union#read has extra read_field_end call - * [THRIFT-1749] - Python TSSLSocket error handling obscures actual error - * [THRIFT-1748] - Guard and RWGuard macros defined in global namespace - * [THRIFT-1734] - Front webpage is still advertising v0.8 as current release - * [THRIFT-1729] - C glib refactor left empty folders in svn - * [THRIFT-1767] - unions can't have required fields (Delphi) - * [THRIFT-1765] - Incorrect error message printed for null or negative keys - * [THRIFT-1778] - Configure requires manual intervention due to tar failure - * [THRIFT-1777] - TPipeServer is UNSTOPPABLE - * [THRIFT-1753] - Multiple C++ Windows, OSX, and iOS portability issues - * [THRIFT-1756] - 'make -j 8' fails with "unterminated #ifdef" error - * [THRIFT-1773] - Python library should run on python 2.4 - * [THRIFT-1769] - unions can't have required fields (C++) - * [THRIFT-1768] - unions can't have required fields (Compiler) - * [THRIFT-1666] - htonll usage in TBinaryProtocol.tcc generates warning with MSVC2010 - * [THRIFT-1919] - libthrift depends on httpcore-4.1.3 (directly) and httpcore-4.1.4 (transitively) - * [THRIFT-1864] - implement event handler for non-blocking server - * [THRIFT-1859] - Generated error c++ code with -out and include_prefix param - * [THRIFT-1869] - TThreadPoolServer (java) dies when threadpool is consumed - * [THRIFT-1842] - Memory leak with Pipes - * [THRIFT-1838] - Can't build compiler on OS X because of missing thrifty.h - * [THRIFT-1846] - Restore socket.h header to support builds with Android NDK - * [THRIFT-1850] - make check hangs on TSocket tests in TransportTest.cpp - * [THRIFT-1873] - Binary protocol factory ignores struct read/write flags - * [THRIFT-1872] - issues with TBufferedTransport buffer - * [THRIFT-1904] - Incorrect code is generated for typedefs which use included types - * [THRIFT-1903] - PHP namespaces cause binary protocols to not be used - * [THRIFT-1895] - Delphi: reserved variable name "result" not detected properly - * [THRIFT-1881] - TNonblockingServer does not release open connections or threads on shutdown - * [THRIFT-1888] - Java Thrift client can't connect to Python Thrift server on same host - * [THRIFT-1831] - Bug in list deserializer - * [THRIFT-1824] - many compile warning, becase Thread.h includes config.h - * [THRIFT-1823] - Missing parenthesis breaks "IS_..." macro in generated code - * [THRIFT-1806] - Python generation always truncates __init__.py files - * [THRIFT-1795] - Race condition in TThreadedServerPool java implementation - * [THRIFT-1794] - C# asyncctp broken - * [THRIFT-1804] - Binary+compact protocol single byte error in Ruby library (ARM architecture): caused by different char signedness - * [THRIFT-1800] - Documentation text not always escaped correctly when rendered to HTML - * [THRIFT-1788] - C#: Constants static constructor does not compile - * [THRIFT-1816] - Need "require" included thrift files in "xxx_types.js" - * [THRIFT-1907] - Compiling namespace and sub-namespace directives for unrecognized generators should only be a warning - * [THRIFT-1913] - skipping unknown fields in java unions - * [THRIFT-2553] - C++ linker error - transport/TSocket - * [THRIFT-274] - Towards a working release/versioning process - -## Documentation - * [THRIFT-1971] - [Graphviz] Adds tutorial/general description documentation - * [THRIFT-2001] - http://thrift.apache.org/ Example "C++ Server" tab is broken - -## Improvement - * [THRIFT-1574] - Apache project branding requirements: DOAP file [PATCH] - * [THRIFT-1347] - Unify the exceptions returned in generated Go code - * [THRIFT-1353] - Switch to performance branch, get rid of BinaryParser - * [THRIFT-1629] - Ruby 1.9 Compatibility during Thrift configure, make, install - * [THRIFT-991] - Refactor Haskell code and generator - * [THRIFT-990] - Sanify gettimeofday usage codebase-wide - * [THRIFT-791] - Let C++ TSimpleServer be driven by an external main loop - * [THRIFT-2117] - Cocoa TBinaryProtocol strictWrite should be set to true by default - * [THRIFT-2014] - Change C++ lib includes to use style throughout - * [THRIFT-1972] - Add support for async processors - * [THRIFT-1970] - [Graphviz] Adds option to render exceptions relationships - * [THRIFT-1966] - Support different files for SSL certificates and keys - * [THRIFT-1965] - Adds Graphviz (graph description language) generator - * [THRIFT-1956] - Switch to Apache Commons Lang 3 - * [THRIFT-1962] - Multiplex processor should send any TApplicationException back to client - * [THRIFT-1960] - main() declares 22 unused gen bools - * [THRIFT-1951] - libthrift.jar has source files in it - * [THRIFT-1997] - Add accept backlog configuration method to TServerSocket - * [THRIFT-2003] - Deprecate senum - * [THRIFT-2052] - Vagrant machine image defaults to only 384MB of RAM - * [THRIFT-1980] - Modernize Go tooling, fix go client libary. - * [THRIFT-1977] - C# compiler should generate constant files prefixed with thrift file name - * [THRIFT-1985] - add a Vagrantfile to build and test Apache Thrift fully reproducable - * [THRIFT-1994] - Deprecate slist - * [THRIFT-1993] - Factory to create instances from known (generated) interface types with Delphi - * [THRIFT-2081] - Specified timeout should be used in TSocket.Open() - * [THRIFT-2084] - Delphi: Ability to create entity Thrift-generated instances based on TypeInfo - * [THRIFT-2083] - Improve the go lib: buffered Transport, save memory allocation, handle concurrent request - * [THRIFT-2109] - Secure connections should be supported in Go - * [THRIFT-2107] - minor Go generator fixes - * [THRIFT-1695] - allow warning-free compilation in VS 2012 and GNU 4.6 - * [THRIFT-1735] - integrate tutorial into regular build - * [THRIFT-1716] - max allowed connections should be PIPE_UNLIMITED_INSTANCES - * [THRIFT-1715] - Allow excluding python parts when building contrib/fb303 - * [THRIFT-1733] - Fix RPM build issues on RHEL6/OL6 systems - * [THRIFT-1728] - Upgradation of httpcomponents - * [THRIFT-1876] - Use enum names instead of casted integers in assignments - * [THRIFT-1874] - timeout for the server-side end of a named pipe - * [THRIFT-1897] - Support validation of required fields - * [THRIFT-1896] - Add TBase protocol for Cocoa - * [THRIFT-1880] - Make named pipes server work asynchronously (overlapped) to allow for clean server stops - * [THRIFT-1878] - Add the possibility to send custom headers - * [THRIFT-1882] - Use single include - * [THRIFT-1793] - C#: Use static read instead of instance read - * [THRIFT-1799] - Option to generate HTML in "standalone mode" - * [THRIFT-1815] - Code generators line buffer output - * [THRIFT-1890] - C++: Make named pipes server work asynchronously - * [THRIFT-474] - Generating Ruby on Rails friendly code - -## New Feature - * [THRIFT-801] - Provide an interactive shell (irb) when generating ruby bindings - * [THRIFT-2292] - Android Library Project - * [THRIFT-2012] - Modernizing Go - * [THRIFT-1969] - C#: Tests not properly linked from the solution - * [THRIFT-1785] - C#: Add TMemoryBuffer serializer/deserializer - * [THRIFT-1780] - Add option to generate nullable values - * [THRIFT-1786] - C# Union Typing - * [THRIFT-591] - Make the C++ runtime library be compatible with Windows and Visual Studio - * [THRIFT-514] - Add option to configure compiler output directory - -## Question - * [THRIFT-1764] - how to get the context of client when on a rpc call in server side? - * [THRIFT-1791] - thrift's namespace directive when generating haskell code - -## Sub-task - * [THRIFT-1594] - Java test clients should have a return codes that reflect whether it succeeds or not. - * [THRIFT-1595] - Java test server should follow the documented behavior as of THRIFT-1590 - * [THRIFT-986] - st: add version Info to the library - * [THRIFT-985] - php: add version Info to the library - * [THRIFT-984] - ocaml: add version Info to the library - * [THRIFT-1924] - Delphi: Inconsistency in serialization of optional fields - * [THRIFT-1922] - C#: Inconsistency in serialization of optional fields - * [THRIFT-1961] - C# tests should be in lib/csharp/test/... - * [THRIFT-1822] - PHP unit test does not work - * [THRIFT-1902] - C++: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-1901] - C#: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-1899] - Delphi: Support for Multiplexing Services on any Transport, Protocol and Server - * [THRIFT-563] - Support for Multiplexing Services on any Transport, Protocol and Server - - - -Thrift 0.9 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1438] - lib/cpp/src/windows/config.h should read version from configure.ac rather than a #define - * [THRIFT-1446] - Compile error with Delphi 2009 in constant initializer - * [THRIFT-1450] - Problems building thrift 0.8.0 for Python and Ruby - * [THRIFT-1449] - Ruby client does not work on solaris (?) - * [THRIFT-1447] - NullpointerException in ProcessFunction.class :in "oneway" method - * [THRIFT-1433] - TServerSocket fix for MSVC - * [THRIFT-1429] - The nonblocking servers is supposed to use TransportFactory to read the data - * [THRIFT-1427] - PHP library uses non-multibyte safe functions with mbstring function overloading - * [THRIFT-1421] - Debian Packages can not be built - * [THRIFT-1394] - Treatment of optional fields is not consistent between C++ and Java - * [THRIFT-1511] - Server with oneway support ( JAVA ) - * [THRIFT-1496] - PHP compiler not namespacing enums - * [THRIFT-1495] - PHP TestClient fatals on missing class - * [THRIFT-1508] - TServerSocket does not allow for the user to specify the IP address to bind to - * [THRIFT-1504] - Cocoa Generator should use local file imports for base Thrift headers - * [THRIFT-1512] - Thrift socket support for Windows XP - * [THRIFT-1502] - TSimpleServer::serve(): Do not print out error message if server was stopped. - * [THRIFT-1501] - PHP old namespaces not generated for enums - * [THRIFT-1483] - java compiler does not generate type parameters for services in extended clauses - * [THRIFT-1479] - Compiled PHP process functions missing writeMessageEnd() - * [THRIFT-1492] - enabling c_glib render thrift unusable (even for C++ code) - * [THRIFT-1491] - Uninitialize processorFactory_ member in TServer.h - * [THRIFT-1475] - Incomplete records generation for Erlang - * [THRIFT-1486] - Javascript manual testserver not returning content types - * [THRIFT-1488] - src/concurrency/Thread.h:91:58: error: invalid conversion from 'pthread_t {aka _opaque_pthread_t*}' to 'apache::thrift::concurrency::Thread::id_t {aka long long unsigned int}' [-fpermissive] - * [THRIFT-1490] - Windows-specific header files - fixes & tweaks - * [THRIFT-1526] - Union TupleSchemeFactory returns StandardSchemes - * [THRIFT-1527] - Generated implementation of tupleReadStruct in unions return null when the setfield is unrecognized - * [THRIFT-1524] - TNonBlockingServer does not compile in Visual Studio 2010 - * [THRIFT-1529] - TupleProtocol can unintentionally include an extra byte in bit vectors when number of optional fields is an integral of 8 - * [THRIFT-1473] - JSON context stack may be left in an incorrect state when an exception is thrown during read or write operations - * [THRIFT-1456] - System.Net.HttpWebRequest' does not contain a definition for 'Proxy' - * [THRIFT-1468] - Memory leak in TSaslServerTransport - * [THRIFT-1461] - Recent TNonblockingServer changes broke --enable-boostthreads=yes, Windows - * [THRIFT-1460] - why not add unicode strings support to python directly? - * [THRIFT-1464] - AbstractNonblockingServer.FrameBuffer TNonblockingTransport accessor changed from public to private - * [THRIFT-1467] - Possible AV with empty strings when using JSON protocol - * [THRIFT-1523] - clientTimeout not worked as expected in TServerSocket created by TSSLTransportFactory - * [THRIFT-1537] - TFramedTransport issues - * [THRIFT-1519] - Thirft Build Failure referencing rb_intern2 symbol - * [THRIFT-1518] - Generated C++ code only sends the first optional field in the write() function for a struct. - * [THRIFT-1515] - NameError: global name 'TApplicationException' is not defined - * [THRIFT-1554] - Inherited service methods are not resolved in derived service implementations - * [THRIFT-1553] - thrift nodejs service side can't read map structure, key as enum, value as Object - * [THRIFT-1575] - Typo in server/TThreadPoolServer.h - * [THRIFT-1327] - Fix Spec Suite under Ruby-1.8.7 (works for MRI Ruby-1.9.2) - * [THRIFT-1326] - on some platforms, #include is necessary to be included in Thrift.h - * [THRIFT-1159] - THttpClient->Flush() issue (connection thru proxy) - * [THRIFT-1277] - Node.js serializes false booleans as null - * [THRIFT-1224] - Cannot insert UTF-8 text - * [THRIFT-1267] - Node.js can't throw exceptions. - * [THRIFT-1338] - Do not use an unpatched autoconf 2.65 to generate release tarball - * [THRIFT-1128] - MAC OS X: thrift.h incompatibility with Thrift.h - * [THRIFT-1631] - Fix C++ server constructor typos - * [THRIFT-1602] - PHP C Extension is not Compatible with PHP 5.4 - * [THRIFT-1610] - IWebProxy not available on WP7 platform - * [THRIFT-1606] - Race condition in BoostThreadFactory.cpp - * [THRIFT-1604] - Python exception handeling for changes from PEP 3110 - * [THRIFT-1607] - Incorrect file modes for several source files - * [THRIFT-1583] - c_glib leaks memory - * [THRIFT-1582] - Bad includes of nested thrift files in c_glib - * [THRIFT-1578] - C_GLib generated code does not compile - * [THRIFT-1597] - TJSONProtocol.php is missing from Makefile.am - * [THRIFT-1591] - Enable TCP_NODELAY for ruby gem - * [THRIFT-1624] - Isset Generated differently on different platforms - * [THRIFT-1622] - Incorrect size returned on read - * [THRIFT-1621] - Memory leaks - * [THRIFT-1612] - Base64 encoding is broken - * [THRIFT-1627] - compiler built using compilers.vcxproj cannot be used to build some test .thrift files - * [THRIFT-1571] - Update Ruby HTTP transport for recent Ruby versions - * [THRIFT-1023] - Thrift encoding (UTF-8) issue with Ruby 1.9.2 - * [THRIFT-1090] - Document the generation of a file called "Constants.java" - * [THRIFT-1082] - Thrift::FramedTransport sometimes calls close() on an undefined value - * [THRIFT-956] - Python module's version meta-data should be updated - * [THRIFT-973] - Cocoa library won't compile using clang - * [THRIFT-1632] - ruby: data corruption in thrift_native implementation of MemoryBufferTransport - * [THRIFT-1665] - TBinaryProtocol: exceeded message length raises generic TException - * [THRIFT-1664] - Reference to non-existing variable in build script - * [THRIFT-1663] - Java Thrift server is not throwing exceptions - * [THRIFT-1662] - "removeObject:" should be "removeObserver:" in [-TSocketServer dealloc]? - * [THRIFT-1643] - Denial of Service attack in TBinaryProtocol.readString - * [THRIFT-1674] - Update Thrift D library to be compatible with 2.060 - * [THRIFT-1673] - Ruby compile flags for extension for multi arch builds (os x) - * [THRIFT-1655] - Configure still trying to use thrift_generators in output - * [THRIFT-1654] - c_glib thrift_socket_read() returns corrupted data - * [THRIFT-1653] - TThreadedSelectorServer leaks CLOSE_WAIT sockets - * [THRIFT-1658] - Java thrift server is not throwing TApplicationException - * [THRIFT-1656] - Setting proper headers in THttpServer.cpp so that "Cross-Origin Resource Sharing" on js client can work. - * [THRIFT-1652] - TSaslTransport does not log the error when kerberos auth fails - * [THRIFT-2272] - CLONE - Denial of Service attack in TBinaryProtocol.readString - * [THRIFT-2086] - Invalid generated code for Node.JS when using namespaces - * [THRIFT-1686] - t_php_generator.cc uses "and" instead of "&&", and causes compiler errors with Visual Studio - * [THRIFT-1693] - libthrift has dependency on two different versions of httpcore - * [THRIFT-1689] - don't exit(-1) in TNonblockingServer - * [THRIFT-1679] - NodeJS: protocol readString() should treat string as utf8, not binary - * [THRIFT-1721] - Dist broken due to 0.8.0 to 0.9.0 changes - * [THRIFT-1710] - Minor issues in test case code - * [THRIFT-1709] - Warning "Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first" in TBinaryProtocol.cs at ReadInt64() - * [THRIFT-1707] - [ruby] Adjust server_spec.rb for RSpec 2.11.x and Ruby 1.9.3 - * [THRIFT-1671] - Cocoa code generator does not put keywords into generated method calls - * [THRIFT-1670] - Incompatibilities between different versions of a Thrift interface - * [THRIFT-1669] - NameError: global name 'TApplicationException' is not defined - * [THRIFT-1668] - Compile error in contrib/fb303, thrift/TDispatchProcessor.h: No such file or directory - * [THRIFT-1845] - Fix compiler warning caused by implicit string conversion with Xcode 4.6 - * [THRIFT-304] - Building the Python library requires development headers - * [THRIFT-369] - sets and maps break equality - * [THRIFT-556] - Ruby compiler does not correctly referred to top-level modules when a submodule masks the top-level name - * [THRIFT-481] - indentation of ruby classes is off by a few - -## Improvement - * [THRIFT-1498] - Allow TThreadedPoolServer.Args to pass a ExecutorService - * [THRIFT-1444] - FunctionRunner - add syntactic sugar to create shared_ptrs - * [THRIFT-1443] - define a TProcessor helper class to implement process() - * [THRIFT-1441] - Generate constructor with parameters for exception class to let it update message property automatically. - * [THRIFT-1520] - Embed version number in erlang .app file - * [THRIFT-1480] - python: remove tabs, adjust whitespace and address PEP8 warnings - * [THRIFT-1485] - Performance: pass large and/or refcounted arguments as "const" - * [THRIFT-1484] - Introduce phpunit test suite - * [THRIFT-1532] - The type specifications in the generated Erlang code should include "undefined" where it's used as a default value - * [THRIFT-1534] - Required fields in the Delphi code generator. - * [THRIFT-1469] - Java isset space optimization - * [THRIFT-1465] - Visibility of methods in generated java code - * [THRIFT-1453] - Don't change types of arguments when serializing with thrift php extension - * [THRIFT-1452] - generate a swap() method for all generated structs - * [THRIFT-1451] - FramedTransport: Prevent infinite loop when writing - * [THRIFT-1521] - Two patches for more Performance - * [THRIFT-1555] - Delphi version of the tutorial code - * [THRIFT-1535] - Why thrift don't use wrapped class for optional fields ? - * [THRIFT-1204] - Ruby autogenerated files should require 'thrift' gem - * [THRIFT-1344] - Using the httpc module directly rather than the deprecated http layer - * [THRIFT-1343] - no_auto_import min/2 to avoid compile warning - * [THRIFT-1340] - Add support of ARC to Objective-C - * [THRIFT-1611] - Improved code generation for typedefs - * [THRIFT-1593] - Pass on errors like "connection closed" to the handler module - * [THRIFT-1615] - PHP Namespace - * [THRIFT-1567] - Thrift/cpp: Allow alternate classes to be used for - * [THRIFT-1072] - Missing - (id) initWithSharedProcessor in TSharedProcessorFactory.h - * [THRIFT-1650] - [ruby] Update clean items and svn:ignore entries for OS X artifacts - * [THRIFT-1661] - [PATCH] Add --with-qt4 configure option - * [THRIFT-1675] - Do we have any plan to support scala? - * [THRIFT-1645] - Replace Object#tee with more conventional Object#tap in specs - * [THRIFT-1644] - Upgrade RSpec to 2.10.x and refactor specs as needed - * [THRIFT-1672] - MonoTouch (and Mono for Android) compatibility - * [THRIFT-1702] - a thrift manual - * [THRIFT-1694] - Re-Enable serialization for WP7 Silverlight - * [THRIFT-1691] - Serializer/deserializer support for Delphi - * [THRIFT-1688] - Update IDL page markup - * [THRIFT-1725] - Tutorial web pages for Delphi and C# - * [THRIFT-1714] - [ruby] Explicitly add CWD to Ruby test_suites.rb - * [THRIFT-317] - Issues with Java struct validation - * [THRIFT-164] - Build web tutorial on Incubator web site - * [THRIFT-541] - Cocoa code generator doesn't put keywords before all arguments. - * [THRIFT-681] - The HTML generator does not handle JavaDoc style comments very well - -## New Feature - * [THRIFT-1500] - D programming language support - * [THRIFT-1510] - There should be an implementation of the JsonProtocol for ruby - * [THRIFT-1115] - python TBase class for dynamic (de)serialization, and __slots__ option for memory savings - * [THRIFT-1953] - support for asp.net mvc 3 - -## Question - * [THRIFT-1235] - How could I use THttpServerTransportFactory withTNonBlockingServer - * [THRIFT-1368] - TNonblockingServer usage - * [THRIFT-1061] - Read an invalid frame size of 0. Are you using TFramedTransport on the client side? - * [THRIFT-491] - Ripping raw pthreads out of TFileTransport and associated test issues - -## Sub-task - * [THRIFT-1596] - Delphi: Test clients should have a return codes that reflect whether they succeeded or not - * [THRIFT-982] - javame: add version Info to the library - * [THRIFT-1722] - C# WP7 Assembly addition beaks mono build - * [THRIFT-336] - Compact Protocol in C# - -## Test - * [THRIFT-1613] - Add code back into empty source file ToStringTest.java - * [THRIFT-1718] - Incorrect check in TFileTransportTest - -## Wish - * [THRIFT-1463] - Decouple Thrift IDL from generators - * [THRIFT-1466] - Proper Documentation for Thrift C Glib - * [THRIFT-1539] - Build and distribute the fb303 python libraries along with thrift - * [THRIFT-1685] - Please add "aereo.com" to "Powered by Apache Thrift" list in about page - * [THRIFT-330] - TProcessor - additional method to called when connection is broken - - - -Thrift 0.8 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1436] - pip install thrift fails on Windows with "Unable to find vcvarsall.bat" - * [THRIFT-1432] - Javascript struct constants declared in the same file as their struct definition will cause an error - * [THRIFT-1428] - shared.thrft does not include namespace for php, so thrift compiler generate incorrect name - * [THRIFT-1426] - Dist package missing files for release 0.8 - * [THRIFT-1425] - The Node package is incompatible with latest node (0.6) & npm (1.0.27) - * [THRIFT-1416] - Python Unit test is broken on ci - * [THRIFT-1419] - AbstractNonBlockingServer does not catch errors when invoking the processor - * [THRIFT-1424] - Ruby specs fail when run with rake - * [THRIFT-1420] - Nonblocking and HsHa server should make sure to close all their socket connections when the selector exits - * [THRIFT-1413] - Generated code does not read MapEnd / ListEnd / SetEnd - * [THRIFT-1409] - Name conflict check does not work properly for exception object(Delphi). - * [THRIFT-1408] - Delphi Test Server: Exception test case fails due to naming conflict with e.message - * [THRIFT-1407] - Typo in Python socket server causes Thrift to fail when we enable a global socket timout - * [THRIFT-1397] - CI server fails during build due to unused parameters in delphi generator - * [THRIFT-1404] - Delphi compiler generates struct reader code with problem. - * [THRIFT-1400] - Ruby native extension aborts with __stack_chk_fail in OSX - * [THRIFT-1399] - One of the TServerImpl.Create CTORs lacks implementation - * [THRIFT-1390] - Debian packages build fix for Squeeze (build from the official 0.7.0 tarball) - * [THRIFT-1393] - TTransportException's thrown from THttpClient contain superfluous slashes in the Exception message - * [THRIFT-1392] - Enabling both namespaces and autoloading in generated PHP code won't work. - * [THRIFT-1406] - Build error after applying THRIFT-1395 - * [THRIFT-1405] - Delphi compiler does not generates container serializer properly. - * [THRIFT-1411] - java generator does not provide type parameter for TBaseProcessor - * [THRIFT-1473] - JSON context stack may be left in an incorrect state when an exception is thrown during read or write operations - * [THRIFT-1331] - Ruby library deserializes an empty map to nil - * [THRIFT-1330] - PHP Namespaces no longer generated - * [THRIFT-1328] - TBaseHelper.toString(...) appends ByteBuffer data outside of valid buffer range - * [THRIFT-1322] - OCaml lib fail to compile: Thrift.ml line 305, int vs int32 mismatch - * [THRIFT-1143] - Build doesn't detect correct architecture type on 64bit osx - * [THRIFT-1205] - port server unduly fragile with arbitrary input - * [THRIFT-1279] - type set is handled incorrectly when writing object - * [THRIFT-1298] - Standard scheme doesn't read or write metadata along with field values - * [THRIFT-1265] - C++ container deserialize - * [THRIFT-1263] - publish ruby client to rubygems - * [THRIFT-1384] - Java help menu missing newline near javame flag - * [THRIFT-1382] - Bundle install doesnot work because thrift crashes - * [THRIFT-1381] - Thrift C++ libs have incorrectly versioned names - * [THRIFT-1350] - Go library code does not build as of r60 (most recent release) - * [THRIFT-1365] - TupleProtocol#writeBitSet unintentionally writes a variable length byte array - * [THRIFT-1359] - --gen-cob cpp:cob_style does not compile anymore - * [THRIFT-1319] - Mismatch between how a union reads and writes a container - * [THRIFT-1309] - libfb303-0.7.0.jar missing in maven repository - * [THRIFT-1238] - Thrift JS client cannot read map of structures - * [THRIFT-1254] - Code can't be compiled against a regular JRE: Object.clone() override has a different return type - * [THRIFT-1367] - Mac OSX build fails with "no such file to load -- spec/rake/spectask" - * [THRIFT-1355] - Running make in lib/rb doesn't build the native extensions - * [THRIFT-1370] - Debian packaging should Build-Depend on libglib2.0-dev - * [THRIFT-1342] - Compilation problem on Windows of fastbinary.c - * [THRIFT-1341] - TProtocol.h endian detection wrong with boost - * [THRIFT-1583] - c_glib leaks memory - * [THRIFT-1582] - Bad includes of nested thrift files in c_glib - * [THRIFT-1578] - C_GLib generated code does not compile - * [THRIFT-1027] - 'make -j 16' fails with "unterminated #ifdef" error - * [THRIFT-1121] - Java server performance regression in 0.6 - * [THRIFT-857] - tests run by "make install" fail if generators are disabled - * [THRIFT-380] - Use setuptools for python build - -## Dependency upgrade - * [THRIFT-1257] - thrift's dependency scope on javax.servlet:servlet-api should be 'provided' - -## Improvement - * [THRIFT-1445] - minor C++ generator variable cleanup - * [THRIFT-1435] - make TException.Message property conformant to the usual expectations - * [THRIFT-1431] - Rename 'sys' module to 'util' - * [THRIFT-1396] - Dephi generator has dependacy on boost 1.42 later. - * [THRIFT-1395] - Patch to prevent warnings for integer types in some cases - * [THRIFT-1275] - thrift: always prefix namespaces with " ::" - * [THRIFT-1274] - thrift: fail compilation if an unexpected token is - * [THRIFT-1271] - thrift: fix missing namespace in generated local - * [THRIFT-1270] - thrift: add --allow-neg-keys argument to allow - * [THRIFT-1345] - Allow building without tests - * [THRIFT-1286] - Modernize the Thrift Ruby Library Dev Environment - * [THRIFT-1284] - thrift: fix processor inheritance - * [THRIFT-1283] - thrift: wrap t_cpp_generator::generate_process_function() to 80 - * [THRIFT-1282] - Upgrade httpclient to 4.1.2 (from 4.0.1) - * [THRIFT-1281] - add @generated to the docblock - * [THRIFT-1280] - Thrift: Improve Monitor exception-free interfaces - * [THRIFT-1278] - javadoc warnings - compilation - * [THRIFT-1227] - Erlang implementation of thrift JSON protocol - * [THRIFT-1295] - Duplicate include in TSocket.cpp - * [THRIFT-1294] - thrift: fix log message typos in TSimpleServer - * [THRIFT-1293] - thrift: improve handling of exceptions thrown by - * [THRIFT-1292] - thrift: silence log spew from TThreadedServer - * [THRIFT-1288] - Allow typedefed exceptions in throws clauses - * [THRIFT-1290] - thrift: TNonblockingServer: clean up state in the - * [THRIFT-1287] - thrift: start refactoring some of the C++ processor - * [THRIFT-1289] - thrift: implement TNonblockingServer::stop() - * [THRIFT-1305] - thrift: make TConnection a private inner class of - * [THRIFT-1304] - TNonblockingServer: pass in the connection context to - * [THRIFT-1302] - thrift: raise an exception if send() times out in - * [THRIFT-1301] - thrift: consolidate common code in TNonblockingServer - * [THRIFT-1377] - abort PHP deserialization on unknown field type - * [THRIFT-1379] - fix uninitialized enum values in thrift C++ objects - * [THRIFT-1376] - Make port specification option in thrift remote - * [THRIFT-1375] - fixed a hex char conversion bug in TJSONProtocol - * [THRIFT-1373] - Fix user-defined exception generation in thrift (python) - * [THRIFT-1361] - Optional replacement of pthread by boost::thread - * [THRIFT-1320] - Consistency of configure generated config.h - * [THRIFT-1317] - Remove copy constructibility from - * [THRIFT-1316] - thrift: update server classes to accept - * [THRIFT-1315] - thrift: generate server interface factory classes - * [THRIFT-1314] - thrift: add TProcessorFactory - * [THRIFT-1335] - Add accept timeout to TServerSocket - * [THRIFT-1334] - Add more info to IllegalStateException - * [THRIFT-1333] - Make RWGuard not copyable - * [THRIFT-1332] - TSSLTransportParameters class uses hard coded value keyManagerType: SunX509 - * [THRIFT-1251] - Generated java code should indicate which fields are required and which are optional - * [THRIFT-1387] - Build MSVC libraries with Boost Threads instead of Pthreads - * [THRIFT-1339] - Extend Tuple Protocol to TUnions - * [THRIFT-1031] - Patch to compile Thrift for vc++ 9.0 and 10.0 - * [THRIFT-1130] - Add the ability to specify symbolic default value for optional boolean - * [THRIFT-1123] - Patch to compile Thrift server and client for vc++ 9.0 and 10.0 - * [THRIFT-386] - Make it possible to build the Python library without the extension - -## New Feature - * [THRIFT-1401] - JSON-protocol for Delphi XE Libraries - * [THRIFT-1167] - Java nonblocking server with more than one thread for select and handling IO - * [THRIFT-1366] - Delphi generator, lirbrary and unit test. - * [THRIFT-1354] - Add rake task to build just the gem file - * [THRIFT-769] - Pluggable Serializers - -## Sub-task - * [THRIFT-1415] - delphi: add version Info to the library - * [THRIFT-1391] - Improved Delphi XE test cases - - - -Thrift 0.7 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1140] - Framed Transport Client using C (Glib) Library hangs when connecting to Ruby Server - * [THRIFT-1154] - HttpClient does not specify the connection close parameter - * [THRIFT-1153] - HttpClient does not specify the connection close parameter - * [THRIFT-1149] - Nonblocking server fails when client connection is reset - * [THRIFT-1146] - Android Incompatibility : in Android < 2.3 java.io.IOException doesn't support for Throwable parameter in constructor - * [THRIFT-1133] - Java and JavaScript tutorial is broken since we have Java maven deployment - * [THRIFT-1132] - Deserialization error in TApplicationException C# - * [THRIFT-1131] - C# JSON Protocol is unable to decode escaped characters in string - * [THRIFT-1208] - python TCompactProtocol.py writeBool and readBool not follow the compact-proto-spec-2.txt spec for CONTAINER_WRITE, CONTAINER_READ - * [THRIFT-1200] - JS compiler generates code that clobbers existing namespaces - * [THRIFT-1183] - Pure-ruby CompactProtocol raises ArgumentError when deserializing under Ruby 1.9 - * [THRIFT-1182] - Native deserializer segfaults on incorrect list element type - * [THRIFT-1181] - AS3 compiler generates incorrect code for setting default values in constructor - * [THRIFT-1234] - thrift --help is missing doc on py:utf8strings - * [THRIFT-1180] - AS3 compiler generates uncompilable code for binary types. - * [THRIFT-1194] - Java lib does not install artifacts to local dir correctly - * [THRIFT-1193] - Potential infinite loop in nonblocking_server - * [THRIFT-1192] - Typo: TProtocol.h tests for HAVE_SYS_PARAM_H_ - * [THRIFT-1190] - readBufferBytesAllocated in TNonblockingServer.java should be AtomicLong to fix FD leakage and general server malfunction - * [THRIFT-1187] - nonblocking_server shutdown race under Ruby 1.9 - * [THRIFT-1178] - Java: TBase signature should be T extends TBase - * [THRIFT-1164] - Segmentation fault on NULL pointer in t_js_generator::generate_const - * [THRIFT-1171] - Perl write/readDouble assumes little-endian platform - * [THRIFT-1222] - Unhandled exception for TEvhttpServer request - * [THRIFT-1220] - TProcessor::process never returns false - * [THRIFT-1285] - Stable 0.7.0 Windows compiler exe available on the webside is not the good one - * [THRIFT-1218] - c_glib uses wrong name in pkg-config - * [THRIFT-1215] - Undefined property Thirft in lib/js/thrift.js - * [THRIFT-1211] - When using THttpClient, non 200 responses leave the connection open - * [THRIFT-1228] - The php accelerator module calls flush incorrectly - * [THRIFT-1308] - libfb303-0.7.0.jar missing in maven repository - * [THRIFT-1255] - Mismatch of method name between JavaME's lib and generated code (compareTo/compareObjects) - * [THRIFT-1253] - Code generated for maps is not compiling - * [THRIFT-1252] - Segfault in Ruby deserializer - * [THRIFT-1094] - bug in TCompactProto python readMessageEnd method and updated test cases - * [THRIFT-1093] - several bugs in python TCompactProtocol - * [THRIFT-1092] - generated validate() method has wrong indentation - * [THRIFT-1011] - Error generating package imports when using classes from other packages - * [THRIFT-1050] - Declaring an argument named "manager" to a service method produces code that fails compile due to name conflicts with protected ivars in TAsyncClient - * [THRIFT-1074] - .keystore and .truststore are missing from the 0.6.0 distribution - * [THRIFT-1067] - Tons of bugs in php implementation - * [THRIFT-1065] - Unexpected exceptions not proper handled on JS - * [THRIFT-1076] - Erlang Thrift socket server has a bug that causes java thrift client of framed binary client to throw "out of sequence" exception - * [THRIFT-1057] - casts in TBinaryProtocol.tcc causing "dereferencing type-punned pointer will break strict-aliasing rules" warnings from gcc - * [THRIFT-1055] - csharp TServerSocket and TSocket do not disable Nagle via Socket.NoDelay = true like cpp and java do - * [THRIFT-1054] - explicit call to PKG_PROG_PKG_CONFIG is missing and first use of PKG_CHECK_MODULES may not happen, causes mono detection to fail - * [THRIFT-1117] - JavaScript Unit Test does not work anymore because libthrift*.jar where moved by Maven Deployment - * [THRIFT-1111] - The HTML generator does not distinguish between string and binary types - * [THRIFT-1032] - "make dist" fails due to c_glib problem - * [THRIFT-1036] - Auto-generated C++ code fails to compile with "-Werror -Wextra -Wall" g++ compiler flags - * [THRIFT-1041] - TDeserializer holds onto a reference of the array it reads after it is done deserializing - * [THRIFT-1106] - C++ code TAsyncProtocolProcessor.h & TAsyncBufferProcessor.h dont have virtual functions but no virtual destructor. Causes warnings on -Wall - * [THRIFT-1105] - OCaml generator does not prefix methods of included structs with their type - * [THRIFT-1104] - INSTALLDIRS should be included in configure script - * [THRIFT-1102] - typo in configure.ac: "==" operator in 'test' (instead of"'=") - * [THRIFT-1101] - bytebuffer length calculation in TBinaryProtocol writeBinary - * [THRIFT-1098] - Undefined properties in TBinaryProtocolFactory - * [THRIFT-1081] - PHP tests broken and somewhat incomplete - * [THRIFT-1080] - erlang test's 'make' fails on Mac OSX - * [THRIFT-1078] - ThriftTest.thrift generates invalid PHP library - * [THRIFT-1120] - proto.WriteListEnd being called in the wrong place - * [THRIFT-1119] - TJSONProtocol fails to UTF8 decode strings - * [THRIFT-867] - PHP accelerator module's output transport is incompatible with TFramedTransport - * [THRIFT-826] - PHP TSocket Write Timeout - * [THRIFT-835] - Bad AS3 syntax in constructors that set default values - * [THRIFT-788] - thrift_protocol.so: multiget/multiget_slice does not handle more than 17 keys correctly - * [THRIFT-125] - OCaml libraries don't compile with 32-bit ocaml - * [THRIFT-342] - PHP: can't have sets of complex types - * [THRIFT-731] - configure doesn't check for ant >= 1.7 - * [THRIFT-690] - Update TApplicationException codes - * [THRIFT-638] - BufferedTransport + C extensions block until recv timeout is reached on last fread call - -## Dependency upgrade - * [THRIFT-1177] - Update thrift to reflect changes in Go's networking libraries - -## Improvement - * [THRIFT-1155] - Remove log4j dependency from java client - * [THRIFT-1151] - Produce more informative runtime error in case of schema and data mismatch during serialization - * [THRIFT-1207] - Support DESTDIR on "make install" of ruby libs - * [THRIFT-1199] - Union structs should have generated methods to test whether a specific field is currently set - * [THRIFT-1233] - Remove unused include in generated C++ code - * [THRIFT-1189] - Ruby deserializer speed improvements - * [THRIFT-1170] - Thrift Generated Code and Java 5 - * [THRIFT-1174] - Publish as3 client implementation via Maven for use by flex-mojos users - * [THRIFT-1225] - TCompactProtocol for PHP - * [THRIFT-1221] - Remove SimpleCallback.h - * [THRIFT-1217] - Use evutil_socketpair instead of pipe (Windows port) - * [THRIFT-1216] - build Java Library behind a proxy - * [THRIFT-1231] - Remove bogus include - * [THRIFT-1213] - Membuffer should provide a way to get back the buffer - * [THRIFT-1237] - Java fb303 missing some methods - * [THRIFT-1063] - Fix Erlang Tutorial Files - * [THRIFT-1053] - Make remote client's IP address available for all socket related transports - * [THRIFT-1109] - Deploy fb303 along side libthrift to maven repo - * [THRIFT-1107] - improvement for compiler-generated python for 'None' object comparisons - * [THRIFT-1069] - Add command line option to prevent thrift from inserting gen-* directories - * [THRIFT-1049] - Allow for TServerSocket python library to bind to a specific host - * [THRIFT-1126] - Extending struct_info for erlang bindings - * [THRIFT-1100] - python TSSLSocket improvements, including certificate validation - * [THRIFT-994] - Don't try to invoke phpize if we don't have it - * [THRIFT-993] - Some improvements in C++ stubs for oneway operations - * [THRIFT-997] - Using valueOf for base types in getFieldValue - * [THRIFT-418] - Don't do runtime sorting of struct fields - * [THRIFT-151] - TSSLServerSocket and TSSLSocket implementation - * [THRIFT-27] - Generated erlang types don't contain default values for records - * [THRIFT-113] - to-string methods should omit optional null fields from output - * [THRIFT-363] - Maven Deploy - * [THRIFT-447] - Make an abstract base Client class so we can generate less code - * [THRIFT-627] - should c++ have setters for optional fields? - -## New Feature - * [THRIFT-1236] - Erlang Reconnecting Thrift Client - * [THRIFT-1021] - Framed transport support for OCaml - * [THRIFT-1068] - Python SSL Socket Support - * [THRIFT-1103] - TZlibTransport for python, a zlib compressed transport - * [THRIFT-1083] - Preforking python process pool server - * [THRIFT-999] - Add TForkingServer - -## Sub-task - * [THRIFT-1152] - Attributes from private to protected - * [THRIFT-1038] - Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable - -## Task - * [THRIFT-892] - Refactor erlang build system with rebar - -## Wish - * [THRIFT-625] - Add support for 'Go' - - - -Thrift 0.6.1 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1133] - Java and JavaScript tutorial is broken since we have Java maven deployment - * [THRIFT-1131] - C# JSON Protocol is unable to decode escaped characters in string - * [THRIFT-1074] - .keystore and .truststore are missing from the 0.6.0 distribution - -## Improvement - * [THRIFT-1109] - Deploy fb303 along side libthrift to maven repo - * [THRIFT-363] - Maven Deploy - -## Question - * [THRIFT-1206] - did the THRIFT 0.6.1 merge THRIFT-563 ? - -## Sub-task - * [THRIFT-1163] - How can i use multi service in one program? - -## Task - * [THRIFT-1112] - Apply THRIFT-363 to 0.6 branch - * [THRIFT-1113] - Apply THRIFT-1074 to 0.6 branch - - - -Thrift 0.6 --------------------------------------------------------------------------------- -## Bug - * [THRIFT-1020] - OCaml compiler generates invalid OCaml - * [THRIFT-1015] - TUnion does not handle ByteBuffer in toString - * [THRIFT-1013] - generated java code may have name clashes with thrift library - * [THRIFT-1009] - TUnion does not correctly deep copy a ByteBuffer - * [THRIFT-1032] - "make dist" fails due to c_glib problem - * [THRIFT-868] - Referencing constant values doesn't work with with typedef types - * [THRIFT-971] - java module can't be compiled without ivy and network connection - * [THRIFT-970] - Under heavy load, THttpClient may fail with "too many open files" - * [THRIFT-969] - Java Tutorial broken, move CalculatorHandler to a separate file - * [THRIFT-807] - JavaScript: Initialization of Base Types with 0 instead of null - * [THRIFT-955] - Thrift compiler for Windows uses lowercase names and directories which is inconsistent with compiling on other platforms - * [THRIFT-992] - Naming convention in C# constructor is not consistent with other fields causes compile errors - * [THRIFT-1008] - byte[] accessors throw NPE on unset field - * [THRIFT-1006] - Impossible to correctly qualify an enum constant in an external thrift file - * [THRIFT-950] - Haskell bindings treat 'byte' as unsigned 8-bit int (Data.Word.Word8), java/cpp as signed (byte/int8_t). - * [THRIFT-975] - lib/c_glib/README is missing => breaks make dist - * [THRIFT-944] - Support all version-4s of base - * [THRIFT-939] - optional binary fields throw NPE on default byte[] getters - * [THRIFT-935] - PHP Extension aborts the build if php-config is not installed - * [THRIFT-933] - Haskell's Thrift.cabal has warnings - * [THRIFT-932] - Haskell tests need to be run through 'make check' (and probably 'cabal check') too - * [THRIFT-904] - C# TSocket should disable nagle and linger - * [THRIFT-941] - Make PHP C Extension use the defined Protocol writeMessageBegin function - * [THRIFT-940] - 'make check' fails if boost is not in the std include and link paths - * [THRIFT-924] - Fix generated php structure constants - * [THRIFT-979] - ruby bindings used to work on jruby - * [THRIFT-977] - Hex Conversion Bug in C++ TJSONProtocol - * [THRIFT-347] - PHP TSocket Timeout Issues - * [THRIFT-517] - TExceptions thrown by server result in cryptic error message on client - Tried to read 4 bytes, but only got 0 bytes - -## Improvement - * [THRIFT-1024] - Add Python Twisted example to the Tutorial - * [THRIFT-958] - Change accessmodifer on trans_ field in the FrameBuffer class to public. - * [THRIFT-957] - THsHaServer: Change access modifier of the invoker field. - * [THRIFT-1002] - CodeStyle: t_c_glib_generator.cc - * [THRIFT-1005] - Give unions byte[] signature methods to go along with their ByteBuffer counterparts - * [THRIFT-951] - Add a new isServing() method to TServer - * [THRIFT-943] - Silly readme typo fix. - * [THRIFT-961] - JavaScript TestSuite using ant/ivy and Java's ServerTestBase Handler - * [THRIFT-960] - add TestServer, TestNonblockingServer and TestClient again - * [THRIFT-949] - Modify the TEnum interface so it defines a method similar to findByValue - * [THRIFT-946] - Augment FieldValueMetaData so it differentiates 'string' and 'binary' fields. - * [THRIFT-903] - custom ThreadFactory in THsHaServer - * [THRIFT-913] - Test Case for Url encoded strings + simple enhancement to lib/js/test/RunTestServer.sh - * [THRIFT-926] - Miscellaneous C++ improvements - * [THRIFT-929] - Improvements to the C++ test suite - * [THRIFT-893] - add JavaScript to the tutorial examples - * [THRIFT-1003] - Polishing c_glib code - * [THRIFT-71] - Debian packaging for thrift - -## New Feature - * [THRIFT-1033] - Node.js language target - * [THRIFT-947] - Provide a helper method to determine the TProtocol used to serialize some data. - * [THRIFT-928] - Make more statistics available in C++ servers - * [THRIFT-922] - Templatized [de]serialization code for C++ - * [THRIFT-923] - Event-driven client and server support for C++ - * [THRIFT-925] - Provide name<->value map for enums in C++ - * [THRIFT-927] - Add option to modify the PHP include path - * [THRIFT-377] - TFileTransport port in Java - * [THRIFT-106] - TSSLServerSocket - * [THRIFT-582] - C implementation of Thrift - * [THRIFT-745] - Make it easier to instantiate servers - -## Sub-task - * [THRIFT-1038] - Generated Java code for structures containing binary fields (or collections thereof) are not serializable (in the Java sense) even though they implement java.io.Serializable - -## Task - * [THRIFT-862] - Async client issues / improvements - -## Test - * [THRIFT-581] - Add a testsuite for txThrift (Twisted) - - - -Thrift 0.5.0 - Incubating --------------------------------------------------------------------------------- -THRIFT-505 Build Make configure give a summary of the enabled components (David Reiss) -THRIFT-506 Build Allow Thrift to be built without the C++ library (David Reiss) -THRIFT-844 Build Build Requirements state autoconf 2.59+ is required, but 2.60+ is needed (Harlan Lieberman-Berg) -THRIFT-850 Build Perl runtime requires Bit::Vector which may not be installed by default, but configure does not fail (Michael Lum) -THRIFT-854 Build Provide configure option and make rules to build/install php extension (Anthony Molinaro) -THRIFT-858 Build Have bootstrap.sh check for a suitable autoconf version before running (David Reiss) -THRIFT-871 Build Thrift compiler for WIndows (binary distribution) (David Reiss) -THRIFT-323 C# TJSONProtocol (Roger Meier) -THRIFT-634 C# C# Compiler Generates Incorrect Code For Fields which begin with an uppercase letter (Jon S Akhtar) -THRIFT-881 C# add csharp to the tutorial (Roger Meier) -THRIFT-856 C++ Building cpp library fails on OS X with malloc and free not being declared in scope (James Clarke) -THRIFT-865 C++ C++ compiler build depends on libfl even when flex/lex not detected (David Reiss) -THRIFT-900 C++ Unix domain socket (Roger Meier) -THRIFT-920 C++ C++ Test and Tutorial does not compile anymore due to the change within Enum handling (Roger Meier) -THRIFT-567 C++ Can't immediately stop a TSimpleServer thread that is idle (Rush Manbert) -THRIFT-756 C++ Exposing TSocket(int) constructor to public (Rajat Goel) -THRIFT-798 C++ TNonblockingServer leaks resources when destroyed (David Reiss) -THRIFT-812 C++, Python Demo of Thrift over ZeroMQ (David Reiss) -THRIFT-629 Cocoa Unused Field In TSocketServer Appears To Break iPhone Build (Jon S Akhtar) -THRIFT-838 Cocoa Generated Cocoa classes have useless @dynamic declarations (Kevin Ballard) -THRIFT-805 Cocoa Don't generate process_XXXX methods for oneway methods (Brad Taylor) -THRIFT-507 Compiler Remove the compiler's dependency on Boost (David Reiss) -THRIFT-895 Compiler (General) Thrift compiler does not allow two different enumerations to have the same key name for one of the enum values (David Reiss) -THRIFT-852 Compiler (General) Missing newline causes many compiler warnings (Anthony Molinaro) -THRIFT-877 Compiler (General) smalltalk namespace doesn't work (Bruce Lowekamp) -THRIFT-897 Compiler (General) Don't allow unqualified constant access to enum values (Bryan Duxbury) -THRIFT-9 Compiler (General) Add a default namespace declaration for all languages (David Reiss) -THRIFT-599 Erlang Don't use unnecessary processes in the Erlang transports and clients (David Reiss) -THRIFT-646 Erlang Erlang library is missing install target (David Reiss) -THRIFT-698 Erlang Generated module list should contain atoms, not strings (Anthony Molinaro) -THRIFT-866 Erlang term() in spec definitions seems to not work in erlang R12 (Anthony Molinaro) -THRIFT-886 Erlang Dialyzer warning (Anthony Molinaro) -THRIFT-785 Erlang Framed transport server problems (Anthony Molinaro) -THRIFT-884 HTML HTML Generator: add Key attribute to the Data Types Tables (Roger Meier) -THRIFT-652 Haskell Generated field name for strut is not capitalized correctly (Christian Lavoie) -THRIFT-743 Haskell compile error with GHC 6.12.1 (Christian Lavoie) -THRIFT-901 Haskell Allow the bindings to compile without -fglasgow-exts and with -Wall -Werror (Christian Lavoie) -THRIFT-905 Haskell Make haskell thrift bindings use automake to compile and install (Christian Lavoie) -THRIFT-906 Haskell Improve type mappings (Christian Lavoie) -THRIFT-914 Haskell Make haskell bindings 'easily' compilable (Christian Lavoie) -THRIFT-918 Haskell Make haskell tests run again (Christian Lavoie) -THRIFT-919 Haskell Update Haskell bindings README (Christian Lavoie) -THRIFT-787 Haskell Enums are not read correctly (Christian Lavoie) -THRIFT-250 Java ExecutorService as a constructor parameter for TServer (Ed Ceaser) -THRIFT-693 Java Thrift compiler generated java code that throws compiler warnings about deprecated methods. (Bryan Duxbury) -THRIFT-843 Java TNonblockingSocket connects without a timeout (Bryan Duxbury) -THRIFT-845 Java async client does not respect timeout (Ning Liang) -THRIFT-870 Java Java constants don't get Javadoc comments (Bryan Duxbury) -THRIFT-873 Java Java tests fail due to Too many open files (Todd Lipcon) -THRIFT-876 Java Add SASL support (Aaron T. Myers) -THRIFT-879 Java Remove @Override from TUnion.clear (Dave Engberg) -THRIFT-882 Java deep copy of binary fields does not copy ByteBuffer characteristics (arrayOffset, position) (Bryan Duxbury) -THRIFT-888 Java async client should also have nonblocking connect (Eric Jensen) -THRIFT-890 Java Java tutorial doesn't work (Todd Lipcon) -THRIFT-894 Java Make default accessors for binary fields return byte[]; provide new accessors to get ByteBuffer version (Bryan Duxbury) -THRIFT-896 Java TNonblockingSocket.isOpen() returns true even after close() (Eric Jensen) -THRIFT-907 Java libfb303 doesn't compile in 0.4.0 (Todd Lipcon) -THRIFT-912 Java Improvements and bug fixes to SASL implementation (Todd Lipcon) -THRIFT-917 Java THsHaServer should not accept an ExecutorService without catching RejectedExecutionException (Ed Ceaser) -THRIFT-931 Java Use log4j for Java tests (Todd Lipcon) -THRIFT-880 JavaME JavaME code generator and runtime library (Dave Engberg) -THRIFT-846 JavaScript JavaScript Test Framwork: extended Testcases (Roger Meier) -THRIFT-885 JavaScript Url encoded strings never get decoded? How do we fix this? (T Jake Luciani) -THRIFT-911 JavaScript (JavaScript compiler) Const structs, maps, sets, and lists generate a trailing comma (T Jake Luciani) -THRIFT-860 OCaml copy method and reset method (Lev Walkin) -THRIFT-682 PHP PHP extension doesn't compile on Mac OS X (Bryan Duxbury) -THRIFT-851 PHP php extension fails to compile on centos 5.x (Todd Lipcon) -THRIFT-840 Perl Perl protocol handler could be more robust against unrecognised types (Conrad Hughes) -THRIFT-758 Perl incorrect deference in exception handling (Yann Kerherve) -THRIFT-257 Python Support validation of required fields (Esteve Fernandez) -THRIFT-335 Python Compact Protocol for Python (David Reiss) -THRIFT-596 Python Make Python's TBufferedTransport use a configurable input buffer (David Reiss) -THRIFT-597 Python Python THttpServer performance improvements (David Reiss) -THRIFT-598 Python Allow Python's threading servers to use daemon threads (David Reiss) -THRIFT-666 Python Allow the handler to override HTTP responses in THttpServer (David Reiss) -THRIFT-673 Python Generated Python code has whitespace issues (Ian Eure) -THRIFT-721 Python THttpClient ignores url parameters (Thomas Kho) -THRIFT-824 Python TApplicationException.__str__() refers to class constants as globals (Peter Schuller) -THRIFT-855 Python Include optimized compiled python objects in install (Anthony Molinaro) -THRIFT-859 Python Allow py:twisted to be generated in different namespace than py (Bruce Lowekamp) -THRIFT-869 Python TSocket.py on Mac (and FreeBSD) doesn't handle ECONNRESET from recv() (Steven Knight) -THRIFT-875 Python Include python setup.cfg in dist (Anthony Molinaro) -THRIFT-610 Ruby binary_protocol.rb segfaults [line 86] (Unassigned) -THRIFT-899 Ruby Ruby read timeouts can sometimes be 2x what they should be (Ryan King) -THRIFT-909 Ruby allow block argument to struct constructor (Michael Stockton) -THRIFT-456 Test Suite Bad IP address string in test/cpp/src/main.cpp (Rush Manbert) - - -Thrift 0.4.0 - Incubating --------------------------------------------------------------------------------- -THRIFT-650 Build Make Check fails on Centos/OSX with 0.2.0 tarball (Anthony Molinaro) -THRIFT-770 Build Get 'make dist' to work without first compiling source code (Anthony Molinaro) -THRIFT-160 C# Created THttpTransport for the C# library based on WebHttpRequest (Michael Greene) -THRIFT-834 C# THttpClient resends contents of message after transport errors (Anatoly Fayngelerin) -THRIFT-247 C++ THttpServer Transport (Unassigned) -THRIFT-676 C++ Change C++ code generator so that generated classes can be wrapped with SWIG (Unassigned) -THRIFT-570 Compiler Thrift compiler does not error when duplicate method names are present (Bruce Simpson) -THRIFT-808 Compiler Segfault when constant declaration references a struct field that doesn't exist (Bryan Duxbury) -THRIFT-646 Erlang Erlang library is missing install target (Anthony Molinaro) -THRIFT-544 General multiple enums with the same key generate invalid code (Ben Taitelbaum) -THRIFT-434 General ruby compiler should warn when a reserved word is used (Michael Stockton) -THRIFT-799 General Files missing proper Apache license header (Bryan Duxbury) -THRIFT-832 HTML HTML generator shows unspecified struct fields as 'required' (Bryan Duxbury) -THRIFT-226 Java Collections with binary keys or values break equals() (Bryan Duxbury) -THRIFT-484 Java Ability to use a slice of a buffer instead of a direct byte[] for binary fields (Bryan Duxbury) -THRIFT-714 Java maxWorkerThreads parameter to THsHaServer has no effect (Bryan Duxbury) -THRIFT-751 Java Add clear() method to TBase (Bryan Duxbury) -THRIFT-765 Java Improved string encoding and decoding performance (Bryan Duxbury) -THRIFT-768 Java Async client for Java (Bryan Duxbury) -THRIFT-774 Java TDeserializer should provide a partialDeserialize method for primitive types (Piotr Kozikowski) -THRIFT-783 Java .equals java method is broken on structs containing binary-type fields (Unassigned) -THRIFT-804 Java CompareTo is broken for unions set to map, set, or list (Bryan Duxbury) -THRIFT-814 Java Include a TServlet in the standard Thrift distribution (Mathias Herberts) -THRIFT-818 Java Async client doesn't send method args (Bryan Duxbury) -THRIFT-830 Java Switch binary field implementation from byte[] to ByteBuffer (Bryan Duxbury) -THRIFT-831 Java FramedTransport implementation that reuses its buffers (Bryan Duxbury) -THRIFT-833 Java build.xml in lib/java is missing a classpathref attribute for the javadoc task (Bryan Duxbury) -THRIFT-836 Java Race condition causes CancelledKeyException in TAsyncClientManager (Bryan Duxbury) -THRIFT-842 Java Upgrade to current version of commons-lang (2.5 instead of 2.4) and/or change dependency in ivy.xml to not be exact (Bryan Duxbury) -THRIFT-815 JavaScript Deserialization of lists is critically broken. (T Jake Luciani) -THRIFT-827 OCaml OCaml generator to take default values into account (Lev Walkin) -THRIFT-647 PHP PHP library is missing install target (Anthony Molinaro) -THRIFT-682 PHP PHP extension doesn't compile on Mac OS X (Bryan Duxbury) -THRIFT-718 PHP Thrift PHP library includes closing tags and extraneous whitespace (Nicholas Telford) -THRIFT-778 PHP PHP socket listening server (Nick Jones) -THRIFT-780 PHP PHP extension sometimes causes an abort with two exceptions at the same time (David Reiss) -THRIFT-837 PHP PHP accelerator bug for writes > 8k (Thomas Kho) -THRIFT-782 Perl Perl code for writing containers doesn't count length of write*Begin or write*End (Conrad Hughes) -THRIFT-395 Python Python library + compiler does not support unicode strings (Unassigned) -THRIFT-133 Ruby 'namespace ruby' should error out, or be an alias to 'namespace rb' (Bryan Duxbury) -THRIFT-664 Ruby Ruby extension fails to build with Ruby 1.9.1 (Rajesh Malepati) -THRIFT-699 Ruby Excise unused "native protocol method table" stuff from thrift_native (Bryan Duxbury) -THRIFT-767 Ruby ruby compiler does not keep comments for enum values (Bryan Duxbury) -THRIFT-811 Ruby http_client_transport.rb: allow custom http headers (Tony Kamenick) -THRIFT-459 Ruby Ruby installation always tries to write to /Library/Ruby/site (Matthieu Imbert) - - -Thrift 0.1.0 - Incubating (not released) --------------------------------------------------------------------------------- -Compatibility Breaking Changes: - C++: - * It's quite possible that regenerating code and rebuilding will be - required. Make sure your headers match your libs! - - Java: - - Python: - - Ruby: - * Generated files now have underscored names [THRIFT-421] - * The library has been rearranged to be more Ruby-like [THRIFT-276] - - Erlang: - * Generated code will have to be regenerated, and the new code will - have to be deployed atomically with the new library code [THRIFT-136] - -New Features and Bug Fixes: - C++: - * Support for TCompactProtocol [THRIFT-333] - - Java: - * Support for TCompactProtocol [THRIFT-110] - - Python: - * Support for Twisted [THRIFT-148] - - Ruby: - * Support for TCompactProtocol [THRIFT-332] - diff --git a/CHANGES.md b/CHANGES.md index 172e9578398..e6db1dc3301 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Apache Thrift Changelog -## 1.0.0 +## 0.13.0 ### New Languages @@ -12,15 +12,16 @@ ### Breaking Changes -- [THRIFT-4740](https://issues.apache.org/jira/browse/THRIFT-4740) - Uses std::chrono::duration for timeouts in C++ runtime library. -- [THRIFT-4702](https://issues.apache.org/jira/browse/THRIFT-4702) - Java class org.apache.thrift.AutoExpandingBuffer is no longer public -- [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - Java changes to UTF-8 handling require JDK 1.7 at a minimum -- [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - Java class org.apache.thrift.ShortStack is no longer public -- [THRIFT-4720](https://issues.apache.org/jira/browse/THRIFT-4720) - C++03/C++98 support has been removed; also removed boost as a runtime dependency -- [THRIFT-4730](https://issues.apache.org/jira/browse/THRIFT-4730) - C++: BoostThreadFactory, PosixThreadFactory, StdThreadFactory removed -- [THRIFT-4732](https://issues.apache.org/jira/browse/THRIFT-4732) - C++: CMake build changed to use BUILD_SHARED_LIBS -- [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735) - C++: Removed Qt4 support -- [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - Java change return type signature of 'process' methods +- [THRIFT-4720](https://issues.apache.org/jira/browse/THRIFT-4720) - cpp: C++03/C++98 support has been removed; also removed boost as a runtime dependency +- [THRIFT-4730](https://issues.apache.org/jira/browse/THRIFT-4730) - cpp: BoostThreadFactory, PosixThreadFactory, StdThreadFactory removed +- [THRIFT-4732](https://issues.apache.org/jira/browse/THRIFT-4732) - cpp: CMake build changed to use BUILD_SHARED_LIBS +- [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735) - cpp: Removed Qt4 support +- [THRIFT-4740](https://issues.apache.org/jira/browse/THRIFT-4740) - cpp: Use std::chrono::duration for timeouts +- [THRIFT-4702](https://issues.apache.org/jira/browse/THRIFT-4702) - java: class org.apache.thrift.AutoExpandingBuffer is no longer public +- [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - java: changes to UTF-8 handling require JDK 1.7 at a minimum +- [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - java: class org.apache.thrift.ShortStack is no longer public +- [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - java: change return type signature of 'process' methods +- [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - js: now uses node-int64 for 64 bit integer constants ### Known Isues (Blocker or Critical) diff --git a/Makefile.am b/Makefile.am index addfa0cfbe6..104d3705a49 100755 --- a/Makefile.am +++ b/Makefile.am @@ -37,8 +37,39 @@ if WITH_TUTORIAL SUBDIRS += tutorial endif +clean-local: + $(RM) -r vendor/ + +distclean-local: + $(RM) -r .dub/ + $(RM) -r autom4te.cache/ + +CLEANFILES = \ + composer.lock \ + dub.selections.json + +DISTCLEANFILES = \ + Makefile \ + Makefile.in \ + apache-thrift-test-library \ + autoscan.log \ + compile \ + config.guess \ + config.hin \ + config.hin~ \ + config.log \ + config.status \ + config.sub \ + configure \ + configure.scan \ + debcomp \ + install-sh \ + ltmain.sh \ + missing \ + ylwrap + dist-hook: - find $(distdir) -type f \( -iname ".DS_Store" -or -iname "._*" -or -iname ".gitignore" \) | xargs rm -rf + find $(distdir) -type f \( -iname ".DS_Store" -or -iname "._*" -or -iname ".gitignore" \) | xargs rm -f find $(distdir) -type d \( -iname ".deps" -or -iname ".libs" \) | xargs rm -rf find $(distdir) -type d \( -iname ".svn" -or -iname ".git" \) | xargs rm -rf @@ -109,27 +140,30 @@ style-local: EXTRA_DIST = \ .clang-format \ + .dockerignore \ .editorconfig \ .travis.yml \ .rustfmt.toml \ - .dockerignore \ + ApacheThrift.nuspec \ appveyor.yml \ + bootstrap.sh \ bower.json \ build \ - bootstrap.sh \ - cleanup.sh \ + CHANGES.md \ CMakeLists.txt \ composer.json \ contrib \ CONTRIBUTING.md \ debian \ - doc \ doap.rdf \ - package.json \ - sonar-project.properties \ + doc \ + dub.json \ + jitpack.yml \ LANGUAGES.md \ LICENSE \ - CHANGES.md \ NOTICE \ + package.json \ + phpcs.xml.dist \ README.md \ + sonar-project.properties \ Thrift.podspec diff --git a/bootstrap.sh b/bootstrap.sh index 2452eea4486..1989437a041 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -19,7 +19,10 @@ # under the License. # -./cleanup.sh +echo -n "make distclean... " +make -k distclean >/dev/null 2>&1 +echo "ok" + if test -d lib/php/src/ext/thrift_protocol ; then if phpize -v >/dev/null 2>/dev/null ; then (cd lib/php/src/ext/thrift_protocol && phpize) diff --git a/build/docker/ubuntu-artful/Dockerfile b/build/docker/old/ubuntu-artful/Dockerfile similarity index 100% rename from build/docker/ubuntu-artful/Dockerfile rename to build/docker/old/ubuntu-artful/Dockerfile diff --git a/cleanup.sh b/cleanup.sh deleted file mode 100755 index f110721ac9f..00000000000 --- a/cleanup.sh +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -topsrcdir="`dirname $0`" -cd "$topsrcdir" - -make -k clean >/dev/null 2>&1 -make -k distclean >/dev/null 2>&1 -find . -name Makefile.in -exec rm -f {} \; -rm -rf \ -AUTHORS \ -ChangeLog \ -INSTALL \ -Makefile \ -Makefile.in \ -Makefile.orig \ -aclocal/libtool.m4 \ -aclocal/ltoptions.m4 \ -aclocal/ltsugar.m4 \ -aclocal/ltversion.m4 \ -aclocal/lt~obsolete.m4 \ -aclocal.m4 \ -autom4te.cache \ -autoscan.log \ -config.guess \ -config.h \ -config.hin \ -config.hin~ \ -config.log \ -config.status \ -config.status.lineno \ -config.sub \ -configure \ -configure.lineno \ -configure.scan \ -depcomp \ -.deps \ -install-sh \ -.libs \ -libtool \ -ltmain.sh \ -missing \ -ylwrap \ -if/gen-* \ -test/gen-* \ -lib/php/src/ext/thrift_protocol/.deps \ -lib/php/src/ext/thrift_protocol/Makefile \ -lib/php/src/ext/thrift_protocol/Makefile.fragments \ -lib/php/src/ext/thrift_protocol/Makefile.global \ -lib/php/src/ext/thrift_protocol/Makefile.objects \ -lib/php/src/ext/thrift_protocol/acinclude.m4 \ -lib/php/src/ext/thrift_protocol/aclocal.m4 \ -lib/php/src/ext/thrift_protocol/autom4te.cache \ -lib/php/src/ext/thrift_protocol/build \ -lib/php/src/ext/thrift_protocol/config.guess \ -lib/php/src/ext/thrift_protocol/config.h \ -lib/php/src/ext/thrift_protocol/config.h.in \ -lib/php/src/ext/thrift_protocol/config.log \ -lib/php/src/ext/thrift_protocol/config.nice \ -lib/php/src/ext/thrift_protocol/config.status \ -lib/php/src/ext/thrift_protocol/config.sub \ -lib/php/src/ext/thrift_protocol/configure \ -lib/php/src/ext/thrift_protocol/configure.in \ -lib/php/src/ext/thrift_protocol/include \ -lib/php/src/ext/thrift_protocol/install-sh \ -lib/php/src/ext/thrift_protocol/libtool \ -lib/php/src/ext/thrift_protocol/ltmain.sh \ -lib/php/src/ext/thrift_protocol/missing \ -lib/php/src/ext/thrift_protocol/mkinstalldirs \ -lib/php/src/ext/thrift_protocol/modules \ -lib/php/src/ext/thrift_protocol/run-tests.php diff --git a/configure.ac b/configure.ac index 1fcd2fb953a..0f6c6da0533 100755 --- a/configure.ac +++ b/configure.ac @@ -206,9 +206,9 @@ if test "$with_c_glib" = "yes"; then fi AM_CONDITIONAL(WITH_C_GLIB, [test "$have_glib2" = "yes" -a "$have_gobject2" = "yes"]) -echo "OpenSSL check" +# echo "OpenSSL check" if test "$have_cpp" = "yes" -o "$have_c_glib" = "yes"; then - echo "Have cpp or c so we check for OpenSSL" + # echo "Have cpp or c so we check for OpenSSL" AX_CHECK_OPENSSL() fi diff --git a/debian/rules b/debian/rules index 9b436d97aaa..e209ba33caf 100755 --- a/debian/rules +++ b/debian/rules @@ -96,8 +96,6 @@ clean: # Add here commands to clean up after the build process. -$(MAKE) clean - $(CURDIR)/cleanup.sh - dh_clean install: install-indep install-arch diff --git a/lib/as3/Makefile.am b/lib/as3/Makefile.am index 5a078c6ff38..0b3c3befc77 100644 --- a/lib/as3/Makefile.am +++ b/lib/as3/Makefile.am @@ -31,6 +31,7 @@ clean-local: ./gradlew $(GRADLE_OPTS) clean \ -Prelease=true \ --console=plain + $(RM) -r .gradle check-local: $(THRIFT) ./gradlew $(GRADLE_OPTS) test \ @@ -43,6 +44,9 @@ maven-publish: -Psign=true \ --console=plain +dist-hook: + $(RM) -r $(distdir)/.gradle/ + EXTRA_DIST = \ CMakeLists.txt \ README.md \ diff --git a/lib/csharp/Makefile.am b/lib/csharp/Makefile.am index 56a8b0f54f4..cc2bbc96cfe 100644 --- a/lib/csharp/Makefile.am +++ b/lib/csharp/Makefile.am @@ -92,9 +92,12 @@ Thrift.dll: $(THRIFTCODE) Thrift.45.dll: $(THRIFTCODE) $(CSC) $(CSC_DEFINES) -out:$@ -target:library -reference:System.Web $(THRIFTCODE) -clean-local: - $(RM) Thrift.dll \ - $(RM) Thrift.45.dll +CLEANFILES = \ + Thrift.dll \ + Thrift.45.dll + +DISTCLEANFILES = \ + Makefile.in EXTRA_DIST = \ $(THRIFTCODE) \ @@ -109,7 +112,3 @@ EXTRA_DIST = \ test \ coding_standards.md \ README.md - -MAINTAINERCLEANFILES = \ - Makefile \ - Makefile.in diff --git a/lib/csharp/test/Multiplex/Makefile.am b/lib/csharp/test/Multiplex/Makefile.am index 57253d6b57b..9c1f1b8b75c 100644 --- a/lib/csharp/test/Multiplex/Makefile.am +++ b/lib/csharp/test/Multiplex/Makefile.am @@ -41,8 +41,19 @@ MultiplexClient.exe: Client/Multiplex.Test.Client.cs ThriftImpl.dll MultiplexServer.exe: Server/Multiplex.Test.Server.cs ThriftImpl.dll $(CSC) $(CSC_DEFINES) -out:$@ -reference:../../Thrift.dll -reference:ThriftImpl.dll $< +CLEANFILES = \ + MultiplexClient.exe \ + MultiplexServer.exe \ + ThriftImpl.dll + +DISTCLEANFILES = \ + Makefile.in + clean-local: - $(RM) -rf gen-csharp *.exe *.dll + $(RM) -rf gen-csharp + +dist-hook: + $(RM) -r $(distdir)/gen-csharp/ TESTPORT = 9501 check-local: MultiplexServer.exe MultiplexClient.exe diff --git a/lib/d/Makefile.am b/lib/d/Makefile.am index 2a812185677..4787e0a6077 100644 --- a/lib/d/Makefile.am +++ b/lib/d/Makefile.am @@ -141,9 +141,13 @@ all-local: $(all_targets) install-exec-local: $(INSTALL_PROGRAM) $(all_targets) $(DESTDIR)$(libdir) - clean-local: - $(RM) -rf docs $(D_LIB_NAME) $(D_EVENT_LIB_NAME) $(D_SSL_LIB_NAME) unittest + $(RM) -r docs + $(RM) $(D_LIB_NAME) + $(RM) $(D_EVENT_LIB_NAME) + $(RM) $(D_SSL_LIB_NAME) + $(RM) -r test/gen-d + $(RM) -r unittest # diff --git a/lib/dart/Makefile.am b/lib/dart/Makefile.am index ab6ddc02256..373a883d6c8 100644 --- a/lib/dart/Makefile.am +++ b/lib/dart/Makefile.am @@ -22,12 +22,18 @@ all-local: clean-local: $(RM) -r .pub - find . -type d -name "packages" | xargs $(RM) -r + find . -type d -name ".dart_tool" | xargs $(RM) -r find . -type f -name ".packages" | xargs $(RM) - find . -type f -name "pubspec.lock" | xargs $(RM) + find . -type d -name "packages" | xargs $(RM) -r check-local: all +dist-hook: + $(RM) -r $(distdir)/.pub + find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r + find $(distdir) -type f -name ".packages" | xargs $(RM) + find $(distdir) -type d -name "packages" | xargs $(RM) -r + EXTRA_DIST = \ .analysis_options diff --git a/lib/erl/Makefile.am b/lib/erl/Makefile.am index 06323b4a7d2..fdfc9eb6b12 100644 --- a/lib/erl/Makefile.am +++ b/lib/erl/Makefile.am @@ -67,16 +67,26 @@ install: all done uninstall: - rm -rf $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift) + $(RM) -rf $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift) -clean: - rm -f .generated - rm -rf test/gen-erl/ - rm -f $(THRIFT_OMIT_FILE) +clean-local: $(REBAR) clean + $(RM) .generated + $(RM) -r .rebar/ + $(RM) -r deps/ + $(RM) -r test/gen-erl/ + $(RM) $(THRIFT_OMIT_FILE) maintainer-clean-local: - rm -rf ebin + $(RM) -r ebin/ + +dist-hook: + $(RM) $(distdir)/.generated + $(RM) -r $(distdir)/.rebar/ + $(RM) -r $(distdir)/deps/ + $(RM) -r $(distdir)/ebin/ + $(RM) -r $(distdir)/test/gen-erl/ + $(RM) $(distdir)/$(THRIFT_OMIT_FILE) EXTRA_DIST = \ include \ diff --git a/lib/js/Makefile.am b/lib/js/Makefile.am index 9ea20a4ab8d..b534042649a 100644 --- a/lib/js/Makefile.am +++ b/lib/js/Makefile.am @@ -18,13 +18,45 @@ # # Make sure this doesn't fail if ant is not configured. -# We call install twice to work around npm issues +# We call npm install twice to work around older npm issues +# (note these issues may no longer be present, but it is ok) # + if HAVE_NPM + SUBDIRS = test -check-local: all +prereq: $(NPM) install || $(NPM) install $(NPM) list + +check-local: prereq all ./node_modules/.bin/grunt + +doc: prereq + ./node_modules/.bin/grunt jsdoc + endif + +clean-local: + $(RM) -r dist + $(RM) -r doc + $(RM) -r node_modules + $(RM) -r test/build/ + $(RM) -r test/gen-*/ + +dist-hook: + $(RM) -r $(distdir)/dist/ + $(RM) -r $(distdir)/doc/ + $(RM) -r $(distdir)/node_modules/ + $(RM) -r $(distdir)/test/build/ + $(RM) -r $(distdir)/test/gen-*/ + +EXTRA_DIST = \ + coding_standards.md \ + Gruntfile.js \ + package.json \ + package-lock.json \ + README.md \ + src \ + test diff --git a/lib/js/test/build.xml b/lib/js/test/build.xml index 4795fd26751..d891b439409 100755 --- a/lib/js/test/build.xml +++ b/lib/js/test/build.xml @@ -73,7 +73,7 @@ You need libthrift*.jar and libthrift*test.jar located at ${thrift.java.dir}/build/libs - Did you compile Thrift Java library and its test suite by "ant compile-test"? + Did you compile Thrift Java library and its test suite by "make check"? diff --git a/lib/json/Makefile.am b/lib/json/Makefile.am index 1051b9bacd6..6c8c0ce8116 100644 --- a/lib/json/Makefile.am +++ b/lib/json/Makefile.am @@ -17,13 +17,17 @@ # under the License. # -SUBDIRS = - if WITH_JAVA # Schema validation test depends on java -SUBDIRS += test +SUBDIRS = test endif +clean-local: + $(RM) -r test/build/ + +dist-hook: + $(RM) -r $(distdir)/test/build/ + EXTRA_DIST = \ schema.json \ test diff --git a/lib/netcore/Makefile.am b/lib/netcore/Makefile.am index caf3f34558b..4e2d6a5972c 100644 --- a/lib/netcore/Makefile.am +++ b/lib/netcore/Makefile.am @@ -17,18 +17,35 @@ # under the License. # -SUBDIRS = . - all-local: $(DOTNETCORE) build check-local: $(DOTNETCORE) test Tests/Thrift.Tests/Thrift.Tests.csproj - ${DOTNETCORE} test Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj + $(DOTNETCORE) test Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj clean-local: $(RM) -r Thrift/bin $(RM) -r Thrift/obj + $(RM) -r Tests/Thrift.Tests/bin + $(RM) -r Tests/Thrift.Tests/obj + $(RM) -r Tests/Thrift.IntegrationTests/bin + $(RM) -r Tests/Thrift.IntegrationTests/obj + $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/bin + $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/obj + +dist-hook: + $(RM) -r $(distdir)/Thrift/bin + $(RM) -r $(distdir)/Thrift/obj + $(RM) -r $(distdir)/Tests/Thrift.Tests/bin + $(RM) -r $(distdir)/Tests/Thrift.Tests/obj + $(RM) -r $(distdir)/Tests/Thrift.IntegrationTests/bin + $(RM) -r $(distdir)/Tests/Thrift.IntegrationTests/obj + $(RM) -r $(distdir)/Tests/Thrift.PublicInterfaces.Compile.Tests/bin + $(RM) -r $(distdir)/Tests/Thrift.PublicInterfaces.Compile.Tests/obj + +DISTCLEANFILES = \ + Makefile.in EXTRA_DIST = \ README.md \ diff --git a/lib/nodejs/Makefile.am b/lib/nodejs/Makefile.am index 68ea3ea48b1..091f768b90a 100755 --- a/lib/nodejs/Makefile.am +++ b/lib/nodejs/Makefile.am @@ -32,7 +32,7 @@ check: deps cd $(top_srcdir) && $(NPM) test && $(NPM) run lint-tests && cd lib/nodejs clean-local: - $(RM) -r test/gen-nodejs + $(RM) -r test/gen-* $(RM) -r $(top_srcdir)/node_modules EXTRA_DIST = \ diff --git a/lib/php/Makefile.am b/lib/php/Makefile.am index 8d9050a1dd9..7fdebe102ad 100755 --- a/lib/php/Makefile.am +++ b/lib/php/Makefile.am @@ -33,6 +33,7 @@ phpmoduledir = `php-config --extension-dir` phpmodule_SCRIPTS = src/ext/thrift_protocol/modules/thrift_protocol.so distclean-local: + if [ -f src/ext/thrift_protocol/Makefile ]; then cd src/ext/thrift_protocol/ && $(MAKE) distclean; fi cd $(phpmodule_SCRIPTS) && $(PHPIZE) --clean endif @@ -128,6 +129,10 @@ phptype_DATA = \ lib/Type/TType.php \ lib/Type/TConstant.php +clean-local: + if [ -f src/ext/thrift_protocol/Makefile ]; then cd src/ext/thrift_protocol/ && $(MAKE) clean; fi + + EXTRA_DIST = \ lib \ src/autoload.php \ @@ -144,6 +149,5 @@ EXTRA_DIST = \ README.md MAINTAINERCLEANFILES = \ - Makefile \ Makefile.in diff --git a/lib/php/test/Makefile.am b/lib/php/test/Makefile.am index 48246882647..6f4e50a50b6 100755 --- a/lib/php/test/Makefile.am +++ b/lib/php/test/Makefile.am @@ -48,6 +48,8 @@ check: deps stubs \ check-validator \ check-json-serializer +distclean-local: + clean-local: $(RM) -r ./packages $(RM) TEST-*.xml diff --git a/lib/py/Makefile.am b/lib/py/Makefile.am index 5861858f46e..46e44054bf1 100644 --- a/lib/py/Makefile.am +++ b/lib/py/Makefile.am @@ -40,13 +40,19 @@ all-local: py3-build install-exec-hook: $(PYTHON) setup.py install --root=$(DESTDIR) --prefix=$(PY_PREFIX) $(PYTHON_SETUPUTIL_ARGS) -clean-local: - $(RM) -r build - check-local: all py3-test $(PYTHON) test/thrift_json.py $(PYTHON) test/test_sslsocket.py +clean-local: + $(RM) -r build + find . -type f \( -iname "*.pyc" \) | xargs rm -f + find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + +dist-hook: + find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f + find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + EXTRA_DIST = \ CMakeLists.txt \ MANIFEST.in \ diff --git a/lib/rb/Makefile.am b/lib/rb/Makefile.am index 137edb4d424..1841065f5a3 100755 --- a/lib/rb/Makefile.am +++ b/lib/rb/Makefile.am @@ -31,6 +31,7 @@ install-exec-hook: clean-local: $(BUNDLER) install $(BUNDLER) exec rake clean + $(RM) -r spec/gen-rb/ check-local: all $(BUNDLER) install @@ -38,6 +39,9 @@ check-local: all endif +dist-hook: + $(RM) -r $(distdir)/spec/gen-rb/ + EXTRA_DIST = \ coding_standards.md \ Rakefile \ diff --git a/package-lock.json b/package-lock.json index 7c39c2a2b59..8a6645fc610 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "1.0.0", + "version": "0.13.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/test/Makefile.am b/test/Makefile.am index 68f198615fe..84f1f25cc45 100755 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -108,25 +108,32 @@ check-local: $(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/test/ThriftTest.thrift clean-local: - rm -rf $(top_srcdir)/test/gen-html + $(RM) -r $(top_srcdir)/test/gen-html/ + find . -type d -name "__pycache__" | xargs rm -rf + find . -type f -name "*.pyc" | xargs rm -f + +dist-hook: + $(RM) -r $(distdir)/gen-html/ + find $(distdir) -type d -name "__pycache__" | xargs rm -rf + find $(distdir) -type f -name "*.pyc" | xargs rm -f EXTRA_DIST = \ audit \ - crossrunner \ - keys \ c_glib \ cl \ cpp \ + crossrunner \ dart \ erl \ hs \ + keys \ lua \ ocaml \ perl \ php \ py \ - py.twisted \ py.tornado \ + py.twisted \ rb \ rs \ threads \ @@ -134,12 +141,14 @@ EXTRA_DIST = \ BrokenConstants.thrift \ ConstantsDemo.thrift \ DebugProtoTest.thrift \ - DoubleConstantsTest.thrift \ DenseLinkingTest.thrift \ DocTest.thrift \ + DoubleConstantsTest.thrift \ + EnumContainersTest.thrift \ EnumTest.thrift \ FullCamelTest.thrift \ Include.thrift \ + Int64Test.thrift \ JavaBeansTest.thrift \ JavaDeepCopyTest.thrift \ JavaTypes.thrift \ @@ -150,7 +159,6 @@ EXTRA_DIST = \ OptionalRequiredTest.thrift \ Recursive.thrift \ ReuseObjects.thrift \ - EnumContainersTest.thrift \ SmallTest.thrift \ StressTest.thrift \ ThriftTest.thrift \ diff --git a/test/c_glib/Makefile.am b/test/c_glib/Makefile.am index 4a03d29d759..01ab2caf094 100755 --- a/test/c_glib/Makefile.am +++ b/test/c_glib/Makefile.am @@ -65,10 +65,18 @@ AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) @GCOV_LDFLAGS@ clean-local: - $(RM) gen-c_glib/* + $(RM) -r gen-c_glib/ + $(RM) test_client + $(RM) test_server + $(RM) libtestcglib.la + find . -type f -iname "*.o" | xargs rm -f + +dist-hook: + $(RM) -r $(distdir)/gen-c_glib/ + $(RM) $(distdir)/test_client + $(RM) $(distdir)/test_server + $(RM) $(distdir)/libtestcglib.la + find $(distdir) -type f -iname "*.o" | xargs rm -f EXTRA_DIST = \ - src/test_client.c \ - src/thrift_test_handler.c \ - src/thrift_test_handler.h \ - src/test_server.c + src diff --git a/test/cpp/Makefile.am b/test/cpp/Makefile.am index e8be80a3a17..ebe715eefa0 100755 --- a/test/cpp/Makefile.am +++ b/test/cpp/Makefile.am @@ -113,7 +113,7 @@ AM_CXXFLAGS = -Wall -Wextra -pedantic -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACR AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) $(ZLIB_LIBS) clean-local: - $(RM) gen-cpp/* + $(RM) -r gen-cpp/ style-local: $(CPPSTYLE_CMD) diff --git a/test/dart/Makefile.am b/test/dart/Makefile.am index 9750ec236d2..27fdc099f43 100644 --- a/test/dart/Makefile.am +++ b/test/dart/Makefile.am @@ -33,10 +33,20 @@ precross: stubs check: stubs clean-local: - $(RM) -r gen-dart test_client/.pub + $(RM) -r gen-dart/ test_client/.pub + find . -type d -name ".dart_tool" | xargs $(RM) -r find . -type d -name "packages" | xargs $(RM) -r find . -type f -name ".packages" | xargs $(RM) find . -type f -name "pubspec.lock" | xargs $(RM) +dist-hook: + $(RM) -r $(distdir)/gen-dart/ $(distdir)/test_client/.pub + find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r + find $(distdir) -type d -name "packages" | xargs $(RM) -r + find $(distdir) -type f -name ".packages" | xargs $(RM) + client: stubs ${DART} test_client/bin/main.dart + +EXTRA_DIST = \ + test_client diff --git a/test/erl/Makefile.am b/test/erl/Makefile.am index ff25e89f9c0..81913eefd76 100644 --- a/test/erl/Makefile.am +++ b/test/erl/Makefile.am @@ -35,7 +35,17 @@ endif precross: .generated $(REBAR) compile +maintainer-clean-local: + $(RM) -r ebin/ + clean: - rm -f .generated - rm -rf src/gen-erl $(REBAR) clean + $(RM) .generated + $(RM) -r .rebar/ + $(RM) -r src/gen-erl/ + +dist-hook: + $(RM) $(distdir)/.generated + $(RM) -r $(distdir)/.rebar/ + $(RM) -r $(distdir)/ebin/ + $(RM) -r $(distdir)/src/gen-erl/ diff --git a/test/hs/Makefile.am b/test/hs/Makefile.am index 17489068c7a..817070d8fa1 100644 --- a/test/hs/Makefile.am +++ b/test/hs/Makefile.am @@ -30,9 +30,18 @@ check: stubs sh run-test.sh Include clean-local: - $(RM) -r gen-hs + $(RM) -r gen-hs/ $(RM) *.hi $(RM) *.o + $(RM) TestClient + $(RM) TestServer + +dist-hook: + $(RM) -r $(distdir)/gen-hs/ + $(RM) $(distdir)/*.hi + $(RM) $(distdir)/*.o + $(RM) $(destdir)/TestClient + $(RM) $(destdir)/TestServer all-local: stubs ghc -igen-hs TestServer.hs diff --git a/test/lua/Makefile.am b/test/lua/Makefile.am index ed8c5aee8d1..b2683e1b968 100644 --- a/test/lua/Makefile.am +++ b/test/lua/Makefile.am @@ -28,4 +28,7 @@ stubs: ../ThriftTest.thrift $(THRIFT) precross: stubs clean-local: - $(RM) -r gen-lua + $(RM) -r gen-lua/ + +dist-hook: + $(RM) -r $(distdir)/gen-lua/ diff --git a/test/netcore/Makefile.am b/test/netcore/Makefile.am index 376ffb71e15..2fff4ba3a33 100644 --- a/test/netcore/Makefile.am +++ b/test/netcore/Makefile.am @@ -27,10 +27,19 @@ precross: clean-local: $(RM) -r Client/bin - $(RM) -r Server/bin $(RM) -r Client/obj + $(RM) -r Client/ThriftTest + $(RM) -r Server/bin $(RM) -r Server/obj - $(RM) -r ThriftTest/ThriftTest + $(RM) -r Server/ThriftTest + +dist-hook: + $(RM) -r $(distdir)/Client/bin + $(RM) -r $(distdir)/Client/obj + $(RM) -r $(distdir)/Client/ThriftTest + $(RM) -r $(distdir)/Server/bin + $(RM) -r $(distdir)/Server/obj + $(RM) -r $(distdir)/Server/ThriftTest EXTRA_DIST = \ Client \ diff --git a/test/perl/Makefile.am b/test/perl/Makefile.am index 165b9a7d043..1dbaf28b0d7 100644 --- a/test/perl/Makefile.am +++ b/test/perl/Makefile.am @@ -25,5 +25,7 @@ precross: stubs check: stubs clean-local: - $(RM) -r gen-perl + $(RM) -r gen-perl/ +dist-hook: + $(RM) -r $(distdir)/gen-perl/ diff --git a/test/php/Makefile.am b/test/php/Makefile.am index 72f7fc58142..5c42321c18b 100755 --- a/test/php/Makefile.am +++ b/test/php/Makefile.am @@ -33,7 +33,12 @@ precross: stubs php_ext_dir check: stubs php_ext_dir clean-local: - $(RM) -r gen-php gen-phpi gen-php-classmap php_ext_dir + $(RM) -r gen-*/ + $(RM) -r php_ext_dir + +dist-hook: + $(RM) -r $(distdir)/gen-*/ + $(RM) -r $(distdir)/php_ext_dir/ client: stubs php_ext_dir php TestClient.php diff --git a/test/py.tornado/Makefile.am b/test/py.tornado/Makefile.am index a8e680a97f1..e962f0cfcb0 100644 --- a/test/py.tornado/Makefile.am +++ b/test/py.tornado/Makefile.am @@ -27,4 +27,12 @@ check: thrift_gen ./test_suite.py clean-local: - $(RM) -r gen-py.tornado + $(RM) -r build + find . -type f \( -iname "*.pyc" \) | xargs rm -f + find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r gen-py*/ + +dist-hook: + find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f + find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r $(distdir)/gen-py*/ diff --git a/test/py.twisted/Makefile.am b/test/py.twisted/Makefile.am index d11908cc0ae..dee8e2f69a7 100644 --- a/test/py.twisted/Makefile.am +++ b/test/py.twisted/Makefile.am @@ -27,4 +27,12 @@ check: stubs $(TRIAL) ./test_suite.py clean-local: - $(RM) -r gen-py.twisted + $(RM) -r build + find . -type f \( -iname "*.pyc" \) | xargs rm -f + find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r gen-py*/ + +dist-hook: + find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f + find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r $(distdir)/gen-py*/ diff --git a/test/py/Makefile.am b/test/py/Makefile.am index 829620055b3..9433e5907da 100644 --- a/test/py/Makefile.am +++ b/test/py/Makefile.am @@ -94,4 +94,12 @@ gen-py-dynamicslots/%/__init__.py: ../%.thrift $(THRIFT) $(THRIFT) --gen py:dynamic,slots -out gen-py-dynamicslots $< clean-local: - $(RM) -r gen-py gen-py-slots gen-py-default gen-py-oldstyle gen-py-no_utf8strings gen-py-dynamic gen-py-dynamicslots + $(RM) -r build + find . -type f \( -iname "*.pyc" \) | xargs rm -f + find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r gen-py*/ + +dist-hook: + find $(distdir) -type f \( -iname "*.pyc" \) | xargs rm -f + find $(distdir) -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf + $(RM) -r $(distdir)/gen-py*/ diff --git a/test/rb/Makefile.am b/test/rb/Makefile.am index cfdc1496efd..39109340d8c 100644 --- a/test/rb/Makefile.am +++ b/test/rb/Makefile.am @@ -30,3 +30,8 @@ if HAVE_BUNDLER $(BUNDLER) exec $(RUBY) -I. test_suite.rb endif +clean-local: + $(RM) -r gen-rb/ + +dist-hook: + $(RM) -r $(distdir)/gen-rb/ diff --git a/test/rs/Makefile.am b/test/rs/Makefile.am index 54905b4ef5c..4b061eae064 100644 --- a/test/rs/Makefile.am +++ b/test/rs/Makefile.am @@ -34,7 +34,7 @@ clean-local: EXTRA_DIST = \ Cargo.toml \ - src/lib.rs \ + src/lib.rs \ src/bin/test_server.rs \ src/bin/test_client.rs diff --git a/tutorial/d/Makefile.am b/tutorial/d/Makefile.am index d8c8b2910fd..358294ce56d 100644 --- a/tutorial/d/Makefile.am +++ b/tutorial/d/Makefile.am @@ -44,3 +44,10 @@ all-local: $(PROGS) clean: $(RM) -f $(PROGS) + $(RM) -r gen-d/ + find . -type f -name '*.o' | xargs rm -f + +dist-hook: + $(RM) -f $(distdir)/$(PROGS) + $(RM) -r $(distdir)/gen-d/ + find $(destdir) -type f -name '*.o' | xargs rm -f diff --git a/tutorial/dart/Makefile.am b/tutorial/dart/Makefile.am index 0495aca6043..0b93ac859dd 100644 --- a/tutorial/dart/Makefile.am +++ b/tutorial/dart/Makefile.am @@ -25,11 +25,19 @@ gen-dart/tutorial/lib/tutorial.dart gen-dart/shared/lib/shared.dart: $(top_srcdi all-local: gen-dart/tutorial/lib/tutorial.dart pub-get clean-local: - $(RM) -r gen-* + $(RM) -r gen-*/ + find . -type d -name ".dart_tool" | xargs $(RM) -r find . -type d -name "packages" | xargs $(RM) -r find . -type f -name ".packages" | xargs $(RM) find . -type f -name "pubspec.lock" | xargs $(RM) +dist-hook: + $(RM) -r $(distdir)/gen-*/ + find $(distdir) -type d -name ".dart_tool" | xargs $(RM) -r + find $(distdir) -type d -name "packages" | xargs $(RM) -r + find $(distdir) -type f -name ".packages" | xargs $(RM) + find $(distdir) -type f -name "pubspec.lock" | xargs $(RM) + pub-get: pub-get-gen pub-get-client pub-get-console-client pub-get-server pub-get-gen: pub-get-tutorial pub-get-shared diff --git a/tutorial/hs/Makefile.am b/tutorial/hs/Makefile.am index a3eccc2b1c8..9c6fd8308a6 100755 --- a/tutorial/hs/Makefile.am +++ b/tutorial/hs/Makefile.am @@ -27,7 +27,12 @@ install-exec-hook: # Make sure this doesn't fail if Haskell is not configured. clean-local: $(CABAL) clean - $(RM) -r gen-* + $(RM) -r dist/ + $(RM) -r gen-*/ + +dist-hook: + $(RM) -r $(distdir)/dist/ + $(RM) -r $(distdir)/gen-*/ check-local: $(CABAL) check diff --git a/tutorial/netcore/Makefile.am b/tutorial/netcore/Makefile.am index e3055565567..bd19dfe6a6f 100644 --- a/tutorial/netcore/Makefile.am +++ b/tutorial/netcore/Makefile.am @@ -31,6 +31,15 @@ clean-local: $(RM) -r Interfaces/bin $(RM) -r Interfaces/obj +dist-hook: + $(RM) $(distdir)/Interfaces.dll + $(RM) -r $(distdir)/Client/bin + $(RM) -r $(distdir)/Client/obj + $(RM) -r $(distdir)/Server/bin + $(RM) -r $(distdir)/Server/obj + $(RM) -r $(distdir)/Interfaces/bin + $(RM) -r $(distdir)/Interfaces/obj + EXTRA_DIST = \ Client \ Interfaces \ From 3f559940c23deed67c61e1e8fd92e1aa5a6f108d Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 26 Jan 2019 08:12:56 -0500 Subject: [PATCH 182/756] THRIFT-4757: fix npm identified security vulnerability in transient dependency on sync-exec --- build/veralign.sh | 1 + lib/js/package-lock.json | 124 ++++++++++++++++++++------------------- lib/js/package.json | 8 +-- lib/ts/Makefile.am | 32 +++++++++- lib/ts/package-lock.json | 81 ++++++++++++------------- lib/ts/package.json | 21 +++++-- 6 files changed, 150 insertions(+), 117 deletions(-) diff --git a/build/veralign.sh b/build/veralign.sh index 05039dc5d80..49c39a5ad7f 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -86,6 +86,7 @@ FILES[lib/rs/Cargo.toml]=simpleReplace FILES[lib/st/package.xml]=simpleReplace FILES[lib/swift/Sources/Thrift.swift]=simpleReplace FILES[lib/swift/Tests/ThriftTests/ThriftTests.swift]=simpleReplace +FILES[lib/ts/package.json]=jsonReplace FILES[package.json]=jsonReplace FILES[sonar-project.properties]=simpleReplace FILES[test/csharp/Properties/AssemblyInfo.cs]=simpleReplace diff --git a/lib/js/package-lock.json b/lib/js/package-lock.json index 7c8374fd0d5..5a6ab05872c 100644 --- a/lib/js/package-lock.json +++ b/lib/js/package-lock.json @@ -236,7 +236,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true + "dev": true, + "optional": true }, "assign-symbols": { "version": "1.0.0", @@ -366,9 +367,9 @@ } }, "bluebird": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", - "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==" + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" }, "bn.js": { "version": "4.11.8", @@ -883,6 +884,7 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "dev": true, + "optional": true, "requires": { "delayed-stream": "~1.0.0" } @@ -1153,7 +1155,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true + "dev": true, + "optional": true }, "deps-sort": { "version": "2.0.0", @@ -1352,7 +1355,7 @@ }, "es6-promisify": { "version": "5.0.0", - "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { @@ -1550,7 +1553,8 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true + "dev": true, + "optional": true }, "eyes": { "version": "0.1.8", @@ -1650,9 +1654,9 @@ } }, "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.1.tgz", + "integrity": "sha512-jQp949ZmEbiYHk3gkbdtpJ0G1+kgtLQBNdP5edFP7Fh+WAYceLQz6yO1SBj72Xkg8GVyTB3bBzAYrHJVh5Xd5g==", "dev": true, "requires": { "expand-tilde": "^2.0.2", @@ -1663,9 +1667,9 @@ } }, "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", "dev": true }, "for-in": { @@ -1873,16 +1877,16 @@ } }, "grunt-cli": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.3.1.tgz", - "integrity": "sha512-UwBRu/QpAjDc53DRLEkyilFdL0zenpxu+fddTIlsF/KJqdNcHaQmvyu1W3cDesZ9rqqZdKK5A8+QDIyLUEWoZQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.3.2.tgz", + "integrity": "sha512-8OHDiZZkcptxVXtMfDxJvmN7MVJNE8L/yIcPb4HB7TlyFD1kDvjHrb62uhySsU14wJx9ORMnTuhRMQ40lH/orQ==", "dev": true, "requires": { "grunt-known-options": "~1.1.0", "interpret": "~1.1.0", "liftoff": "~2.5.0", "nopt": "~4.0.1", - "v8flags": "~3.0.2" + "v8flags": "~3.1.1" } }, "grunt-contrib-concat": { @@ -1961,14 +1965,14 @@ } }, "grunt-contrib-qunit": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-3.0.1.tgz", - "integrity": "sha512-s994+ipKwc+oUUIWaGIw1soyID4pExSGMd/cHQN5h0p8KbIjR1Le3ZC3giSDDKXtZFE0i+Obf0uIjNvjftX2Cw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-3.1.0.tgz", + "integrity": "sha512-mdk8UltH6mxCD63E0hTXMAts42DOi4z4bBBrY7qnuHiShflMF7IueSMYe0zWaZ2dO8mgujh57Zfny2EbigJhRg==", "dev": true, "requires": { "eventemitter2": "^5.0.1", "p-each-series": "^1.0.0", - "puppeteer": "1.7.0" + "puppeteer": "^1.11.0" }, "dependencies": { "eventemitter2": { @@ -2082,13 +2086,12 @@ } }, "grunt-shell-spawn": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/grunt-shell-spawn/-/grunt-shell-spawn-0.3.10.tgz", - "integrity": "sha1-gbuNRX7EfTGCqH1jCO+EXd+5SI8=", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/grunt-shell-spawn/-/grunt-shell-spawn-0.3.12.tgz", + "integrity": "sha512-TprZct92sQ4M2Q92piaeLsCrx4+gq/ageuxjZsRG6cglKt7x7rGA3YHt8D30+G789v+/pw4l0tDjEyrkMXx2tA==", "dev": true, "requires": { - "grunt": ">=0.4.x", - "sync-exec": "~0.6.2" + "grunt": ">=0.4.x" } }, "gzip-size": { @@ -2596,7 +2599,8 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true + "dev": true, + "optional": true }, "js-yaml": { "version": "3.5.5", @@ -2620,7 +2624,8 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true + "dev": true, + "optional": true }, "jsdoc": { "version": "3.5.5", @@ -2727,9 +2732,9 @@ } }, "json-int64": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-0.0.3.tgz", - "integrity": "sha512-6nAloOVry+klkifPKPqFLX/FI4L95oBfu5T5vKKt4L8gik8cy80wOtzC+kM1Vh2r60QdDqDr7u/XVk6VlfueEg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-1.0.0.tgz", + "integrity": "sha512-yrTg9swToElhEPETLMdZkEzDhbXLs+cxkw/b2rglMPOBlM1DE0utH1EReSMLcnpYJk5iUvD12r0fP2/xHitF5Q==", "requires": { "node-int64": "0.4.0" } @@ -2948,7 +2953,7 @@ }, "marked": { "version": "0.3.19", - "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==" }, "maxmin": { @@ -3059,22 +3064,24 @@ } }, "mime": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", - "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", "dev": true }, "mime-db": { "version": "1.37.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", - "dev": true + "dev": true, + "optional": true }, "mime-types": { "version": "2.1.21", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", "dev": true, + "optional": true, "requires": { "mime-db": "~1.37.0" } @@ -3659,25 +3666,25 @@ "dev": true }, "puppeteer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.7.0.tgz", - "integrity": "sha512-f+1DxKHPqce6CXUBz2eVO2WcATeVeQSOPG9GYaGObEZDCiCEUwG+gogjMsrvn7he2wHTqNVb5p6RUrwmr8XFBA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.11.0.tgz", + "integrity": "sha512-iG4iMOHixc2EpzqRV+pv7o3GgmU2dNYEMkvKwSaQO/vMZURakwSOn/EYJ6OIRFYOque1qorzIBvrytPIQB3YzQ==", "dev": true, "requires": { - "debug": "^3.1.0", + "debug": "^4.1.0", "extract-zip": "^1.6.6", "https-proxy-agent": "^2.2.1", "mime": "^2.0.3", - "progress": "^2.0.0", + "progress": "^2.0.1", "proxy-from-env": "^1.0.0", "rimraf": "^2.6.1", - "ws": "^5.1.1" + "ws": "^6.1.0" }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -3690,9 +3697,9 @@ "dev": true }, "progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.1.tgz", - "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true } } @@ -4532,12 +4539,6 @@ "has-flag": "^3.0.0" } }, - "sync-exec": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.6.2.tgz", - "integrity": "sha1-cX0izFPwzh3vVZQ2LzqJouu5EQU=", - "dev": true - }, "syntax-error": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", @@ -4695,7 +4696,8 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true + "dev": true, + "optional": true }, "typedarray": { "version": "0.0.6", @@ -4923,9 +4925,9 @@ "optional": true }, "v8flags": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.0.2.tgz", - "integrity": "sha512-6sgSKoFw1UpUPd3cFdF7QGnrH6tDeBgW1F3v9gy8gLY0mlbiBXq8soy8aQpY6xeeCjH5K+JvC62Acp7gtl7wWA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", + "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==", "dev": true, "requires": { "homedir-polyfill": "^1.0.1" @@ -5018,9 +5020,9 @@ "dev": true }, "ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.3.tgz", + "integrity": "sha512-tbSxiT+qJI223AP4iLfQbkbxkwdFcneYinM2+x46Gx2wgvbaOMO36czfdfVUBRTHvzAMRhDd98sA5d/BuWbQdg==", "dev": true, "requires": { "async-limiter": "~1.0.0" diff --git a/lib/js/package.json b/lib/js/package.json index b5c0238a1c5..8b16d95b825 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -12,14 +12,14 @@ "license": "Apache-2.0", "devDependencies": { "browserify": "^16.2.3", - "grunt": "^1.0.2", - "grunt-cli": "^1.2.0", + "grunt": "^1.0.3", + "grunt-cli": "^1.3.2", "grunt-contrib-concat": "^1.0.1", "grunt-contrib-jshint": "^1.0.0", - "grunt-contrib-qunit": "^3.0.1", + "grunt-contrib-qunit": "^3.1.0", "grunt-contrib-uglify": "^1.0.1", "grunt-jsdoc": "^2.2.1", - "grunt-shell-spawn": "^0.3.10", + "grunt-shell-spawn": "^0.3.12", "jslint": "^0.12.0", "node-int64": "^0.4.0" }, diff --git a/lib/ts/Makefile.am b/lib/ts/Makefile.am index 9ea20a4ab8d..62ea2069f16 100644 --- a/lib/ts/Makefile.am +++ b/lib/ts/Makefile.am @@ -21,10 +21,38 @@ # We call install twice to work around npm issues # if HAVE_NPM -SUBDIRS = test -check-local: all +prereq: $(NPM) install || $(NPM) install $(NPM) list + +check-local: prereq all ./node_modules/.bin/grunt + +doc: prereq + ./node_modules/.bin/grunt jsdoc + endif + +clean-local: + $(RM) -r dist + $(RM) -r doc + $(RM) -r node_modules + $(RM) -r test/build/ + $(RM) -r test/gen-*/ + +dist-hook: + $(RM) -r $(distdir)/dist/ + $(RM) -r $(distdir)/doc/ + $(RM) -r $(distdir)/node_modules/ + $(RM) -r $(distdir)/test/build/ + $(RM) -r $(distdir)/test/gen-*/ + +EXTRA_DIST = \ + coding_standards.md \ + Gruntfile.js \ + package.json \ + package-lock.json \ + thrift.d.ts \ + tsconfig.json + diff --git a/lib/ts/package-lock.json b/lib/ts/package-lock.json index a7dec9dd364..8d0a7ff2f3c 100644 --- a/lib/ts/package-lock.json +++ b/lib/ts/package-lock.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "1.0.0", + "version": "0.13.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -26,9 +26,9 @@ "dev": true }, "@types/qunit": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/@types/qunit/-/qunit-2.5.3.tgz", - "integrity": "sha512-b9xNH1wBOnY+yiCT2DiAC0yi7GCF5g6whiAFA/dpd9RtL/Jn2XR7e4yyeAQwH3TUeF00zikmYqYxS0K8+EKTKQ==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@types/qunit/-/qunit-2.5.4.tgz", + "integrity": "sha512-VHi2lEd4/zp8OOouf43JXGJJ5ZxHvdLL1dU0Yakp6Iy73SjpuXl7yjwAwmh1qhTv8krDgHteSwaySr++uXX9YQ==", "dev": true }, "JSONStream": { @@ -1300,7 +1300,7 @@ }, "es6-promisify": { "version": "5.0.0", - "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { @@ -1927,14 +1927,14 @@ } }, "grunt-contrib-qunit": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-3.0.1.tgz", - "integrity": "sha512-s994+ipKwc+oUUIWaGIw1soyID4pExSGMd/cHQN5h0p8KbIjR1Le3ZC3giSDDKXtZFE0i+Obf0uIjNvjftX2Cw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-qunit/-/grunt-contrib-qunit-3.1.0.tgz", + "integrity": "sha512-mdk8UltH6mxCD63E0hTXMAts42DOi4z4bBBrY7qnuHiShflMF7IueSMYe0zWaZ2dO8mgujh57Zfny2EbigJhRg==", "dev": true, "requires": { "eventemitter2": "^5.0.1", "p-each-series": "^1.0.0", - "puppeteer": "1.7.0" + "puppeteer": "^1.11.0" }, "dependencies": { "eventemitter2": { @@ -2048,13 +2048,12 @@ } }, "grunt-shell-spawn": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/grunt-shell-spawn/-/grunt-shell-spawn-0.3.10.tgz", - "integrity": "sha1-gbuNRX7EfTGCqH1jCO+EXd+5SI8=", + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/grunt-shell-spawn/-/grunt-shell-spawn-0.3.12.tgz", + "integrity": "sha512-TprZct92sQ4M2Q92piaeLsCrx4+gq/ageuxjZsRG6cglKt7x7rGA3YHt8D30+G789v+/pw4l0tDjEyrkMXx2tA==", "dev": true, "requires": { - "grunt": ">=0.4.x", - "sync-exec": "~0.6.2" + "grunt": ">=0.4.x" } }, "gzip-size": { @@ -2719,9 +2718,9 @@ } }, "json-int64": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-0.0.3.tgz", - "integrity": "sha512-6nAloOVry+klkifPKPqFLX/FI4L95oBfu5T5vKKt4L8gik8cy80wOtzC+kM1Vh2r60QdDqDr7u/XVk6VlfueEg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-1.0.0.tgz", + "integrity": "sha512-yrTg9swToElhEPETLMdZkEzDhbXLs+cxkw/b2rglMPOBlM1DE0utH1EReSMLcnpYJk5iUvD12r0fP2/xHitF5Q==", "requires": { "node-int64": "0.4.0" } @@ -2970,7 +2969,7 @@ }, "marked": { "version": "0.3.19", - "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==" }, "maxmin": { @@ -3353,12 +3352,12 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" }, "os-tmpdir": { "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, "osenv": { @@ -3659,25 +3658,25 @@ "dev": true }, "puppeteer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.7.0.tgz", - "integrity": "sha512-f+1DxKHPqce6CXUBz2eVO2WcATeVeQSOPG9GYaGObEZDCiCEUwG+gogjMsrvn7he2wHTqNVb5p6RUrwmr8XFBA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-1.11.0.tgz", + "integrity": "sha512-iG4iMOHixc2EpzqRV+pv7o3GgmU2dNYEMkvKwSaQO/vMZURakwSOn/EYJ6OIRFYOque1qorzIBvrytPIQB3YzQ==", "dev": true, "requires": { - "debug": "^3.1.0", + "debug": "^4.1.0", "extract-zip": "^1.6.6", "https-proxy-agent": "^2.2.1", "mime": "^2.0.3", - "progress": "^2.0.0", + "progress": "^2.0.1", "proxy-from-env": "^1.0.0", "rimraf": "^2.6.1", - "ws": "^5.1.1" + "ws": "^6.1.0" }, "dependencies": { "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -3881,7 +3880,7 @@ "dependencies": { "underscore": { "version": "1.6.0", - "resolved": "http://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" } } @@ -4419,12 +4418,6 @@ "has-flag": "^3.0.0" } }, - "sync-exec": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.6.2.tgz", - "integrity": "sha1-cX0izFPwzh3vVZQ2LzqJouu5EQU=", - "dev": true - }, "syntax-error": { "version": "1.4.0", "resolved": "http://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", @@ -4574,9 +4567,9 @@ "dev": true }, "typescript": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", - "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", + "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", "dev": true }, "uglify-js": { @@ -4631,7 +4624,7 @@ }, "underscore": { "version": "1.8.3", - "resolved": "http://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" }, "underscore-contrib": { @@ -4644,7 +4637,7 @@ "dependencies": { "underscore": { "version": "1.6.0", - "resolved": "http://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" } } @@ -4910,9 +4903,9 @@ "dev": true }, "ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.3.tgz", + "integrity": "sha512-tbSxiT+qJI223AP4iLfQbkbxkwdFcneYinM2+x46Gx2wgvbaOMO36czfdfVUBRTHvzAMRhDd98sA5d/BuWbQdg==", "dev": true, "requires": { "async-limiter": "~1.0.0" diff --git a/lib/ts/package.json b/lib/ts/package.json index 1a1ccdc85a8..eda1c0aea55 100644 --- a/lib/ts/package.json +++ b/lib/ts/package.json @@ -1,24 +1,33 @@ { "name": "thrift", - "version": "1.0.0", + "version": "0.13.0", + "description": "Thrift is a software framework for scalable cross-language services development.", + "author": { + "name": "Apache Thrift Developers", + "email": "dev@thrift.apache.org" + }, + "bugs": "https://issues.apache.org/jira/projects/THRIFT/summary", + "homepage": "http://thrift.apache.org", + "repository": "https://github.com/apache/thrift", + "license": "Apache-2.0", "devDependencies": { "@types/node-int64": "^0.4.29", "@types/phantom": "^3.2.5", - "@types/qunit": "^2.5.3", + "@types/qunit": "^2.5.4", "browserify": "^16.2.3", "bufferutil": "^4.0.1", - "grunt": "^1.0.2", + "grunt": "^1.0.3", "grunt-cli": "^1.2.0", "grunt-contrib-concat": "^1.0.1", "grunt-contrib-jshint": "^1.0.0", - "grunt-contrib-qunit": "^3.0.1", + "grunt-contrib-qunit": "^3.1.0", "grunt-contrib-uglify": "^1.0.1", "grunt-jsdoc": "^2.2.1", - "grunt-shell-spawn": "^0.3.10", + "grunt-shell-spawn": "^0.3.12", "jslint": "^0.12.0", "node-int64": "^0.4.0", "phantom": "^6.0.3", - "typescript": "^3.2.2" + "typescript": "^3.2.4" }, "dependencies": { "bufferutil": "^4.0.1", From 29f7f8f32f6bf88751e0ef3c8e3f2fba1aac5b8f Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 26 Jan 2019 09:15:19 -0500 Subject: [PATCH 183/756] THRIFT-4743: remove cpp compiler plugin support to simplify the project --- .travis.yml | 9 - Makefile.am | 8 - appveyor.yml | 8 +- build/cmake/DefineOptions.cmake | 9 +- build/cmake/DefinePlatformSpecifc.cmake | 8 - compiler/cpp/CMakeLists.txt | 94 +--- compiler/cpp/Makefile.am | 131 +---- compiler/cpp/README.md | 4 +- compiler/cpp/src/Makefile.am | 48 -- compiler/cpp/src/thrift/common.cc | 4 - compiler/cpp/src/thrift/logging.cc | 5 - compiler/cpp/src/thrift/main.cc | 21 - compiler/cpp/src/thrift/parse/t_const_value.h | 9 - compiler/cpp/src/thrift/parse/t_scope.h | 9 - compiler/cpp/src/thrift/plugin/Makefile.am | 47 -- compiler/cpp/src/thrift/plugin/plugin.cc | 511 ------------------ compiler/cpp/src/thrift/plugin/plugin.h | 44 -- compiler/cpp/src/thrift/plugin/plugin.thrift | 207 ------- .../cpp/src/thrift/plugin/plugin_output.cc | 455 ---------------- .../cpp/src/thrift/plugin/plugin_output.h | 38 -- compiler/cpp/src/thrift/plugin/type_util.h | 95 ---- compiler/cpp/test/CMakeLists.txt | 46 +- compiler/cpp/test/Makefile.am | 32 -- compiler/cpp/test/cpp_plugin_test.cmake | 45 -- compiler/cpp/test/cpp_plugin_test.sh | 27 - compiler/cpp/test/plugin/conversion_test.cc | 498 ----------------- compiler/cpp/test/plugin/cpp_plugin.cc | 43 -- compiler/cpp/test/plugin_stability_test.sh | 32 -- configure.ac | 16 - lib/Makefile.am | 3 - lib/cpp/Makefile.am | 4 - 31 files changed, 36 insertions(+), 2474 deletions(-) delete mode 100644 compiler/cpp/src/thrift/plugin/Makefile.am delete mode 100644 compiler/cpp/src/thrift/plugin/plugin.cc delete mode 100644 compiler/cpp/src/thrift/plugin/plugin.h delete mode 100644 compiler/cpp/src/thrift/plugin/plugin.thrift delete mode 100644 compiler/cpp/src/thrift/plugin/plugin_output.cc delete mode 100644 compiler/cpp/src/thrift/plugin/plugin_output.h delete mode 100644 compiler/cpp/src/thrift/plugin/type_util.h delete mode 100644 compiler/cpp/test/cpp_plugin_test.cmake delete mode 100755 compiler/cpp/test/cpp_plugin_test.sh delete mode 100644 compiler/cpp/test/plugin/conversion_test.cc delete mode 100644 compiler/cpp/test/plugin/cpp_plugin.cc delete mode 100755 compiler/cpp/test/plugin_stability_test.sh diff --git a/.travis.yml b/.travis.yml index aecdd130ac0..4a399a60e82 100644 --- a/.travis.yml +++ b/.travis.yml @@ -130,15 +130,6 @@ jobs: - JOB="CMake" - BUILD_ARG="-DCMAKE_BUILD_TYPE=Release" - # C++ specific options: compiler plug-in, threading model - - script: build/docker/run.sh - env: - - JOB="C++ (Std Thread) and Plugin" - - SCRIPT="cmake.sh" - - BUILD_LIBS="CPP TESTING TUTORIALS" - - BUILD_ARG="-DWITH_PLUGIN=ON -DWITH_PYTHON=OFF -DWITH_C_GLIB=OFF -DWITH_JAVA=OFF -DWITH_HASKELL=OFF" - - BUILD_ENV="-e CC=clang -e CXX=clang++" - # ------------------------- phase: dist ------------------------- - script: build/docker/run.sh env: diff --git a/Makefile.am b/Makefile.am index 104d3705a49..1f2d4836ab0 100755 --- a/Makefile.am +++ b/Makefile.am @@ -19,15 +19,7 @@ ACLOCAL_AMFLAGS = -I ./aclocal -if WITH_PLUGIN -# To enable bootstrap, build order is lib/cpp -> compiler -> others -SUBDIRS = lib/cpp compiler/cpp lib -if WITH_TESTS -SUBDIRS += lib/cpp/test -endif -else SUBDIRS = compiler/cpp lib -endif if WITH_TESTS SUBDIRS += test diff --git a/appveyor.yml b/appveyor.yml index 6cbabf1eed9..2dee45fa882 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -45,7 +45,7 @@ environment: PYTHON_VERSION: 3.6 QT_VERSION: 5.10 ZLIB_VERSION: 1.2.11 - DISABLED_TESTS: StressTestNonBlocking + DISABLED_TESTS: (concurrency_test|StressTestNonBlocking) - PROFILE: MSVC2015 PLATFORM: x86 @@ -56,18 +56,18 @@ environment: PYTHON_VERSION: 3.5 QT_VERSION: 5.8 ZLIB_VERSION: 1.2.8 - DISABLED_TESTS: StressTestNonBlocking + DISABLED_TESTS: (concurrency_test|StressTestNonBlocking) APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - PROFILE: MINGW PLATFORM: x64 CONFIGURATION: RelWithDebInfo - DISABLED_TESTS: StressTestNonBlocking + DISABLED_TESTS: (concurrency_test|StressTestNonBlocking) - PROFILE: CYGWIN PLATFORM: x64 CONFIGURATION: RelWithDebInfo - DISABLED_TESTS: (ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest|StressTestNonBlocking) + DISABLED_TESTS: (concurrency_test|ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest|StressTestNonBlocking) install: - cd %APPVEYOR_BUILD_FOLDER% diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 2c8ea505031..eea0b2915e1 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -79,8 +79,6 @@ if(WITH_CPP) endif() CMAKE_DEPENDENT_OPTION(BUILD_CPP "Build C++ library" ON "BUILD_LIBRARIES;WITH_CPP" OFF) -CMAKE_DEPENDENT_OPTION(WITH_PLUGIN "Build compiler plugin support" OFF - "BUILD_COMPILER;BUILD_CPP" OFF) # C GLib option(WITH_C_GLIB "Build C (GLib) Thrift library" ON) @@ -149,14 +147,13 @@ message(STATUS "----------------------------------------------------------") message(STATUS "Thrift version: ${thrift_VERSION} (${thrift_VERSION_MAJOR}.${thrift_VERSION_MINOR}.${thrift_VERSION_PATCH})") message(STATUS "Thrift package version: ${PACKAGE_VERSION}") message(STATUS "Build configuration Summary") -if (UNIX) - message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") -endif () message(STATUS " Build compiler: ${BUILD_COMPILER}") -message(STATUS " Build compiler plugin support: ${WITH_PLUGIN}") message(STATUS " Build libraries: ${BUILD_LIBRARIES}") message(STATUS " Build tests: ${BUILD_TESTING}") MESSAGE_DEP(HAVE_COMPILER "Disabled because BUILD_THRIFT=OFF and no valid THRIFT_COMPILER is given") +if (UNIX) + message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") +endif () message(STATUS " Language libraries:") message(STATUS " Build as3 library: ${BUILD_AS3}") MESSAGE_DEP(WITH_AS3 "Disabled by WITH_AS3=OFF") diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index 298780c97e2..b87fd6524c2 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -94,11 +94,3 @@ endif() if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-register") endif() - -# Building WITH_PLUGIN requires boost memory operations, for now, and gcc >= 4.8 -if (WITH_PLUGIN) - if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8") - message(SEND_ERROR "Thrift compiler plug-in support is not possible with older gcc ( < 4.8 ) compiler") - endif() -endif() - diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt index 372cbab75fe..6f7ae5d7e42 100644 --- a/compiler/cpp/CMakeLists.txt +++ b/compiler/cpp/CMakeLists.txt @@ -106,51 +106,10 @@ THRIFT_ADD_COMPILER(xsd "Enable compiler for XSD" ON) # we also add the current binary directory for generated files include_directories(${CMAKE_CURRENT_BINARY_DIR} src) -if(NOT DEFINED WITH_PLUGIN OR NOT ${WITH_PLUGIN}) - list(APPEND thrift-compiler_SOURCES ${compiler_core}) -endif() +list(APPEND thrift-compiler_SOURCES ${compiler_core}) add_executable(thrift-compiler ${thrift-compiler_SOURCES}) -if(${WITH_PLUGIN}) - add_executable(thrift-bootstrap ${compiler_core} - src/thrift/main.cc - src/thrift/audit/t_audit.cpp - src/thrift/generate/t_cpp_generator.cc - ) - target_link_libraries(thrift-bootstrap parse) - - set(PLUGIN_GEN_SOURCES - ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_types.h - ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_types.cpp - ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_constants.h - ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin/plugin_constants.cpp - ) - - file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin) - add_custom_command(OUTPUT ${PLUGIN_GEN_SOURCES} - DEPENDS thrift-bootstrap src/thrift/plugin/plugin.thrift - COMMAND thrift-bootstrap -gen cpp - -out ${CMAKE_CURRENT_BINARY_DIR}/thrift/plugin - ${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/plugin/plugin.thrift - ) - - include_directories(../../lib/cpp/src) - - include(ThriftMacros) - ADD_LIBRARY_THRIFT(thriftc - ${compiler_core} - ${PLUGIN_GEN_SOURCES} - src/thrift/logging.cc - src/thrift/plugin/plugin_output.cc - src/thrift/plugin/plugin.cc - ) - TARGET_INCLUDE_DIRECTORIES_THRIFT(thriftc PUBLIC ${Boost_INCLUDE_DIRS}) - TARGET_LINK_LIBRARIES_THRIFT_AGAINST_THRIFT_LIBRARY(thriftc thrift PUBLIC) - target_compile_definitions(thrift-compiler PUBLIC THRIFT_ENABLE_PLUGIN) - LINK_AGAINST_THRIFT_LIBRARY(thrift-compiler thriftc) -endif() - set_target_properties(thrift-compiler PROPERTIES RUNTIME_OUTPUT_DIRECTORY bin/) set_target_properties(thrift-compiler PROPERTIES OUTPUT_NAME thrift) @@ -158,57 +117,6 @@ target_link_libraries(thrift-compiler parse) install(TARGETS thrift-compiler DESTINATION bin) -if(${WITH_PLUGIN}) - # Install the headers - install(FILES - "src/thrift/common.h" - "src/thrift/globals.h" - "src/thrift/logging.h" - "src/thrift/main.h" - "src/thrift/platform.h" - "${CMAKE_BINARY_DIR}/compiler/cpp/thrift/version.h" - DESTINATION "${INCLUDE_INSTALL_DIR}/thrift") - install(FILES - "src/thrift/audit/t_audit.h" - DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/audit") - install(FILES - "src/thrift/generate/t_generator.h" - "src/thrift/generate/t_generator_registry.h" - "src/thrift/generate/t_html_generator.h" - "src/thrift/generate/t_oop_generator.h" - DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/generate") - install(FILES - "src/thrift/parse/t_base_type.h" - "src/thrift/parse/t_const.h" - "src/thrift/parse/t_const_value.h" - "src/thrift/parse/t_container.h" - "src/thrift/parse/t_doc.h" - "src/thrift/parse/t_enum.h" - "src/thrift/parse/t_enum_value.h" - "src/thrift/parse/t_field.h" - "src/thrift/parse/t_function.h" - "src/thrift/parse/t_list.h" - "src/thrift/parse/t_map.h" - "src/thrift/parse/t_program.h" - "src/thrift/parse/t_scope.h" - "src/thrift/parse/t_service.h" - "src/thrift/parse/t_set.h" - "src/thrift/parse/t_struct.h" - "src/thrift/parse/t_typedef.h" - "src/thrift/parse/t_type.h" - DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/parse") - install(FILES - "src/thrift/plugin/plugin.h" - "src/thrift/plugin/plugin_output.h" - "src/thrift/plugin/type_util.h" - DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/plugin") -if(MSVC) - install(FILES - "src/thrift/windows/config.h" - DESTINATION "${INCLUDE_INSTALL_DIR}/thrift/windows") -endif() -endif() - if(BUILD_TESTING) add_subdirectory(test) endif() diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am index 087f6bdbd03..9b5742fe946 100644 --- a/compiler/cpp/Makefile.am +++ b/compiler/cpp/Makefile.am @@ -23,12 +23,7 @@ AUTOMAKE_OPTIONS = subdir-objects -# Note on why we have src/thrift and src/thrift/plugin directories: -# Since Automake supports only one set of BUILT_SOURCES per file and does not allow -# SUBDIRS built before BUILT_SOURCES, we end up separate Makefile.am for each source -# code generation, i.e. lex-yacc and Thrift, to achieve stable parallel make. - -SUBDIRS = src src/thrift/plugin . +SUBDIRS = src . if WITH_TESTS SUBDIRS += test endif @@ -37,46 +32,40 @@ bin_PROGRAMS = thrift thrift_OBJDIR = obj -plugin_gen = src/thrift/plugin/plugin_types.h \ - src/thrift/plugin/plugin_types.cpp \ - src/thrift/plugin/plugin_constants.h \ - src/thrift/plugin/plugin_constants.cpp - -compiler_core = src/thrift/common.h \ +thrift_SOURCES = src/thrift/audit/t_audit.cpp \ + src/thrift/audit/t_audit.h \ src/thrift/common.cc \ + src/thrift/common.h \ src/thrift/generate/t_generator.cc \ + src/thrift/generate/t_generator.h \ src/thrift/generate/t_generator_registry.h \ + src/thrift/generate/t_html_generator.h \ + src/thrift/generate/t_oop_generator.h \ src/thrift/globals.h \ - src/thrift/platform.h \ src/thrift/logging.h \ - src/thrift/parse/t_doc.h \ - src/thrift/parse/t_type.h \ + src/thrift/main.cc \ + src/thrift/main.h \ + src/thrift/parse/parse.cc \ src/thrift/parse/t_base_type.h \ + src/thrift/parse/t_const.h \ + src/thrift/parse/t_const_value.h \ + src/thrift/parse/t_container.h \ + src/thrift/parse/t_doc.h \ src/thrift/parse/t_enum.h \ src/thrift/parse/t_enum_value.h \ - src/thrift/parse/t_typedef.h \ - src/thrift/parse/t_typedef.cc \ - src/thrift/parse/t_container.h \ - src/thrift/parse/t_list.h \ - src/thrift/parse/t_set.h \ - src/thrift/parse/t_map.h \ - src/thrift/parse/t_struct.h \ src/thrift/parse/t_field.h \ - src/thrift/parse/t_service.h \ src/thrift/parse/t_function.h \ + src/thrift/parse/t_list.h \ + src/thrift/parse/t_map.h \ src/thrift/parse/t_program.h \ src/thrift/parse/t_scope.h \ - src/thrift/parse/t_const.h \ - src/thrift/parse/t_const_value.h \ - src/thrift/parse/parse.cc \ - src/thrift/generate/t_generator.h \ - src/thrift/generate/t_oop_generator.h \ - src/thrift/generate/t_html_generator.h - -thrift_SOURCES = src/thrift/main.h \ - src/thrift/main.cc \ - src/thrift/audit/t_audit.cpp \ - src/thrift/audit/t_audit.h + src/thrift/parse/t_service.h \ + src/thrift/parse/t_set.h \ + src/thrift/parse/t_struct.h \ + src/thrift/parse/t_type.h \ + src/thrift/parse/t_typedef.cc \ + src/thrift/parse/t_typedef.h \ + src/thrift/platform.h # Specific client generator source thrift_SOURCES += src/thrift/generate/t_as3_generator.cc \ @@ -115,76 +104,6 @@ thrift_CPPFLAGS = -I$(srcdir)/src thrift_CXXFLAGS = -Wall -Wextra -pedantic -Werror thrift_LDADD = @LEXLIB@ src/thrift/libparse.a -if !WITH_PLUGIN -thrift_SOURCES += $(compiler_core) -else - -lib_LTLIBRARIES = libthriftc.la - -thrift_CPPFLAGS += -DTHRIFT_ENABLE_PLUGIN=1 -thrift_LDADD += libthriftc.la - -nodist_libthriftc_la_SOURCES = $(plugin_gen) -libthriftc_la_SOURCES = $(compiler_core) \ - src/thrift/plugin/type_util.h \ - src/thrift/plugin/plugin.h \ - src/thrift/plugin/plugin.cc \ - src/thrift/plugin/plugin_output.h \ - src/thrift/plugin/plugin_output.cc \ - src/thrift/plugin/plugin.thrift \ - src/thrift/logging.cc - - -libthriftc_la_CPPFLAGS = -I$(srcdir)/src -Isrc -I$(top_builddir)/lib/cpp/src -DTHRIFT_ENABLE_PLUGIN=1 -libthriftc_la_CXXFLAGS = -Wall -Wextra -pedantic -libthriftc_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la - -include_thriftdir = $(includedir)/thrift -include_thrift_HEADERS = src/thrift/common.h \ - src/thrift/globals.h \ - src/thrift/logging.h \ - src/thrift/main.h \ - src/thrift/platform.h \ - src/thrift/version.h - -include_auditdir = $(include_thriftdir)/windows -include_audit_HEADERS = src/thrift/audit/t_audit.h - -include_generatedir = $(include_thriftdir)/generate -include_generate_HEADERS = src/thrift/generate/t_generator.h \ - src/thrift/generate/t_generator_registry.h \ - src/thrift/generate/t_oop_generator.h \ - src/thrift/generate/t_html_generator.h - -include_parsedir = $(include_thriftdir)/parse -include_parse_HEADERS = src/thrift/parse/t_service.h \ - src/thrift/parse/t_program.h \ - src/thrift/parse/t_field.h \ - src/thrift/parse/t_scope.h \ - src/thrift/parse/t_typedef.h \ - src/thrift/parse/t_set.h \ - src/thrift/parse/t_const_value.h \ - src/thrift/parse/t_enum_value.h \ - src/thrift/parse/t_const.h \ - src/thrift/parse/t_list.h \ - src/thrift/parse/t_map.h \ - src/thrift/parse/t_container.h \ - src/thrift/parse/t_base_type.h \ - src/thrift/parse/t_enum.h \ - src/thrift/parse/t_function.h \ - src/thrift/parse/t_type.h \ - src/thrift/parse/t_doc.h \ - src/thrift/parse/t_struct.h - -include_plugindir = $(include_thriftdir)/plugin -include_plugin_HEADERS = src/thrift/plugin/plugin.h \ - src/thrift/plugin/type_util.h \ - src/thrift/plugin/plugin_output.h - -include_windowsdir = $(include_thriftdir)/windows -include_windows_HEADERS = src/thrift/windows/config.h -endif - WINDOWS_DIST = \ compiler.sln \ compiler.vcxproj \ @@ -198,9 +117,9 @@ EXTRA_DIST = \ $(WINDOWS_DIST) clean-local: - $(RM) version.h $(plugin_gen) + $(RM) version.h src/thrift/main.cc: src/thrift/version.h style-local: - $(CPPSTYLE_CMD) + $(CPPSTYLE_CMD) diff --git a/compiler/cpp/README.md b/compiler/cpp/README.md index 355191293ec..5c04cd869db 100644 --- a/compiler/cpp/README.md +++ b/compiler/cpp/README.md @@ -67,7 +67,7 @@ brew install bison ``` mkdir cmake-build && cd cmake-build -cmake -G "Xcode" -DWITH_PLUGIN=OFF .. +cmake -G "Xcode" .. cmake --build . ``` @@ -107,7 +107,7 @@ cmake --build . ``` mkdir cmake-vs cd cmake-vs -cmake -G "Visual Studio 15 2017" -DWITH_PLUGIN=OFF .. +cmake -G "Visual Studio 15 2017" .. ``` - Now open the folder cmake-vs using Visual Studio. diff --git a/compiler/cpp/src/Makefile.am b/compiler/cpp/src/Makefile.am index bc2c5cbacea..b3139e21db6 100644 --- a/compiler/cpp/src/Makefile.am +++ b/compiler/cpp/src/Makefile.am @@ -37,51 +37,3 @@ thrift_libparse_a_SOURCES = thrift/thrifty.yy \ clean-local: $(RM) thrift/thriftl.cc thrift/thrifty.cc thrift/thrifty.h thrift/thrifty.hh - -if WITH_PLUGIN -noinst_PROGRAMS = thrift/thrift-bootstrap - -thrift_thrift_bootstrap_SOURCES = \ - thrift/common.h \ - thrift/common.cc \ - thrift/audit/t_audit.h \ - thrift/audit/t_audit.cpp \ - thrift/generate/t_generator.cc \ - thrift/generate/t_generator_registry.h \ - thrift/globals.h \ - thrift/platform.h \ - thrift/logging.h \ - thrift/parse/t_doc.h \ - thrift/parse/t_type.h \ - thrift/parse/t_base_type.h \ - thrift/parse/t_enum.h \ - thrift/parse/t_enum_value.h \ - thrift/parse/t_typedef.h \ - thrift/parse/t_typedef.cc \ - thrift/parse/t_container.h \ - thrift/parse/t_list.h \ - thrift/parse/t_set.h \ - thrift/parse/t_map.h \ - thrift/parse/t_struct.h \ - thrift/parse/t_field.h \ - thrift/parse/t_service.h \ - thrift/parse/t_function.h \ - thrift/parse/t_program.h \ - thrift/parse/t_scope.h \ - thrift/parse/t_const.h \ - thrift/parse/t_const_value.h \ - thrift/parse/parse.cc \ - thrift/generate/t_generator.h \ - thrift/generate/t_oop_generator.h \ - thrift/generate/t_html_generator.h \ - thrift/windows/config.h \ - thrift/version.h \ - thrift/generate/t_cpp_generator.cc \ - thrift/main.h \ - thrift/main.cc - -main.cc: version.h - -thrift_thrift_bootstrap_CXXFLAGS = -Wall -Wextra -pedantic -thrift_thrift_bootstrap_LDADD = @LEXLIB@ thrift/libparse.a -endif diff --git a/compiler/cpp/src/thrift/common.cc b/compiler/cpp/src/thrift/common.cc index 3a2b9d359ec..fb1832daf7e 100644 --- a/compiler/cpp/src/thrift/common.cc +++ b/compiler/cpp/src/thrift/common.cc @@ -57,10 +57,6 @@ void clearGlobals() { delete g_type_double; } -/** - * Those are not really needed for plugins but causes link errors without - */ - /** * The location of the last parsed doctext comment. */ diff --git a/compiler/cpp/src/thrift/logging.cc b/compiler/cpp/src/thrift/logging.cc index f821f5fc563..4811c4ef179 100644 --- a/compiler/cpp/src/thrift/logging.cc +++ b/compiler/cpp/src/thrift/logging.cc @@ -17,17 +17,12 @@ * under the License. */ -/** - * Logging functions copied from main.cc to avoid link errors for plugins - */ - #include "thrift/logging.h" #include "thrift/globals.h" #include #include #include -// TODO: make plugins accept log options from main compiler int g_debug = 0; int g_warn = 1; int g_verbose = 0; diff --git a/compiler/cpp/src/thrift/main.cc b/compiler/cpp/src/thrift/main.cc index eddbd56b03e..adcab83c19e 100644 --- a/compiler/cpp/src/thrift/main.cc +++ b/compiler/cpp/src/thrift/main.cc @@ -53,9 +53,6 @@ #include "thrift/parse/t_scope.h" #include "thrift/generate/t_generator.h" #include "thrift/audit/t_audit.h" -#ifdef THRIFT_ENABLE_PLUGIN -#include "thrift/plugin/plugin_output.h" -#endif #include "thrift/version.h" @@ -1007,26 +1004,8 @@ void generate(t_program* program, const vector& generator_strings) { t_generator* generator = t_generator_registry::get_generator(program, *iter); if (generator == NULL) { -#ifdef THRIFT_ENABLE_PLUGIN - switch (plugin_output::delegateToPlugin(program, *iter)) { - case plugin_output::PLUGIN_NOT_FOUND: - pwarning(1, "Unable to get a generator for \"%s\".\n", iter->c_str()); - g_generator_failure = true; - break; - case plugin_output::PLUGIN_FAILURE: - pwarning(1, "Plugin generator for \"%s\" failed.\n", iter->c_str()); - g_generator_failure = true; - break; - case plugin_output::PLUGIN_SUCCEESS: - break; - default: - assert(false); - break; - } -#else pwarning(1, "Unable to get a generator for \"%s\".\n", iter->c_str()); g_generator_failure = true; -#endif } else if (generator) { generator->validate_input(); pverbose("Generating \"%s\"\n", iter->c_str()); diff --git a/compiler/cpp/src/thrift/parse/t_const_value.h b/compiler/cpp/src/thrift/parse/t_const_value.h index 6a114cf169b..e5ecc1d6df6 100644 --- a/compiler/cpp/src/thrift/parse/t_const_value.h +++ b/compiler/cpp/src/thrift/parse/t_const_value.h @@ -26,11 +26,6 @@ #include #include -namespace plugin_output { -template -void convert(From*, To&); -} - /** * A const value is something parsed that could be a map, set, list, struct * or whatever. @@ -204,10 +199,6 @@ class t_const_value { t_enum* enum_; t_const_value_type valType_; - - // to read enum_ - template - friend void plugin_output::convert(From*, To&); }; #endif diff --git a/compiler/cpp/src/thrift/parse/t_scope.h b/compiler/cpp/src/thrift/parse/t_scope.h index 6f160a5cc8b..137af88329e 100644 --- a/compiler/cpp/src/thrift/parse/t_scope.h +++ b/compiler/cpp/src/thrift/parse/t_scope.h @@ -33,11 +33,6 @@ #include "thrift/parse/t_list.h" #include "thrift/parse/t_set.h" -namespace plugin_output { -template -void convert(From*, To&); -} - /** * This represents a variable scope used for looking up predefined types and * services. Typically, a scope is associated with a t_program. Scopes are not @@ -179,10 +174,6 @@ class t_scope { // Map of names to services std::map services_; - - // to list map entries - template - friend void plugin_output::convert(From*, To&); }; #endif diff --git a/compiler/cpp/src/thrift/plugin/Makefile.am b/compiler/cpp/src/thrift/plugin/Makefile.am deleted file mode 100644 index e84cdbd9c0c..00000000000 --- a/compiler/cpp/src/thrift/plugin/Makefile.am +++ /dev/null @@ -1,47 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# -# -# Contains some contributions under the Thrift Software License. -# Please see doc/old-thrift-license.txt in the Thrift distribution for -# details. - -AUTOMAKE_OPTIONS = subdir-objects - -if WITH_PLUGIN -plugin_gen = plugin_types.h \ - plugin_types.cpp \ - plugin_constants.h \ - plugin_constants.cpp - -BUILT_SOURCES = $(plugin_gen) -gen.stamp: plugin.thrift $(top_builddir)/compiler/cpp/src/thrift/thrift-bootstrap - @$(RM) -f gen.tmp - @touch gen.tmp - $(top_builddir)/compiler/cpp/src/thrift/thrift-bootstrap -gen cpp -out . $< - @mv -f gen.tmp $@ - -$(plugin_gen): gen.stamp - @if test -f $@; then :; else \ - $(RM) -f gen.stamp; \ - $(MAKE) $(AM_MAKEFLAGS) gen.stamp; \ - fi - -clean-local: - $(RM) version.h windows/version.h $(plugin_gen) -endif diff --git a/compiler/cpp/src/thrift/plugin/plugin.cc b/compiler/cpp/src/thrift/plugin/plugin.cc deleted file mode 100644 index 7c4c432b099..00000000000 --- a/compiler/cpp/src/thrift/plugin/plugin.cc +++ /dev/null @@ -1,511 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "thrift/plugin/plugin.h" - -#ifdef _WIN32 -#include -#include -#endif - -#include -#include -#include -#include - -#include -#include - -#include "thrift/generate/t_generator.h" -#include "thrift/plugin/type_util.h" -#include "thrift/protocol/TBinaryProtocol.h" -#include "thrift/transport/TBufferTransports.h" -#include "thrift/transport/TFDTransport.h" -#include "thrift/plugin/plugin_types.h" - -namespace apache { -namespace thrift { -namespace plugin { - -using apache::thrift::protocol::TBinaryProtocol; -using apache::thrift::transport::TFDTransport; -using apache::thrift::transport::TFramedTransport; - -#define THRIFT_CONVERT_FORWARD(from_type) \ - template <> \ - typename ToType::type* convert_forward(const from_type& from) - -#define THRIFT_CONVERT_COMPLETE_DECL(from_type) \ - template <> \ - void convert(const from_type& from, ToType::type* to) - -#define THRIFT_CONVERT_UNARY_DECL(from_type) \ - template <> \ - typename ToType::type* convert(const from_type& from) - -#define THRIFT_CONVERSION_DECL(from_type) \ - THRIFT_CONVERT_FORWARD(from_type); \ - THRIFT_CONVERT_COMPLETE_DECL(from_type); \ - THRIFT_CONVERT_UNARY_DECL(from_type) - -#define THRIFT_CONVERT_COMPLETE(from_type) \ - THRIFT_CONVERSION_DECL(from_type) { \ - ToType::type* to = convert_forward(from); \ - convert(from, to); \ - return to; \ - } \ - THRIFT_CONVERT_COMPLETE_DECL(from_type) - -#define THRIFT_CONVERSION(from_type, ...) \ - THRIFT_CONVERT_FORWARD(from_type) { \ - (void)from; \ - return new ToType::type(__VA_ARGS__); \ - } \ - THRIFT_CONVERT_COMPLETE(from_type) - -#define THRIFT_ASSIGN_DOC() \ - do { \ - if (from.__isset.doc) \ - to->set_doc(from.doc); \ - } while (0) - -#define THRIFT_ASSIGN_ANNOTATIONS() \ - THRIFT_ASSIGN_DOC(); \ - do { \ - if (from.__isset.annotations) \ - to->annotations_ = from.annotations; \ - } while (0) - -#define THRIFT_ASSIGN_METADATA() \ - do { \ - to->set_name(from.metadata.name); \ - if (from.metadata.__isset.doc) \ - to->set_doc(from.metadata.doc); \ - if (from.metadata.__isset.annotations) \ - to->annotations_ = from.metadata.annotations; \ - } while (0) - -::t_program* g_program = 0; - -template -struct TypeCache { - C* operator[](const int64_t& k) { - typename std::map::iterator it = cache.find(k); - if (it != cache.end()) { - return it->second; - } else { - typename std::map::const_iterator cit = source->find(k); - if (cit == source->end()) { - throw ThriftPluginError("Type not found"); - } - return (cache)[k] = convert_forward(cit->second); - } - } - - void compileAll() { - boost::for_each(*source | boost::adaptors::map_keys, - std::bind(&TypeCache::compile, this, std::placeholders::_1)); - } - - std::map const* source; - - void clear() { - source = nullptr ; - cache.clear() ; - } - -protected: - std::map cache; - -private: - void compile(const int64_t& k) { - typename std::map::const_iterator cit = source->find(k); - if (cit == source->end()) { - throw ThriftPluginError("Type not found "); - } - convert(cit->second, (*this)[k]); - } -}; -std::map g_program_cache; -TypeCache< ::t_type, t_type> g_type_cache; -TypeCache< ::t_const, t_const> g_const_cache; -TypeCache< ::t_service, t_service> g_service_cache; - -void clear_global_cache() { - g_type_cache.clear(); - g_const_cache.clear(); - g_service_cache.clear(); -} - -void set_global_cache(const TypeRegistry& from) { - g_type_cache.source = &from.types; - g_const_cache.source = &from.constants; - g_service_cache.source = &from.services; - - g_type_cache.compileAll(); - g_const_cache.compileAll(); - g_service_cache.compileAll(); -} - -template -T* resolve_type(int64_t name) { - return reinterpret_cast(g_type_cache[name]); -} - -::t_const* resolve_const(int64_t name) { - return g_const_cache[name]; -} - -::t_service* resolve_service(int64_t name) { - return g_service_cache[name]; -} - -THRIFT_CONVERT_FORWARD(t_base_type) { -#define T_BASETYPE_CASE(type) \ - case t_base::TYPE_##type: \ - t = ::t_base_type::TYPE_##type; \ - break - - ::t_base_type::t_base t = ::t_base_type::TYPE_VOID; - bool is_binary = false; - switch (from.value) { - T_BASETYPE_CASE(VOID); - T_BASETYPE_CASE(STRING); - T_BASETYPE_CASE(BOOL); - T_BASETYPE_CASE(I8); - T_BASETYPE_CASE(I16); - T_BASETYPE_CASE(I32); - T_BASETYPE_CASE(I64); - T_BASETYPE_CASE(DOUBLE); - case t_base::TYPE_BINARY: - t = ::t_base_type::TYPE_STRING; - is_binary = true; - break; - } - ::t_base_type* to = new ::t_base_type(from.metadata.name, t); - to->set_binary(is_binary); - return to; -#undef T_BASETYPE_CASE -} -THRIFT_CONVERT_COMPLETE(t_base_type) { - THRIFT_ASSIGN_METADATA(); -} - -THRIFT_CONVERT_FORWARD(t_typedef) { - ::t_typedef* to; - if (from.forward) { - to = new ::t_typedef(g_program_cache[from.metadata.program_id], from.symbolic, true); - } else { - to = new ::t_typedef(g_program_cache[from.metadata.program_id], - resolve_type< ::t_type>(from.type), from.symbolic); - } - return to; -} -THRIFT_CONVERT_COMPLETE(t_typedef) { - THRIFT_ASSIGN_METADATA(); -} -THRIFT_CONVERSION(t_enum_value, from.name, from.value) { - assert(to); - THRIFT_ASSIGN_ANNOTATIONS(); -} -THRIFT_CONVERSION(t_enum, g_program_cache[from.metadata.program_id]) { - assert(to); - THRIFT_ASSIGN_METADATA(); - boost::for_each(from.constants | boost::adaptors::transformed(convert), - std::bind(&::t_enum::append, to, std::placeholders::_1)); -} -THRIFT_CONVERSION(t_list, resolve_type< ::t_type>(from.elem_type)) { - assert(to); - THRIFT_ASSIGN_METADATA(); - if (from.__isset.cpp_name) - to->set_cpp_name(from.cpp_name); -} -THRIFT_CONVERSION(t_set, resolve_type< ::t_type>(from.elem_type)) { - assert(to); - THRIFT_ASSIGN_METADATA(); - if (from.__isset.cpp_name) - to->set_cpp_name(from.cpp_name); -} -THRIFT_CONVERSION(t_map, - resolve_type< ::t_type>(from.key_type), - resolve_type< ::t_type>(from.val_type)) { - assert(to); - THRIFT_ASSIGN_METADATA(); - if (from.__isset.cpp_name) - to->set_cpp_name(from.cpp_name); -} -THRIFT_CONVERSION(t_const_value, ) { -#define T_CONST_VALUE_CASE(type) \ - if (from.__isset.type##_val) \ - to->set_##type(from.type##_val) - - assert(to); - if (from.__isset.map_val) { - to->set_map(); - for (std::map::const_iterator it = from.map_val.begin(); - it != from.map_val.end(); it++) { - to->add_map(convert(it->first), convert(it->second)); - } - } else if (from.__isset.list_val) { - to->set_list(); - boost::for_each(from.list_val | boost::adaptors::transformed(&convert), - std::bind(&::t_const_value::add_list, to, std::placeholders::_1)); - } else - T_CONST_VALUE_CASE(string); - else T_CONST_VALUE_CASE(integer); - else T_CONST_VALUE_CASE(double); - else if (from.__isset.const_identifier_val) { - to->set_identifier(from.const_identifier_val.identifier_val) ; - to->set_enum(resolve_type< ::t_enum>(from.const_identifier_val.enum_val)) ; - } - -#undef T_CONST_VALUE_CASE -} -THRIFT_CONVERSION(t_field, resolve_type< ::t_type>(from.type), from.name, from.key) { - assert(to); - THRIFT_ASSIGN_ANNOTATIONS(); - to->set_reference(from.reference); - to->set_req(static_cast< ::t_field::e_req>(from.req)); - if (from.__isset.value) { - to->set_value(convert(from.value)); - } -} -THRIFT_CONVERSION(t_struct, g_program_cache[from.metadata.program_id]) { - assert(to); - THRIFT_ASSIGN_METADATA(); - to->set_union(from.is_union); - to->set_xception(from.is_xception); - boost::for_each(from.members | boost::adaptors::transformed(convert), - std::bind(&::t_struct::append, to, std::placeholders::_1)); -} -THRIFT_CONVERSION(t_const, - resolve_type< ::t_type>(from.type), - from.name, - convert(from.value)) { - assert(to); - THRIFT_ASSIGN_DOC(); -} - -THRIFT_CONVERSION(t_function, - resolve_type< ::t_type>(from.returntype), - from.name, - resolve_type< ::t_struct>(from.arglist), - resolve_type< ::t_struct>(from.xceptions), - from.is_oneway) { - assert(to); - THRIFT_ASSIGN_DOC(); -} - -THRIFT_CONVERSION(t_service, g_program_cache[from.metadata.program_id]) { - assert(to); - assert(from.metadata.program_id); - assert(g_program_cache[from.metadata.program_id]); - THRIFT_ASSIGN_METADATA(); - - boost::for_each(from.functions | boost::adaptors::transformed(convert), - std::bind(&::t_service::add_function, to, std::placeholders::_1)); - - if (from.__isset.extends_) - to->set_extends(resolve_service(from.extends_)); -} - -THRIFT_CONVERT_FORWARD(t_type) { -#define T_TYPE_CASE_FW_T(case, type) \ - if (from.__isset.case##_val) \ - return convert_forward(from.case##_val) -#define T_TYPE_CASE_FW(case) T_TYPE_CASE_FW_T(case, t_##case) - - T_TYPE_CASE_FW(base_type); - T_TYPE_CASE_FW(typedef); - T_TYPE_CASE_FW(enum); - T_TYPE_CASE_FW(struct); - T_TYPE_CASE_FW_T(xception, t_struct); - T_TYPE_CASE_FW(list); - T_TYPE_CASE_FW(set); - T_TYPE_CASE_FW(map); - T_TYPE_CASE_FW(service); - throw ThriftPluginError("Invalid data: Type union has no value."); -#undef T_TYPE_CASE_FW_T -#undef T_TYPE_CASE_FW -} -THRIFT_CONVERT_COMPLETE(t_type) { -#define T_TYPE_CASE_T(case, type) \ - else if (from.__isset.case##_val) \ - convert(from.case##_val, reinterpret_cast< ::type*>(to)) -#define T_TYPE_CASE(case) T_TYPE_CASE_T(case, t_##case) - - if (false) { - } - T_TYPE_CASE(base_type); - T_TYPE_CASE(typedef); - T_TYPE_CASE(enum); - T_TYPE_CASE(struct); - T_TYPE_CASE_T(xception, t_struct); - T_TYPE_CASE(list); - T_TYPE_CASE(set); - T_TYPE_CASE(map); - T_TYPE_CASE(service); - else { - throw ThriftPluginError("Invalid data: Type union has no value."); - } -#undef T_TYPE_CASE_T -#undef T_TYPE_CASE -} - -THRIFT_CONVERSION(t_scope, ) { - assert(to); -#define T_SCOPE_RESOLVE(type, name, a) \ - for (std::vector::const_iterator it = from.name##s.begin(); it != from.name##s.end(); \ - it++) { \ - ::t_##type* t = resolve_##type a(*it); \ - to->add_##name(t->get_name(), t); \ - } - T_SCOPE_RESOLVE(type, type, < ::t_type>); - T_SCOPE_RESOLVE(const, constant, ); - T_SCOPE_RESOLVE(service, service, ); -#undef T_SCOPE_RESOLVE -} - -THRIFT_CONVERT_FORWARD(t_program) { - ::t_program* to = new ::t_program(from.path, from.name); - for (std::vector::const_iterator it = from.includes.begin(); it != from.includes.end(); - it++) { - to->add_include(convert_forward(*it)); - } - g_program_cache[from.program_id] = to; - return to; -} -THRIFT_CONVERT_COMPLETE(t_program) { - assert(to); - g_program = to; - convert(from.scope, to->scope()); - THRIFT_ASSIGN_DOC(); - - to->set_out_path(from.out_path, from.out_path_is_absolute); - - boost::for_each(from.typedefs | boost::adaptors::transformed(&resolve_type< ::t_typedef>), - std::bind(&::t_program::add_typedef, to, std::placeholders::_1)); - boost::for_each(from.enums | boost::adaptors::transformed(&resolve_type< ::t_enum>), - std::bind(&::t_program::add_enum, to, std::placeholders::_1)); - for (std::vector::const_iterator it = from.objects.begin(); it != from.objects.end(); - it++) { - ::t_struct* t2 = resolve_type< ::t_struct>(*it); - if (t2->is_xception()) { - to->add_xception(t2); - } else { - to->add_struct(t2); - } - } - boost::for_each(from.consts | boost::adaptors::transformed(&resolve_const), - std::bind(&::t_program::add_const, to, std::placeholders::_1)); - boost::for_each(from.services | boost::adaptors::transformed(&resolve_service), - std::bind(&::t_program::add_service, to, std::placeholders::_1)); - - for (std::vector::const_iterator it = from.includes.begin(); it != from.includes.end(); - it++) { - convert(*it, g_program_cache[it->program_id]); - } - std::for_each(from.c_includes.begin(), from.c_includes.end(), - std::bind(&::t_program::add_c_include, to, std::placeholders::_1)); - std::for_each(from.cpp_includes.begin(), from.cpp_includes.end(), - std::bind(&::t_program::add_cpp_include, to, std::placeholders::_1)); - for (std::map::const_iterator it = from.namespaces.begin(); - it != from.namespaces.end(); it++) { - to->set_namespace(it->first, it->second); - } - - to->set_include_prefix(from.include_prefix); - to->set_namespace(from.namespace_); -} - -int GeneratorPlugin::exec(int, char* []) { -#ifdef _WIN32 - _setmode(fileno(stdin), _O_BINARY); -#endif - std::shared_ptr transport( - new TFramedTransport(std::make_shared(fileno(stdin)))); - TBinaryProtocol proto(transport); - GeneratorInput input; - try { - input.read(&proto); - } catch (std::exception& err) { - std::cerr << "Error while receiving plugin data: " << err.what() << std::endl; - return -1; - } - initGlobals(); - ::t_program* p = g_program = convert_forward(input.program); - set_global_cache(input.type_registry); - convert(input.program, p); - - int ret = generate(p, input.parsed_options); - clearGlobals(); - - return ret; -} - -::t_const_value::t_const_value_type const_value_case(const t_const_value& v) { - if (v.__isset.map_val) - return ::t_const_value::CV_MAP; - if (v.__isset.list_val) - return ::t_const_value::CV_LIST; - if (v.__isset.string_val) - return ::t_const_value::CV_STRING; - if (v.__isset.integer_val) - return ::t_const_value::CV_INTEGER; - if (v.__isset.double_val) - return ::t_const_value::CV_DOUBLE; - if (v.__isset.const_identifier_val) - return ::t_const_value::CV_IDENTIFIER; - throw ThriftPluginError("Unknown const value type"); -} - -bool t_const_value::operator<(const t_const_value& that) const { - ::t_const_value::t_const_value_type t1 = const_value_case(*this); - ::t_const_value::t_const_value_type t2 = const_value_case(that); - if (t1 != t2) - return t1 < t2; - switch (t1) { - case ::t_const_value::CV_INTEGER: - return integer_val < that.integer_val; - case ::t_const_value::CV_DOUBLE: - return double_val < that.double_val; - case ::t_const_value::CV_STRING: - return string_val < that.string_val; - case ::t_const_value::CV_MAP: - if (that.map_val.empty()) - return false; - else if (map_val.empty()) - return true; - else - return map_val.begin()->first < that.map_val.begin()->first; - case ::t_const_value::CV_LIST: - if (that.list_val.empty()) - return false; - else if (list_val.empty()) - return true; - else - return list_val.front() < that.list_val.front(); - case ::t_const_value::CV_IDENTIFIER: - return integer_val < that.integer_val; - } - throw ThriftPluginError("Unknown const value type"); -} -} -} -} diff --git a/compiler/cpp/src/thrift/plugin/plugin.h b/compiler/cpp/src/thrift/plugin/plugin.h deleted file mode 100644 index 705cd41ffae..00000000000 --- a/compiler/cpp/src/thrift/plugin/plugin.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef T_PLUGIN_PLUGIN_H -#define T_PLUGIN_PLUGIN_H - -#include "thrift/Thrift.h" - -class t_program; - -namespace apache { -namespace thrift { -namespace plugin { - -struct ThriftPluginError : public apache::thrift::TException { - ThriftPluginError(const std::string& msg) : apache::thrift::TException(msg) {} -}; - -class GeneratorPlugin { -public: - int exec(int argc, char* argv[]); - virtual int generate(::t_program*, const std::map&) = 0; -}; -} -} -} - -#endif diff --git a/compiler/cpp/src/thrift/plugin/plugin.thrift b/compiler/cpp/src/thrift/plugin/plugin.thrift deleted file mode 100644 index 6d98f99558c..00000000000 --- a/compiler/cpp/src/thrift/plugin/plugin.thrift +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -namespace as3 org.apache.thrift.plugin -namespace cpp apache.thrift.plugin -namespace csharp Thrift.Plugin -namespace d thrift.plugin -namespace delphi Thrift.Plugin -namespace erl thrift.plugin -namespace go thrift -namespace haxe org.apache.thrift.plugin -namespace hs Thrift.Plugin -namespace java org.apache.thrift.plugin -namespace ocaml Thrift -namespace perl Thrift.Plugin -namespace php thrift.plugin -namespace py thrift.plugin -namespace rb Thrift - -typedef i64 t_program_id -typedef i64 t_type_id -typedef i64 t_const_id -typedef i64 t_service_id - -enum t_base { - TYPE_VOID - TYPE_STRING - TYPE_BOOL - TYPE_I8 - TYPE_I16 - TYPE_I32 - TYPE_I64 - TYPE_DOUBLE - TYPE_BINARY -} - -struct TypeMetadata { - 1: required string name - 2: required t_program_id program_id - 99: optional map annotations - 100: optional string doc -} - -struct t_base_type { - 1: required TypeMetadata metadata - 2: required t_base value -} - -struct t_list { - 1: required TypeMetadata metadata - 2: optional string cpp_name - 3: required t_type_id elem_type -} - -struct t_set { - 1: required TypeMetadata metadata - 2: optional string cpp_name - 3: required t_type_id elem_type -} - -struct t_map { - 1: required TypeMetadata metadata - 2: optional string cpp_name - 3: required t_type_id key_type - 4: required t_type_id val_type -} - -struct t_typedef { - 1: required TypeMetadata metadata - 2: required t_type_id type - 3: required string symbolic - 4: required bool forward -} - -struct t_enum_value { - 1: required string name - 2: required i32 value - 99: optional map annotations - 100: optional string doc -} -struct t_enum { - 1: required TypeMetadata metadata - 2: required list constants -} - -enum Requiredness { - T_REQUIRED = 0 - T_OPTIONAL = 1 - T_OPT_IN_REQ_OUT = 2 -} - -struct t_const_identifier_value { - 1: required string identifier_val - 2: required t_type_id enum_val -} - -union t_const_value { - 1: optional map map_val - 2: optional list list_val - 3: optional string string_val - 4: optional i64 integer_val - 5: optional double double_val - 8: optional t_const_identifier_value const_identifier_val -} - -struct t_const { - 1: required string name - 2: required t_type_id type - 3: required t_const_value value - 100: optional string doc -} -struct t_field { - 1: required string name - 2: required t_type_id type - 3: required i32 key - 4: required Requiredness req - 5: optional t_const_value value - 10: required bool reference - 99: optional map annotations - 100: optional string doc -} -struct t_struct { - 1: required TypeMetadata metadata - 2: required list members - 3: required bool is_union - 4: required bool is_xception -} -struct t_function { - 1: required string name - 2: required t_type_id returntype - 3: required t_type_id arglist - 4: required t_type_id xceptions - 5: required bool is_oneway - 100: optional string doc -} -struct t_service { - 1: required TypeMetadata metadata - 2: required list functions - 3: optional t_service_id extends_ -} -union t_type { - 1: optional t_base_type base_type_val - 2: optional t_typedef typedef_val - 3: optional t_enum enum_val - 4: optional t_struct struct_val - 5: optional t_struct xception_val - 6: optional t_list list_val - 7: optional t_set set_val - 8: optional t_map map_val - 9: optional t_service service_val -} -struct t_scope { - 1: required list types - 2: required list constants - 3: required list services -} - -struct TypeRegistry { - 1: required map types - 2: required map constants - 3: required map services -} - -struct t_program { - 1: required string name - 2: required t_program_id program_id - 3: required string path - 4: required string namespace_ - 5: required string out_path - 6: required bool out_path_is_absolute - 8: required list includes - 9: required string include_prefix - 10: required t_scope scope - - 11: required list typedefs - 12: required list enums - 13: required list consts - 14: required list objects - 15: required list services - - 16: required map namespaces - 17: required list cpp_includes - 18: required list c_includes - 100: optional string doc -} - -struct GeneratorInput { - 1: required t_program program - 2: required TypeRegistry type_registry - 3: required map parsed_options -} diff --git a/compiler/cpp/src/thrift/plugin/plugin_output.cc b/compiler/cpp/src/thrift/plugin/plugin_output.cc deleted file mode 100644 index f8223dedc2a..00000000000 --- a/compiler/cpp/src/thrift/plugin/plugin_output.cc +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifdef _WIN32 -#include -#include -#include -#include -#define THRIFT_POPEN(cmd) _popen(cmd, "wb") -#define THRIFT_PCLOSE _pclose -#else -#define THRIFT_POPEN(cmd) popen(cmd, "w") -#define THRIFT_PCLOSE pclose -#endif - -#include "thrift/plugin/plugin_output.h" - -#include -#include -#include - -#include "thrift/generate/t_generator.h" -#include "thrift/plugin/plugin.h" -#include "thrift/plugin/type_util.h" -#include "thrift/protocol/TBinaryProtocol.h" -#include "thrift/transport/TBufferTransports.h" -#include "thrift/transport/TFDTransport.h" - -#include "thrift/plugin/plugin_types.h" - -#include - -namespace plugin_output { - -template -typename apache::thrift::plugin::ToType::type convert(From* from) { - typename apache::thrift::plugin::ToType::type to; - convert(from, to); - return to; -} - -using apache::thrift::protocol::TBinaryProtocol; -using std::make_shared; -using std::shared_ptr; -using apache::thrift::transport::TFDTransport; -using apache::thrift::transport::TFramedTransport; - -using namespace apache::thrift; - -#define THRIFT_CONVERSION_N(from_type, to_type) \ - template <> \ - void convert(from_type * from, to_type & to) -#define THRIFT_CONVERSION(type) THRIFT_CONVERSION_N(::type, plugin::type) - -#define THRIFT_ASSIGN_N(from_name, to_name, prefix) \ - do { \ - if (from) \ - to.__set_##to_name(prefix(from->from_name)); \ - } while (0) - -#define THRIFT_ASSIGN(name) THRIFT_ASSIGN_N(get_##name(), name, ) -#define THRIFT_ASSIGN_CONVERT(type, from_name, to_name) \ - do { \ - if (from && from->from_name) { \ - to.__set_##to_name(convert(from->from_name)); \ - } \ - } while (0) - -#define THRIFT_ASSIGN_OPT(name) \ - do { \ - if (from->has_##name()) \ - THRIFT_ASSIGN(name); \ - } while (0) - -#define THRIFT_ASSIGN_LIST_N(type, from_name, to_name) \ - do { \ - if (from && !from->from_name.empty()) { \ - std::transform(from->from_name.begin(), \ - from->from_name.end(), \ - std::back_inserter(to.to_name), \ - convert< ::type>); \ - } \ - } while (0) - -#define THRIFT_ASSIGN_METADATA() convert(reinterpret_cast(from), to.metadata) - -// a generator of sequential unique identifiers for addresses -- so -// that the TypeCache below can use those IDs instead of -// addresses. This allows GeneratorInput's various -// t_{program,type,etc}_id types to be dense consecutively-numbered -// integers, instead of large random-seeming integers. -// -// Furthermore, this allows GeneratorInput to be deterministic (no -// addresses, so no pseudo-randomness) and that means reproducibility -// of output. -const int64_t ONE_MILLION = 1000 * 1000; -class id_generator { -public: - id_generator() : addr2id_(), next_id_(ONE_MILLION) {} - - void clear() { - addr2id_.clear() ; - next_id_ = ONE_MILLION ; - } - - int64_t gensym(const int64_t addr) { - if (!addr) return 0L ; - std::map::iterator it = addr2id_.find(addr); - if (it != addr2id_.end()) return it->second ; - int64_t id = next_id_++ ; - addr2id_.insert(std::make_pair(addr, id)) ; - return id ; - } - - std::map addr2id_ ; - int64_t next_id_ ; -} ; - -// To avoid multiple instances of same type, t_type, t_const and t_service are stored in one place -// and referenced by ID. -template -struct TypeCache { - typedef typename plugin::ToType::type to_type; - id_generator idgen ; - std::map cache; - - template - int64_t store(T2* t) { - intptr_t addr = reinterpret_cast(t); - if (!addr) return 0L ; - - int64_t id = idgen.gensym(addr) ; - if (cache.end() != cache.find(id)) return id ; - - // HACK: fake resolve for recursive type - cache.insert(std::make_pair(id, to_type())); - // overwrite with true value - cache[id] = convert(t); - return id ; - } - - void clear() { cache.clear() ; idgen.clear(); } -}; - -template -int64_t store_type(T* t); - -#define T_STORE(type) \ - TypeCache type##_cache; \ - template <> \ - plugin::t_##type##_id store_type(t_##type * t) { \ - return type##_cache.store(t); \ - } -T_STORE(type) -T_STORE(const) -T_STORE(service) -#undef T_STORE -// this id_generator is for gensymm-ing t_program_id -id_generator program_cache ; - -#define THRIFT_ASSIGN_ID_N(t, from_name, to_name) \ - do { \ - if (from && from->from_name) \ - to.__set_##to_name(store_type(from->from_name)); \ - } while (0) - -#define THRIFT_ASSIGN_ID(name) THRIFT_ASSIGN_ID_N(t_type, get_##name(), name) - -#define THRIFT_ASSIGN_LIST_ID(t, name) \ - do { \ - if (from && !from->get_##name##s().empty()) { \ - std::transform(from->get_##name##s().begin(), \ - from->get_##name##s().end(), \ - std::back_inserter(to.name##s), \ - &store_type); \ - } \ - } while (0) - -THRIFT_CONVERSION_N(::t_type, plugin::TypeMetadata) { - to.program_id = program_cache.gensym(reinterpret_cast(from->get_program())); - THRIFT_ASSIGN_N(annotations_, annotations, ); - if (from->has_doc()) { - to.__set_doc(from->get_doc()); - } - THRIFT_ASSIGN(name); -} - -THRIFT_CONVERSION(t_typedef) { - THRIFT_ASSIGN_METADATA(); - THRIFT_ASSIGN_ID(type); - THRIFT_ASSIGN(symbolic); - THRIFT_ASSIGN_N(is_forward_typedef(), forward, ); -} - -THRIFT_CONVERSION(t_enum_value) { - THRIFT_ASSIGN_OPT(doc); - THRIFT_ASSIGN(name); - THRIFT_ASSIGN(value); -} - -THRIFT_CONVERSION(t_enum) { - THRIFT_ASSIGN_METADATA(); - THRIFT_ASSIGN_LIST_N(t_enum_value, get_constants(), constants); -} - -THRIFT_CONVERSION(t_const_value) { - switch (from->get_type()) { - case t_const_value::CV_INTEGER: - THRIFT_ASSIGN_N(get_integer(), integer_val, ); - break; - case t_const_value::CV_DOUBLE: - THRIFT_ASSIGN_N(get_double(), double_val, ); - break; - case t_const_value::CV_STRING: - THRIFT_ASSIGN_N(get_string(), string_val, ); - break; - case t_const_value::CV_IDENTIFIER: - if (from) { - apache::thrift::plugin::t_const_identifier_value cidval ; - if (from->enum_) - cidval.__set_enum_val(store_type(from->enum_)); - cidval.__set_identifier_val(from->get_identifier()); - to.__set_const_identifier_val(cidval) ; - } - break; - case t_const_value::CV_MAP: - to.__isset.map_val = true; - if (from && !from->get_map().empty()) { - for (std::map< ::t_const_value*, ::t_const_value*>::const_iterator it - = from->get_map().begin(); - it != from->get_map().end(); - it++) { - to.map_val.insert(std::make_pair(convert(it->first), convert(it->second))); - } - } - break; - case t_const_value::CV_LIST: - to.__isset.list_val = true; - THRIFT_ASSIGN_LIST_N(t_const_value, get_list(), list_val); - break; - default: - throw plugin::ThriftPluginError("const value has no value"); - } -} -THRIFT_CONVERSION(t_const) { - THRIFT_ASSIGN_OPT(doc); - THRIFT_ASSIGN(name); - THRIFT_ASSIGN_ID(type); - THRIFT_ASSIGN_CONVERT(t_const_value, get_value(), value); -} -THRIFT_CONVERSION(t_field) { - THRIFT_ASSIGN_OPT(doc); - THRIFT_ASSIGN(name); - THRIFT_ASSIGN(key); - THRIFT_ASSIGN_N(get_req(), req, (plugin::Requiredness::type)); - THRIFT_ASSIGN(reference); - THRIFT_ASSIGN_ID(type); - THRIFT_ASSIGN_CONVERT(t_const_value, get_value(), value); -} -THRIFT_CONVERSION(t_struct) { - THRIFT_ASSIGN_METADATA(); - THRIFT_ASSIGN_LIST_N(t_field, get_members(), members); - THRIFT_ASSIGN_N(is_union(), is_union, ); - THRIFT_ASSIGN_N(is_xception(), is_xception, ); -} -THRIFT_CONVERSION(t_function) { - THRIFT_ASSIGN_OPT(doc); - THRIFT_ASSIGN(name); - THRIFT_ASSIGN_ID(returntype); - THRIFT_ASSIGN_N(is_oneway(), is_oneway, ); - THRIFT_ASSIGN_ID(arglist); - THRIFT_ASSIGN_ID(xceptions); -} - -THRIFT_CONVERSION(t_list) { - THRIFT_ASSIGN_METADATA(); - THRIFT_ASSIGN_OPT(cpp_name); - THRIFT_ASSIGN_ID(elem_type); -} -THRIFT_CONVERSION(t_set) { - THRIFT_ASSIGN_METADATA(); - THRIFT_ASSIGN_OPT(cpp_name); - THRIFT_ASSIGN_ID(elem_type); -} -THRIFT_CONVERSION(t_map) { - THRIFT_ASSIGN_METADATA(); - THRIFT_ASSIGN_OPT(cpp_name); - THRIFT_ASSIGN_ID(key_type); - THRIFT_ASSIGN_ID(val_type); -} - -THRIFT_CONVERSION(t_service) { - THRIFT_ASSIGN_METADATA(); - THRIFT_ASSIGN_LIST_N(t_function, get_functions(), functions); - THRIFT_ASSIGN_ID_N(t_service, get_extends(), extends_); -} - -THRIFT_CONVERSION(t_base_type) { - THRIFT_ASSIGN_METADATA(); - if (from->is_binary()) { - to.value = plugin::t_base::TYPE_BINARY; - } else { - switch (from->get_base()) { -#define T_BASETYPE_CASE(name) \ - case t_base_type::TYPE_##name: \ - to.value = plugin::t_base::TYPE_##name; \ - break - T_BASETYPE_CASE(VOID); - T_BASETYPE_CASE(STRING); - T_BASETYPE_CASE(BOOL); - T_BASETYPE_CASE(I8); - T_BASETYPE_CASE(I16); - T_BASETYPE_CASE(I32); - T_BASETYPE_CASE(I64); - T_BASETYPE_CASE(DOUBLE); - default: - throw plugin::ThriftPluginError("Base type union has no value"); - break; -#undef T_BASETYPE_CASE - } - } -} -THRIFT_CONVERSION(t_type) { -#define T_CONVERT_UNION_N(name, type) \ - else if (from->is_##name()) { \ - to.__isset.name##_val = true; \ - convert(reinterpret_cast< ::type*>(from), to.name##_val); \ - } -#define T_CONVERT_UNION(name) T_CONVERT_UNION_N(name, t_##name) - if (false) { - } - T_CONVERT_UNION(base_type) - T_CONVERT_UNION(typedef) - T_CONVERT_UNION(enum) - T_CONVERT_UNION(struct) - T_CONVERT_UNION_N(xception, t_struct) - T_CONVERT_UNION(list) - T_CONVERT_UNION(set) - T_CONVERT_UNION(map) - T_CONVERT_UNION(service) - else { - throw plugin::ThriftPluginError("Type union has no value"); - } -#undef T_CONVERT_UNION_N -#undef T_CONVERT_UNION -} - -THRIFT_CONVERSION(t_scope) { -#define T_SCOPE_ASSIGN(name, type) \ - boost::copy(from->name##s_ | boost::adaptors::map_values \ - | boost::adaptors::transformed(&store_type), \ - std::back_inserter(to.name##s)) - T_SCOPE_ASSIGN(type, t_type); - T_SCOPE_ASSIGN(constant, t_const); - T_SCOPE_ASSIGN(service, t_service); -#undef T_SCOPE_ASSIGN -} - -void get_global_cache(plugin::TypeRegistry& reg) { - reg.types = type_cache.cache; - reg.constants = const_cache.cache; - reg.services = service_cache.cache; -} - -void clear_global_cache() { - type_cache.clear(); - const_cache.clear(); - service_cache.clear(); - program_cache.clear() ; -} - -THRIFT_CONVERSION(t_program) { - THRIFT_ASSIGN_CONVERT(t_scope, scope(), scope); - THRIFT_ASSIGN(path); - THRIFT_ASSIGN(out_path); - THRIFT_ASSIGN(name); - THRIFT_ASSIGN(include_prefix); - THRIFT_ASSIGN(cpp_includes); - THRIFT_ASSIGN(c_includes); - THRIFT_ASSIGN(namespaces); - THRIFT_ASSIGN_N(is_out_path_absolute(), out_path_is_absolute, ); - THRIFT_ASSIGN_N(get_namespace(), namespace_, ); - THRIFT_ASSIGN_LIST_ID(t_type, typedef); - THRIFT_ASSIGN_LIST_ID(t_type, enum); - THRIFT_ASSIGN_LIST_ID(t_type, object); - THRIFT_ASSIGN_LIST_ID(t_const, const); - THRIFT_ASSIGN_LIST_ID(t_service, service); - THRIFT_ASSIGN_LIST_N(t_program, get_includes(), includes); - to.program_id = program_cache.gensym(reinterpret_cast(from)); -} - -PluginDelegateResult delegateToPlugin(t_program* program, const std::string& options) { - std::string language; - std::map parsed_options; - t_generator::parse_options(options, language, parsed_options); - std::string cmd = "thrift-gen-"; - if (language.find_first_not_of("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-0123456789") - != std::string::npos) { - std::cerr << "Invalid language name" << std::endl; - return PLUGIN_FAILURE; - } - cmd.append(language); - FILE* fd = THRIFT_POPEN(cmd.c_str()); - if (fd) { -#ifdef _WIN32 - _setmode(fileno(fd), _O_BINARY); -#endif - shared_ptr transport( - new TFramedTransport(make_shared(fileno(fd)))); - TBinaryProtocol proto(transport); - - plugin::GeneratorInput input; - input.__set_parsed_options(parsed_options); - clear_global_cache(); - convert(program, input.program); - get_global_cache(input.type_registry); - try { - input.write(&proto); - transport->flush(); - } catch (std::exception& err) { - std::cerr << "Error while sending data to plugin: " << err.what() << std::endl; - THRIFT_PCLOSE(fd); - return PLUGIN_FAILURE; - } - - // TODO: be prepared for hang or crash of child process - int ret = THRIFT_PCLOSE(fd); - if (!ret) { - return PLUGIN_SUCCEESS; - } else { - std::cerr << "plugin process returned non zero exit code: " << ret << std::endl; - return PLUGIN_FAILURE; - } - } - clear_global_cache(); - return PLUGIN_NOT_FOUND; -} -} - diff --git a/compiler/cpp/src/thrift/plugin/plugin_output.h b/compiler/cpp/src/thrift/plugin/plugin_output.h deleted file mode 100644 index eab2d1bfcde..00000000000 --- a/compiler/cpp/src/thrift/plugin/plugin_output.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef T_PLUGIN_PLUGIN_OUTPUT_H -#define T_PLUGIN_PLUGIN_OUTPUT_H - -#include - -class t_program; - -namespace plugin_output { - -enum PluginDelegateResult { - PLUGIN_NOT_FOUND, - PLUGIN_FAILURE, - PLUGIN_SUCCEESS, -}; - -PluginDelegateResult delegateToPlugin(t_program* program, const std::string& options); -} - -#endif diff --git a/compiler/cpp/src/thrift/plugin/type_util.h b/compiler/cpp/src/thrift/plugin/type_util.h deleted file mode 100644 index 996b5c66670..00000000000 --- a/compiler/cpp/src/thrift/plugin/type_util.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#ifndef T_PLUGIN_TYPE_UTIL_H -#define T_PLUGIN_TYPE_UTIL_H - -namespace apache { -namespace thrift { -namespace plugin { - -template -struct ToType {}; - -template -typename ToType::type* convert_forward(const From&); - -template -void convert(const From&, To*); - -template -typename ToType::type* convert(const From& from); - -class TypeRegistry; -void set_global_cache(const TypeRegistry&); -void clear_global_cache(); -} -} -} - -// conversion from raw compiler types to plugin wire type -namespace plugin_output { - -template -void convert(From* from, To& to); - -template -typename apache::thrift::plugin::ToType::type convert(From* from); - -void get_global_cache(apache::thrift::plugin::TypeRegistry&); -void clear_global_cache(); -} - -#define THRIFT_TYPE_MAPPING(TYPE) \ - class TYPE; \ - namespace apache { \ - namespace thrift { \ - namespace plugin { \ - class TYPE; \ - template <> \ - struct ToType< ::TYPE> { \ - typedef TYPE type; \ - }; \ - template <> \ - struct ToType { \ - typedef ::TYPE type; \ - }; \ - } \ - } \ - } -THRIFT_TYPE_MAPPING(t_base_type) -THRIFT_TYPE_MAPPING(t_const) -THRIFT_TYPE_MAPPING(t_const_value) -THRIFT_TYPE_MAPPING(t_container) -THRIFT_TYPE_MAPPING(t_doc) -THRIFT_TYPE_MAPPING(t_enum) -THRIFT_TYPE_MAPPING(t_enum_value) -THRIFT_TYPE_MAPPING(t_field) -THRIFT_TYPE_MAPPING(t_function) -THRIFT_TYPE_MAPPING(t_list) -THRIFT_TYPE_MAPPING(t_map) -THRIFT_TYPE_MAPPING(t_program) -THRIFT_TYPE_MAPPING(t_scope) -THRIFT_TYPE_MAPPING(t_service) -THRIFT_TYPE_MAPPING(t_set) -THRIFT_TYPE_MAPPING(t_struct) -THRIFT_TYPE_MAPPING(t_type) -THRIFT_TYPE_MAPPING(t_typedef) -#undef THRIFT_TYPE_MAPPING -#endif diff --git a/compiler/cpp/test/CMakeLists.txt b/compiler/cpp/test/CMakeLists.txt index 373cb78f075..2bc7e9e6910 100644 --- a/compiler/cpp/test/CMakeLists.txt +++ b/compiler/cpp/test/CMakeLists.txt @@ -23,50 +23,6 @@ REQUIRE_BOOST_HEADERS() set(BOOST_COMPONENTS unit_test_framework) REQUIRE_BOOST_LIBRARIES(BOOST_COMPONENTS) -if(${WITH_PLUGIN}) - # Make sure gen-cpp files can be included - include_directories("${CMAKE_CURRENT_BINARY_DIR}") - - set(plugintest_SOURCES - plugin/conversion_test.cc - ) - add_executable(plugintest ${plugintest_SOURCES}) - target_link_libraries(plugintest - thriftc - ${Boost_LIBRARIES} - ) - add_test(NAME PluginUnitTest COMMAND plugintest) - - set(thrift-gen-mycpp_SOURCES - ../src/thrift/generate/t_cpp_generator.cc - plugin/cpp_plugin.cc - ) - add_executable(thrift-gen-mycpp ${thrift-gen-mycpp_SOURCES}) - target_link_libraries(thrift-gen-mycpp thriftc) - - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(BUILDTYPE "Debug") - else() - # RelWithDebInfo generates binaries in "Release" directory too - set(BUILDTYPE "Release") - endif() - - set_directory_properties(PROPERTIES - ADDITIONAL_MAKE_CLEAN_FILES gen-cpp - ADDITIONAL_MAKE_CLEAN_FILES gen-mycpp) - - file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gen-cpp) - file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gen-mycpp) - add_test(NAME PluginIntegrationTest - COMMAND ${CMAKE_COMMAND} - -DTHRIFT_COMPILER=${THRIFT_COMPILER} - -DBINDIR=${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - -DBUILDTYPE=${BUILDTYPE} - -DCURDIR=${CMAKE_CURRENT_BINARY_DIR} - -DSRCDIR=${CMAKE_CURRENT_SOURCE_DIR} - -P ${CMAKE_CURRENT_SOURCE_DIR}/cpp_plugin_test.cmake) -endif() - file(GLOB KEYWORD_SAMPLES "${CMAKE_CURRENT_SOURCE_DIR}/keyword-samples/*.thrift") foreach(LANG ${thrift_compiler_LANGS}) foreach(SAMPLE ${KEYWORD_SAMPLES}) @@ -84,4 +40,4 @@ if(PYTHONINTERP_FOUND) add_test(NAME StalenessCheckTest COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/compiler/staleness_check.py ${THRIFT_COMPILER}) else() message(WARNING "Skipping StalenessCheckTest as there is no python interpreter available.") -endif() \ No newline at end of file +endif() diff --git a/compiler/cpp/test/Makefile.am b/compiler/cpp/test/Makefile.am index b7fc91d359f..96258342407 100644 --- a/compiler/cpp/test/Makefile.am +++ b/compiler/cpp/test/Makefile.am @@ -26,35 +26,3 @@ AUTOMAKE_OPTIONS = subdir-objects serial-tests AM_CPPFLAGS = $(BOOST_CPPFLAGS) -I$(top_srcdir)/compiler/cpp/src AM_LDFLAGS = $(BOOST_LDFLAGS) AM_CXXFLAGS = -Wall -Wextra -pedantic - -if WITH_PLUGIN -check_PROGRAMS = plugintest - -noinst_PROGRAMS = thrift-gen-mycpp - -all-local: thrift-gen-bincat - -AM_CPPFLAGS += -I$(top_srcdir)/lib/cpp/src -I$(top_builddir)/lib/cpp/src - -plugintest_SOURCES = plugin/conversion_test.cc -plugintest_LDADD = $(top_builddir)/compiler/cpp/libthriftc.la - -thrift_gen_mycpp_SOURCES = plugin/cpp_plugin.cc \ - plugin/t_cpp_generator.cc -thrift_gen_mycpp_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/compiler/cpp -I$(top_srcdir)/compiler/cpp/src/generate -thrift_gen_mycpp_LDADD = $(top_builddir)/compiler/cpp/libthriftc.la - -cpp_plugin_test.sh: thrift-gen-mycpp - -thrift-gen-bincat: - cp bincat.sh $@ - chmod 755 $@ - -plugin_stability_test.sh: thrift-gen-bincat - -TESTS = $(check_PROGRAMS) cpp_plugin_test.sh plugin_stability_test.sh - -clean-local: - $(RM) -rf gen-cpp gen-mycpp gen-bincat thrift-gen-bincat - -endif diff --git a/compiler/cpp/test/cpp_plugin_test.cmake b/compiler/cpp/test/cpp_plugin_test.cmake deleted file mode 100644 index fd182818d1b..00000000000 --- a/compiler/cpp/test/cpp_plugin_test.cmake +++ /dev/null @@ -1,45 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -file(MAKE_DIRECTORY ${CURDIR}/gen-cpp) -execute_process(COMMAND ${THRIFT_COMPILER} -r -out ${CURDIR}/gen-cpp -gen cpp ${SRCDIR}/../../../test/Include.thrift) -if(EXITCODE) - message(FATAL_ERROR "FAILED: \"${ARGV}\": \"${EXITCODE}\"") -endif() -if(WIN32) - set(ENV{PATH} "${BINDIR}/${BUILDTYPE};${BINDIR};$ENV{PATH}") -else() - set(ENV{PATH} "${BINDIR}:$ENV{PATH}") -endif() - -file(MAKE_DIRECTORY ${CURDIR}/gen-mycpp) -execute_process(COMMAND ${THRIFT_COMPILER} -r -out ${CURDIR}/gen-mycpp -gen mycpp ${SRCDIR}/../../../test/Include.thrift RESULT_VARIABLE EXITCODE) -if(EXITCODE) - message(FATAL_ERROR "FAILED: \"${EXITCODE}\"") -endif() - -find_program(DIFF diff) -if(DIFF) - execute_process(COMMAND ${DIFF} -urN gen-cpp gen-mycpp RESULT_VARIABLE EXITCODE) - if(EXITCODE) - message(FATAL_ERROR "FAILED: \"${EXITCODE}\"") - endif() -else() - message(WARNING "diff executable is not available. Not validating plugin-generated code.") -endif() diff --git a/compiler/cpp/test/cpp_plugin_test.sh b/compiler/cpp/test/cpp_plugin_test.sh deleted file mode 100755 index ddb2e0a0923..00000000000 --- a/compiler/cpp/test/cpp_plugin_test.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# this file is intended to be invoked by make. -set -e -mkdir -p gen-cpp gen-mycpp -PATH=.:"$PATH" ../thrift -r -out gen-cpp -gen cpp ../../../test/Include.thrift -PATH=.:"$PATH" ../thrift -r -out gen-mycpp -gen mycpp ../../../test/Include.thrift -diff -urN gen-cpp gen-mycpp diff --git a/compiler/cpp/test/plugin/conversion_test.cc b/compiler/cpp/test/plugin/conversion_test.cc deleted file mode 100644 index 3c8d812cfba..00000000000 --- a/compiler/cpp/test/plugin/conversion_test.cc +++ /dev/null @@ -1,498 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "thrift/parse/t_program.h" -#include "thrift/plugin/type_util.h" -#include "thrift/plugin/plugin_types.h" - -#include -#include - -#include -#include -#include - -using namespace apache::thrift; -using namespace boost::unit_test; - -namespace test_data { -#define T_TEST_TYPES \ - BOOST_PP_TUPLE_TO_LIST(14, \ - (program, \ - base_type, \ - enum_value, \ - enum, \ - const_value, \ - const, \ - list, \ - set, \ - map, \ - field, \ - struct, \ - typedef, \ - function, \ - service)) -#define T_DELETE_TESTDATA(r, d, elem) \ - for (std::vector::reverse_iterator it = elem##s.rbegin(); it != elem##s.rend(); it++) \ - delete *it; -#define T_DECL_TESTDATA(r, d, elem) static std::vector< ::t_##elem*> elem##s; -BOOST_PP_LIST_FOR_EACH(T_DECL_TESTDATA, _, T_TEST_TYPES) -#undef T_DECL_TESTDATA - -bool has_data = false; -void cleanup() { - if (has_data) { - has_data = false; - BOOST_PP_LIST_FOR_EACH(T_DELETE_TESTDATA, _, T_TEST_TYPES) - } -} - -void init_programs() { - programs.push_back(new t_program("prog path", "prog_name")); -} - -void init_base_types() { - base_types.push_back(new ::t_base_type("name0", ::t_base_type::TYPE_VOID)); - base_types.push_back(new ::t_base_type("name1", ::t_base_type::TYPE_STRING)); - base_types.push_back(new ::t_base_type("name2", ::t_base_type::TYPE_BOOL)); - base_types.push_back(new ::t_base_type("name3", ::t_base_type::TYPE_I8)); - base_types.push_back(new ::t_base_type("name4", ::t_base_type::TYPE_I16)); - base_types.push_back(new ::t_base_type("name5", ::t_base_type::TYPE_I32)); - base_types.push_back(new ::t_base_type("name6", ::t_base_type::TYPE_I64)); - base_types.push_back(new ::t_base_type("name7", ::t_base_type::TYPE_DOUBLE)); -} - -void init_const_values() { - const_values.push_back(new t_const_value(42)); - const_values.push_back(new t_const_value("foo")); - { - t_const_value* x = new t_const_value; - x->set_double(3.1415); - const_values.push_back(x); - } - { - t_const_value* x = new t_const_value; - x->set_identifier("bar"); - x->set_enum(enums[0]); - const_values.push_back(x); - } - { - t_const_value* x = new t_const_value; - x->set_map(); - x->add_map(const_values[0], const_values[1]); - x->add_map(const_values[1], const_values[0]); - const_values.push_back(x); - } - { - t_const_value* x = new t_const_value; - x->set_list(); - x->add_list(const_values[0]); - x->add_list(const_values[1]); - const_values.push_back(x); - } -} - -void init_consts() { - // base_type/enum indexes for this and other tests are arbitrary - consts.push_back(new t_const(base_types[2], "aaa", const_values[0])); - consts.back()->set_doc("soem doc"); - consts.push_back(new t_const(base_types[3], "bbb", const_values[1])); -} - -void init_enum_values() { - enum_values.push_back(new t_enum_value("VAL1", 11)); - enum_values.back()->set_doc("enum doc 1"); - enum_values.back()->annotations_.insert(std::make_pair("anno1", "val1")); - - enum_values.push_back(new t_enum_value("VAL2", 22)); -} - -void init_enums() { - enums.push_back(new t_enum(programs[0])); - enums.back()->set_doc("enum doc 1"); - enums.back()->annotations_.insert(std::make_pair("anno1", "val1")); - enums.back()->set_name("fooo"); - enums.back()->append(enum_values[0]); - enums.back()->append(enum_values[1]); -} - -void init_lists() { - lists.push_back(new t_list(enums[0])); - lists.push_back(new t_list(base_types[5])); - lists.back()->set_cpp_name("list_cpp_name_1"); -} -void init_sets() { - sets.push_back(new t_set(base_types[4])); - sets.push_back(new t_set(enums[0])); - sets.back()->set_cpp_name("set_cpp_name_1"); -} -void init_maps() { - maps.push_back(new t_map(base_types[4], base_types[1])); - maps.push_back(new t_map(base_types[5], enums[0])); - maps.back()->set_cpp_name("map_cpp_name_1"); -} - -void init_typedefs() { - typedefs.push_back(new t_typedef(programs[0], base_types[3], "VAL1")); -} -void init_fields() { - fields.push_back(new t_field(base_types[1], "f1")); - fields.back()->set_reference(false); - fields.back()->set_req(t_field::T_OPTIONAL); - fields.push_back(new t_field(base_types[2], "f2", 9)); - fields.back()->set_reference(true); - fields.push_back(new t_field(base_types[3], "f3", 11)); - fields.back()->set_req(t_field::T_REQUIRED); - fields.back()->set_value(const_values[0]); -} -void init_structs() { - structs.push_back(new t_struct(programs[0], "struct1")); - structs.back()->append(fields[0]); - structs.back()->append(fields[1]); - structs.push_back(new t_struct(programs[0], "union1")); - structs.back()->append(fields[0]); - structs.back()->append(fields[1]); - structs.back()->set_union(true); - structs.push_back(new t_struct(programs[0], "xcept1")); - structs.back()->set_xception(true); -} -void init_functions() { - structs.push_back(new t_struct(programs[0], "errs1")); - t_struct* errors = structs.back(); - structs.push_back(new t_struct(programs[0], "args1")); - t_struct* arglist = structs.back(); - functions.push_back(new t_function(base_types[0], "func1", errors, arglist, false)); - functions.push_back(new t_function(base_types[0], "func2", errors, arglist, true)); -} -void init_services() { - services.push_back(new t_service(programs[0])); - services.back()->set_doc("srv1 doc"); - services.back()->set_name("srv1"); - services.back()->add_function(functions[0]); - services.back()->add_function(functions[1]); - - services.push_back(new t_service(programs[0])); - services.back()->set_name("srv2"); - services.back()->set_extends(services[0]); -} - -std::vector types; -void init_types() { -#define T_COPY_TYPES(type) std::copy(type##s.begin(), type##s.end(), std::back_inserter(types)) - T_COPY_TYPES(base_type); - T_COPY_TYPES(enum); - T_COPY_TYPES(typedef); - T_COPY_TYPES(struct); - T_COPY_TYPES(list); - T_COPY_TYPES(set); - T_COPY_TYPES(map); -// T_COPY_TYPES(service); -#undef T_COPY_TYPES -} - -void init() { - if (!has_data) { - has_data = true; -#define T_INIT_TESTDATA(r, d, elem) init_##elem##s(); - BOOST_PP_LIST_FOR_EACH(T_INIT_TESTDATA, _, T_TEST_TYPES) - init_types(); -#undef T_INIT_TESTDATA - } -} -} -struct GlobalFixture { - ~GlobalFixture() { test_data::cleanup(); } -}; -#if (BOOST_VERSION >= 105900) -BOOST_GLOBAL_FIXTURE(GlobalFixture); -#else -BOOST_GLOBAL_FIXTURE(GlobalFixture) -#endif - -void migrate_global_cache() { - plugin::TypeRegistry reg; - plugin_output::get_global_cache(reg); - plugin::set_global_cache(reg); - plugin_output::clear_global_cache(); -} -template -T* round_trip(T* t) { - typename plugin::ToType::type p; - plugin::clear_global_cache(); - plugin_output::clear_global_cache(); - plugin_output::convert(t, p); - migrate_global_cache(); - return plugin::convert(p); -} - -void test_base_type(::t_base_type* sut) { - plugin::t_base_type p; - plugin_output::convert(sut, p); - boost::scoped_ptr< ::t_base_type> sut2(plugin::convert(p)); - -#define THRIFT_CHECK(r, data, elem) BOOST_PP_EXPAND(BOOST_CHECK_EQUAL(data elem, sut2->elem)); - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(7, - (is_void(), - is_string(), - is_bool(), - is_string_list(), - is_binary(), - is_string_enum(), - is_base_type()))) -} - -void test_const_value(t_const_value* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_CHECK_EQUAL(sut->get_type(), sut2->get_type()); - switch (sut->get_type()) { -#define T_CONST_VALUE_CASE(type, name) \ - case t_const_value::type: \ - BOOST_CHECK_EQUAL(sut->get_##name(), sut2->get_##name()); \ - break - T_CONST_VALUE_CASE(CV_INTEGER, integer); - T_CONST_VALUE_CASE(CV_DOUBLE, double); - T_CONST_VALUE_CASE(CV_STRING, string); - T_CONST_VALUE_CASE(CV_IDENTIFIER, identifier); -#undef T_CONST_VALUE_CASE - case t_const_value::CV_MAP: - BOOST_CHECK_EQUAL(sut->get_map().size(), sut2->get_map().size()); - { - std::map sut_values; - for (std::map::const_iterator it = sut->get_map().begin(); - it != sut->get_map().end(); it++) { - sut_values[it->first->get_type()] = it->second->get_type(); - } - std::map sut2_values; - for (std::map::const_iterator it = sut2->get_map().begin(); - it != sut2->get_map().end(); it++) { - sut2_values[it->first->get_type()] = it->second->get_type(); - } - BOOST_CHECK_EQUAL(sut_values.begin()->first, sut2_values.begin()->first); - BOOST_CHECK_EQUAL(sut_values.begin()->second, sut2_values.begin()->second); - } - break; - case t_const_value::CV_LIST: - BOOST_CHECK_EQUAL(sut->get_list().size(), sut2->get_list().size()); - BOOST_CHECK_EQUAL(sut->get_list().front()->get_type(), sut2->get_list().front()->get_type()); - break; - default: - BOOST_ASSERT(false); - break; - } -} - -void test_const(t_const* sut) { - boost::scoped_ptr< ::t_const> sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(4, - (get_type()->get_name(), - get_name(), - get_value()->get_type(), - get_doc()))) -} - -void test_enum_value(t_enum_value* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(3, (get_name(), get_value(), get_doc()))) -} - -void test_enum(t_enum* sut) { - boost::scoped_ptr< ::t_enum> sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(6, - (get_name(), - get_min_value()->get_value(), - get_max_value()->get_value(), - get_constant_by_value(11)->get_value(), - get_constant_by_name("VAL1")->get_value(), - get_doc()))) -} - -void test_list(t_list* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(4, - (get_elem_type()->get_name(), - has_cpp_name(), - get_doc(), - get_name()))) - if (sut->has_cpp_name()) - BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name()); -} -void test_set(t_set* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(4, - (get_elem_type()->get_name(), - has_cpp_name(), - get_doc(), - get_name()))) - if (sut->has_cpp_name()) - BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name()); -} -void test_map(t_map* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(5, - (get_key_type()->get_name(), - get_val_type()->get_name(), - has_cpp_name(), - get_doc(), - get_name()))) - if (sut->has_cpp_name()) - BOOST_CHECK_EQUAL(sut->get_cpp_name(), sut2->get_cpp_name()); -} - -void test_typedef(t_typedef* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(4, - (get_doc(), - get_name(), - get_symbolic(), - is_forward_typedef()))) -} - -void test_type(t_type* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(15, - (is_void(), - is_base_type(), - is_string(), - is_bool(), - is_typedef(), - is_enum(), - is_struct(), - is_xception(), - is_container(), - is_list(), - is_set(), - is_map(), - is_service(), - get_doc(), - get_name()))) -} - -void test_field(t_field* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(5, - (get_req(), - get_reference(), - get_key(), - get_doc(), - get_name()))) - if (sut->get_value()) { - THRIFT_CHECK(, sut->, get_value()->get_type()); - } else { - BOOST_CHECK(!sut2->get_value()); - } - if (sut->get_type()) { - THRIFT_CHECK(, sut->, get_type()->get_name()); - } else { - BOOST_CHECK(!sut2->get_type()); - } -} -void test_struct(t_struct* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(5, - (is_union(), - is_xception(), - is_struct(), - get_doc(), - get_name()))) -} - -void test_function(t_function* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH( - THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(4, (get_doc(), get_name(), get_returntype()->get_name(), is_oneway()))) -} -void test_service(t_service* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, - sut->, - BOOST_PP_TUPLE_TO_LIST(3, (get_doc(), get_name(), get_functions().size()))) - if (sut->get_extends()) { - THRIFT_CHECK(, sut->, get_extends()->get_name()); - } else { - BOOST_CHECK(!sut2->get_extends()); - } -} - -void test_program(t_program* sut) { - boost::scoped_ptr sut2(round_trip(sut)); - - BOOST_PP_LIST_FOR_EACH(THRIFT_CHECK, sut->, BOOST_PP_TUPLE_TO_LIST(2, (get_doc(), get_name()))) -} -boost::unit_test::test_suite* do_init_unit_test_suite() { - test_data::init(); - test_suite* ts = BOOST_TEST_SUITE("PluginConversionTest"); - -#define T_TEST_CASE(r, d, type) \ - ts->add(BOOST_PARAM_TEST_CASE(test_##type, test_data::type##s.begin(), test_data::type##s.end())); - BOOST_PP_LIST_FOR_EACH(T_TEST_CASE, _, T_TEST_TYPES) - T_TEST_CASE(_, _, type) -#undef T_TEST_CASE - return ts; -} - -#ifdef BOOST_TEST_DYN_LINK -bool init_unit_test_suite() { - framework::master_test_suite().add(do_init_unit_test_suite()); - return true; -} -int main(int argc, char* argv[]) { - return ::boost::unit_test::unit_test_main(&init_unit_test_suite, argc, argv); -} -#else -boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) { - return do_init_unit_test_suite(); -} -#endif diff --git a/compiler/cpp/test/plugin/cpp_plugin.cc b/compiler/cpp/test/plugin/cpp_plugin.cc deleted file mode 100644 index 6cc19f2a3fc..00000000000 --- a/compiler/cpp/test/plugin/cpp_plugin.cc +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#include "thrift/plugin/plugin.h" -#include "thrift/generate/t_generator.h" - -namespace apache { -namespace thrift { -namespace plugin { - -class MyCppGenerator : public GeneratorPlugin { - virtual int generate(::t_program* program, - const std::map& parsed_options) { - t_generator* gen = t_generator_registry::get_generator(program, "cpp", parsed_options, ""); - gen->generate_program(); - delete gen; - return 0; - } -}; -} -} -} - -int main(int argc, char* argv[]) { - apache::thrift::plugin::MyCppGenerator p; - return p.exec(argc, argv); -} diff --git a/compiler/cpp/test/plugin_stability_test.sh b/compiler/cpp/test/plugin_stability_test.sh deleted file mode 100755 index eb7c93d6674..00000000000 --- a/compiler/cpp/test/plugin_stability_test.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -# this file is intended to be invoked by make. -# -# This file runs the compiler twice, using a plugin that just invokes -# /bin/cat, and compares the output. If GeneratorInput is -# nondeterminsitic, you'd expect the output to differ from run-to-run. -# So this tests that in fact, the output is stable from run-to-run. -set -e -mkdir -p gen-bincat -PATH=.:"$PATH" ../thrift -r -gen bincat ../../../test/Include.thrift > gen-bincat/1.ser -PATH=.:"$PATH" ../thrift -r -gen bincat ../../../test/Include.thrift > gen-bincat/2.ser -diff --binary gen-bincat/1.ser gen-bincat/2.ser diff --git a/configure.ac b/configure.ac index 0f6c6da0533..7da52a0bfa1 100755 --- a/configure.ac +++ b/configure.ac @@ -607,20 +607,6 @@ if test "$enable_tests" = "no"; then fi AM_CONDITIONAL(WITH_TESTS, [test "$have_tests" = "yes"]) -AC_ARG_ENABLE([plugin], - AS_HELP_STRING([--enable-plugin], [build compiler plugin support [default=no]]), - [], enable_plugin=no -) -have_plugin=yes -if test "$have_cpp" = "no" ; then - have_plugin="no" -fi -if test "$enable_plugin" = "no"; then - have_plugin="no" -fi -AC_CONFIG_LINKS([compiler/cpp/test/plugin/t_cpp_generator.cc:compiler/cpp/src/thrift/generate/t_cpp_generator.cc]) -AM_CONDITIONAL(WITH_PLUGIN, [test "$have_plugin" = "yes"]) - AC_ARG_ENABLE([tutorial], AS_HELP_STRING([--enable-tutorial], [build tutorial [default=yes]]), [], enable_tutorial=yes @@ -803,7 +789,6 @@ AC_CONFIG_FILES([ Makefile compiler/cpp/Makefile compiler/cpp/src/Makefile - compiler/cpp/src/thrift/plugin/Makefile compiler/cpp/test/Makefile compiler/cpp/src/thrift/version.h lib/Makefile @@ -957,7 +942,6 @@ echo "Building Lua Library ......... : $have_lua" echo "Building NodeJS Library ...... : $have_nodejs" echo "Building Perl Library ........ : $have_perl" echo "Building PHP Library ......... : $have_php" -echo "Building Plugin Support ...... : $have_plugin" echo "Building Python Library ...... : $have_python" echo "Building Py3 Library ......... : $have_py3" echo "Building Ruby Library ........ : $have_ruby" diff --git a/lib/Makefile.am b/lib/Makefile.am index 901c3ef02f0..f6060c40d72 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -25,11 +25,8 @@ SUBDIRS += as3 endif if WITH_CPP -# cpp dir is picked directly by plugin build -if !WITH_PLUGIN SUBDIRS += cpp endif -endif if WITH_C_GLIB SUBDIRS += c_glib diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index db9d751e457..616effddd9a 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -25,12 +25,8 @@ moc__%.cpp: %.h SUBDIRS = . if WITH_TESTS -# This file is needed by compiler with plugin, while test/Makefile.am needs compiler -# So test directory is directly picked by top level Makefile.am for plugin build -if !WITH_PLUGIN SUBDIRS += test endif -endif pkgconfigdir = $(libdir)/pkgconfig From 5e23c4df5b8a2c7f36f807dc07dc897fd8a39763 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sun, 27 Jan 2019 00:00:33 -0500 Subject: [PATCH 184/756] Update changes with removal of compiler plugin [ci skip]. --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index e6db1dc3301..8915a80abb9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -12,6 +12,7 @@ ### Breaking Changes +- [THRIFT-4743](https://issues.apache.org/jira/browse/THRIFT-4743) - compiler: remove plug-in mechanism - [THRIFT-4720](https://issues.apache.org/jira/browse/THRIFT-4720) - cpp: C++03/C++98 support has been removed; also removed boost as a runtime dependency - [THRIFT-4730](https://issues.apache.org/jira/browse/THRIFT-4730) - cpp: BoostThreadFactory, PosixThreadFactory, StdThreadFactory removed - [THRIFT-4732](https://issues.apache.org/jira/browse/THRIFT-4732) - cpp: CMake build changed to use BUILD_SHARED_LIBS From 638c91f6be6e4417f0d5d8d57886c9b74afabfbd Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 26 Jan 2019 10:33:04 -0500 Subject: [PATCH 185/756] THRIFT-1549: properly unwrap and close TSSLSocket in python --- lib/py/src/transport/TSSLSocket.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/py/src/transport/TSSLSocket.py b/lib/py/src/transport/TSSLSocket.py index b54ca5dd9c2..00d1f10f572 100644 --- a/lib/py/src/transport/TSSLSocket.py +++ b/lib/py/src/transport/TSSLSocket.py @@ -263,6 +263,15 @@ def __init__(self, host='localhost', port=9090, *args, **kwargs): TSSLBase.__init__(self, False, host, kwargs) TSocket.TSocket.__init__(self, host, port, unix_socket) + def close(self): + try: + self.handle.settimeout(0.001) + self.handle = self.handle.unwrap() + except (ssl.SSLError, socket.error, OSError): + # could not complete shutdown in a reasonable amount of time. bail. + pass + TSocket.TSocket.close(self) + @property def validate(self): warnings.warn('validate is deprecated. please use cert_reqs instead', From 4927179a5384a75932e459e290d424f8df8db50c Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 28 Jan 2019 08:32:47 -0500 Subject: [PATCH 186/756] Update the pull request template. [ci skip] --- pull_request_template.md | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/pull_request_template.md b/pull_request_template.md index 0b6965b046a..b719fc3ca2d 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -1,19 +1,37 @@ -Some helpful tips for a successful Apache Thrift PR: +### Pull Request Guidance ### -* Did you test your changes locally or using CI in your fork? -* Is the Apache Jira THRIFT ticket identifier in the PR title? -* Is the Apache Jira THRIFT ticket identifier in the commit message? -* Did you squash your changes to a single commit? -* Are these changes backwards compatible? (please say so in PR description) -* Do you need to update the language-specific README? +Review the following items to ensure a smooth pull request experience. -Example ideal pull request title: +- [ ] Did you make a breaking change? If so: + + - [ ] Add (or reference) an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) THRIFT ticket. + - [ ] Add a `Breaking-Change` label to the Jira ticket. + - [ ] Add a note to the `lib//README.md` file. + - [ ] Add a line to the `CHANGES.md` file. + +- [ ] Is this change significant enough to be in release notes? + + All release-note worthy changes require an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) THRIFT ticket. + For example: + - Breaking Changes + - New, Deprecated, or Removed Languages + - Security Fix + - Significant Refactoring + +- [ ] If there is an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) ticket: + + - [ ] Is the [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) THRIFT ticket identifier in the PR title? THRIFT-9999: an example pull request title -Example ideal commit message: + - [ ] Is the [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) THRIFT ticket identifier and affected languages in the commit message? THRIFT-9999: [summary of fix, one line if possible] Client: [language(s) affected, comma separated, use lib/ directory names please] +- [ ] Did you squash your changes to a single commit? + + Committers can squash when they merge, but sometimes we forget, and it makes the history + pretty dirty. Please squash your pull requests to a single commit if you can. + For more information about committing, see CONTRIBUTING.md From 1231930abd1d72b422deec967559caf3dc02dac7 Mon Sep 17 00:00:00 2001 From: Joel 'Aaron' Cohen Date: Fri, 25 Jan 2019 10:42:54 -0500 Subject: [PATCH 187/756] THRIFT-4760: Configure and install pkgconfig files when using cmake Client: cpp --- build/cmake/DefineInstallationPaths.cmake | 5 +++++ build/cmake/ThriftMacros.cmake | 7 +++++++ lib/cpp/CMakeLists.txt | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/build/cmake/DefineInstallationPaths.cmake b/build/cmake/DefineInstallationPaths.cmake index 122f0f6a937..d9a7174acc9 100644 --- a/build/cmake/DefineInstallationPaths.cmake +++ b/build/cmake/DefineInstallationPaths.cmake @@ -23,4 +23,9 @@ set(BIN_INSTALL_DIR "bin" CACHE PATH "The binary install dir (default: bin)") set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "The library install dir (default: lib${LIB_SUFFIX})") set(INCLUDE_INSTALL_DIR "include" CACHE PATH "The library install dir (default: include)") set(CMAKE_INSTALL_DIR "cmake" CACHE PATH "The subdirectory to install cmake config files (default: cmake)") +set(PKGCONFIG_INSTALL_DIR "lib/pkgconfig" CACHE PATH "The subdirectory to install pkgconfig config files (default: lib/pkgconfig)") set(DOC_INSTALL_DIR "share/doc" CACHE PATH "The subdirectory to install documentation files (default: share/doc)") +set(prefix "${CMAKE_INSTALL_PREFIX}") +set(exec_prefix "${CMAKE_INSTALL_PREFIX}/bin") +set(libdir "${CMAKE_INSTALL_PREFIX}/lib") +set(includedir "${CMAKE_INSTALL_PREFIX}/include") diff --git a/build/cmake/ThriftMacros.cmake b/build/cmake/ThriftMacros.cmake index 366719fbb93..8f370df6c1d 100644 --- a/build/cmake/ThriftMacros.cmake +++ b/build/cmake/ThriftMacros.cmake @@ -17,6 +17,13 @@ # under the License. # +macro(ADD_PKGCONFIG_THRIFT name) + configure_file("${name}.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/${name}.pc" @ONLY) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${name}.pc" + DESTINATION "${PKGCONFIG_INSTALL_DIR}") +endmacro(ADD_PKGCONFIG_THRIFT) + + macro(ADD_LIBRARY_THRIFT name) add_library(${name} ${ARGN}) set_target_properties(${name} PROPERTIES diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index f4e810461d3..dd90c808bed 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -144,6 +144,7 @@ if(WIN32) else() TARGET_LINK_LIBRARIES_THRIFT(thrift ${SYSLIBS}) endif() +ADD_PKGCONFIG_THRIFT(thrift) if(WITH_LIBEVENT) find_package(Libevent REQUIRED) # Libevent comes with CMake support form upstream @@ -152,6 +153,7 @@ if(WITH_LIBEVENT) ADD_LIBRARY_THRIFT(thriftnb ${thriftcppnb_SOURCES}) LINK_AGAINST_THRIFT_LIBRARY(thriftnb thrift) TARGET_LINK_LIBRARIES_THRIFT(thriftnb ${SYSLIBS} ${LIBEVENT_LIBRARIES}) + ADD_PKGCONFIG_THRIFT(thrift-nb) endif() if(WITH_ZLIB) @@ -161,10 +163,12 @@ if(WITH_ZLIB) ADD_LIBRARY_THRIFT(thriftz ${thriftcppz_SOURCES}) TARGET_LINK_LIBRARIES_THRIFT(thriftz ${SYSLIBS} ${ZLIB_LIBRARIES}) TARGET_LINK_LIBRARIES_THRIFT_AGAINST_THRIFT_LIBRARY(thriftz thrift) + ADD_PKGCONFIG_THRIFT(thrift-z) endif() if(WITH_QT5) add_subdirectory(src/thrift/qt) + ADD_PKGCONFIG_THRIFT(thrift-qt5) endif() if(MSVC) From aa0c8b35d8f78812de1d7803d6277a37d2ed593a Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Mon, 28 Jan 2019 23:27:45 +0100 Subject: [PATCH 188/756] THRIFT-4723 Consolidate C#/netcore into new netstd language target Client: netstd Patch: Jens Geyer This closes #1710 --- .gitignore | 8 + CHANGES.md | 6 +- build/veralign.sh | 2 + compiler/cpp/CMakeLists.txt | 1 + compiler/cpp/Makefile.am | 2 + compiler/cpp/compiler.vcxproj | 1 + compiler/cpp/compiler.vcxproj.filters | 12 + .../src/thrift/generate/t_netcore_generator.h | 23 + .../src/thrift/generate/t_netstd_generator.cc | 3115 +++++++++++++++++ .../src/thrift/generate/t_netstd_generator.h | 160 + configure.ac | 13 +- lib/Makefile.am | 3 +- lib/csharp/README.md | 6 + lib/netcore/README.md | 5 + lib/netstd/Makefile.am | 58 + lib/netstd/README.md | 54 + .../Protocols/ProtocolsOperationsTests.cs | 502 +++ .../Thrift.IntegrationTests.csproj | 48 + .../CassandraTest.thrift | 705 ++++ .../Properties/AssemblyInfo.cs | 40 + ...rift.PublicInterfaces.Compile.Tests.csproj | 54 + .../Collections/TCollectionsTests.cs | 83 + .../Thrift.Tests/Collections/THashSetTests.cs | 71 + .../Protocols/TJsonProtocolHelperTests.cs | 172 + .../Protocols/TJsonProtocolTests.cs | 67 + .../Tests/Thrift.Tests/Thrift.Tests.csproj | 36 + lib/netstd/Thrift.sln | 85 + lib/netstd/Thrift/Collections/TCollections.cs | 101 + lib/netstd/Thrift/Collections/THashSet.cs | 67 + .../Thrift/Processor/ITAsyncProcessor.cs | 28 + .../Thrift/Processor/ITProcessorFactory.cs | 28 + .../Thrift/Processor/TMultiplexedProcessor.cs | 143 + .../Processor/TSingletonProcessorFactory.cs | 38 + lib/netstd/Thrift/Properties/AssemblyInfo.cs | 56 + lib/netstd/Thrift/Protocol/Entities/TField.cs | 37 + lib/netstd/Thrift/Protocol/Entities/TList.cs | 33 + lib/netstd/Thrift/Protocol/Entities/TMap.cs | 36 + .../Thrift/Protocol/Entities/TMessage.cs | 37 + .../Thrift/Protocol/Entities/TMessageType.cs | 28 + lib/netstd/Thrift/Protocol/Entities/TSet.cs | 38 + .../Thrift/Protocol/Entities/TStruct.cs | 30 + lib/netstd/Thrift/Protocol/Entities/TType.cs | 37 + .../Thrift/Protocol/ITProtocolFactory.cs | 27 + lib/netstd/Thrift/Protocol/TBase.cs | 33 + lib/netstd/Thrift/Protocol/TBinaryProtocol.cs | 613 ++++ .../Thrift/Protocol/TCompactProtocol.cs | 922 +++++ lib/netstd/Thrift/Protocol/TJSONProtocol.cs | 981 ++++++ .../Thrift/Protocol/TMultiplexedProtocol.cs | 91 + lib/netstd/Thrift/Protocol/TProtocol.cs | 376 ++ .../Thrift/Protocol/TProtocolDecorator.cs | 247 ++ .../Thrift/Protocol/TProtocolException.cs | 62 + .../Thrift/Protocol/Utilities/TBase64Utils.cs | 101 + .../Utilities/TJsonProtocolConstants.cs | 61 + .../Protocol/Utilities/TJsonProtocolHelper.cs | 176 + .../Protocol/Utilities/TProtocolUtil.cs | 110 + lib/netstd/Thrift/Server/TServer.cs | 87 + .../Thrift/Server/TServerEventHandler.cs | 54 + .../Thrift/Server/TSimpleAsyncServer.cs | 196 ++ .../Thrift/Server/TThreadPoolAsyncServer.cs | 297 ++ lib/netstd/Thrift/TApplicationException.cs | 150 + lib/netstd/Thrift/TBaseClient.cs | 91 + lib/netstd/Thrift/TException.cs | 34 + lib/netstd/Thrift/Thrift.csproj | 50 + .../Transport/Client/TBufferedTransport.cs | 205 ++ .../Transport/Client/TFramedTransport.cs | 201 ++ .../Thrift/Transport/Client/THttpTransport.cs | 226 ++ .../Client/TMemoryBufferTransport.cs | 97 + .../Transport/Client/TNamedPipeTransport.cs | 98 + .../Transport/Client/TSocketTransport.cs | 162 + .../Transport/Client/TStreamTransport.cs | 110 + .../Transport/Client/TTlsSocketTransport.cs | 237 ++ .../Thrift/Transport/Server/NullLogger.cs | 56 + .../Transport/Server/THttpServerTransport.cs | 96 + .../Server/TNamedPipeServerTransport.cs | 191 + .../Server/TServerFramedTransport.cs | 150 + .../Server/TServerSocketTransport.cs | 174 + .../Server/TTlsServerSocketTransport.cs | 177 + .../Thrift/Transport/TClientTransport.cs | 179 + .../Thrift/Transport/TServerTransport.cs | 54 + .../Thrift/Transport/TTransportException.cs | 60 + .../Thrift/Transport/TTransportFactory.cs | 35 + lib/netstd/build.cmd | 27 + lib/netstd/build.sh | 32 + lib/netstd/runtests.cmd | 28 + lib/netstd/runtests.sh | 26 + test/Makefile.am | 3 +- test/ThriftTest.thrift | 1 + test/netstd/Client/.gitignore | 2 + test/netstd/Client/Client.csproj | 50 + test/netstd/Client/Program.cs | 72 + test/netstd/Client/Properties/AssemblyInfo.cs | 43 + test/netstd/Client/TestClient.cs | 943 +++++ test/netstd/Makefile.am | 41 + test/netstd/README.md | 20 + test/netstd/Server/.gitignore | 2 + test/netstd/Server/Program.cs | 72 + test/netstd/Server/Properties/AssemblyInfo.cs | 43 + test/netstd/Server/Server.csproj | 50 + test/netstd/Server/TestServer.cs | 595 ++++ test/netstd/ThriftTest.sln | 64 + test/netstd/build.cmd | 25 + test/netstd/build.sh | 26 + tutorial/Makefile.am | 3 +- tutorial/netstd/.gitignore | 1 + tutorial/netstd/Client/Client.csproj | 37 + tutorial/netstd/Client/Program.cs | 355 ++ .../netstd/Client/Properties/AssemblyInfo.cs | 40 + .../Client/Properties/launchSettings.json | 8 + tutorial/netstd/Client/ThriftTest.pfx | Bin 0 -> 2661 bytes tutorial/netstd/Interfaces/.gitignore | 3 + tutorial/netstd/Interfaces/Interfaces.csproj | 48 + .../Interfaces/Properties/AssemblyInfo.cs | 40 + tutorial/netstd/Makefile.am | 42 + tutorial/netstd/README.md | 278 ++ tutorial/netstd/Server/Program.cs | 429 +++ .../netstd/Server/Properties/AssemblyInfo.cs | 40 + .../Server/Properties/launchSettings.json | 8 + tutorial/netstd/Server/Server.csproj | 44 + tutorial/netstd/Server/ThriftTest.pfx | Bin 0 -> 2661 bytes tutorial/netstd/Tutorial.sln | 78 + tutorial/netstd/build.cmd | 25 + tutorial/netstd/build.sh | 26 + tutorial/shared.thrift | 2 + tutorial/tutorial.thrift | 1 + 124 files changed, 17004 insertions(+), 5 deletions(-) create mode 100644 compiler/cpp/src/thrift/generate/t_netstd_generator.cc create mode 100644 compiler/cpp/src/thrift/generate/t_netstd_generator.h create mode 100644 lib/netstd/Makefile.am create mode 100644 lib/netstd/README.md create mode 100644 lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs create mode 100644 lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj create mode 100644 lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift create mode 100644 lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs create mode 100644 lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj create mode 100644 lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs create mode 100644 lib/netstd/Tests/Thrift.Tests/Collections/THashSetTests.cs create mode 100644 lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs create mode 100644 lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs create mode 100644 lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj create mode 100644 lib/netstd/Thrift.sln create mode 100644 lib/netstd/Thrift/Collections/TCollections.cs create mode 100644 lib/netstd/Thrift/Collections/THashSet.cs create mode 100644 lib/netstd/Thrift/Processor/ITAsyncProcessor.cs create mode 100644 lib/netstd/Thrift/Processor/ITProcessorFactory.cs create mode 100644 lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs create mode 100644 lib/netstd/Thrift/Processor/TSingletonProcessorFactory.cs create mode 100644 lib/netstd/Thrift/Properties/AssemblyInfo.cs create mode 100644 lib/netstd/Thrift/Protocol/Entities/TField.cs create mode 100644 lib/netstd/Thrift/Protocol/Entities/TList.cs create mode 100644 lib/netstd/Thrift/Protocol/Entities/TMap.cs create mode 100644 lib/netstd/Thrift/Protocol/Entities/TMessage.cs create mode 100644 lib/netstd/Thrift/Protocol/Entities/TMessageType.cs create mode 100644 lib/netstd/Thrift/Protocol/Entities/TSet.cs create mode 100644 lib/netstd/Thrift/Protocol/Entities/TStruct.cs create mode 100644 lib/netstd/Thrift/Protocol/Entities/TType.cs create mode 100644 lib/netstd/Thrift/Protocol/ITProtocolFactory.cs create mode 100644 lib/netstd/Thrift/Protocol/TBase.cs create mode 100644 lib/netstd/Thrift/Protocol/TBinaryProtocol.cs create mode 100644 lib/netstd/Thrift/Protocol/TCompactProtocol.cs create mode 100644 lib/netstd/Thrift/Protocol/TJSONProtocol.cs create mode 100644 lib/netstd/Thrift/Protocol/TMultiplexedProtocol.cs create mode 100644 lib/netstd/Thrift/Protocol/TProtocol.cs create mode 100644 lib/netstd/Thrift/Protocol/TProtocolDecorator.cs create mode 100644 lib/netstd/Thrift/Protocol/TProtocolException.cs create mode 100644 lib/netstd/Thrift/Protocol/Utilities/TBase64Utils.cs create mode 100644 lib/netstd/Thrift/Protocol/Utilities/TJsonProtocolConstants.cs create mode 100644 lib/netstd/Thrift/Protocol/Utilities/TJsonProtocolHelper.cs create mode 100644 lib/netstd/Thrift/Protocol/Utilities/TProtocolUtil.cs create mode 100644 lib/netstd/Thrift/Server/TServer.cs create mode 100644 lib/netstd/Thrift/Server/TServerEventHandler.cs create mode 100644 lib/netstd/Thrift/Server/TSimpleAsyncServer.cs create mode 100644 lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs create mode 100644 lib/netstd/Thrift/TApplicationException.cs create mode 100644 lib/netstd/Thrift/TBaseClient.cs create mode 100644 lib/netstd/Thrift/TException.cs create mode 100644 lib/netstd/Thrift/Thrift.csproj create mode 100644 lib/netstd/Thrift/Transport/Client/TBufferedTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Client/TFramedTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Client/THttpTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Client/TSocketTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Client/TStreamTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Server/NullLogger.cs create mode 100644 lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Server/TServerFramedTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs create mode 100644 lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs create mode 100644 lib/netstd/Thrift/Transport/TClientTransport.cs create mode 100644 lib/netstd/Thrift/Transport/TServerTransport.cs create mode 100644 lib/netstd/Thrift/Transport/TTransportException.cs create mode 100644 lib/netstd/Thrift/Transport/TTransportFactory.cs create mode 100644 lib/netstd/build.cmd create mode 100644 lib/netstd/build.sh create mode 100644 lib/netstd/runtests.cmd create mode 100644 lib/netstd/runtests.sh create mode 100644 test/netstd/Client/.gitignore create mode 100644 test/netstd/Client/Client.csproj create mode 100644 test/netstd/Client/Program.cs create mode 100644 test/netstd/Client/Properties/AssemblyInfo.cs create mode 100644 test/netstd/Client/TestClient.cs create mode 100644 test/netstd/Makefile.am create mode 100644 test/netstd/README.md create mode 100644 test/netstd/Server/.gitignore create mode 100644 test/netstd/Server/Program.cs create mode 100644 test/netstd/Server/Properties/AssemblyInfo.cs create mode 100644 test/netstd/Server/Server.csproj create mode 100644 test/netstd/Server/TestServer.cs create mode 100644 test/netstd/ThriftTest.sln create mode 100644 test/netstd/build.cmd create mode 100644 test/netstd/build.sh create mode 100644 tutorial/netstd/.gitignore create mode 100644 tutorial/netstd/Client/Client.csproj create mode 100644 tutorial/netstd/Client/Program.cs create mode 100644 tutorial/netstd/Client/Properties/AssemblyInfo.cs create mode 100644 tutorial/netstd/Client/Properties/launchSettings.json create mode 100644 tutorial/netstd/Client/ThriftTest.pfx create mode 100644 tutorial/netstd/Interfaces/.gitignore create mode 100644 tutorial/netstd/Interfaces/Interfaces.csproj create mode 100644 tutorial/netstd/Interfaces/Properties/AssemblyInfo.cs create mode 100644 tutorial/netstd/Makefile.am create mode 100644 tutorial/netstd/README.md create mode 100644 tutorial/netstd/Server/Program.cs create mode 100644 tutorial/netstd/Server/Properties/AssemblyInfo.cs create mode 100644 tutorial/netstd/Server/Properties/launchSettings.json create mode 100644 tutorial/netstd/Server/Server.csproj create mode 100644 tutorial/netstd/Server/ThriftTest.pfx create mode 100644 tutorial/netstd/Tutorial.sln create mode 100644 tutorial/netstd/build.cmd create mode 100644 tutorial/netstd/build.sh diff --git a/.gitignore b/.gitignore index cd98fa778a8..135b085495c 100644 --- a/.gitignore +++ b/.gitignore @@ -232,6 +232,8 @@ project.lock.json /lib/js/test/build /lib/netcore/**/bin /lib/netcore/**/obj +/lib/netstd/**/bin +/lib/netstd/**/obj /lib/nodejs/coverage /lib/nodejs/node_modules/ /lib/perl/MANIFEST @@ -337,6 +339,9 @@ project.lock.json /test/netcore/**/bin /test/netcore/**/obj /test/netcore/Thrift +/test/netstd/**/bin +/test/netstd/**/obj +/test/netstd/Thrift /test/php/php_ext_dir/ /test/rs/Cargo.lock /test/rs/src/thrift_test.rs @@ -390,6 +395,9 @@ project.lock.json /tutorial/netcore/**/bin /tutorial/netcore/**/obj /tutorial/netcore/Thrift +/tutorial/netstd/**/bin +/tutorial/netstd/**/obj +/tutorial/netstd/Interfaces /tutorial/rs/*.iml /tutorial/rs/src/shared.rs /tutorial/rs/src/tutorial.rs diff --git a/CHANGES.md b/CHANGES.md index 8915a80abb9..dcba6d12dd8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,10 @@ - [THRIFT-4719](https://issues.apache.org/jira/browse/THRIFT-4719) - Cocoa language was removed - use swift instead. +### Deprecated Languages + +- [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - CSharp and Netcore targets are deprecated and will be removed with the next release - use NetStd instead. + ### Breaking Changes - [THRIFT-4743](https://issues.apache.org/jira/browse/THRIFT-4743) - compiler: remove plug-in mechanism @@ -24,7 +28,7 @@ - [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - java: change return type signature of 'process' methods - [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - js: now uses node-int64 for 64 bit integer constants -### Known Isues (Blocker or Critical) +### Known Issues (Blocker or Critical) ## 0.12.0 diff --git a/build/veralign.sh b/build/veralign.sh index 49c39a5ad7f..56c436a8136 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -78,6 +78,8 @@ FILES[lib/js/src/thrift.js]=simpleReplace FILES[lib/lua/Thrift.lua]=simpleReplace FILES[lib/netcore/Thrift/Properties/AssemblyInfo.cs]=simpleReplace FILES[lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs]=simpleReplace +FILES[lib/netstd/Thrift/Properties/AssemblyInfo.cs]=simpleReplace +FILES[lib/netstd/Thrift/Transports/Client/THttpClientTransport.cs]=simpleReplace FILES[lib/ocaml/_oasis]=simpleReplace FILES[lib/perl/lib/Thrift.pm]=simpleReplace FILES[lib/py/setup.py]=simpleReplace diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt index 6f7ae5d7e42..17dae4787b4 100644 --- a/compiler/cpp/CMakeLists.txt +++ b/compiler/cpp/CMakeLists.txt @@ -91,6 +91,7 @@ THRIFT_ADD_COMPILER(js "Enable compiler for JavaScript" ON) THRIFT_ADD_COMPILER(json "Enable compiler for JSON" ON) THRIFT_ADD_COMPILER(lua "Enable compiler for Lua" ON) THRIFT_ADD_COMPILER(netcore "Enable compiler for .NET Core" ON) +THRIFT_ADD_COMPILER(netstd "Enable compiler for .NET Standard" ON) THRIFT_ADD_COMPILER(ocaml "Enable compiler for OCaml" ON) THRIFT_ADD_COMPILER(perl "Enable compiler for Perl" ON) THRIFT_ADD_COMPILER(php "Enable compiler for PHP" ON) diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am index 9b5742fe946..16d4d3ac8af 100644 --- a/compiler/cpp/Makefile.am +++ b/compiler/cpp/Makefile.am @@ -89,6 +89,8 @@ thrift_SOURCES += src/thrift/generate/t_as3_generator.cc \ src/thrift/generate/t_lua_generator.cc \ src/thrift/generate/t_netcore_generator.cc \ src/thrift/generate/t_netcore_generator.h \ + src/thrift/generate/t_netstd_generator.cc \ + src/thrift/generate/t_netstd_generator.h \ src/thrift/generate/t_ocaml_generator.cc \ src/thrift/generate/t_perl_generator.cc \ src/thrift/generate/t_php_generator.cc \ diff --git a/compiler/cpp/compiler.vcxproj b/compiler/cpp/compiler.vcxproj index 3b597280b1a..06c4eb4d8eb 100644 --- a/compiler/cpp/compiler.vcxproj +++ b/compiler/cpp/compiler.vcxproj @@ -74,6 +74,7 @@ + diff --git a/compiler/cpp/compiler.vcxproj.filters b/compiler/cpp/compiler.vcxproj.filters index b96865b51ce..5a575894fa3 100644 --- a/compiler/cpp/compiler.vcxproj.filters +++ b/compiler/cpp/compiler.vcxproj.filters @@ -161,6 +161,18 @@ generate + + generate + + + generate + + + generate + + + generate + generate diff --git a/compiler/cpp/src/thrift/generate/t_netcore_generator.h b/compiler/cpp/src/thrift/generate/t_netcore_generator.h index 6efc922b74f..e98980a9eee 100644 --- a/compiler/cpp/src/thrift/generate/t_netcore_generator.h +++ b/compiler/cpp/src/thrift/generate/t_netcore_generator.h @@ -1,3 +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. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + #include #include diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc new file mode 100644 index 00000000000..8cb302736a6 --- /dev/null +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -0,0 +1,3115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "thrift/platform.h" +#include "thrift/generate/t_oop_generator.h" +#include "thrift/generate/t_netstd_generator.h" + +using std::map; +using std::ostream; +using std::ostringstream; +using std::string; +using std::stringstream; +using std::vector; + +//TODO: check for indentation +//TODO: Do we need seqId_ in generation? + +t_netstd_generator::t_netstd_generator(t_program* program, const map& parsed_options, const string& option_string) + : t_oop_generator(program) +{ + (void)option_string; + + union_ = false; + serialize_ = false; + wcf_ = false; + wcf_namespace_.clear(); + + map::const_iterator iter; + + for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) + { + if (iter->first.compare("union") == 0) + { + union_ = true; + } + else if (iter->first.compare("serial") == 0) + { + serialize_ = true; + wcf_namespace_ = iter->second; // since there can be only one namespace + } + else if (iter->first.compare("wcf") == 0) + { + wcf_ = true; + wcf_namespace_ = iter->second; + } + else + { + throw "unknown option netstd:" + iter->first; + } + } + + out_dir_base_ = "gen-netstd"; +} + +static string correct_function_name_for_async(string const& function_name) +{ + string const async_end = "Async"; + size_t i = function_name.find(async_end); + if (i != string::npos) + { + return function_name + async_end; + } + + return function_name; +} + +/** +* \brief Search and replace "_args" substring in struct name if exist (for C# class naming) +* \param struct_name +* \return Modified struct name ("Struct_args" -> "StructArgs") or original name +*/ +static string check_and_correct_struct_name(const string& struct_name) +{ + string args_end = "_args"; + size_t i = struct_name.find(args_end); + if (i != string::npos) + { + string new_struct_name = struct_name; + new_struct_name.replace(i, args_end.length(), "Args"); + return new_struct_name; + } + + string result_end = "_result"; + size_t j = struct_name.find(result_end); + if (j != string::npos) + { + string new_struct_name = struct_name; + new_struct_name.replace(j, result_end.length(), "Result"); + return new_struct_name; + } + + return struct_name; +} + +static bool field_has_default(t_field* tfield) { return tfield->get_value() != NULL; } + +static bool field_is_required(t_field* tfield) { return tfield->get_req() == t_field::T_REQUIRED; } + +static bool type_can_be_null(t_type* ttype) +{ + while (ttype->is_typedef()) + { + ttype = static_cast(ttype)->get_type(); + } + + return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string(); +} + +bool t_netstd_generator::is_wcf_enabled() const { return wcf_; } + +bool t_netstd_generator::is_nullable_enabled() const { return false; } + +bool t_netstd_generator::is_serialize_enabled() const { return serialize_; } + +bool t_netstd_generator::is_union_enabled() const { return union_; } + +map t_netstd_generator::get_keywords_list() const +{ + return netstd_keywords; +} + +void t_netstd_generator::init_generator() +{ + MKDIR(get_out_dir().c_str()); + + // for usage of csharp namespaces in thrift files (from files for csharp) + namespace_name_ = program_->get_namespace("netstd"); + if (namespace_name_.empty()) + { + namespace_name_ = program_->get_namespace("netstd"); + } + + string dir = namespace_name_; + string subdir = get_out_dir().c_str(); + string::size_type loc; + + while ((loc = dir.find(".")) != string::npos) + { + subdir = subdir + "/" + dir.substr(0, loc); + MKDIR(subdir.c_str()); + dir = dir.substr(loc + 1); + } + if (dir.size() > 0) + { + subdir = subdir + "/" + dir; + MKDIR(subdir.c_str()); + } + + namespace_dir_ = subdir; + init_keywords(); + + while (!member_mapping_scopes.empty()) + { + cleanup_member_name_mapping(member_mapping_scopes.back().scope_member); + } + + pverbose(".NET Core options:\n"); + //pverbose("- nullable ... %s\n", (is_nullable_enabled() ? "ON" : "off")); -- deprecated, removal candidate + pverbose("- union ...... %s\n", (is_union_enabled() ? "ON" : "off")); + pverbose("- serialize .. %s\n", (is_serialize_enabled() ? "ON" : "off")); + pverbose("- wcf ........ %s\n", (is_wcf_enabled() ? "ON" : "off")); +} + +string t_netstd_generator::normalize_name(string name) +{ + string tmp(name); + transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast(tolower)); + + // un-conflict keywords by prefixing with "@" + if (netstd_keywords.find(tmp) != netstd_keywords.end()) + { + return "@" + name; + } + + // no changes necessary + return name; +} + +void t_netstd_generator::init_keywords() +{ + netstd_keywords.clear(); + + // C# keywords + netstd_keywords["abstract"] = 1; + netstd_keywords["as"] = 1; + netstd_keywords["base"] = 1; + netstd_keywords["bool"] = 1; + netstd_keywords["break"] = 1; + netstd_keywords["byte"] = 1; + netstd_keywords["case"] = 1; + netstd_keywords["catch"] = 1; + netstd_keywords["char"] = 1; + netstd_keywords["checked"] = 1; + netstd_keywords["class"] = 1; + netstd_keywords["const"] = 1; + netstd_keywords["continue"] = 1; + netstd_keywords["decimal"] = 1; + netstd_keywords["default"] = 1; + netstd_keywords["delegate"] = 1; + netstd_keywords["do"] = 1; + netstd_keywords["double"] = 1; + netstd_keywords["else"] = 1; + netstd_keywords["enum"] = 1; + netstd_keywords["event"] = 1; + netstd_keywords["explicit"] = 1; + netstd_keywords["extern"] = 1; + netstd_keywords["false"] = 1; + netstd_keywords["finally"] = 1; + netstd_keywords["fixed"] = 1; + netstd_keywords["float"] = 1; + netstd_keywords["for"] = 1; + netstd_keywords["foreach"] = 1; + netstd_keywords["goto"] = 1; + netstd_keywords["if"] = 1; + netstd_keywords["implicit"] = 1; + netstd_keywords["in"] = 1; + netstd_keywords["int"] = 1; + netstd_keywords["interface"] = 1; + netstd_keywords["internal"] = 1; + netstd_keywords["is"] = 1; + netstd_keywords["lock"] = 1; + netstd_keywords["long"] = 1; + netstd_keywords["namespace"] = 1; + netstd_keywords["new"] = 1; + netstd_keywords["null"] = 1; + netstd_keywords["object"] = 1; + netstd_keywords["operator"] = 1; + netstd_keywords["out"] = 1; + netstd_keywords["override"] = 1; + netstd_keywords["params"] = 1; + netstd_keywords["private"] = 1; + netstd_keywords["protected"] = 1; + netstd_keywords["public"] = 1; + netstd_keywords["readonly"] = 1; + netstd_keywords["ref"] = 1; + netstd_keywords["return"] = 1; + netstd_keywords["sbyte"] = 1; + netstd_keywords["sealed"] = 1; + netstd_keywords["short"] = 1; + netstd_keywords["sizeof"] = 1; + netstd_keywords["stackalloc"] = 1; + netstd_keywords["static"] = 1; + netstd_keywords["string"] = 1; + netstd_keywords["struct"] = 1; + netstd_keywords["switch"] = 1; + netstd_keywords["this"] = 1; + netstd_keywords["throw"] = 1; + netstd_keywords["true"] = 1; + netstd_keywords["try"] = 1; + netstd_keywords["typeof"] = 1; + netstd_keywords["uint"] = 1; + netstd_keywords["ulong"] = 1; + netstd_keywords["unchecked"] = 1; + netstd_keywords["unsafe"] = 1; + netstd_keywords["ushort"] = 1; + netstd_keywords["using"] = 1; + netstd_keywords["virtual"] = 1; + netstd_keywords["void"] = 1; + netstd_keywords["volatile"] = 1; + netstd_keywords["while"] = 1; + + // C# contextual keywords + netstd_keywords["add"] = 1; + netstd_keywords["alias"] = 1; + netstd_keywords["ascending"] = 1; + netstd_keywords["async"] = 1; + netstd_keywords["await"] = 1; + netstd_keywords["descending"] = 1; + netstd_keywords["dynamic"] = 1; + netstd_keywords["from"] = 1; + netstd_keywords["get"] = 1; + netstd_keywords["global"] = 1; + netstd_keywords["group"] = 1; + netstd_keywords["into"] = 1; + netstd_keywords["join"] = 1; + netstd_keywords["let"] = 1; + netstd_keywords["orderby"] = 1; + netstd_keywords["partial"] = 1; + netstd_keywords["remove"] = 1; + netstd_keywords["select"] = 1; + netstd_keywords["set"] = 1; + netstd_keywords["value"] = 1; + netstd_keywords["var"] = 1; + netstd_keywords["where"] = 1; + netstd_keywords["yield"] = 1; + + netstd_keywords["when"] = 1; +} + +void t_netstd_generator::start_netstd_namespace(ostream& out) +{ + if (!namespace_name_.empty()) + { + out << "namespace " << namespace_name_ << endl; + scope_up(out); + } +} + +void t_netstd_generator::end_netstd_namespace(ostream& out) +{ + if (!namespace_name_.empty()) + { + scope_down(out); + } +} + +string t_netstd_generator::netstd_type_usings() const +{ + string namespaces = + "using System;\n" + "using System.Collections;\n" + "using System.Collections.Generic;\n" + "using System.Text;\n" + "using System.IO;\n" + "using System.Threading;\n" + "using System.Threading.Tasks;\n" + "using Thrift;\n" + "using Thrift.Collections;\n"; + + if (is_wcf_enabled()) + { + namespaces += "using System.ServiceModel;\n"; + namespaces += "using System.Runtime.Serialization;\n"; + } + + return namespaces + endl; +} + +string t_netstd_generator::netstd_thrift_usings() const +{ + string namespaces = + "using Thrift.Protocol;\n" + "using Thrift.Protocol.Entities;\n" + "using Thrift.Protocol.Utilities;\n" + "using Thrift.Transport;\n" + "using Thrift.Transport.Client;\n" + "using Thrift.Transport.Server;\n" + "using Thrift.Processor;\n"; + + return namespaces + endl; +} + +void t_netstd_generator::close_generator() +{ +} + +void t_netstd_generator::generate_typedef(t_typedef* ttypedef) +{ + (void)ttypedef; +} + +void t_netstd_generator::generate_enum(t_enum* tenum) +{ + int ic = indent_count(); + string f_enum_name = namespace_dir_ + "/" + tenum->get_name() + ".cs"; + + ofstream_with_content_based_conditional_update f_enum; + f_enum.open(f_enum_name.c_str()); + + generate_enum(f_enum, tenum); + + f_enum.close(); + indent_validate(ic, "generate_enum"); +} + +void t_netstd_generator::generate_enum(ostream& out, t_enum* tenum) +{ + out << autogen_comment() << endl; + + start_netstd_namespace(out); + generate_netstd_doc(out, tenum); + + out << indent() << "public enum " << tenum->get_name() << endl; + scope_up(out); + + vector constants = tenum->get_constants(); + vector::iterator c_iter; + + for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) + { + generate_netstd_doc(out, *c_iter); + int value = (*c_iter)->get_value(); + out << indent() << (*c_iter)->get_name() << " = " << value << "," << endl; + } + + scope_down(out); + end_netstd_namespace(out); +} + +void t_netstd_generator::generate_consts(vector consts) +{ + if (consts.empty()) + { + return; + } + + string f_consts_name = namespace_dir_ + '/' + program_name_ + ".Constants.cs"; + ofstream_with_content_based_conditional_update f_consts; + f_consts.open(f_consts_name.c_str()); + + generate_consts(f_consts, consts); + + f_consts.close(); +} + +void t_netstd_generator::generate_consts(ostream& out, vector consts) +{ + if (consts.empty()) + { + return; + } + + out << autogen_comment() << netstd_type_usings() << endl; + + start_netstd_namespace(out); + + out << indent() << "public static class " << make_valid_csharp_identifier(program_name_) << "Constants" << endl; + + scope_up(out); + + vector::iterator c_iter; + bool need_static_constructor = false; + for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) + { + generate_netstd_doc(out, *c_iter); + if (print_const_value(out, (*c_iter)->get_name(), (*c_iter)->get_type(), (*c_iter)->get_value(), false)) + { + need_static_constructor = true; + } + } + + if (need_static_constructor) + { + print_const_constructor(out, consts); + } + + scope_down(out); + end_netstd_namespace(out); +} + +void t_netstd_generator::print_const_def_value(ostream& out, string name, t_type* type, t_const_value* value) +{ + if (type->is_struct() || type->is_xception()) + { + const vector& fields = static_cast(type)->get_members(); + const map& val = value->get_map(); + vector::const_iterator f_iter; + map::const_iterator v_iter; + prepare_member_name_mapping(static_cast(type)); + + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) + { + t_field* field = NULL; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + if ((*f_iter)->get_name() == v_iter->first->get_string()) + { + field = *f_iter; + } + } + + if (field == NULL) + { + throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); + } + + t_type* field_type = field->get_type(); + + string val = render_const_value(out, name, field_type, v_iter->second); + out << indent() << name << "." << prop_name(field) << " = " << val << ";" << endl; + } + + cleanup_member_name_mapping(static_cast(type)); + } + else if (type->is_map()) + { + t_type* ktype = static_cast(type)->get_key_type(); + t_type* vtype = static_cast(type)->get_val_type(); + const map& val = value->get_map(); + map::const_iterator v_iter; + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) + { + string key = render_const_value(out, name, ktype, v_iter->first); + string val = render_const_value(out, name, vtype, v_iter->second); + out << indent() << name << "[" << key << "]" << " = " << val << ";" << endl; + } + } + else if (type->is_list() || type->is_set()) + { + t_type* etype; + if (type->is_list()) + { + etype = static_cast(type)->get_elem_type(); + } + else + { + etype = static_cast(type)->get_elem_type(); + } + + const vector& val = value->get_list(); + vector::const_iterator v_iter; + for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) + { + string val = render_const_value(out, name, etype, *v_iter); + out << indent() << name << ".Add(" << val << ");" << endl; + } + } +} + +void t_netstd_generator::print_const_constructor(ostream& out, vector consts) +{ + out << indent() << "static " << make_valid_csharp_identifier(program_name_).c_str() << "Constants()" << endl; + scope_up(out); + + vector::iterator c_iter; + for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) + { + string name = (*c_iter)->get_name(); + t_type* type = (*c_iter)->get_type(); + t_const_value* value = (*c_iter)->get_value(); + + print_const_def_value(out, name, type, value); + } + scope_down(out); +} + +bool t_netstd_generator::print_const_value(ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval, bool needtype) +{ + out << indent(); + bool need_static_construction = !in_static; + while (type->is_typedef()) + { + type = static_cast(type)->get_type(); + } + + if (!defval || needtype) + { + out << (in_static ? "" : type->is_base_type() ? "public const " : "public static ") << type_name(type) << " "; + } + + if (type->is_base_type()) + { + string v2 = render_const_value(out, name, type, value); + out << normalize_name(name) << " = " << v2 << ";" << endl; + need_static_construction = false; + } + else if (type->is_enum()) + { + out << name << " = " << type_name(type, false, true) << "." << value->get_identifier_name() << ";" << endl; + need_static_construction = false; + } + else if (type->is_struct() || type->is_xception()) + { + out << name << " = new " << type_name(type) << "();" << endl; + } + else if (type->is_map()) + { + out << name << " = new " << type_name(type, true, true) << "();" << endl; + } + else if (type->is_list() || type->is_set()) + { + out << name << " = new " << type_name(type) << "();" << endl; + } + + if (defval && !type->is_base_type() && !type->is_enum()) + { + print_const_def_value(out, name, type, value); + } + + return need_static_construction; +} + +string t_netstd_generator::render_const_value(ostream& out, string name, t_type* type, t_const_value* value) +{ + (void)name; + ostringstream render; + + if (type->is_base_type()) + { + t_base_type::t_base tbase = static_cast(type)->get_base(); + switch (tbase) + { + case t_base_type::TYPE_STRING: + render << '"' << get_escaped_string(value) << '"'; + break; + case t_base_type::TYPE_BOOL: + render << ((value->get_integer() > 0) ? "true" : "false"); + break; + case t_base_type::TYPE_I8: + case t_base_type::TYPE_I16: + case t_base_type::TYPE_I32: + case t_base_type::TYPE_I64: + render << value->get_integer(); + break; + case t_base_type::TYPE_DOUBLE: + if (value->get_type() == t_const_value::CV_INTEGER) + { + render << value->get_integer(); + } + else + { + render << value->get_double(); + } + break; + default: + throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); + } + } + else if (type->is_enum()) + { + render << type->get_name() << "." << value->get_identifier_name(); + } + else + { + string t = tmp("tmp"); + print_const_value(out, t, type, value, true, true, true); + render << t; + } + + return render.str(); +} + +void t_netstd_generator::generate_struct(t_struct* tstruct) +{ + if (is_union_enabled() && tstruct->is_union()) + { + generate_netstd_union(tstruct); + } + else + { + generate_netstd_struct(tstruct, false); + } +} + +void t_netstd_generator::generate_xception(t_struct* txception) +{ + generate_netstd_struct(txception, true); +} + +void t_netstd_generator::generate_netstd_struct(t_struct* tstruct, bool is_exception) +{ + int ic = indent_count(); + + string f_struct_name = namespace_dir_ + "/" + (tstruct->get_name()) + ".cs"; + ofstream_with_content_based_conditional_update f_struct; + + f_struct.open(f_struct_name.c_str()); + + f_struct << autogen_comment() << netstd_type_usings() << netstd_thrift_usings() << endl; + + generate_netstd_struct_definition(f_struct, tstruct, is_exception); + + f_struct.close(); + + indent_validate(ic, "generate_netstd_struct"); +} + +void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool in_class, bool is_result) +{ + if (!in_class) + { + start_netstd_namespace(out); + } + + out << endl; + + generate_netstd_doc(out, tstruct); + prepare_member_name_mapping(tstruct); + + if ((is_serialize_enabled() || is_wcf_enabled()) && !is_exception) + { + out << indent() << "[DataContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; + } + + bool is_final = tstruct->annotations_.find("final") != tstruct->annotations_.end(); + + string sharp_struct_name = check_and_correct_struct_name(normalize_name(tstruct->get_name())); + + out << indent() << "public " << (is_final ? "sealed " : "") << "partial class " << sharp_struct_name << " : "; + + if (is_exception) + { + out << "TException, "; + } + + out << "TBase" << endl + << indent() << "{" << endl; + indent_up(); + + const vector& members = tstruct->get_members(); + vector::const_iterator m_iter; + + // make private members with public Properties + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) + { + // if the field is required, then we use auto-properties + if (!field_is_required((*m_iter)) && (!is_nullable_enabled() || field_has_default((*m_iter)))) + { + out << indent() << "private " << declare_field(*m_iter, false, "_") << endl; + } + } + out << endl; + + bool has_non_required_fields = false; + bool has_non_required_default_value_fields = false; + bool has_required_fields = false; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) + { + generate_netstd_doc(out, *m_iter); + generate_property(out, *m_iter, true, true); + bool is_required = field_is_required((*m_iter)); + bool has_default = field_has_default((*m_iter)); + if (is_required) + { + has_required_fields = true; + } + else + { + if (has_default) + { + has_non_required_default_value_fields = true; + } + has_non_required_fields = true; + } + } + + bool generate_isset = (is_nullable_enabled() && has_non_required_default_value_fields) || (!is_nullable_enabled() && has_non_required_fields); + if (generate_isset) + { + out << endl; + if (is_serialize_enabled() || is_wcf_enabled()) + { + out << indent() << "[DataMember(Order = 1)]" << endl; + } + out << indent() << "public Isset __isset;" << endl; + if (is_serialize_enabled() || is_wcf_enabled()) + { + out << indent() << "[DataContract]" << endl; + } + + out << indent() << "public struct Isset" << endl + << indent() << "{" << endl; + indent_up(); + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) + { + bool is_required = field_is_required((*m_iter)); + bool has_default = field_has_default((*m_iter)); + // if it is required, don't need Isset for that variable + // if it is not required, if it has a default value, we need to generate Isset + // if we are not nullable, then we generate Isset + if (!is_required && (!is_nullable_enabled() || has_default)) + { + if (is_serialize_enabled() || is_wcf_enabled()) + { + out << indent() << "[DataMember]" << endl; + } + out << indent() << "public bool " << normalize_name((*m_iter)->get_name()) << ";" << endl; + } + } + + indent_down(); + out << indent() << "}" << endl << endl; + + if (generate_isset && (is_serialize_enabled() || is_wcf_enabled())) + { + out << indent() << "#region XmlSerializer support" << endl << endl; + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) + { + bool is_required = field_is_required(*m_iter); + bool has_default = field_has_default(*m_iter); + // if it is required, don't need Isset for that variable + // if it is not required, if it has a default value, we need to generate Isset + // if we are not nullable, then we generate Isset + if (!is_required && (!is_nullable_enabled() || has_default)) + { + out << indent() << "public bool ShouldSerialize" << prop_name(*m_iter) << "()" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "return __isset." << normalize_name((*m_iter)->get_name()) << ";" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + } + } + + out << indent() << "#endregion XmlSerializer support" << endl << endl; + } + } + + // We always want a default, no argument constructor for Reading + out << indent() << "public " << sharp_struct_name << "()" << endl + << indent() << "{" << endl; + indent_up(); + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) + { + t_type* t = (*m_iter)->get_type(); + while (t->is_typedef()) + { + t = static_cast(t)->get_type(); + } + if ((*m_iter)->get_value() != NULL) + { + if (field_is_required((*m_iter))) + { + print_const_value(out, "this." + prop_name(*m_iter), t, (*m_iter)->get_value(), true, true); + } + else + { + print_const_value(out, "this._" + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true); + // Optionals with defaults are marked set + out << indent() << "this.__isset." << normalize_name((*m_iter)->get_name()) << " = true;" << endl; + } + } + } + indent_down(); + out << indent() << "}" << endl << endl; + + if (has_required_fields) + { + out << indent() << "public " << sharp_struct_name << "("; + bool first = true; + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) + { + if (field_is_required(*m_iter)) + { + if (first) + { + first = false; + } + else + { + out << ", "; + } + out << type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name(); + } + } + out << ") : this()" << endl + << indent() << "{" << endl; + indent_up(); + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) + { + if (field_is_required(*m_iter)) + { + out << indent() << "this." << prop_name(*m_iter) << " = " << (*m_iter)->get_name() << ";" << endl; + } + } + + indent_down(); + out << indent() << "}" << endl << endl; + } + + generate_netstd_struct_reader(out, tstruct); + if (is_result) + { + generate_netstd_struct_result_writer(out, tstruct); + } + else + { + generate_netstd_struct_writer(out, tstruct); + } + generate_netstd_struct_equals(out, tstruct); + generate_netstd_struct_hashcode(out, tstruct); + generate_netstd_struct_tostring(out, tstruct); + + indent_down(); + out << indent() << "}" << endl << endl; + + // generate a corresponding WCF fault to wrap the exception + if ((is_serialize_enabled() || is_wcf_enabled()) && is_exception) + { + generate_netstd_wcffault(out, tstruct); + } + + cleanup_member_name_mapping(tstruct); + if (!in_class) + { + end_netstd_namespace(out); + } +} + +void t_netstd_generator::generate_netstd_wcffault(ostream& out, t_struct* tstruct) +{ + out << endl; + out << indent() << "[DataContract]" << endl; + + bool is_final = tstruct->annotations_.find("final") != tstruct->annotations_.end(); + + out << indent() << "public " << (is_final ? "sealed " : "") << "partial class " << tstruct->get_name() << "Fault" << endl + << indent() << "{" << endl; + indent_up(); + + const vector& members = tstruct->get_members(); + vector::const_iterator m_iter; + + // make private members with public Properties + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) + { + out << indent() << "private " << declare_field(*m_iter, false, "_") << endl; + } + out << endl; + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) + { + generate_property(out, *m_iter, true, false); + } + + indent_down(); + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_netstd_struct_reader(ostream& out, t_struct* tstruct) +{ + out << indent() << "public async Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "iprot.IncrementRecursionDepth();" << endl + << indent() << "try" << endl + << indent() << "{" << endl; + indent_up(); + + const vector& fields = tstruct->get_members(); + vector::const_iterator f_iter; + + // Required variables aren't in __isset, so we need tmp vars to check them + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + if (field_is_required(*f_iter)) + { + out << indent() << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl; + } + } + + out << indent() << "TField field;" << endl + << indent() << "await iprot.ReadStructBeginAsync(cancellationToken);" << endl + << indent() << "while (true)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "field = await iprot.ReadFieldBeginAsync(cancellationToken);" << endl + << indent() << "if (field.Type == TType.Stop)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "break;" << endl; + indent_down(); + out << indent() << "}" << endl << endl + << indent() << "switch (field.ID)" << endl + << indent() << "{" << endl; + indent_up(); + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + bool is_required = field_is_required(*f_iter); + out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; + indent_up(); + out << indent() << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ")" << endl + << indent() << "{" << endl; + indent_up(); + + generate_deserialize_field(out, *f_iter); + if (is_required) + { + out << indent() << "isset_" << (*f_iter)->get_name() << " = true;" << endl; + } + + indent_down(); + out << indent() << "}" << endl + << indent() << "else" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);" << endl; + indent_down(); + out << indent() << "}" << endl + << indent() << "break;" << endl; + indent_down(); + } + + out << indent() << "default: " << endl; + indent_up(); + out << indent() << "await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);" << endl + << indent() << "break;" << endl; + indent_down(); + indent_down(); + out << indent() << "}" << endl + << endl + << indent() << "await iprot.ReadFieldEndAsync(cancellationToken);" << endl; + indent_down(); + out << indent() << "}" << endl + << endl + << indent() << "await iprot.ReadStructEndAsync(cancellationToken);" << endl; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + if (field_is_required((*f_iter))) + { + out << indent() << "if (!isset_" << (*f_iter)->get_name() << ")" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl; + indent_down(); + out << indent() << "}" << endl; + } + } + + indent_down(); + out << indent() << "}" << endl; + out << indent() << "finally" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "iprot.DecrementRecursionDepth();" << endl; + indent_down(); + out << indent() << "}" << endl; + indent_down(); + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_netstd_struct_writer(ostream& out, t_struct* tstruct) +{ + out << indent() << "public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl + << indent() << "{" << endl; + indent_up(); + + out << indent() << "oprot.IncrementRecursionDepth();" << endl + << indent() << "try" << endl + << indent() << "{" << endl; + indent_up(); + + string name = tstruct->get_name(); + const vector& fields = tstruct->get_sorted_members(); + vector::const_iterator f_iter; + + out << indent() << "var struc = new TStruct(\"" << name << "\");" << endl + << indent() << "await oprot.WriteStructBeginAsync(struc, cancellationToken);" << endl; + + if (fields.size() > 0) + { + out << indent() << "var field = new TField();" << endl; + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + bool is_required = field_is_required(*f_iter); + bool has_default = field_has_default(*f_iter); + if (is_nullable_enabled() && !has_default && !is_required) + { + out << indent() << "if (" << prop_name(*f_iter) << " != null)" << endl + << indent() << "{" << endl; + indent_up(); + } + else if (!is_required) + { + bool null_allowed = type_can_be_null((*f_iter)->get_type()); + if (null_allowed) + { + out << indent() << "if (" << prop_name(*f_iter) << " != null && __isset." << normalize_name((*f_iter)->get_name()) << ")" << endl + << indent() << "{" << endl; + indent_up(); + } + else + { + out << indent() << "if (__isset." << normalize_name((*f_iter)->get_name()) << ")" << endl + << indent() << "{" << endl; + indent_up(); + } + } + out << indent() << "field.Name = \"" << (*f_iter)->get_name() << "\";" << endl + << indent() << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl + << indent() << "field.ID = " << (*f_iter)->get_key() << ";" << endl + << indent() << "await oprot.WriteFieldBeginAsync(field, cancellationToken);" << endl; + + generate_serialize_field(out, *f_iter); + + out << indent() << "await oprot.WriteFieldEndAsync(cancellationToken);" << endl; + if (!is_required) + { + indent_down(); + out << indent() << "}" << endl; + } + } + } + + out << indent() << "await oprot.WriteFieldStopAsync(cancellationToken);" << endl + << indent() << "await oprot.WriteStructEndAsync(cancellationToken);" << endl; + indent_down(); + out << indent() << "}" << endl + << indent() << "finally" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "oprot.DecrementRecursionDepth();" << endl; + indent_down(); + out << indent() << "}" << endl; + indent_down(); + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_netstd_struct_result_writer(ostream& out, t_struct* tstruct) +{ + out << indent() << "public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl + << indent() << "{" << endl; + indent_up(); + + out << indent() << "oprot.IncrementRecursionDepth();" << endl + << indent() << "try" << endl + << indent() << "{" << endl; + indent_up(); + + string name = tstruct->get_name(); + const vector& fields = tstruct->get_sorted_members(); + vector::const_iterator f_iter; + + out << indent() << "var struc = new TStruct(\"" << name << "\");" << endl + << indent() << "await oprot.WriteStructBeginAsync(struc, cancellationToken);" << endl; + + if (fields.size() > 0) + { + out << indent() << "var field = new TField();" << endl; + bool first = true; + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + if (first) + { + first = false; + out << endl << indent() << "if"; + } + else + { + out << indent() << "else if"; + } + + if (is_nullable_enabled()) + { + out << "(this." << prop_name((*f_iter)) << " != null)" << endl + << indent() << "{" << endl; + } + else + { + out << "(this.__isset." << normalize_name((*f_iter)->get_name()) << ")" << endl + << indent() << "{" << endl; + } + indent_up(); + + bool null_allowed = !is_nullable_enabled() && type_can_be_null((*f_iter)->get_type()); + if (null_allowed) + { + out << indent() << "if (" << prop_name(*f_iter) << " != null)" << endl + << indent() << "{" << endl; + indent_up(); + } + + out << indent() << "field.Name = \"" << prop_name(*f_iter) << "\";" << endl + << indent() << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl + << indent() << "field.ID = " << (*f_iter)->get_key() << ";" << endl + << indent() << "await oprot.WriteFieldBeginAsync(field, cancellationToken);" << endl; + + generate_serialize_field(out, *f_iter); + + out << indent() << "await oprot.WriteFieldEndAsync(cancellationToken);" << endl; + + if (null_allowed) + { + indent_down(); + out << indent() << "}" << endl; + } + + indent_down(); + out << indent() << "}" << endl; + } + } + + out << indent() << "await oprot.WriteFieldStopAsync(cancellationToken);" << endl + << indent() << "await oprot.WriteStructEndAsync(cancellationToken);" << endl; + indent_down(); + out << indent() << "}" << endl + << indent() << "finally" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "oprot.DecrementRecursionDepth();" << endl; + indent_down(); + out << indent() << "}" << endl; + indent_down(); + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_netstd_struct_tostring(ostream& out, t_struct* tstruct) +{ + out << indent() << "public override string ToString()" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "var sb = new StringBuilder(\"" << tstruct->get_name() << "(\");" << endl; + + const vector& fields = tstruct->get_members(); + vector::const_iterator f_iter; + + bool useFirstFlag = false; + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + if (!field_is_required((*f_iter))) + { + out << indent() << "bool __first = true;" << endl; + useFirstFlag = true; + } + break; + } + + bool had_required = false; // set to true after first required field has been processed + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + bool is_required = field_is_required((*f_iter)); + bool has_default = field_has_default((*f_iter)); + if (is_nullable_enabled() && !has_default && !is_required) + { + out << indent() << "if (" << prop_name((*f_iter)) << " != null)" << endl + << indent() << "{" << endl; + indent_up(); + } + else if (!is_required) + { + bool null_allowed = type_can_be_null((*f_iter)->get_type()); + if (null_allowed) + { + out << indent() << "if (" << prop_name((*f_iter)) << " != null && __isset." << normalize_name((*f_iter)->get_name()) << ")" << endl + << indent() << "{" << endl; + indent_up(); + } + else + { + out << indent() << "if (__isset." << normalize_name((*f_iter)->get_name()) << ")" << endl + << indent() << "{" << endl; + indent_up(); + } + } + + if (useFirstFlag && (!had_required)) + { + out << indent() << "if(!__first) { sb.Append(\", \"); }" << endl; + if (!is_required) + { + out << indent() << "__first = false;" << endl; + } + out << indent() << "sb.Append(\"" << prop_name(*f_iter) << ": \");" << endl; + } + else + { + out << indent() << "sb.Append(\", " << prop_name(*f_iter) << ": \");" << endl; + } + + t_type* ttype = (*f_iter)->get_type(); + if (ttype->is_xception() || ttype->is_struct()) + { + out << indent() << "sb.Append(" << prop_name(*f_iter) << "== null ? \"\" : " << prop_name(*f_iter) << ".ToString());" << endl; + } + else + { + out << indent() << "sb.Append(" << prop_name(*f_iter) << ");" << endl; + } + + if (!is_required) + { + indent_down(); + out << indent() << "}" << endl; + } + else + { + had_required = true; // now __first must be false, so we don't need to check it anymore + } + } + + out << indent() << "sb.Append(\")\");" << endl + << indent() << "return sb.ToString();" << endl; + indent_down(); + out << indent() << "}" << endl; +} + +void t_netstd_generator::generate_netstd_union(t_struct* tunion) +{ + int ic = indent_count(); + + string f_union_name = namespace_dir_ + "/" + (tunion->get_name()) + ".cs"; + ofstream_with_content_based_conditional_update f_union; + + f_union.open(f_union_name.c_str()); + + f_union << autogen_comment() << netstd_type_usings() << netstd_thrift_usings() << endl; + + generate_netstd_union_definition(f_union, tunion); + + f_union.close(); + + indent_validate(ic, "generate_netstd_union."); +} + +void t_netstd_generator::generate_netstd_union_definition(ostream& out, t_struct* tunion) +{ + // Let's define the class first + start_netstd_namespace(out); + + out << indent() << "public abstract partial class " << tunion->get_name() << " : TUnionBase" << endl + << indent() << "{" << endl; + indent_up(); + + out << indent() << "public abstract Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken);" << endl + << indent() << "public readonly int Isset;" << endl + << indent() << "public abstract object Data { get; }" << endl + << indent() << "protected " << tunion->get_name() << "(int isset)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "Isset = isset;" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + + out << indent() << "public class ___undefined : " << tunion->get_name() << endl + << indent() << "{" << endl; + indent_up(); + + out << indent() << "public override object Data { get { return null; } }" << endl + << indent() << "public ___undefined() : base(0) {}" << endl << endl; + + out << indent() << "public override Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "throw new TProtocolException( TProtocolException.INVALID_DATA, \"Cannot persist an union type which is not set.\");" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + indent_down(); + out << indent() << "}" << endl << endl; + + const vector& fields = tunion->get_members(); + vector::const_iterator f_iter; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + generate_netstd_union_class(out, tunion, (*f_iter)); + } + + generate_netstd_union_reader(out, tunion); + + indent_down(); + out << indent() << "}" << endl << endl; + + end_netstd_namespace(out); +} + +void t_netstd_generator::generate_netstd_union_class(ostream& out, t_struct* tunion, t_field* tfield) +{ + out << indent() << "public " << type_name(tfield->get_type()) << " As_" << tfield->get_name() << endl; + out << indent() << "{" << endl; + indent_up(); + out << indent() << "get" << endl; + out << indent() << "{" << endl; + indent_up(); + out << indent() << "return (" << tfield->get_key() << " == Isset) ? (" << type_name(tfield->get_type()) << ")Data : default(" << type_name(tfield->get_type()) << ");" << endl; + indent_down(); + out << indent() << "}" << endl; + indent_down(); + out << indent() << "}" << endl + << endl; + + + out << indent() << "public class " << tfield->get_name() << " : " << tunion->get_name() << endl + << indent() << "{" << endl; + indent_up(); + + out << indent() << "private " << type_name(tfield->get_type()) << " _data;" << endl + << indent() << "public override object Data { get { return _data; } }" << endl + << indent() << "public " << tfield->get_name() << "(" << type_name(tfield->get_type()) << " data) : base("<< tfield->get_key() <<")" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "this._data = data;" << endl; + indent_down(); + out << indent() << "}" << endl; + + out << indent() << "public override async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) {" << endl; + indent_up(); + + out << indent() << "oprot.IncrementRecursionDepth();" << endl + << indent() << "try" << endl + << indent() << "{" << endl; + indent_up(); + + out << indent() << "var struc = new TStruct(\"" << tunion->get_name() << "\");" << endl + << indent() << "await oprot.WriteStructBeginAsync(struc, cancellationToken);" << endl; + + out << indent() << "var field = new TField();" << endl + << indent() << "field.Name = \"" << tfield->get_name() << "\";" << endl + << indent() << "field.Type = " << type_to_enum(tfield->get_type()) << ";" << endl + << indent() << "field.ID = " << tfield->get_key() << ";" << endl + << indent() << "await oprot.WriteFieldBeginAsync(field, cancellationToken);" << endl; + + generate_serialize_field(out, tfield, "_data", true, true); + + out << indent() << "await oprot.WriteFieldEndAsync(cancellationToken);" << endl + << indent() << "await oprot.WriteFieldStopAsync(cancellationToken);" << endl + << indent() << "await oprot.WriteStructEndAsync(cancellationToken);" << endl; + indent_down(); + out << indent() << "}" << endl + << indent() << "finally" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "oprot.DecrementRecursionDepth();" << endl; + indent_down(); + out << indent() << "}" << endl; + out << indent() << "}" << endl; + indent_down(); + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_netstd_struct_equals(ostream& out, t_struct* tstruct) +{ + out << indent() << "public override bool Equals(object that)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "var other = that as " << check_and_correct_struct_name(normalize_name(tstruct->get_name())) << ";" << endl + << indent() << "if (other == null) return false;" << endl + << indent() << "if (ReferenceEquals(this, other)) return true;" << endl; + + const vector& fields = tstruct->get_members(); + vector::const_iterator f_iter; + + bool first = true; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + if (first) + { + first = false; + out << indent() << "return "; + indent_up(); + } + else + { + out << endl; + out << indent() << "&& "; + } + if (!field_is_required((*f_iter)) && !(is_nullable_enabled() && !field_has_default((*f_iter)))) + { + out << "((__isset." << normalize_name((*f_iter)->get_name()) << " == other.__isset." + << normalize_name((*f_iter)->get_name()) << ") && ((!__isset." + << normalize_name((*f_iter)->get_name()) << ") || ("; + } + t_type* ttype = (*f_iter)->get_type(); + if (ttype->is_container() || ttype->is_binary()) + { + out << "TCollections.Equals("; + } + else + { + out << "System.Object.Equals("; + } + out << prop_name((*f_iter)) << ", other." << prop_name((*f_iter)) << ")"; + if (!field_is_required((*f_iter)) && !(is_nullable_enabled() && !field_has_default((*f_iter)))) + { + out << ")))"; + } + } + if (first) + { + out << indent() << "return true;" << endl; + } + else + { + out << ";" << endl; + indent_down(); + } + + indent_down(); + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_netstd_struct_hashcode(ostream& out, t_struct* tstruct) +{ + out << indent() << "public override int GetHashCode() {" << endl; + indent_up(); + + out << indent() << "int hashcode = 0;" << endl; + out << indent() << "unchecked {" << endl; + indent_up(); + + const vector& fields = tstruct->get_members(); + vector::const_iterator f_iter; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + t_type* ttype = (*f_iter)->get_type(); + out << indent() << "hashcode = (hashcode * 397) ^ "; + if (field_is_required((*f_iter))) + { + out << "("; + } + else if (is_nullable_enabled()) + { + out << "(" << prop_name((*f_iter)) << " == null ? 0 : "; + } + else + { + out << "(!__isset." << normalize_name((*f_iter)->get_name()) << " ? 0 : "; + } + if (ttype->is_container()) + { + out << "(TCollections.GetHashCode(" << prop_name((*f_iter)) << "))"; + } + else + { + out << "(" << prop_name((*f_iter)) << ".GetHashCode())"; + } + out << ");" << endl; + } + + indent_down(); + out << indent() << "}" << endl; + out << indent() << "return hashcode;" << endl; + + indent_down(); + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_service(t_service* tservice) +{ + int ic = indent_count(); + + string f_service_name = namespace_dir_ + "/" + service_name_ + ".cs"; + ofstream_with_content_based_conditional_update f_service; + f_service.open(f_service_name.c_str()); + + f_service << autogen_comment() << netstd_type_usings() << netstd_thrift_usings() << endl; + + start_netstd_namespace(f_service); + + f_service << indent() << "public partial class " << normalize_name(service_name_) << endl + << indent() << "{" << endl; + indent_up(); + + generate_service_interface(f_service, tservice); + generate_service_client(f_service, tservice); + generate_service_server(f_service, tservice); + generate_service_helpers(f_service, tservice); + + indent_down(); + f_service << indent() << "}" << endl; + + end_netstd_namespace(f_service); + f_service.close(); + + indent_validate(ic, "generate_service."); +} + +void t_netstd_generator::generate_service_interface(ostream& out, t_service* tservice) +{ + string extends = ""; + string extends_iface = ""; + if (tservice->get_extends() != NULL) + { + extends = type_name(tservice->get_extends()); + extends_iface = " : " + extends + ".IAsync"; + } + + //out << endl << endl; + + generate_netstd_doc(out, tservice); + + if (is_wcf_enabled()) + { + out << indent() << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; + } + + out << indent() << "public interface IAsync" << extends_iface << endl + << indent() << "{" << endl; + + indent_up(); + vector functions = tservice->get_functions(); + vector::iterator f_iter; + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) + { + generate_netstd_doc(out, *f_iter); + + // if we're using WCF, add the corresponding attributes + if (is_wcf_enabled()) + { + out << indent() << "[OperationContract]" << endl; + + const vector& xceptions = (*f_iter)->get_xceptions()->get_members(); + vector::const_iterator x_iter; + for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) + { + out << indent() << "[FaultContract(typeof(" + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl; + } + } + + out << indent() << function_signature_async(*f_iter) << ";" << endl << endl; + } + indent_down(); + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_service_helpers(ostream& out, t_service* tservice) +{ + vector functions = tservice->get_functions(); + vector::iterator f_iter; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) + { + t_struct* ts = (*f_iter)->get_arglist(); + generate_netstd_struct_definition(out, ts, false, true); + generate_function_helpers(out, *f_iter); + } +} + +void t_netstd_generator::generate_service_client(ostream& out, t_service* tservice) +{ + string extends = ""; + string extends_client = ""; + if (tservice->get_extends() != NULL) + { + extends = type_name(tservice->get_extends()); + extends_client = extends + ".Client, "; + } + else + { + extends_client = "TBaseClient, IDisposable, "; + } + + out << endl; + + generate_netstd_doc(out, tservice); + + out << indent() << "public class Client : " << extends_client << "IAsync" << endl + << indent() << "{" << endl; + indent_up(); + + out << indent() << "public Client(TProtocol protocol) : this(protocol, protocol)" << endl + << indent() << "{" << endl + << indent() << "}" << endl + << endl + << indent() << "public Client(TProtocol inputProtocol, TProtocol outputProtocol) : base(inputProtocol, outputProtocol)" + << indent() << "{" << endl + << indent() << "}" << endl; + + vector functions = tservice->get_functions(); + vector::const_iterator functions_iterator; + + for (functions_iterator = functions.begin(); functions_iterator != functions.end(); ++functions_iterator) + { + string function_name = correct_function_name_for_async((*functions_iterator)->get_name()); + + // async + out << indent() << "public async " << function_signature_async(*functions_iterator, "") << endl + << indent() << "{" << endl; + indent_up(); + + string argsname = (*functions_iterator)->get_name() + "Args"; + + out << indent() << "await OutputProtocol.WriteMessageBeginAsync(new TMessage(\"" << function_name + << "\", " << ((*functions_iterator)->is_oneway() ? "TMessageType.Oneway" : "TMessageType.Call") << ", SeqId), cancellationToken);" << endl + << indent() << endl + << indent() << "var args = new " << argsname << "();" << endl; + + t_struct* arg_struct = (*functions_iterator)->get_arglist(); + prepare_member_name_mapping(arg_struct); + const vector& fields = arg_struct->get_members(); + vector::const_iterator fld_iter; + + for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) + { + out << indent() << "args." << prop_name(*fld_iter) << " = " << normalize_name((*fld_iter)->get_name()) << ";" << endl; + } + + out << indent() << endl + << indent() << "await args.WriteAsync(OutputProtocol, cancellationToken);" << endl + << indent() << "await OutputProtocol.WriteMessageEndAsync(cancellationToken);" << endl + << indent() << "await OutputProtocol.Transport.FlushAsync(cancellationToken);" << endl; + + if (!(*functions_iterator)->is_oneway()) + { + string resultname = (*functions_iterator)->get_name() + "Result"; + t_struct noargs(program_); + t_struct* xs = (*functions_iterator)->get_xceptions(); + prepare_member_name_mapping(xs, xs->get_members(), resultname); + + out << indent() << endl + << indent() << "var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);" << endl + << indent() << "if (msg.Type == TMessageType.Exception)" << endl + << indent() << "{" << endl; + indent_up(); + + out << indent() << "var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);" << endl + << indent() << "await InputProtocol.ReadMessageEndAsync(cancellationToken);" << endl + << indent() << "throw x;" << endl; + indent_down(); + + out << indent() << "}" << endl + << endl + << indent() << "var result = new " << resultname << "();" << endl + << indent() << "await result.ReadAsync(InputProtocol, cancellationToken);" << endl + << indent() << "await InputProtocol.ReadMessageEndAsync(cancellationToken);" << endl; + + if (!(*functions_iterator)->get_returntype()->is_void()) + { + if (is_nullable_enabled()) + { + if (type_can_be_null((*functions_iterator)->get_returntype())) + { + out << indent() << "if (result.Success != null)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "return result.Success;" << endl; + indent_down(); + out << indent() << "}" << endl; + } + else + { + out << indent() << "if (result.Success.HasValue)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "return result.Success.Value;" << endl; + indent_down(); + out << indent() << "}" << endl; + } + } + else + { + out << indent() << "if (result.__isset.success)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "return result.Success;" << endl; + indent_down(); + out << indent() << "}" << endl; + } + } + + const vector& xceptions = xs->get_members(); + vector::const_iterator x_iter; + for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) + { + if (is_nullable_enabled()) + { + out << indent() << "if (result." << prop_name(*x_iter) << " != null)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "throw result." << prop_name(*x_iter) << ";" << endl; + indent_down(); + out << indent() << "}" << endl; + } + else + { + out << indent() << "if (result.__isset." << normalize_name((*x_iter)->get_name()) << ")" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "throw result." << prop_name(*x_iter) << ";" << endl; + indent_down(); + out << indent() << "}" << endl; + } + } + + if ((*functions_iterator)->get_returntype()->is_void()) + { + out << indent() << "return;" << endl; + } + else + { + out << indent() << "throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, \"" + << function_name << " failed: unknown result\");" << endl; + } + + cleanup_member_name_mapping((*functions_iterator)->get_xceptions()); + indent_down(); + out << indent() << "}" << endl << endl; + } + else + { + indent_down(); + out << indent() << "}" << endl; + } + } + + indent_down(); + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_service_server(ostream& out, t_service* tservice) +{ + vector functions = tservice->get_functions(); + vector::iterator f_iter; + + string extends = ""; + string extends_processor = ""; + if (tservice->get_extends() != NULL) + { + extends = type_name(tservice->get_extends()); + extends_processor = extends + ".AsyncProcessor, "; + } + + out << indent() << "public class AsyncProcessor : " << extends_processor << "ITAsyncProcessor" << endl + << indent() << "{" << endl; + + indent_up(); + + out << indent() << "private IAsync _iAsync;" << endl + << endl + << indent() << "public AsyncProcessor(IAsync iAsync)"; + + if (!extends.empty()) + { + out << " : base(iAsync)"; + } + + out << endl + << indent() << "{" << endl; + indent_up(); + + out << indent() << "if (iAsync == null) throw new ArgumentNullException(nameof(iAsync));" << endl + << endl + << indent() << "_iAsync = iAsync;" << endl; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) + { + string function_name = (*f_iter)->get_name(); + out << indent() << "processMap_[\"" << correct_function_name_for_async(function_name) << "\"] = " << function_name << "_ProcessAsync;" << endl; + } + + indent_down(); + out << indent() << "}" << endl + << endl; + + if (extends.empty()) + { + out << indent() << "protected delegate Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken);" << endl; + } + + if (extends.empty()) + { + out << indent() << "protected Dictionary processMap_ = new Dictionary();" << endl; + } + + out << endl; + + if (extends.empty()) + { + out << indent() << "public async Task ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "return await ProcessAsync(iprot, oprot, CancellationToken.None);" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + + out << indent() << "public async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken)" << endl; + } + else + { + out << indent() << "public new async Task ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "return await ProcessAsync(iprot, oprot, CancellationToken.None);" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + + out << indent() << "public new async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken)" << endl; + } + + out << indent() << "{" << endl; + indent_up(); + out << indent() << "try" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "var msg = await iprot.ReadMessageBeginAsync(cancellationToken);" << endl + << endl + << indent() << "ProcessFunction fn;" << endl + << indent() << "processMap_.TryGetValue(msg.Name, out fn);" << endl + << endl + << indent() << "if (fn == null)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "await TProtocolUtil.SkipAsync(iprot, TType.Struct, cancellationToken);" << endl + << indent() << "await iprot.ReadMessageEndAsync(cancellationToken);" << endl + << indent() << "var x = new TApplicationException (TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + msg.Name + \"'\");" << endl + << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID), cancellationToken);" << endl + << indent() << "await x.WriteAsync(oprot, cancellationToken);" << endl + << indent() << "await oprot.WriteMessageEndAsync(cancellationToken);" << endl + << indent() << "await oprot.Transport.FlushAsync(cancellationToken);" << endl + << indent() << "return true;" << endl; + indent_down(); + out << indent() << "}" << endl + << endl + << indent() << "await fn(msg.SeqID, iprot, oprot, cancellationToken);" << endl + << endl; + indent_down(); + out << indent() << "}" << endl; + out << indent() << "catch (IOException)" << endl + << indent() << "{" << endl; + indent_up(); + out << indent() << "return false;" << endl; + indent_down(); + out << indent() << "}" << endl + << endl + << indent() << "return true;" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) + { + generate_process_function_async(out, tservice, *f_iter); + } + + indent_down(); + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_function_helpers(ostream& out, t_function* tfunction) +{ + if (tfunction->is_oneway()) + { + return; + } + + t_struct result(program_, tfunction->get_name() + "_result"); + t_field success(tfunction->get_returntype(), "success", 0); + if (!tfunction->get_returntype()->is_void()) + { + result.append(&success); + } + + t_struct* xs = tfunction->get_xceptions(); + const vector& fields = xs->get_members(); + vector::const_iterator f_iter; + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + result.append(*f_iter); + } + + generate_netstd_struct_definition(out, &result, false, true, true); +} + +void t_netstd_generator::generate_process_function_async(ostream& out, t_service* tservice, t_function* tfunction) +{ + (void)tservice; + out << indent() << "public async Task " << tfunction->get_name() + << "_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken)" << endl + << indent() << "{" << endl; + indent_up(); + + string argsname = tfunction->get_name() + "Args"; + string resultname = tfunction->get_name() + "Result"; + + out << indent() << "var args = new " << argsname << "();" << endl + << indent() << "await args.ReadAsync(iprot, cancellationToken);" << endl + << indent() << "await iprot.ReadMessageEndAsync(cancellationToken);" << endl; + + if (!tfunction->is_oneway()) + { + out << indent() << "var result = new " << resultname << "();" << endl; + } + + out << indent() << "try" << endl + << indent() << "{" << endl; + indent_up(); + + t_struct* xs = tfunction->get_xceptions(); + const vector& xceptions = xs->get_members(); + + if (xceptions.size() > 0) + { + out << indent() << "try" << endl + << indent() << "{" << endl; + indent_up(); + } + + t_struct* arg_struct = tfunction->get_arglist(); + const vector& fields = arg_struct->get_members(); + vector::const_iterator f_iter; + + out << indent(); + if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) + { + out << "result.Success = "; + } + + out << "await _iAsync." << normalize_name(tfunction->get_name()) << "Async("; + + bool first = true; + prepare_member_name_mapping(arg_struct); + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + if (first) + { + first = false; + } + else + { + out << ", "; + } + + out << "args." << prop_name(*f_iter); + if (is_nullable_enabled() && !type_can_be_null((*f_iter)->get_type())) + { + out << ".Value"; + } + } + + cleanup_member_name_mapping(arg_struct); + + if (!first) + { + out << ", "; + } + + out << "cancellationToken);" << endl; + + vector::const_iterator x_iter; + + prepare_member_name_mapping(xs, xs->get_members(), resultname); + if (xceptions.size() > 0) + { + indent_down(); + out << indent() << "}" << endl; + + for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) + { + out << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " " << (*x_iter)->get_name() << ")" << endl + << indent() << "{" << endl; + + if (!tfunction->is_oneway()) + { + indent_up(); + out << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name() << ";" << endl; + indent_down(); + } + out << indent() << "}" << endl; + } + } + + if (!tfunction->is_oneway()) + { + out << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\"" + << correct_function_name_for_async(tfunction->get_name()) << "\", TMessageType.Reply, seqid), cancellationToken); " << endl + << indent() << "await result.WriteAsync(oprot, cancellationToken);" << endl; + } + indent_down(); + + cleanup_member_name_mapping(xs); + + out << indent() << "}" << endl + << indent() << "catch (TTransportException)" << endl + << indent() << "{" << endl + << indent() << " throw;" << endl + << indent() << "}" << endl + << indent() << "catch (Exception ex)" << endl + << indent() << "{" << endl; + indent_up(); + + out << indent() << "Console.Error.WriteLine(\"Error occurred in processor:\");" << endl + << indent() << "Console.Error.WriteLine(ex.ToString());" << endl; + + if (tfunction->is_oneway()) + { + indent_down(); + out << indent() << "}" << endl; + } + else + { + out << indent() << "var x = new TApplicationException(TApplicationException.ExceptionType.InternalError,\" Internal error.\");" << endl + << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\"" << correct_function_name_for_async(tfunction->get_name()) + << "\", TMessageType.Exception, seqid), cancellationToken);" << endl + << indent() << "await x.WriteAsync(oprot, cancellationToken);" << endl; + indent_down(); + + out << indent() << "}" << endl + << indent() << "await oprot.WriteMessageEndAsync(cancellationToken);" << endl + << indent() << "await oprot.Transport.FlushAsync(cancellationToken);" << endl; + } + + indent_down(); + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_netstd_union_reader(ostream& out, t_struct* tunion) +{ + // Thanks to THRIFT-1768, we don't need to check for required fields in the union + const vector& fields = tunion->get_members(); + vector::const_iterator f_iter; + + out << indent() << "public static async Task<" << tunion->get_name() << "> ReadAsync(TProtocol iprot, CancellationToken cancellationToken)" << endl; + scope_up(out); + + out << indent() << "iprot.IncrementRecursionDepth();" << endl; + out << indent() << "try" << endl; + scope_up(out); + + out << indent() << tunion->get_name() << " retval;" << endl; + out << indent() << "await iprot.ReadStructBeginAsync(cancellationToken);" << endl; + out << indent() << "TField field = await iprot.ReadFieldBeginAsync(cancellationToken);" << endl; + // we cannot have the first field be a stop -- we must have a single field defined + out << indent() << "if (field.Type == TType.Stop)" << endl; + scope_up(out); + out << indent() << "await iprot.ReadFieldEndAsync(cancellationToken);" << endl; + out << indent() << "retval = new ___undefined();" << endl; + scope_down(out); + out << indent() << "else" << endl; + scope_up(out); + out << indent() << "switch (field.ID)" << endl; + scope_up(out); + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; + indent_up(); + out << indent() << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; + indent_up(); + + out << indent() << type_name((*f_iter)->get_type()) << " temp;" << endl; + generate_deserialize_field(out, (*f_iter), "temp", true); + out << indent() << "retval = new " << (*f_iter)->get_name() << "(temp);" << endl; + + indent_down(); + out << indent() << "} else { " << endl << indent() << " await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);" + << endl << indent() << " retval = new ___undefined();" << endl << indent() << "}" << endl + << indent() << "break;" << endl; + indent_down(); + } + + out << indent() << "default: " << endl; + indent_up(); + out << indent() << "await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);" << endl << indent() + << "retval = new ___undefined();" << endl; + out << indent() << "break;" << endl; + indent_down(); + + scope_down(out); + + out << indent() << "await iprot.ReadFieldEndAsync(cancellationToken);" << endl; + + out << indent() << "if ((await iprot.ReadFieldBeginAsync(cancellationToken)).Type != TType.Stop)" << endl; + scope_up(out); + out << indent() << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl; + scope_down(out); + + // end of else for TStop + scope_down(out); + out << indent() << "await iprot.ReadStructEndAsync(cancellationToken);" << endl; + out << indent() << "return retval;" << endl; + indent_down(); + + scope_down(out); + out << indent() << "finally" << endl; + scope_up(out); + out << indent() << "iprot.DecrementRecursionDepth();" << endl; + scope_down(out); + + out << indent() << "}" << endl << endl; +} + +void t_netstd_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, bool is_propertyless) +{ + t_type* type = tfield->get_type(); + while (type->is_typedef()) + { + type = static_cast(type)->get_type(); + } + + if (type->is_void()) + { + throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); + } + + string name = prefix + (is_propertyless ? "" : prop_name(tfield)); + + if (type->is_struct() || type->is_xception()) + { + generate_deserialize_struct(out, static_cast(type), name); + } + else if (type->is_container()) + { + generate_deserialize_container(out, type, name); + } + else if (type->is_base_type() || type->is_enum()) + { + out << indent() << name << " = "; + + if (type->is_enum()) + { + out << "(" << type_name(type, false, true) << ")"; + } + + out << "await iprot."; + + if (type->is_base_type()) + { + t_base_type::t_base tbase = static_cast(type)->get_base(); + switch (tbase) + { + case t_base_type::TYPE_VOID: + throw "compiler error: cannot serialize void field in a struct: " + name; + break; + case t_base_type::TYPE_STRING: + if (type->is_binary()) + { + out << "ReadBinaryAsync(cancellationToken);"; + } + else + { + out << "ReadStringAsync(cancellationToken);"; + } + break; + case t_base_type::TYPE_BOOL: + out << "ReadBoolAsync(cancellationToken);"; + break; + case t_base_type::TYPE_I8: + out << "ReadByteAsync(cancellationToken);"; + break; + case t_base_type::TYPE_I16: + out << "ReadI16Async(cancellationToken);"; + break; + case t_base_type::TYPE_I32: + out << "ReadI32Async(cancellationToken);"; + break; + case t_base_type::TYPE_I64: + out << "ReadI64Async(cancellationToken);"; + break; + case t_base_type::TYPE_DOUBLE: + out << "ReadDoubleAsync(cancellationToken);"; + break; + default: + throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase); + } + } + else if (type->is_enum()) + { + out << "ReadI32Async(cancellationToken);"; + } + out << endl; + } + else + { + printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type_name(type).c_str()); + } +} + +void t_netstd_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) +{ + if (is_union_enabled() && tstruct->is_union()) + { + out << indent() << prefix << " = await " << type_name(tstruct) << ".ReadAsync(iprot, cancellationToken);" << endl; + } + else + { + out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl + << indent() << "await " << prefix << ".ReadAsync(iprot, cancellationToken);" << endl; + } +} + +void t_netstd_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) +{ + out << indent() << "{" << endl; + indent_up(); + + string obj; + + if (ttype->is_map()) + { + obj = tmp("_map"); + } + else if (ttype->is_set()) + { + obj = tmp("_set"); + } + else if (ttype->is_list()) + { + obj = tmp("_list"); + } + + out << indent() << prefix << " = new " << type_name(ttype, false, true) << "();" << endl; + if (ttype->is_map()) + { + out << indent() << "TMap " << obj << " = await iprot.ReadMapBeginAsync(cancellationToken);" << endl; + } + else if (ttype->is_set()) + { + out << indent() << "TSet " << obj << " = await iprot.ReadSetBeginAsync(cancellationToken);" << endl; + } + else if (ttype->is_list()) + { + out << indent() << "TList " << obj << " = await iprot.ReadListBeginAsync(cancellationToken);" << endl; + } + + string i = tmp("_i"); + out << indent() << "for(int " << i << " = 0; " << i << " < " << obj << ".Count; ++" << i << ")" << endl + << indent() << "{" << endl; + indent_up(); + + if (ttype->is_map()) + { + generate_deserialize_map_element(out, static_cast(ttype), prefix); + } + else if (ttype->is_set()) + { + generate_deserialize_set_element(out, static_cast(ttype), prefix); + } + else if (ttype->is_list()) + { + generate_deserialize_list_element(out, static_cast(ttype), prefix); + } + + indent_down(); + out << indent() << "}" << endl; + + if (ttype->is_map()) + { + out << indent() << "await iprot.ReadMapEndAsync(cancellationToken);" << endl; + } + else if (ttype->is_set()) + { + out << indent() << "await iprot.ReadSetEndAsync(cancellationToken);" << endl; + } + else if (ttype->is_list()) + { + out << indent() << "await iprot.ReadListEndAsync(cancellationToken);" << endl; + } + + indent_down(); + out << indent() << "}" << endl; +} + +void t_netstd_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) +{ + string key = tmp("_key"); + string val = tmp("_val"); + + t_field fkey(tmap->get_key_type(), key); + t_field fval(tmap->get_val_type(), val); + + out << indent() << declare_field(&fkey) << endl; + out << indent() << declare_field(&fval) << endl; + + generate_deserialize_field(out, &fkey); + generate_deserialize_field(out, &fval); + + out << indent() << prefix << "[" << key << "] = " << val << ";" << endl; +} + +void t_netstd_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) +{ + string elem = tmp("_elem"); + t_field felem(tset->get_elem_type(), elem); + + out << indent() << declare_field(&felem) << endl; + + generate_deserialize_field(out, &felem); + + out << indent() << prefix << ".Add(" << elem << ");" << endl; +} + +void t_netstd_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix) +{ + string elem = tmp("_elem"); + t_field felem(tlist->get_elem_type(), elem); + + out << indent() << declare_field(&felem) << endl; + + generate_deserialize_field(out, &felem); + + out << indent() << prefix << ".Add(" << elem << ");" << endl; +} + +void t_netstd_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix, bool is_element, bool is_propertyless) +{ + t_type* type = tfield->get_type(); + while (type->is_typedef()) + { + type = static_cast(type)->get_type(); + } + + string name = prefix + (is_propertyless ? "" : prop_name(tfield)); + + if (type->is_void()) + { + throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; + } + + if (type->is_struct() || type->is_xception()) + { + generate_serialize_struct(out, static_cast(type), name); + } + else if (type->is_container()) + { + generate_serialize_container(out, type, name); + } + else if (type->is_base_type() || type->is_enum()) + { + out << indent() << "await oprot."; + + string nullable_name = is_nullable_enabled() && !is_element && !field_is_required(tfield) ? name + ".Value" : name; + + if (type->is_base_type()) + { + t_base_type::t_base tbase = static_cast(type)->get_base(); + switch (tbase) + { + case t_base_type::TYPE_VOID: + throw "compiler error: cannot serialize void field in a struct: " + name; + case t_base_type::TYPE_STRING: + if (type->is_binary()) + { + out << "WriteBinaryAsync("; + } + else + { + out << "WriteStringAsync("; + } + out << name << ", cancellationToken);"; + break; + case t_base_type::TYPE_BOOL: + out << "WriteBoolAsync(" << nullable_name << ", cancellationToken);"; + break; + case t_base_type::TYPE_I8: + out << "WriteByteAsync(" << nullable_name << ", cancellationToken);"; + break; + case t_base_type::TYPE_I16: + out << "WriteI16Async(" << nullable_name << ", cancellationToken);"; + break; + case t_base_type::TYPE_I32: + out << "WriteI32Async(" << nullable_name << ", cancellationToken);"; + break; + case t_base_type::TYPE_I64: + out << "WriteI64Async(" << nullable_name << ", cancellationToken);"; + break; + case t_base_type::TYPE_DOUBLE: + out << "WriteDoubleAsync(" << nullable_name << ", cancellationToken);"; + break; + default: + throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase); + } + } + else if (type->is_enum()) + { + out << "WriteI32Async((int)" << nullable_name << ", cancellationToken);"; + } + out << endl; + } + else + { + printf("DO NOT KNOW HOW TO SERIALIZE '%s%s' TYPE '%s'\n", prefix.c_str(), tfield->get_name().c_str(), type_name(type).c_str()); + } +} + +void t_netstd_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) +{ + (void)tstruct; + out << indent() << "await " << prefix << ".WriteAsync(oprot, cancellationToken);" << endl; +} + +void t_netstd_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) +{ + out << indent() << "{" << endl; + indent_up(); + + if (ttype->is_map()) + { + out << indent() << "await oprot.WriteMapBeginAsync(new TMap(" << type_to_enum(static_cast(ttype)->get_key_type()) + << ", " << type_to_enum(static_cast(ttype)->get_val_type()) << ", " << prefix + << ".Count), cancellationToken);" << endl; + } + else if (ttype->is_set()) + { + out << indent() << "await oprot.WriteSetBeginAsync(new TSet(" << type_to_enum(static_cast(ttype)->get_elem_type()) + << ", " << prefix << ".Count), cancellationToken);" << endl; + } + else if (ttype->is_list()) + { + out << indent() << "await oprot.WriteListBeginAsync(new TList(" + << type_to_enum(static_cast(ttype)->get_elem_type()) << ", " << prefix << ".Count), cancellationToken);" + << endl; + } + + string iter = tmp("_iter"); + if (ttype->is_map()) + { + out << indent() << "foreach (" << type_name(static_cast(ttype)->get_key_type()) << " " << iter + << " in " << prefix << ".Keys)"; + } + else if (ttype->is_set()) + { + out << indent() << "foreach (" << type_name(static_cast(ttype)->get_elem_type()) << " " << iter + << " in " << prefix << ")"; + } + else if (ttype->is_list()) + { + out << indent() << "foreach (" << type_name(static_cast(ttype)->get_elem_type()) << " " << iter + << " in " << prefix << ")"; + } + + out << endl; + out << indent() << "{" << endl; + indent_up(); + + if (ttype->is_map()) + { + generate_serialize_map_element(out, static_cast(ttype), iter, prefix); + } + else if (ttype->is_set()) + { + generate_serialize_set_element(out, static_cast(ttype), iter); + } + else if (ttype->is_list()) + { + generate_serialize_list_element(out, static_cast(ttype), iter); + } + + indent_down(); + out << indent() << "}" << endl; + + if (ttype->is_map()) + { + out << indent() << "await oprot.WriteMapEndAsync(cancellationToken);" << endl; + } + else if (ttype->is_set()) + { + out << indent() << "await oprot.WriteSetEndAsync(cancellationToken);" << endl; + } + else if (ttype->is_list()) + { + out << indent() << "await oprot.WriteListEndAsync(cancellationToken);" << endl; + } + + indent_down(); + out << indent() << "}" << endl; +} + +void t_netstd_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map) +{ + t_field kfield(tmap->get_key_type(), iter); + generate_serialize_field(out, &kfield, "", true); + t_field vfield(tmap->get_val_type(), map + "[" + iter + "]"); + generate_serialize_field(out, &vfield, "", true); +} + +void t_netstd_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) +{ + t_field efield(tset->get_elem_type(), iter); + generate_serialize_field(out, &efield, "", true); +} + +void t_netstd_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) +{ + t_field efield(tlist->get_elem_type(), iter); + generate_serialize_field(out, &efield, "", true); +} + +void t_netstd_generator::generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset) +{ + generate_netstd_property(out, tfield, isPublic, generateIsset, "_"); +} + +void t_netstd_generator::generate_netstd_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset, string fieldPrefix) +{ + if ((is_serialize_enabled() || is_wcf_enabled()) && isPublic) + { + out << indent() << "[DataMember(Order = 0)]" << endl; + } + bool has_default = field_has_default(tfield); + bool is_required = field_is_required(tfield); + if ((is_nullable_enabled() && !has_default) || is_required) + { + out << indent() << (isPublic ? "public " : "private ") << type_name(tfield->get_type(), false, false, true, is_required) << " " << prop_name(tfield) << " { get; set; }" << endl; + } + else + { + out << indent() << (isPublic ? "public " : "private ") << type_name(tfield->get_type(), false, false, true) << " " << prop_name(tfield) << endl + << indent() << "{" << endl; + indent_up(); + + out << indent() << "get" << endl + << indent() << "{" << endl; + indent_up(); + + bool use_nullable = false; + if (is_nullable_enabled()) + { + t_type* ttype = tfield->get_type(); + while (ttype->is_typedef()) + { + ttype = static_cast(ttype)->get_type(); + } + if (ttype->is_base_type()) + { + use_nullable = static_cast(ttype)->get_base() != t_base_type::TYPE_STRING; + } + } + + out << indent() << "return " << fieldPrefix + tfield->get_name() << ";" << endl; + indent_down(); + out << indent() << "}" << endl + << indent() << "set" << endl + << indent() << "{" << endl; + indent_up(); + + if (use_nullable) + { + if (generateIsset) + { + out << indent() << "__isset." << normalize_name(tfield->get_name()) << " = value.HasValue;" << endl; + } + out << indent() << "if (value.HasValue) this." << fieldPrefix + tfield->get_name() << " = value.Value;" << endl; + } + else + { + if (generateIsset) + { + out << indent() << "__isset." << normalize_name(tfield->get_name()) << " = true;" << endl; + } + out << indent() << "this." << fieldPrefix + tfield->get_name() << " = value;" << endl; + } + + indent_down(); + out << indent() << "}" << endl; + indent_down(); + out << indent() << "}" << endl; + } + out << endl; +} + +string t_netstd_generator::make_valid_csharp_identifier(string const& fromName) +{ + string str = fromName; + if (str.empty()) + { + return str; + } + + // tests rely on this + assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9')); + + // if the first letter is a number, we add an additional underscore in front of it + char c = str.at(0); + if (('0' <= c) && (c <= '9')) + { + str = "_" + str; + } + + // following chars: letter, number or underscore + for (size_t i = 0; i < str.size(); ++i) + { + c = str.at(i); + if (('A' > c || c > 'Z') && ('a' > c || c > 'z') && ('0' > c || c > '9') && '_' != c) + { + str.replace(i, 1, "_"); + } + } + + return str; +} + +void t_netstd_generator::cleanup_member_name_mapping(void* scope) +{ + if (member_mapping_scopes.empty()) + { + throw "internal error: cleanup_member_name_mapping() no scope active"; + } + + member_mapping_scope& active = member_mapping_scopes.back(); + if (active.scope_member != scope) + { + throw "internal error: cleanup_member_name_mapping() called for wrong struct"; + } + + member_mapping_scopes.pop_back(); +} + +string t_netstd_generator::get_mapped_member_name(string name) +{ + if (!member_mapping_scopes.empty()) + { + member_mapping_scope& active = member_mapping_scopes.back(); + map::iterator iter = active.mapping_table.find(name); + if (active.mapping_table.end() != iter) + { + return iter->second; + } + } + + pverbose("no mapping for member %s\n", name.c_str()); + return name; +} + +void t_netstd_generator::prepare_member_name_mapping(t_struct* tstruct) +{ + prepare_member_name_mapping(tstruct, tstruct->get_members(), tstruct->get_name()); +} + +void t_netstd_generator::prepare_member_name_mapping(void* scope, const vector& members, const string& structname) +{ + // begin new scope + member_mapping_scopes.push_back(member_mapping_scope()); + member_mapping_scope& active = member_mapping_scopes.back(); + active.scope_member = scope; + + // current C# generator policy: + // - prop names are always rendered with an Uppercase first letter + // - struct names are used as given + std::set used_member_names; + vector::const_iterator iter; + + // prevent name conflicts with struct (CS0542 error) + used_member_names.insert(structname); + + // prevent name conflicts with known methods (THRIFT-2942) + used_member_names.insert("Read"); + used_member_names.insert("Write"); + + for (iter = members.begin(); iter != members.end(); ++iter) + { + string oldname = (*iter)->get_name(); + string newname = prop_name(*iter, true); + while (true) + { + // new name conflicts with another member + if (used_member_names.find(newname) != used_member_names.end()) + { + pverbose("struct %s: member %s conflicts with another member\n", structname.c_str(), newname.c_str()); + newname += '_'; + continue; + } + + // add always, this helps us to detect edge cases like + // different spellings ("foo" and "Foo") within the same struct + pverbose("struct %s: member mapping %s => %s\n", structname.c_str(), oldname.c_str(), newname.c_str()); + active.mapping_table[oldname] = newname; + used_member_names.insert(newname); + break; + } + } +} + +string t_netstd_generator::prop_name(t_field* tfield, bool suppress_mapping) +{ + string name(tfield->get_name()); + if (suppress_mapping) + { + name[0] = toupper(name[0]); + } + else + { + name = get_mapped_member_name(name); + } + return name; +} + +string t_netstd_generator::type_name(t_type* ttype, bool in_container, bool in_init, bool in_param, bool is_required) +{ + (void)in_init; + + while (ttype->is_typedef()) + { + ttype = static_cast(ttype)->get_type(); + } + + if (ttype->is_base_type()) + { + return base_type_name(static_cast(ttype), in_container, in_param, is_required); + } + + if (ttype->is_map()) + { + t_map* tmap = static_cast(ttype); + return "Dictionary<" + type_name(tmap->get_key_type(), true) + ", " + type_name(tmap->get_val_type(), true) + ">"; + } + + if (ttype->is_set()) + { + t_set* tset = static_cast(ttype); + return "THashSet<" + type_name(tset->get_elem_type(), true) + ">"; + } + + if (ttype->is_list()) + { + t_list* tlist = static_cast(ttype); + return "List<" + type_name(tlist->get_elem_type(), true) + ">"; + } + + t_program* program = ttype->get_program(); + string postfix = (!is_required && is_nullable_enabled() && in_param && ttype->is_enum()) ? "?" : ""; + if (program != NULL && program != program_) + { + string ns = program->get_namespace("netstd"); + if (!ns.empty()) + { + return ns + "." + normalize_name(ttype->get_name()) + postfix; + } + } + + return normalize_name(ttype->get_name()) + postfix; +} + +string t_netstd_generator::base_type_name(t_base_type* tbase, bool in_container, bool in_param, bool is_required) +{ + (void)in_container; + string postfix = (!is_required && is_nullable_enabled() && in_param) ? "?" : ""; + switch (tbase->get_base()) + { + case t_base_type::TYPE_VOID: + return "void"; + case t_base_type::TYPE_STRING: + { + if (tbase->is_binary()) + { + return "byte[]"; + } + return "string"; + } + case t_base_type::TYPE_BOOL: + return "bool" + postfix; + case t_base_type::TYPE_I8: + return "sbyte" + postfix; + case t_base_type::TYPE_I16: + return "short" + postfix; + case t_base_type::TYPE_I32: + return "int" + postfix; + case t_base_type::TYPE_I64: + return "long" + postfix; + case t_base_type::TYPE_DOUBLE: + return "double" + postfix; + default: + throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase->get_base()); + } +} + +string t_netstd_generator::declare_field(t_field* tfield, bool init, string prefix) +{ + string result = type_name(tfield->get_type()) + " " + prefix + tfield->get_name(); + if (init) + { + t_type* ttype = tfield->get_type(); + while (ttype->is_typedef()) + { + ttype = static_cast(ttype)->get_type(); + } + if (ttype->is_base_type() && field_has_default(tfield)) + { + std::ofstream dummy; + result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value()); + } + else if (ttype->is_base_type()) + { + t_base_type::t_base tbase = static_cast(ttype)->get_base(); + switch (tbase) + { + case t_base_type::TYPE_VOID: + throw "NO T_VOID CONSTRUCT"; + case t_base_type::TYPE_STRING: + result += " = null"; + break; + case t_base_type::TYPE_BOOL: + result += " = false"; + break; + case t_base_type::TYPE_I8: + case t_base_type::TYPE_I16: + case t_base_type::TYPE_I32: + case t_base_type::TYPE_I64: + result += " = 0"; + break; + case t_base_type::TYPE_DOUBLE: + result += " = (double)0"; + break; + } + } + else if (ttype->is_enum()) + { + result += " = (" + type_name(ttype, false, true) + ")0"; + } + else if (ttype->is_container()) + { + result += " = new " + type_name(ttype, false, true) + "()"; + } + else + { + result += " = new " + type_name(ttype, false, true) + "()"; + } + } + return result + ";"; +} + +string t_netstd_generator::function_signature(t_function* tfunction, string prefix) +{ + t_type* ttype = tfunction->get_returntype(); + return type_name(ttype) + " " + normalize_name(prefix + tfunction->get_name()) + "(" + argument_list(tfunction->get_arglist()) + ")"; +} + +string t_netstd_generator::function_signature_async(t_function* tfunction, string prefix) +{ + t_type* ttype = tfunction->get_returntype(); + string task = "Task"; + if (!ttype->is_void()) + { + task += "<" + type_name(ttype) + ">"; + } + + string result = task + " " + normalize_name(prefix + tfunction->get_name()) + "Async("; + string args = argument_list(tfunction->get_arglist()); + result += args; + if (!args.empty()) + { + result += ", "; + } + result += "CancellationToken cancellationToken = default(CancellationToken))"; + + return result; +} + +string t_netstd_generator::argument_list(t_struct* tstruct) +{ + string result = ""; + const vector& fields = tstruct->get_members(); + vector::const_iterator f_iter; + bool first = true; + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + if (first) + { + first = false; + } + else + { + result += ", "; + } + result += type_name((*f_iter)->get_type()) + " " + normalize_name((*f_iter)->get_name()); + } + return result; +} + +string t_netstd_generator::type_to_enum(t_type* type) +{ + while (type->is_typedef()) + { + type = static_cast(type)->get_type(); + } + + if (type->is_base_type()) + { + t_base_type::t_base tbase = static_cast(type)->get_base(); + switch (tbase) + { + case t_base_type::TYPE_VOID: + throw "NO T_VOID CONSTRUCT"; + case t_base_type::TYPE_STRING: + return "TType.String"; + case t_base_type::TYPE_BOOL: + return "TType.Bool"; + case t_base_type::TYPE_I8: + return "TType.Byte"; + case t_base_type::TYPE_I16: + return "TType.I16"; + case t_base_type::TYPE_I32: + return "TType.I32"; + case t_base_type::TYPE_I64: + return "TType.I64"; + case t_base_type::TYPE_DOUBLE: + return "TType.Double"; + } + } + else if (type->is_enum()) + { + return "TType.I32"; + } + else if (type->is_struct() || type->is_xception()) + { + return "TType.Struct"; + } + else if (type->is_map()) + { + return "TType.Map"; + } + else if (type->is_set()) + { + return "TType.Set"; + } + else if (type->is_list()) + { + return "TType.List"; + } + + throw "INVALID TYPE IN type_to_enum: " + type->get_name(); +} + +void t_netstd_generator::generate_netstd_docstring_comment(ostream& out, string contents) +{ + docstring_comment(out, "/// " + endl, "/// ", contents, "/// " + endl); +} + +void t_netstd_generator::generate_netstd_doc(ostream& out, t_field* field) +{ + if (field->get_type()->is_enum()) + { + string combined_message = field->get_doc() + endl + "get_type()) + "\"/>"; + generate_netstd_docstring_comment(out, combined_message); + } + else + { + generate_netstd_doc(out, static_cast(field)); + } +} + +void t_netstd_generator::generate_netstd_doc(ostream& out, t_doc* tdoc) +{ + if (tdoc->has_doc()) + { + generate_netstd_docstring_comment(out, tdoc->get_doc()); + } +} + +void t_netstd_generator::generate_netstd_doc(ostream& out, t_function* tfunction) +{ + if (tfunction->has_doc()) + { + stringstream ps; + const vector& fields = tfunction->get_arglist()->get_members(); + vector::const_iterator p_iter; + for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) + { + t_field* p = *p_iter; + ps << endl << "get_name() << "\">"; + if (p->has_doc()) + { + string str = p->get_doc(); + str.erase(remove(str.begin(), str.end(), '\n'), str.end()); + ps << str; + } + ps << ""; + } + + docstring_comment(out, + "", + "/// ", + "" + endl + tfunction->get_doc() + "" + ps.str(), + ""); + } +} + +void t_netstd_generator::docstring_comment(ostream& out, const string& comment_start, const string& line_prefix, const string& contents, const string& comment_end) +{ + if (comment_start != "") + { + out << indent() << comment_start; + } + + stringstream docs(contents, std::ios_base::in); + + while (!(docs.eof() || docs.fail())) + { + char line[1024]; + docs.getline(line, 1024); + + // Just prnt a newline when the line & prefix are empty. + if (strlen(line) == 0 && line_prefix == "" && !docs.eof()) + { + out << endl; + } + else if (strlen(line) > 0 || !docs.eof()) + { // skip the empty last line + out << indent() << line_prefix << line << endl; + } + } + if (comment_end != "") + { + out << indent() << comment_end; + } +} + +string t_netstd_generator::get_enum_class_name(t_type* type) +{ + string package = ""; + t_program* program = type->get_program(); + if (program != NULL && program != program_) + { + package = program->get_namespace("netstd") + "."; + } + return package + type->get_name(); +} + +THRIFT_REGISTER_GENERATOR( + netstd, + "C#", + " wcf: Adds bindings for WCF to generated classes.\n" + " serial: Add serialization support to generated classes.\n" + //" nullable: Use nullable types for properties.\n" + " union: Use new union typing, which includes a static read function for union types.\n" +) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.h b/compiler/cpp/src/thrift/generate/t_netstd_generator.h new file mode 100644 index 00000000000..9a49dd5be8f --- /dev/null +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.h @@ -0,0 +1,160 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "thrift/platform.h" +#include "thrift/generate/t_oop_generator.h" + +using std::map; +using std::ostream; +using std::ostringstream; +using std::string; +using std::stringstream; +using std::vector; + +static const string endl = "\n"; // avoid ostream << std::endl flushes + +class t_netstd_generator : public t_oop_generator +{ + + struct member_mapping_scope + { + public: + member_mapping_scope() : scope_member(0) { } + void* scope_member; + map mapping_table; + }; + +public: + t_netstd_generator(t_program* program, const map& parsed_options, const string& option_string); + + bool is_wcf_enabled() const; + bool is_nullable_enabled() const; + bool is_hashcode_enabled() const; + bool is_serialize_enabled() const; + bool is_union_enabled() const; + map get_keywords_list() const; + + // overrides + void init_generator(); + void close_generator(); + void generate_consts(vector consts); + void generate_consts(ostream& out, vector consts); + void generate_typedef(t_typedef* ttypedef); + void generate_enum(t_enum* tenum); + void generate_enum(ostream& out, t_enum* tenum); + void generate_struct(t_struct* tstruct); + void generate_xception(t_struct* txception); + void generate_service(t_service* tservice); + + void generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset); + void generate_netstd_property(ostream& out, t_field* tfield, bool isPublic, bool includeIsset = true, string fieldPrefix = ""); + bool print_const_value(ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval = false, bool needtype = false); + string render_const_value(ostream& out, string name, t_type* type, t_const_value* value); + void print_const_constructor(ostream& out, vector consts); + void print_const_def_value(ostream& out, string name, t_type* type, t_const_value* value); + void generate_netstd_struct(t_struct* tstruct, bool is_exception); + void generate_netstd_union(t_struct* tunion); + void generate_netstd_struct_definition(ostream& out, t_struct* tstruct, bool is_xception = false, bool in_class = false, bool is_result = false); + void generate_netstd_union_definition(ostream& out, t_struct* tunion); + void generate_netstd_union_class(ostream& out, t_struct* tunion, t_field* tfield); + void generate_netstd_wcffault(ostream& out, t_struct* tstruct); + void generate_netstd_struct_reader(ostream& out, t_struct* tstruct); + void generate_netstd_struct_result_writer(ostream& out, t_struct* tstruct); + void generate_netstd_struct_writer(ostream& out, t_struct* tstruct); + void generate_netstd_struct_tostring(ostream& out, t_struct* tstruct); + void generate_netstd_struct_equals(ostream& out, t_struct* tstruct); + void generate_netstd_struct_hashcode(ostream& out, t_struct* tstruct); + void generate_netstd_union_reader(ostream& out, t_struct* tunion); + void generate_function_helpers(ostream& out, t_function* tfunction); + void generate_service_interface(ostream& out, t_service* tservice); + void generate_service_helpers(ostream& out, t_service* tservice); + void generate_service_client(ostream& out, t_service* tservice); + void generate_service_server(ostream& out, t_service* tservice); + void generate_process_function_async(ostream& out, t_service* tservice, t_function* function); + void generate_deserialize_field(ostream& out, t_field* tfield, string prefix = "", bool is_propertyless = false); + void generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix = ""); + void generate_deserialize_container(ostream& out, t_type* ttype, string prefix = ""); + void generate_deserialize_set_element(ostream& out, t_set* tset, string prefix = ""); + void generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix = ""); + void generate_deserialize_list_element(ostream& out, t_list* list, string prefix = ""); + void generate_serialize_field(ostream& out, t_field* tfield, string prefix = "", bool is_element = false, bool is_propertyless = false); + void generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix = ""); + void generate_serialize_container(ostream& out, t_type* ttype, string prefix = ""); + void generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map); + void generate_serialize_set_element(ostream& out, t_set* tmap, string iter); + void generate_serialize_list_element(ostream& out, t_list* tlist, string iter); + void generate_netstd_doc(ostream& out, t_field* field); + void generate_netstd_doc(ostream& out, t_doc* tdoc); + void generate_netstd_doc(ostream& out, t_function* tdoc); + void generate_netstd_docstring_comment(ostream& out, string contents); + void docstring_comment(ostream& out, const string& comment_start, const string& line_prefix, const string& contents, const string& comment_end); + void start_netstd_namespace(ostream& out); + void end_netstd_namespace(ostream& out); + + string netstd_type_usings() const; + string netstd_thrift_usings() const; + + string type_name(t_type* ttype, bool in_countainer = false, bool in_init = false, bool in_param = false, bool is_required = false); + string base_type_name(t_base_type* tbase, bool in_container = false, bool in_param = false, bool is_required = false); + string declare_field(t_field* tfield, bool init = false, string prefix = ""); + string function_signature_async(t_function* tfunction, string prefix = ""); + string function_signature(t_function* tfunction, string prefix = ""); + string argument_list(t_struct* tstruct); + string type_to_enum(t_type* ttype); + string prop_name(t_field* tfield, bool suppress_mapping = false); + string get_enum_class_name(t_type* type); + +private: + string namespace_name_; + string namespace_dir_; + + bool nullable_; + bool union_; + bool hashcode_; + bool serialize_; + bool wcf_; + + string wcf_namespace_; + map netstd_keywords; + vector member_mapping_scopes; + + void init_keywords(); + string normalize_name(string name); + string make_valid_csharp_identifier(string const& fromName); + void prepare_member_name_mapping(t_struct* tstruct); + void prepare_member_name_mapping(void* scope, const vector& members, const string& structname); + void cleanup_member_name_mapping(void* scope); + string get_mapped_member_name(string oldname); +}; diff --git a/configure.ac b/configure.ac index 7da52a0bfa1..b09c98361dd 100755 --- a/configure.ac +++ b/configure.ac @@ -128,6 +128,7 @@ if test "$enable_libs" = "no"; then with_haskell="no" with_haxe="no" with_dotnetcore="no" + with_netstd="no" with_perl="no" with_php="no" with_php_extension="no" @@ -508,7 +509,7 @@ if test "$with_dotnetcore" = "yes"; then AX_PROG_DOTNETCORE_VERSION( [2.0.0], have_dotnetcore="yes", have_dotnetcore="no") fi fi -AM_CONDITIONAL(WITH_DOTNETCORE, [test "$have_dotnetcore" = "yes"]) +AM_CONDITIONAL(WITH_DOTNET, [test "$have_dotnetcore" = "yes"]) AX_THRIFT_LIB(d, [D], yes) @@ -818,6 +819,7 @@ AC_CONFIG_FILES([ lib/json/Makefile lib/json/test/Makefile lib/netcore/Makefile + lib/netstd/Makefile lib/nodejs/Makefile lib/nodets/Makefile lib/perl/Makefile @@ -846,6 +848,7 @@ AC_CONFIG_FILES([ test/hs/Makefile test/lua/Makefile test/netcore/Makefile + test/netstd/Makefile test/php/Makefile test/dart/Makefile test/perl/Makefile @@ -865,6 +868,7 @@ AC_CONFIG_FILES([ tutorial/java/Makefile tutorial/js/Makefile tutorial/netcore/Makefile + tutorial/netstd/Makefile tutorial/nodejs/Makefile tutorial/dart/Makefile tutorial/py/Makefile @@ -933,6 +937,7 @@ echo "Building Common Lisp Library.. : $have_cl" echo "Building D Library ........... : $have_d" echo "Building Dart Library ........ : $have_dart" echo "Building dotnetcore Library .. : $have_dotnetcore" +echo "Building .NET Standard Library : $have_dotnetcore" echo "Building Erlang Library ...... : $have_erlang" echo "Building Go Library .......... : $have_go" echo "Building Haskell Library ..... : $have_haskell" @@ -1001,6 +1006,12 @@ if test "$have_dotnetcore" = "yes" ; then echo " Using .NET Core ........... : $DOTNETCORE" echo " Using .NET Core version ... : $DOTNETCORE_VERSION" fi +if test "$have_dotnetcore" = "yes" ; then + echo + echo ".NET Standard Library:" + echo " Using dotnet .............. : $DOTNETCORE" + echo " Using dotnet version ...... : $DOTNETCORE_VERSION" +fi if test "$have_erlang" = "yes" ; then echo echo "Erlang Library:" diff --git a/lib/Makefile.am b/lib/Makefile.am index f6060c40d72..73326a56d85 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -72,8 +72,9 @@ if WITH_DART SUBDIRS += dart endif -if WITH_DOTNETCORE +if WITH_DOTNET SUBDIRS += netcore +SUBDIRS += netstd endif if WITH_GO diff --git a/lib/csharp/README.md b/lib/csharp/README.md index b7dc5de3272..5fc14cb3cdd 100644 --- a/lib/csharp/README.md +++ b/lib/csharp/README.md @@ -1,5 +1,11 @@ Thrift C# Software Library +Deprecation notice +======= + +Per [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723), both CSharp and Netcore targets are deprecated +and will be removed with the next release. Migrate to the [NetStd language target](../netstd/README.md) instead. + License ======= diff --git a/lib/netcore/README.md b/lib/netcore/README.md index 94b047f5cd9..bcd25b92728 100644 --- a/lib/netcore/README.md +++ b/lib/netcore/README.md @@ -2,6 +2,11 @@ Thrift client library ported to Microsoft .Net Core +# Deprecation notice + +Per [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723), both CSharp and Netcore targets are deprecated +and will be removed with the next release. Migrate to the [NetStd language target](../netstd/README.md) instead. + # Content - Tests/Thrift.PublicInterfaces.Compile.Tests - project for checking public interfaces during adding changes to Thrift library - Thrift - Thrift library diff --git a/lib/netstd/Makefile.am b/lib/netstd/Makefile.am new file mode 100644 index 00000000000..f6faacae5ba --- /dev/null +++ b/lib/netstd/Makefile.am @@ -0,0 +1,58 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +SUBDIRS = . + +all-local: + $(DOTNETCORE) build + +check-local: + $(DOTNETCORE) test Tests/Thrift.Tests/Thrift.Tests.csproj + ${DOTNETCORE} test Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj + +clean-local: + $(RM) -r Thrift/bin + $(RM) -r Thrift/obj + +EXTRA_DIST = \ + README.md \ + Tests/Thrift.IntegrationTests/Protocols \ + Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj \ + Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj \ + Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs \ + Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift \ + Tests/Thrift.Tests/Thrift.Tests.csproj \ + Tests/Thrift.Tests/Protocols \ + Tests/Thrift.Tests/Collections \ + Thrift/TApplicationException.cs \ + Thrift/TBaseClient.cs \ + Thrift/TException.cs \ + Thrift/Thrift.csproj \ + Thrift/Collections \ + Thrift/Processor \ + Thrift/Properties \ + Thrift/Protocol \ + Thrift/Server \ + Thrift/Transport \ + Thrift.sln \ + build.cmd \ + build.sh \ + runtests.cmd \ + runtests.sh + \ No newline at end of file diff --git a/lib/netstd/README.md b/lib/netstd/README.md new file mode 100644 index 00000000000..88ba73aebcd --- /dev/null +++ b/lib/netstd/README.md @@ -0,0 +1,54 @@ +# Apache Thrift netstd + +Thrift client library for Microsoft .NET Standard + +# Build the library + +## How to build on Windows +- Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable +- Open the Thrift.sln project with Visual Studio and build. +or +- Build with scripts + +## How to build on Unix/Linux +- Ensure you have .NET SDK >= 2.0 installed, or use the [Ubuntu docker image](../../build/docker/README.md) +- Follow common automake build practice: `./ bootstrap && ./ configure && make` + +## Known issues +- In trace logging mode you can see some not important internal exceptions + +# Migration to netstd + +## ... from netcore + +If you are migrating your code from netcore library, you will have to: + +- Switch to `thrift -gen netstd` +- the following compiler flags are no longer needed or supported: `hashcode` is now standard, while `nullable` is no longer supported. +- the `Thrift.Transport` and `Thrift.Protocol` namespaces now use the singular form +- add `using Thrift.Processor;` in the server code where appropriate +- rename all `T*ClientTransport` to `T*Transport` +- rename all `TBaseServer` occurrences in your code to `TServer` +- the `SingletonTProcessorFactory` is now called `TSingletonProcessorFactory` +- and the `AsyncBaseServer` is now the `TSimpleAsyncServer` + +You may wonder why we changed so many names. The naming scheme has been revised for two reasons: First, we want to get back the established, well-known naming consistency across the Thrift libraries which the netcore library did not fully respect. Second, by achieving that first objective, we get the additional benefit of making migration at least a bit easier for C# projects. + +## ... from csharp + +Because of the different environment requirements, migration from C# takes slightly more efforts. While the code changes related to Thrift itself are moderate, you may need to upgrade certain dependencies, components or even modules to more recent versions. + +1. Client and server applications must use at least framework 4.6.1, any version below will not work. +1. Switch to `thrift -gen netstd`. The following compiler flags are no longer needed or supported: `hashcode` and `async` are now standard, while `nullable` is no longer supported. +1. [Familiarize yourself with the `async/await` model](https://msdn.microsoft.com/en-us/magazine/jj991977.aspx), if you have not already done so. As netstd does not support `ISync` anymore, async is mandatory. The synchronous model is simply no longer available (that's also the reason why we don't need the `async` flag anymore). +1. Consider proper use of `cancellationToken` parameters. They are optional but may be quite helpful. +1. As you probably already guessed, there are a few names that have been changed: +- add `using Thrift.Processor;` in the server code where appropriate +- the `TServerSocket` is now called `TServerSocketTransport` +- change `IProtocolFactory` into `ITProtocolFactory` +- if you are looking for `TSimpleServer`, try `TSimpleAsyncServer` instead +- similarly, the `TThreadPoolServer` is now a `TThreadPoolAsyncServer` +- the server's `Serve()` method does now `ServeAsync()` +- In case you are using Thrift server event handlers: the `SetEventHandler` method now starts with an uppercase letter +- and you will also have to revise the method names of all `TServerEventHandler` descendants you have in your code + diff --git a/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs new file mode 100644 index 00000000000..b1f841892c3 --- /dev/null +++ b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs @@ -0,0 +1,502 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using KellermanSoftware.CompareNetObjects; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Transport.Client; + +namespace Thrift.IntegrationTests.Protocols +{ + [TestClass] + public class ProtocolsOperationsTests + { + private readonly CompareLogic _compareLogic = new CompareLogic(); + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol), TMessageType.Call)] + [DataRow(typeof(TBinaryProtocol), TMessageType.Exception)] + [DataRow(typeof(TBinaryProtocol), TMessageType.Oneway)] + [DataRow(typeof(TBinaryProtocol), TMessageType.Reply)] + [DataRow(typeof(TCompactProtocol), TMessageType.Call)] + [DataRow(typeof(TCompactProtocol), TMessageType.Exception)] + [DataRow(typeof(TCompactProtocol), TMessageType.Oneway)] + [DataRow(typeof(TCompactProtocol), TMessageType.Reply)] + [DataRow(typeof(TJsonProtocol), TMessageType.Call)] + [DataRow(typeof(TJsonProtocol), TMessageType.Exception)] + [DataRow(typeof(TJsonProtocol), TMessageType.Oneway)] + [DataRow(typeof(TJsonProtocol), TMessageType.Reply)] + public async Task WriteReadMessage_Test(Type protocolType, TMessageType messageType) + { + var expected = new TMessage(nameof(TMessage), messageType, 1); + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteMessageBeginAsync(expected); + await protocol.WriteMessageEndAsync(); + + stream.Seek(0, SeekOrigin.Begin); + + var actualMessage = await protocol.ReadMessageBeginAsync(); + await protocol.ReadMessageEndAsync(); + + var result = _compareLogic.Compare(expected, actualMessage); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + [ExpectedException(typeof(Exception))] + public async Task WriteReadStruct_Test(Type protocolType) + { + var expected = new TStruct(nameof(TStruct)); + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteStructBeginAsync(expected); + await protocol.WriteStructEndAsync(); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadStructBeginAsync(); + await protocol.ReadStructEndAsync(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + [ExpectedException(typeof(Exception))] + public async Task WriteReadField_Test(Type protocolType) + { + var expected = new TField(nameof(TField), TType.String, 1); + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteFieldBeginAsync(expected); + await protocol.WriteFieldEndAsync(); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadFieldBeginAsync(); + await protocol.ReadFieldEndAsync(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + public async Task WriteReadMap_Test(Type protocolType) + { + var expected = new TMap(TType.String, TType.String, 1); + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteMapBeginAsync(expected); + await protocol.WriteMapEndAsync(); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadMapBeginAsync(); + await protocol.ReadMapEndAsync(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + public async Task WriteReadList_Test(Type protocolType) + { + var expected = new TList(TType.String, 1); + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteListBeginAsync(expected); + await protocol.WriteListEndAsync(); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadListBeginAsync(); + await protocol.ReadListEndAsync(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + public async Task WriteReadSet_Test(Type protocolType) + { + var expected = new TSet(TType.String, 1); + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteSetBeginAsync(expected); + await protocol.WriteSetEndAsync(); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadSetBeginAsync(); + await protocol.ReadSetEndAsync(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + public async Task WriteReadBool_Test(Type protocolType) + { + var expected = true; + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteBoolAsync(expected); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadBoolAsync(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + public async Task WriteReadByte_Test(Type protocolType) + { + var expected = sbyte.MaxValue; + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteByteAsync(expected); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadByteAsync(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + public async Task WriteReadI16_Test(Type protocolType) + { + var expected = short.MaxValue; + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteI16Async(expected); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadI16Async(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + public async Task WriteReadI32_Test(Type protocolType) + { + var expected = int.MaxValue; + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteI32Async(expected); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadI32Async(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + public async Task WriteReadI64_Test(Type protocolType) + { + var expected = long.MaxValue; + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteI64Async(expected); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadI64Async(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + public async Task WriteReadDouble_Test(Type protocolType) + { + var expected = double.MaxValue; + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteDoubleAsync(expected); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadDoubleAsync(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + public async Task WriteReadString_Test(Type protocolType) + { + var expected = nameof(String); + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteStringAsync(expected); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadStringAsync(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + [DataTestMethod] + [DataRow(typeof(TBinaryProtocol))] + [DataRow(typeof(TCompactProtocol))] + [DataRow(typeof(TJsonProtocol))] + public async Task WriteReadBinary_Test(Type protocolType) + { + var expected = Encoding.UTF8.GetBytes(nameof(String)); + + try + { + var tuple = GetProtocolInstance(protocolType); + using (var stream = tuple.Item1) + { + var protocol = tuple.Item2; + + await protocol.WriteBinaryAsync(expected); + + stream?.Seek(0, SeekOrigin.Begin); + + var actual = await protocol.ReadBinaryAsync(); + + var result = _compareLogic.Compare(expected, actual); + Assert.IsTrue(result.AreEqual, result.DifferencesString); + } + } + catch (Exception e) + { + throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); + } + } + + private static Tuple GetProtocolInstance(Type protocolType) + { + var memoryStream = new MemoryStream(); + var streamClientTransport = new TStreamTransport(memoryStream, memoryStream); + var protocol = (TProtocol) Activator.CreateInstance(protocolType, streamClientTransport); + return new Tuple(memoryStream, protocol); + } + } +} diff --git a/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj b/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj new file mode 100644 index 00000000000..4a235edc034 --- /dev/null +++ b/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj @@ -0,0 +1,48 @@ + + + + + netcoreapp2.0 + Thrift.IntegrationTests + Thrift.IntegrationTests + Exe + false + false + false + false + false + false + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift new file mode 100644 index 00000000000..26cb380c5a4 --- /dev/null +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift @@ -0,0 +1,705 @@ +#!/usr/local/bin/thrift --java --php --py +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# *** PLEASE REMEMBER TO EDIT THE VERSION CONSTANT WHEN MAKING CHANGES *** +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# +# Interface definition for Cassandra Service +# + +namespace netstd Apache.Cassandra.Test + +# Thrift.rb has a bug where top-level modules that include modules +# with the same name are not properly referenced, so we can't do +# Cassandra::Cassandra::Client. +namespace rb CassandraThrift + +# The API version (NOT the product version), composed as a dot delimited +# string with major, minor, and patch level components. +# +# - Major: Incremented for backward incompatible changes. An example would +# be changes to the number or disposition of method arguments. +# - Minor: Incremented for backward compatible changes. An example would +# be the addition of a new (optional) method. +# - Patch: Incremented for bug fixes. The patch level should be increased +# for every edit that doesn't result in a change to major/minor. +# +# See the Semantic Versioning Specification (SemVer) http://semver.org. +const string VERSION = "19.24.0" + + +# +# data structures +# + +/** Basic unit of data within a ColumnFamily. + * @param name, the name by which this column is set and retrieved. Maximum 64KB long. + * @param value. The data associated with the name. Maximum 2GB long, but in practice you should limit it to small numbers of MB (since Thrift must read the full value into memory to operate on it). + * @param timestamp. The timestamp is used for conflict detection/resolution when two columns with same name need to be compared. + * @param ttl. An optional, positive delay (in seconds) after which the column will be automatically deleted. + */ +struct Column { + 1: required binary name, + 2: optional binary value, + 3: optional i64 timestamp, + 4: optional i32 ttl, +} + +/** A named list of columns. + * @param name. see Column.name. + * @param columns. A collection of standard Columns. The columns within a super column are defined in an adhoc manner. + * Columns within a super column do not have to have matching structures (similarly named child columns). + */ +struct SuperColumn { + 1: required binary name, + 2: required list columns, +} + +struct CounterColumn { + 1: required binary name, + 2: required i64 value +} + +struct CounterSuperColumn { + 1: required binary name, + 2: required list columns +} + +/** + Methods for fetching rows/records from Cassandra will return either a single instance of ColumnOrSuperColumn or a list + of ColumnOrSuperColumns (get_slice()). If you're looking up a SuperColumn (or list of SuperColumns) then the resulting + instances of ColumnOrSuperColumn will have the requested SuperColumn in the attribute super_column. For queries resulting + in Columns, those values will be in the attribute column. This change was made between 0.3 and 0.4 to standardize on + single query methods that may return either a SuperColumn or Column. + + If the query was on a counter column family, you will either get a counter_column (instead of a column) or a + counter_super_column (instead of a super_column) + + @param column. The Column returned by get() or get_slice(). + @param super_column. The SuperColumn returned by get() or get_slice(). + @param counter_column. The Counterolumn returned by get() or get_slice(). + @param counter_super_column. The CounterSuperColumn returned by get() or get_slice(). + */ +struct ColumnOrSuperColumn { + 1: optional Column column, + 2: optional SuperColumn super_column, + 3: optional CounterColumn counter_column, + 4: optional CounterSuperColumn counter_super_column +} + + +# +# Exceptions +# (note that internal server errors will raise a TApplicationException, courtesy of Thrift) +# + +/** A specific column was requested that does not exist. */ +exception NotFoundException { +} + +/** Invalid request could mean keyspace or column family does not exist, required parameters are missing, or a parameter is malformed. + why contains an associated error message. +*/ +exception InvalidRequestException { + 1: required string why +} + +/** Not all the replicas required could be created and/or read. */ +exception UnavailableException { +} + +/** RPC timeout was exceeded. either a node failed mid-operation, or load was too high, or the requested op was too large. */ +exception TimedOutException { +} + +/** invalid authentication request (invalid keyspace, user does not exist, or credentials invalid) */ +exception AuthenticationException { + 1: required string why +} + +/** invalid authorization request (user does not have access to keyspace) */ +exception AuthorizationException { + 1: required string why +} + +/** schemas are not in agreement across all nodes */ +exception SchemaDisagreementException { +} + + +# +# service api +# +/** + * The ConsistencyLevel is an enum that controls both read and write + * behavior based on the ReplicationFactor of the keyspace. The + * different consistency levels have different meanings, depending on + * if you're doing a write or read operation. + * + * If W + R > ReplicationFactor, where W is the number of nodes to + * block for on write, and R the number to block for on reads, you + * will have strongly consistent behavior; that is, readers will + * always see the most recent write. Of these, the most interesting is + * to do QUORUM reads and writes, which gives you consistency while + * still allowing availability in the face of node failures up to half + * of . Of course if latency is more important than + * consistency then you can use lower values for either or both. + * + * Some ConsistencyLevels (ONE, TWO, THREE) refer to a specific number + * of replicas rather than a logical concept that adjusts + * automatically with the replication factor. Of these, only ONE is + * commonly used; TWO and (even more rarely) THREE are only useful + * when you care more about guaranteeing a certain level of + * durability, than consistency. + * + * Write consistency levels make the following guarantees before reporting success to the client: + * ANY Ensure that the write has been written once somewhere, including possibly being hinted in a non-target node. + * ONE Ensure that the write has been written to at least 1 node's commit log and memory table + * TWO Ensure that the write has been written to at least 2 node's commit log and memory table + * THREE Ensure that the write has been written to at least 3 node's commit log and memory table + * QUORUM Ensure that the write has been written to / 2 + 1 nodes + * LOCAL_QUORUM Ensure that the write has been written to / 2 + 1 nodes, within the local datacenter (requires NetworkTopologyStrategy) + * EACH_QUORUM Ensure that the write has been written to / 2 + 1 nodes in each datacenter (requires NetworkTopologyStrategy) + * ALL Ensure that the write is written to <ReplicationFactor> nodes before responding to the client. + * + * Read consistency levels make the following guarantees before returning successful results to the client: + * ANY Not supported. You probably want ONE instead. + * ONE Returns the record obtained from a single replica. + * TWO Returns the record with the most recent timestamp once two replicas have replied. + * THREE Returns the record with the most recent timestamp once three replicas have replied. + * QUORUM Returns the record with the most recent timestamp once a majority of replicas have replied. + * LOCAL_QUORUM Returns the record with the most recent timestamp once a majority of replicas within the local datacenter have replied. + * EACH_QUORUM Returns the record with the most recent timestamp once a majority of replicas within each datacenter have replied. + * ALL Returns the record with the most recent timestamp once all replicas have replied (implies no replica may be down).. +*/ +enum ConsistencyLevel { + ONE = 1, + QUORUM = 2, + LOCAL_QUORUM = 3, + EACH_QUORUM = 4, + ALL = 5, + ANY = 6, + TWO = 7, + THREE = 8, +} + +/** + ColumnParent is used when selecting groups of columns from the same ColumnFamily. In directory structure terms, imagine + ColumnParent as ColumnPath + '/../'. + + See also ColumnPath + */ +struct ColumnParent { + 3: required string column_family, + 4: optional binary super_column, +} + +/** The ColumnPath is the path to a single column in Cassandra. It might make sense to think of ColumnPath and + * ColumnParent in terms of a directory structure. + * + * ColumnPath is used to looking up a single column. + * + * @param column_family. The name of the CF of the column being looked up. + * @param super_column. The super column name. + * @param column. The column name. + */ +struct ColumnPath { + 3: required string column_family, + 4: optional binary super_column, + 5: optional binary column, +} + +/** + A slice range is a structure that stores basic range, ordering and limit information for a query that will return + multiple columns. It could be thought of as Cassandra's version of LIMIT and ORDER BY + + @param start. The column name to start the slice with. This attribute is not required, though there is no default value, + and can be safely set to '', i.e., an empty byte array, to start with the first column name. Otherwise, it + must a valid value under the rules of the Comparator defined for the given ColumnFamily. + @param finish. The column name to stop the slice at. This attribute is not required, though there is no default value, + and can be safely set to an empty byte array to not stop until 'count' results are seen. Otherwise, it + must also be a valid value to the ColumnFamily Comparator. + @param reversed. Whether the results should be ordered in reversed order. Similar to ORDER BY blah DESC in SQL. + @param count. How many columns to return. Similar to LIMIT in SQL. May be arbitrarily large, but Thrift will + materialize the whole result into memory before returning it to the client, so be aware that you may + be better served by iterating through slices by passing the last value of one call in as the 'start' + of the next instead of increasing 'count' arbitrarily large. + */ +struct SliceRange { + 1: required binary start, + 2: required binary finish, + 3: required bool reversed=0, + 4: required i32 count=100, +} + +/** + A SlicePredicate is similar to a mathematic predicate (see http://en.wikipedia.org/wiki/Predicate_(mathematical_logic)), + which is described as "a property that the elements of a set have in common." + + SlicePredicate's in Cassandra are described with either a list of column_names or a SliceRange. If column_names is + specified, slice_range is ignored. + + @param column_name. A list of column names to retrieve. This can be used similar to Memcached's "multi-get" feature + to fetch N known column names. For instance, if you know you wish to fetch columns 'Joe', 'Jack', + and 'Jim' you can pass those column names as a list to fetch all three at once. + @param slice_range. A SliceRange describing how to range, order, and/or limit the slice. + */ +struct SlicePredicate { + 1: optional list column_names, + 2: optional SliceRange slice_range, +} + +enum IndexOperator { + EQ, + GTE, + GT, + LTE, + LT +} + +struct IndexExpression { + 1: required binary column_name, + 2: required IndexOperator op, + 3: required binary value, +} + +struct IndexClause { + 1: required list expressions + 2: required binary start_key, + 3: required i32 count=100, +} + +/** +The semantics of start keys and tokens are slightly different. +Keys are start-inclusive; tokens are start-exclusive. Token +ranges may also wrap -- that is, the end token may be less +than the start one. Thus, a range from keyX to keyX is a +one-element range, but a range from tokenY to tokenY is the +full ring. +*/ +struct KeyRange { + 1: optional binary start_key, + 2: optional binary end_key, + 3: optional string start_token, + 4: optional string end_token, + 5: required i32 count=100 +} + +/** + A KeySlice is key followed by the data it maps to. A collection of KeySlice is returned by the get_range_slice operation. + + @param key. a row key + @param columns. List of data represented by the key. Typically, the list is pared down to only the columns specified by + a SlicePredicate. + */ +struct KeySlice { + 1: required binary key, + 2: required list columns, +} + +struct KeyCount { + 1: required binary key, + 2: required i32 count +} + +/** + * Note that the timestamp is only optional in case of counter deletion. + */ +struct Deletion { + 1: optional i64 timestamp, + 2: optional binary super_column, + 3: optional SlicePredicate predicate, +} + +/** + A Mutation is either an insert (represented by filling column_or_supercolumn) or a deletion (represented by filling the deletion attribute). + @param column_or_supercolumn. An insert to a column or supercolumn (possibly counter column or supercolumn) + @param deletion. A deletion of a column or supercolumn +*/ +struct Mutation { + 1: optional ColumnOrSuperColumn column_or_supercolumn, + 2: optional Deletion deletion, +} + +struct EndpointDetails { + 1: string host, + 2: string datacenter, + 3: optional string rack +} + +/** + A TokenRange describes part of the Cassandra ring, it is a mapping from a range to + endpoints responsible for that range. + @param start_token The first token in the range + @param end_token The last token in the range + @param endpoints The endpoints responsible for the range (listed by their configured listen_address) + @param rpc_endpoints The endpoints responsible for the range (listed by their configured rpc_address) +*/ +struct TokenRange { + 1: required string start_token, + 2: required string end_token, + 3: required list endpoints, + 4: optional list rpc_endpoints + 5: optional list endpoint_details, +} + +/** + Authentication requests can contain any data, dependent on the IAuthenticator used +*/ +struct AuthenticationRequest { + 1: required map credentials +} + +enum IndexType { + KEYS, + CUSTOM +} + +/* describes a column in a column family. */ +struct ColumnDef { + 1: required binary name, + 2: required string validation_class, + 3: optional IndexType index_type, + 4: optional string index_name, + 5: optional map index_options +} + + +/* describes a column family. */ +struct CfDef { + 1: required string keyspace, + 2: required string name, + 3: optional string column_type="Standard", + 5: optional string comparator_type="BytesType", + 6: optional string subcomparator_type, + 8: optional string comment, + 12: optional double read_repair_chance=1.0, + 13: optional list column_metadata, + 14: optional i32 gc_grace_seconds, + 15: optional string default_validation_class, + 16: optional i32 id, + 17: optional i32 min_compaction_threshold, + 18: optional i32 max_compaction_threshold, + 24: optional bool replicate_on_write, + 25: optional double merge_shards_chance, + 26: optional string key_validation_class, + 28: optional binary key_alias, + 29: optional string compaction_strategy, + 30: optional map compaction_strategy_options, + 32: optional map compression_options, + 33: optional double bloom_filter_fp_chance, +} + +/* describes a keyspace. */ +struct KsDef { + 1: required string name, + 2: required string strategy_class, + 3: optional map strategy_options, + + /** @deprecated */ + 4: optional i32 replication_factor, + + 5: required list cf_defs, + 6: optional bool durable_writes=1, +} + +/** CQL query compression */ +enum Compression { + GZIP = 1, + NONE = 2 +} + +enum CqlResultType { + ROWS = 1, + VOID = 2, + INT = 3 +} + +/** Row returned from a CQL query */ +struct CqlRow { + 1: required binary key, + 2: required list columns +} + +struct CqlMetadata { + 1: required map name_types, + 2: required map value_types, + 3: required string default_name_type, + 4: required string default_value_type +} + +struct CqlResult { + 1: required CqlResultType type, + 2: optional list rows, + 3: optional i32 num, + 4: optional CqlMetadata schema +} + +struct CqlPreparedResult { + 1: required i32 itemId, + 2: required i32 count +} + + +service Cassandra { + # auth methods + void login(1: required AuthenticationRequest auth_request) throws (1:AuthenticationException authnx, 2:AuthorizationException authzx), + + # set keyspace + void set_keyspace(1: required string keyspace) throws (1:InvalidRequestException ire), + + # retrieval methods + + /** + Get the Column or SuperColumn at the given column_path. If no value is present, NotFoundException is thrown. (This is + the only method that can throw an exception under non-failure conditions.) + */ + ColumnOrSuperColumn get(1:required binary key, + 2:required ColumnPath column_path, + 3:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:NotFoundException nfe, 3:UnavailableException ue, 4:TimedOutException te), + + /** + Get the group of columns contained by column_parent (either a ColumnFamily name or a ColumnFamily/SuperColumn name + pair) specified by the given SlicePredicate. If no matching values are found, an empty list is returned. + */ + list get_slice(1:required binary key, + 2:required ColumnParent column_parent, + 3:required SlicePredicate predicate, + 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), + + /** + returns the number of columns matching predicate for a particular key, + ColumnFamily and optionally SuperColumn. + */ + i32 get_count(1:required binary key, + 2:required ColumnParent column_parent, + 3:required SlicePredicate predicate, + 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), + + /** + Performs a get_slice for column_parent and predicate for the given keys in parallel. + */ + map> multiget_slice(1:required list keys, + 2:required ColumnParent column_parent, + 3:required SlicePredicate predicate, + 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), + + /** + Perform a get_count in parallel on the given list keys. The return value maps keys to the count found. + */ + map multiget_count(1:required list keys, + 2:required ColumnParent column_parent, + 3:required SlicePredicate predicate, + 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), + + /** + returns a subset of columns for a contiguous range of keys. + */ + list get_range_slices(1:required ColumnParent column_parent, + 2:required SlicePredicate predicate, + 3:required KeyRange range, + 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), + + /** Returns the subset of columns specified in SlicePredicate for the rows matching the IndexClause */ + list get_indexed_slices(1:required ColumnParent column_parent, + 2:required IndexClause index_clause, + 3:required SlicePredicate column_predicate, + 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), + + # modification methods + + /** + * Insert a Column at the given column_parent.column_family and optional column_parent.super_column. + */ + void insert(1:required binary key, + 2:required ColumnParent column_parent, + 3:required Column column, + 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), + + /** + * Increment or decrement a counter. + */ + void add(1:required binary key, + 2:required ColumnParent column_parent, + 3:required CounterColumn column, + 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), + + /** + Remove data from the row specified by key at the granularity specified by column_path, and the given timestamp. Note + that all the values in column_path besides column_path.column_family are truly optional: you can remove the entire + row by just specifying the ColumnFamily, or you can remove a SuperColumn or a single Column by specifying those levels too. + */ + void remove(1:required binary key, + 2:required ColumnPath column_path, + 3:required i64 timestamp, + 4:ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), + + /** + * Remove a counter at the specified location. + * Note that counters have limited support for deletes: if you remove a counter, you must wait to issue any following update + * until the delete has reached all the nodes and all of them have been fully compacted. + */ + void remove_counter(1:required binary key, + 2:required ColumnPath path, + 3:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), + + + /** + Mutate many columns or super columns for many row keys. See also: Mutation. + + mutation_map maps key to column family to a list of Mutation objects to take place at that scope. + **/ + void batch_mutate(1:required map>> mutation_map, + 2:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) + throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), + + /** + Truncate will mark and entire column family as deleted. + From the user's perspective a successful call to truncate will result complete data deletion from cfname. + Internally, however, disk space will not be immediatily released, as with all deletes in cassandra, this one + only marks the data as deleted. + The operation succeeds only if all hosts in the cluster at available and will throw an UnavailableException if + some hosts are down. + */ + void truncate(1:required string cfname) + throws (1: InvalidRequestException ire, 2: UnavailableException ue, 3: TimedOutException te), + + + + // Meta-APIs -- APIs to get information about the node or cluster, + // rather than user data. The nodeprobe program provides usage examples. + + /** + * for each schema version present in the cluster, returns a list of nodes at that version. + * hosts that do not respond will be under the key DatabaseDescriptor.INITIAL_VERSION. + * the cluster is all on the same version if the size of the map is 1. + */ + map> describe_schema_versions() + throws (1: InvalidRequestException ire), + + /** list the defined keyspaces in this cluster */ + list describe_keyspaces() + throws (1:InvalidRequestException ire), + + /** get the cluster name */ + string describe_cluster_name(), + + /** get the thrift api version */ + string describe_version(), + + /** get the token ring: a map of ranges to host addresses, + represented as a set of TokenRange instead of a map from range + to list of endpoints, because you can't use Thrift structs as + map keys: + https://issues.apache.org/jira/browse/THRIFT-162 + + for the same reason, we can't return a set here, even though + order is neither important nor predictable. */ + list describe_ring(1:required string keyspace) + throws (1:InvalidRequestException ire), + + /** returns the partitioner used by this cluster */ + string describe_partitioner(), + + /** returns the snitch used by this cluster */ + string describe_snitch(), + + /** describe specified keyspace */ + KsDef describe_keyspace(1:required string keyspace) + throws (1:NotFoundException nfe, 2:InvalidRequestException ire), + + /** experimental API for hadoop/parallel query support. + may change violently and without warning. + + returns list of token strings such that first subrange is (list[0], list[1]], + next is (list[1], list[2]], etc. */ + list describe_splits(1:required string cfName, + 2:required string start_token, + 3:required string end_token, + 4:required i32 keys_per_split) + throws (1:InvalidRequestException ire), + + /** adds a column family. returns the new schema id. */ + string system_add_column_family(1:required CfDef cf_def) + throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), + + /** drops a column family. returns the new schema id. */ + string system_drop_column_family(1:required string column_family) + throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), + + /** adds a keyspace and any column families that are part of it. returns the new schema id. */ + string system_add_keyspace(1:required KsDef ks_def) + throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), + + /** drops a keyspace and any column families that are part of it. returns the new schema id. */ + string system_drop_keyspace(1:required string keyspace) + throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), + + /** updates properties of a keyspace. returns the new schema id. */ + string system_update_keyspace(1:required KsDef ks_def) + throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), + + /** updates properties of a column family. returns the new schema id. */ + string system_update_column_family(1:required CfDef cf_def) + throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), + + /** + * Executes a CQL (Cassandra Query Language) statement and returns a + * CqlResult containing the results. + */ + CqlResult execute_cql_query(1:required binary query, 2:required Compression compression) + throws (1:InvalidRequestException ire, + 2:UnavailableException ue, + 3:TimedOutException te, + 4:SchemaDisagreementException sde) + + + /** + * Prepare a CQL (Cassandra Query Language) statement by compiling and returning + * - the type of CQL statement + * - an id token of the compiled CQL stored on the server side. + * - a count of the discovered bound markers in the statement + */ + CqlPreparedResult prepare_cql_query(1:required binary query, 2:required Compression compression) + throws (1:InvalidRequestException ire) + + + /** + * Executes a prepared CQL (Cassandra Query Language) statement by passing an id token and a list of variables + * to bind and returns a CqlResult containing the results. + */ + CqlResult execute_prepared_cql_query(1:required i32 itemId, 2:required list values) + throws (1:InvalidRequestException ire, + 2:UnavailableException ue, + 3:TimedOutException te, + 4:SchemaDisagreementException sde) + + +} diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..0bb460ff441 --- /dev/null +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("d0d3706b-fed5-4cf5-b984-04f448de9d7b")] \ No newline at end of file diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj new file mode 100644 index 00000000000..6687a9d5ec1 --- /dev/null +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj @@ -0,0 +1,54 @@ + + + + + netcoreapp2.0 + Thrift.PublicInterfaces.Compile.Tests + Thrift.PublicInterfaces.Compile.Tests + false + false + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs b/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs new file mode 100644 index 00000000000..1be99b48fd6 --- /dev/null +++ b/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs @@ -0,0 +1,83 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Thrift.Collections; + +namespace Thrift.Tests.Collections +{ + // ReSharper disable once InconsistentNaming + [TestClass] + public class TCollectionsTests + { + //TODO: Add tests for IEnumerable with objects and primitive values inside + + [TestMethod] + public void TCollection_Equals_Primitive_Test() + { + var collection1 = new List {1,2,3}; + var collection2 = new List {1,2,3}; + + var result = TCollections.Equals(collection1, collection2); + + Assert.IsTrue(result); + } + + [TestMethod] + public void TCollection_Equals_Primitive_Different_Test() + { + var collection1 = new List { 1, 2, 3 }; + var collection2 = new List { 1, 2 }; + + var result = TCollections.Equals(collection1, collection2); + + Assert.IsFalse(result); + } + + [TestMethod] + public void TCollection_Equals_Objects_Test() + { + var collection1 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; + var collection2 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; + + var result = TCollections.Equals(collection1, collection2); + + // references to different collections + Assert.IsFalse(result); + } + + [TestMethod] + public void TCollection_Equals_OneAndTheSameObject_Test() + { + var collection1 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; + var collection2 = collection1; + + var result = TCollections.Equals(collection1, collection2); + + // references to one and the same collection + Assert.IsTrue(result); + } + + private class ExampleClass + { + public int X { get; set; } + } + } +} diff --git a/lib/netstd/Tests/Thrift.Tests/Collections/THashSetTests.cs b/lib/netstd/Tests/Thrift.Tests/Collections/THashSetTests.cs new file mode 100644 index 00000000000..8de573eee8c --- /dev/null +++ b/lib/netstd/Tests/Thrift.Tests/Collections/THashSetTests.cs @@ -0,0 +1,71 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Thrift.Collections; + +namespace Thrift.Tests.Collections +{ + // ReSharper disable once InconsistentNaming + [TestClass] + public class THashSetTests + { + [TestMethod] + public void THashSet_Equals_Primitive_Test() + { + const int value = 1; + + var hashSet = new THashSet {value}; + + Assert.IsTrue(hashSet.Contains(value)); + + hashSet.Remove(value); + + Assert.IsTrue(hashSet.Count == 0); + + hashSet.Add(value); + + Assert.IsTrue(hashSet.Contains(value)); + + hashSet.Clear(); + + Assert.IsTrue(hashSet.Count == 0); + + var newArr = new int[1]; + hashSet.Add(value); + hashSet.CopyTo(newArr, 0); + + Assert.IsTrue(newArr.Contains(value)); + + var en = hashSet.GetEnumerator(); + en.MoveNext(); + + Assert.IsTrue((int)en.Current == value); + + using (var ien = ((IEnumerable)hashSet).GetEnumerator()) + { + ien.MoveNext(); + + Assert.IsTrue(ien.Current == value); + } + } + } +} diff --git a/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs b/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs new file mode 100644 index 00000000000..6d391516e44 --- /dev/null +++ b/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs @@ -0,0 +1,172 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; + +namespace Thrift.Tests.Protocols +{ + [TestClass] + public class TJSONProtocolHelperTests + { + [TestMethod] + public void GetTypeNameForTypeId_Test() + { + // input/output + var sets = new List> + { + new Tuple(TType.Bool, TJSONProtocolConstants.TypeNames.NameBool), + new Tuple(TType.Byte, TJSONProtocolConstants.TypeNames.NameByte), + new Tuple(TType.I16, TJSONProtocolConstants.TypeNames.NameI16), + new Tuple(TType.I32, TJSONProtocolConstants.TypeNames.NameI32), + new Tuple(TType.I64, TJSONProtocolConstants.TypeNames.NameI64), + new Tuple(TType.Double, TJSONProtocolConstants.TypeNames.NameDouble), + new Tuple(TType.String, TJSONProtocolConstants.TypeNames.NameString), + new Tuple(TType.Struct, TJSONProtocolConstants.TypeNames.NameStruct), + new Tuple(TType.Map, TJSONProtocolConstants.TypeNames.NameMap), + new Tuple(TType.Set, TJSONProtocolConstants.TypeNames.NameSet), + new Tuple(TType.List, TJSONProtocolConstants.TypeNames.NameList), + }; + + foreach (var t in sets) + { + Assert.IsTrue(TJSONProtocolHelper.GetTypeNameForTypeId(t.Item1) == t.Item2, $"Wrong mapping of TypeName {t.Item2} to TType: {t.Item1}"); + } + } + + [TestMethod] + [ExpectedException(typeof(TProtocolException))] + public void GetTypeNameForTypeId_TStop_Test() + { + TJSONProtocolHelper.GetTypeNameForTypeId(TType.Stop); + } + + [TestMethod] + [ExpectedException(typeof(TProtocolException))] + public void GetTypeNameForTypeId_NonExistingTType_Test() + { + TJSONProtocolHelper.GetTypeNameForTypeId((TType)100); + } + + [TestMethod] + public void GetTypeIdForTypeName_Test() + { + // input/output + var sets = new List> + { + new Tuple(TType.Bool, TJSONProtocolConstants.TypeNames.NameBool), + new Tuple(TType.Byte, TJSONProtocolConstants.TypeNames.NameByte), + new Tuple(TType.I16, TJSONProtocolConstants.TypeNames.NameI16), + new Tuple(TType.I32, TJSONProtocolConstants.TypeNames.NameI32), + new Tuple(TType.I64, TJSONProtocolConstants.TypeNames.NameI64), + new Tuple(TType.Double, TJSONProtocolConstants.TypeNames.NameDouble), + new Tuple(TType.String, TJSONProtocolConstants.TypeNames.NameString), + new Tuple(TType.Struct, TJSONProtocolConstants.TypeNames.NameStruct), + new Tuple(TType.Map, TJSONProtocolConstants.TypeNames.NameMap), + new Tuple(TType.Set, TJSONProtocolConstants.TypeNames.NameSet), + new Tuple(TType.List, TJSONProtocolConstants.TypeNames.NameList), + }; + + foreach (var t in sets) + { + Assert.IsTrue(TJSONProtocolHelper.GetTypeIdForTypeName(t.Item2) == t.Item1, $"Wrong mapping of TypeName {t.Item2} to TType: {t.Item1}"); + } + } + + [TestMethod] + [ExpectedException(typeof(TProtocolException))] + public void GetTypeIdForTypeName_TStopTypeName_Test() + { + TJSONProtocolHelper.GetTypeIdForTypeName(new []{(byte)TType.Stop, (byte)TType.Stop}); + } + + [TestMethod] + [ExpectedException(typeof(TProtocolException))] + public void GetTypeIdForTypeName_NonExistingTypeName_Test() + { + TJSONProtocolHelper.GetTypeIdForTypeName(new byte[]{100}); + } + + [TestMethod] + [ExpectedException(typeof(TProtocolException))] + public void GetTypeIdForTypeName_EmptyName_Test() + { + TJSONProtocolHelper.GetTypeIdForTypeName(new byte[] {}); + } + + [TestMethod] + public void IsJsonNumeric_Test() + { + // input/output + var correctJsonNumeric = "+-.0123456789Ee"; + var incorrectJsonNumeric = "AaBcDd/*\\"; + + var sets = correctJsonNumeric.Select(ch => new Tuple((byte) ch, true)).ToList(); + sets.AddRange(incorrectJsonNumeric.Select(ch => new Tuple((byte) ch, false))); + + foreach (var t in sets) + { + Assert.IsTrue(TJSONProtocolHelper.IsJsonNumeric(t.Item1) == t.Item2, $"Wrong mapping of Char {t.Item1} to bool: {t.Item2}"); + } + } + + [TestMethod] + public void ToHexVal_Test() + { + // input/output + var chars = "0123456789abcdef"; + var expectedHexValues = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + + var sets = chars.Select((ch, i) => new Tuple(ch, expectedHexValues[i])).ToList(); + + foreach (var t in sets) + { + var actualResult = TJSONProtocolHelper.ToHexVal((byte)t.Item1); + Assert.IsTrue(actualResult == t.Item2, $"Wrong mapping of char byte {t.Item1} to it expected hex value: {t.Item2}. Actual hex value: {actualResult}"); + } + } + + [TestMethod] + [ExpectedException(typeof(TProtocolException))] + public void ToHexVal_WrongInputChar_Test() + { + TJSONProtocolHelper.ToHexVal((byte)'s'); + } + + [TestMethod] + public void ToHexChar_Test() + { + // input/output + var hexValues = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + var expectedChars = "0123456789abcdef"; + + + var sets = hexValues.Select((hv, i) => new Tuple(hv, expectedChars[i])).ToList(); + + foreach (var t in sets) + { + var actualResult = TJSONProtocolHelper.ToHexChar(t.Item1); + Assert.IsTrue(actualResult == t.Item2, $"Wrong mapping of hex value {t.Item1} to it expected char: {t.Item2}. Actual hex value: {actualResult}"); + } + } + } +} \ No newline at end of file diff --git a/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs b/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs new file mode 100644 index 00000000000..a74f42b39c0 --- /dev/null +++ b/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs @@ -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. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using NSubstitute; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Transport; +using Thrift.Transport.Client; + +namespace Thrift.Tests.Protocols +{ + // ReSharper disable once InconsistentNaming + [TestClass] + public class TJSONProtocolTests + { + [TestMethod] + public void TJSONProtocol_Can_Create_Instance_Test() + { + var httpClientTransport = Substitute.For(new Uri("http://localhost"), null); + + var result = new TJSONProtocolWrapper(httpClientTransport); + + Assert.IsNotNull(result); + Assert.IsNotNull(result.WrappedContext); + Assert.IsNotNull(result.WrappedReader); + Assert.IsNotNull(result.Transport); + Assert.IsTrue(result.WrappedRecursionDepth == 0); + Assert.IsTrue(result.WrappedRecursionLimit == TProtocol.DefaultRecursionDepth); + + Assert.IsTrue(result.Transport.Equals(httpClientTransport)); + Assert.IsTrue(result.WrappedContext.GetType().Name.Equals("JSONBaseContext", StringComparison.OrdinalIgnoreCase)); + Assert.IsTrue(result.WrappedReader.GetType().Name.Equals("LookaheadReader", StringComparison.OrdinalIgnoreCase)); + } + + private class TJSONProtocolWrapper : TJsonProtocol + { + public TJSONProtocolWrapper(TTransport trans) : base(trans) + { + } + + public object WrappedContext => Context; + public object WrappedReader => Reader; + public int WrappedRecursionDepth => RecursionDepth; + public int WrappedRecursionLimit => RecursionLimit; + } + } +} diff --git a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj new file mode 100644 index 00000000000..3150910ce99 --- /dev/null +++ b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj @@ -0,0 +1,36 @@ + + + + netcoreapp2.0 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/netstd/Thrift.sln b/lib/netstd/Thrift.sln new file mode 100644 index 00000000000..2952eb0d885 --- /dev/null +++ b/lib/netstd/Thrift.sln @@ -0,0 +1,85 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{ED5A45B0-07D1-4507-96B7-83FBD3D031CA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "Thrift\Thrift.csproj", "{5B501D21-D428-408D-AB5C-32D6F5355294}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.IntegrationTests", "Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj", "{837F4084-AAD7-45F5-BC96-10E05A669DB4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.Tests", "Tests\Thrift.Tests\Thrift.Tests.csproj", "{0790D388-1A3C-4423-8CF2-C97074A8B68B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.PublicInterfaces.Compile.Tests", "Tests\Thrift.PublicInterfaces.Compile.Tests\Thrift.PublicInterfaces.Compile.Tests.csproj", "{A6AE021D-61CB-4D84-A103-0B663C62AE2C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|x64.ActiveCfg = Debug|Any CPU + {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|x64.Build.0 = Debug|Any CPU + {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|x86.ActiveCfg = Debug|Any CPU + {5B501D21-D428-408D-AB5C-32D6F5355294}.Debug|x86.Build.0 = Debug|Any CPU + {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|Any CPU.Build.0 = Release|Any CPU + {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|x64.ActiveCfg = Release|Any CPU + {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|x64.Build.0 = Release|Any CPU + {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|x86.ActiveCfg = Release|Any CPU + {5B501D21-D428-408D-AB5C-32D6F5355294}.Release|x86.Build.0 = Release|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|x64.ActiveCfg = Debug|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|x64.Build.0 = Debug|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|x86.ActiveCfg = Debug|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Debug|x86.Build.0 = Debug|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|Any CPU.Build.0 = Release|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|x64.ActiveCfg = Release|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|x64.Build.0 = Release|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|x86.ActiveCfg = Release|Any CPU + {837F4084-AAD7-45F5-BC96-10E05A669DB4}.Release|x86.Build.0 = Release|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|x64.ActiveCfg = Debug|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|x64.Build.0 = Debug|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|x86.ActiveCfg = Debug|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Debug|x86.Build.0 = Debug|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|Any CPU.Build.0 = Release|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|x64.ActiveCfg = Release|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|x64.Build.0 = Release|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|x86.ActiveCfg = Release|Any CPU + {0790D388-1A3C-4423-8CF2-C97074A8B68B}.Release|x86.Build.0 = Release|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|x64.ActiveCfg = Debug|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|x64.Build.0 = Debug|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|x86.ActiveCfg = Debug|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Debug|x86.Build.0 = Debug|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|Any CPU.Build.0 = Release|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|x64.ActiveCfg = Release|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|x64.Build.0 = Release|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|x86.ActiveCfg = Release|Any CPU + {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {837F4084-AAD7-45F5-BC96-10E05A669DB4} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA} + {0790D388-1A3C-4423-8CF2-C97074A8B68B} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA} + {A6AE021D-61CB-4D84-A103-0B663C62AE2C} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FD20BC4A-0109-41D8-8C0C-893E784D7EF9} + EndGlobalSection +EndGlobal diff --git a/lib/netstd/Thrift/Collections/TCollections.cs b/lib/netstd/Thrift/Collections/TCollections.cs new file mode 100644 index 00000000000..147bfc7d31c --- /dev/null +++ b/lib/netstd/Thrift/Collections/TCollections.cs @@ -0,0 +1,101 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Collections; + +namespace Thrift.Collections +{ + // ReSharper disable once InconsistentNaming + public class TCollections + { + /// + /// This will return true if the two collections are value-wise the same. + /// If the collection contains a collection, the collections will be compared using this method. + /// + public static bool Equals(IEnumerable first, IEnumerable second) + { + if (first == null && second == null) + { + return true; + } + + if (first == null || second == null) + { + return false; + } + + var fiter = first.GetEnumerator(); + var siter = second.GetEnumerator(); + + var fnext = fiter.MoveNext(); + var snext = siter.MoveNext(); + + while (fnext && snext) + { + var fenum = fiter.Current as IEnumerable; + var senum = siter.Current as IEnumerable; + + if (fenum != null && senum != null) + { + if (!Equals(fenum, senum)) + { + return false; + } + } + else if (fenum == null ^ senum == null) + { + return false; + } + else if (!Equals(fiter.Current, siter.Current)) + { + return false; + } + + fnext = fiter.MoveNext(); + snext = siter.MoveNext(); + } + + return fnext == snext; + } + + /// + /// This returns a hashcode based on the value of the enumerable. + /// + public static int GetHashCode(IEnumerable enumerable) + { + if (enumerable == null) + { + return 0; + } + + var hashcode = 0; + + foreach (var obj in enumerable) + { + var enum2 = obj as IEnumerable; + var objHash = enum2 == null ? obj.GetHashCode() : GetHashCode(enum2); + + unchecked + { + hashcode = (hashcode*397) ^ (objHash); + } + } + + return hashcode; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Collections/THashSet.cs b/lib/netstd/Thrift/Collections/THashSet.cs new file mode 100644 index 00000000000..011f0a0d629 --- /dev/null +++ b/lib/netstd/Thrift/Collections/THashSet.cs @@ -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. + +using System.Collections; +using System.Collections.Generic; + +namespace Thrift.Collections +{ + // ReSharper disable once InconsistentNaming + public class THashSet : ICollection + { + private readonly HashSet _set = new HashSet(); + + public int Count => _set.Count; + + public bool IsReadOnly => false; + + public void Add(T item) + { + _set.Add(item); + } + + public void Clear() + { + _set.Clear(); + } + + public bool Contains(T item) + { + return _set.Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + _set.CopyTo(array, arrayIndex); + } + + public IEnumerator GetEnumerator() + { + return _set.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable) _set).GetEnumerator(); + } + + public bool Remove(T item) + { + return _set.Remove(item); + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Processor/ITAsyncProcessor.cs b/lib/netstd/Thrift/Processor/ITAsyncProcessor.cs new file mode 100644 index 00000000000..b8c1bce7213 --- /dev/null +++ b/lib/netstd/Thrift/Processor/ITAsyncProcessor.cs @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol; + +namespace Thrift.Processor +{ + public interface ITAsyncProcessor + { + Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken = default(CancellationToken)); + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Processor/ITProcessorFactory.cs b/lib/netstd/Thrift/Processor/ITProcessorFactory.cs new file mode 100644 index 00000000000..e0fe3d0a8d8 --- /dev/null +++ b/lib/netstd/Thrift/Processor/ITProcessorFactory.cs @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using Thrift.Server; +using Thrift.Transport; + +namespace Thrift.Processor +{ + // ReSharper disable once InconsistentNaming + public interface ITProcessorFactory + { + ITAsyncProcessor GetAsyncProcessor(TTransport trans, TServer baseServer = null); + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs b/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs new file mode 100644 index 00000000000..81274be965e --- /dev/null +++ b/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs @@ -0,0 +1,143 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol; +using Thrift.Protocol.Entities; + +namespace Thrift.Processor +{ + // ReSharper disable once InconsistentNaming + public class TMultiplexedProcessor : ITAsyncProcessor + { + //TODO: Localization + + private readonly Dictionary _serviceProcessorMap = + new Dictionary(); + + public async Task ProcessAsync(TProtocol iprot, TProtocol oprot) + { + return await ProcessAsync(iprot, oprot, CancellationToken.None); + } + + public async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + try + { + var message = await iprot.ReadMessageBeginAsync(cancellationToken); + + if ((message.Type != TMessageType.Call) && (message.Type != TMessageType.Oneway)) + { + await FailAsync(oprot, message, TApplicationException.ExceptionType.InvalidMessageType, + "Message exType CALL or ONEWAY expected", cancellationToken); + return false; + } + + // Extract the service name + var index = message.Name.IndexOf(TMultiplexedProtocol.Separator, StringComparison.Ordinal); + if (index < 0) + { + await FailAsync(oprot, message, TApplicationException.ExceptionType.InvalidProtocol, + $"Service name not found in message name: {message.Name}. Did you forget to use a TMultiplexProtocol in your client?", + cancellationToken); + return false; + } + + // Create a new TMessage, something that can be consumed by any TProtocol + var serviceName = message.Name.Substring(0, index); + ITAsyncProcessor actualProcessor; + if (!_serviceProcessorMap.TryGetValue(serviceName, out actualProcessor)) + { + await FailAsync(oprot, message, TApplicationException.ExceptionType.InternalError, + $"Service name not found: {serviceName}. Did you forget to call RegisterProcessor()?", + cancellationToken); + return false; + } + + // Create a new TMessage, removing the service name + var newMessage = new TMessage( + message.Name.Substring(serviceName.Length + TMultiplexedProtocol.Separator.Length), + message.Type, + message.SeqID); + + // Dispatch processing to the stored processor + return + await + actualProcessor.ProcessAsync(new StoredMessageProtocol(iprot, newMessage), oprot, + cancellationToken); + } + catch (IOException) + { + return false; // similar to all other processors + } + } + + public void RegisterProcessor(string serviceName, ITAsyncProcessor processor) + { + if (_serviceProcessorMap.ContainsKey(serviceName)) + { + throw new InvalidOperationException( + $"Processor map already contains processor with name: '{serviceName}'"); + } + + _serviceProcessorMap.Add(serviceName, processor); + } + + private async Task FailAsync(TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, + string etxt, CancellationToken cancellationToken) + { + var appex = new TApplicationException(extype, etxt); + + var newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID); + + await oprot.WriteMessageBeginAsync(newMessage, cancellationToken); + await appex.WriteAsync(oprot, cancellationToken); + await oprot.WriteMessageEndAsync(cancellationToken); + await oprot.Transport.FlushAsync(cancellationToken); + } + + private class StoredMessageProtocol : TProtocolDecorator + { + readonly TMessage _msgBegin; + + public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) + : base(protocol) + { + _msgBegin = messageBegin; + } + + public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + return _msgBegin; + } + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Processor/TSingletonProcessorFactory.cs b/lib/netstd/Thrift/Processor/TSingletonProcessorFactory.cs new file mode 100644 index 00000000000..97ecff65c45 --- /dev/null +++ b/lib/netstd/Thrift/Processor/TSingletonProcessorFactory.cs @@ -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. + +using Thrift.Server; +using Thrift.Transport; + +namespace Thrift.Processor +{ + // ReSharper disable once InconsistentNaming + public class TSingletonProcessorFactory : ITProcessorFactory + { + private readonly ITAsyncProcessor _asyncProcessor; + + public TSingletonProcessorFactory(ITAsyncProcessor asyncProcessor) + { + _asyncProcessor = asyncProcessor; + } + + public ITAsyncProcessor GetAsyncProcessor(TTransport trans, TServer baseServer = null) + { + return _asyncProcessor; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Properties/AssemblyInfo.cs b/lib/netstd/Thrift/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..e3118ab23be --- /dev/null +++ b/lib/netstd/Thrift/Properties/AssemblyInfo.cs @@ -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. + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Thrift")] +[assembly: AssemblyDescription("C# .NET Core bindings for the Apache Thrift RPC system")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +//@TODO where to put License information? + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a exType in this assembly from +// COM, set the ComVisible attribute to true on that exType. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("df3f8ef0-e0a3-4c86-a65b-8ec84e016b1d")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.0.1")] +[assembly: AssemblyFileVersion("1.0.0.1")] \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Entities/TField.cs b/lib/netstd/Thrift/Protocol/Entities/TField.cs new file mode 100644 index 00000000000..4e29bb5d4e4 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Entities/TField.cs @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TField + { + public TField(string name, TType type, short id) + { + Name = name; + Type = type; + ID = id; + } + + public string Name { get; set; } + + public TType Type { get; set; } + + // ReSharper disable once InconsistentNaming - do not rename - it used for generation + public short ID { get; set; } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Entities/TList.cs b/lib/netstd/Thrift/Protocol/Entities/TList.cs new file mode 100644 index 00000000000..f5992256444 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Entities/TList.cs @@ -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. + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TList + { + public TList(TType elementType, int count) + { + ElementType = elementType; + Count = count; + } + + public TType ElementType { get; set; } + + public int Count { get; set; } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Entities/TMap.cs b/lib/netstd/Thrift/Protocol/Entities/TMap.cs new file mode 100644 index 00000000000..1efebe7a199 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Entities/TMap.cs @@ -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. + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TMap + { + public TMap(TType keyType, TType valueType, int count) + { + KeyType = keyType; + ValueType = valueType; + Count = count; + } + + public TType KeyType { get; set; } + + public TType ValueType { get; set; } + + public int Count { get; set; } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Entities/TMessage.cs b/lib/netstd/Thrift/Protocol/Entities/TMessage.cs new file mode 100644 index 00000000000..08d741d65ec --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Entities/TMessage.cs @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TMessage + { + public TMessage(string name, TMessageType type, int seqid) + { + Name = name; + Type = type; + SeqID = seqid; + } + + public string Name { get; set; } + + public TMessageType Type { get; set; } + + // ReSharper disable once InconsistentNaming - do not rename - it used for generation + public int SeqID { get; set; } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Entities/TMessageType.cs b/lib/netstd/Thrift/Protocol/Entities/TMessageType.cs new file mode 100644 index 00000000000..24d663e2d32 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Entities/TMessageType.cs @@ -0,0 +1,28 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public enum TMessageType + { + Call = 1, + Reply = 2, + Exception = 3, + Oneway = 4 + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Entities/TSet.cs b/lib/netstd/Thrift/Protocol/Entities/TSet.cs new file mode 100644 index 00000000000..692d5642c4e --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Entities/TSet.cs @@ -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. + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TSet + { + public TSet(TType elementType, int count) + { + ElementType = elementType; + Count = count; + } + + public TSet(TList list) + : this(list.ElementType, list.Count) + { + } + + public TType ElementType { get; set; } + + public int Count { get; set; } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Entities/TStruct.cs b/lib/netstd/Thrift/Protocol/Entities/TStruct.cs new file mode 100644 index 00000000000..e04167e475a --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Entities/TStruct.cs @@ -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. + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public struct TStruct + { + public TStruct(string name) + { + Name = name; + } + + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Entities/TType.cs b/lib/netstd/Thrift/Protocol/Entities/TType.cs new file mode 100644 index 00000000000..4e922a7e756 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Entities/TType.cs @@ -0,0 +1,37 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +namespace Thrift.Protocol.Entities +{ + // ReSharper disable once InconsistentNaming + public enum TType : byte + { + Stop = 0, + Void = 1, + Bool = 2, + Byte = 3, + Double = 4, + I16 = 6, + I32 = 8, + I64 = 10, + String = 11, + Struct = 12, + Map = 13, + Set = 14, + List = 15 + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/ITProtocolFactory.cs b/lib/netstd/Thrift/Protocol/ITProtocolFactory.cs new file mode 100644 index 00000000000..3abcbb0fde5 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/ITProtocolFactory.cs @@ -0,0 +1,27 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using Thrift.Transport; + +namespace Thrift.Protocol +{ + // ReSharper disable once InconsistentNaming + public interface ITProtocolFactory + { + TProtocol GetProtocol(TTransport trans); + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/TBase.cs b/lib/netstd/Thrift/Protocol/TBase.cs new file mode 100644 index 00000000000..b5ef2aea923 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/TBase.cs @@ -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. + +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Protocol +{ + public interface TUnionBase + { + Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken = default(CancellationToken)); + } + + // ReSharper disable once InconsistentNaming + public interface TBase : TUnionBase + { + Task ReadAsync(TProtocol tProtocol, CancellationToken cancellationToken = default(CancellationToken)); + } +} diff --git a/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs new file mode 100644 index 00000000000..37bca8018b1 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs @@ -0,0 +1,613 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; +using Thrift.Transport; + +namespace Thrift.Protocol +{ + // ReSharper disable once InconsistentNaming + public class TBinaryProtocol : TProtocol + { + //TODO: Unit tests + //TODO: Localization + //TODO: pragma + + protected const uint VersionMask = 0xffff0000; + protected const uint Version1 = 0x80010000; + + protected bool StrictRead; + protected bool StrictWrite; + + public TBinaryProtocol(TTransport trans) + : this(trans, false, true) + { + } + + public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite) + : base(trans) + { + StrictRead = strictRead; + StrictWrite = strictWrite; + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + if (StrictWrite) + { + var version = Version1 | (uint) message.Type; + await WriteI32Async((int) version, cancellationToken); + await WriteStringAsync(message.Name, cancellationToken); + await WriteI32Async(message.SeqID, cancellationToken); + } + else + { + await WriteStringAsync(message.Name, cancellationToken); + await WriteByteAsync((sbyte) message.Type, cancellationToken); + await WriteI32Async(message.SeqID, cancellationToken); + } + } + + public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync((sbyte) field.Type, cancellationToken); + await WriteI16Async(field.ID, cancellationToken); + } + + public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync((sbyte) TType.Stop, cancellationToken); + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync((sbyte) map.KeyType, cancellationToken); + await WriteByteAsync((sbyte) map.ValueType, cancellationToken); + await WriteI32Async(map.Count, cancellationToken); + } + + public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync((sbyte) list.ElementType, cancellationToken); + await WriteI32Async(list.Count, cancellationToken); + } + + public override async Task WriteListEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync((sbyte) set.ElementType, cancellationToken); + await WriteI32Async(set.Count, cancellationToken); + } + + public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteByteAsync(b ? (sbyte) 1 : (sbyte) 0, cancellationToken); + } + + protected internal static byte[] CreateWriteByte(sbyte b) + { + var bout = new byte[1]; + + bout[0] = (byte) b; + + return bout; + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bout = CreateWriteByte(b); + await Trans.WriteAsync(bout, 0, 1, cancellationToken); + } + + protected internal static byte[] CreateWriteI16(short s) + { + var i16Out = new byte[2]; + + i16Out[0] = (byte) (0xff & (s >> 8)); + i16Out[1] = (byte) (0xff & s); + + return i16Out; + } + + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var i16Out = CreateWriteI16(i16); + await Trans.WriteAsync(i16Out, 0, 2, cancellationToken); + } + + protected internal static byte[] CreateWriteI32(int i32) + { + var i32Out = new byte[4]; + + i32Out[0] = (byte) (0xff & (i32 >> 24)); + i32Out[1] = (byte) (0xff & (i32 >> 16)); + i32Out[2] = (byte) (0xff & (i32 >> 8)); + i32Out[3] = (byte) (0xff & i32); + + return i32Out; + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var i32Out = CreateWriteI32(i32); + await Trans.WriteAsync(i32Out, 0, 4, cancellationToken); + } + + protected internal static byte[] CreateWriteI64(long i64) + { + var i64Out = new byte[8]; + + i64Out[0] = (byte) (0xff & (i64 >> 56)); + i64Out[1] = (byte) (0xff & (i64 >> 48)); + i64Out[2] = (byte) (0xff & (i64 >> 40)); + i64Out[3] = (byte) (0xff & (i64 >> 32)); + i64Out[4] = (byte) (0xff & (i64 >> 24)); + i64Out[5] = (byte) (0xff & (i64 >> 16)); + i64Out[6] = (byte) (0xff & (i64 >> 8)); + i64Out[7] = (byte) (0xff & i64); + + return i64Out; + } + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var i64Out = CreateWriteI64(i64); + await Trans.WriteAsync(i64Out, 0, 8, cancellationToken); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteI64Async(BitConverter.DoubleToInt64Bits(d), cancellationToken); + } + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteI32Async(bytes.Length, cancellationToken); + await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); + } + + public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var message = new TMessage(); + var size = await ReadI32Async(cancellationToken); + if (size < 0) + { + var version = (uint) size & VersionMask; + if (version != Version1) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, + $"Bad version in ReadMessageBegin: {version}"); + } + message.Type = (TMessageType) (size & 0x000000ff); + message.Name = await ReadStringAsync(cancellationToken); + message.SeqID = await ReadI32Async(cancellationToken); + } + else + { + if (StrictRead) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, + "Missing version in ReadMessageBegin, old client?"); + } + message.Name = await ReadStringBodyAsync(size, cancellationToken); + message.Type = (TMessageType) await ReadByteAsync(cancellationToken); + message.SeqID = await ReadI32Async(cancellationToken); + } + return message; + } + + public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + //TODO: no read from internal transport? + return new TStruct(); + } + + public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var field = new TField + { + Type = (TType) await ReadByteAsync(cancellationToken) + }; + + if (field.Type != TType.Stop) + { + field.ID = await ReadI16Async(cancellationToken); + } + + return field; + } + + public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var map = new TMap + { + KeyType = (TType) await ReadByteAsync(cancellationToken), + ValueType = (TType) await ReadByteAsync(cancellationToken), + Count = await ReadI32Async(cancellationToken) + }; + + return map; + } + + public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var list = new TList + { + ElementType = (TType) await ReadByteAsync(cancellationToken), + Count = await ReadI32Async(cancellationToken) + }; + + return list; + } + + public override async Task ReadListEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var set = new TSet + { + ElementType = (TType) await ReadByteAsync(cancellationToken), + Count = await ReadI32Async(cancellationToken) + }; + + return set; + } + + public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task ReadBoolAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + return await ReadByteAsync(cancellationToken) == 1; + } + + public override async Task ReadByteAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var bin = new byte[1]; + await Trans.ReadAllAsync(bin, 0, 1, cancellationToken); //TODO: why readall ? + return (sbyte) bin[0]; + } + + public override async Task ReadI16Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var i16In = new byte[2]; + await Trans.ReadAllAsync(i16In, 0, 2, cancellationToken); + var result = (short) (((i16In[0] & 0xff) << 8) | i16In[1] & 0xff); + return result; + } + + public override async Task ReadI32Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var i32In = new byte[4]; + await Trans.ReadAllAsync(i32In, 0, 4, cancellationToken); + + var result = + ((i32In[0] & 0xff) << 24) | + ((i32In[1] & 0xff) << 16) | + ((i32In[2] & 0xff) << 8) | + i32In[3] & 0xff; + + return result; + } + +#pragma warning disable 675 + + protected internal long CreateReadI64(byte[] buf) + { + var result = + ((long) (buf[0] & 0xff) << 56) | + ((long) (buf[1] & 0xff) << 48) | + ((long) (buf[2] & 0xff) << 40) | + ((long) (buf[3] & 0xff) << 32) | + ((long) (buf[4] & 0xff) << 24) | + ((long) (buf[5] & 0xff) << 16) | + ((long) (buf[6] & 0xff) << 8) | + buf[7] & 0xff; + + return result; + } + +#pragma warning restore 675 + + public override async Task ReadI64Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var i64In = new byte[8]; + await Trans.ReadAllAsync(i64In, 0, 8, cancellationToken); + return CreateReadI64(i64In); + } + + public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var d = await ReadI64Async(cancellationToken); + return BitConverter.Int64BitsToDouble(d); + } + + public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var size = await ReadI32Async(cancellationToken); + var buf = new byte[size]; + await Trans.ReadAllAsync(buf, 0, size, cancellationToken); + return buf; + } + + private async Task ReadStringBodyAsync(int size, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + var buf = new byte[size]; + await Trans.ReadAllAsync(buf, 0, size, cancellationToken); + return Encoding.UTF8.GetString(buf, 0, buf.Length); + } + + public class Factory : ITProtocolFactory + { + protected bool StrictRead; + protected bool StrictWrite; + + public Factory() + : this(false, true) + { + } + + public Factory(bool strictRead, bool strictWrite) + { + StrictRead = strictRead; + StrictWrite = strictWrite; + } + + public TProtocol GetProtocol(TTransport trans) + { + return new TBinaryProtocol(trans, StrictRead, StrictWrite); + } + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs new file mode 100644 index 00000000000..9ff640a2576 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs @@ -0,0 +1,922 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; +using Thrift.Transport; + +namespace Thrift.Protocol +{ + //TODO: implementation of TProtocol + + // ReSharper disable once InconsistentNaming + public class TCompactProtocol : TProtocol + { + private const byte ProtocolId = 0x82; + private const byte Version = 1; + private const byte VersionMask = 0x1f; // 0001 1111 + private const byte TypeMask = 0xE0; // 1110 0000 + private const byte TypeBits = 0x07; // 0000 0111 + private const int TypeShiftAmount = 5; + private static readonly TStruct AnonymousStruct = new TStruct(string.Empty); + private static readonly TField Tstop = new TField(string.Empty, TType.Stop, 0); + + // ReSharper disable once InconsistentNaming + private static readonly byte[] TTypeToCompactType = new byte[16]; + + /// + /// Used to keep track of the last field for the current and previous structs, so we can do the delta stuff. + /// + private readonly Stack _lastField = new Stack(15); + + /// + /// If we encounter a boolean field begin, save the TField here so it can have the value incorporated. + /// + private TField? _booleanField; + + /// + /// If we Read a field header, and it's a boolean field, save the boolean value here so that ReadBool can use it. + /// + private bool? _boolValue; + + private short _lastFieldId; + + public TCompactProtocol(TTransport trans) + : base(trans) + { + TTypeToCompactType[(int) TType.Stop] = Types.Stop; + TTypeToCompactType[(int) TType.Bool] = Types.BooleanTrue; + TTypeToCompactType[(int) TType.Byte] = Types.Byte; + TTypeToCompactType[(int) TType.I16] = Types.I16; + TTypeToCompactType[(int) TType.I32] = Types.I32; + TTypeToCompactType[(int) TType.I64] = Types.I64; + TTypeToCompactType[(int) TType.Double] = Types.Double; + TTypeToCompactType[(int) TType.String] = Types.Binary; + TTypeToCompactType[(int) TType.List] = Types.List; + TTypeToCompactType[(int) TType.Set] = Types.Set; + TTypeToCompactType[(int) TType.Map] = Types.Map; + TTypeToCompactType[(int) TType.Struct] = Types.Struct; + } + + public void Reset() + { + _lastField.Clear(); + _lastFieldId = 0; + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await Trans.WriteAsync(new[] {ProtocolId}, cancellationToken); + await + Trans.WriteAsync( + new[] {(byte) ((Version & VersionMask) | (((uint) message.Type << TypeShiftAmount) & TypeMask))}, + cancellationToken); + + var bufferTuple = CreateWriteVarInt32((uint) message.SeqID); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + + await WriteStringAsync(message.Name, cancellationToken); + } + + public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + /// + /// 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 override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + _lastField.Push(_lastFieldId); + _lastFieldId = 0; + } + + public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + _lastFieldId = _lastField.Pop(); + } + + private async Task WriteFieldBeginInternalAsync(TField field, byte typeOverride, + CancellationToken cancellationToken) + { + // if there's a exType override, use that. + var typeToWrite = typeOverride == 0xFF ? GetCompactType(field.Type) : typeOverride; + + // check if we can use delta encoding for the field id + if ((field.ID > _lastFieldId) && (field.ID - _lastFieldId <= 15)) + { + var b = (byte) (((field.ID - _lastFieldId) << 4) | typeToWrite); + // Write them together + await Trans.WriteAsync(new[] {b}, cancellationToken); + } + else + { + // Write them separate + await Trans.WriteAsync(new[] {typeToWrite}, cancellationToken); + await WriteI16Async(field.ID, cancellationToken); + } + + _lastFieldId = field.ID; + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + if (field.Type == TType.Bool) + { + _booleanField = field; + } + else + { + await WriteFieldBeginInternalAsync(field, 0xFF, cancellationToken); + } + } + + public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await Trans.WriteAsync(new[] {Types.Stop}, cancellationToken); + } + + protected async Task WriteCollectionBeginAsync(TType elemType, int size, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + /* + Abstract method for writing the start of lists and sets. List and sets on + the wire differ only by the exType indicator. + */ + + if (size <= 14) + { + await Trans.WriteAsync(new[] {(byte) ((size << 4) | GetCompactType(elemType))}, cancellationToken); + } + else + { + await Trans.WriteAsync(new[] {(byte) (0xf0 | GetCompactType(elemType))}, cancellationToken); + + var bufferTuple = CreateWriteVarInt32((uint) size); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + } + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + await WriteCollectionBeginAsync(list.ElementType, list.Count, cancellationToken); + } + + public override async Task WriteListEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await WriteCollectionBeginAsync(set.ElementType, set.Count, cancellationToken); + } + + public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + /* + 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 exType header is for the value and then Write the field header. + Otherwise, Write a single byte. + */ + + if (_booleanField != null) + { + // we haven't written the field header yet + await + WriteFieldBeginInternalAsync(_booleanField.Value, b ? Types.BooleanTrue : Types.BooleanFalse, + cancellationToken); + _booleanField = null; + } + else + { + // we're not part of a field, so just Write the value. + await Trans.WriteAsync(new[] {b ? Types.BooleanTrue : Types.BooleanFalse}, cancellationToken); + } + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + await Trans.WriteAsync(new[] {(byte) b}, cancellationToken); + } + + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bufferTuple = CreateWriteVarInt32(IntToZigzag(i16)); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + } + + protected internal Tuple CreateWriteVarInt32(uint n) + { + // Write an i32 as a varint.Results in 1 - 5 bytes on the wire. + var i32Buf = new byte[5]; + var idx = 0; + + while (true) + { + if ((n & ~0x7F) == 0) + { + i32Buf[idx++] = (byte) n; + break; + } + + i32Buf[idx++] = (byte) ((n & 0x7F) | 0x80); + n >>= 7; + } + + return new Tuple(i32Buf, idx); + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bufferTuple = CreateWriteVarInt32(IntToZigzag(i32)); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + } + + protected internal Tuple CreateWriteVarInt64(ulong n) + { + // Write an i64 as a varint. Results in 1-10 bytes on the wire. + var buf = new byte[10]; + var idx = 0; + + while (true) + { + if ((n & ~(ulong) 0x7FL) == 0) + { + buf[idx++] = (byte) n; + break; + } + buf[idx++] = (byte) ((n & 0x7F) | 0x80); + n >>= 7; + } + + return new Tuple(buf, idx); + } + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bufferTuple = CreateWriteVarInt64(LongToZigzag(i64)); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var data = new byte[8]; + FixedLongToBytes(BitConverter.DoubleToInt64Bits(d), data, 0); + await Trans.WriteAsync(data, cancellationToken); + } + + public override async Task WriteStringAsync(string str, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bytes = Encoding.UTF8.GetBytes(str); + + var bufferTuple = CreateWriteVarInt32((uint) bytes.Length); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); + } + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + var bufferTuple = CreateWriteVarInt32((uint) bytes.Length); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + if (map.Count == 0) + { + await Trans.WriteAsync(new[] {(byte) 0}, cancellationToken); + } + else + { + var bufferTuple = CreateWriteVarInt32((uint) map.Count); + await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + await + Trans.WriteAsync( + new[] {(byte) ((GetCompactType(map.KeyType) << 4) | GetCompactType(map.ValueType))}, + cancellationToken); + } + } + + public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var protocolId = (byte) await ReadByteAsync(cancellationToken); + if (protocolId != ProtocolId) + { + throw new TProtocolException($"Expected protocol id {ProtocolId:X} but got {protocolId:X}"); + } + + var versionAndType = (byte) await ReadByteAsync(cancellationToken); + var version = (byte) (versionAndType & VersionMask); + + if (version != Version) + { + throw new TProtocolException($"Expected version {Version} but got {version}"); + } + + var type = (byte) ((versionAndType >> TypeShiftAmount) & TypeBits); + var seqid = (int) await ReadVarInt32Async(cancellationToken); + var messageName = await ReadStringAsync(cancellationToken); + + return new TMessage(messageName, (TMessageType) type, seqid); + } + + public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + // some magic is here ) + + _lastField.Push(_lastFieldId); + _lastFieldId = 0; + + return AnonymousStruct; + } + + public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + /* + Doesn't actually consume any wire data, just removes the last field for + this struct from the field stack. + */ + + // consume the last field we Read off the wire. + _lastFieldId = _lastField.Pop(); + } + + public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + { + // Read a field header off the wire. + var type = (byte) await ReadByteAsync(cancellationToken); + // if it's a stop, then we can return immediately, as the struct is over. + if (type == Types.Stop) + { + return Tstop; + } + + short fieldId; + // mask off the 4 MSB of the exType header. it could contain a field id delta. + var modifier = (short) ((type & 0xf0) >> 4); + if (modifier == 0) + { + fieldId = await ReadI16Async(cancellationToken); + } + else + { + fieldId = (short) (_lastFieldId + modifier); + } + + var field = new TField(string.Empty, GetTType((byte) (type & 0x0f)), fieldId); + // if this happens to be a boolean field, the value is encoded in the exType + if (IsBoolType(type)) + { + _boolValue = (byte) (type & 0x0f) == Types.BooleanTrue; + } + + // push the new field onto the field stack so we can keep the deltas going. + _lastFieldId = field.ID; + return field; + } + + public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + /* + Read a map header off the wire. If the size is zero, skip Reading the key + and value exType. This means that 0-length maps will yield TMaps without the + "correct" types. + */ + + var size = (int) await ReadVarInt32Async(cancellationToken); + var keyAndValueType = size == 0 ? (byte) 0 : (byte) await ReadByteAsync(cancellationToken); + return new TMap(GetTType((byte) (keyAndValueType >> 4)), GetTType((byte) (keyAndValueType & 0xf)), size); + } + + public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + { + /* + Read a set header off the wire. If the set size is 0-14, the size will + be packed into the element exType header. If it's a longer set, the 4 MSB + of the element exType header will be 0xF, and a varint will follow with the + true size. + */ + + return new TSet(await ReadListBeginAsync(cancellationToken)); + } + + public override async Task ReadBoolAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + /* + 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. + */ + + if (_boolValue != null) + { + var result = _boolValue.Value; + _boolValue = null; + return result; + } + + return await ReadByteAsync(cancellationToken) == Types.BooleanTrue; + } + + public override async Task ReadByteAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + // Read a single byte off the wire. Nothing interesting here. + var buf = new byte[1]; + await Trans.ReadAllAsync(buf, 0, 1, cancellationToken); + return (sbyte) buf[0]; + } + + public override async Task ReadI16Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + return (short) ZigzagToInt(await ReadVarInt32Async(cancellationToken)); + } + + public override async Task ReadI32Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + return ZigzagToInt(await ReadVarInt32Async(cancellationToken)); + } + + public override async Task ReadI64Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + return ZigzagToLong(await ReadVarInt64Async(cancellationToken)); + } + + public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var longBits = new byte[8]; + await Trans.ReadAllAsync(longBits, 0, 8, cancellationToken); + + return BitConverter.Int64BitsToDouble(BytesToLong(longBits)); + } + + public override async Task ReadStringAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + // Reads a byte[] (via ReadBinary), and then UTF-8 decodes it. + var length = (int) await ReadVarInt32Async(cancellationToken); + + if (length == 0) + { + return string.Empty; + } + + var buf = new byte[length]; + await Trans.ReadAllAsync(buf, 0, length, cancellationToken); + + return Encoding.UTF8.GetString(buf); + } + + public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + // Read a byte[] from the wire. + var length = (int) await ReadVarInt32Async(cancellationToken); + if (length == 0) + { + return new byte[0]; + } + + var buf = new byte[length]; + await Trans.ReadAllAsync(buf, 0, length, cancellationToken); + return buf; + } + + public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + /* + Read a list header off the wire. If the list size is 0-14, the size will + be packed into the element exType header. If it's a longer list, the 4 MSB + of the element exType header will be 0xF, and a varint will follow with the + true size. + */ + + var sizeAndType = (byte) await ReadByteAsync(cancellationToken); + var size = (sizeAndType >> 4) & 0x0f; + if (size == 15) + { + size = (int) await ReadVarInt32Async(cancellationToken); + } + + var type = GetTType(sizeAndType); + return new TList(type, size); + } + + public override async Task ReadListEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + private static byte GetCompactType(TType ttype) + { + // Given a TType value, find the appropriate TCompactProtocol.Types constant. + return TTypeToCompactType[(int) ttype]; + } + + + private async Task ReadVarInt32Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + /* + 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. + */ + + uint result = 0; + var shift = 0; + + while (true) + { + var b = (byte) await ReadByteAsync(cancellationToken); + result |= (uint) (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) + { + break; + } + shift += 7; + } + + return result; + } + + private async Task ReadVarInt64Async(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + /* + 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. + */ + + var shift = 0; + ulong result = 0; + while (true) + { + var b = (byte) await ReadByteAsync(cancellationToken); + result |= (ulong) (b & 0x7f) << shift; + if ((b & 0x80) != 0x80) + { + break; + } + shift += 7; + } + + return result; + } + + private static int ZigzagToInt(uint n) + { + return (int) (n >> 1) ^ -(int) (n & 1); + } + + private static long ZigzagToLong(ulong n) + { + return (long) (n >> 1) ^ -(long) (n & 1); + } + + private static long BytesToLong(byte[] bytes) + { + /* + 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. + */ + + 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); + } + + private static bool IsBoolType(byte b) + { + var lowerNibble = b & 0x0f; + return (lowerNibble == Types.BooleanTrue) || (lowerNibble == Types.BooleanFalse); + } + + private static TType GetTType(byte type) + { + // Given a TCompactProtocol.Types constant, convert it to its corresponding TType value. + switch ((byte) (type & 0x0f)) + { + case Types.Stop: + return TType.Stop; + case Types.BooleanFalse: + case Types.BooleanTrue: + 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 exType: {(byte) (type & 0x0f)}"); + } + } + + private static ulong LongToZigzag(long n) + { + // Convert l into a zigzag long. This allows negative numbers to be represented compactly as a varint + return (ulong) (n << 1) ^ (ulong) (n >> 63); + } + + private static uint IntToZigzag(int n) + { + // Convert n into a zigzag int. This allows negative numbers to be represented compactly as a varint + return (uint) (n << 1) ^ (uint) (n >> 31); + } + + private static void FixedLongToBytes(long n, byte[] buf, int off) + { + // Convert a long into little-endian bytes in buf starting at off and going until off+7. + 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); + } + + public class Factory : ITProtocolFactory + { + public TProtocol GetProtocol(TTransport trans) + { + return new TCompactProtocol(trans); + } + } + + /// + /// All of the on-wire exType codes. + /// + private static class Types + { + public const byte Stop = 0x00; + public const byte BooleanTrue = 0x01; + public const byte BooleanFalse = 0x02; + public const byte Byte = 0x03; + public const byte I16 = 0x04; + public const byte I32 = 0x05; + public const byte I64 = 0x06; + public const byte Double = 0x07; + public const byte Binary = 0x08; + public const byte List = 0x09; + public const byte Set = 0x0A; + public const byte Map = 0x0B; + public const byte Struct = 0x0C; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs new file mode 100644 index 00000000000..fab13853ec4 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs @@ -0,0 +1,981 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; +using Thrift.Transport; + +namespace Thrift.Protocol +{ + /// + /// 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. + /// Adapted from the Java version. + /// + // ReSharper disable once InconsistentNaming + public class TJsonProtocol : TProtocol + { + private const long Version = 1; + + // Temporary buffer used by several methods + private readonly byte[] _tempBuffer = new byte[4]; + + // Current context that we are in + protected JSONBaseContext Context; + + // Stack of nested contexts that we may be in + protected Stack ContextStack = new Stack(); + + // Reader that manages a 1-byte buffer + protected LookaheadReader Reader; + + // Default encoding + protected Encoding Utf8Encoding = Encoding.UTF8; + + /// + /// TJsonProtocol Constructor + /// + public TJsonProtocol(TTransport trans) + : base(trans) + { + Context = new JSONBaseContext(this); + Reader = new LookaheadReader(this); + } + + /// + /// Push a new JSON context onto the stack. + /// + protected void PushContext(JSONBaseContext c) + { + ContextStack.Push(Context); + Context = c; + } + + /// + /// Pop the last JSON context off the stack + /// + protected void PopContext() + { + Context = ContextStack.Pop(); + } + + /// + /// 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 async Task ReadJsonSyntaxCharAsync(byte[] bytes, CancellationToken cancellationToken) + { + var ch = await Reader.ReadAsync(cancellationToken); + if (ch != bytes[0]) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, $"Unexpected character: {(char) ch}"); + } + } + + /// + /// Write the bytes in array buf as a JSON characters, escaping as needed + /// + private async Task WriteJsonStringAsync(byte[] bytes, CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken); + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + + var len = bytes.Length; + for (var i = 0; i < len; i++) + { + if ((bytes[i] & 0x00FF) >= 0x30) + { + if (bytes[i] == TJSONProtocolConstants.Backslash[0]) + { + await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); + await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); + } + else + { + await Trans.WriteAsync(bytes.ToArray(), i, 1, cancellationToken); + } + } + else + { + _tempBuffer[0] = TJSONProtocolConstants.JsonCharTable[bytes[i]]; + if (_tempBuffer[0] == 1) + { + await Trans.WriteAsync(bytes, i, 1, cancellationToken); + } + else if (_tempBuffer[0] > 1) + { + await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); + await Trans.WriteAsync(_tempBuffer, 0, 1, cancellationToken); + } + else + { + await Trans.WriteAsync(TJSONProtocolConstants.EscSequences, cancellationToken); + _tempBuffer[0] = TJSONProtocolHelper.ToHexChar((byte) (bytes[i] >> 4)); + _tempBuffer[1] = TJSONProtocolHelper.ToHexChar(bytes[i]); + await Trans.WriteAsync(_tempBuffer, 0, 2, cancellationToken); + } + } + } + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + /// + /// 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 async Task WriteJsonIntegerAsync(long num, CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken); + var str = num.ToString(); + + var escapeNum = Context.EscapeNumbers(); + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + var bytes = Utf8Encoding.GetBytes(str); + await Trans.WriteAsync(bytes, cancellationToken); + + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + } + + /// + /// 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 async Task WriteJsonDoubleAsync(double num, CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken); + var str = num.ToString("G17", CultureInfo.InvariantCulture); + var special = false; + + switch (str[0]) + { + case 'N': // NaN + case 'I': // Infinity + special = true; + break; + case '-': + if (str[1] == 'I') + { + // -Infinity + special = true; + } + break; + } + + var escapeNum = special || Context.EscapeNumbers(); + + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + await Trans.WriteAsync(Utf8Encoding.GetBytes(str), cancellationToken); + + if (escapeNum) + { + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + } + + /// + /// Write out contents of byte array b as a JSON string with base-64 encoded + /// data + /// + private async Task WriteJsonBase64Async(byte[] bytes, CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken); + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + + var len = bytes.Length; + var off = 0; + + while (len >= 3) + { + // Encode 3 bytes at a time + TBase64Utils.Encode(bytes, off, 3, _tempBuffer, 0); + await Trans.WriteAsync(_tempBuffer, 0, 4, cancellationToken); + off += 3; + len -= 3; + } + + if (len > 0) + { + // Encode remainder + TBase64Utils.Encode(bytes, off, len, _tempBuffer, 0); + await Trans.WriteAsync(_tempBuffer, 0, len + 1, cancellationToken); + } + + await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + private async Task WriteJsonObjectStartAsync(CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken); + await Trans.WriteAsync(TJSONProtocolConstants.LeftBrace, cancellationToken); + PushContext(new JSONPairContext(this)); + } + + private async Task WriteJsonObjectEndAsync(CancellationToken cancellationToken) + { + PopContext(); + await Trans.WriteAsync(TJSONProtocolConstants.RightBrace, cancellationToken); + } + + private async Task WriteJsonArrayStartAsync(CancellationToken cancellationToken) + { + await Context.WriteAsync(cancellationToken); + await Trans.WriteAsync(TJSONProtocolConstants.LeftBracket, cancellationToken); + PushContext(new JSONListContext(this)); + } + + private async Task WriteJsonArrayEndAsync(CancellationToken cancellationToken) + { + PopContext(); + await Trans.WriteAsync(TJSONProtocolConstants.RightBracket, cancellationToken); + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + await WriteJsonArrayStartAsync(cancellationToken); + await WriteJsonIntegerAsync(Version, cancellationToken); + + var b = Utf8Encoding.GetBytes(message.Name); + await WriteJsonStringAsync(b, cancellationToken); + + await WriteJsonIntegerAsync((long) message.Type, cancellationToken); + await WriteJsonIntegerAsync(message.SeqID, cancellationToken); + } + + public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + await WriteJsonArrayEndAsync(cancellationToken); + } + + public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + await WriteJsonObjectStartAsync(cancellationToken); + } + + public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + { + await WriteJsonObjectEndAsync(cancellationToken); + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(field.ID, cancellationToken); + await WriteJsonObjectStartAsync(cancellationToken); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(field.Type), cancellationToken); + } + + public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + await WriteJsonObjectEndAsync(cancellationToken); + } + + public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + await WriteJsonArrayStartAsync(cancellationToken); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.KeyType), cancellationToken); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.ValueType), cancellationToken); + await WriteJsonIntegerAsync(map.Count, cancellationToken); + await WriteJsonObjectStartAsync(cancellationToken); + } + + public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + { + await WriteJsonObjectEndAsync(cancellationToken); + await WriteJsonArrayEndAsync(cancellationToken); + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + await WriteJsonArrayStartAsync(cancellationToken); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(list.ElementType), cancellationToken); + await WriteJsonIntegerAsync(list.Count, cancellationToken); + } + + public override async Task WriteListEndAsync(CancellationToken cancellationToken) + { + await WriteJsonArrayEndAsync(cancellationToken); + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + await WriteJsonArrayStartAsync(cancellationToken); + await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(set.ElementType), cancellationToken); + await WriteJsonIntegerAsync(set.Count, cancellationToken); + } + + public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + { + await WriteJsonArrayEndAsync(cancellationToken); + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(b ? 1 : 0, cancellationToken); + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(b, cancellationToken); + } + + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(i16, cancellationToken); + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(i32, cancellationToken); + } + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + await WriteJsonIntegerAsync(i64, cancellationToken); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + await WriteJsonDoubleAsync(d, cancellationToken); + } + + public override async Task WriteStringAsync(string s, CancellationToken cancellationToken) + { + var b = Utf8Encoding.GetBytes(s); + await WriteJsonStringAsync(b, cancellationToken); + } + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + await WriteJsonBase64Async(bytes, cancellationToken); + } + + /// + /// Read in a JSON string, unescaping as appropriate.. Skip Reading from the + /// context if skipContext is true. + /// + private async Task ReadJsonStringAsync(bool skipContext, CancellationToken cancellationToken) + { + using (var buffer = new MemoryStream()) + { + var codeunits = new List(); + + + if (!skipContext) + { + await Context.ReadAsync(cancellationToken); + } + + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); + + while (true) + { + var ch = await Reader.ReadAsync(cancellationToken); + if (ch == TJSONProtocolConstants.Quote[0]) + { + break; + } + + // escaped? + if (ch != TJSONProtocolConstants.EscSequences[0]) + { + await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken); + continue; + } + + // distinguish between \uXXXX and \? + ch = await Reader.ReadAsync(cancellationToken); + if (ch != TJSONProtocolConstants.EscSequences[1]) // control chars like \n + { + var off = Array.IndexOf(TJSONProtocolConstants.EscapeChars, (char) ch); + if (off == -1) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected control char"); + } + ch = TJSONProtocolConstants.EscapeCharValues[off]; + await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken); + continue; + } + + // it's \uXXXX + await Trans.ReadAllAsync(_tempBuffer, 0, 4, cancellationToken); + + var wch = (short) ((TJSONProtocolHelper.ToHexVal(_tempBuffer[0]) << 12) + + (TJSONProtocolHelper.ToHexVal(_tempBuffer[1]) << 8) + + (TJSONProtocolHelper.ToHexVal(_tempBuffer[2]) << 4) + + TJSONProtocolHelper.ToHexVal(_tempBuffer[3])); + + if (char.IsHighSurrogate((char) wch)) + { + if (codeunits.Count > 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); + } + codeunits.Add((char) wch); + } + else if (char.IsLowSurrogate((char) wch)) + { + if (codeunits.Count == 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected high surrogate char"); + } + + codeunits.Add((char) wch); + var tmp = Utf8Encoding.GetBytes(codeunits.ToArray()); + await buffer.WriteAsync(tmp, 0, tmp.Length, cancellationToken); + codeunits.Clear(); + } + else + { + var tmp = Utf8Encoding.GetBytes(new[] {(char) wch}); + await buffer.WriteAsync(tmp, 0, tmp.Length, cancellationToken); + } + } + + if (codeunits.Count > 0) + { + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); + } + + return buffer.ToArray(); + } + } + + /// + /// 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 async Task ReadJsonNumericCharsAsync(CancellationToken cancellationToken) + { + var strbld = new StringBuilder(); + while (true) + { + //TODO: workaround for primitive types with TJsonProtocol, think - how to rewrite into more easy form without exceptions + try + { + var ch = await Reader.PeekAsync(cancellationToken); + if (!TJSONProtocolHelper.IsJsonNumeric(ch)) + { + break; + } + var c = (char)await Reader.ReadAsync(cancellationToken); + strbld.Append(c); + } + catch (TTransportException) + { + break; + } + } + return strbld.ToString(); + } + + /// + /// Read in a JSON number. If the context dictates, Read in enclosing quotes. + /// + private async Task ReadJsonIntegerAsync(CancellationToken cancellationToken) + { + await Context.ReadAsync(cancellationToken); + if (Context.EscapeNumbers()) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + var str = await ReadJsonNumericCharsAsync(cancellationToken); + if (Context.EscapeNumbers()) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + try + { + return long.Parse(str); + } + catch (FormatException) + { + 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 async Task ReadJsonDoubleAsync(CancellationToken cancellationToken) + { + await Context.ReadAsync(cancellationToken); + if (await Reader.PeekAsync(cancellationToken) == TJSONProtocolConstants.Quote[0]) + { + var arr = await ReadJsonStringAsync(true, cancellationToken); + var dub = double.Parse(Utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture); + + if (!Context.EscapeNumbers() && !double.IsNaN(dub) && !double.IsInfinity(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; + } + + if (Context.EscapeNumbers()) + { + // This will throw - we should have had a quote if escapeNum == true + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); + } + + try + { + return double.Parse(await ReadJsonNumericCharsAsync(cancellationToken), CultureInfo.InvariantCulture); + } + catch (FormatException) + { + 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 async Task ReadJsonBase64Async(CancellationToken cancellationToken) + { + var b = await ReadJsonStringAsync(false, cancellationToken); + var len = b.Length; + var off = 0; + var size = 0; + + // reduce len to ignore fill bytes + while ((len > 0) && (b[len - 1] == '=')) + { + --len; + } + + // read & decode full byte triplets = 4 source bytes + 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 exType) + 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?) + var result = new byte[size]; + Array.Copy(b, 0, result, 0, size); + return result; + } + + private async Task ReadJsonObjectStartAsync(CancellationToken cancellationToken) + { + await Context.ReadAsync(cancellationToken); + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBrace, cancellationToken); + PushContext(new JSONPairContext(this)); + } + + private async Task ReadJsonObjectEndAsync(CancellationToken cancellationToken) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBrace, cancellationToken); + PopContext(); + } + + private async Task ReadJsonArrayStartAsync(CancellationToken cancellationToken) + { + await Context.ReadAsync(cancellationToken); + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBracket, cancellationToken); + PushContext(new JSONListContext(this)); + } + + private async Task ReadJsonArrayEndAsync(CancellationToken cancellationToken) + { + await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBracket, cancellationToken); + PopContext(); + } + + public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + { + var message = new TMessage(); + await ReadJsonArrayStartAsync(cancellationToken); + if (await ReadJsonIntegerAsync(cancellationToken) != Version) + { + throw new TProtocolException(TProtocolException.BAD_VERSION, "Message contained bad version."); + } + + var buf = await ReadJsonStringAsync(false, cancellationToken); + message.Name = Utf8Encoding.GetString(buf, 0, buf.Length); + message.Type = (TMessageType) await ReadJsonIntegerAsync(cancellationToken); + message.SeqID = (int) await ReadJsonIntegerAsync(cancellationToken); + return message; + } + + public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + await ReadJsonArrayEndAsync(cancellationToken); + } + + public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectStartAsync(cancellationToken); + return new TStruct(); + } + + public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectEndAsync(cancellationToken); + } + + public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + { + var field = new TField(); + var ch = await Reader.PeekAsync(cancellationToken); + if (ch == TJSONProtocolConstants.RightBrace[0]) + { + field.Type = TType.Stop; + } + else + { + field.ID = (short) await ReadJsonIntegerAsync(cancellationToken); + await ReadJsonObjectStartAsync(cancellationToken); + field.Type = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); + } + return field; + } + + public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectEndAsync(cancellationToken); + } + + public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + { + var map = new TMap(); + await ReadJsonArrayStartAsync(cancellationToken); + map.KeyType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); + map.ValueType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); + map.Count = (int) await ReadJsonIntegerAsync(cancellationToken); + await ReadJsonObjectStartAsync(cancellationToken); + return map; + } + + public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + { + await ReadJsonObjectEndAsync(cancellationToken); + await ReadJsonArrayEndAsync(cancellationToken); + } + + public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + { + var list = new TList(); + await ReadJsonArrayStartAsync(cancellationToken); + list.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); + list.Count = (int) await ReadJsonIntegerAsync(cancellationToken); + return list; + } + + public override async Task ReadListEndAsync(CancellationToken cancellationToken) + { + await ReadJsonArrayEndAsync(cancellationToken); + } + + public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + { + var set = new TSet(); + await ReadJsonArrayStartAsync(cancellationToken); + set.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); + set.Count = (int) await ReadJsonIntegerAsync(cancellationToken); + return set; + } + + public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + { + await ReadJsonArrayEndAsync(cancellationToken); + } + + public override async Task ReadBoolAsync(CancellationToken cancellationToken) + { + return await ReadJsonIntegerAsync(cancellationToken) != 0; + } + + public override async Task ReadByteAsync(CancellationToken cancellationToken) + { + return (sbyte) await ReadJsonIntegerAsync(cancellationToken); + } + + public override async Task ReadI16Async(CancellationToken cancellationToken) + { + return (short) await ReadJsonIntegerAsync(cancellationToken); + } + + public override async Task ReadI32Async(CancellationToken cancellationToken) + { + return (int) await ReadJsonIntegerAsync(cancellationToken); + } + + public override async Task ReadI64Async(CancellationToken cancellationToken) + { + return await ReadJsonIntegerAsync(cancellationToken); + } + + public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + { + return await ReadJsonDoubleAsync(cancellationToken); + } + + public override async Task ReadStringAsync(CancellationToken cancellationToken) + { + var buf = await ReadJsonStringAsync(false, cancellationToken); + return Utf8Encoding.GetString(buf, 0, buf.Length); + } + + public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + { + return await ReadJsonBase64Async(cancellationToken); + } + + /// + /// Factory for JSON protocol objects + /// + public class Factory : ITProtocolFactory + { + public TProtocol GetProtocol(TTransport trans) + { + return new TJsonProtocol(trans); + } + } + + /// + /// Base class for tracking JSON contexts that may require + /// inserting/Reading additional JSON syntax characters + /// This base context does nothing. + /// + protected class JSONBaseContext + { + protected TJsonProtocol Proto; + + public JSONBaseContext(TJsonProtocol proto) + { + Proto = proto; + } + + public virtual async Task WriteAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public virtual async Task ReadAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public virtual bool EscapeNumbers() + { + return false; + } + } + + /// + /// Context for JSON lists. Will insert/Read commas before each item except + /// for the first one + /// + protected class JSONListContext : JSONBaseContext + { + private bool _first = true; + + public JSONListContext(TJsonProtocol protocol) + : base(protocol) + { + } + + public override async Task WriteAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + } + else + { + await Proto.Trans.WriteAsync(TJSONProtocolConstants.Comma, cancellationToken); + } + } + + public override async Task ReadAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + } + else + { + await Proto.ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Comma, cancellationToken); + } + } + } + + /// + /// 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). + /// + // ReSharper disable once InconsistentNaming + protected class JSONPairContext : JSONBaseContext + { + private bool _colon = true; + + private bool _first = true; + + public JSONPairContext(TJsonProtocol proto) + : base(proto) + { + } + + public override async Task WriteAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + _colon = true; + } + else + { + await Proto.Trans.WriteAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken); + _colon = !_colon; + } + } + + public override async Task ReadAsync(CancellationToken cancellationToken) + { + if (_first) + { + _first = false; + _colon = true; + } + else + { + await Proto.ReadJsonSyntaxCharAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken); + _colon = !_colon; + } + } + + public override bool EscapeNumbers() + { + return _colon; + } + } + + /// + /// Holds up to one byte from the transport + /// + protected class LookaheadReader + { + private readonly byte[] _data = new byte[1]; + + private bool _hasData; + protected TJsonProtocol Proto; + + public LookaheadReader(TJsonProtocol proto) + { + Proto = proto; + } + + /// + /// 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. + /// + public async Task ReadAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + if (_hasData) + { + _hasData = false; + } + else + { + // find more easy way to avoid exception on reading primitive types + await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken); + } + return _data[0]; + } + + /// + /// Return the next byte to be Read without consuming, filling the data + /// buffer if it has not been filled alReady. + /// + public async Task PeekAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + if (!_hasData) + { + // find more easy way to avoid exception on reading primitive types + await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken); + } + _hasData = true; + return _data[0]; + } + } + } +} diff --git a/lib/netstd/Thrift/Protocol/TMultiplexedProtocol.cs b/lib/netstd/Thrift/Protocol/TMultiplexedProtocol.cs new file mode 100644 index 00000000000..fbc8c05ccd7 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/TMultiplexedProtocol.cs @@ -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. + +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; + +namespace Thrift.Protocol +{ + /** + * 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 TO BE USED BY SERVERS. + * On the server, use TMultiplexedProcessor to handle requests from a multiplexing client. + * + * This example uses a single socket transport to invoke two services: + * + * TSocketTransport transport = new TSocketTransport("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()); + * + */ + + //TODO: implementation of TProtocol + + // ReSharper disable once InconsistentNaming + public class TMultiplexedProtocol : TProtocolDecorator + { + /** Used to delimit the service name from the function name */ + public const string Separator = ":"; + + private readonly string _serviceName; + + /** + * 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. + * + * Args: + * protocol Your communication protocol of choice, e.g. TBinaryProtocol + * serviceName The service name of the service communicating via this protocol. + */ + + public TMultiplexedProtocol(TProtocol protocol, string serviceName) + : base(protocol) + { + _serviceName = serviceName; + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + switch (message.Type) + { + case TMessageType.Call: + case TMessageType.Oneway: + await base.WriteMessageBeginAsync(new TMessage($"{_serviceName}{Separator}{message.Name}", message.Type, message.SeqID), cancellationToken); + break; + default: + await base.WriteMessageBeginAsync(message, cancellationToken); + break; + } + } + } +} diff --git a/lib/netstd/Thrift/Protocol/TProtocol.cs b/lib/netstd/Thrift/Protocol/TProtocol.cs new file mode 100644 index 00000000000..1bc91eb9850 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/TProtocol.cs @@ -0,0 +1,376 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; +using Thrift.Transport; + +namespace Thrift.Protocol +{ + // ReSharper disable once InconsistentNaming + public abstract class TProtocol : IDisposable + { + public const int DefaultRecursionDepth = 64; + private bool _isDisposed; + protected int RecursionDepth; + + protected TTransport Trans; + + protected TProtocol(TTransport trans) + { + Trans = trans; + RecursionLimit = DefaultRecursionDepth; + RecursionDepth = 0; + } + + public TTransport Transport => Trans; + + protected int RecursionLimit { get; set; } + + public void Dispose() + { + Dispose(true); + } + + public void IncrementRecursionDepth() + { + if (RecursionDepth < RecursionLimit) + { + ++RecursionDepth; + } + else + { + throw new TProtocolException(TProtocolException.DEPTH_LIMIT, "Depth limit exceeded"); + } + } + + public void DecrementRecursionDepth() + { + --RecursionDepth; + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + (Trans as IDisposable)?.Dispose(); + } + } + _isDisposed = true; + } + + public virtual async Task WriteMessageBeginAsync(TMessage message) + { + await WriteMessageBeginAsync(message, CancellationToken.None); + } + + public abstract Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken); + + public virtual async Task WriteMessageEndAsync() + { + await WriteMessageEndAsync(CancellationToken.None); + } + + public abstract Task WriteMessageEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteStructBeginAsync(TStruct @struct) + { + await WriteStructBeginAsync(@struct, CancellationToken.None); + } + + public abstract Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken); + + public virtual async Task WriteStructEndAsync() + { + await WriteStructEndAsync(CancellationToken.None); + } + + public abstract Task WriteStructEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteFieldBeginAsync(TField field) + { + await WriteFieldBeginAsync(field, CancellationToken.None); + } + + public abstract Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken); + + public virtual async Task WriteFieldEndAsync() + { + await WriteFieldEndAsync(CancellationToken.None); + } + + public abstract Task WriteFieldEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteFieldStopAsync() + { + await WriteFieldStopAsync(CancellationToken.None); + } + + public abstract Task WriteFieldStopAsync(CancellationToken cancellationToken); + + public virtual async Task WriteMapBeginAsync(TMap map) + { + await WriteMapBeginAsync(map, CancellationToken.None); + } + + public abstract Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken); + + public virtual async Task WriteMapEndAsync() + { + await WriteMapEndAsync(CancellationToken.None); + } + + public abstract Task WriteMapEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteListBeginAsync(TList list) + { + await WriteListBeginAsync(list, CancellationToken.None); + } + + public abstract Task WriteListBeginAsync(TList list, CancellationToken cancellationToken); + + public virtual async Task WriteListEndAsync() + { + await WriteListEndAsync(CancellationToken.None); + } + + public abstract Task WriteListEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteSetBeginAsync(TSet set) + { + await WriteSetBeginAsync(set, CancellationToken.None); + } + + public abstract Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken); + + public virtual async Task WriteSetEndAsync() + { + await WriteSetEndAsync(CancellationToken.None); + } + + public abstract Task WriteSetEndAsync(CancellationToken cancellationToken); + + public virtual async Task WriteBoolAsync(bool b) + { + await WriteBoolAsync(b, CancellationToken.None); + } + + public abstract Task WriteBoolAsync(bool b, CancellationToken cancellationToken); + + public virtual async Task WriteByteAsync(sbyte b) + { + await WriteByteAsync(b, CancellationToken.None); + } + + public abstract Task WriteByteAsync(sbyte b, CancellationToken cancellationToken); + + public virtual async Task WriteI16Async(short i16) + { + await WriteI16Async(i16, CancellationToken.None); + } + + public abstract Task WriteI16Async(short i16, CancellationToken cancellationToken); + + public virtual async Task WriteI32Async(int i32) + { + await WriteI32Async(i32, CancellationToken.None); + } + + public abstract Task WriteI32Async(int i32, CancellationToken cancellationToken); + + public virtual async Task WriteI64Async(long i64) + { + await WriteI64Async(i64, CancellationToken.None); + } + + public abstract Task WriteI64Async(long i64, CancellationToken cancellationToken); + + public virtual async Task WriteDoubleAsync(double d) + { + await WriteDoubleAsync(d, CancellationToken.None); + } + + public abstract Task WriteDoubleAsync(double d, CancellationToken cancellationToken); + + public virtual async Task WriteStringAsync(string s) + { + await WriteStringAsync(s, CancellationToken.None); + } + + public virtual async Task WriteStringAsync(string s, CancellationToken cancellationToken) + { + var bytes = Encoding.UTF8.GetBytes(s); + await WriteBinaryAsync(bytes, cancellationToken); + } + + public virtual async Task WriteBinaryAsync(byte[] bytes) + { + await WriteBinaryAsync(bytes, CancellationToken.None); + } + + public abstract Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken); + + public virtual async Task ReadMessageBeginAsync() + { + return await ReadMessageBeginAsync(CancellationToken.None); + } + + public abstract Task ReadMessageBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadMessageEndAsync() + { + await ReadMessageEndAsync(CancellationToken.None); + } + + public abstract Task ReadMessageEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadStructBeginAsync() + { + return await ReadStructBeginAsync(CancellationToken.None); + } + + public abstract Task ReadStructBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadStructEndAsync() + { + await ReadStructEndAsync(CancellationToken.None); + } + + public abstract Task ReadStructEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadFieldBeginAsync() + { + return await ReadFieldBeginAsync(CancellationToken.None); + } + + public abstract Task ReadFieldBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadFieldEndAsync() + { + await ReadFieldEndAsync(CancellationToken.None); + } + + public abstract Task ReadFieldEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadMapBeginAsync() + { + return await ReadMapBeginAsync(CancellationToken.None); + } + + public abstract Task ReadMapBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadMapEndAsync() + { + await ReadMapEndAsync(CancellationToken.None); + } + + public abstract Task ReadMapEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadListBeginAsync() + { + return await ReadListBeginAsync(CancellationToken.None); + } + + public abstract Task ReadListBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadListEndAsync() + { + await ReadListEndAsync(CancellationToken.None); + } + + public abstract Task ReadListEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadSetBeginAsync() + { + return await ReadSetBeginAsync(CancellationToken.None); + } + + public abstract Task ReadSetBeginAsync(CancellationToken cancellationToken); + + public virtual async Task ReadSetEndAsync() + { + await ReadSetEndAsync(CancellationToken.None); + } + + public abstract Task ReadSetEndAsync(CancellationToken cancellationToken); + + public virtual async Task ReadBoolAsync() + { + return await ReadBoolAsync(CancellationToken.None); + } + + public abstract Task ReadBoolAsync(CancellationToken cancellationToken); + + public virtual async Task ReadByteAsync() + { + return await ReadByteAsync(CancellationToken.None); + } + + public abstract Task ReadByteAsync(CancellationToken cancellationToken); + + public virtual async Task ReadI16Async() + { + return await ReadI16Async(CancellationToken.None); + } + + public abstract Task ReadI16Async(CancellationToken cancellationToken); + + public virtual async Task ReadI32Async() + { + return await ReadI32Async(CancellationToken.None); + } + + public abstract Task ReadI32Async(CancellationToken cancellationToken); + + public virtual async Task ReadI64Async() + { + return await ReadI64Async(CancellationToken.None); + } + + public abstract Task ReadI64Async(CancellationToken cancellationToken); + + public virtual async Task ReadDoubleAsync() + { + return await ReadDoubleAsync(CancellationToken.None); + } + + public abstract Task ReadDoubleAsync(CancellationToken cancellationToken); + + public virtual async Task ReadStringAsync() + { + return await ReadStringAsync(CancellationToken.None); + } + + public virtual async Task ReadStringAsync(CancellationToken cancellationToken) + { + var buf = await ReadBinaryAsync(cancellationToken); + return Encoding.UTF8.GetString(buf, 0, buf.Length); + } + + public virtual async Task ReadBinaryAsync() + { + return await ReadBinaryAsync(CancellationToken.None); + } + + public abstract Task ReadBinaryAsync(CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs b/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs new file mode 100644 index 00000000000..c8a433d0b66 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs @@ -0,0 +1,247 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; + +namespace Thrift.Protocol +{ + // ReSharper disable once InconsistentNaming + /// + /// 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. + /// + public abstract class TProtocolDecorator : TProtocol + { + private readonly TProtocol _wrappedProtocol; + + protected TProtocolDecorator(TProtocol protocol) + : base(protocol.Transport) + { + _wrappedProtocol = protocol ?? throw new ArgumentNullException(nameof(protocol)); + } + + public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMessageBeginAsync(message, cancellationToken); + } + + public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMessageEndAsync(cancellationToken); + } + + public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteStructBeginAsync(@struct, cancellationToken); + } + + public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteStructEndAsync(cancellationToken); + } + + public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteFieldBeginAsync(field, cancellationToken); + } + + public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteFieldEndAsync(cancellationToken); + } + + public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteFieldStopAsync(cancellationToken); + } + + public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMapBeginAsync(map, cancellationToken); + } + + public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteMapEndAsync(cancellationToken); + } + + public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteListBeginAsync(list, cancellationToken); + } + + public override async Task WriteListEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteListEndAsync(cancellationToken); + } + + public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteSetBeginAsync(set, cancellationToken); + } + + public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteSetEndAsync(cancellationToken); + } + + public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteBoolAsync(b, cancellationToken); + } + + public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteByteAsync(b, cancellationToken); + } + + public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteI16Async(i16, cancellationToken); + } + + public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteI32Async(i32, cancellationToken); + } + + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteI64Async(i64, cancellationToken); + } + + public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteDoubleAsync(d, cancellationToken); + } + + public override async Task WriteStringAsync(string s, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteStringAsync(s, cancellationToken); + } + + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) + { + await _wrappedProtocol.WriteBinaryAsync(bytes, cancellationToken); + } + + public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadMessageBeginAsync(cancellationToken); + } + + public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadMessageEndAsync(cancellationToken); + } + + public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadStructBeginAsync(cancellationToken); + } + + public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadStructEndAsync(cancellationToken); + } + + public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadFieldBeginAsync(cancellationToken); + } + + public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadFieldEndAsync(cancellationToken); + } + + public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadMapBeginAsync(cancellationToken); + } + + public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadMapEndAsync(cancellationToken); + } + + public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadListBeginAsync(cancellationToken); + } + + public override async Task ReadListEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadListEndAsync(cancellationToken); + } + + public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadSetBeginAsync(cancellationToken); + } + + public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + { + await _wrappedProtocol.ReadSetEndAsync(cancellationToken); + } + + public override async Task ReadBoolAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadBoolAsync(cancellationToken); + } + + public override async Task ReadByteAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadByteAsync(cancellationToken); + } + + public override async Task ReadI16Async(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadI16Async(cancellationToken); + } + + public override async Task ReadI32Async(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadI32Async(cancellationToken); + } + + public override async Task ReadI64Async(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadI64Async(cancellationToken); + } + + public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadDoubleAsync(cancellationToken); + } + + public override async Task ReadStringAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadStringAsync(cancellationToken); + } + + public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + { + return await _wrappedProtocol.ReadBinaryAsync(cancellationToken); + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/TProtocolException.cs b/lib/netstd/Thrift/Protocol/TProtocolException.cs new file mode 100644 index 00000000000..328babd051b --- /dev/null +++ b/lib/netstd/Thrift/Protocol/TProtocolException.cs @@ -0,0 +1,62 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +// ReSharper disable InconsistentNaming +using System; + +namespace Thrift.Protocol +{ + public class TProtocolException : TException + { + // do not rename public constants - they used in generated files + public const int UNKNOWN = 0; + public const int INVALID_DATA = 1; + public const int NEGATIVE_SIZE = 2; + public const int SIZE_LIMIT = 3; + public const int BAD_VERSION = 4; + public const int NOT_IMPLEMENTED = 5; + public const int DEPTH_LIMIT = 6; + + protected int Type = UNKNOWN; + + public TProtocolException() + { + } + + public TProtocolException(int type, Exception inner = null) + : base(string.Empty, inner) + { + Type = type; + } + + public TProtocolException(int type, string message, Exception inner = null) + : base(message, inner) + { + Type = type; + } + + public TProtocolException(string message, Exception inner = null) + : base(message, inner) + { + } + + public int GetExceptionType() + { + return Type; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Utilities/TBase64Utils.cs b/lib/netstd/Thrift/Protocol/Utilities/TBase64Utils.cs new file mode 100644 index 00000000000..90b8f8867b1 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Utilities/TBase64Utils.cs @@ -0,0 +1,101 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; + +namespace Thrift.Protocol.Utilities +{ + // ReSharper disable once InconsistentNaming + internal static class TBase64Utils + { + //TODO: Constants + //TODO: Check for args + //TODO: Unitests + + internal const string EncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + private static readonly int[] DecodeTable = + { + -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 + }; + + internal static void Encode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) + { + if (src == null) + { + throw new ArgumentNullException(nameof(src)); + } + + dst[dstOff] = (byte) EncodeTable[(src[srcOff] >> 2) & 0x3F]; + + if (len == 3) + { + dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; + dst[dstOff + 2] = (byte) EncodeTable[((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)]; + dst[dstOff + 3] = (byte) EncodeTable[src[srcOff + 2] & 0x3F]; + } + else if (len == 2) + { + dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; + dst[dstOff + 2] = (byte) EncodeTable[(src[srcOff + 1] << 2) & 0x3C]; + } + else + { + // len == 1 + dst[dstOff + 1] = (byte) EncodeTable[(src[srcOff] << 4) & 0x30]; + } + } + + internal static void Decode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) + { + if (src == null) + { + throw new ArgumentNullException(nameof(src)); + } + + dst[dstOff] = (byte) ((DecodeTable[src[srcOff] & 0x0FF] << 2) | (DecodeTable[src[srcOff + 1] & 0x0FF] >> 4)); + + if (len > 2) + { + dst[dstOff + 1] = + (byte) + (((DecodeTable[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) | (DecodeTable[src[srcOff + 2] & 0x0FF] >> 2)); + if (len > 3) + { + dst[dstOff + 2] = + (byte) + (((DecodeTable[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) | DecodeTable[src[srcOff + 3] & 0x0FF]); + } + } + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Utilities/TJsonProtocolConstants.cs b/lib/netstd/Thrift/Protocol/Utilities/TJsonProtocolConstants.cs new file mode 100644 index 00000000000..6cc1302e910 --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Utilities/TJsonProtocolConstants.cs @@ -0,0 +1,61 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +namespace Thrift.Protocol.Utilities +{ + // ReSharper disable once InconsistentNaming + public static class TJSONProtocolConstants + { + //TODO Check for performance for reusing ImmutableArray from System.Collections.Immutable (https://blogs.msdn.microsoft.com/dotnet/2013/06/24/please-welcome-immutablearrayt/) + // can be possible to get better performance and also better GC + + public static readonly byte[] Comma = {(byte) ','}; + public static readonly byte[] Colon = {(byte) ':'}; + public static readonly byte[] LeftBrace = {(byte) '{'}; + public static readonly byte[] RightBrace = {(byte) '}'}; + public static readonly byte[] LeftBracket = {(byte) '['}; + public static readonly byte[] RightBracket = {(byte) ']'}; + public static readonly byte[] Quote = {(byte) '"'}; + public static readonly byte[] Backslash = {(byte) '\\'}; + + public static readonly byte[] JsonCharTable = + { + 0, 0, 0, 0, 0, 0, 0, 0, (byte) 'b', (byte) 't', (byte) 'n', 0, (byte) 'f', (byte) 'r', 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, (byte) '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + }; + + public static readonly char[] EscapeChars = "\"\\/bfnrt".ToCharArray(); + public static readonly byte[] EscapeCharValues = {(byte) '"', (byte) '\\', (byte) '/', (byte) '\b', (byte) '\f', (byte) '\n', (byte) '\r', (byte) '\t'}; + public static readonly byte[] EscSequences = {(byte) '\\', (byte) 'u', (byte) '0', (byte) '0'}; + + public static class TypeNames + { + public static readonly byte[] NameBool = { (byte)'t', (byte)'f' }; + public static readonly byte[] NameByte = { (byte)'i', (byte)'8' }; + public static readonly byte[] NameI16 = { (byte)'i', (byte)'1', (byte)'6' }; + public static readonly byte[] NameI32 = { (byte)'i', (byte)'3', (byte)'2' }; + public static readonly byte[] NameI64 = { (byte)'i', (byte)'6', (byte)'4' }; + public static readonly byte[] NameDouble = { (byte)'d', (byte)'b', (byte)'l' }; + public static readonly byte[] NameStruct = { (byte)'r', (byte)'e', (byte)'c' }; + public static readonly byte[] NameString = { (byte)'s', (byte)'t', (byte)'r' }; + public static readonly byte[] NameMap = { (byte)'m', (byte)'a', (byte)'p' }; + public static readonly byte[] NameList = { (byte)'l', (byte)'s', (byte)'t' }; + public static readonly byte[] NameSet = { (byte)'s', (byte)'e', (byte)'t' }; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Utilities/TJsonProtocolHelper.cs b/lib/netstd/Thrift/Protocol/Utilities/TJsonProtocolHelper.cs new file mode 100644 index 00000000000..ff49ebe240e --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Utilities/TJsonProtocolHelper.cs @@ -0,0 +1,176 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using Thrift.Protocol.Entities; + +namespace Thrift.Protocol.Utilities +{ + // ReSharper disable once InconsistentNaming + public static class TJSONProtocolHelper + { + public static byte[] GetTypeNameForTypeId(TType typeId) + { + switch (typeId) + { + case TType.Bool: + return TJSONProtocolConstants.TypeNames.NameBool; + case TType.Byte: + return TJSONProtocolConstants.TypeNames.NameByte; + case TType.I16: + return TJSONProtocolConstants.TypeNames.NameI16; + case TType.I32: + return TJSONProtocolConstants.TypeNames.NameI32; + case TType.I64: + return TJSONProtocolConstants.TypeNames.NameI64; + case TType.Double: + return TJSONProtocolConstants.TypeNames.NameDouble; + case TType.String: + return TJSONProtocolConstants.TypeNames.NameString; + case TType.Struct: + return TJSONProtocolConstants.TypeNames.NameStruct; + case TType.Map: + return TJSONProtocolConstants.TypeNames.NameMap; + case TType.Set: + return TJSONProtocolConstants.TypeNames.NameSet; + case TType.List: + return TJSONProtocolConstants.TypeNames.NameList; + default: + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType"); + } + } + + public static TType GetTypeIdForTypeName(byte[] name) + { + var result = TType.Stop; + if (name.Length > 1) + { + switch (name[0]) + { + case (byte) 'd': + result = TType.Double; + break; + case (byte) 'i': + switch (name[1]) + { + case (byte) '8': + result = TType.Byte; + break; + case (byte) '1': + result = TType.I16; + break; + case (byte) '3': + result = TType.I32; + break; + case (byte) '6': + result = TType.I64; + break; + } + break; + case (byte) 'l': + result = TType.List; + break; + case (byte) 'm': + result = TType.Map; + break; + case (byte) 'r': + result = TType.Struct; + break; + case (byte) 's': + if (name[1] == (byte) 't') + { + result = TType.String; + } + else if (name[1] == (byte) 'e') + { + result = TType.Set; + } + break; + case (byte) 't': + result = TType.Bool; + break; + } + } + if (result == TType.Stop) + { + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType"); + } + return result; + } + + /// + /// Return true if the given byte could be a valid part of a JSON number. + /// + public static bool IsJsonNumeric(byte b) + { + switch (b) + { + case (byte)'+': + case (byte)'-': + case (byte)'.': + case (byte)'0': + case (byte)'1': + case (byte)'2': + case (byte)'3': + case (byte)'4': + case (byte)'5': + case (byte)'6': + case (byte)'7': + case (byte)'8': + case (byte)'9': + case (byte)'E': + case (byte)'e': + return true; + default: + return false; + } + } + + /// + /// Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its + /// corresponding hex value + /// + public static byte ToHexVal(byte ch) + { + if (ch >= '0' && ch <= '9') + { + return (byte)((char)ch - '0'); + } + + if (ch >= 'a' && ch <= 'f') + { + ch += 10; + return (byte)((char)ch - 'a'); + } + + throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected hex character"); + } + + /// + /// Convert a byte containing a hex value to its corresponding hex character + /// + public static byte ToHexChar(byte val) + { + val &= 0x0F; + if (val < 10) + { + return (byte)((char)val + '0'); + } + val -= 10; + return (byte)((char)val + 'a'); + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Protocol/Utilities/TProtocolUtil.cs b/lib/netstd/Thrift/Protocol/Utilities/TProtocolUtil.cs new file mode 100644 index 00000000000..18f92d8161e --- /dev/null +++ b/lib/netstd/Thrift/Protocol/Utilities/TProtocolUtil.cs @@ -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. + +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol.Entities; + +namespace Thrift.Protocol.Utilities +{ + // ReSharper disable once InconsistentNaming + public static class TProtocolUtil + { + public static async Task SkipAsync(TProtocol protocol, TType type, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + protocol.IncrementRecursionDepth(); + try + { + switch (type) + { + case TType.Bool: + await protocol.ReadBoolAsync(cancellationToken); + break; + case TType.Byte: + await protocol.ReadByteAsync(cancellationToken); + break; + case TType.I16: + await protocol.ReadI16Async(cancellationToken); + break; + case TType.I32: + await protocol.ReadI32Async(cancellationToken); + break; + case TType.I64: + await protocol.ReadI64Async(cancellationToken); + break; + case TType.Double: + await protocol.ReadDoubleAsync(cancellationToken); + break; + case TType.String: + // Don't try to decode the string, just skip it. + await protocol.ReadBinaryAsync(cancellationToken); + break; + case TType.Struct: + await protocol.ReadStructBeginAsync(cancellationToken); + while (true) + { + var field = await protocol.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + await SkipAsync(protocol, field.Type, cancellationToken); + await protocol.ReadFieldEndAsync(cancellationToken); + } + await protocol.ReadStructEndAsync(cancellationToken); + break; + case TType.Map: + var map = await protocol.ReadMapBeginAsync(cancellationToken); + for (var i = 0; i < map.Count; i++) + { + await SkipAsync(protocol, map.KeyType, cancellationToken); + await SkipAsync(protocol, map.ValueType, cancellationToken); + } + await protocol.ReadMapEndAsync(cancellationToken); + break; + case TType.Set: + var set = await protocol.ReadSetBeginAsync(cancellationToken); + for (var i = 0; i < set.Count; i++) + { + await SkipAsync(protocol, set.ElementType, cancellationToken); + } + await protocol.ReadSetEndAsync(cancellationToken); + break; + case TType.List: + var list = await protocol.ReadListBeginAsync(cancellationToken); + for (var i = 0; i < list.Count; i++) + { + await SkipAsync(protocol, list.ElementType, cancellationToken); + } + await protocol.ReadListEndAsync(cancellationToken); + break; + default: + throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d")); + } + } + finally + { + protocol.DecrementRecursionDepth(); + } + } + } +} diff --git a/lib/netstd/Thrift/Server/TServer.cs b/lib/netstd/Thrift/Server/TServer.cs new file mode 100644 index 00000000000..3a70c07735e --- /dev/null +++ b/lib/netstd/Thrift/Server/TServer.cs @@ -0,0 +1,87 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift.Protocol; +using Thrift.Transport; +using Thrift.Processor; + +namespace Thrift.Server +{ + // ReSharper disable once InconsistentNaming + public abstract class TServer + { + protected readonly ILogger Logger; + protected ITProtocolFactory InputProtocolFactory; + protected TTransportFactory InputTransportFactory; + protected ITProcessorFactory ProcessorFactory; + protected ITProtocolFactory OutputProtocolFactory; + protected TTransportFactory OutputTransportFactory; + + protected TServerEventHandler ServerEventHandler; + protected TServerTransport ServerTransport; + + protected TServer(ITProcessorFactory processorFactory, TServerTransport serverTransport, + TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, + ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory, + ILogger logger = null) + { + ProcessorFactory = processorFactory ?? throw new ArgumentNullException(nameof(processorFactory)); + ServerTransport = serverTransport; + InputTransportFactory = inputTransportFactory ?? throw new ArgumentNullException(nameof(inputTransportFactory)); + OutputTransportFactory = outputTransportFactory ?? throw new ArgumentNullException(nameof(outputTransportFactory)); + InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory)); + OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory)); + Logger = logger; // null is absolutely legal + } + + public void SetEventHandler(TServerEventHandler seh) + { + ServerEventHandler = seh; + } + + public TServerEventHandler GetEventHandler() + { + return ServerEventHandler; + } + + // Log delegation? deprecated, use ILogger + protected void LogError( string msg) + { + if (Logger != null) + Logger.LogError(msg); + } + + public abstract void Stop(); + + public virtual void Start() + { + // do nothing + } + + public virtual async Task ServeAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Server/TServerEventHandler.cs b/lib/netstd/Thrift/Server/TServerEventHandler.cs new file mode 100644 index 00000000000..0c31bf67dea --- /dev/null +++ b/lib/netstd/Thrift/Server/TServerEventHandler.cs @@ -0,0 +1,54 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol; +using Thrift.Transport; + +namespace Thrift.Server +{ + //TODO: replacement by event? + + /// + /// Interface implemented by server users to handle events from the server + /// + // ReSharper disable once InconsistentNaming + public interface TServerEventHandler + { + /// + /// Called before the server begins */ + /// + Task PreServeAsync(CancellationToken cancellationToken); + + /// + /// Called when a new client has connected and is about to being processing */ + /// + Task CreateContextAsync(TProtocol input, TProtocol output, CancellationToken cancellationToken); + + /// + /// Called when a client has finished request-handling to delete server context */ + /// + Task DeleteContextAsync(object serverContext, TProtocol input, TProtocol output, + CancellationToken cancellationToken); + + /// + /// Called when a client is about to call the processor */ + /// + Task ProcessContextAsync(object serverContext, TTransport transport, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs b/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs new file mode 100644 index 00000000000..a0a3e4c15f2 --- /dev/null +++ b/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs @@ -0,0 +1,196 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift.Protocol; +using Thrift.Processor; +using Thrift.Transport; + +namespace Thrift.Server +{ + //TODO: unhandled exceptions, etc. + + // ReSharper disable once InconsistentNaming + public class TSimpleAsyncServer : TServer + { + private readonly int _clientWaitingDelay; + private volatile Task _serverTask; + + public TSimpleAsyncServer(ITAsyncProcessor processor, TServerTransport serverTransport, + ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory, + ILoggerFactory loggerFactory, int clientWaitingDelay = 10) + : this(new TSingletonProcessorFactory(processor), serverTransport, + new TTransportFactory(), new TTransportFactory(), + inputProtocolFactory, outputProtocolFactory, + loggerFactory.CreateLogger(nameof(TSimpleAsyncServer)), clientWaitingDelay) + { + } + + public TSimpleAsyncServer(ITProcessorFactory itProcessorFactory, TServerTransport serverTransport, + TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, + ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory, + ILogger logger, int clientWaitingDelay = 10) + : base(itProcessorFactory, serverTransport, inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory, logger) + { + _clientWaitingDelay = clientWaitingDelay; + } + + public override async Task ServeAsync(CancellationToken cancellationToken) + { + try + { + // cancelation token + _serverTask = Task.Factory.StartNew(() => StartListening(cancellationToken), TaskCreationOptions.LongRunning); + await _serverTask; + } + catch (Exception ex) + { + Logger.LogError(ex.ToString()); + } + } + + private async Task StartListening(CancellationToken cancellationToken) + { + ServerTransport.Listen(); + + Logger.LogTrace("Started listening at server"); + + if (ServerEventHandler != null) + { + await ServerEventHandler.PreServeAsync(cancellationToken); + } + + while (!cancellationToken.IsCancellationRequested) + { + if (ServerTransport.IsClientPending()) + { + Logger.LogTrace("Waiting for client connection"); + + try + { + var client = await ServerTransport.AcceptAsync(cancellationToken); + await Task.Factory.StartNew(() => Execute(client, cancellationToken), cancellationToken); + } + catch (TTransportException ttx) + { + Logger.LogTrace($"Transport exception: {ttx}"); + + if (ttx.Type != TTransportException.ExceptionType.Interrupted) + { + Logger.LogError(ttx.ToString()); + } + } + } + else + { + try + { + await Task.Delay(TimeSpan.FromMilliseconds(_clientWaitingDelay), cancellationToken); + } + catch (TaskCanceledException) { } + } + } + + ServerTransport.Close(); + + Logger.LogTrace("Completed listening at server"); + } + + public override void Stop() + { + } + + private async Task Execute(TTransport client, CancellationToken cancellationToken) + { + Logger.LogTrace("Started client request processing"); + + var processor = ProcessorFactory.GetAsyncProcessor(client, this); + + TTransport inputTransport = null; + TTransport outputTransport = null; + TProtocol inputProtocol = null; + TProtocol outputProtocol = null; + object connectionContext = null; + + try + { + try + { + inputTransport = InputTransportFactory.GetTransport(client); + outputTransport = OutputTransportFactory.GetTransport(client); + inputProtocol = InputProtocolFactory.GetProtocol(inputTransport); + outputProtocol = OutputProtocolFactory.GetProtocol(outputTransport); + + if (ServerEventHandler != null) + { + connectionContext = await ServerEventHandler.CreateContextAsync(inputProtocol, outputProtocol, cancellationToken); + } + + while (!cancellationToken.IsCancellationRequested) + { + if (!await inputTransport.PeekAsync(cancellationToken)) + { + break; + } + + if (ServerEventHandler != null) + { + await ServerEventHandler.ProcessContextAsync(connectionContext, inputTransport, cancellationToken); + } + + if (!await processor.ProcessAsync(inputProtocol, outputProtocol, cancellationToken)) + { + break; + } + } + } + catch (TTransportException ttx) + { + Logger.LogTrace($"Transport exception: {ttx}"); + } + catch (Exception x) + { + Logger.LogError($"Error: {x}"); + } + + if (ServerEventHandler != null) + { + await ServerEventHandler.DeleteContextAsync(connectionContext, inputProtocol, outputProtocol, cancellationToken); + } + + } + finally + { + //Close transports + inputTransport?.Close(); + outputTransport?.Close(); + + // disposable stuff should be disposed + inputProtocol?.Dispose(); + outputProtocol?.Dispose(); + inputTransport?.Dispose(); + outputTransport?.Dispose(); + } + + Logger.LogTrace("Completed client request processing"); + } + } +} diff --git a/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs b/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs new file mode 100644 index 00000000000..e5c56607a36 --- /dev/null +++ b/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs @@ -0,0 +1,297 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Contains some contributions under the Thrift Software License. + * Please see doc/old-thrift-license.txt in the Thrift distribution for + * details. + */ + +using System; +using System.Threading; +using Thrift.Protocol; +using Thrift.Transport; +using Thrift.Processor; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; + +namespace Thrift.Server +{ + /// + /// Server that uses C# built-in ThreadPool to spawn threads when handling requests. + /// + public class TThreadPoolAsyncServer : TServer + { + private const int DEFAULT_MIN_THREADS = -1; // use .NET ThreadPool defaults + private const int DEFAULT_MAX_THREADS = -1; // use .NET ThreadPool defaults + private volatile bool stop = false; + + private CancellationToken ServerCancellationToken; + + public struct Configuration + { + public int MinWorkerThreads; + public int MaxWorkerThreads; + public int MinIOThreads; + public int MaxIOThreads; + + public Configuration(int min = DEFAULT_MIN_THREADS, int max = DEFAULT_MAX_THREADS) + { + MinWorkerThreads = min; + MaxWorkerThreads = max; + MinIOThreads = min; + MaxIOThreads = max; + } + + public Configuration(int minWork, int maxWork, int minIO, int maxIO) + { + MinWorkerThreads = minWork; + MaxWorkerThreads = maxWork; + MinIOThreads = minIO; + MaxIOThreads = maxIO; + } + } + + public TThreadPoolAsyncServer(ITAsyncProcessor processor, TServerTransport serverTransport, ILogger logger = null) + : this(new TSingletonProcessorFactory(processor), serverTransport, + new TTransportFactory(), new TTransportFactory(), + new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), + new Configuration(), logger) + { + } + + public TThreadPoolAsyncServer(ITAsyncProcessor processor, + TServerTransport serverTransport, + TTransportFactory transportFactory, + ITProtocolFactory protocolFactory) + : this(new TSingletonProcessorFactory(processor), serverTransport, + transportFactory, transportFactory, + protocolFactory, protocolFactory, + new Configuration()) + { + } + + public TThreadPoolAsyncServer(ITProcessorFactory processorFactory, + TServerTransport serverTransport, + TTransportFactory transportFactory, + ITProtocolFactory protocolFactory) + : this(processorFactory, serverTransport, + transportFactory, transportFactory, + protocolFactory, protocolFactory, + new Configuration()) + { + } + + public TThreadPoolAsyncServer(ITProcessorFactory processorFactory, + TServerTransport serverTransport, + TTransportFactory inputTransportFactory, + TTransportFactory outputTransportFactory, + ITProtocolFactory inputProtocolFactory, + ITProtocolFactory outputProtocolFactory, + int minThreadPoolThreads, int maxThreadPoolThreads, ILogger logger= null) + : this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory, + new Configuration(minThreadPoolThreads, maxThreadPoolThreads), + logger) + { + } + + public TThreadPoolAsyncServer(ITProcessorFactory processorFactory, + TServerTransport serverTransport, + TTransportFactory inputTransportFactory, + TTransportFactory outputTransportFactory, + ITProtocolFactory inputProtocolFactory, + ITProtocolFactory outputProtocolFactory, + Configuration threadConfig, + ILogger logger = null) + : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory, logger) + { + lock (typeof(TThreadPoolAsyncServer)) + { + if ((threadConfig.MaxWorkerThreads > 0) || (threadConfig.MaxIOThreads > 0)) + { + int work, comm; + ThreadPool.GetMaxThreads(out work, out comm); + if (threadConfig.MaxWorkerThreads > 0) + work = threadConfig.MaxWorkerThreads; + if (threadConfig.MaxIOThreads > 0) + comm = threadConfig.MaxIOThreads; + if (!ThreadPool.SetMaxThreads(work, comm)) + throw new Exception("Error: could not SetMaxThreads in ThreadPool"); + } + + if ((threadConfig.MinWorkerThreads > 0) || (threadConfig.MinIOThreads > 0)) + { + int work, comm; + ThreadPool.GetMinThreads(out work, out comm); + if (threadConfig.MinWorkerThreads > 0) + work = threadConfig.MinWorkerThreads; + if (threadConfig.MinIOThreads > 0) + comm = threadConfig.MinIOThreads; + if (!ThreadPool.SetMinThreads(work, comm)) + throw new Exception("Error: could not SetMinThreads in ThreadPool"); + } + } + } + + + /// + /// Use new ThreadPool thread for each new client connection. + /// + public override async Task ServeAsync(CancellationToken cancellationToken) + { + ServerCancellationToken = cancellationToken; + try + { + try + { + ServerTransport.Listen(); + } + catch (TTransportException ttx) + { + LogError("Error, could not listen on ServerTransport: " + ttx); + return; + } + + //Fire the preServe server event when server is up but before any client connections + if (ServerEventHandler != null) + await ServerEventHandler.PreServeAsync(cancellationToken); + + while (!stop) + { + int failureCount = 0; + try + { + TTransport client = await ServerTransport.AcceptAsync(cancellationToken); + ThreadPool.QueueUserWorkItem(this.Execute, client); + } + catch (TTransportException ttx) + { + if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted) + { + ++failureCount; + LogError(ttx.ToString()); + } + + } + } + + if (stop) + { + try + { + ServerTransport.Close(); + } + catch (TTransportException ttx) + { + LogError("TServerTransport failed on close: " + ttx.Message); + } + stop = false; + } + + } + finally + { + ServerCancellationToken = default(CancellationToken); + } + } + + /// + /// Loops on processing a client forever + /// threadContext will be a TTransport instance + /// + /// + private void Execute(object threadContext) + { + var cancellationToken = ServerCancellationToken; + + using (TTransport client = (TTransport)threadContext) + { + ITAsyncProcessor processor = ProcessorFactory.GetAsyncProcessor(client, this); + TTransport inputTransport = null; + TTransport outputTransport = null; + TProtocol inputProtocol = null; + TProtocol outputProtocol = null; + object connectionContext = null; + try + { + try + { + inputTransport = InputTransportFactory.GetTransport(client); + outputTransport = OutputTransportFactory.GetTransport(client); + inputProtocol = InputProtocolFactory.GetProtocol(inputTransport); + outputProtocol = OutputProtocolFactory.GetProtocol(outputTransport); + + //Recover event handler (if any) and fire createContext server event when a client connects + if (ServerEventHandler != null) + connectionContext = ServerEventHandler.CreateContextAsync(inputProtocol, outputProtocol, cancellationToken).Result; + + //Process client requests until client disconnects + while (!stop) + { + if (! inputTransport.PeekAsync(cancellationToken).Result) + break; + + //Fire processContext server event + //N.B. This is the pattern implemented in C++ and the event fires provisionally. + //That is to say it may be many minutes between the event firing and the client request + //actually arriving or the client may hang up without ever makeing a request. + if (ServerEventHandler != null) + ServerEventHandler.ProcessContextAsync(connectionContext, inputTransport, cancellationToken).Wait(); + //Process client request (blocks until transport is readable) + if (!processor.ProcessAsync(inputProtocol, outputProtocol, cancellationToken).Result) + break; + } + } + catch (TTransportException) + { + //Usually a client disconnect, expected + } + catch (Exception x) + { + //Unexpected + LogError("Error: " + x); + } + + //Fire deleteContext server event after client disconnects + if (ServerEventHandler != null) + ServerEventHandler.DeleteContextAsync(connectionContext, inputProtocol, outputProtocol, cancellationToken).Wait(); + + } + finally + { + //Close transports + inputTransport?.Close(); + outputTransport?.Close(); + + // disposable stuff should be disposed + inputProtocol?.Dispose(); + outputProtocol?.Dispose(); + inputTransport?.Dispose(); + outputTransport?.Dispose(); + } + } + } + + public override void Stop() + { + stop = true; + ServerTransport?.Close(); + } + } +} diff --git a/lib/netstd/Thrift/TApplicationException.cs b/lib/netstd/Thrift/TApplicationException.cs new file mode 100644 index 00000000000..50f65d647db --- /dev/null +++ b/lib/netstd/Thrift/TApplicationException.cs @@ -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. + +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol; +using Thrift.Protocol.Entities; +using Thrift.Protocol.Utilities; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + public class TApplicationException : TException + { + public enum ExceptionType + { + Unknown, + UnknownMethod, + InvalidMessageType, + WrongMethodName, + BadSequenceId, + MissingResult, + InternalError, + ProtocolError, + InvalidTransform, + InvalidProtocol, + UnsupportedClientType + } + + private const int MessageTypeFieldId = 1; + private const int ExTypeFieldId = 2; + + protected ExceptionType Type; + + public TApplicationException() + { + } + + public TApplicationException(ExceptionType type) + { + Type = type; + } + + public TApplicationException(ExceptionType type, string message) + : base(message, null) // TApplicationException is serializable, but we never serialize InnerException + { + Type = type; + } + + public static async Task ReadAsync(TProtocol inputProtocol, CancellationToken cancellationToken) + { + string message = null; + var type = ExceptionType.Unknown; + + await inputProtocol.ReadStructBeginAsync(cancellationToken); + while (true) + { + var field = await inputProtocol.ReadFieldBeginAsync(cancellationToken); + if (field.Type == TType.Stop) + { + break; + } + + switch (field.ID) + { + case MessageTypeFieldId: + if (field.Type == TType.String) + { + message = await inputProtocol.ReadStringAsync(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); + } + break; + case ExTypeFieldId: + if (field.Type == TType.I32) + { + type = (ExceptionType) await inputProtocol.ReadI32Async(cancellationToken); + } + else + { + await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); + } + break; + default: + await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); + break; + } + + await inputProtocol.ReadFieldEndAsync(cancellationToken); + } + + await inputProtocol.ReadStructEndAsync(cancellationToken); + + return new TApplicationException(type, message); + } + + public async Task WriteAsync(TProtocol outputProtocol, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + const string messageTypeFieldName = "message"; + const string exTypeFieldName = "exType"; + const string structApplicationExceptionName = "TApplicationException"; + + var struc = new TStruct(structApplicationExceptionName); + var field = new TField(); + + await outputProtocol.WriteStructBeginAsync(struc, cancellationToken); + + if (!string.IsNullOrEmpty(Message)) + { + field.Name = messageTypeFieldName; + field.Type = TType.String; + field.ID = MessageTypeFieldId; + await outputProtocol.WriteFieldBeginAsync(field, cancellationToken); + await outputProtocol.WriteStringAsync(Message, cancellationToken); + await outputProtocol.WriteFieldEndAsync(cancellationToken); + } + + field.Name = exTypeFieldName; + field.Type = TType.I32; + field.ID = ExTypeFieldId; + + await outputProtocol.WriteFieldBeginAsync(field, cancellationToken); + await outputProtocol.WriteI32Async((int) Type, cancellationToken); + await outputProtocol.WriteFieldEndAsync(cancellationToken); + await outputProtocol.WriteFieldStopAsync(cancellationToken); + await outputProtocol.WriteStructEndAsync(cancellationToken); + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/TBaseClient.cs b/lib/netstd/Thrift/TBaseClient.cs new file mode 100644 index 00000000000..0edac0f0812 --- /dev/null +++ b/lib/netstd/Thrift/TBaseClient.cs @@ -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. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Protocol; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + /// + /// TBaseClient. + /// Base client for generated clients. + /// Do not change this class without checking generated code (namings, etc.) + /// + public abstract class TBaseClient + { + private readonly TProtocol _inputProtocol; + private readonly TProtocol _outputProtocol; + private bool _isDisposed; + private int _seqId; + public readonly Guid ClientId = Guid.NewGuid(); + + protected TBaseClient(TProtocol inputProtocol, TProtocol outputProtocol) + { + _inputProtocol = inputProtocol ?? throw new ArgumentNullException(nameof(inputProtocol)); + _outputProtocol = outputProtocol ?? throw new ArgumentNullException(nameof(outputProtocol)); + } + + public TProtocol InputProtocol => _inputProtocol; + + public TProtocol OutputProtocol => _outputProtocol; + + public int SeqId + { + get { return ++_seqId; } + } + + public virtual async Task OpenTransportAsync() + { + await OpenTransportAsync(CancellationToken.None); + } + + public virtual async Task OpenTransportAsync(CancellationToken cancellationToken) + { + if (!_inputProtocol.Transport.IsOpen) + { + await _inputProtocol.Transport.OpenAsync(cancellationToken); + } + + if (!_inputProtocol.Transport.IsOpen) + { + await _outputProtocol.Transport.OpenAsync(cancellationToken); + } + } + + public void Dispose() + { + Dispose(true); + } + + protected virtual void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _inputProtocol?.Dispose(); + _outputProtocol?.Dispose(); + } + } + + _isDisposed = true; + } + } +} diff --git a/lib/netstd/Thrift/TException.cs b/lib/netstd/Thrift/TException.cs new file mode 100644 index 00000000000..43e70549bea --- /dev/null +++ b/lib/netstd/Thrift/TException.cs @@ -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. + +using System; + +namespace Thrift +{ + // ReSharper disable once InconsistentNaming + public class TException : Exception + { + public TException() + { + } + + public TException(string message, Exception inner) + : base(message, inner) + { + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj new file mode 100644 index 00000000000..e2f17250990 --- /dev/null +++ b/lib/netstd/Thrift/Thrift.csproj @@ -0,0 +1,50 @@ + + + + + netstandard2.0 + Thrift + Thrift + true + true + false + false + false + false + false + false + false + false + + + + + + + + + + + + + + + + diff --git a/lib/netstd/Thrift/Transport/Client/TBufferedTransport.cs b/lib/netstd/Thrift/Transport/Client/TBufferedTransport.cs new file mode 100644 index 00000000000..b8b5f53dc38 --- /dev/null +++ b/lib/netstd/Thrift/Transport/Client/TBufferedTransport.cs @@ -0,0 +1,205 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Client +{ + // ReSharper disable once InconsistentNaming + public class TBufferedTransport : TTransport + { + private readonly int _bufSize; + private readonly MemoryStream _inputBuffer = new MemoryStream(0); + private readonly MemoryStream _outputBuffer = new MemoryStream(0); + private readonly TTransport _transport; + private bool _isDisposed; + + //TODO: should support only specified input transport? + public TBufferedTransport(TTransport transport, int bufSize = 1024) + { + if (bufSize <= 0) + { + throw new ArgumentOutOfRangeException(nameof(bufSize), "Buffer size must be a positive number."); + } + + _transport = transport ?? throw new ArgumentNullException(nameof(transport)); + _bufSize = bufSize; + } + + public TTransport UnderlyingTransport + { + get + { + CheckNotDisposed(); + + return _transport; + } + } + + public override bool IsOpen => !_isDisposed && _transport.IsOpen; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + await _transport.OpenAsync(cancellationToken); + } + + public override void Close() + { + CheckNotDisposed(); + + _transport.Close(); + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + //TODO: investigate how it should work correctly + CheckNotDisposed(); + + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + if (_inputBuffer.Capacity < _bufSize) + { + _inputBuffer.Capacity = _bufSize; + } + + var got = await _inputBuffer.ReadAsync(buffer, offset, length, cancellationToken); + if (got > 0) + { + return got; + } + + _inputBuffer.Seek(0, SeekOrigin.Begin); + _inputBuffer.SetLength(_inputBuffer.Capacity); + + ArraySegment bufSegment; + _inputBuffer.TryGetBuffer(out bufSegment); + + // investigate + var filled = await _transport.ReadAsync(bufSegment.Array, 0, (int) _inputBuffer.Length, cancellationToken); + _inputBuffer.SetLength(filled); + + if (filled == 0) + { + return 0; + } + + return await ReadAsync(buffer, offset, length, cancellationToken); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + CheckNotDisposed(); + + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + // Relative offset from "off" argument + var writtenCount = 0; + if (_outputBuffer.Length > 0) + { + var capa = (int) (_outputBuffer.Capacity - _outputBuffer.Length); + var writeSize = capa <= length ? capa : length; + await _outputBuffer.WriteAsync(buffer, offset, writeSize, cancellationToken); + + writtenCount += writeSize; + if (writeSize == capa) + { + //ArraySegment bufSegment; + //_outputBuffer.TryGetBuffer(out bufSegment); + var data = _outputBuffer.ToArray(); + //await _transport.WriteAsync(bufSegment.Array, cancellationToken); + await _transport.WriteAsync(data, cancellationToken); + _outputBuffer.SetLength(0); + } + } + + while (length - writtenCount >= _bufSize) + { + await _transport.WriteAsync(buffer, offset + writtenCount, _bufSize, cancellationToken); + writtenCount += _bufSize; + } + + var remain = length - writtenCount; + if (remain > 0) + { + if (_outputBuffer.Capacity < _bufSize) + { + _outputBuffer.Capacity = _bufSize; + } + await _outputBuffer.WriteAsync(buffer, offset + writtenCount, remain, cancellationToken); + } + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + if (_outputBuffer.Length > 0) + { + var data = _outputBuffer.ToArray(); + + await _transport.WriteAsync(data /*bufSegment.Array*/, cancellationToken); + _outputBuffer.SetLength(0); + } + + await _transport.FlushAsync(cancellationToken); + } + + private void CheckNotDisposed() + { + if (_isDisposed) + { + throw new ObjectDisposedException(nameof(_transport)); + } + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _inputBuffer?.Dispose(); + _outputBuffer?.Dispose(); + _transport?.Dispose(); + } + } + _isDisposed = true; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Client/TFramedTransport.cs b/lib/netstd/Thrift/Transport/Client/TFramedTransport.cs new file mode 100644 index 00000000000..7b764dfbe28 --- /dev/null +++ b/lib/netstd/Thrift/Transport/Client/TFramedTransport.cs @@ -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. + +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Client +{ + //TODO: check for correct implementation + + // ReSharper disable once InconsistentNaming + public class TFramedTransport : TTransport + { + private const int HeaderSize = 4; + private readonly byte[] _headerBuf = new byte[HeaderSize]; + private readonly MemoryStream _readBuffer = new MemoryStream(1024); + private readonly TTransport _transport; + private readonly MemoryStream _writeBuffer = new MemoryStream(1024); + + private bool _isDisposed; + + public TFramedTransport(TTransport transport) + { + _transport = transport ?? throw new ArgumentNullException(nameof(transport)); + + InitWriteBuffer(); + } + + public override bool IsOpen => !_isDisposed && _transport.IsOpen; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + await _transport.OpenAsync(cancellationToken); + } + + public override void Close() + { + CheckNotDisposed(); + + _transport.Close(); + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + CheckNotDisposed(); + + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + var got = await _readBuffer.ReadAsync(buffer, offset, length, cancellationToken); + if (got > 0) + { + return got; + } + + // Read another frame of data + await ReadFrameAsync(cancellationToken); + + return await _readBuffer.ReadAsync(buffer, offset, length, cancellationToken); + } + + private async Task ReadFrameAsync(CancellationToken cancellationToken) + { + await _transport.ReadAllAsync(_headerBuf, 0, HeaderSize, cancellationToken); + + var size = DecodeFrameSize(_headerBuf); + + _readBuffer.SetLength(size); + _readBuffer.Seek(0, SeekOrigin.Begin); + + ArraySegment bufSegment; + _readBuffer.TryGetBuffer(out bufSegment); + + var buff = bufSegment.Array; + + await _transport.ReadAllAsync(buff, 0, size, cancellationToken); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + CheckNotDisposed(); + + ValidateBufferArgs(buffer, offset, length); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + if (_writeBuffer.Length + length > int.MaxValue) + { + await FlushAsync(cancellationToken); + } + + await _writeBuffer.WriteAsync(buffer, offset, length, cancellationToken); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + CheckNotDisposed(); + + if (!IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + //ArraySegment bufSegment; + //_writeBuffer.TryGetBuffer(out bufSegment); + //var buf = bufSegment.Array; + var buf = _writeBuffer.ToArray(); + + //var len = (int)_writeBuffer.Length; + var dataLen = (int) _writeBuffer.Length - HeaderSize; + if (dataLen < 0) + { + throw new InvalidOperationException(); // logic error actually + } + + // Inject message header into the reserved buffer space + EncodeFrameSize(dataLen, buf); + + // Send the entire message at once + await _transport.WriteAsync(buf, cancellationToken); + + InitWriteBuffer(); + + await _transport.FlushAsync(cancellationToken); + } + + private void InitWriteBuffer() + { + // Reserve space for message header to be put right before sending it out + _writeBuffer.SetLength(HeaderSize); + _writeBuffer.Seek(0, SeekOrigin.End); + } + + private static void EncodeFrameSize(int frameSize, 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)); + } + + private static int DecodeFrameSize(byte[] buf) + { + return + ((buf[0] & 0xff) << 24) | + ((buf[1] & 0xff) << 16) | + ((buf[2] & 0xff) << 8) | + (buf[3] & 0xff); + } + + + private void CheckNotDisposed() + { + if (_isDisposed) + { + throw new ObjectDisposedException("TFramedTransport"); + } + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _readBuffer?.Dispose(); + _writeBuffer?.Dispose(); + _transport?.Dispose(); + } + } + _isDisposed = true; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs new file mode 100644 index 00000000000..0dd5493efa9 --- /dev/null +++ b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs @@ -0,0 +1,226 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Client +{ + // ReSharper disable once InconsistentNaming + public class THttpTransport : TTransport + { + private readonly X509Certificate[] _certificates; + private readonly Uri _uri; + + // Timeouts in milliseconds + private int _connectTimeout = 30000; + private HttpClient _httpClient; + private Stream _inputStream; + + private bool _isDisposed; + private MemoryStream _outputStream = new MemoryStream(); + + public THttpTransport(Uri u, IDictionary customHeaders = null) + : this(u, Enumerable.Empty(), customHeaders) + { + } + + public THttpTransport(Uri u, IEnumerable certificates, + IDictionary customHeaders) + { + _uri = u; + _certificates = (certificates ?? Enumerable.Empty()).ToArray(); + CustomHeaders = customHeaders; + + // due to current bug with performance of Dispose in netcore https://github.com/dotnet/corefx/issues/8809 + // this can be switched to default way (create client->use->dispose per flush) later + _httpClient = CreateClient(); + } + + public IDictionary CustomHeaders { get; } + + public int ConnectTimeout + { + set { _connectTimeout = value; } + } + + public override bool IsOpen => true; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override void Close() + { + if (_inputStream != null) + { + _inputStream.Dispose(); + _inputStream = null; + } + + if (_outputStream != null) + { + _outputStream.Dispose(); + _outputStream = null; + } + + if (_httpClient != null) + { + _httpClient.Dispose(); + _httpClient = null; + } + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + if (_inputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No request has been sent"); + } + + try + { + var ret = await _inputStream.ReadAsync(buffer, offset, length, cancellationToken); + + if (ret == -1) + { + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "No more data available"); + } + + return ret; + } + catch (IOException iox) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString()); + } + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + await _outputStream.WriteAsync(buffer, offset, length, cancellationToken); + } + + private HttpClient CreateClient() + { + var handler = new HttpClientHandler(); + handler.ClientCertificates.AddRange(_certificates); + + var httpClient = new HttpClient(handler); + + if (_connectTimeout > 0) + { + httpClient.Timeout = TimeSpan.FromSeconds(_connectTimeout); + } + + httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); + httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpTransport", "1.0.0")); + + if (CustomHeaders != null) + { + foreach (var item in CustomHeaders) + { + httpClient.DefaultRequestHeaders.Add(item.Key, item.Value); + } + } + + return httpClient; + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + try + { + try + { + if (_outputStream.CanSeek) + { + _outputStream.Seek(0, SeekOrigin.Begin); + } + + using (var outStream = new StreamContent(_outputStream)) + { + var msg = await _httpClient.PostAsync(_uri, outStream, cancellationToken); + + msg.EnsureSuccessStatusCode(); + + if (_inputStream != null) + { + _inputStream.Dispose(); + _inputStream = null; + } + + _inputStream = await msg.Content.ReadAsStreamAsync(); + if (_inputStream.CanSeek) + { + _inputStream.Seek(0, SeekOrigin.Begin); + } + } + } + catch (IOException iox) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString()); + } + catch (HttpRequestException wx) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, + "Couldn't connect to server: " + wx); + } + } + finally + { + _outputStream = new MemoryStream(); + } + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _inputStream?.Dispose(); + _outputStream?.Dispose(); + _httpClient?.Dispose(); + } + } + _isDisposed = true; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs new file mode 100644 index 00000000000..75529d167e3 --- /dev/null +++ b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs @@ -0,0 +1,97 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Client +{ + // ReSharper disable once InconsistentNaming + public class TMemoryBufferTransport : TTransport + { + private readonly MemoryStream _byteStream; + private bool _isDisposed; + + public TMemoryBufferTransport() + { + _byteStream = new MemoryStream(); + } + + public TMemoryBufferTransport(byte[] buf) + { + _byteStream = new MemoryStream(buf); + } + + public override bool IsOpen => true; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override void Close() + { + /** do nothing **/ + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + return await _byteStream.ReadAsync(buffer, offset, length, cancellationToken); + } + + public override async Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) + { + await _byteStream.WriteAsync(buffer, 0, buffer.Length, cancellationToken); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + await _byteStream.WriteAsync(buffer, offset, length, cancellationToken); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public byte[] GetBuffer() + { + return _byteStream.ToArray(); + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + _byteStream?.Dispose(); + } + } + _isDisposed = true; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs new file mode 100644 index 00000000000..b78c791400b --- /dev/null +++ b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs @@ -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. + +using System.IO.Pipes; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Client +{ + // ReSharper disable once InconsistentNaming + public class TNamedPipeTransport : TTransport + { + private NamedPipeClientStream _client; + private int ConnectTimeout; + + public TNamedPipeTransport(string pipe, int timeout = Timeout.Infinite) + : this(".", pipe, timeout) + { + } + + public TNamedPipeTransport(string server, string pipe, int timeout = Timeout.Infinite) + { + var serverName = string.IsNullOrWhiteSpace(server) ? server : "."; + ConnectTimeout = (timeout > 0) ? timeout : Timeout.Infinite; + + _client = new NamedPipeClientStream(serverName, pipe, PipeDirection.InOut, PipeOptions.None); + } + + public override bool IsOpen => _client != null && _client.IsConnected; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen); + } + + await _client.ConnectAsync( ConnectTimeout, cancellationToken); + } + + public override void Close() + { + if (_client != null) + { + _client.Dispose(); + _client = null; + } + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + if (_client == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + return await _client.ReadAsync(buffer, offset, length, cancellationToken); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + if (_client == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + await _client.WriteAsync(buffer, offset, length, cancellationToken); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + protected override void Dispose(bool disposing) + { + _client.Dispose(); + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs b/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs new file mode 100644 index 00000000000..00da045813a --- /dev/null +++ b/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs @@ -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. + +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Client +{ + // ReSharper disable once InconsistentNaming + public class TSocketTransport : TStreamTransport + { + private bool _isDisposed; + + + public TSocketTransport(TcpClient client) + { + TcpClient = client ?? throw new ArgumentNullException(nameof(client)); + SetInputOutputStream(); + } + + public TSocketTransport(IPAddress host, int port) + : this(host, port, 0) + { + } + + public TSocketTransport(IPAddress host, int port, int timeout) + { + Host = host; + Port = port; + + TcpClient = new TcpClient(); + TcpClient.ReceiveTimeout = TcpClient.SendTimeout = timeout; + TcpClient.Client.NoDelay = true; + SetInputOutputStream(); + } + + public TSocketTransport(string host, int port, int timeout = 0) + { + try + { + var entry = Dns.GetHostEntry(host); + if (entry.AddressList.Length == 0) + throw new TTransportException(TTransportException.ExceptionType.Unknown, "unable to resolve host name"); + + var addr = entry.AddressList[0]; + Host = new IPAddress(addr.GetAddressBytes(), addr.ScopeId); + Port = port; + + TcpClient = new TcpClient(host, port); + TcpClient.ReceiveTimeout = TcpClient.SendTimeout = timeout; + TcpClient.Client.NoDelay = true; + SetInputOutputStream(); + } + catch (SocketException e) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, e.Message, e); + } + } + + private void SetInputOutputStream() + { + if (IsOpen) + { + InputStream = TcpClient.GetStream(); + OutputStream = TcpClient.GetStream(); + } + } + + public TcpClient TcpClient { get; private set; } + public IPAddress Host { get; } + public int Port { get; } + + public int Timeout + { + set + { + if (TcpClient != null) + { + TcpClient.ReceiveTimeout = TcpClient.SendTimeout = value; + } + } + } + + public override bool IsOpen + { + get + { + return (TcpClient != null) && TcpClient.Connected; + } + } + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); + } + + if (Port <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); + } + + if (TcpClient == null) + { + throw new InvalidOperationException("Invalid or not initialized tcp client"); + } + + await TcpClient.ConnectAsync(Host, Port); + SetInputOutputStream(); + } + + public override void Close() + { + base.Close(); + + if (TcpClient != null) + { + TcpClient.Dispose(); + TcpClient = null; + } + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + TcpClient?.Dispose(); + + base.Dispose(disposing); + } + } + _isDisposed = true; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs b/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs new file mode 100644 index 00000000000..9b035339d77 --- /dev/null +++ b/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs @@ -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. + +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Client +{ + // ReSharper disable once InconsistentNaming + public class TStreamTransport : TTransport + { + private bool _isDisposed; + + protected TStreamTransport() + { + } + + public TStreamTransport(Stream inputStream, Stream outputStream) + { + InputStream = inputStream; + OutputStream = outputStream; + } + + protected Stream OutputStream { get; set; } + + protected Stream InputStream { get; set; } + + public override bool IsOpen => true; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override void Close() + { + if (InputStream != null) + { + InputStream.Dispose(); + InputStream = null; + } + + if (OutputStream != null) + { + OutputStream.Dispose(); + OutputStream = null; + } + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + if (InputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, + "Cannot read from null inputstream"); + } + + return await InputStream.ReadAsync(buffer, offset, length, cancellationToken); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + { + if (OutputStream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, + "Cannot write to null outputstream"); + } + + await OutputStream.WriteAsync(buffer, offset, length, cancellationToken); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + await OutputStream.FlushAsync(cancellationToken); + } + + // IDisposable + protected override void Dispose(bool disposing) + { + if (!_isDisposed) + { + if (disposing) + { + InputStream?.Dispose(); + OutputStream?.Dispose(); + } + } + _isDisposed = true; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs new file mode 100644 index 00000000000..3bd9606d5cb --- /dev/null +++ b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs @@ -0,0 +1,237 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Net; +using System.Net.Security; +using System.Net.Sockets; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Client +{ + //TODO: check for correct work + + // ReSharper disable once InconsistentNaming + public class TTlsSocketTransport : TStreamTransport + { + private readonly X509Certificate2 _certificate; + private readonly RemoteCertificateValidationCallback _certValidator; + private readonly IPAddress _host; + private readonly bool _isServer; + private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; + private readonly int _port; + private readonly SslProtocols _sslProtocols; + private TcpClient _client; + private SslStream _secureStream; + private int _timeout; + + public TTlsSocketTransport(TcpClient client, X509Certificate2 certificate, bool isServer = false, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + { + _client = client; + _certificate = certificate; + _certValidator = certValidator; + _localCertificateSelectionCallback = localCertificateSelectionCallback; + _sslProtocols = sslProtocols; + _isServer = isServer; + + if (isServer && certificate == null) + { + throw new ArgumentException("TTlsSocketTransport needs certificate to be used for server", + nameof(certificate)); + } + + if (IsOpen) + { + InputStream = client.GetStream(); + OutputStream = client.GetStream(); + } + } + + public TTlsSocketTransport(IPAddress host, int port, string certificatePath, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + : this(host, port, 0, + new X509Certificate2(certificatePath), + certValidator, + localCertificateSelectionCallback, + sslProtocols) + { + } + + public TTlsSocketTransport(IPAddress host, int port, + X509Certificate2 certificate = null, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + : this(host, port, 0, + certificate, + certValidator, + localCertificateSelectionCallback, + sslProtocols) + { + } + + public TTlsSocketTransport(IPAddress host, int port, int timeout, + X509Certificate2 certificate, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + { + _host = host; + _port = port; + _timeout = timeout; + _certificate = certificate; + _certValidator = certValidator; + _localCertificateSelectionCallback = localCertificateSelectionCallback; + _sslProtocols = sslProtocols; + + InitSocket(); + } + + public int Timeout + { + set { _client.ReceiveTimeout = _client.SendTimeout = _timeout = value; } + } + + public TcpClient TcpClient => _client; + + public IPAddress Host => _host; + + public int Port => _port; + + public override bool IsOpen + { + get + { + if (_client == null) + { + return false; + } + + return _client.Connected; + } + } + + private void InitSocket() + { + _client = new TcpClient(); + _client.ReceiveTimeout = _client.SendTimeout = _timeout; + _client.Client.NoDelay = true; + } + + private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, + SslPolicyErrors sslValidationErrors) + { + return sslValidationErrors == SslPolicyErrors.None; + } + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (IsOpen) + { + throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); + } + + if (_host == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); + } + + if (_port <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); + } + + if (_client == null) + { + InitSocket(); + } + + if (_client != null) + { + await _client.ConnectAsync(_host, _port); + await SetupTlsAsync(); + } + } + + public async Task SetupTlsAsync() + { + var validator = _certValidator ?? DefaultCertificateValidator; + + if (_localCertificateSelectionCallback != null) + { + _secureStream = new SslStream(_client.GetStream(), false, validator, _localCertificateSelectionCallback); + } + else + { + _secureStream = new SslStream(_client.GetStream(), false, validator); + } + + try + { + if (_isServer) + { + // Server authentication + await + _secureStream.AuthenticateAsServerAsync(_certificate, _certValidator != null, _sslProtocols, + true); + } + else + { + // Client authentication + var certs = _certificate != null + ? new X509CertificateCollection {_certificate} + : new X509CertificateCollection(); + + var targetHost = _host.ToString(); + await _secureStream.AuthenticateAsClientAsync(targetHost, certs, _sslProtocols, true); + } + } + catch (Exception) + { + Close(); + throw; + } + + InputStream = _secureStream; + OutputStream = _secureStream; + } + + public override void Close() + { + base.Close(); + if (_client != null) + { + _client.Dispose(); + _client = null; + } + + if (_secureStream != null) + { + _secureStream.Dispose(); + _secureStream = null; + } + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Server/NullLogger.cs b/lib/netstd/Thrift/Transport/Server/NullLogger.cs new file mode 100644 index 00000000000..1f1f542d59f --- /dev/null +++ b/lib/netstd/Thrift/Transport/Server/NullLogger.cs @@ -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. + +using Microsoft.Extensions.Logging; +using System; + + +namespace Thrift.Transport.Server +{ + // sometimes we just don't want to log anything + internal class NullLogger : IDisposable, ILogger, ILogger + { + internal class NullScope : IDisposable + { + public void Dispose() + { + // nothing to do + } + } + + public IDisposable BeginScope(TState state) + { + return new NullScope(); + } + + public void Dispose() + { + // nothing to do + } + + public bool IsEnabled(LogLevel logLevel) + { + return false; // no + } + + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + // do nothing + } + } +} + diff --git a/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs new file mode 100644 index 00000000000..fab9fa7a5ec --- /dev/null +++ b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs @@ -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. + +using System; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Thrift.Processor; +using Thrift.Protocol; +using Thrift.Transport.Client; + +namespace Thrift.Transport.Server +{ + // ReSharper disable once InconsistentNaming + public class THttpServerTransport + { + protected const string ContentType = "application/x-thrift"; + private readonly ILogger _logger; + private readonly RequestDelegate _next; + protected Encoding Encoding = Encoding.UTF8; + + protected ITProtocolFactory InputProtocolFactory; + protected ITProtocolFactory OutputProtocolFactory; + + protected ITAsyncProcessor Processor; + + public THttpServerTransport(ITAsyncProcessor processor, RequestDelegate next = null, ILoggerFactory loggerFactory = null) + : this(processor, new TBinaryProtocol.Factory(), next, loggerFactory) + { + } + + public THttpServerTransport(ITAsyncProcessor processor, ITProtocolFactory protocolFactory, RequestDelegate next = null, + ILoggerFactory loggerFactory = null) + : this(processor, protocolFactory, protocolFactory, next, loggerFactory) + { + } + + public THttpServerTransport(ITAsyncProcessor processor, ITProtocolFactory inputProtocolFactory, + ITProtocolFactory outputProtocolFactory, RequestDelegate next = null, ILoggerFactory loggerFactory = null) + { + // loggerFactory == null is not illegal anymore + + Processor = processor ?? throw new ArgumentNullException(nameof(processor)); + InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory)); + OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory)); + + _next = next; + _logger = (loggerFactory != null) ? loggerFactory.CreateLogger() : new NullLogger(); + } + + public async Task Invoke(HttpContext context) + { + context.Response.ContentType = ContentType; + await ProcessRequestAsync(context, context.RequestAborted); //TODO: check for correct logic + } + + public async Task ProcessRequestAsync(HttpContext context, CancellationToken cancellationToken) + { + var transport = new TStreamTransport(context.Request.Body, context.Response.Body); + + try + { + var input = InputProtocolFactory.GetProtocol(transport); + var output = OutputProtocolFactory.GetProtocol(transport); + + while (await Processor.ProcessAsync(input, output, cancellationToken)) + { + } + } + catch (TTransportException) + { + // Client died, just move on + } + finally + { + transport.Close(); + } + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs new file mode 100644 index 00000000000..be6d0fc59bb --- /dev/null +++ b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs @@ -0,0 +1,191 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.IO.Pipes; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport.Server +{ + // ReSharper disable once InconsistentNaming + public class TNamedPipeServerTransport : TServerTransport + { + /// + /// This is the address of the Pipe on the localhost. + /// + private readonly string _pipeAddress; + + private bool _asyncMode = true; + private volatile bool _isPending = true; + + private NamedPipeServerStream _stream = null; + + public TNamedPipeServerTransport(string pipeAddress) + { + _pipeAddress = pipeAddress; + } + + public override void Listen() + { + // nothing to do here + } + + public override void Close() + { + if (_stream != null) + { + try + { + //TODO: check for disconection + _stream.Disconnect(); + _stream.Dispose(); + } + finally + { + _stream = null; + _isPending = false; + } + } + } + + public override bool IsClientPending() + { + return _isPending; + } + + private void EnsurePipeInstance() + { + if (_stream == null) + { + var direction = PipeDirection.InOut; + var maxconn = 254; + var mode = PipeTransmissionMode.Byte; + var options = _asyncMode ? PipeOptions.Asynchronous : PipeOptions.None; + var inbuf = 4096; + var outbuf = 4096; + // TODO: security + + try + { + _stream = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, outbuf); + } + catch (NotImplementedException) // Mono still does not support async, fallback to sync + { + if (_asyncMode) + { + options &= (~PipeOptions.Asynchronous); + _stream = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, + outbuf); + _asyncMode = false; + } + else + { + throw; + } + } + } + } + + protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) + { + try + { + EnsurePipeInstance(); + + await _stream.WaitForConnectionAsync(cancellationToken); + + var trans = new ServerTransport(_stream); + _stream = null; // pass ownership to ServerTransport + + //_isPending = false; + + return trans; + } + catch (TTransportException) + { + Close(); + throw; + } + catch (Exception e) + { + Close(); + throw new TTransportException(TTransportException.ExceptionType.NotOpen, e.Message); + } + } + + private class ServerTransport : TTransport + { + private readonly NamedPipeServerStream _stream; + + public ServerTransport(NamedPipeServerStream stream) + { + _stream = stream; + } + + public override bool IsOpen => _stream != null && _stream.IsConnected; + + public override async Task OpenAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + public override void Close() + { + _stream?.Dispose(); + } + + public override async Task ReadAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + if (_stream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + return await _stream.ReadAsync(buffer, offset, length, cancellationToken); + } + + public override async Task WriteAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + if (_stream == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen); + } + + await _stream.WriteAsync(buffer, offset, length, cancellationToken); + } + + public override async Task FlushAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + await Task.FromCanceled(cancellationToken); + } + } + + protected override void Dispose(bool disposing) + { + _stream?.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Server/TServerFramedTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerFramedTransport.cs new file mode 100644 index 00000000000..b3b38025a8c --- /dev/null +++ b/lib/netstd/Thrift/Transport/Server/TServerFramedTransport.cs @@ -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. + +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Transport.Client; + +namespace Thrift.Transport.Server +{ + // ReSharper disable once InconsistentNaming + public class TServerFramedTransport : TServerTransport + { + private readonly int _clientTimeout; + private readonly int _port; + private TcpListener _server; + + public TServerFramedTransport(TcpListener listener) + : this(listener, 0) + { + } + + public TServerFramedTransport(TcpListener listener, int clientTimeout) + { + _server = listener; + _clientTimeout = clientTimeout; + } + + public TServerFramedTransport(int port) + : this(port, 0) + { + } + + public TServerFramedTransport(int port, int clientTimeout) + { + _port = port; + _clientTimeout = clientTimeout; + try + { + // Make server socket + _server = new TcpListener(IPAddress.Any, _port); + _server.Server.NoDelay = true; + } + catch (Exception) + { + _server = null; + throw new TTransportException("Could not create ServerSocket on port " + port + "."); + } + } + + public override void Listen() + { + // Make sure not to block on accept + if (_server != null) + { + try + { + _server.Start(); + } + catch (SocketException sx) + { + throw new TTransportException("Could not accept on listening socket: " + sx.Message); + } + } + } + + public override bool IsClientPending() + { + return _server.Pending(); + } + + protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + if (_server == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); + } + + try + { + TFramedTransport tSocketTransport = null; + var tcpClient = await _server.AcceptTcpClientAsync(); + + try + { + tSocketTransport = new TFramedTransport(new TSocketTransport(tcpClient) + { + Timeout = _clientTimeout + }); + + return tSocketTransport; + } + catch (Exception) + { + if (tSocketTransport != null) + { + tSocketTransport.Dispose(); + } + else // Otherwise, clean it up ourselves. + { + ((IDisposable) tcpClient).Dispose(); + } + + throw; + } + } + catch (Exception ex) + { + throw new TTransportException(ex.ToString()); + } + } + + public override void Close() + { + if (_server != null) + { + try + { + _server.Stop(); + } + catch (Exception ex) + { + throw new TTransportException("WARNING: Could not close server socket: " + ex); + } + _server = null; + } + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs new file mode 100644 index 00000000000..710dedf00d1 --- /dev/null +++ b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs @@ -0,0 +1,174 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Transport.Client; + +namespace Thrift.Transport.Server +{ + // ReSharper disable once InconsistentNaming + public class TServerSocketTransport : TServerTransport + { + private readonly int _clientTimeout; + private readonly int _port; + private readonly bool _useBufferedSockets; + private readonly bool _useFramedTransport; + private TcpListener _server; + + public TServerSocketTransport(TcpListener listener) + : this(listener, 0) + { + } + + public TServerSocketTransport(TcpListener listener, int clientTimeout) + { + _server = listener; + _clientTimeout = clientTimeout; + } + + public TServerSocketTransport(int port) + : this(port, 0) + { + } + + public TServerSocketTransport(int port, int clientTimeout) + : this(port, clientTimeout, false) + { + } + + public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets): + this(port, clientTimeout, useBufferedSockets, false) + { + } + + public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets, bool useFramedTransport) + { + _port = port; + _clientTimeout = clientTimeout; + _useBufferedSockets = useBufferedSockets; + _useFramedTransport = useFramedTransport; + try + { + // Make server socket + _server = new TcpListener(IPAddress.Any, _port); + _server.Server.NoDelay = true; + } + catch (Exception) + { + _server = null; + throw new TTransportException("Could not create ServerSocket on port " + port + "."); + } + } + + public override void Listen() + { + // Make sure not to block on accept + if (_server != null) + { + try + { + _server.Start(); + } + catch (SocketException sx) + { + throw new TTransportException("Could not accept on listening socket: " + sx.Message); + } + } + } + + public override bool IsClientPending() + { + return _server.Pending(); + } + + protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + if (_server == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); + } + + try + { + TTransport tSocketTransport = null; + var tcpClient = await _server.AcceptTcpClientAsync(); + + try + { + tSocketTransport = new TSocketTransport(tcpClient) + { + Timeout = _clientTimeout + }; + + if (_useBufferedSockets) + { + tSocketTransport = new TBufferedTransport(tSocketTransport); + } + + if (_useFramedTransport) + { + tSocketTransport = new TFramedTransport(tSocketTransport); + } + + return tSocketTransport; + } + catch (Exception) + { + if (tSocketTransport != null) + { + tSocketTransport.Dispose(); + } + else // Otherwise, clean it up ourselves. + { + ((IDisposable) tcpClient).Dispose(); + } + + throw; + } + } + catch (Exception ex) + { + throw new TTransportException(ex.ToString()); + } + } + + public override void Close() + { + if (_server != null) + { + try + { + _server.Stop(); + } + catch (Exception ex) + { + throw new TTransportException("WARNING: Could not close server socket: " + ex); + } + _server = null; + } + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs new file mode 100644 index 00000000000..14d7ff25f36 --- /dev/null +++ b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs @@ -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. + +using System; +using System.Net; +using System.Net.Security; +using System.Net.Sockets; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Transport.Client; + +namespace Thrift.Transport.Server +{ + // ReSharper disable once InconsistentNaming + public class TTlsServerSocketTransport : TServerTransport + { + private readonly RemoteCertificateValidationCallback _clientCertValidator; + private readonly int _clientTimeout = 0; + private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; + private readonly int _port; + private readonly X509Certificate2 _serverCertificate; + private readonly SslProtocols _sslProtocols; + private readonly bool _useBufferedSockets; + private readonly bool _useFramedTransport; + private TcpListener _server; + + public TTlsServerSocketTransport(int port, X509Certificate2 certificate) + : this(port, false, certificate) + { + } + + public TTlsServerSocketTransport( + int port, + bool useBufferedSockets, + X509Certificate2 certificate, + RemoteCertificateValidationCallback clientCertValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + : this(port, useBufferedSockets, false, certificate, + clientCertValidator, localCertificateSelectionCallback, sslProtocols) + { + } + + public TTlsServerSocketTransport( + int port, + bool useBufferedSockets, + bool useFramedTransport, + X509Certificate2 certificate, + RemoteCertificateValidationCallback clientCertValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + { + if (!certificate.HasPrivateKey) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, + "Your server-certificate needs to have a private key"); + } + + _port = port; + _serverCertificate = certificate; + _useBufferedSockets = useBufferedSockets; + _useFramedTransport = useFramedTransport; + _clientCertValidator = clientCertValidator; + _localCertificateSelectionCallback = localCertificateSelectionCallback; + _sslProtocols = sslProtocols; + + try + { + // Create server socket + _server = new TcpListener(IPAddress.Any, _port); + _server.Server.NoDelay = true; + } + catch (Exception) + { + _server = null; + throw new TTransportException($"Could not create ServerSocket on port {port}."); + } + } + + public override void Listen() + { + // Make sure accept is not blocking + if (_server != null) + { + try + { + _server.Start(); + } + catch (SocketException sx) + { + throw new TTransportException($"Could not accept on listening socket: {sx.Message}"); + } + } + } + + public override bool IsClientPending() + { + return _server.Pending(); + } + + protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + if (_server == null) + { + throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); + } + + try + { + var client = await _server.AcceptTcpClientAsync(); + client.SendTimeout = client.ReceiveTimeout = _clientTimeout; + + //wrap the client in an SSL Socket passing in the SSL cert + var tTlsSocket = new TTlsSocketTransport(client, _serverCertificate, true, _clientCertValidator, + _localCertificateSelectionCallback, _sslProtocols); + + await tTlsSocket.SetupTlsAsync(); + + TTransport trans = tTlsSocket; + + if (_useBufferedSockets) + { + trans = new TBufferedTransport(trans); + } + + if (_useFramedTransport) + { + trans = new TFramedTransport(trans); + } + + return trans; + } + catch (Exception ex) + { + throw new TTransportException(ex.ToString()); + } + } + + public override void Close() + { + if (_server != null) + { + try + { + _server.Stop(); + } + catch (Exception ex) + { + throw new TTransportException($"WARNING: Could not close server socket: {ex}"); + } + + _server = null; + } + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/TClientTransport.cs b/lib/netstd/Thrift/Transport/TClientTransport.cs new file mode 100644 index 00000000000..d5c8186f7b2 --- /dev/null +++ b/lib/netstd/Thrift/Transport/TClientTransport.cs @@ -0,0 +1,179 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport +{ + //TODO: think about client info + // ReSharper disable once InconsistentNaming + public abstract class TTransport : IDisposable + { + //TODO: think how to avoid peek byte + private readonly byte[] _peekBuffer = new byte[1]; + private bool _hasPeekByte; + public abstract bool IsOpen { get; } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public async Task PeekAsync(CancellationToken cancellationToken) + { + //If we already have a byte read but not consumed, do nothing. + if (_hasPeekByte) + { + return true; + } + + //If transport closed we can't peek. + if (!IsOpen) + { + return false; + } + + //Try to read one byte. If succeeds we will need to store it for the next read. + try + { + var bytes = await ReadAsync(_peekBuffer, 0, 1, cancellationToken); + if (bytes == 0) + { + return false; + } + } + catch (IOException) + { + return false; + } + + _hasPeekByte = true; + return true; + } + + public virtual async Task OpenAsync() + { + await OpenAsync(CancellationToken.None); + } + + public abstract Task OpenAsync(CancellationToken cancellationToken); + + public abstract void Close(); + + protected static void ValidateBufferArgs(byte[] buffer, int offset, int length) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + + if (offset < 0) + { + throw new ArgumentOutOfRangeException(nameof(offset), "Buffer offset is smaller than zero."); + } + + if (length < 0) + { + throw new ArgumentOutOfRangeException(nameof(length), "Buffer length is smaller than zero."); + } + + if (offset + length > buffer.Length) + { + throw new ArgumentOutOfRangeException(nameof(buffer), "Not enough data."); + } + } + + public virtual async Task ReadAsync(byte[] buffer, int offset, int length) + { + return await ReadAsync(buffer, offset, length, CancellationToken.None); + } + + public abstract Task ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); + + public virtual async Task ReadAllAsync(byte[] buffer, int offset, int length) + { + return await ReadAllAsync(buffer, offset, length, CancellationToken.None); + } + + public virtual async Task ReadAllAsync(byte[] buffer, int offset, int length, + CancellationToken cancellationToken) + { + ValidateBufferArgs(buffer, offset, length); + + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var retrieved = 0; + + //If we previously peeked a byte, we need to use that first. + if (_hasPeekByte) + { + buffer[offset + retrieved++] = _peekBuffer[0]; + _hasPeekByte = false; + } + + while (retrieved < length) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var returnedCount = await ReadAsync(buffer, offset + retrieved, length - retrieved, cancellationToken); + if (returnedCount <= 0) + { + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, + "Cannot read, Remote side has closed"); + } + retrieved += returnedCount; + } + return retrieved; + } + + public virtual async Task WriteAsync(byte[] buffer) + { + await WriteAsync(buffer, CancellationToken.None); + } + + public virtual async Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) + { + await WriteAsync(buffer, 0, buffer.Length, CancellationToken.None); + } + + public virtual async Task WriteAsync(byte[] buffer, int offset, int length) + { + await WriteAsync(buffer, offset, length, CancellationToken.None); + } + + public abstract Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); + + public virtual async Task FlushAsync() + { + await FlushAsync(CancellationToken.None); + } + + public abstract Task FlushAsync(CancellationToken cancellationToken); + + protected abstract void Dispose(bool disposing); + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/TServerTransport.cs b/lib/netstd/Thrift/Transport/TServerTransport.cs new file mode 100644 index 00000000000..e25c0c5e9b4 --- /dev/null +++ b/lib/netstd/Thrift/Transport/TServerTransport.cs @@ -0,0 +1,54 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Threading; +using System.Threading.Tasks; + +namespace Thrift.Transport +{ + // ReSharper disable once InconsistentNaming + public abstract class TServerTransport + { + public abstract void Listen(); + public abstract void Close(); + public abstract bool IsClientPending(); + + protected virtual async Task AcceptImplementationAsync() + { + return await AcceptImplementationAsync(CancellationToken.None); + } + + protected abstract Task AcceptImplementationAsync(CancellationToken cancellationToken); + + public async Task AcceptAsync() + { + return await AcceptAsync(CancellationToken.None); + } + + public async Task AcceptAsync(CancellationToken cancellationToken) + { + var transport = await AcceptImplementationAsync(cancellationToken); + + if (transport == null) + { + throw new TTransportException($"{nameof(AcceptImplementationAsync)} should not return null"); + } + + return transport; + } + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/TTransportException.cs b/lib/netstd/Thrift/Transport/TTransportException.cs new file mode 100644 index 00000000000..7469b8ba278 --- /dev/null +++ b/lib/netstd/Thrift/Transport/TTransportException.cs @@ -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. + +using System; + +namespace Thrift.Transport +{ + // ReSharper disable once InconsistentNaming + public class TTransportException : TException + { + public enum ExceptionType + { + Unknown, + NotOpen, + AlreadyOpen, + TimedOut, + EndOfFile, + Interrupted + } + + protected ExceptionType ExType; + + public TTransportException() + { + } + + public TTransportException(ExceptionType exType, Exception inner = null) + : base(string.Empty, inner) + { + ExType = exType; + } + + public TTransportException(ExceptionType exType, string message, Exception inner = null) + : base(message, inner) + { + ExType = exType; + } + + public TTransportException(string message, Exception inner = null) + : base(message, inner) + { + } + + public ExceptionType Type => ExType; + } +} \ No newline at end of file diff --git a/lib/netstd/Thrift/Transport/TTransportFactory.cs b/lib/netstd/Thrift/Transport/TTransportFactory.cs new file mode 100644 index 00000000000..69662f3f4d9 --- /dev/null +++ b/lib/netstd/Thrift/Transport/TTransportFactory.cs @@ -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. + +namespace Thrift.Transport +{ + /// + /// From Mark Slee & Aditya Agarwal of Facebook: + /// 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) + /// + // ReSharper disable once InconsistentNaming + public class TTransportFactory + { + public virtual TTransport GetTransport(TTransport trans) + { + return trans; + } + } +} \ No newline at end of file diff --git a/lib/netstd/build.cmd b/lib/netstd/build.cmd new file mode 100644 index 00000000000..863c4b45eae --- /dev/null +++ b/lib/netstd/build.cmd @@ -0,0 +1,27 @@ +@echo off +rem /* +rem * Licensed to the Apache Software Foundation (ASF) under one +rem * or more contributor license agreements. See the NOTICE file +rem * distributed with this work for additional information +rem * regarding copyright ownership. The ASF licenses this file +rem * to you under the Apache License, Version 2.0 (the +rem * "License"); you may not use this file except in compliance +rem * with the License. You may obtain a copy of the License at +rem * +rem * http://www.apache.org/licenses/LICENSE-2.0 +rem * +rem * Unless required by applicable law or agreed to in writing, +rem * software distributed under the License is distributed on an +rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +rem * KIND, either express or implied. See the License for the +rem * specific language governing permissions and limitations +rem * under the License. +rem */ + +setlocal + +thrift -version +dotnet --info +dotnet build + +:eof diff --git a/lib/netstd/build.sh b/lib/netstd/build.sh new file mode 100644 index 00000000000..ae18bce9bf2 --- /dev/null +++ b/lib/netstd/build.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +#exit if any command fails +#set -e + +thrift --version +dotnet --info +dotnet build + +#revision=${TRAVIS_JOB_ID:=1} +#revision=$(printf "%04d" $revision) + +#dotnet pack ./src/PROJECT_NAME -c Release -o ./artifacts --version-suffix=$revision diff --git a/lib/netstd/runtests.cmd b/lib/netstd/runtests.cmd new file mode 100644 index 00000000000..5114bc594d8 --- /dev/null +++ b/lib/netstd/runtests.cmd @@ -0,0 +1,28 @@ +@echo off +rem /* +rem * Licensed to the Apache Software Foundation (ASF) under one +rem * or more contributor license agreements. See the NOTICE file +rem * distributed with this work for additional information +rem * regarding copyright ownership. The ASF licenses this file +rem * to you under the Apache License, Version 2.0 (the +rem * "License"); you may not use this file except in compliance +rem * with the License. You may obtain a copy of the License at +rem * +rem * http://www.apache.org/licenses/LICENSE-2.0 +rem * +rem * Unless required by applicable law or agreed to in writing, +rem * software distributed under the License is distributed on an +rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +rem * KIND, either express or implied. See the License for the +rem * specific language governing permissions and limitations +rem * under the License. +rem */ +setlocal + +thrift -version +dotnet --info + +dotnet test Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj +dotnet test Tests\Thrift.Tests\Thrift.Tests.csproj + +:eof diff --git a/lib/netstd/runtests.sh b/lib/netstd/runtests.sh new file mode 100644 index 00000000000..a26cc36ac23 --- /dev/null +++ b/lib/netstd/runtests.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +thrift -version +dotnet --info + +dotnet test Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj +dotnet test Tests\Thrift.Tests\Thrift.Tests.csproj \ No newline at end of file diff --git a/test/Makefile.am b/test/Makefile.am index 84f1f25cc45..682e04a6eeb 100755 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -77,8 +77,9 @@ if WITH_HAXE SUBDIRS += haxe endif -if WITH_DOTNETCORE +if WITH_DOTNET SUBDIRS += netcore +SUBDIRS += netstd endif if WITH_GO diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift index e025b7f54a6..d1e6b5eea8b 100644 --- a/test/ThriftTest.thrift +++ b/test/ThriftTest.thrift @@ -30,6 +30,7 @@ namespace java thrift.test namespace js ThriftTest namespace lua ThriftTest namespace netcore ThriftTest +namespace netstd ThriftTest namespace perl ThriftTest namespace php ThriftTest namespace py ThriftTest diff --git a/test/netstd/Client/.gitignore b/test/netstd/Client/.gitignore new file mode 100644 index 00000000000..67d55106a4b --- /dev/null +++ b/test/netstd/Client/.gitignore @@ -0,0 +1,2 @@ +# ignore for autogenerated files +/ThriftTest diff --git a/test/netstd/Client/Client.csproj b/test/netstd/Client/Client.csproj new file mode 100644 index 00000000000..38e455dbe03 --- /dev/null +++ b/test/netstd/Client/Client.csproj @@ -0,0 +1,50 @@ + + + + + netcoreapp2.0 + Client + Client + Exe + false + false + false + false + false + false + + + + + + + + + + + + + + + + + + + diff --git a/test/netstd/Client/Program.cs b/test/netstd/Client/Program.cs new file mode 100644 index 00000000000..72139d9def5 --- /dev/null +++ b/test/netstd/Client/Program.cs @@ -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. + +using System; +using System.Collections.Generic; +using ThriftTest; + +namespace Client +{ + public class Program + { + public static int Main(string[] args) + { + try + { + Console.SetBufferSize(Console.BufferWidth, 4096); + } + catch (Exception) + { + Console.WriteLine("Failed to grow scroll-back buffer"); + } + + // split mode and options + var subArgs = new List(args); + var firstArg = string.Empty; + if (subArgs.Count > 0) + { + firstArg = subArgs[0]; + subArgs.RemoveAt(0); + } + + // run whatever mode is choosen + switch(firstArg) + { + case "client": + return TestClient.Execute(subArgs); + case "--help": + PrintHelp(); + return 0; + default: + PrintHelp(); + return -1; + } + } + + private static void PrintHelp() + { + Console.WriteLine("Usage:"); + Console.WriteLine(" Client client [options]'"); + Console.WriteLine(" Client --help"); + Console.WriteLine(""); + + TestClient.PrintOptionsHelp(); + } + } +} + + diff --git a/test/netstd/Client/Properties/AssemblyInfo.cs b/test/netstd/Client/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..157152b4dbb --- /dev/null +++ b/test/netstd/Client/Properties/AssemblyInfo.cs @@ -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. +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Client")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("B0C13DA0-3117-4844-8AE8-B1775E46223D")] + diff --git a/test/netstd/Client/TestClient.cs b/test/netstd/Client/TestClient.cs new file mode 100644 index 00000000000..b2e8cbf5c88 --- /dev/null +++ b/test/netstd/Client/TestClient.cs @@ -0,0 +1,943 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Reflection; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.ServiceModel; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Thrift.Collections; +using Thrift.Protocol; +using Thrift.Transport; +using Thrift.Transport.Client; + +namespace ThriftTest +{ + public class TestClient + { + private class TestParams + { + public int numIterations = 1; + public IPAddress host = IPAddress.Any; + public int port = 9090; + public int numThreads = 1; + public string url; + public string pipe; + public bool buffered; + public bool framed; + public string protocol; + public bool encrypted = false; + + internal void Parse( List args) + { + for (var i = 0; i < args.Count; ++i) + { + if (args[i] == "-u") + { + url = args[++i]; + } + else if (args[i] == "-n") + { + numIterations = Convert.ToInt32(args[++i]); + } + else if (args[i].StartsWith("--pipe=")) + { + pipe = args[i].Substring(args[i].IndexOf("=") + 1); + Console.WriteLine("Using named pipes transport"); + } + else if (args[i].StartsWith("--host=")) + { + // check there for ipaddress + host = new IPAddress(Encoding.Unicode.GetBytes(args[i].Substring(args[i].IndexOf("=") + 1))); + } + else if (args[i].StartsWith("--port=")) + { + port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); + } + else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") + { + buffered = true; + Console.WriteLine("Using buffered sockets"); + } + else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") + { + framed = true; + Console.WriteLine("Using framed transport"); + } + else if (args[i] == "-t") + { + numThreads = Convert.ToInt32(args[++i]); + } + else if (args[i] == "--binary" || args[i] == "--protocol=binary") + { + protocol = "binary"; + Console.WriteLine("Using binary protocol"); + } + else if (args[i] == "--compact" || args[i] == "--protocol=compact") + { + protocol = "compact"; + Console.WriteLine("Using compact protocol"); + } + else if (args[i] == "--json" || args[i] == "--protocol=json") + { + protocol = "json"; + Console.WriteLine("Using JSON protocol"); + } + else if (args[i] == "--ssl") + { + encrypted = true; + Console.WriteLine("Using encrypted transport"); + } + else + { + //throw new ArgumentException(args[i]); + } + } + } + + private static X509Certificate2 GetClientCert() + { + var clientCertName = "client.p12"; + var possiblePaths = new List + { + "../../../keys/", + "../../keys/", + "../keys/", + "keys/", + }; + + string existingPath = null; + foreach (var possiblePath in possiblePaths) + { + var path = Path.GetFullPath(possiblePath + clientCertName); + if (File.Exists(path)) + { + existingPath = path; + break; + } + } + + if (string.IsNullOrEmpty(existingPath)) + { + throw new FileNotFoundException($"Cannot find file: {clientCertName}"); + } + + var cert = new X509Certificate2(existingPath, "thrift"); + + return cert; + } + + public TTransport CreateTransport() + { + if (url == null) + { + // endpoint transport + TTransport trans = null; + + if (pipe != null) + { + trans = new TNamedPipeTransport(pipe); + } + else + { + if (encrypted) + { + var cert = GetClientCert(); + + if (cert == null || !cert.HasPrivateKey) + { + throw new InvalidOperationException("Certificate doesn't contain private key"); + } + + trans = new TTlsSocketTransport(host, port, 0, cert, + (sender, certificate, chain, errors) => true, + null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); + } + else + { + trans = new TSocketTransport(host, port); + } + } + + // layered transport + if (buffered) + { + trans = new TBufferedTransport(trans); + } + + if (framed) + { + trans = new TFramedTransport(trans); + } + + return trans; + } + + return new THttpTransport(new Uri(url), null); + } + + public TProtocol CreateProtocol(TTransport transport) + { + if (protocol == "compact") + { + return new TCompactProtocol(transport); + } + + if (protocol == "json") + { + return new TJsonProtocol(transport); + } + + return new TBinaryProtocol(transport); + } + } + + + private const int ErrorBaseTypes = 1; + private const int ErrorStructs = 2; + private const int ErrorContainers = 4; + private const int ErrorExceptions = 8; + private const int ErrorUnknown = 64; + + private class ClientTest + { + private readonly TTransport transport; + private readonly ThriftTest.Client client; + private readonly int numIterations; + private bool done; + + public int ReturnCode { get; set; } + + public ClientTest(TestParams param) + { + transport = param.CreateTransport(); + client = new ThriftTest.Client(param.CreateProtocol(transport)); + numIterations = param.numIterations; + } + + public void Execute() + { + var token = CancellationToken.None; + + if (done) + { + Console.WriteLine("Execute called more than once"); + throw new InvalidOperationException(); + } + + for (var i = 0; i < numIterations; i++) + { + try + { + if (!transport.IsOpen) + { + transport.OpenAsync(token).GetAwaiter().GetResult(); + } + } + catch (TTransportException ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Connect failed: " + ex.Message); + ReturnCode |= ErrorUnknown; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + continue; + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Connect failed: " + ex.Message); + ReturnCode |= ErrorUnknown; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + continue; + } + + try + { + ReturnCode |= ExecuteClientTestAsync(client).GetAwaiter().GetResult(); ; + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + ReturnCode |= ErrorUnknown; + } + } + try + { + transport.Close(); + } + catch (Exception ex) + { + Console.WriteLine("Error while closing transport"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + done = true; + } + } + + internal static void PrintOptionsHelp() + { + Console.WriteLine("Client options:"); + Console.WriteLine(" -u "); + Console.WriteLine(" -t <# of threads to run> default = 1"); + Console.WriteLine(" -n <# of iterations> per thread"); + Console.WriteLine(" --pipe="); + Console.WriteLine(" --host="); + Console.WriteLine(" --port="); + Console.WriteLine(" --transport= one of buffered,framed (defaults to none)"); + Console.WriteLine(" --protocol= one of compact,json (defaults to binary)"); + Console.WriteLine(" --ssl"); + Console.WriteLine(); + } + + public static int Execute(List args) + { + try + { + var param = new TestParams(); + + try + { + param.Parse(args); + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Error while parsing arguments"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + return ErrorUnknown; + } + + var tests = Enumerable.Range(0, param.numThreads).Select(_ => new ClientTest(param)).ToArray(); + + //issue tests on separate threads simultaneously + var threads = tests.Select(test => new Task(test.Execute)).ToArray(); + var start = DateTime.Now; + foreach (var t in threads) + { + t.Start(); + } + + Task.WaitAll(threads); + + Console.WriteLine("Total time: " + (DateTime.Now - start)); + Console.WriteLine(); + return tests.Select(t => t.ReturnCode).Aggregate((r1, r2) => r1 | r2); + } + catch (Exception outerEx) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Unexpected error"); + Console.WriteLine(outerEx.Message + " ST: " + outerEx.StackTrace); + return ErrorUnknown; + } + } + + public static string BytesToHex(byte[] data) + { + return BitConverter.ToString(data).Replace("-", string.Empty); + } + + public static byte[] PrepareTestData(bool randomDist) + { + var retval = new byte[0x100]; + var initLen = Math.Min(0x100, retval.Length); + + // linear distribution, unless random is requested + if (!randomDist) + { + for (var i = 0; i < initLen; ++i) + { + retval[i] = (byte)i; + } + return retval; + } + + // random distribution + for (var i = 0; i < initLen; ++i) + { + retval[i] = (byte)0; + } + var rnd = new Random(); + for (var i = 1; i < initLen; ++i) + { + while (true) + { + var nextPos = rnd.Next() % initLen; + if (retval[nextPos] == 0) + { + retval[nextPos] = (byte)i; + break; + } + } + } + return retval; + } + + public static async Task ExecuteClientTestAsync(ThriftTest.Client client) + { + var token = CancellationToken.None; + var returnCode = 0; + + Console.Write("testVoid()"); + await client.testVoidAsync(token); + Console.WriteLine(" = void"); + + Console.Write("testString(\"Test\")"); + var s = await client.testStringAsync("Test", token); + Console.WriteLine(" = \"" + s + "\""); + if ("Test" != s) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testBool(true)"); + var t = await client.testBoolAsync((bool)true, token); + Console.WriteLine(" = " + t); + if (!t) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + Console.Write("testBool(false)"); + var f = await client.testBoolAsync((bool)false, token); + Console.WriteLine(" = " + f); + if (f) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testByte(1)"); + var i8 = await client.testByteAsync((sbyte)1, token); + Console.WriteLine(" = " + i8); + if (1 != i8) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testI32(-1)"); + var i32 = await client.testI32Async(-1, token); + Console.WriteLine(" = " + i32); + if (-1 != i32) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("testI64(-34359738368)"); + var i64 = await client.testI64Async(-34359738368, token); + Console.WriteLine(" = " + i64); + if (-34359738368 != i64) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + // TODO: Validate received message + Console.Write("testDouble(5.325098235)"); + var dub = await client.testDoubleAsync(5.325098235, token); + Console.WriteLine(" = " + dub); + if (5.325098235 != dub) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + Console.Write("testDouble(-0.000341012439638598279)"); + dub = await client.testDoubleAsync(-0.000341012439638598279, token); + Console.WriteLine(" = " + dub); + if (-0.000341012439638598279 != dub) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + var binOut = PrepareTestData(true); + Console.Write("testBinary(" + BytesToHex(binOut) + ")"); + try + { + var binIn = await client.testBinaryAsync(binOut, token); + Console.WriteLine(" = " + BytesToHex(binIn)); + if (binIn.Length != binOut.Length) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + for (var ofs = 0; ofs < Math.Min(binIn.Length, binOut.Length); ++ofs) + if (binIn[ofs] != binOut[ofs]) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + } + catch (Thrift.TApplicationException ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + + // binary equals? + Console.WriteLine("Test CrazyNesting"); + var one = new CrazyNesting(); + var two = new CrazyNesting(); + one.String_field = "crazy"; + two.String_field = "crazy"; + one.Binary_field = new byte[] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; + two.Binary_field = new byte[10] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; + if (typeof(CrazyNesting).GetMethod("Equals")?.DeclaringType == typeof(CrazyNesting)) + { + if (!one.Equals(two)) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorContainers; + throw new Exception("CrazyNesting.Equals failed"); + } + } + + // TODO: Validate received message + Console.Write("testStruct({\"Zero\", 1, -3, -5})"); + var o = new Xtruct(); + o.String_thing = "Zero"; + o.Byte_thing = (sbyte)1; + o.I32_thing = -3; + o.I64_thing = -5; + var i = await client.testStructAsync(o, token); + Console.WriteLine(" = {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}"); + + // TODO: Validate received message + Console.Write("testNest({1, {\"Zero\", 1, -3, -5}, 5})"); + var o2 = new Xtruct2(); + o2.Byte_thing = (sbyte)1; + o2.Struct_thing = o; + o2.I32_thing = 5; + var i2 = await client.testNestAsync(o2, token); + i = i2.Struct_thing; + Console.WriteLine(" = {" + i2.Byte_thing + ", {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}, " + i2.I32_thing + "}"); + + var mapout = new Dictionary(); + for (var j = 0; j < 5; j++) + { + mapout[j] = j - 10; + } + Console.Write("testMap({"); + var first = true; + foreach (var key in mapout.Keys) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(key + " => " + mapout[key]); + } + Console.Write("})"); + + var mapin = await client.testMapAsync(mapout, token); + + Console.Write(" = {"); + first = true; + foreach (var key in mapin.Keys) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(key + " => " + mapin[key]); + } + Console.WriteLine("}"); + + // TODO: Validate received message + var listout = new List(); + for (var j = -2; j < 3; j++) + { + listout.Add(j); + } + Console.Write("testList({"); + first = true; + foreach (var j in listout) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.Write("})"); + + var listin = await client.testListAsync(listout, token); + + Console.Write(" = {"); + first = true; + foreach (var j in listin) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.WriteLine("}"); + + //set + // TODO: Validate received message + var setout = new THashSet(); + for (var j = -2; j < 3; j++) + { + setout.Add(j); + } + Console.Write("testSet({"); + first = true; + foreach (int j in setout) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.Write("})"); + + var setin = await client.testSetAsync(setout, token); + + Console.Write(" = {"); + first = true; + foreach (int j in setin) + { + if (first) + { + first = false; + } + else + { + Console.Write(", "); + } + Console.Write(j); + } + Console.WriteLine("}"); + + + Console.Write("testEnum(ONE)"); + var ret = await client.testEnumAsync(Numberz.ONE, token); + Console.WriteLine(" = " + ret); + if (Numberz.ONE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(TWO)"); + ret = await client.testEnumAsync(Numberz.TWO, token); + Console.WriteLine(" = " + ret); + if (Numberz.TWO != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(THREE)"); + ret = await client.testEnumAsync(Numberz.THREE, token); + Console.WriteLine(" = " + ret); + if (Numberz.THREE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(FIVE)"); + ret = await client.testEnumAsync(Numberz.FIVE, token); + Console.WriteLine(" = " + ret); + if (Numberz.FIVE != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testEnum(EIGHT)"); + ret = await client.testEnumAsync(Numberz.EIGHT, token); + Console.WriteLine(" = " + ret); + if (Numberz.EIGHT != ret) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + Console.Write("testTypedef(309858235082523)"); + var uid = await client.testTypedefAsync(309858235082523L, token); + Console.WriteLine(" = " + uid); + if (309858235082523L != uid) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorStructs; + } + + // TODO: Validate received message + Console.Write("testMapMap(1)"); + var mm = await client.testMapMapAsync(1, token); + Console.Write(" = {"); + foreach (var key in mm.Keys) + { + Console.Write(key + " => {"); + var m2 = mm[key]; + foreach (var k2 in m2.Keys) + { + Console.Write(k2 + " => " + m2[k2] + ", "); + } + Console.Write("}, "); + } + Console.WriteLine("}"); + + // TODO: Validate received message + var insane = new Insanity(); + insane.UserMap = new Dictionary(); + insane.UserMap[Numberz.FIVE] = 5000L; + var truck = new Xtruct(); + truck.String_thing = "Truck"; + truck.Byte_thing = (sbyte)8; + truck.I32_thing = 8; + truck.I64_thing = 8; + insane.Xtructs = new List(); + insane.Xtructs.Add(truck); + Console.Write("testInsanity()"); + var whoa = await client.testInsanityAsync(insane, token); + Console.Write(" = {"); + foreach (var key in whoa.Keys) + { + var val = whoa[key]; + Console.Write(key + " => {"); + + foreach (var k2 in val.Keys) + { + var v2 = val[k2]; + + Console.Write(k2 + " => {"); + var userMap = v2.UserMap; + + Console.Write("{"); + if (userMap != null) + { + foreach (var k3 in userMap.Keys) + { + Console.Write(k3 + " => " + userMap[k3] + ", "); + } + } + else + { + Console.Write("null"); + } + Console.Write("}, "); + + var xtructs = v2.Xtructs; + + Console.Write("{"); + if (xtructs != null) + { + foreach (var x in xtructs) + { + Console.Write("{\"" + x.String_thing + "\", " + x.Byte_thing + ", " + x.I32_thing + ", " + x.I32_thing + "}, "); + } + } + else + { + Console.Write("null"); + } + Console.Write("}"); + + Console.Write("}, "); + } + Console.Write("}, "); + } + Console.WriteLine("}"); + + sbyte arg0 = 1; + var arg1 = 2; + var arg2 = long.MaxValue; + var multiDict = new Dictionary(); + multiDict[1] = "one"; + + var tmpMultiDict = new List(); + foreach (var pair in multiDict) + tmpMultiDict.Add(pair.Key +" => "+ pair.Value); + + var arg4 = Numberz.FIVE; + long arg5 = 5000000; + Console.Write("Test Multi(" + arg0 + "," + arg1 + "," + arg2 + ",{" + string.Join(",", tmpMultiDict) + "}," + arg4 + "," + arg5 + ")"); + var multiResponse = await client.testMultiAsync(arg0, arg1, arg2, multiDict, arg4, arg5, token); + Console.Write(" = Xtruct(byte_thing:" + multiResponse.Byte_thing + ",String_thing:" + multiResponse.String_thing + + ",i32_thing:" + multiResponse.I32_thing + ",i64_thing:" + multiResponse.I64_thing + ")\n"); + + try + { + Console.WriteLine("testException(\"Xception\")"); + await client.testExceptionAsync("Xception", token); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception ex) + { + if (ex.ErrorCode != 1001 || ex.Message != "Xception") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testException(\"TException\")"); + await client.testExceptionAsync("TException", token); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Thrift.TException) + { + // OK + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testException(\"ok\")"); + await client.testExceptionAsync("ok", token); + // OK + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + + try + { + Console.WriteLine("testMultiException(\"Xception\", ...)"); + await client.testMultiExceptionAsync("Xception", "ignore", token); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception ex) + { + if (ex.ErrorCode != 1001 || ex.Message != "This is an Xception") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testMultiException(\"Xception2\", ...)"); + await client.testMultiExceptionAsync("Xception2", "ignore", token); + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + catch (Xception2 ex) + { + if (ex.ErrorCode != 2002 || ex.Struct_thing.String_thing != "This is an Xception2") + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + try + { + Console.WriteLine("testMultiException(\"success\", \"OK\")"); + if ("OK" != (await client.testMultiExceptionAsync("success", "OK", token)).String_thing) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + } + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorExceptions; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } + + var sw = new Stopwatch(); + sw.Start(); + Console.WriteLine("Test Oneway(1)"); + await client.testOnewayAsync(1, token); + sw.Stop(); + if (sw.ElapsedMilliseconds > 1000) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + + Console.Write("Test Calltime()"); + var times = 50; + sw.Reset(); + sw.Start(); + for (var k = 0; k < times; ++k) + await client.testVoidAsync(token); + sw.Stop(); + Console.WriteLine(" = {0} ms a testVoid() call", sw.ElapsedMilliseconds / times); + return returnCode; + } + } +} diff --git a/test/netstd/Makefile.am b/test/netstd/Makefile.am new file mode 100644 index 00000000000..376ffb71e15 --- /dev/null +++ b/test/netstd/Makefile.am @@ -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. +# + +SUBDIRS = . + +all-local: + $(DOTNETCORE) build + +precross: + $(DOTNETCORE) build + +clean-local: + $(RM) -r Client/bin + $(RM) -r Server/bin + $(RM) -r Client/obj + $(RM) -r Server/obj + $(RM) -r ThriftTest/ThriftTest + +EXTRA_DIST = \ + Client \ + README.md \ + Server \ + ThriftTest.sln \ + build.cmd \ + build.sh diff --git a/test/netstd/README.md b/test/netstd/README.md new file mode 100644 index 00000000000..ed728d1bac4 --- /dev/null +++ b/test/netstd/README.md @@ -0,0 +1,20 @@ +# Apache Thrift net-core-lib tests + +Tests for Thrift client library ported to Microsoft .Net Core + +# Content +- ThriftTest - tests for Thrift library + +# Reused components +- NET Core Standard 1.6 (SDK 2.0.0) + +# How to build on Windows +- Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable +- Open ThriftTest.sln in Visual Studio and build +or +- Build with scripts + +# How to build on Unix +- Ensure you have .NET Core 2.0.0 SDK installed or use the Ubuntu Xenial docker image +- Follow common build practice for Thrift: bootstrap, configure, and make precross + diff --git a/test/netstd/Server/.gitignore b/test/netstd/Server/.gitignore new file mode 100644 index 00000000000..67d55106a4b --- /dev/null +++ b/test/netstd/Server/.gitignore @@ -0,0 +1,2 @@ +# ignore for autogenerated files +/ThriftTest diff --git a/test/netstd/Server/Program.cs b/test/netstd/Server/Program.cs new file mode 100644 index 00000000000..e647e5b2a58 --- /dev/null +++ b/test/netstd/Server/Program.cs @@ -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. + +using System; +using System.Collections.Generic; +using ThriftTest; + +namespace Server +{ + public class Program + { + public static int Main(string[] args) + { + try + { + Console.SetBufferSize(Console.BufferWidth, 4096); + } + catch (Exception) + { + Console.WriteLine("Failed to grow scroll-back buffer"); + } + + // split mode and options + var subArgs = new List(args); + var firstArg = string.Empty; + if (subArgs.Count > 0) + { + firstArg = subArgs[0]; + subArgs.RemoveAt(0); + } + + // run whatever mode is choosen + switch(firstArg) + { + case "server": + return TestServer.Execute(subArgs); + case "--help": + PrintHelp(); + return 0; + default: + PrintHelp(); + return -1; + } + } + + private static void PrintHelp() + { + Console.WriteLine("Usage:"); + Console.WriteLine(" Server server [options]'"); + Console.WriteLine(" Server --help"); + Console.WriteLine(""); + + TestServer.PrintOptionsHelp(); + } + } +} + + diff --git a/test/netstd/Server/Properties/AssemblyInfo.cs b/test/netstd/Server/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..265495c0535 --- /dev/null +++ b/test/netstd/Server/Properties/AssemblyInfo.cs @@ -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. +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("Server")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("B0C13DA0-3117-4844-8AE8-B1775E46223D")] + diff --git a/test/netstd/Server/Server.csproj b/test/netstd/Server/Server.csproj new file mode 100644 index 00000000000..60e1968b594 --- /dev/null +++ b/test/netstd/Server/Server.csproj @@ -0,0 +1,50 @@ + + + + + netcoreapp2.0 + Server + Server + Exe + false + false + false + false + false + false + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs new file mode 100644 index 00000000000..8a7410f95fc --- /dev/null +++ b/test/netstd/Server/TestServer.cs @@ -0,0 +1,595 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Collections; +using Thrift.Processor; +using Thrift.Protocol; +using Thrift.Server; +using Thrift.Transport; +using Thrift.Transport.Server; + +namespace ThriftTest +{ + internal class ServerParam + { + internal bool useBufferedSockets = false; + internal bool useFramed = false; + internal bool useEncryption = false; + internal bool compact = false; + internal bool json = false; + internal int port = 9090; + internal string pipe = null; + + internal void Parse(List args) + { + for (var i = 0; i < args.Count; i++) + { + if (args[i].StartsWith("--pipe=")) + { + pipe = args[i].Substring(args[i].IndexOf("=") + 1); + } + else if (args[i].StartsWith("--port=")) + { + port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); + } + else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") + { + useBufferedSockets = true; + } + else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") + { + useFramed = true; + } + else if (args[i] == "--binary" || args[i] == "--protocol=binary") + { + // nothing needed + } + else if (args[i] == "--compact" || args[i] == "--protocol=compact") + { + compact = true; + } + else if (args[i] == "--json" || args[i] == "--protocol=json") + { + json = true; + } + else if (args[i] == "--threaded" || args[i] == "--server-type=threaded") + { + throw new NotImplementedException(args[i]); + } + else if (args[i] == "--threadpool" || args[i] == "--server-type=threadpool") + { + throw new NotImplementedException(args[i]); + } + else if (args[i] == "--prototype" || args[i] == "--processor=prototype") + { + throw new NotImplementedException(args[i]); + } + else if (args[i] == "--ssl") + { + useEncryption = true; + } + else + { + //throw new ArgumentException(args[i]); + } + } + + } + } + + public class TestServer + { + public static int _clientID = -1; + public delegate void TestLogDelegate(string msg, params object[] values); + + public class MyServerEventHandler : TServerEventHandler + { + public int callCount = 0; + + public Task PreServeAsync(CancellationToken cancellationToken) + { + callCount++; + return Task.CompletedTask; + } + + public Task CreateContextAsync(TProtocol input, TProtocol output, CancellationToken cancellationToken) + { + callCount++; + return Task.FromResult(null); + } + + public Task DeleteContextAsync(object serverContext, TProtocol input, TProtocol output, CancellationToken cancellationToken) + { + callCount++; + return Task.CompletedTask; + } + + public Task ProcessContextAsync(object serverContext, TTransport transport, CancellationToken cancellationToken) + { + callCount++; + return Task.CompletedTask; + } + } + + public class TestHandlerAsync : ThriftTest.IAsync + { + public TServer server { get; set; } + private int handlerID; + private StringBuilder sb = new StringBuilder(); + private TestLogDelegate logger; + + public TestHandlerAsync() + { + handlerID = Interlocked.Increment(ref _clientID); + logger += testConsoleLogger; + logger.Invoke("New TestHandler instance created"); + } + + public void testConsoleLogger(string msg, params object[] values) + { + sb.Clear(); + sb.AppendFormat("handler{0:D3}:", handlerID); + sb.AppendFormat(msg, values); + sb.AppendLine(); + Console.Write(sb.ToString()); + } + + public Task testVoidAsync(CancellationToken cancellationToken) + { + logger.Invoke("testVoid()"); + return Task.CompletedTask; + } + + public Task testStringAsync(string thing, CancellationToken cancellationToken) + { + logger.Invoke("testString({0})", thing); + return Task.FromResult(thing); + } + + public Task testBoolAsync(bool thing, CancellationToken cancellationToken) + { + logger.Invoke("testBool({0})", thing); + return Task.FromResult(thing); + } + + public Task testByteAsync(sbyte thing, CancellationToken cancellationToken) + { + logger.Invoke("testByte({0})", thing); + return Task.FromResult(thing); + } + + public Task testI32Async(int thing, CancellationToken cancellationToken) + { + logger.Invoke("testI32({0})", thing); + return Task.FromResult(thing); + } + + public Task testI64Async(long thing, CancellationToken cancellationToken) + { + logger.Invoke("testI64({0})", thing); + return Task.FromResult(thing); + } + + public Task testDoubleAsync(double thing, CancellationToken cancellationToken) + { + logger.Invoke("testDouble({0})", thing); + return Task.FromResult(thing); + } + + public Task testBinaryAsync(byte[] thing, CancellationToken cancellationToken) + { + var hex = BitConverter.ToString(thing).Replace("-", string.Empty); + logger.Invoke("testBinary({0:X})", hex); + return Task.FromResult(thing); + } + + public Task testStructAsync(Xtruct thing, CancellationToken cancellationToken) + { + logger.Invoke("testStruct({{\"{0}\", {1}, {2}, {3}}})", thing.String_thing, thing.Byte_thing, thing.I32_thing, thing.I64_thing); + return Task.FromResult(thing); + } + + public Task testNestAsync(Xtruct2 nest, CancellationToken cancellationToken) + { + var thing = nest.Struct_thing; + logger.Invoke("testNest({{{0}, {{\"{1}\", {2}, {3}, {4}, {5}}}}})", + nest.Byte_thing, + thing.String_thing, + thing.Byte_thing, + thing.I32_thing, + thing.I64_thing, + nest.I32_thing); + return Task.FromResult(nest); + } + + public Task> testMapAsync(Dictionary thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testMap({{"); + var first = true; + foreach (var key in thing.Keys) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0} => {1}", key, thing[key]); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task> testStringMapAsync(Dictionary thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testStringMap({{"); + var first = true; + foreach (var key in thing.Keys) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0} => {1}", key, thing[key]); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task> testSetAsync(THashSet thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testSet({{"); + var first = true; + foreach (int elem in thing) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0}", elem); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task> testListAsync(List thing, CancellationToken cancellationToken) + { + sb.Clear(); + sb.Append("testList({{"); + var first = true; + foreach (var elem in thing) + { + if (first) + { + first = false; + } + else + { + sb.Append(", "); + } + sb.AppendFormat("{0}", elem); + } + sb.Append("}})"); + logger.Invoke(sb.ToString()); + return Task.FromResult(thing); + } + + public Task testEnumAsync(Numberz thing, CancellationToken cancellationToken) + { + logger.Invoke("testEnum({0})", thing); + return Task.FromResult(thing); + } + + public Task testTypedefAsync(long thing, CancellationToken cancellationToken) + { + logger.Invoke("testTypedef({0})", thing); + return Task.FromResult(thing); + } + + public Task>> testMapMapAsync(int hello, CancellationToken cancellationToken) + { + logger.Invoke("testMapMap({0})", hello); + var mapmap = new Dictionary>(); + + var pos = new Dictionary(); + var neg = new Dictionary(); + for (var i = 1; i < 5; i++) + { + pos[i] = i; + neg[-i] = -i; + } + + mapmap[4] = pos; + mapmap[-4] = neg; + + return Task.FromResult(mapmap); + } + + public Task>> testInsanityAsync(Insanity argument, CancellationToken cancellationToken) + { + logger.Invoke("testInsanity()"); + + /** from ThriftTest.thrift: + * So you think you've got this all worked, out eh? + * + * Creates a the returned map with these values and prints it out: + * { 1 => { 2 => argument, + * 3 => argument, + * }, + * 2 => { 6 => , }, + * } + * @return map> - a map with the above values + */ + + var first_map = new Dictionary(); + var second_map = new Dictionary(); ; + + first_map[Numberz.TWO] = argument; + first_map[Numberz.THREE] = argument; + + second_map[Numberz.SIX] = new Insanity(); + + var insane = new Dictionary> + { + [1] = first_map, + [2] = second_map + }; + + return Task.FromResult(insane); + } + + public Task testMultiAsync(sbyte arg0, int arg1, long arg2, Dictionary arg3, Numberz arg4, long arg5, + CancellationToken cancellationToken) + { + logger.Invoke("testMulti()"); + + var hello = new Xtruct(); ; + hello.String_thing = "Hello2"; + hello.Byte_thing = arg0; + hello.I32_thing = arg1; + hello.I64_thing = arg2; + return Task.FromResult(hello); + } + + public Task testExceptionAsync(string arg, CancellationToken cancellationToken) + { + logger.Invoke("testException({0})", arg); + if (arg == "Xception") + { + var x = new Xception + { + ErrorCode = 1001, + Message = arg + }; + throw x; + } + if (arg == "TException") + { + throw new TException(); + } + return Task.CompletedTask; + } + + public Task testMultiExceptionAsync(string arg0, string arg1, CancellationToken cancellationToken) + { + logger.Invoke("testMultiException({0}, {1})", arg0, arg1); + if (arg0 == "Xception") + { + var x = new Xception + { + ErrorCode = 1001, + Message = "This is an Xception" + }; + throw x; + } + + if (arg0 == "Xception2") + { + var x = new Xception2 + { + ErrorCode = 2002, + Struct_thing = new Xtruct { String_thing = "This is an Xception2" } + }; + throw x; + } + + var result = new Xtruct { String_thing = arg1 }; + return Task.FromResult(result); + } + + public Task testOnewayAsync(int secondsToSleep, CancellationToken cancellationToken) + { + logger.Invoke("testOneway({0}), sleeping...", secondsToSleep); + Task.Delay(secondsToSleep * 1000, cancellationToken).GetAwaiter().GetResult(); + logger.Invoke("testOneway finished"); + + return Task.CompletedTask; + } + } + + internal static void PrintOptionsHelp() + { + Console.WriteLine("Server options:"); + Console.WriteLine(" --pipe="); + Console.WriteLine(" --port="); + Console.WriteLine(" --transport= one of buffered,framed (defaults to none)"); + Console.WriteLine(" --protocol= one of compact,json (defaults to binary)"); + Console.WriteLine(" --server-type= one of threaded,threadpool (defaults to simple)"); + Console.WriteLine(" --processor="); + Console.WriteLine(" --ssl"); + Console.WriteLine(); + } + + private static X509Certificate2 GetServerCert() + { + var serverCertName = "server.p12"; + var possiblePaths = new List + { + "../../../keys/", + "../../keys/", + "../keys/", + "keys/", + }; + + string existingPath = null; + foreach (var possiblePath in possiblePaths) + { + var path = Path.GetFullPath(possiblePath + serverCertName); + if (File.Exists(path)) + { + existingPath = path; + break; + } + } + + if (string.IsNullOrEmpty(existingPath)) + { + throw new FileNotFoundException($"Cannot find file: {serverCertName}"); + } + + var cert = new X509Certificate2(existingPath, "thrift"); + + return cert; + } + + public static int Execute(List args) + { + var loggerFactory = new LoggerFactory();//.AddConsole().AddDebug(); + var logger = new LoggerFactory().CreateLogger("Test"); + + try + { + var param = new ServerParam(); + + try + { + param.Parse(args); + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Error while parsing arguments"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + return 1; + } + + + // Transport + TServerTransport trans; + if (param.pipe != null) + { + trans = new TNamedPipeServerTransport(param.pipe); + } +// else if (param.useFramed) +// { +// trans = new TServerFramedTransport(param.port); +// } + else + { + if (param.useEncryption) + { + var cert = GetServerCert(); + + if (cert == null || !cert.HasPrivateKey) + { + throw new InvalidOperationException("Certificate doesn't contain private key"); + } + + trans = new TTlsServerSocketTransport(param.port, param.useBufferedSockets, param.useFramed, cert, + (sender, certificate, chain, errors) => true, + null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); + } + else + { + trans = new TServerSocketTransport(param.port, 0, param.useBufferedSockets, param.useFramed); + } + } + + ITProtocolFactory proto; + if (param.compact) + proto = new TCompactProtocol.Factory(); + else if (param.json) + proto = new TJsonProtocol.Factory(); + else + proto = new TBinaryProtocol.Factory(); + + ITProcessorFactory processorFactory; + + // Processor + var testHandler = new TestHandlerAsync(); + var testProcessor = new ThriftTest.AsyncProcessor(testHandler); + processorFactory = new TSingletonProcessorFactory(testProcessor); + + TTransportFactory transFactory = new TTransportFactory(); + + TServer serverEngine = new TSimpleAsyncServer(processorFactory, trans, transFactory, transFactory, proto, proto, logger); + + //Server event handler + var serverEvents = new MyServerEventHandler(); + serverEngine.SetEventHandler(serverEvents); + + // Run it + var where = (! string.IsNullOrEmpty(param.pipe)) ? "on pipe " + param.pipe : "on port " + param.port; + Console.WriteLine("Starting the AsyncBaseServer " + where + + " with processor TPrototypeProcessorFactory prototype factory " + + (param.useBufferedSockets ? " with buffered socket" : "") + + (param.useFramed ? " with framed transport" : "") + + (param.useEncryption ? " with encryption" : "") + + (param.compact ? " with compact protocol" : "") + + (param.json ? " with json protocol" : "") + + "..."); + serverEngine.ServeAsync(CancellationToken.None).GetAwaiter().GetResult(); + Console.ReadLine(); + } + catch (Exception x) + { + Console.Error.Write(x); + return 1; + } + Console.WriteLine("done."); + return 0; + } + } + +} diff --git a/test/netstd/ThriftTest.sln b/test/netstd/ThriftTest.sln new file mode 100644 index 00000000000..6bd08555b7a --- /dev/null +++ b/test/netstd/ThriftTest.sln @@ -0,0 +1,64 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26730.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netstd\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{21039F25-6ED7-4E80-A545-EBC93472EBD1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{0C6E8685-F191-4479-9842-882A38961127}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.ActiveCfg = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.Build.0 = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.ActiveCfg = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.Build.0 = Debug|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.Build.0 = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.ActiveCfg = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.Build.0 = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.ActiveCfg = Release|Any CPU + {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.Build.0 = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.ActiveCfg = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.Build.0 = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.ActiveCfg = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.Build.0 = Debug|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.Build.0 = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x64.ActiveCfg = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x64.Build.0 = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x86.ActiveCfg = Release|Any CPU + {0C6E8685-F191-4479-9842-882A38961127}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {52CE9A12-F6CB-4F0C-BB42-0105612F5FF4} + EndGlobalSection +EndGlobal diff --git a/test/netstd/build.cmd b/test/netstd/build.cmd new file mode 100644 index 00000000000..9b84ef27606 --- /dev/null +++ b/test/netstd/build.cmd @@ -0,0 +1,25 @@ +@echo off +rem /* +rem * Licensed to the Apache Software Foundation (ASF) under one +rem * or more contributor license agreements. See the NOTICE file +rem * distributed with this work for additional information +rem * regarding copyright ownership. The ASF licenses this file +rem * to you under the Apache License, Version 2.0 (the +rem * "License"); you may not use this file except in compliance +rem * with the License. You may obtain a copy of the License at +rem * +rem * http://www.apache.org/licenses/LICENSE-2.0 +rem * +rem * Unless required by applicable law or agreed to in writing, +rem * software distributed under the License is distributed on an +rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +rem * KIND, either express or implied. See the License for the +rem * specific language governing permissions and limitations +rem * under the License. +rem */ +setlocal + +dotnet --info +dotnet build + +:eof diff --git a/test/netstd/build.sh b/test/netstd/build.sh new file mode 100644 index 00000000000..c97e310f011 --- /dev/null +++ b/test/netstd/build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +#exit if any command fails +set -e + +dotnet --info +dotnet build diff --git a/tutorial/Makefile.am b/tutorial/Makefile.am index 0499460aaf4..17a92573b44 100755 --- a/tutorial/Makefile.am +++ b/tutorial/Makefile.am @@ -58,8 +58,9 @@ if WITH_HAXE SUBDIRS += haxe endif -if WITH_DOTNETCORE +if WITH_DOTNET SUBDIRS += netcore +SUBDIRS += netstd endif if WITH_GO diff --git a/tutorial/netstd/.gitignore b/tutorial/netstd/.gitignore new file mode 100644 index 00000000000..9938bb237a0 --- /dev/null +++ b/tutorial/netstd/.gitignore @@ -0,0 +1 @@ +!**/*.pfx \ No newline at end of file diff --git a/tutorial/netstd/Client/Client.csproj b/tutorial/netstd/Client/Client.csproj new file mode 100644 index 00000000000..70eae15847b --- /dev/null +++ b/tutorial/netstd/Client/Client.csproj @@ -0,0 +1,37 @@ + + + + + netcoreapp2.0 + Client + Client + Exe + false + false + false + false + + + + + + + + diff --git a/tutorial/netstd/Client/Program.cs b/tutorial/netstd/Client/Program.cs new file mode 100644 index 00000000000..bf35746e323 --- /dev/null +++ b/tutorial/netstd/Client/Program.cs @@ -0,0 +1,355 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Protocol; +using Thrift.Transport; +using Thrift.Transport.Client; +using tutorial; +using shared; + +namespace Client +{ + public class Program + { + private static readonly ILogger Logger = new LoggerFactory().AddConsole().AddDebug().CreateLogger(nameof(Client)); + + private static void DisplayHelp() + { + Logger.LogInformation(@" +Usage: + Client.exe -help + will diplay help information + + Client.exe -tr: -pr: -mc: + will run client with specified arguments (tcp transport and binary protocol by default) and with 1 client + +Options: + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + tcpbuffered - buffered transport over tcp will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (address - ""http://localhost:9090"") + tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) + framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + multiplexed - multiplexed protocol will be used + + -mc (multiple clients): + - number of multiple clients to connect to server (max 100, default 1) + +Sample: + Client.exe -tr:tcp -p:binary +"); + } + + public static void Main(string[] args) + { + args = args ?? new string[0]; + + if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) + { + DisplayHelp(); + return; + } + + Logger.LogInformation("Starting client..."); + + using (var source = new CancellationTokenSource()) + { + RunAsync(args, source.Token).GetAwaiter().GetResult(); + } + } + + private static async Task RunAsync(string[] args, CancellationToken cancellationToken) + { + var numClients = GetNumberOfClients(args); + + Logger.LogInformation($"Selected # of clients: {numClients}"); + + var transports = new TTransport[numClients]; + for (int i = 0; i < numClients; i++) + { + var t = GetTransport(args); + transports[i] = t; + } + + Logger.LogInformation($"Selected client transport: {transports[0]}"); + + var protocols = new Tuple[numClients]; + for (int i = 0; i < numClients; i++) + { + var p = GetProtocol(args, transports[i]); + protocols[i] = p; + } + + Logger.LogInformation($"Selected client protocol: {protocols[0].Item1}"); + + var tasks = new Task[numClients]; + for (int i = 0; i < numClients; i++) + { + var task = RunClientAsync(protocols[i], cancellationToken); + tasks[i] = task; + } + + Task.WaitAll(tasks); + + await Task.CompletedTask; + } + + private static TTransport GetTransport(string[] args) + { + var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; + + Transport selectedTransport; + if (Enum.TryParse(transport, true, out selectedTransport)) + { + switch (selectedTransport) + { + case Transport.Tcp: + return new TSocketTransport(IPAddress.Loopback, 9090); + case Transport.NamedPipe: + return new TNamedPipeTransport(".test"); + case Transport.Http: + return new THttpTransport(new Uri("http://localhost:9090"), null); + case Transport.TcpBuffered: + return new TBufferedTransport(new TSocketTransport(IPAddress.Loopback, 9090)); + case Transport.TcpTls: + return new TTlsSocketTransport(IPAddress.Loopback, 9090, GetCertificate(), CertValidator, LocalCertificateSelectionCallback); + case Transport.Framed: + return new TFramedTransport(new TSocketTransport(IPAddress.Loopback, 9090)); + } + } + + return new TSocketTransport(IPAddress.Loopback, 9090); + } + + private static int GetNumberOfClients(string[] args) + { + var numClients = args.FirstOrDefault(x => x.StartsWith("-mc"))?.Split(':')?[1]; + + Logger.LogInformation($"Selected # of clients: {numClients}"); + + int c; + if( int.TryParse(numClients, out c) && (0 < c) && (c <= 100)) + return c; + else + return 1; + } + + private static X509Certificate2 GetCertificate() + { + // due to files location in net core better to take certs from top folder + var certFile = GetCertPath(Directory.GetParent(Directory.GetCurrentDirectory())); + return new X509Certificate2(certFile, "ThriftTest"); + } + + private static string GetCertPath(DirectoryInfo di, int maxCount = 6) + { + var topDir = di; + var certFile = + topDir.EnumerateFiles("ThriftTest.pfx", SearchOption.AllDirectories) + .FirstOrDefault(); + if (certFile == null) + { + if (maxCount == 0) + throw new FileNotFoundException("Cannot find file in directories"); + return GetCertPath(di.Parent, maxCount - 1); + } + + return certFile.FullName; + } + + private static X509Certificate LocalCertificateSelectionCallback(object sender, + string targetHost, X509CertificateCollection localCertificates, + X509Certificate remoteCertificate, string[] acceptableIssuers) + { + return GetCertificate(); + } + + private static bool CertValidator(object sender, X509Certificate certificate, + X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + return true; + } + + private static Tuple GetProtocol(string[] args, TTransport transport) + { + var protocol = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; + + Protocol selectedProtocol; + if (Enum.TryParse(protocol, true, out selectedProtocol)) + { + switch (selectedProtocol) + { + case Protocol.Binary: + return new Tuple(selectedProtocol, new TBinaryProtocol(transport)); + case Protocol.Compact: + return new Tuple(selectedProtocol, new TCompactProtocol(transport)); + case Protocol.Json: + return new Tuple(selectedProtocol, new TJsonProtocol(transport)); + case Protocol.Multiplexed: + // it returns BinaryProtocol to avoid making wrapped protocol as public in TProtocolDecorator (in RunClientAsync it will be wrapped into Multiplexed protocol) + return new Tuple(selectedProtocol, new TBinaryProtocol(transport)); + } + } + + return new Tuple(selectedProtocol, new TBinaryProtocol(transport)); + } + + private static async Task RunClientAsync(Tuple protocolTuple, CancellationToken cancellationToken) + { + try + { + var protocol = protocolTuple.Item2; + var protocolType = protocolTuple.Item1; + + TBaseClient client = null; + + try + { + if (protocolType != Protocol.Multiplexed) + { + + client = new Calculator.Client(protocol); + await ExecuteCalculatorClientOperations(cancellationToken, (Calculator.Client)client); + } + else + { + // it uses binary protocol there to create Multiplexed protocols + var multiplex = new TMultiplexedProtocol(protocol, nameof(Calculator)); + client = new Calculator.Client(multiplex); + await ExecuteCalculatorClientOperations(cancellationToken, (Calculator.Client)client); + + multiplex = new TMultiplexedProtocol(protocol, nameof(SharedService)); + client = new SharedService.Client(multiplex); + await ExecuteSharedServiceClientOperations(cancellationToken, (SharedService.Client)client); + } + } + catch (Exception ex) + { + Logger.LogError($"{client?.ClientId} " + ex); + } + finally + { + protocol.Transport.Close(); + } + } + catch (TApplicationException x) + { + Logger.LogError(x.ToString()); + } + } + + private static async Task ExecuteCalculatorClientOperations(CancellationToken cancellationToken, Calculator.Client client) + { + await client.OpenTransportAsync(cancellationToken); + + // Async version + + Logger.LogInformation($"{client.ClientId} PingAsync()"); + await client.pingAsync(cancellationToken); + + Logger.LogInformation($"{client.ClientId} AddAsync(1,1)"); + var sum = await client.addAsync(1, 1, cancellationToken); + Logger.LogInformation($"{client.ClientId} AddAsync(1,1)={sum}"); + + var work = new Work + { + Op = Operation.DIVIDE, + Num1 = 1, + Num2 = 0 + }; + + try + { + Logger.LogInformation($"{client.ClientId} CalculateAsync(1)"); + await client.calculateAsync(1, work, cancellationToken); + Logger.LogInformation($"{client.ClientId} Whoa we can divide by 0"); + } + catch (InvalidOperation io) + { + Logger.LogInformation($"{client.ClientId} Invalid operation: " + io); + } + + work.Op = Operation.SUBTRACT; + work.Num1 = 15; + work.Num2 = 10; + + try + { + Logger.LogInformation($"{client.ClientId} CalculateAsync(1)"); + var diff = await client.calculateAsync(1, work, cancellationToken); + Logger.LogInformation($"{client.ClientId} 15-10={diff}"); + } + catch (InvalidOperation io) + { + Logger.LogInformation($"{client.ClientId} Invalid operation: " + io); + } + + Logger.LogInformation($"{client.ClientId} GetStructAsync(1)"); + var log = await client.getStructAsync(1, cancellationToken); + Logger.LogInformation($"{client.ClientId} Check log: {log.Value}"); + + Logger.LogInformation($"{client.ClientId} ZipAsync() with delay 100mc on server side"); + await client.zipAsync(cancellationToken); + } + private static async Task ExecuteSharedServiceClientOperations(CancellationToken cancellationToken, SharedService.Client client) + { + await client.OpenTransportAsync(cancellationToken); + + // Async version + + Logger.LogInformation($"{client.ClientId} SharedService GetStructAsync(1)"); + var log = await client.getStructAsync(1, cancellationToken); + Logger.LogInformation($"{client.ClientId} SharedService Value: {log.Value}"); + } + + + private enum Transport + { + Tcp, + NamedPipe, + Http, + TcpBuffered, + Framed, + TcpTls + } + + private enum Protocol + { + Binary, + Compact, + Json, + Multiplexed + } + } +} diff --git a/tutorial/netstd/Client/Properties/AssemblyInfo.cs b/tutorial/netstd/Client/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..568382e66dc --- /dev/null +++ b/tutorial/netstd/Client/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("de78a01b-f7c6-49d1-97da-669d2ed37641")] \ No newline at end of file diff --git a/tutorial/netstd/Client/Properties/launchSettings.json b/tutorial/netstd/Client/Properties/launchSettings.json new file mode 100644 index 00000000000..6b7b60d78f4 --- /dev/null +++ b/tutorial/netstd/Client/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Client": { + "commandName": "Project", + "commandLineArgs": "-p:multiplexed" + } + } +} \ No newline at end of file diff --git a/tutorial/netstd/Client/ThriftTest.pfx b/tutorial/netstd/Client/ThriftTest.pfx new file mode 100644 index 0000000000000000000000000000000000000000..f0ded28173dc2c33cebbb2b74e1e9e9e870b5876 GIT binary patch literal 2661 zcmY+Fc{r5q7ssC&Gb1!J$(kiQNi-_kNTzK}lBB4-#%>tDNgCV8K7;IKOK6d75tC&a zp={ZTH)}K@WXZmpv83PB^)A`wF(pXt7XpsY=bHUSlV3;5-A{d&ZS=A9rAjL!JLlxE zU_0M6u}dL5dyZUM*eZRTK7%!HnQk@RhDO-B4XYapVO%Fw7K^smqmrq9#TGaL=NEIm z?!`FK&>hR?Z@)%UKPau-%?m`A(>#}=i#q*6>Xe+P#mwBs6Q0@@Ixp|5@9I+wut zA#tRevtir~_G0T(aAFKzvy!O$=C`*W)A|(nrt(YY1n}Kp^LEZq_lyzXl)hwOG@G=i zxbiB-SnTQD^sz>x%QCdt1fw!Er?MpQ>#O~U^B1Ih|GdFM1{`4ISt#RHN4|ZYyq|=< z{j;$~n=*954;otf@)^47LvcfPIKt$_Y2BL+D}7sV7s{aov!F89pkkhg#@d`RVvtv8 zqhf(QFGtL@?Vi^c`LJWbZE9|TN_1?X9?l3DaIjMO5`V9F;~;j1FwiWFV#DZK zPZjSTs!0RAwSeaugCPfE_z~82e~?}o;1!SDpMJeV`Q?+Y@TQRE z%jhKjwXIG1?LW{8%1ry~$CvoFtuttc!kQ${aiZfTlsc}(9#g1pD3VzLU3ij7h2^CD z;6Lz8^m(Xe5?)8Y0Gr#QxBP*P)`mX~ycEnzpRed9N46To2eUk?5^Lp}$Xu=>65C8xu{J&6G(`>&f z-~~7X>HrGR1atr=u0{d&fFqaa0!O&99#K(?2gPlgcy9MFU_Ez}9Obs^@?Q}%0v{+j;MU>669QYwovF;u<-Oys<_RI{b3>F|lw0+!xJ>$_T%M|8 z*-&MWR7IRjyg|Rdz}Y^1c3>+=Wp`aAotnEcJk{mR2!9S=p@lzc?XYcYm9LJXMtHbTOVA7ageNhdBfi0|v1eLr9PtqI`)XEsA zC0p*r#f2MT4Hybzy5V<-3)*Qcno)THYn1lrjq6Dik zc86XkszLcvn;9QTVpJ9nk<@$OqssciMrRF6FvCqZbspu(u*qkj2*`%Mz8yK zJdDp2+luWj&vuSBXbE_thM;=6A| zTxptZh*kG4;p+`oVSXP~RY=Ckmncb%Q_UISo?$+pr{w0qs^nnM(Hjvem6Iv&+#MtM zv{NJq4}S()s9l6QL`u&D)**e1PVG7Kle}4G&E6j*6WUk@Gf{A7t$m7Kzgxiio)Vux zaUZfKT(@FZ>2x``Vy-=XKo?(27vH5gZ(9I{TgrlFvqh3z9qJGySLfwbj9a-H4Nq*qFpUg@ld}K z)hFz#CqBwVT7Rl=a|*hQAa-`0o9X{L*g@fX}@vnbf G^#21?=Cu0& literal 0 HcmV?d00001 diff --git a/tutorial/netstd/Interfaces/.gitignore b/tutorial/netstd/Interfaces/.gitignore new file mode 100644 index 00000000000..2e7446e33e7 --- /dev/null +++ b/tutorial/netstd/Interfaces/.gitignore @@ -0,0 +1,3 @@ +# ignore for autogenerated files +/shared +/tutorial diff --git a/tutorial/netstd/Interfaces/Interfaces.csproj b/tutorial/netstd/Interfaces/Interfaces.csproj new file mode 100644 index 00000000000..68d87476e32 --- /dev/null +++ b/tutorial/netstd/Interfaces/Interfaces.csproj @@ -0,0 +1,48 @@ + + + + + netstandard2.0 + Interfaces + Interfaces + false + false + false + false + + + + + + + + + + + + + + + + + + + + diff --git a/tutorial/netstd/Interfaces/Properties/AssemblyInfo.cs b/tutorial/netstd/Interfaces/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..9126b173e7c --- /dev/null +++ b/tutorial/netstd/Interfaces/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("4d13163d-9067-4c9c-8af0-64e08451397d")] \ No newline at end of file diff --git a/tutorial/netstd/Makefile.am b/tutorial/netstd/Makefile.am new file mode 100644 index 00000000000..e3055565567 --- /dev/null +++ b/tutorial/netstd/Makefile.am @@ -0,0 +1,42 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +SUBDIRS = . + +all-local: + $(DOTNETCORE) build + +clean-local: + $(RM) Interfaces.dll + $(RM) -r Client/bin + $(RM) -r Client/obj + $(RM) -r Server/bin + $(RM) -r Server/obj + $(RM) -r Interfaces/bin + $(RM) -r Interfaces/obj + +EXTRA_DIST = \ + Client \ + Interfaces \ + README.md \ + Server \ + Tutorial.sln \ + build.cmd \ + build.sh + diff --git a/tutorial/netstd/README.md b/tutorial/netstd/README.md new file mode 100644 index 00000000000..8c8317a6581 --- /dev/null +++ b/tutorial/netstd/README.md @@ -0,0 +1,278 @@ +# Building of samples for different platforms + +# Reused components +- NET Core Standard 2.0 +- NET Core App 2.0 + +# How to build +- Download and install the latest .NET Core SDK for your platform https://www.microsoft.com/net/core#windowsvs2015 (archive for SDK 1.0.0-preview2-003121 located by: https://github.com/dotnet/core/blob/master/release-notes/download-archive.md) +- Ensure that you have thrift.exe which supports netstd lib and it added to PATH +- Go to current folder +- Run **build.sh** or **build.cmd** from the root of cloned repository +- Check tests in **src/Tests** folder +- Continue with /tutorials/netstd + +# How to run + +Notes: dotnet run supports passing arguments to app after -- symbols (https://docs.microsoft.com/en-us/dotnet/articles/core/tools/dotnet-run) - example: **dotnet run -- -h** will show help for app + +- build +- go to folder (Client/Server) +- run with specifying of correct parameters **dotnet run -tr:tcp -pr:multiplexed**, **dotnet run -help** (later, after migration to csproj and latest SDK will be possibility to use more usable form **dotnet run -- arguments**) + +#Notes +- Possible adding additional platforms after stabilization of .NET Core (runtimes, platforms (Red Hat Linux, OpenSuse, etc.) + +#Known issues +- In trace logging mode you can see some not important internal exceptions + +# Running of samples +Please install Thrift C# .NET Core library or copy sources and build them to correcly build and run samples + +# NetCore Server + +Usage: + + Server.exe -h + will diplay help information + + Server.exe -tr: -pr: + will run server with specified arguments (tcp transport and binary protocol by default) + +Options: + + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + tcpbuffered - tcp buffered transport will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (http address - ""localhost:9090"") + tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) + framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + +Sample: + + Server.exe -tr:tcp + +**Remarks**: + + For TcpTls mode certificate's file ThriftTest.pfx should be in directory with binaries in case of command line usage (or at project level in case of debugging from IDE). + Password for certificate - "ThriftTest". + + + +# NetCore Client + +Usage: + + Client.exe -h + will diplay help information + + Client.exe -tr: -pr: -mc: + will run client with specified arguments (tcp transport and binary protocol by default) + +Options: + + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + tcpbuffered - buffered transport over tcp will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (address - ""http://localhost:9090"") + tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) + framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + + -mc (multiple clients): + - number of multiple clients to connect to server (max 100, default 1) + +Sample: + + Client.exe -tr:tcp -pr:binary -mc:10 + +Remarks: + + For TcpTls mode certificate's file ThriftTest.pfx should be in directory + with binaries in case of command line usage (or at project level in case of debugging from IDE). + Password for certificate - "ThriftTest". + +# How to test communication between NetCore and Python + +* Generate code with the latest **thrift.exe** util +* Ensure that **thrift.exe** util generated folder **gen-py** with generated code for Python +* Create **client.py** and **server.py** from the code examples below and save them to the folder with previosly generated folder **gen-py** +* Run netstd samples (client and server) and python samples (client and server) + +Remarks: + +Samples of client and server code below use correct methods (operations) +and fields (properties) according to generated contracts from *.thrift files + +At Windows 10 add record **127.0.0.1 testserver** to **C:\Windows\System32\drivers\etc\hosts** file +for correct work of python server + + +**Python Client:** + +```python +import sys +import glob +sys.path.append('gen-py') + +from tutorial import Calculator +from tutorial.ttypes import InvalidOperation, Operation, Work + +from thrift import Thrift +from thrift.transport import TSocket +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol + + +def main(): + # Make socket + transport = TSocket.TSocket('127.0.0.1', 9090) + + # Buffering is critical. Raw sockets are very slow + transport = TTransport.TBufferedTransport(transport) + + # Wrap in a protocol + protocol = TBinaryProtocol.TBinaryProtocol(transport) + + # Create a client to use the protocol encoder + client = Calculator.Client(protocol) + + # Connect! + transport.open() + + client.Ping() + print('ping()') + + sum = client.Add(1, 1) + print(('1+1=%d' % (sum))) + + work = Work() + + work.Op = Operation.Divide + work.Num1 = 1 + work.Num2 = 0 + + try: + quotient = client.Calculate(1, work) + print('Whoa? You know how to divide by zero?') + print('FYI the answer is %d' % quotient) + except InvalidOperation as e: + print(('InvalidOperation: %r' % e)) + + work.Op = Operation.Substract + work.Num1 = 15 + work.Num2 = 10 + + diff = client.Calculate(1, work) + print(('15-10=%d' % (diff))) + + log = client.GetStruct(1) + print(('Check log: %s' % (log.Value))) + + client.Zip() + print('zip()') + + # Close! + transport.close() + +if __name__ == '__main__': + try: + main() + except Thrift.TException as tx: + print('%s' % tx.message) +``` + + +**Python Server:** + + +```python +import glob +import sys +sys.path.append('gen-py') + +from tutorial import Calculator +from tutorial.ttypes import InvalidOperation, Operation + +from shared.ttypes import SharedStruct + +from thrift.transport import TSocket +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol +from thrift.server import TServer + + +class CalculatorHandler: + def __init__(self): + self.log = {} + + def Ping(self): + print('ping()') + + def Add(self, n1, n2): + print('add(%d,%d)' % (n1, n2)) + return n1 + n2 + + def Calculate(self, logid, work): + print('calculate(%d, %r)' % (logid, work)) + + if work.Op == Operation.Add: + val = work.Num1 + work.Num2 + elif work.Op == Operation.Substract: + val = work.Num1 - work.Num2 + elif work.Op == Operation.Multiply: + val = work.Num1 * work.Num2 + elif work.Op == Operation.Divide: + if work.Num2 == 0: + x = InvalidOperation() + x.WhatOp = work.Op + x.Why = 'Cannot divide by 0' + raise x + val = work.Num1 / work.Num2 + else: + x = InvalidOperation() + x.WhatOp = work.Op + x.Why = 'Invalid operation' + raise x + + log = SharedStruct() + log.Key = logid + log.Value = '%d' % (val) + self.log[logid] = log + + return val + + def GetStruct(self, key): + print('getStruct(%d)' % (key)) + return self.log[key] + + def Zip(self): + print('zip()') + +if __name__ == '__main__': + handler = CalculatorHandler() + processor = Calculator.Processor(handler) + transport = TSocket.TServerSocket(host="testserver", port=9090) + tfactory = TTransport.TBufferedTransportFactory() + pfactory = TBinaryProtocol.TBinaryProtocolFactory() + + server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) + print('Starting the server...') + server.serve() + print('done.') + + # You could do one of these for a multithreaded server + # server = TServer.TThreadedServer(processor, transport, tfactory, pfactory) + # server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory) +``` diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs new file mode 100644 index 00000000000..9a650c5aa74 --- /dev/null +++ b/tutorial/netstd/Server/Program.cs @@ -0,0 +1,429 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Thrift; +using Thrift.Protocol; +using Thrift.Server; +using Thrift.Transport; +using Thrift.Transport.Server; +using tutorial; +using shared; +using Thrift.Processor; + +namespace Server +{ + public class Program + { + private static readonly ILogger Logger = new LoggerFactory().AddConsole(LogLevel.Trace).AddDebug(LogLevel.Trace).CreateLogger(nameof(Server)); + + public static void Main(string[] args) + { + args = args ?? new string[0]; + + if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) + { + DisplayHelp(); + return; + } + + using (var source = new CancellationTokenSource()) + { + RunAsync(args, source.Token).GetAwaiter().GetResult(); + + Logger.LogInformation("Press any key to stop..."); + + Console.ReadLine(); + source.Cancel(); + } + + Logger.LogInformation("Server stopped"); + } + + private static void DisplayHelp() + { + Logger.LogInformation(@" +Usage: + Server.exe -help + will diplay help information + + Server.exe -tr: -pr: + will run server with specified arguments (tcp transport and binary protocol by default) + +Options: + -tr (transport): + tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) + tcpbuffered - tcp buffered transport will be used (host - ""localhost"", port - 9090) + namedpipe - namedpipe transport will be used (pipe address - "".test"") + http - http transport will be used (http address - ""localhost:9090"") + tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) + framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -pr (protocol): + binary - (default) binary protocol will be used + compact - compact protocol will be used + json - json protocol will be used + multiplexed - multiplexed protocol will be used + +Sample: + Server.exe -tr:tcp +"); + } + + private static async Task RunAsync(string[] args, CancellationToken cancellationToken) + { + var selectedTransport = GetTransport(args); + var selectedProtocol = GetProtocol(args); + + if (selectedTransport == Transport.Http) + { + new HttpServerSample().Run(cancellationToken); + } + else + { + await RunSelectedConfigurationAsync(selectedTransport, selectedProtocol, cancellationToken); + } + } + + private static Protocol GetProtocol(string[] args) + { + var transport = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; + + Enum.TryParse(transport, true, out Protocol selectedProtocol); + + return selectedProtocol; + } + + private static Transport GetTransport(string[] args) + { + var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; + + Enum.TryParse(transport, true, out Transport selectedTransport); + + return selectedTransport; + } + + private static async Task RunSelectedConfigurationAsync(Transport transport, Protocol protocol, CancellationToken cancellationToken) + { + var fabric = new LoggerFactory().AddConsole(LogLevel.Trace).AddDebug(LogLevel.Trace); + var handler = new CalculatorAsyncHandler(); + ITAsyncProcessor processor = null; + + TServerTransport serverTransport = null; + + switch (transport) + { + case Transport.Tcp: + serverTransport = new TServerSocketTransport(9090); + break; + case Transport.TcpBuffered: + serverTransport = new TServerSocketTransport(port: 9090, clientTimeout: 10000, useBufferedSockets: true); + break; + case Transport.NamedPipe: + serverTransport = new TNamedPipeServerTransport(".test"); + break; + case Transport.TcpTls: + serverTransport = new TTlsServerSocketTransport(9090, false, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback); + break; + case Transport.Framed: + serverTransport = new TServerFramedTransport(9090); + break; + } + + ITProtocolFactory inputProtocolFactory; + ITProtocolFactory outputProtocolFactory; + + switch (protocol) + { + case Protocol.Binary: + { + inputProtocolFactory = new TBinaryProtocol.Factory(); + outputProtocolFactory = new TBinaryProtocol.Factory(); + processor = new Calculator.AsyncProcessor(handler); + } + break; + case Protocol.Compact: + { + inputProtocolFactory = new TCompactProtocol.Factory(); + outputProtocolFactory = new TCompactProtocol.Factory(); + processor = new Calculator.AsyncProcessor(handler); + } + break; + case Protocol.Json: + { + inputProtocolFactory = new TJsonProtocol.Factory(); + outputProtocolFactory = new TJsonProtocol.Factory(); + processor = new Calculator.AsyncProcessor(handler); + } + break; + case Protocol.Multiplexed: + { + inputProtocolFactory = new TBinaryProtocol.Factory(); + outputProtocolFactory = new TBinaryProtocol.Factory(); + + var calcHandler = new CalculatorAsyncHandler(); + var calcProcessor = new Calculator.AsyncProcessor(calcHandler); + + var sharedServiceHandler = new SharedServiceAsyncHandler(); + var sharedServiceProcessor = new SharedService.AsyncProcessor(sharedServiceHandler); + + var multiplexedProcessor = new TMultiplexedProcessor(); + multiplexedProcessor.RegisterProcessor(nameof(Calculator), calcProcessor); + multiplexedProcessor.RegisterProcessor(nameof(SharedService), sharedServiceProcessor); + + processor = multiplexedProcessor; + } + break; + default: + throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null); + } + + try + { + Logger.LogInformation( + $"Selected TAsyncServer with {serverTransport} transport, {processor} processor and {inputProtocolFactory} protocol factories"); + + var server = new TSimpleAsyncServer(processor, serverTransport, inputProtocolFactory, outputProtocolFactory, fabric); + + Logger.LogInformation("Starting the server..."); + await server.ServeAsync(cancellationToken); + } + catch (Exception x) + { + Logger.LogInformation(x.ToString()); + } + } + + private static X509Certificate2 GetCertificate() + { + // due to files location in net core better to take certs from top folder + var certFile = GetCertPath(Directory.GetParent(Directory.GetCurrentDirectory())); + return new X509Certificate2(certFile, "ThriftTest"); + } + + private static string GetCertPath(DirectoryInfo di, int maxCount = 6) + { + var topDir = di; + var certFile = + topDir.EnumerateFiles("ThriftTest.pfx", SearchOption.AllDirectories) + .FirstOrDefault(); + if (certFile == null) + { + if (maxCount == 0) + throw new FileNotFoundException("Cannot find file in directories"); + return GetCertPath(di.Parent, maxCount - 1); + } + + return certFile.FullName; + } + + private static X509Certificate LocalCertificateSelectionCallback(object sender, + string targetHost, X509CertificateCollection localCertificates, + X509Certificate remoteCertificate, string[] acceptableIssuers) + { + return GetCertificate(); + } + + private static bool ClientCertValidator(object sender, X509Certificate certificate, + X509Chain chain, SslPolicyErrors sslPolicyErrors) + { + return true; + } + + private enum Transport + { + Tcp, + TcpBuffered, + NamedPipe, + Http, + TcpTls, + Framed + } + + private enum Protocol + { + Binary, + Compact, + Json, + Multiplexed + } + + public class HttpServerSample + { + public void Run(CancellationToken cancellationToken) + { + var config = new ConfigurationBuilder() + .AddEnvironmentVariables(prefix: "ASPNETCORE_") + .Build(); + + var host = new WebHostBuilder() + .UseConfiguration(config) + .UseKestrel() + .UseUrls("http://localhost:9090") + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseStartup() + .Build(); + + host.RunAsync(cancellationToken).GetAwaiter().GetResult(); + } + + public class Startup + { + public Startup(IHostingEnvironment env) + { + var builder = new ConfigurationBuilder() + .SetBasePath(env.ContentRootPath) + .AddEnvironmentVariables(); + + Configuration = builder.Build(); + } + + public IConfigurationRoot Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, + ILoggerFactory loggerFactory) + { + app.UseMiddleware(); + } + } + } + + public class CalculatorAsyncHandler : Calculator.IAsync + { + private readonly Dictionary _log = new Dictionary(); + + public CalculatorAsyncHandler() + { + } + + public async Task getStructAsync(int key, + CancellationToken cancellationToken) + { + Logger.LogInformation("GetStructAsync({0})", key); + return await Task.FromResult(_log[key]); + } + + public async Task pingAsync(CancellationToken cancellationToken) + { + Logger.LogInformation("PingAsync()"); + await Task.CompletedTask; + } + + public async Task addAsync(int num1, int num2, CancellationToken cancellationToken) + { + Logger.LogInformation($"AddAsync({num1},{num2})"); + return await Task.FromResult(num1 + num2); + } + + public async Task calculateAsync(int logid, Work w, CancellationToken cancellationToken) + { + Logger.LogInformation($"CalculateAsync({logid}, [{w.Op},{w.Num1},{w.Num2}])"); + + var val = 0; + switch (w.Op) + { + case Operation.ADD: + val = w.Num1 + w.Num2; + break; + + case Operation.SUBTRACT: + val = w.Num1 - w.Num2; + break; + + case Operation.MULTIPLY: + val = w.Num1 * w.Num2; + break; + + case Operation.DIVIDE: + if (w.Num2 == 0) + { + var io = new InvalidOperation + { + WhatOp = (int) w.Op, + Why = "Cannot divide by 0" + }; + + throw io; + } + val = w.Num1 / w.Num2; + break; + + default: + { + var io = new InvalidOperation + { + WhatOp = (int) w.Op, + Why = "Unknown operation" + }; + + throw io; + } + } + + var entry = new SharedStruct + { + Key = logid, + Value = val.ToString() + }; + + _log[logid] = entry; + + return await Task.FromResult(val); + } + + public async Task zipAsync(CancellationToken cancellationToken) + { + Logger.LogInformation("ZipAsync() with delay 100mc"); + await Task.Delay(100, CancellationToken.None); + } + } + + public class SharedServiceAsyncHandler : SharedService.IAsync + { + public async Task getStructAsync(int key, CancellationToken cancellationToken) + { + Logger.LogInformation("GetStructAsync({0})", key); + return await Task.FromResult(new SharedStruct() + { + Key = key, + Value = "GetStructAsync" + }); + } + } + } +} diff --git a/tutorial/netstd/Server/Properties/AssemblyInfo.cs b/tutorial/netstd/Server/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..a0442350bd9 --- /dev/null +++ b/tutorial/netstd/Server/Properties/AssemblyInfo.cs @@ -0,0 +1,40 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("The Apache Software Foundation")] +[assembly: AssemblyProduct("Thrift")] +[assembly: AssemblyCopyright("The Apache Software Foundation")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly: Guid("e210fc10-5aff-4b04-ac21-58afc7b74b0c")] \ No newline at end of file diff --git a/tutorial/netstd/Server/Properties/launchSettings.json b/tutorial/netstd/Server/Properties/launchSettings.json new file mode 100644 index 00000000000..78076ff7cf5 --- /dev/null +++ b/tutorial/netstd/Server/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Server": { + "commandName": "Project", + "commandLineArgs": "-p:multiplexed" + } + } +} \ No newline at end of file diff --git a/tutorial/netstd/Server/Server.csproj b/tutorial/netstd/Server/Server.csproj new file mode 100644 index 00000000000..4b20a3b055a --- /dev/null +++ b/tutorial/netstd/Server/Server.csproj @@ -0,0 +1,44 @@ + + + + + netcoreapp2.0 + Server + Server + Exe + false + false + false + false + + + + + + + + + + + + + + + diff --git a/tutorial/netstd/Server/ThriftTest.pfx b/tutorial/netstd/Server/ThriftTest.pfx new file mode 100644 index 0000000000000000000000000000000000000000..f0ded28173dc2c33cebbb2b74e1e9e9e870b5876 GIT binary patch literal 2661 zcmY+Fc{r5q7ssC&Gb1!J$(kiQNi-_kNTzK}lBB4-#%>tDNgCV8K7;IKOK6d75tC&a zp={ZTH)}K@WXZmpv83PB^)A`wF(pXt7XpsY=bHUSlV3;5-A{d&ZS=A9rAjL!JLlxE zU_0M6u}dL5dyZUM*eZRTK7%!HnQk@RhDO-B4XYapVO%Fw7K^smqmrq9#TGaL=NEIm z?!`FK&>hR?Z@)%UKPau-%?m`A(>#}=i#q*6>Xe+P#mwBs6Q0@@Ixp|5@9I+wut zA#tRevtir~_G0T(aAFKzvy!O$=C`*W)A|(nrt(YY1n}Kp^LEZq_lyzXl)hwOG@G=i zxbiB-SnTQD^sz>x%QCdt1fw!Er?MpQ>#O~U^B1Ih|GdFM1{`4ISt#RHN4|ZYyq|=< z{j;$~n=*954;otf@)^47LvcfPIKt$_Y2BL+D}7sV7s{aov!F89pkkhg#@d`RVvtv8 zqhf(QFGtL@?Vi^c`LJWbZE9|TN_1?X9?l3DaIjMO5`V9F;~;j1FwiWFV#DZK zPZjSTs!0RAwSeaugCPfE_z~82e~?}o;1!SDpMJeV`Q?+Y@TQRE z%jhKjwXIG1?LW{8%1ry~$CvoFtuttc!kQ${aiZfTlsc}(9#g1pD3VzLU3ij7h2^CD z;6Lz8^m(Xe5?)8Y0Gr#QxBP*P)`mX~ycEnzpRed9N46To2eUk?5^Lp}$Xu=>65C8xu{J&6G(`>&f z-~~7X>HrGR1atr=u0{d&fFqaa0!O&99#K(?2gPlgcy9MFU_Ez}9Obs^@?Q}%0v{+j;MU>669QYwovF;u<-Oys<_RI{b3>F|lw0+!xJ>$_T%M|8 z*-&MWR7IRjyg|Rdz}Y^1c3>+=Wp`aAotnEcJk{mR2!9S=p@lzc?XYcYm9LJXMtHbTOVA7ageNhdBfi0|v1eLr9PtqI`)XEsA zC0p*r#f2MT4Hybzy5V<-3)*Qcno)THYn1lrjq6Dik zc86XkszLcvn;9QTVpJ9nk<@$OqssciMrRF6FvCqZbspu(u*qkj2*`%Mz8yK zJdDp2+luWj&vuSBXbE_thM;=6A| zTxptZh*kG4;p+`oVSXP~RY=Ckmncb%Q_UISo?$+pr{w0qs^nnM(Hjvem6Iv&+#MtM zv{NJq4}S()s9l6QL`u&D)**e1PVG7Kle}4G&E6j*6WUk@Gf{A7t$m7Kzgxiio)Vux zaUZfKT(@FZ>2x``Vy-=XKo?(27vH5gZ(9I{TgrlFvqh3z9qJGySLfwbj9a-H4Nq*qFpUg@ld}K z)hFz#CqBwVT7Rl=a|*hQAa-`0o9X{L*g@fX}@vnbf G^#21?=Cu0& literal 0 HcmV?d00001 diff --git a/tutorial/netstd/Tutorial.sln b/tutorial/netstd/Tutorial.sln new file mode 100644 index 00000000000..84b25790269 --- /dev/null +++ b/tutorial/netstd/Tutorial.sln @@ -0,0 +1,78 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26114.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netstd\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Interfaces", "Interfaces\Interfaces.csproj", "{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.ActiveCfg = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.Build.0 = Debug|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU + {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.ActiveCfg = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.Build.0 = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.ActiveCfg = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.Build.0 = Debug|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.Build.0 = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.ActiveCfg = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.Build.0 = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.ActiveCfg = Release|Any CPU + {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.Build.0 = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.ActiveCfg = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.Build.0 = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.ActiveCfg = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.Build.0 = Debug|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.Build.0 = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.ActiveCfg = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.Build.0 = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.ActiveCfg = Release|Any CPU + {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.Build.0 = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.ActiveCfg = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.Build.0 = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.ActiveCfg = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.Build.0 = Debug|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.Build.0 = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.ActiveCfg = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.Build.0 = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.ActiveCfg = Release|Any CPU + {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {070A5D1D-B29D-4603-999D-693DB444AD0D} + EndGlobalSection +EndGlobal diff --git a/tutorial/netstd/build.cmd b/tutorial/netstd/build.cmd new file mode 100644 index 00000000000..9b84ef27606 --- /dev/null +++ b/tutorial/netstd/build.cmd @@ -0,0 +1,25 @@ +@echo off +rem /* +rem * Licensed to the Apache Software Foundation (ASF) under one +rem * or more contributor license agreements. See the NOTICE file +rem * distributed with this work for additional information +rem * regarding copyright ownership. The ASF licenses this file +rem * to you under the Apache License, Version 2.0 (the +rem * "License"); you may not use this file except in compliance +rem * with the License. You may obtain a copy of the License at +rem * +rem * http://www.apache.org/licenses/LICENSE-2.0 +rem * +rem * Unless required by applicable law or agreed to in writing, +rem * software distributed under the License is distributed on an +rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +rem * KIND, either express or implied. See the License for the +rem * specific language governing permissions and limitations +rem * under the License. +rem */ +setlocal + +dotnet --info +dotnet build + +:eof diff --git a/tutorial/netstd/build.sh b/tutorial/netstd/build.sh new file mode 100644 index 00000000000..c97e310f011 --- /dev/null +++ b/tutorial/netstd/build.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +#exit if any command fails +set -e + +dotnet --info +dotnet build diff --git a/tutorial/shared.thrift b/tutorial/shared.thrift index f1685bd1618..5747f06bfc3 100644 --- a/tutorial/shared.thrift +++ b/tutorial/shared.thrift @@ -31,6 +31,8 @@ namespace perl shared namespace php shared namespace haxe shared namespace netcore shared +namespace netstd shared + struct SharedStruct { 1: i32 key diff --git a/tutorial/tutorial.thrift b/tutorial/tutorial.thrift index e0275464440..ea18b73ddce 100644 --- a/tutorial/tutorial.thrift +++ b/tutorial/tutorial.thrift @@ -72,6 +72,7 @@ namespace php tutorial namespace perl tutorial namespace haxe tutorial namespace netcore tutorial +namespace netstd tutorial /** * Thrift lets you do typedefs to get pretty names for your types. Standard From 042580f53441efe1bc5c80c89351fcb30740659e Mon Sep 17 00:00:00 2001 From: Sebastian Zenker Date: Tue, 29 Jan 2019 15:48:12 +0100 Subject: [PATCH 189/756] THRIFT-4762: Applied some C++11 refactorings to the runtime library and compiler (#1719) * make use of C++11 override keyword * added const specifier to TTransport::getOrigin() * added more const correctness to the compiler * make use of auto keyword * replaced usage of NULL with nullptr * make use of explicitly-defaulted function definition * extended changelog --- CHANGES.md | 1 + compiler/cpp/src/thrift/audit/t_audit.cpp | 30 +-- .../thrift/generate/t_generator_registry.h | 8 +- compiler/cpp/src/thrift/main.h | 2 +- compiler/cpp/src/thrift/parse/parse.cc | 6 +- compiler/cpp/src/thrift/parse/t_base_type.h | 10 +- compiler/cpp/src/thrift/parse/t_const_value.h | 10 +- compiler/cpp/src/thrift/parse/t_container.h | 4 +- compiler/cpp/src/thrift/parse/t_doc.h | 2 +- compiler/cpp/src/thrift/parse/t_enum.h | 20 +- compiler/cpp/src/thrift/parse/t_enum_value.h | 2 +- compiler/cpp/src/thrift/parse/t_field.h | 14 +- compiler/cpp/src/thrift/parse/t_function.h | 4 +- compiler/cpp/src/thrift/parse/t_list.h | 2 +- compiler/cpp/src/thrift/parse/t_map.h | 2 +- compiler/cpp/src/thrift/parse/t_program.h | 49 +++-- compiler/cpp/src/thrift/parse/t_scope.h | 39 +++- compiler/cpp/src/thrift/parse/t_service.h | 4 +- compiler/cpp/src/thrift/parse/t_set.h | 6 +- compiler/cpp/src/thrift/parse/t_struct.h | 22 +- compiler/cpp/src/thrift/parse/t_type.h | 6 +- compiler/cpp/src/thrift/parse/t_typedef.cc | 8 +- compiler/cpp/src/thrift/parse/t_typedef.h | 10 +- lib/c_glib/test/testthrifttestclient.cpp | 192 +++++++++--------- lib/cpp/README.md | 4 + lib/cpp/src/thrift/TApplicationException.h | 4 +- lib/cpp/src/thrift/TBase.h | 2 +- lib/cpp/src/thrift/TDispatchProcessor.h | 12 +- lib/cpp/src/thrift/TOutput.cpp | 2 +- lib/cpp/src/thrift/TProcessor.h | 18 +- lib/cpp/src/thrift/Thrift.h | 8 +- .../src/thrift/async/TAsyncBufferProcessor.h | 2 +- lib/cpp/src/thrift/async/TAsyncChannel.h | 2 +- .../thrift/async/TAsyncDispatchProcessor.h | 12 +- lib/cpp/src/thrift/async/TAsyncProcessor.h | 6 +- .../thrift/async/TAsyncProtocolProcessor.h | 6 +- .../async/TConcurrentClientSyncInfo.cpp | 4 +- .../src/thrift/async/TEvhttpClientChannel.cpp | 12 +- .../src/thrift/async/TEvhttpClientChannel.h | 22 +- lib/cpp/src/thrift/async/TEvhttpServer.cpp | 24 +-- lib/cpp/src/thrift/concurrency/Exception.h | 4 +- .../src/thrift/concurrency/FunctionRunner.h | 2 +- lib/cpp/src/thrift/concurrency/Monitor.cpp | 12 +- lib/cpp/src/thrift/concurrency/Mutex.h | 8 +- lib/cpp/src/thrift/concurrency/Thread.h | 2 +- .../src/thrift/concurrency/ThreadManager.cpp | 56 ++--- .../src/thrift/concurrency/ThreadManager.h | 4 +- .../src/thrift/concurrency/TimerManager.cpp | 16 +- .../src/thrift/processor/PeekProcessor.cpp | 3 +- lib/cpp/src/thrift/processor/PeekProcessor.h | 6 +- .../thrift/processor/TMultiplexedProcessor.h | 6 +- lib/cpp/src/thrift/protocol/TBinaryProtocol.h | 4 +- .../src/thrift/protocol/TBinaryProtocol.tcc | 12 +- .../src/thrift/protocol/TCompactProtocol.h | 14 +- .../src/thrift/protocol/TCompactProtocol.tcc | 16 +- lib/cpp/src/thrift/protocol/TDebugProtocol.h | 8 +- lib/cpp/src/thrift/protocol/THeaderProtocol.h | 12 +- lib/cpp/src/thrift/protocol/TJSONProtocol.cpp | 27 ++- lib/cpp/src/thrift/protocol/TJSONProtocol.h | 10 +- .../thrift/protocol/TMultiplexedProtocol.h | 4 +- lib/cpp/src/thrift/protocol/TProtocol.cpp | 4 +- lib/cpp/src/thrift/protocol/TProtocol.h | 4 +- .../src/thrift/protocol/TProtocolDecorator.h | 94 ++++----- .../src/thrift/protocol/TProtocolException.h | 4 +- .../src/thrift/protocol/TVirtualProtocol.h | 96 ++++----- lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp | 2 +- lib/cpp/src/thrift/qt/TQIODeviceTransport.h | 10 +- lib/cpp/src/thrift/qt/TQTcpServer.cpp | 7 +- lib/cpp/src/thrift/qt/TQTcpServer.h | 4 +- .../src/thrift/server/TConnectedClient.cpp | 5 +- lib/cpp/src/thrift/server/TConnectedClient.h | 4 +- .../src/thrift/server/TNonblockingServer.cpp | 52 ++--- .../src/thrift/server/TNonblockingServer.h | 12 +- lib/cpp/src/thrift/server/TServer.h | 10 +- .../src/thrift/server/TServerFramework.cpp | 3 +- lib/cpp/src/thrift/server/TServerFramework.h | 6 +- lib/cpp/src/thrift/server/TSimpleServer.cpp | 3 +- lib/cpp/src/thrift/server/TSimpleServer.h | 8 +- .../src/thrift/server/TThreadPoolServer.cpp | 3 +- lib/cpp/src/thrift/server/TThreadPoolServer.h | 8 +- lib/cpp/src/thrift/server/TThreadedServer.cpp | 12 +- lib/cpp/src/thrift/server/TThreadedServer.h | 12 +- .../thrift/transport/TBufferTransports.cpp | 28 +-- .../src/thrift/transport/TBufferTransports.h | 78 +++---- lib/cpp/src/thrift/transport/TFDTransport.h | 6 +- .../src/thrift/transport/TFileTransport.cpp | 46 ++--- lib/cpp/src/thrift/transport/TFileTransport.h | 28 +-- .../src/thrift/transport/THeaderTransport.cpp | 22 +- .../src/thrift/transport/THeaderTransport.h | 14 +- lib/cpp/src/thrift/transport/THttpClient.cpp | 9 +- lib/cpp/src/thrift/transport/THttpClient.h | 6 +- lib/cpp/src/thrift/transport/THttpServer.cpp | 13 +- lib/cpp/src/thrift/transport/THttpServer.h | 10 +- .../src/thrift/transport/THttpTransport.cpp | 16 +- lib/cpp/src/thrift/transport/THttpTransport.h | 14 +- .../transport/TNonblockingSSLServerSocket.h | 2 +- .../transport/TNonblockingServerSocket.cpp | 14 +- .../transport/TNonblockingServerSocket.h | 10 +- .../transport/TNonblockingServerTransport.h | 4 +- .../src/thrift/transport/TSSLServerSocket.h | 2 +- lib/cpp/src/thrift/transport/TSSLSocket.cpp | 72 +++---- lib/cpp/src/thrift/transport/TSSLSocket.h | 30 +-- .../src/thrift/transport/TServerSocket.cpp | 20 +- lib/cpp/src/thrift/transport/TServerSocket.h | 14 +- .../src/thrift/transport/TServerTransport.h | 4 +- .../thrift/transport/TShortReadTransport.h | 8 +- lib/cpp/src/thrift/transport/TSocket.cpp | 36 ++-- lib/cpp/src/thrift/transport/TSocket.h | 18 +- lib/cpp/src/thrift/transport/TSocketPool.cpp | 4 +- lib/cpp/src/thrift/transport/TSocketPool.h | 6 +- lib/cpp/src/thrift/transport/TTransport.h | 12 +- .../thrift/transport/TTransportException.h | 4 +- .../src/thrift/transport/TTransportUtils.cpp | 11 +- .../src/thrift/transport/TTransportUtils.h | 60 +++--- .../src/thrift/transport/TVirtualTransport.h | 6 +- .../src/thrift/transport/TZlibTransport.cpp | 2 +- lib/cpp/src/thrift/transport/TZlibTransport.h | 30 +-- lib/cpp/test/Benchmark.cpp | 10 +- lib/cpp/test/EnumTest.cpp | 2 +- lib/cpp/test/OneWayHTTPTest.cpp | 24 +-- lib/cpp/test/OpenSSLManualInitTest.cpp | 2 +- lib/cpp/test/RecursiveTest.cpp | 8 +- lib/cpp/test/TFileTransportTest.cpp | 26 +-- lib/cpp/test/TNonblockingSSLServerTest.cpp | 20 +- lib/cpp/test/TNonblockingServerTest.cpp | 20 +- lib/cpp/test/TServerIntegrationTest.cpp | 28 +-- lib/cpp/test/TServerTransportTest.cpp | 4 +- lib/cpp/test/TransportTest.cpp | 74 +++---- lib/cpp/test/ZlibTest.cpp | 16 +- lib/cpp/test/concurrency/Tests.cpp | 2 +- lib/cpp/test/concurrency/ThreadFactoryTests.h | 8 +- lib/cpp/test/concurrency/ThreadManagerTests.h | 10 +- lib/cpp/test/concurrency/TimerManagerTests.h | 8 +- lib/cpp/test/processor/EventLog.cpp | 2 +- lib/cpp/test/processor/Handlers.h | 68 +++---- lib/cpp/test/processor/ProcessorTest.cpp | 16 +- lib/cpp/test/processor/ServerThread.h | 6 +- lib/cpp/test/qt/TQTcpServerTest.cpp | 20 +- test/cpp/src/StressTest.cpp | 26 +-- test/cpp/src/StressTestNonBlocking.cpp | 24 +-- test/cpp/src/TestClient.cpp | 8 +- test/cpp/src/TestServer.cpp | 140 ++++++------- tutorial/cpp/CppServer.cpp | 18 +- 143 files changed, 1231 insertions(+), 1200 deletions(-) mode change 100755 => 100644 lib/c_glib/test/testthrifttestclient.cpp diff --git a/CHANGES.md b/CHANGES.md index dcba6d12dd8..b77003bcaa6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -27,6 +27,7 @@ - [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - java: class org.apache.thrift.ShortStack is no longer public - [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - java: change return type signature of 'process' methods - [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - js: now uses node-int64 for 64 bit integer constants +- [THRIFT-4672](https://issues.apache.org/jira/browse/THRIFT-4672) - C++: TTransport::getOrigin() is now const ### Known Issues (Blocker or Critical) diff --git a/compiler/cpp/src/thrift/audit/t_audit.cpp b/compiler/cpp/src/thrift/audit/t_audit.cpp index ef39d60c302..4ae9a1fcec0 100644 --- a/compiler/cpp/src/thrift/audit/t_audit.cpp +++ b/compiler/cpp/src/thrift/audit/t_audit.cpp @@ -54,11 +54,11 @@ void compare_namespace(t_program* newProgram, t_program* oldProgram) const std::map& newNamespaceMap = newProgram->get_all_namespaces(); const std::map& oldNamespaceMap = oldProgram->get_all_namespaces(); - for(std::map::const_iterator oldNamespaceMapIt = oldNamespaceMap.begin(); + for(auto oldNamespaceMapIt = oldNamespaceMap.begin(); oldNamespaceMapIt != oldNamespaceMap.end(); oldNamespaceMapIt++) { - std::map::const_iterator newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt->first); + auto newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt->first); if(newNamespaceMapIt == newNamespaceMap.end()) { thrift_audit_warning(1, "Language %s not found in new thrift file\n", (oldNamespaceMapIt->first).c_str()); @@ -73,13 +73,13 @@ void compare_namespace(t_program* newProgram, t_program* oldProgram) void compare_enum_values(t_enum* newEnum,t_enum* oldEnum) { const std::vector& oldEnumValues = oldEnum->get_constants(); - for(std::vector::const_iterator oldEnumValuesIt = oldEnumValues.begin(); + for(auto oldEnumValuesIt = oldEnumValues.begin(); oldEnumValuesIt != oldEnumValues.end(); oldEnumValuesIt++) { int enumValue = (*oldEnumValuesIt)->get_value(); t_enum_value* newEnumValue = newEnum->get_constant_by_value(enumValue); - if(newEnumValue != NULL) + if(newEnumValue != nullptr) { std::string enumName = (*oldEnumValuesIt)->get_name(); if(enumName != newEnumValue->get_name()) @@ -175,9 +175,9 @@ bool compare_pair(std::pair newMapPair, std::pai // This function returns 'true' if the default values are same. Returns false if they are different. bool compare_defaults(t_const_value* newStructDefault, t_const_value* oldStructDefault) { - if(newStructDefault == NULL && oldStructDefault == NULL) return true; - else if(newStructDefault == NULL && oldStructDefault != NULL) return false; - else if (newStructDefault != NULL && oldStructDefault == NULL) return false; + if(newStructDefault == nullptr && oldStructDefault == nullptr) return true; + else if(newStructDefault == nullptr && oldStructDefault != nullptr) return false; + else if (newStructDefault != nullptr && oldStructDefault == nullptr) return false; if(newStructDefault->get_type() != oldStructDefault->get_type()) { @@ -255,8 +255,8 @@ void compare_single_struct(t_struct* newStruct, t_struct* oldStruct, const std:: std::string structName = oldStructName.empty() ? oldStruct->get_name() : oldStructName; const std::vector& oldStructMembersInIdOrder = oldStruct->get_sorted_members(); const std::vector& newStructMembersInIdOrder = newStruct->get_sorted_members(); - std::vector::const_iterator oldStructMemberIt = oldStructMembersInIdOrder.begin(); - std::vector::const_iterator newStructMemberIt = newStructMembersInIdOrder.begin(); + auto oldStructMemberIt = oldStructMembersInIdOrder.begin(); + auto newStructMemberIt = newStructMembersInIdOrder.begin(); // Since we have the struct members in their ID order, comparing their IDs can be done by traversing the two member // lists together. @@ -352,14 +352,14 @@ void compare_functions(const std::vector& newFunctionList, const st { std::map newFunctionMap; std::map::iterator newFunctionMapIt; - for(std::vector::const_iterator newFunctionIt = newFunctionList.begin(); + for(auto newFunctionIt = newFunctionList.begin(); newFunctionIt != newFunctionList.end(); newFunctionIt++) { newFunctionMap[(*newFunctionIt)->get_name()] = *newFunctionIt; } - for(std::vector::const_iterator oldFunctionIt = oldFunctionList.begin(); + for(auto oldFunctionIt = oldFunctionList.begin(); oldFunctionIt != oldFunctionList.end(); oldFunctionIt++) { @@ -383,7 +383,7 @@ void compare_services(const std::vector& newServices, const std::vec std::vector::const_iterator oldServiceIt; std::map newServiceMap; - for(std::vector::const_iterator newServiceIt = newServices.begin(); + for(auto newServiceIt = newServices.begin(); newServiceIt != newServices.end(); newServiceIt++) { @@ -394,7 +394,7 @@ void compare_services(const std::vector& newServices, const std::vec for(oldServiceIt = oldServices.begin(); oldServiceIt != oldServices.end(); oldServiceIt++) { const std::string oldServiceName = (*oldServiceIt)->get_name(); - std::map::iterator newServiceMapIt = newServiceMap.find(oldServiceName); + auto newServiceMapIt = newServiceMap.find(oldServiceName); if(newServiceMapIt == newServiceMap.end()) { @@ -405,12 +405,12 @@ void compare_services(const std::vector& newServices, const std::vec t_service* oldServiceExtends = (*oldServiceIt)->get_extends(); t_service* newServiceExtends = (newServiceMapIt->second)->get_extends(); - if(oldServiceExtends == NULL) + if(oldServiceExtends == nullptr) { // It is fine to add extends. So if service in older thrift did not have any extends, we are fine. // DO Nothing } - else if(oldServiceExtends != NULL && newServiceExtends == NULL) + else if(oldServiceExtends != nullptr && newServiceExtends == nullptr) { thrift_audit_failure("Change in Service inheritance for %s\n", oldServiceName.c_str()); } diff --git a/compiler/cpp/src/thrift/generate/t_generator_registry.h b/compiler/cpp/src/thrift/generate/t_generator_registry.h index 1f02167bc11..d27f7108201 100644 --- a/compiler/cpp/src/thrift/generate/t_generator_registry.h +++ b/compiler/cpp/src/thrift/generate/t_generator_registry.h @@ -35,7 +35,7 @@ class t_generator_factory { const std::string& long_name, const std::string& documentation); - virtual ~t_generator_factory() {} + virtual ~t_generator_factory() = default; virtual t_generator* get_generator( // The program to generate. @@ -65,13 +65,13 @@ class t_generator_factory_impl : public t_generator_factory { const std::string& documentation) : t_generator_factory(short_name, long_name, documentation) {} - virtual t_generator* get_generator(t_program* program, + t_generator* get_generator(t_program* program, const std::map& parsed_options, - const std::string& option_string) { + const std::string& option_string) override { return new generator(program, parsed_options, option_string); } - virtual bool is_valid_namespace(const std::string& sub_namespace) { + bool is_valid_namespace(const std::string& sub_namespace) override { return generator::is_valid_namespace(sub_namespace); } }; diff --git a/compiler/cpp/src/thrift/main.h b/compiler/cpp/src/thrift/main.h index 54abb03c351..163b02e4ba7 100644 --- a/compiler/cpp/src/thrift/main.h +++ b/compiler/cpp/src/thrift/main.h @@ -106,7 +106,7 @@ void emit_byte_type_warning(); * If new_form is NULL, old_form is assumed to be a language identifier, such as "cpp" * If new_form is not NULL, both arguments are used exactly as given */ -void error_unsupported_namespace_decl(const char* old_form, const char* new_form = NULL); +void error_unsupported_namespace_decl(const char* old_form, const char* new_form = nullptr); /** * Flex utilities diff --git a/compiler/cpp/src/thrift/parse/parse.cc b/compiler/cpp/src/thrift/parse/parse.cc index 01f763751dc..23db61ccb33 100644 --- a/compiler/cpp/src/thrift/parse/parse.cc +++ b/compiler/cpp/src/thrift/parse/parse.cc @@ -23,11 +23,7 @@ #include "thrift/main.h" t_type* t_type::get_true_type() { - t_type* type = this; - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } - return type; + return const_cast(const_cast(this)->get_true_type()); } const t_type* t_type::get_true_type() const { diff --git a/compiler/cpp/src/thrift/parse/t_base_type.h b/compiler/cpp/src/thrift/parse/t_base_type.h index 71398ba70a6..ca2b0f6efcb 100644 --- a/compiler/cpp/src/thrift/parse/t_base_type.h +++ b/compiler/cpp/src/thrift/parse/t_base_type.h @@ -49,11 +49,11 @@ class t_base_type : public t_type { t_base get_base() const { return base_; } - bool is_void() const { return base_ == TYPE_VOID; } + bool is_void() const override { return base_ == TYPE_VOID; } - bool is_string() const { return base_ == TYPE_STRING; } + bool is_string() const override { return base_ == TYPE_STRING; } - bool is_bool() const { return base_ == TYPE_BOOL; } + bool is_bool() const override { return base_ == TYPE_BOOL; } void set_string_list(bool val) { string_list_ = val; } @@ -61,7 +61,7 @@ class t_base_type : public t_type { void set_binary(bool val) { binary_ = val; } - bool is_binary() const { return binary_ && (base_ == TYPE_STRING); } + bool is_binary() const override { return binary_ && (base_ == TYPE_STRING); } void set_string_enum(bool val) { string_enum_ = val; } @@ -71,7 +71,7 @@ class t_base_type : public t_type { const std::vector& get_string_enum_vals() const { return string_enum_vals_; } - bool is_base_type() const { return true; } + bool is_base_type() const override { return true; } static std::string t_base_name(t_base tbase) { switch (tbase) { diff --git a/compiler/cpp/src/thrift/parse/t_const_value.h b/compiler/cpp/src/thrift/parse/t_const_value.h index e5ecc1d6df6..5b8156f1ada 100644 --- a/compiler/cpp/src/thrift/parse/t_const_value.h +++ b/compiler/cpp/src/thrift/parse/t_const_value.h @@ -46,11 +46,11 @@ class t_const_value { enum t_const_value_type { CV_INTEGER, CV_DOUBLE, CV_STRING, CV_MAP, CV_LIST, CV_IDENTIFIER, CV_UNKNOWN }; - t_const_value() : intVal_(0), doubleVal_(0.0f), enum_((t_enum*)0), valType_(CV_UNKNOWN) {} + t_const_value() : intVal_(0), doubleVal_(0.0f), enum_((t_enum*)nullptr), valType_(CV_UNKNOWN) {} - t_const_value(int64_t val) : doubleVal_(0.0f), enum_((t_enum*)0), valType_(CV_UNKNOWN) { set_integer(val); } + t_const_value(int64_t val) : doubleVal_(0.0f), enum_((t_enum*)nullptr), valType_(CV_UNKNOWN) { set_integer(val); } - t_const_value(std::string val) : intVal_(0), doubleVal_(0.0f), enum_((t_enum*)0), valType_(CV_UNKNOWN) { set_string(val); } + t_const_value(std::string val) : intVal_(0), doubleVal_(0.0f), enum_((t_enum*)nullptr), valType_(CV_UNKNOWN) { set_string(val); } void set_string(std::string val) { valType_ = CV_STRING; @@ -66,7 +66,7 @@ class t_const_value { int64_t get_integer() const { if (valType_ == CV_IDENTIFIER) { - if (enum_ == NULL) { + if (enum_ == nullptr) { throw "have identifier \"" + get_identifier() + "\", but unset enum on line!"; } std::string identifier = get_identifier(); @@ -75,7 +75,7 @@ class t_const_value { identifier = identifier.substr(dot + 1); } t_enum_value* val = enum_->get_constant_by_name(identifier); - if (val == NULL) { + if (val == nullptr) { throw "Unable to find enum value \"" + identifier + "\" in enum \"" + enum_->get_name() + "\""; } diff --git a/compiler/cpp/src/thrift/parse/t_container.h b/compiler/cpp/src/thrift/parse/t_container.h index 5bdab70a7af..a124d31fdb5 100644 --- a/compiler/cpp/src/thrift/parse/t_container.h +++ b/compiler/cpp/src/thrift/parse/t_container.h @@ -26,7 +26,7 @@ class t_container : public t_type { public: t_container() : cpp_name_(), has_cpp_name_(false) {} - virtual ~t_container() {} + ~t_container() override = default; void set_cpp_name(std::string cpp_name) { cpp_name_ = cpp_name; @@ -37,7 +37,7 @@ class t_container : public t_type { std::string get_cpp_name() const { return cpp_name_; } - bool is_container() const { return true; } + bool is_container() const override { return true; } private: std::string cpp_name_; diff --git a/compiler/cpp/src/thrift/parse/t_doc.h b/compiler/cpp/src/thrift/parse/t_doc.h index 7bcb8f5e4b9..0df893eb263 100644 --- a/compiler/cpp/src/thrift/parse/t_doc.h +++ b/compiler/cpp/src/thrift/parse/t_doc.h @@ -31,7 +31,7 @@ class t_doc { public: t_doc() : has_doc_(false) {} - virtual ~t_doc() {} + virtual ~t_doc() = default; void set_doc(const std::string& doc) { doc_ = doc; diff --git a/compiler/cpp/src/thrift/parse/t_enum.h b/compiler/cpp/src/thrift/parse/t_enum.h index 9e23780cb84..3f013ee1f98 100644 --- a/compiler/cpp/src/thrift/parse/t_enum.h +++ b/compiler/cpp/src/thrift/parse/t_enum.h @@ -33,13 +33,13 @@ class t_enum : public t_type { public: t_enum(t_program* program) : t_type(program) {} - void set_name(const std::string& name) { name_ = name; } + void set_name(const std::string& name) override { name_ = name; } void append(t_enum_value* constant) { constants_.push_back(constant); } const std::vector& get_constants() const { return constants_; } - t_enum_value* get_constant_by_name(const std::string& name) { + t_enum_value* get_constant_by_name(const std::string& name) const { const std::vector& enum_values = get_constants(); std::vector::const_iterator c_iter; for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) { @@ -47,10 +47,10 @@ class t_enum : public t_type { return *c_iter; } } - return NULL; + return nullptr; } - t_enum_value* get_constant_by_value(int64_t value) { + t_enum_value* get_constant_by_value(int64_t value) const { const std::vector& enum_values = get_constants(); std::vector::const_iterator c_iter; for (c_iter = enum_values.begin(); c_iter != enum_values.end(); ++c_iter) { @@ -58,15 +58,15 @@ class t_enum : public t_type { return *c_iter; } } - return NULL; + return nullptr; } - t_enum_value* get_min_value() { + t_enum_value* get_min_value() const { const std::vector& enum_values = get_constants(); std::vector::const_iterator c_iter; t_enum_value* min_value; if (enum_values.size() == 0) { - min_value = NULL; + min_value = nullptr; } else { int min_value_value; min_value = enum_values.front(); @@ -81,12 +81,12 @@ class t_enum : public t_type { return min_value; } - t_enum_value* get_max_value() { + t_enum_value* get_max_value() const { const std::vector& enum_values = get_constants(); std::vector::const_iterator c_iter; t_enum_value* max_value; if (enum_values.size() == 0) { - max_value = NULL; + max_value = nullptr; } else { int max_value_value; max_value = enum_values.back(); @@ -101,7 +101,7 @@ class t_enum : public t_type { return max_value; } - bool is_enum() const { return true; } + bool is_enum() const override { return true; } private: std::vector constants_; diff --git a/compiler/cpp/src/thrift/parse/t_enum_value.h b/compiler/cpp/src/thrift/parse/t_enum_value.h index c0bf3adfcb7..70eee861831 100644 --- a/compiler/cpp/src/thrift/parse/t_enum_value.h +++ b/compiler/cpp/src/thrift/parse/t_enum_value.h @@ -34,7 +34,7 @@ class t_enum_value : public t_doc { public: t_enum_value(std::string name, int value) : name_(name), value_(value) {} - ~t_enum_value() {} + ~t_enum_value() override = default; const std::string& get_name() const { return name_; } diff --git a/compiler/cpp/src/thrift/parse/t_field.h b/compiler/cpp/src/thrift/parse/t_field.h index c5f1f800c73..4be87706dd9 100644 --- a/compiler/cpp/src/thrift/parse/t_field.h +++ b/compiler/cpp/src/thrift/parse/t_field.h @@ -41,10 +41,10 @@ class t_field : public t_doc { : type_(type), name_(name), key_(0), - value_(NULL), + value_(nullptr), xsd_optional_(false), xsd_nillable_(false), - xsd_attrs_(NULL), + xsd_attrs_(nullptr), reference_(false) {} t_field(t_type* type, std::string name, int32_t key) @@ -52,13 +52,13 @@ class t_field : public t_doc { name_(name), key_(key), req_(T_OPT_IN_REQ_OUT), - value_(NULL), + value_(nullptr), xsd_optional_(false), xsd_nillable_(false), - xsd_attrs_(NULL), + xsd_attrs_(nullptr), reference_(false) {} - ~t_field() {} + ~t_field() override = default; t_type* get_type() { return type_; } @@ -92,6 +92,8 @@ class t_field : public t_doc { t_struct* get_xsd_attrs() { return xsd_attrs_; } + const t_struct* get_xsd_attrs() const { return xsd_attrs_; } + /** * Comparator to sort fields in ascending order by key. * Make this a functor instead of a function to help GCC inline it. @@ -105,7 +107,7 @@ class t_field : public t_doc { std::map annotations_; - bool get_reference() { return reference_; } + bool get_reference() const { return reference_; } void set_reference(bool reference) { reference_ = reference; } diff --git a/compiler/cpp/src/thrift/parse/t_function.h b/compiler/cpp/src/thrift/parse/t_function.h index 22d26091a04..d30c8a46e62 100644 --- a/compiler/cpp/src/thrift/parse/t_function.h +++ b/compiler/cpp/src/thrift/parse/t_function.h @@ -37,7 +37,7 @@ class t_function : public t_doc { : returntype_(returntype), name_(name), arglist_(arglist), - xceptions_(new t_struct(NULL)), + xceptions_(new t_struct(nullptr)), own_xceptions_(true), oneway_(oneway) { if (oneway_ && (!returntype_->is_void())) { @@ -64,7 +64,7 @@ class t_function : public t_doc { } } - ~t_function() { + ~t_function() override { if (own_xceptions_) delete xceptions_; } diff --git a/compiler/cpp/src/thrift/parse/t_list.h b/compiler/cpp/src/thrift/parse/t_list.h index acf68653b2c..f0b896d0cb0 100644 --- a/compiler/cpp/src/thrift/parse/t_list.h +++ b/compiler/cpp/src/thrift/parse/t_list.h @@ -32,7 +32,7 @@ class t_list : public t_container { t_type* get_elem_type() const { return elem_type_; } - bool is_list() const { return true; } + bool is_list() const override { return true; } private: t_type* elem_type_; diff --git a/compiler/cpp/src/thrift/parse/t_map.h b/compiler/cpp/src/thrift/parse/t_map.h index dd3f089c197..9614e6849c6 100644 --- a/compiler/cpp/src/thrift/parse/t_map.h +++ b/compiler/cpp/src/thrift/parse/t_map.h @@ -35,7 +35,7 @@ class t_map : public t_container { t_type* get_val_type() const { return val_type_; } - bool is_map() const { return true; } + bool is_map() const override { return true; } private: t_type* key_type_; diff --git a/compiler/cpp/src/thrift/parse/t_program.h b/compiler/cpp/src/thrift/parse/t_program.h index 43dd45a6183..8b60611f8b2 100644 --- a/compiler/cpp/src/thrift/parse/t_program.h +++ b/compiler/cpp/src/thrift/parse/t_program.h @@ -65,10 +65,10 @@ class t_program : public t_doc { scope_ = new t_scope(); } - ~t_program() { + ~t_program() override { if (scope_) { delete scope_; - scope_ = NULL; + scope_ = nullptr; } } @@ -115,6 +115,8 @@ class t_program : public t_doc { void add_service(t_service* ts) { services_.push_back(ts); } // Programs to include + std::vector& get_includes() { return includes_; } + const std::vector& get_includes() const { return includes_; } void set_out_path(std::string out_path, bool out_path_is_absolute) { @@ -133,9 +135,9 @@ class t_program : public t_doc { * @param t the type to test for collisions * @return true if a certain collision was found, otherwise false */ - bool is_unique_typename(t_type* t) { + bool is_unique_typename(const t_type* t) const { int occurrences = program_typename_count(this, t); - for (std::vector::iterator it = includes_.begin(); it != includes_.end(); ++it) { + for (auto it = includes_.cbegin(); it != includes_.cend(); ++it) { occurrences += program_typename_count(*it, t); } return 0 == occurrences; @@ -147,7 +149,7 @@ class t_program : public t_doc { * @param t the type to test for collisions * @return the number of certain typename collisions */ - int program_typename_count(t_program* prog, t_type* t) { + int program_typename_count(const t_program* prog, const t_type* t) const { int occurrences = 0; occurrences += collection_typename_count(prog, prog->typedefs_, t); occurrences += collection_typename_count(prog, prog->enums_, t); @@ -164,9 +166,9 @@ class t_program : public t_doc { * @return the number of certain typename collisions */ template - int collection_typename_count(t_program* prog, T type_collection, t_type* t) { + int collection_typename_count(const t_program* prog, const T type_collection, const t_type* t) const { int occurrences = 0; - for (typename T::iterator it = type_collection.begin(); it != type_collection.end(); ++it) + for (auto it = type_collection.cbegin(); it != type_collection.cend(); ++it) if (t != *it && 0 == t->get_name().compare((*it)->get_name()) && is_common_namespace(prog, t)) ++occurrences; return occurrences; @@ -184,7 +186,7 @@ class t_program : public t_doc { * @param t the type containing the typename match * @return true if a collision within namespaces is found, otherwise false */ - bool is_common_namespace(t_program* prog, t_type* t) { + bool is_common_namespace(const t_program* prog, const t_type* t) const { // Case 1: Typenames are in the same program [collision] if (prog == t->get_program()) { pwarning(1, @@ -196,8 +198,8 @@ class t_program : public t_doc { // Case 2: Both programs have identical namespace scope/name declarations [collision] bool match = true; - for (std::map::iterator it = prog->namespaces_.begin(); - it != prog->namespaces_.end(); + for (auto it = prog->namespaces_.cbegin(); + it != prog->namespaces_.cend(); ++it) { if (0 == it->second.compare(t->get_program()->get_namespace(it->first))) { pwarning(1, @@ -213,8 +215,8 @@ class t_program : public t_doc { match = false; } } - for (std::map::iterator it = t->get_program()->namespaces_.begin(); - it != t->get_program()->namespaces_.end(); + for (auto it = t->get_program()->namespaces_.cbegin(); + it != t->get_program()->namespaces_.cend(); ++it) { if (0 == it->second.compare(prog->get_namespace(it->first))) { pwarning(1, @@ -244,7 +246,9 @@ class t_program : public t_doc { void set_namespace(std::string name) { namespace_ = name; } // Scope accessor - t_scope* scope() const { return scope_; } + t_scope* scope() { return scope_; } + + const t_scope* scope() const { return scope_; } // Includes @@ -267,8 +271,6 @@ class t_program : public t_doc { includes_.push_back(program); } - std::vector& get_includes() { return includes_; } - void set_include_prefix(std::string include_prefix) { include_prefix_ = include_prefix; @@ -323,7 +325,7 @@ class t_program : public t_doc { return std::string(); } - const std::map& get_all_namespaces(){ + const std::map& get_all_namespaces() const { return namespaces_; } @@ -331,7 +333,16 @@ class t_program : public t_doc { namespace_annotations_[language] = annotations; } - const std::map& get_namespace_annotations(std::string language) { + const std::map& get_namespace_annotations(const std::string& language) const { + auto it = namespace_annotations_.find(language); + if (namespace_annotations_.end() != it) { + return it->second; + } + static const std::map emptyMap; + return emptyMap; + } + + std::map& get_namespace_annotations(const std::string& language) { return namespace_annotations_[language]; } @@ -339,11 +350,11 @@ class t_program : public t_doc { void add_cpp_include(std::string path) { cpp_includes_.push_back(path); } - const std::vector& get_cpp_includes() { return cpp_includes_; } + const std::vector& get_cpp_includes() const { return cpp_includes_; } void add_c_include(std::string path) { c_includes_.push_back(path); } - const std::vector& get_c_includes() { return c_includes_; } + const std::vector& get_c_includes() const { return c_includes_; } private: // File path diff --git a/compiler/cpp/src/thrift/parse/t_scope.h b/compiler/cpp/src/thrift/parse/t_scope.h index 137af88329e..a12c4df5e1d 100644 --- a/compiler/cpp/src/thrift/parse/t_scope.h +++ b/compiler/cpp/src/thrift/parse/t_scope.h @@ -42,16 +42,34 @@ */ class t_scope { public: - t_scope() {} + t_scope() = default; void add_type(std::string name, t_type* type) { types_[name] = type; } t_type* get_type(std::string name) { return types_[name]; } + const t_type* get_type(std::string name) const { + const auto it = types_.find(name); + if (types_.end() != it) + { + return it->second; + } + return nullptr; + } + void add_service(std::string name, t_service* service) { services_[name] = service; } t_service* get_service(std::string name) { return services_[name]; } + const t_service* get_service(std::string name) const { + const auto it = services_.find(name); + if (services_.end() != it) + { + return it->second; + } + return nullptr; + } + void add_constant(std::string name, t_const* constant) { if (constants_.find(name) != constants_.end()) { throw "Enum " + name + " is already defined!"; @@ -62,6 +80,15 @@ class t_scope { t_const* get_constant(std::string name) { return constants_[name]; } + const t_const* get_constant(std::string name) const { + const auto it = constants_.find(name); + if (constants_.end() != it) + { + return it->second; + } + return nullptr; + } + void print() { std::map::iterator iter; for (iter = types_.begin(); iter != types_.end(); ++iter) { @@ -90,12 +117,12 @@ class t_scope { resolve_const_value((*v_iter), ((t_set*)ttype)->get_elem_type()); } } else if (ttype->is_struct()) { - t_struct* tstruct = (t_struct*)ttype; + auto* tstruct = (t_struct*)ttype; const std::map& map = const_val->get_map(); std::map::const_iterator v_iter; for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { t_field* field = tstruct->get_field_by_name(v_iter->first->get_string()); - if (field == NULL) { + if (field == nullptr) { throw "No field named \"" + v_iter->first->get_string() + "\" was found in struct of type \"" + tstruct->get_name() + "\""; } @@ -106,7 +133,7 @@ class t_scope { const_val->set_enum((t_enum*)ttype); } else { t_const* constant = get_constant(const_val->get_identifier()); - if (constant == NULL) { + if (constant == nullptr) { throw "No enum value or constant found named \"" + const_val->get_identifier() + "\"!"; } @@ -152,9 +179,9 @@ class t_scope { } else if (ttype->is_enum()) { // enum constant with non-identifier value. set the enum and find the // value's name. - t_enum* tenum = (t_enum*)ttype; + auto* tenum = (t_enum*)ttype; t_enum_value* enum_value = tenum->get_constant_by_value(const_val->get_integer()); - if (enum_value == NULL) { + if (enum_value == nullptr) { std::ostringstream valstm; valstm << const_val->get_integer(); throw "Couldn't find a named value in enum " + tenum->get_name() + " for value " diff --git a/compiler/cpp/src/thrift/parse/t_service.h b/compiler/cpp/src/thrift/parse/t_service.h index e2204caee9c..a43a515cac6 100644 --- a/compiler/cpp/src/thrift/parse/t_service.h +++ b/compiler/cpp/src/thrift/parse/t_service.h @@ -31,9 +31,9 @@ class t_program; */ class t_service : public t_type { public: - t_service(t_program* program) : t_type(program), extends_(NULL) {} + t_service(t_program* program) : t_type(program), extends_(nullptr) {} - bool is_service() const { return true; } + bool is_service() const override { return true; } void set_extends(t_service* extends) { extends_ = extends; } diff --git a/compiler/cpp/src/thrift/parse/t_set.h b/compiler/cpp/src/thrift/parse/t_set.h index f913be4fa3c..c0d4a35c190 100644 --- a/compiler/cpp/src/thrift/parse/t_set.h +++ b/compiler/cpp/src/thrift/parse/t_set.h @@ -30,9 +30,11 @@ class t_set : public t_container { public: t_set(t_type* elem_type) : elem_type_(elem_type) {} - t_type* get_elem_type() const { return elem_type_; } + const t_type* get_elem_type() const { return elem_type_; } - bool is_set() const { return true; } + t_type* get_elem_type() { return elem_type_; } + + bool is_set() const override { return true; } private: t_type* elem_type_; diff --git a/compiler/cpp/src/thrift/parse/t_struct.h b/compiler/cpp/src/thrift/parse/t_struct.h index 4102da7be7f..7e1e6caf012 100644 --- a/compiler/cpp/src/thrift/parse/t_struct.h +++ b/compiler/cpp/src/thrift/parse/t_struct.h @@ -56,7 +56,7 @@ class t_struct : public t_type { members_with_value(0), xsd_all_(false) {} - void set_name(const std::string& name) { + void set_name(const std::string& name) override { name_ = name; validate_union_members(); } @@ -80,7 +80,7 @@ class t_struct : public t_type { } // unions may have up to one member defaulted, but not more - if (field->get_value() != NULL) { + if (field->get_value() != nullptr) { if (1 < ++members_with_value) { throw "Error: Field " + field->get_name() + " provides another default value for union " + name_; @@ -118,7 +118,7 @@ class t_struct : public t_type { return false; } // returns false when there is a conflict of field names - if (get_field_by_name(elem->get_name()) != NULL) { + if (get_field_by_name(elem->get_name()) != nullptr) { return false; } members_.push_back(elem); @@ -129,22 +129,16 @@ class t_struct : public t_type { const members_type& get_members() const { return members_; } - const members_type& get_sorted_members() { return members_in_id_order_; } + const members_type& get_sorted_members() const { return members_in_id_order_; } - bool is_struct() const { return !is_xception_; } + bool is_struct() const override { return !is_xception_; } - bool is_xception() const { return is_xception_; } + bool is_xception() const override { return is_xception_; } bool is_union() const { return is_union_; } t_field* get_field_by_name(std::string field_name) { - members_type::const_iterator m_iter; - for (m_iter = members_in_id_order_.begin(); m_iter != members_in_id_order_.end(); ++m_iter) { - if ((*m_iter)->get_name() == field_name) { - return *m_iter; - } - } - return NULL; + return const_cast(const_cast(*this).get_field_by_name(field_name)); } const t_field* get_field_by_name(std::string field_name) const { @@ -154,7 +148,7 @@ class t_struct : public t_type { return *m_iter; } } - return NULL; + return nullptr; } private: diff --git a/compiler/cpp/src/thrift/parse/t_type.h b/compiler/cpp/src/thrift/parse/t_type.h index 3a6d1e04484..63f99ed8774 100644 --- a/compiler/cpp/src/thrift/parse/t_type.h +++ b/compiler/cpp/src/thrift/parse/t_type.h @@ -38,7 +38,7 @@ class t_program; */ class t_type : public t_doc { public: - virtual ~t_type() {} + ~t_type() override = default; virtual void set_name(const std::string& name) { name_ = name; } @@ -85,13 +85,13 @@ class t_type : public t_doc { std::map annotations_; protected: - t_type() : program_(NULL) { ; } + t_type() : program_(nullptr) { ; } t_type(t_program* program) : program_(program) { ; } t_type(t_program* program, std::string name) : program_(program), name_(name) { ; } - t_type(std::string name) : program_(NULL), name_(name) { ; } + t_type(std::string name) : program_(nullptr), name_(name) { ; } t_program* program_; std::string name_; diff --git a/compiler/cpp/src/thrift/parse/t_typedef.cc b/compiler/cpp/src/thrift/parse/t_typedef.cc index 99ffdb8bdc6..c80868560e9 100644 --- a/compiler/cpp/src/thrift/parse/t_typedef.cc +++ b/compiler/cpp/src/thrift/parse/t_typedef.cc @@ -21,9 +21,13 @@ #include "thrift/parse/t_typedef.h" #include "thrift/parse/t_program.h" -t_type* t_typedef::get_type() const { +t_type* t_typedef::get_type() { + return const_cast(const_cast(this)->get_type()); +} + +const t_type* t_typedef::get_type() const { if (type_ == NULL) { - t_type* type = get_program()->scope()->get_type(symbolic_); + const t_type* type = get_program()->scope()->get_type(symbolic_); if (type == NULL) { printf("Type \"%s\" not defined\n", symbolic_.c_str()); exit(1); diff --git a/compiler/cpp/src/thrift/parse/t_typedef.h b/compiler/cpp/src/thrift/parse/t_typedef.h index aad3a50e8e9..d21d863a928 100644 --- a/compiler/cpp/src/thrift/parse/t_typedef.h +++ b/compiler/cpp/src/thrift/parse/t_typedef.h @@ -42,20 +42,22 @@ class t_typedef : public t_type { */ t_typedef(t_program* program, const std::string& symbolic, bool forward) : t_type(program, symbolic), - type_(NULL), + type_(nullptr), symbolic_(symbolic), forward_(forward) {} - ~t_typedef() {} + ~t_typedef() override = default; - t_type* get_type() const; + t_type* get_type(); + + const t_type* get_type() const; const std::string& get_symbolic() const { return symbolic_; } bool is_forward_typedef() const { return forward_; } - bool is_typedef() const { return true; } + bool is_typedef() const override { return true; } private: t_type* type_; diff --git a/lib/c_glib/test/testthrifttestclient.cpp b/lib/c_glib/test/testthrifttestclient.cpp old mode 100755 new mode 100644 index 1910c8a40b0..20fbcdb03b4 --- a/lib/c_glib/test/testthrifttestclient.cpp +++ b/lib/c_glib/test/testthrifttestclient.cpp @@ -67,58 +67,58 @@ bool Insanity::operator<(thrift::test::Insanity const& other) const { class TestHandler : public ThriftTestIf { public: - TestHandler() {} + TestHandler() = default; - void testVoid() { + void testVoid() override { cout << "[C -> C++] testVoid()" << endl; } - void testString(string& out, const string &thing) { + void testString(string& out, const string &thing) override { cout << "[C -> C++] testString(\"" << thing << "\")" << endl; out = thing; } - bool testBool(const bool thing) { + bool testBool(const bool thing) override { cout << "[C -> C++] testBool(" << (thing ? "true" : "false") << ")" << endl; return thing; } - int8_t testByte(const int8_t thing) { + int8_t testByte(const int8_t thing) override { cout << "[C -> C++] testByte(" << (int)thing << ")" << endl; return thing; } - int32_t testI32(const int32_t thing) { + int32_t testI32(const int32_t thing) override { cout << "[C -> C++] testI32(" << thing << ")" << endl; return thing; } - int64_t testI64(const int64_t thing) { + int64_t testI64(const int64_t thing) override { cout << "[C -> C++] testI64(" << thing << ")" << endl; return thing; } - double testDouble(const double thing) { + double testDouble(const double thing) override { cout.precision(6); cout << "[C -> C++] testDouble(" << fixed << thing << ")" << endl; return thing; } - void testBinary(string& out, const string &thing) { + void testBinary(string& out, const string &thing) override { cout << "[C -> C++] testBinary(\"" << thing << "\")" << endl; out = thing; } - void testStruct(Xtruct& out, const Xtruct &thing) { + void testStruct(Xtruct& out, const Xtruct &thing) override { cout << "[C -> C++] testStruct({\"" << thing.string_thing << "\", " << (int)thing.byte_thing << ", " << thing.i32_thing << ", " << thing.i64_thing << "})" << endl; out = thing; } - void testNest(Xtruct2& out, const Xtruct2& nest) { + void testNest(Xtruct2& out, const Xtruct2& nest) override { const Xtruct &thing = nest.struct_thing; cout << "[C -> C++] testNest({" << (int)nest.byte_thing << ", {\"" << thing.string_thing << "\", " << (int)thing.byte_thing << ", " << thing.i32_thing << ", " << thing.i64_thing << "}, " << nest.i32_thing << "})" << endl; out = nest; } - void testMap(map &out, const map &thing) { + void testMap(map &out, const map &thing) override { cout << "[C -> C++] testMap({"; map::const_iterator m_iter; bool first = true; @@ -134,7 +134,7 @@ class TestHandler : public ThriftTestIf { out = thing; } - void testStringMap(map &out, const map &thing) { + void testStringMap(map &out, const map &thing) override { cout << "[C -> C++] testStringMap({"; map::const_iterator m_iter; bool first = true; @@ -151,7 +151,7 @@ class TestHandler : public ThriftTestIf { } - void testSet(set &out, const set &thing) { + void testSet(set &out, const set &thing) override { cout << "[C -> C++] testSet({"; set::const_iterator s_iter; bool first = true; @@ -167,7 +167,7 @@ class TestHandler : public ThriftTestIf { out = thing; } - void testList(vector &out, const vector &thing) { + void testList(vector &out, const vector &thing) override { cout << "[C -> C++] testList({"; vector::const_iterator l_iter; bool first = true; @@ -183,16 +183,16 @@ class TestHandler : public ThriftTestIf { out = thing; } - Numberz::type testEnum(const Numberz::type thing) { + Numberz::type testEnum(const Numberz::type thing) override { cout << "[C -> C++] testEnum(" << thing << ")" << endl; return thing; } - UserId testTypedef(const UserId thing) { + UserId testTypedef(const UserId thing) override { cout << "[C -> C++] testTypedef(" << thing << ")" << endl; return thing; } - void testMapMap(map > &mapmap, const int32_t hello) { + void testMapMap(map > &mapmap, const int32_t hello) override { cout << "[C -> C++] testMapMap(" << hello << ")" << endl; map pos; @@ -207,7 +207,7 @@ class TestHandler : public ThriftTestIf { } - void testInsanity(map > &insane, const Insanity &argument) { + void testInsanity(map > &insane, const Insanity &argument) override { THRIFT_UNUSED_VARIABLE (argument); cout << "[C -> C++] testInsanity()" << endl; @@ -277,7 +277,7 @@ class TestHandler : public ThriftTestIf { } - void testMulti(Xtruct &hello, const int8_t arg0, const int32_t arg1, const int64_t arg2, const std::map &arg3, const Numberz::type arg4, const UserId arg5) { + void testMulti(Xtruct &hello, const int8_t arg0, const int32_t arg1, const int64_t arg2, const std::map &arg3, const Numberz::type arg4, const UserId arg5) override { THRIFT_UNUSED_VARIABLE (arg3); THRIFT_UNUSED_VARIABLE (arg4); THRIFT_UNUSED_VARIABLE (arg5); @@ -291,7 +291,7 @@ class TestHandler : public ThriftTestIf { } void testException(const std::string &arg) - throw(Xception, apache::thrift::TException) + throw(Xception, apache::thrift::TException) override { cout << "[C -> C++] testException(" << arg << ")" << endl; if (arg.compare("Xception") == 0) { @@ -309,7 +309,7 @@ class TestHandler : public ThriftTestIf { } } - void testMultiException(Xtruct &result, const std::string &arg0, const std::string &arg1) throw(Xception, Xception2) { + void testMultiException(Xtruct &result, const std::string &arg0, const std::string &arg1) throw(Xception, Xception2) override { cout << "[C -> C++] testMultiException(" << arg0 << ", " << arg1 << ")" << endl; @@ -329,7 +329,7 @@ class TestHandler : public ThriftTestIf { } } - void testOneway(int sleepFor) { + void testOneway(int sleepFor) override { cout << "testOneway(" << sleepFor << "): Sleeping..." << endl; sleep(sleepFor); cout << "testOneway(" << sleepFor << "): done sleeping!" << endl; @@ -350,12 +350,12 @@ extern "C" { static void test_thrift_client (void) { - ThriftSocket *tsocket = NULL; - ThriftBinaryProtocol *protocol = NULL; - TTestThriftTestClient *client = NULL; - TTestThriftTestIf *iface = NULL; - GError *error = NULL; - gchar *string = NULL; + ThriftSocket *tsocket = nullptr; + ThriftBinaryProtocol *protocol = nullptr; + TTestThriftTestClient *client = nullptr; + TTestThriftTestIf *iface = nullptr; + GError *error = nullptr; + gchar *string = nullptr; gint8 byte = 0; gint16 i16 = 0; gint32 i32 = 0, another_i32 = 56789; @@ -363,18 +363,18 @@ test_thrift_client (void) double dbl = 0.0; TTestXtruct *xtruct_in, *xtruct_out; TTestXtruct2 *xtruct2_in, *xtruct2_out; - GHashTable *map_in = NULL, *map_out = NULL; - GHashTable *set_in = NULL, *set_out = NULL; - GArray *list_in = NULL, *list_out = NULL; + GHashTable *map_in = nullptr, *map_out = nullptr; + GHashTable *set_in = nullptr, *set_out = nullptr; + GArray *list_in = nullptr, *list_out = nullptr; TTestNumberz enum_in, enum_out; TTestUserId user_id_in, user_id_out; - GHashTable *insanity_in = NULL; + GHashTable *insanity_in = nullptr; TTestXtruct *xtruct1, *xtruct2; - TTestInsanity *insanity_out = NULL; - TTestXtruct *multi_in = NULL; - GHashTable *multi_map_out = NULL; - TTestXception *xception = NULL; - TTestXception2 *xception2 = NULL; + TTestInsanity *insanity_out = nullptr; + TTestXtruct *multi_in = nullptr; + GHashTable *multi_map_out = nullptr; + TTestXception *xception = nullptr; + TTestXception2 *xception2 = nullptr; #if (!GLIB_CHECK_VERSION (2, 36, 0)) // initialize gobject @@ -392,33 +392,33 @@ test_thrift_client (void) iface = T_TEST_THRIFT_TEST_IF (client); // open and send - thrift_transport_open (THRIFT_TRANSPORT(tsocket), NULL); + thrift_transport_open (THRIFT_TRANSPORT(tsocket), nullptr); assert (t_test_thrift_test_client_test_void (iface, &error) == TRUE); - assert (error == NULL); + assert (error == nullptr); assert (t_test_thrift_test_client_test_string (iface, &string, "test123", &error) == TRUE); assert (strcmp (string, "test123") == 0); g_free (string); - assert (error == NULL); + assert (error == nullptr); assert (t_test_thrift_test_client_test_byte (iface, &byte, (gint8) 5, &error) == TRUE); assert (byte == 5); - assert (error == NULL); + assert (error == nullptr); assert (t_test_thrift_test_client_test_i32 (iface, &i32, 123, &error) == TRUE); assert (i32 == 123); - assert (error == NULL); + assert (error == nullptr); assert (t_test_thrift_test_client_test_i64 (iface, &i64, 12345, &error) == TRUE); assert (i64 == 12345); - assert (error == NULL); + assert (error == nullptr); assert (t_test_thrift_test_client_test_double (iface, &dbl, 5.6, &error) == TRUE); assert (dbl == 5.6); - assert (error == NULL); + assert (error == nullptr); - xtruct_out = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, NULL); + xtruct_out = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); xtruct_out->byte_thing = 1; xtruct_out->__isset_byte_thing = TRUE; xtruct_out->i32_thing = 15; @@ -427,50 +427,50 @@ test_thrift_client (void) xtruct_out->__isset_i64_thing = TRUE; xtruct_out->string_thing = g_strdup ("abc123"); xtruct_out->__isset_string_thing = TRUE; - xtruct_in = (TTestXtruct *) g_object_new(T_TEST_TYPE_XTRUCT, NULL); + xtruct_in = (TTestXtruct *) g_object_new(T_TEST_TYPE_XTRUCT, nullptr); assert (t_test_thrift_test_client_test_struct (iface, &xtruct_in, xtruct_out, &error) == TRUE); - assert (error == NULL); + assert (error == nullptr); - xtruct2_out = (TTestXtruct2 *) g_object_new (T_TEST_TYPE_XTRUCT2, NULL); + xtruct2_out = (TTestXtruct2 *) g_object_new (T_TEST_TYPE_XTRUCT2, nullptr); xtruct2_out->byte_thing = 1; xtruct2_out->__isset_byte_thing = TRUE; - if (xtruct2_out->struct_thing != NULL) + if (xtruct2_out->struct_thing != nullptr) g_object_unref(xtruct2_out->struct_thing); xtruct2_out->struct_thing = xtruct_out; xtruct2_out->__isset_struct_thing = TRUE; xtruct2_out->i32_thing = 123; xtruct2_out->__isset_i32_thing = TRUE; - xtruct2_in = (TTestXtruct2 *) g_object_new (T_TEST_TYPE_XTRUCT2, NULL); + xtruct2_in = (TTestXtruct2 *) g_object_new (T_TEST_TYPE_XTRUCT2, nullptr); assert (t_test_thrift_test_client_test_nest (iface, &xtruct2_in, xtruct2_out, &error) == TRUE); - assert (error == NULL); + assert (error == nullptr); g_object_unref (xtruct2_out); g_object_unref (xtruct2_in); g_object_unref (xtruct_in); - map_out = g_hash_table_new (NULL, NULL); - map_in = g_hash_table_new (NULL, NULL); g_hash_table_insert (map_out, &i32, &i32); + map_out = g_hash_table_new (nullptr, nullptr); + map_in = g_hash_table_new (nullptr, nullptr); g_hash_table_insert (map_out, &i32, &i32); assert (t_test_thrift_test_client_test_map (iface, &map_in, map_out, &error) == TRUE); - assert (error == NULL); + assert (error == nullptr); g_hash_table_destroy (map_out); g_hash_table_destroy (map_in); - map_out = g_hash_table_new (NULL, NULL); - map_in = g_hash_table_new (NULL, NULL); + map_out = g_hash_table_new (nullptr, nullptr); + map_in = g_hash_table_new (nullptr, nullptr); g_hash_table_insert (map_out, g_strdup ("a"), g_strdup ("123")); g_hash_table_insert (map_out, g_strdup ("a b"), g_strdup ("with spaces ")); g_hash_table_insert (map_out, g_strdup ("same"), g_strdup ("same")); g_hash_table_insert (map_out, g_strdup ("0"), g_strdup ("numeric key")); assert (t_test_thrift_test_client_test_string_map (iface, &map_in, map_out, &error) == TRUE); - assert (error == NULL); + assert (error == nullptr); g_hash_table_destroy (map_out); g_hash_table_destroy (map_in); - set_out = g_hash_table_new (NULL, NULL); - set_in = g_hash_table_new (NULL, NULL); + set_out = g_hash_table_new (nullptr, nullptr); + set_in = g_hash_table_new (nullptr, nullptr); g_hash_table_insert (set_out, &i32, &i32); assert (t_test_thrift_test_client_test_set (iface, &set_in, set_out, &error) == TRUE); - assert (error == NULL); + assert (error == nullptr); g_hash_table_destroy (set_out); g_hash_table_destroy (set_in); @@ -480,31 +480,31 @@ test_thrift_client (void) g_array_append_val (list_out, i32); g_array_append_val (list_out, another_i32); assert (t_test_thrift_test_client_test_list (iface, &list_in, list_out, &error) == TRUE); - assert (error == NULL); + assert (error == nullptr); g_array_free (list_out, TRUE); g_array_free (list_in, TRUE); enum_out = T_TEST_NUMBERZ_ONE; assert (t_test_thrift_test_client_test_enum (iface, &enum_in, enum_out, &error) == TRUE); assert (enum_in == enum_out); - assert (error == NULL); + assert (error == nullptr); user_id_out = 12345; assert (t_test_thrift_test_client_test_typedef (iface, &user_id_in, user_id_out, &error) == TRUE); assert (user_id_in == user_id_out); - assert (error == NULL); + assert (error == nullptr); - map_in = g_hash_table_new (NULL, NULL); + map_in = g_hash_table_new (nullptr, nullptr); assert (t_test_thrift_test_client_test_map_map (iface, &map_in, i32, &error) == TRUE); - assert (error == NULL); + assert (error == nullptr); g_hash_table_destroy (map_in); // insanity - insanity_out = (TTestInsanity *) g_object_new (T_TEST_TYPE_INSANITY, NULL); - insanity_out->userMap = g_hash_table_new (NULL, NULL); + insanity_out = (TTestInsanity *) g_object_new (T_TEST_TYPE_INSANITY, nullptr); + insanity_out->userMap = g_hash_table_new (nullptr, nullptr); g_hash_table_insert (insanity_out->userMap, GINT_TO_POINTER (enum_out), &user_id_out); - xtruct1 = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, NULL); + xtruct1 = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); xtruct1->byte_thing = 1; xtruct1->__isset_byte_thing = TRUE; xtruct1->i32_thing = 15; @@ -513,7 +513,7 @@ test_thrift_client (void) xtruct1->__isset_i64_thing = TRUE; xtruct1->string_thing = g_strdup ("abc123"); xtruct1->__isset_string_thing = TRUE; - xtruct2 = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, NULL); + xtruct2 = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); xtruct2->byte_thing = 1; xtruct2->__isset_byte_thing = TRUE; xtruct2->i32_thing = 15; @@ -523,7 +523,7 @@ test_thrift_client (void) xtruct2->string_thing = g_strdup ("abc123"); xtruct2->__isset_string_thing = TRUE; - insanity_in = g_hash_table_new (NULL, NULL); + insanity_in = g_hash_table_new (nullptr, nullptr); g_ptr_array_add (insanity_out->xtructs, xtruct1); g_ptr_array_add (insanity_out->xtructs, xtruct2); assert (t_test_thrift_test_client_test_insanity (iface, &insanity_in, insanity_out, &error) == TRUE); @@ -531,10 +531,10 @@ test_thrift_client (void) g_hash_table_unref (insanity_in); g_ptr_array_free (insanity_out->xtructs, TRUE); - multi_map_out = g_hash_table_new (NULL, NULL); + multi_map_out = g_hash_table_new (nullptr, nullptr); string = g_strdup ("abc123"); g_hash_table_insert (multi_map_out, &i16, string); - multi_in = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, NULL); + multi_in = (TTestXtruct *) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); assert (t_test_thrift_test_client_test_multi (iface, &multi_in, byte, i32, i64, multi_map_out, enum_out, user_id_out, &error) == TRUE); assert (multi_in->i32_thing == i32); assert (multi_in->i64_thing == i64); @@ -545,53 +545,53 @@ test_thrift_client (void) assert (t_test_thrift_test_client_test_exception (iface, "Xception", &xception, &error) == FALSE); assert (xception->errorCode == 1001); g_error_free (error); - error = NULL; + error = nullptr; g_object_unref (xception); - xception = NULL; + xception = nullptr; assert (t_test_thrift_test_client_test_exception (iface, "ApplicationException", &xception, &error) == FALSE); g_error_free (error); - error = NULL; - assert (xception == NULL); + error = nullptr; + assert (xception == nullptr); assert (t_test_thrift_test_client_test_exception (iface, "Test", &xception, &error) == TRUE); - assert (error == NULL); + assert (error == nullptr); - multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, NULL); - assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception", NULL, &xception, &xception2, &error) == FALSE); + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception", nullptr, &xception, &xception2, &error) == FALSE); assert (xception->errorCode == 1001); - assert (xception2 == NULL); + assert (xception2 == nullptr); g_error_free (error); - error = NULL; + error = nullptr; g_object_unref (xception); g_object_unref (multi_in); - xception = NULL; - multi_in = NULL; + xception = nullptr; + multi_in = nullptr; - multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, NULL); - assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception2", NULL, &xception, &xception2, &error) == FALSE); + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, "Xception2", nullptr, &xception, &xception2, &error) == FALSE); assert (xception2->errorCode == 2002); - assert (xception == NULL); + assert (xception == nullptr); g_error_free (error); - error = NULL; + error = nullptr; g_object_unref (xception2); g_object_unref (multi_in); - xception2 = NULL; - multi_in = NULL; + xception2 = nullptr; + multi_in = nullptr; - multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, NULL); - assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, NULL , NULL, &xception, &xception2, &error) == TRUE); - assert (error == NULL); + multi_in = (TTestXtruct*) g_object_new (T_TEST_TYPE_XTRUCT, nullptr); + assert (t_test_thrift_test_client_test_multi_exception (iface, &multi_in, nullptr , nullptr, &xception, &xception2, &error) == TRUE); + assert (error == nullptr); g_object_unref(multi_in); - multi_in = NULL; + multi_in = nullptr; assert (t_test_thrift_test_client_test_oneway (iface, 1, &error) == TRUE); - assert (error == NULL); + assert (error == nullptr); /* sleep to let the oneway call go through */ sleep (5); - thrift_transport_close (THRIFT_TRANSPORT(tsocket), NULL); + thrift_transport_close (THRIFT_TRANSPORT(tsocket), nullptr); g_object_unref (client); g_object_unref (protocol); g_object_unref (tsocket); diff --git a/lib/cpp/README.md b/lib/cpp/README.md index af37627d2a2..8a897d1ef4d 100755 --- a/lib/cpp/README.md +++ b/lib/cpp/README.md @@ -252,6 +252,10 @@ libraries now. This is CMake standard behavior. THRIFT-4735: Qt4 support was removed. +THRIFT-4762: +Added `const` specifier to `TTransport::getOrigin()`. This changes its function signature. +It's recommended to add the `override` specifier in implementations derived from `TTransport`. + ## 0.11.0 Older versions of thrift depended on the classes which diff --git a/lib/cpp/src/thrift/TApplicationException.h b/lib/cpp/src/thrift/TApplicationException.h index 60618fbe83c..cd1b3e7c0d1 100644 --- a/lib/cpp/src/thrift/TApplicationException.h +++ b/lib/cpp/src/thrift/TApplicationException.h @@ -57,7 +57,7 @@ class TApplicationException : public TException { TApplicationException(TApplicationExceptionType type, const std::string& message) : TException(message), type_(type) {} - virtual ~TApplicationException() noexcept {} + ~TApplicationException() noexcept override = default; /** * Returns an error code that provides information about the type of error @@ -67,7 +67,7 @@ class TApplicationException : public TException { */ TApplicationExceptionType getType() const { return type_; } - virtual const char* what() const noexcept { + const char* what() const noexcept override { if (message_.empty()) { switch (type_) { case UNKNOWN: diff --git a/lib/cpp/src/thrift/TBase.h b/lib/cpp/src/thrift/TBase.h index a274bcd73bb..cc31c346af7 100644 --- a/lib/cpp/src/thrift/TBase.h +++ b/lib/cpp/src/thrift/TBase.h @@ -28,7 +28,7 @@ namespace thrift { class TBase { public: - virtual ~TBase(){}; + virtual ~TBase()= default;; virtual uint32_t read(protocol::TProtocol* iprot) = 0; virtual uint32_t write(protocol::TProtocol* oprot) const = 0; }; diff --git a/lib/cpp/src/thrift/TDispatchProcessor.h b/lib/cpp/src/thrift/TDispatchProcessor.h index 28d347dbbd2..ae522b2d846 100644 --- a/lib/cpp/src/thrift/TDispatchProcessor.h +++ b/lib/cpp/src/thrift/TDispatchProcessor.h @@ -33,15 +33,15 @@ namespace thrift { template class TDispatchProcessorT : public TProcessor { public: - virtual bool process(std::shared_ptr in, + bool process(std::shared_ptr in, std::shared_ptr out, - void* connectionContext) { + void* connectionContext) override { protocol::TProtocol* inRaw = in.get(); protocol::TProtocol* outRaw = out.get(); // Try to dynamic cast to the template protocol type - Protocol_* specificIn = dynamic_cast(inRaw); - Protocol_* specificOut = dynamic_cast(outRaw); + auto* specificIn = dynamic_cast(inRaw); + auto* specificOut = dynamic_cast(outRaw); if (specificIn && specificOut) { return processFast(specificIn, specificOut, connectionContext); } @@ -105,9 +105,9 @@ class TDispatchProcessorT : public TProcessor { */ class TDispatchProcessor : public TProcessor { public: - virtual bool process(std::shared_ptr in, + bool process(std::shared_ptr in, std::shared_ptr out, - void* connectionContext) { + void* connectionContext) override { std::string fname; protocol::TMessageType mtype; int32_t seqid; diff --git a/lib/cpp/src/thrift/TOutput.cpp b/lib/cpp/src/thrift/TOutput.cpp index af36137b4c9..f25b5665393 100644 --- a/lib/cpp/src/thrift/TOutput.cpp +++ b/lib/cpp/src/thrift/TOutput.cpp @@ -62,7 +62,7 @@ void TOutput::printf(const char* message, ...) { #endif char* heap_buf = (char*)malloc((need + 1) * sizeof(char)); - if (heap_buf == NULL) { + if (heap_buf == nullptr) { #ifdef _MSC_VER va_start(ap, message); vsnprintf_s(stack_buf, STACK_BUF_SIZE, _TRUNCATE, message, ap); diff --git a/lib/cpp/src/thrift/TProcessor.h b/lib/cpp/src/thrift/TProcessor.h index 6a464668fe5..65bf3d4a7a4 100644 --- a/lib/cpp/src/thrift/TProcessor.h +++ b/lib/cpp/src/thrift/TProcessor.h @@ -35,7 +35,7 @@ namespace thrift { */ class TProcessorEventHandler { public: - virtual ~TProcessorEventHandler() {} + virtual ~TProcessorEventHandler() = default; /** * Called before calling other callback methods. @@ -46,7 +46,7 @@ class TProcessorEventHandler { virtual void* getContext(const char* fn_name, void* serverContext) { (void)fn_name; (void)serverContext; - return NULL; + return nullptr; } /** @@ -108,7 +108,7 @@ class TProcessorEventHandler { } protected: - TProcessorEventHandler() {} + TProcessorEventHandler() = default; }; /** @@ -119,10 +119,10 @@ class TProcessorContextFreer { TProcessorContextFreer(TProcessorEventHandler* handler, void* context, const char* method) : handler_(handler), context_(context), method_(method) {} ~TProcessorContextFreer() { - if (handler_ != NULL) + if (handler_ != nullptr) handler_->freeContext(context_, method_); } - void unregister() { handler_ = NULL; } + void unregister() { handler_ = nullptr; } private: apache::thrift::TProcessorEventHandler* handler_; @@ -139,7 +139,7 @@ class TProcessorContextFreer { */ class TProcessor { public: - virtual ~TProcessor() {} + virtual ~TProcessor() = default; virtual bool process(std::shared_ptr in, std::shared_ptr out, @@ -156,7 +156,7 @@ class TProcessor { } protected: - TProcessor() {} + TProcessor() = default; std::shared_ptr eventHandler_; }; @@ -202,7 +202,7 @@ struct TConnectionInfo { class TProcessorFactory { public: - virtual ~TProcessorFactory() {} + virtual ~TProcessorFactory() = default; /** * Get the TProcessor to use for a particular connection. @@ -218,7 +218,7 @@ class TSingletonProcessorFactory : public TProcessorFactory { public: TSingletonProcessorFactory(std::shared_ptr processor) : processor_(processor) {} - std::shared_ptr getProcessor(const TConnectionInfo&) { return processor_; } + std::shared_ptr getProcessor(const TConnectionInfo&) override { return processor_; } private: std::shared_ptr processor_; diff --git a/lib/cpp/src/thrift/Thrift.h b/lib/cpp/src/thrift/Thrift.h index 63227426d97..951cc2865ba 100644 --- a/lib/cpp/src/thrift/Thrift.h +++ b/lib/cpp/src/thrift/Thrift.h @@ -79,9 +79,9 @@ class TException : public std::exception { TException(const std::string& message) : message_(message) {} - virtual ~TException() noexcept {} + ~TException() noexcept override = default; - virtual const char* what() const noexcept { + const char* what() const noexcept override { if (message_.empty()) { return "Default TException."; } else { @@ -98,14 +98,14 @@ class TDelayedException { template static TDelayedException* delayException(const E& e); virtual void throw_it() = 0; - virtual ~TDelayedException(){}; + virtual ~TDelayedException()= default;; }; template class TExceptionWrapper : public TDelayedException { public: TExceptionWrapper(const E& e) : e_(e) {} - virtual void throw_it() { + void throw_it() override { E temp(e_); delete this; throw temp; diff --git a/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h b/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h index 9c96b14a6e4..e3c3597c2db 100644 --- a/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h +++ b/lib/cpp/src/thrift/async/TAsyncBufferProcessor.h @@ -37,7 +37,7 @@ class TAsyncBufferProcessor { virtual void process(std::function _return, std::shared_ptr ibuf, std::shared_ptr obuf) = 0; - virtual ~TAsyncBufferProcessor() {} + virtual ~TAsyncBufferProcessor() = default; }; } } diff --git a/lib/cpp/src/thrift/async/TAsyncChannel.h b/lib/cpp/src/thrift/async/TAsyncChannel.h index d7ace96c29c..22cf383883a 100644 --- a/lib/cpp/src/thrift/async/TAsyncChannel.h +++ b/lib/cpp/src/thrift/async/TAsyncChannel.h @@ -41,7 +41,7 @@ class TAsyncChannel { public: typedef std::function VoidCallback; - virtual ~TAsyncChannel() {} + virtual ~TAsyncChannel() = default; // is the channel in a good state? virtual bool good() const = 0; diff --git a/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h b/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h index 59db5977d3c..2a694ac53bb 100644 --- a/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h +++ b/lib/cpp/src/thrift/async/TAsyncDispatchProcessor.h @@ -34,15 +34,15 @@ namespace async { template class TAsyncDispatchProcessorT : public TAsyncProcessor { public: - virtual void process(std::function _return, + void process(std::function _return, std::shared_ptr in, - std::shared_ptr out) { + std::shared_ptr out) override { protocol::TProtocol* inRaw = in.get(); protocol::TProtocol* outRaw = out.get(); // Try to dynamic cast to the template protocol type - Protocol_* specificIn = dynamic_cast(inRaw); - Protocol_* specificOut = dynamic_cast(outRaw); + auto* specificIn = dynamic_cast(inRaw); + auto* specificOut = dynamic_cast(outRaw); if (specificIn && specificOut) { return processFast(_return, specificIn, specificOut); } @@ -106,9 +106,9 @@ class TAsyncDispatchProcessorT : public TAsyncProcessor { */ class TAsyncDispatchProcessor : public TAsyncProcessor { public: - virtual void process(std::function _return, + void process(std::function _return, std::shared_ptr in, - std::shared_ptr out) { + std::shared_ptr out) override { protocol::TProtocol* inRaw = in.get(); protocol::TProtocol* outRaw = out.get(); diff --git a/lib/cpp/src/thrift/async/TAsyncProcessor.h b/lib/cpp/src/thrift/async/TAsyncProcessor.h index fdb976dd3cf..01923394587 100644 --- a/lib/cpp/src/thrift/async/TAsyncProcessor.h +++ b/lib/cpp/src/thrift/async/TAsyncProcessor.h @@ -35,7 +35,7 @@ namespace async { class TAsyncProcessor { public: - virtual ~TAsyncProcessor() {} + virtual ~TAsyncProcessor() = default; virtual void process(std::function _return, std::shared_ptr in, @@ -53,14 +53,14 @@ class TAsyncProcessor { } protected: - TAsyncProcessor() {} + TAsyncProcessor() = default; std::shared_ptr eventHandler_; }; class TAsyncProcessorFactory { public: - virtual ~TAsyncProcessorFactory() {} + virtual ~TAsyncProcessorFactory() = default; /** * Get the TAsyncProcessor to use for a particular connection. diff --git a/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h b/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h index 8052cf36487..ace72b6dcb5 100644 --- a/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h +++ b/lib/cpp/src/thrift/async/TAsyncProtocolProcessor.h @@ -34,11 +34,11 @@ class TAsyncProtocolProcessor : public TAsyncBufferProcessor { std::shared_ptr pfact) : underlying_(underlying), pfact_(pfact) {} - virtual void process(std::function _return, + void process(std::function _return, std::shared_ptr ibuf, - std::shared_ptr obuf); + std::shared_ptr obuf) override; - virtual ~TAsyncProtocolProcessor() {} + ~TAsyncProtocolProcessor() override = default; private: static void finish(std::function _return, diff --git a/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.cpp b/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.cpp index c7e27c07873..952394bca4f 100644 --- a/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.cpp +++ b/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.cpp @@ -75,7 +75,7 @@ void TConcurrentClientSyncInfo::updatePending( MonitorPtr monitor; { Guard seqidGuard(seqidMutex_); - MonitorMap::iterator i = seqidToMonitorMap_.find(rseqid); + auto i = seqidToMonitorMap_.find(rseqid); if(i == seqidToMonitorMap_.end()) throwBadSeqId_(); monitor = i->second; @@ -140,7 +140,7 @@ void TConcurrentClientSyncInfo::markBad_(const Guard &) { wakeupSomeone_ = true; stop_ = true; - for(MonitorMap::iterator i = seqidToMonitorMap_.begin(); i != seqidToMonitorMap_.end(); ++i) + for(auto i = seqidToMonitorMap_.begin(); i != seqidToMonitorMap_.end(); ++i) i->second->notify(); } diff --git a/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp b/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp index 6af8104b649..7656596859a 100644 --- a/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp +++ b/lib/cpp/src/thrift/async/TEvhttpClientChannel.cpp @@ -41,15 +41,15 @@ TEvhttpClientChannel::TEvhttpClientChannel(const std::string& host, struct event_base* eb, struct evdns_base* dnsbase) - : host_(host), path_(path), conn_(NULL) { + : host_(host), path_(path), conn_(nullptr) { conn_ = evhttp_connection_base_new(eb, dnsbase, address, port); - if (conn_ == NULL) { + if (conn_ == nullptr) { throw TException("evhttp_connection_new failed"); } } TEvhttpClientChannel::~TEvhttpClientChannel() { - if (conn_ != NULL) { + if (conn_ != nullptr) { evhttp_connection_free(conn_); } } @@ -58,7 +58,7 @@ void TEvhttpClientChannel::sendAndRecvMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* sendBuf, apache::thrift::transport::TMemoryBuffer* recvBuf) { struct evhttp_request* req = evhttp_request_new(response, this); - if (req == NULL) { + if (req == nullptr) { throw TException("evhttp_request_new failed"); } @@ -110,7 +110,7 @@ void TEvhttpClientChannel::finish(struct evhttp_request* req) { assert(!completionQueue_.empty()); Completion completion = completionQueue_.front(); completionQueue_.pop(); - if (req == NULL) { + if (req == nullptr) { try { completion.first(); } catch (const TTransportException& e) { @@ -142,7 +142,7 @@ void TEvhttpClientChannel::finish(struct evhttp_request* req) { } /* static */ void TEvhttpClientChannel::response(struct evhttp_request* req, void* arg) { - TEvhttpClientChannel* self = (TEvhttpClientChannel*)arg; + auto* self = (TEvhttpClientChannel*)arg; try { self->finish(req); } catch (std::exception& e) { diff --git a/lib/cpp/src/thrift/async/TEvhttpClientChannel.h b/lib/cpp/src/thrift/async/TEvhttpClientChannel.h index a321f417b42..f74272665b8 100644 --- a/lib/cpp/src/thrift/async/TEvhttpClientChannel.h +++ b/lib/cpp/src/thrift/async/TEvhttpClientChannel.h @@ -52,24 +52,24 @@ class TEvhttpClientChannel : public TAsyncChannel { const char* address, int port, struct event_base* eb, - struct evdns_base *dnsbase = 0); - ~TEvhttpClientChannel(); + struct evdns_base *dnsbase = nullptr); + ~TEvhttpClientChannel() override; - virtual void sendAndRecvMessage(const VoidCallback& cob, + void sendAndRecvMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* sendBuf, - apache::thrift::transport::TMemoryBuffer* recvBuf); + apache::thrift::transport::TMemoryBuffer* recvBuf) override; - virtual void sendMessage(const VoidCallback& cob, - apache::thrift::transport::TMemoryBuffer* message); - virtual void recvMessage(const VoidCallback& cob, - apache::thrift::transport::TMemoryBuffer* message); + void sendMessage(const VoidCallback& cob, + apache::thrift::transport::TMemoryBuffer* message) override; + void recvMessage(const VoidCallback& cob, + apache::thrift::transport::TMemoryBuffer* message) override; void finish(struct evhttp_request* req); // XXX - virtual bool good() const { return true; } - virtual bool error() const { return false; } - virtual bool timedOut() const { return false; } + bool good() const override { return true; } + bool error() const override { return false; } + bool timedOut() const override { return false; } private: static void response(struct evhttp_request* req, void* arg); diff --git a/lib/cpp/src/thrift/async/TEvhttpServer.cpp b/lib/cpp/src/thrift/async/TEvhttpServer.cpp index bdc32661fad..7d2cf21c0fc 100644 --- a/lib/cpp/src/thrift/async/TEvhttpServer.cpp +++ b/lib/cpp/src/thrift/async/TEvhttpServer.cpp @@ -46,24 +46,24 @@ struct TEvhttpServer::RequestContext { }; TEvhttpServer::TEvhttpServer(std::shared_ptr processor) - : processor_(processor), eb_(NULL), eh_(NULL) { + : processor_(processor), eb_(nullptr), eh_(nullptr) { } TEvhttpServer::TEvhttpServer(std::shared_ptr processor, int port) - : processor_(processor), eb_(NULL), eh_(NULL) { + : processor_(processor), eb_(nullptr), eh_(nullptr) { // Create event_base and evhttp. eb_ = event_base_new(); - if (eb_ == NULL) { + if (eb_ == nullptr) { throw TException("event_base_new failed"); } eh_ = evhttp_new(eb_); - if (eh_ == NULL) { + if (eh_ == nullptr) { event_base_free(eb_); throw TException("evhttp_new failed"); } // Bind to port. - int ret = evhttp_bind_socket(eh_, NULL, port); + int ret = evhttp_bind_socket(eh_, nullptr, port); if (ret < 0) { evhttp_free(eh_); event_base_free(eb_); @@ -77,16 +77,16 @@ TEvhttpServer::TEvhttpServer(std::shared_ptr processor, i } TEvhttpServer::~TEvhttpServer() { - if (eh_ != NULL) { + if (eh_ != nullptr) { evhttp_free(eh_); } - if (eb_ != NULL) { + if (eb_ != nullptr) { event_base_free(eb_); } } int TEvhttpServer::serve() { - if (eb_ == NULL) { + if (eb_ == nullptr) { throw TException("Unexpected call to TEvhttpServer::serve"); } return event_base_dispatch(eb_); @@ -103,12 +103,12 @@ void TEvhttpServer::request(struct evhttp_request* req, void* self) { try { static_cast(self)->process(req); } catch (std::exception& e) { - evhttp_send_reply(req, HTTP_INTERNAL, e.what(), 0); + evhttp_send_reply(req, HTTP_INTERNAL, e.what(), nullptr); } } void TEvhttpServer::process(struct evhttp_request* req) { - RequestContext* ctx = new RequestContext(req); + auto* ctx = new RequestContext(req); return processor_->process(std::bind(&TEvhttpServer::complete, this, ctx, @@ -131,7 +131,7 @@ void TEvhttpServer::complete(RequestContext* ctx, bool success) { } struct evbuffer* buf = evbuffer_new(); - if (buf == NULL) { + if (buf == nullptr) { // TODO: Log an error. std::cerr << "evbuffer_new failed " << __FILE__ << ":" << __LINE__ << std::endl; } else { @@ -147,7 +147,7 @@ void TEvhttpServer::complete(RequestContext* ctx, bool success) { } evhttp_send_reply(ctx->req, code, reason, buf); - if (buf != NULL) { + if (buf != nullptr) { evbuffer_free(buf); } } diff --git a/lib/cpp/src/thrift/concurrency/Exception.h b/lib/cpp/src/thrift/concurrency/Exception.h index 6438fda101e..947fc9f04a0 100644 --- a/lib/cpp/src/thrift/concurrency/Exception.h +++ b/lib/cpp/src/thrift/concurrency/Exception.h @@ -35,7 +35,7 @@ class InvalidArgumentException : public apache::thrift::TException {}; class IllegalStateException : public apache::thrift::TException { public: - IllegalStateException() {} + IllegalStateException() = default; IllegalStateException(const std::string& message) : TException(message) {} }; @@ -53,7 +53,7 @@ class TooManyPendingTasksException : public apache::thrift::TException { class SystemResourceException : public apache::thrift::TException { public: - SystemResourceException() {} + SystemResourceException() = default; SystemResourceException(const std::string& message) : TException(message) {} }; diff --git a/lib/cpp/src/thrift/concurrency/FunctionRunner.h b/lib/cpp/src/thrift/concurrency/FunctionRunner.h index 8ad176eb4c8..46883441666 100644 --- a/lib/cpp/src/thrift/concurrency/FunctionRunner.h +++ b/lib/cpp/src/thrift/concurrency/FunctionRunner.h @@ -96,7 +96,7 @@ class FunctionRunner : public Runnable { */ FunctionRunner(const BoolFunc& cob, int intervalMs) : repFunc_(cob), intervalMs_(intervalMs) {} - void run() { + void run() override { if (repFunc_) { while (repFunc_()) { THRIFT_SLEEP_USEC(intervalMs_ * 1000); diff --git a/lib/cpp/src/thrift/concurrency/Monitor.cpp b/lib/cpp/src/thrift/concurrency/Monitor.cpp index 99d52b3e351..dc92efd6cd5 100644 --- a/lib/cpp/src/thrift/concurrency/Monitor.cpp +++ b/lib/cpp/src/thrift/concurrency/Monitor.cpp @@ -41,11 +41,11 @@ namespace concurrency { class Monitor::Impl { public: - Impl() : ownedMutex_(new Mutex()), conditionVariable_(), mutex_(NULL) { init(ownedMutex_.get()); } + Impl() : ownedMutex_(new Mutex()), conditionVariable_(), mutex_(nullptr) { init(ownedMutex_.get()); } - Impl(Mutex* mutex) : ownedMutex_(), conditionVariable_(), mutex_(NULL) { init(mutex); } + Impl(Mutex* mutex) : ownedMutex_(), conditionVariable_(), mutex_(nullptr) { init(mutex); } - Impl(Monitor* monitor) : ownedMutex_(), conditionVariable_(), mutex_(NULL) { + Impl(Monitor* monitor) : ownedMutex_(), conditionVariable_(), mutex_(nullptr) { init(&(monitor->mutex())); } @@ -81,7 +81,7 @@ class Monitor::Impl { } assert(mutex_); - std::timed_mutex* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); + auto* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); assert(mutexImpl); std::unique_lock lock(*mutexImpl, std::adopt_lock); @@ -97,7 +97,7 @@ class Monitor::Impl { */ int waitForTime(const std::chrono::time_point& abstime) { assert(mutex_); - std::timed_mutex* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); + auto* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); assert(mutexImpl); std::unique_lock lock(*mutexImpl, std::adopt_lock); @@ -113,7 +113,7 @@ class Monitor::Impl { */ int waitForever() { assert(mutex_); - std::timed_mutex* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); + auto* mutexImpl = static_cast(mutex_->getUnderlyingImpl()); assert(mutexImpl); std::unique_lock lock(*mutexImpl, std::adopt_lock); diff --git a/lib/cpp/src/thrift/concurrency/Mutex.h b/lib/cpp/src/thrift/concurrency/Mutex.h index 5e0f85b0265..27e386ed48b 100644 --- a/lib/cpp/src/thrift/concurrency/Mutex.h +++ b/lib/cpp/src/thrift/concurrency/Mutex.h @@ -40,7 +40,7 @@ namespace concurrency { class Mutex { public: Mutex(); - virtual ~Mutex() {} + virtual ~Mutex() = default; virtual void lock() const; virtual bool trylock() const; @@ -62,11 +62,11 @@ class Guard : boost::noncopyable { value.lock(); } else if (timeout < 0) { if (!value.trylock()) { - mutex_ = NULL; + mutex_ = nullptr; } } else { if (!value.timedlock(timeout)) { - mutex_ = NULL; + mutex_ = nullptr; } } } @@ -76,7 +76,7 @@ class Guard : boost::noncopyable { } } - operator bool() const { return (mutex_ != NULL); } + operator bool() const { return (mutex_ != nullptr); } private: const Mutex* mutex_; diff --git a/lib/cpp/src/thrift/concurrency/Thread.h b/lib/cpp/src/thrift/concurrency/Thread.h index f8a3f51571a..bced240f019 100644 --- a/lib/cpp/src/thrift/concurrency/Thread.h +++ b/lib/cpp/src/thrift/concurrency/Thread.h @@ -39,7 +39,7 @@ class Thread; class Runnable { public: - virtual ~Runnable(){}; + virtual ~Runnable()= default;; virtual void run() = 0; /** diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp index 4c7c372afb0..c889660cfb3 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp +++ b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp @@ -64,19 +64,19 @@ class ThreadManager::Impl : public ThreadManager { maxMonitor_(&mutex_), workerMonitor_(&mutex_) {} - ~Impl() { stop(); } + ~Impl() override { stop(); } - void start(); - void stop(); + void start() override; + void stop() override; - ThreadManager::STATE state() const { return state_; } + ThreadManager::STATE state() const override { return state_; } - shared_ptr threadFactory() const { + shared_ptr threadFactory() const override { Guard g(mutex_); return threadFactory_; } - void threadFactory(shared_ptr value) { + void threadFactory(shared_ptr value) override { Guard g(mutex_); if (threadFactory_ && threadFactory_->isDetached() != value->isDetached()) { throw InvalidArgumentException(); @@ -84,33 +84,33 @@ class ThreadManager::Impl : public ThreadManager { threadFactory_ = value; } - void addWorker(size_t value); + void addWorker(size_t value) override; - void removeWorker(size_t value); + void removeWorker(size_t value) override; - size_t idleWorkerCount() const { return idleCount_; } + size_t idleWorkerCount() const override { return idleCount_; } - size_t workerCount() const { + size_t workerCount() const override { Guard g(mutex_); return workerCount_; } - size_t pendingTaskCount() const { + size_t pendingTaskCount() const override { Guard g(mutex_); return tasks_.size(); } - size_t totalTaskCount() const { + size_t totalTaskCount() const override { Guard g(mutex_); return tasks_.size() + workerCount_ - idleCount_; } - size_t pendingTaskCountMax() const { + size_t pendingTaskCountMax() const override { Guard g(mutex_); return pendingTaskCountMax_; } - size_t expiredTaskCount() const { + size_t expiredTaskCount() const override { Guard g(mutex_); return expiredCount_; } @@ -120,17 +120,17 @@ class ThreadManager::Impl : public ThreadManager { pendingTaskCountMax_ = value; } - void add(shared_ptr value, int64_t timeout, int64_t expiration); + void add(shared_ptr value, int64_t timeout, int64_t expiration) override; - void remove(shared_ptr task); + void remove(shared_ptr task) override; - shared_ptr removeNextPending(); + shared_ptr removeNextPending() override; - void removeExpiredTasks() { + void removeExpiredTasks() override { removeExpired(false); } - void setExpireCallback(ExpireCallback expireCallback); + void setExpireCallback(ExpireCallback expireCallback) override; private: /** @@ -188,9 +188,9 @@ class ThreadManager::Task : public Runnable { } } - ~Task() {} + ~Task() override = default; - void run() { + void run() override { if (state_ == EXECUTING) { runnable_->run(); state_ = COMPLETE; @@ -214,7 +214,7 @@ class ThreadManager::Worker : public Runnable { public: Worker(ThreadManager::Impl* manager) : manager_(manager), state_(UNINITIALIZED) {} - ~Worker() {} + ~Worker() override = default; private: bool isActive() const { @@ -229,7 +229,7 @@ class ThreadManager::Worker : public Runnable { * As long as worker thread is running, pull tasks off the task queue and * execute. */ - void run() { + void run() override { Guard g(manager_->mutex_); /** @@ -352,7 +352,7 @@ void ThreadManager::Impl::addWorker(size_t value) { workerMaxCount_ += value; workers_.insert(newThreads.begin(), newThreads.end()); - for (std::set >::iterator ix = newThreads.begin(); ix != newThreads.end(); + for (auto ix = newThreads.begin(); ix != newThreads.end(); ++ix) { shared_ptr worker = dynamic_pointer_cast((*ix)->runnable()); @@ -430,7 +430,7 @@ void ThreadManager::Impl::removeWorkersUnderLock(size_t value) { workerMonitor_.wait(); } - for (std::set >::iterator ix = deadWorkers_.begin(); + for (auto ix = deadWorkers_.begin(); ix != deadWorkers_.end(); ++ix) { @@ -497,7 +497,7 @@ void ThreadManager::Impl::remove(shared_ptr task) { "started"); } - for (TaskQueue::iterator it = tasks_.begin(); it != tasks_.end(); ++it) + for (auto it = tasks_.begin(); it != tasks_.end(); ++it) { if ((*it)->getRunnable() == task) { @@ -532,7 +532,7 @@ void ThreadManager::Impl::removeExpired(bool justOne) { } auto now = std::chrono::steady_clock::now(); - for (TaskQueue::iterator it = tasks_.begin(); it != tasks_.end(); ) + for (auto it = tasks_.begin(); it != tasks_.end(); ) { if ((*it)->getExpireTime() && *((*it)->getExpireTime()) < now) { if (expireCallback_) { @@ -562,7 +562,7 @@ class SimpleThreadManager : public ThreadManager::Impl { SimpleThreadManager(size_t workerCount = 4, size_t pendingTaskCountMax = 0) : workerCount_(workerCount), pendingTaskCountMax_(pendingTaskCountMax) {} - void start() { + void start() override { ThreadManager::Impl::pendingTaskCountMax(pendingTaskCountMax_); ThreadManager::Impl::start(); addWorker(workerCount_); diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.h b/lib/cpp/src/thrift/concurrency/ThreadManager.h index 605e36326da..7b202ca6ad1 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadManager.h +++ b/lib/cpp/src/thrift/concurrency/ThreadManager.h @@ -55,12 +55,12 @@ class ThreadManager; class ThreadManager { protected: - ThreadManager() {} + ThreadManager() = default; public: typedef std::function)> ExpireCallback; - virtual ~ThreadManager() {} + virtual ~ThreadManager() = default; /** * Starts the thread manager. Verifies all attributes have been properly diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.cpp b/lib/cpp/src/thrift/concurrency/TimerManager.cpp index edd336be07c..df599009527 100644 --- a/lib/cpp/src/thrift/concurrency/TimerManager.cpp +++ b/lib/cpp/src/thrift/concurrency/TimerManager.cpp @@ -43,9 +43,9 @@ class TimerManager::Task : public Runnable { Task(shared_ptr runnable) : runnable_(runnable), state_(WAITING) {} - ~Task() {} + ~Task() override = default; - void run() { + void run() override { if (state_ == EXECUTING) { runnable_->run(); state_ = COMPLETE; @@ -67,7 +67,7 @@ class TimerManager::Dispatcher : public Runnable { public: Dispatcher(TimerManager* manager) : manager_(manager) {} - ~Dispatcher() {} + ~Dispatcher() override = default; /** * Dispatcher entry point @@ -75,7 +75,7 @@ class TimerManager::Dispatcher : public Runnable { * As long as dispatcher thread is running, pull tasks off the task taskMap_ * and execute. */ - void run() { + void run() override { { Synchronized s(manager_->monitor_); if (manager_->state_ == TimerManager::STARTING) { @@ -108,7 +108,7 @@ class TimerManager::Dispatcher : public Runnable { } if (manager_->state_ == TimerManager::STARTED) { - for (task_iterator ix = manager_->taskMap_.begin(); ix != expiredTaskEnd; ix++) { + for (auto ix = manager_->taskMap_.begin(); ix != expiredTaskEnd; ix++) { shared_ptr task = ix->second; expiredTasks.insert(task); task->it_ = manager_->taskMap_.end(); @@ -121,7 +121,7 @@ class TimerManager::Dispatcher : public Runnable { } } - for (std::set >::iterator ix = expiredTasks.begin(); + for (auto ix = expiredTasks.begin(); ix != expiredTasks.end(); ++ix) { (*ix)->run(); @@ -221,7 +221,7 @@ void TimerManager::stop() { taskMap_.clear(); // Remove dispatcher's reference to us. - dispatcher_->manager_ = NULL; + dispatcher_->manager_ = nullptr; } } @@ -280,7 +280,7 @@ void TimerManager::remove(shared_ptr task) { throw IllegalStateException(); } bool found = false; - for (task_iterator ix = taskMap_.begin(); ix != taskMap_.end();) { + for (auto ix = taskMap_.begin(); ix != taskMap_.end();) { if (*ix->second == task) { found = true; taskCount_--; diff --git a/lib/cpp/src/thrift/processor/PeekProcessor.cpp b/lib/cpp/src/thrift/processor/PeekProcessor.cpp index 07f6ba58bfd..4cd58b8dbb9 100644 --- a/lib/cpp/src/thrift/processor/PeekProcessor.cpp +++ b/lib/cpp/src/thrift/processor/PeekProcessor.cpp @@ -31,8 +31,7 @@ PeekProcessor::PeekProcessor() { memoryBuffer_.reset(new TMemoryBuffer()); targetTransport_ = memoryBuffer_; } -PeekProcessor::~PeekProcessor() { -} +PeekProcessor::~PeekProcessor() = default; void PeekProcessor::initialize(std::shared_ptr actualProcessor, std::shared_ptr protocolFactory, diff --git a/lib/cpp/src/thrift/processor/PeekProcessor.h b/lib/cpp/src/thrift/processor/PeekProcessor.h index efac2b96130..ae565fc4bbd 100644 --- a/lib/cpp/src/thrift/processor/PeekProcessor.h +++ b/lib/cpp/src/thrift/processor/PeekProcessor.h @@ -40,7 +40,7 @@ class PeekProcessor : public apache::thrift::TProcessor { public: PeekProcessor(); - virtual ~PeekProcessor(); + ~PeekProcessor() override; // Input here: actualProcessor - the underlying processor // protocolFactory - the protocol factory used to wrap the memory buffer @@ -56,9 +56,9 @@ class PeekProcessor : public apache::thrift::TProcessor { void setTargetTransport(std::shared_ptr targetTransport); - virtual bool process(std::shared_ptr in, + bool process(std::shared_ptr in, std::shared_ptr out, - void* connectionContext); + void* connectionContext) override; // The following three functions can be overloaded by child classes to // achieve desired peeking behavior diff --git a/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h b/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h index 2aa7f751109..85c0affc265 100644 --- a/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h +++ b/lib/cpp/src/thrift/processor/TMultiplexedProcessor.h @@ -42,7 +42,7 @@ class StoredMessageProtocol : public TProtocolDecorator { const int32_t _seqid) : TProtocolDecorator(_protocol), name(_name), type(_type), seqid(_seqid) {} - uint32_t readMessageBegin_virt(std::string& _name, TMessageType& _type, int32_t& _seqid) { + uint32_t readMessageBegin_virt(std::string& _name, TMessageType& _type, int32_t& _seqid) override { _name = name; _type = type; @@ -149,7 +149,7 @@ class TMultiplexedProcessor : public TProcessor { */ bool process(std::shared_ptr in, std::shared_ptr out, - void* connectionContext) { + void* connectionContext) override { std::string name; protocol::TMessageType type; int32_t seqid; @@ -174,7 +174,7 @@ class TMultiplexedProcessor : public TProcessor { // name and the name of the method to call. if (tokens.size() == 2) { // Search for a processor associated with this service name. - services_t::iterator it = services.find(tokens[0]); + auto it = services.find(tokens[0]); if (it != services.end()) { std::shared_ptr processor = it->second; diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h index 906775831b4..6bd5fb830c7 100644 --- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.h +++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.h @@ -201,7 +201,7 @@ class TBinaryProtocolFactoryT : public TProtocolFactory { strict_read_(strict_read), strict_write_(strict_write) {} - virtual ~TBinaryProtocolFactoryT() {} + ~TBinaryProtocolFactoryT() override = default; void setStringSizeLimit(int32_t string_limit) { string_limit_ = string_limit; } @@ -212,7 +212,7 @@ class TBinaryProtocolFactoryT : public TProtocolFactory { strict_write_ = strict_write; } - std::shared_ptr getProtocol(std::shared_ptr trans) { + std::shared_ptr getProtocol(std::shared_ptr trans) override { std::shared_ptr specific_trans = std::dynamic_pointer_cast(trans); TProtocol* prot; if (specific_trans) { diff --git a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc index fe739928212..2964f25d033 100644 --- a/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc +++ b/lib/cpp/src/thrift/protocol/TBinaryProtocol.tcc @@ -144,21 +144,21 @@ uint32_t TBinaryProtocolT::writeByte(const int8_t byte) template uint32_t TBinaryProtocolT::writeI16(const int16_t i16) { - int16_t net = (int16_t)ByteOrder_::toWire16(i16); + auto net = (int16_t)ByteOrder_::toWire16(i16); this->trans_->write((uint8_t*)&net, 2); return 2; } template uint32_t TBinaryProtocolT::writeI32(const int32_t i32) { - int32_t net = (int32_t)ByteOrder_::toWire32(i32); + auto net = (int32_t)ByteOrder_::toWire32(i32); this->trans_->write((uint8_t*)&net, 4); return 4; } template uint32_t TBinaryProtocolT::writeI64(const int64_t i64) { - int64_t net = (int64_t)ByteOrder_::toWire64(i64); + auto net = (int64_t)ByteOrder_::toWire64(i64); this->trans_->write((uint8_t*)&net, 8); return 8; } @@ -168,7 +168,7 @@ uint32_t TBinaryProtocolT::writeDouble(const double dub) static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); - uint64_t bits = bitwise_cast(dub); + auto bits = bitwise_cast(dub); bits = ByteOrder_::toWire64(bits); this->trans_->write((uint8_t*)&bits, 8); return 8; @@ -179,7 +179,7 @@ template uint32_t TBinaryProtocolT::writeString(const StrType& str) { if (str.size() > static_cast((std::numeric_limits::max)())) throw TProtocolException(TProtocolException::SIZE_LIMIT); - uint32_t size = static_cast(str.size()); + auto size = static_cast(str.size()); uint32_t result = writeI32((int32_t)size); if (size > 0) { this->trans_->write((uint8_t*)str.data(), size); @@ -437,7 +437,7 @@ uint32_t TBinaryProtocolT::readStringBody(StrType& str, // Try to borrow first const uint8_t* borrow_buf; uint32_t got = size; - if ((borrow_buf = this->trans_->borrow(NULL, &got))) { + if ((borrow_buf = this->trans_->borrow(nullptr, &got))) { str.assign((const char*)borrow_buf, size); this->trans_->consume(size); return size; diff --git a/lib/cpp/src/thrift/protocol/TCompactProtocol.h b/lib/cpp/src/thrift/protocol/TCompactProtocol.h index 5cfb47d2058..2930aba291f 100644 --- a/lib/cpp/src/thrift/protocol/TCompactProtocol.h +++ b/lib/cpp/src/thrift/protocol/TCompactProtocol.h @@ -79,10 +79,10 @@ class TCompactProtocolT : public TVirtualProtocol trans_(trans.get()), lastFieldId_(0), string_limit_(0), - string_buf_(NULL), + string_buf_(nullptr), string_buf_size_(0), container_limit_(0) { - booleanField_.name = NULL; + booleanField_.name = nullptr; boolValue_.hasBoolValue = false; } @@ -93,14 +93,14 @@ class TCompactProtocolT : public TVirtualProtocol trans_(trans.get()), lastFieldId_(0), string_limit_(string_limit), - string_buf_(NULL), + string_buf_(nullptr), string_buf_size_(0), container_limit_(container_limit) { - booleanField_.name = NULL; + booleanField_.name = nullptr; boolValue_.hasBoolValue = false; } - ~TCompactProtocolT() { free(string_buf_); } + ~TCompactProtocolT() override { free(string_buf_); } /** * Writing functions @@ -233,13 +233,13 @@ class TCompactProtocolFactoryT : public TProtocolFactory { TCompactProtocolFactoryT(int32_t string_limit, int32_t container_limit) : string_limit_(string_limit), container_limit_(container_limit) {} - virtual ~TCompactProtocolFactoryT() {} + ~TCompactProtocolFactoryT() override = default; void setStringSizeLimit(int32_t string_limit) { string_limit_ = string_limit; } void setContainerSizeLimit(int32_t container_limit) { container_limit_ = container_limit; } - std::shared_ptr getProtocol(std::shared_ptr trans) { + std::shared_ptr getProtocol(std::shared_ptr trans) override { std::shared_ptr specific_trans = std::dynamic_pointer_cast(trans); TProtocol* prot; if (specific_trans) { diff --git a/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc b/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc index 8efec6edc29..d1e342efd7d 100644 --- a/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc +++ b/lib/cpp/src/thrift/protocol/TCompactProtocol.tcc @@ -198,7 +198,7 @@ template uint32_t TCompactProtocolT::writeBool(const bool value) { uint32_t wsize = 0; - if (booleanField_.name != NULL) { + if (booleanField_.name != nullptr) { // we haven't written the field header yet wsize += writeFieldBeginInternal(booleanField_.name, @@ -207,7 +207,7 @@ uint32_t TCompactProtocolT::writeBool(const bool value) { static_cast(value ? detail::compact::CT_BOOLEAN_TRUE : detail::compact::CT_BOOLEAN_FALSE)); - booleanField_.name = NULL; + booleanField_.name = nullptr; } else { // we're not part of a field, so just write the value wsize @@ -256,7 +256,7 @@ uint32_t TCompactProtocolT::writeDouble(const double dub) { static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) == sizeof(uint64_t)"); static_assert(std::numeric_limits::is_iec559, "std::numeric_limits::is_iec559"); - uint64_t bits = bitwise_cast(dub); + auto bits = bitwise_cast(dub); bits = THRIFT_htolell(bits); trans_->write((uint8_t*)&bits, 8); return 8; @@ -274,7 +274,7 @@ template uint32_t TCompactProtocolT::writeBinary(const std::string& str) { if(str.size() > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); - uint32_t ssize = static_cast(str.size()); + auto ssize = static_cast(str.size()); uint32_t wsize = writeVarint32(ssize) ; // checking ssize + wsize > uint_max, but we don't want to overflow while checking for overflows. // transforming the check to ssize > uint_max - wsize @@ -488,7 +488,7 @@ uint32_t TCompactProtocolT::readFieldBegin(std::string& name, } // mask off the 4 MSB of the type header. it could contain a field id delta. - int16_t modifier = (int16_t)(((uint8_t)byte & 0xf0) >> 4); + auto modifier = (int16_t)(((uint8_t)byte & 0xf0) >> 4); if (modifier == 0) { // not a delta, look ahead for the zigzag varint field id. rsize += readI16(fieldId); @@ -695,9 +695,9 @@ uint32_t TCompactProtocolT::readBinary(std::string& str) { } // Use the heap here to prevent stack overflow for v. large strings - if (size > string_buf_size_ || string_buf_ == NULL) { + if (size > string_buf_size_ || string_buf_ == nullptr) { void* new_string_buf = std::realloc(string_buf_, (uint32_t)size); - if (new_string_buf == NULL) { + if (new_string_buf == nullptr) { throw std::bad_alloc(); } string_buf_ = (uint8_t*)new_string_buf; @@ -735,7 +735,7 @@ uint32_t TCompactProtocolT::readVarint64(int64_t& i64) { const uint8_t* borrowed = trans_->borrow(buf, &buf_size); // Fast path. - if (borrowed != NULL) { + if (borrowed != nullptr) { while (true) { uint8_t byte = borrowed[rsize]; rsize++; diff --git a/lib/cpp/src/thrift/protocol/TDebugProtocol.h b/lib/cpp/src/thrift/protocol/TDebugProtocol.h index c07962475a2..41bb0d4ec94 100644 --- a/lib/cpp/src/thrift/protocol/TDebugProtocol.h +++ b/lib/cpp/src/thrift/protocol/TDebugProtocol.h @@ -138,10 +138,10 @@ class TDebugProtocol : public TVirtualProtocol { */ class TDebugProtocolFactory : public TProtocolFactory { public: - TDebugProtocolFactory() {} - virtual ~TDebugProtocolFactory() {} + TDebugProtocolFactory() = default; + ~TDebugProtocolFactory() override = default; - std::shared_ptr getProtocol(std::shared_ptr trans) { + std::shared_ptr getProtocol(std::shared_ptr trans) override { return std::shared_ptr(new TDebugProtocol(trans)); } }; @@ -159,7 +159,7 @@ template std::string ThriftDebugString(const ThriftStruct& ts) { using namespace apache::thrift::transport; using namespace apache::thrift::protocol; - TMemoryBuffer* buffer = new TMemoryBuffer; + auto* buffer = new TMemoryBuffer; std::shared_ptr trans(buffer); TDebugProtocol protocol(trans); diff --git a/lib/cpp/src/thrift/protocol/THeaderProtocol.h b/lib/cpp/src/thrift/protocol/THeaderProtocol.h index e5e2b657420..0d5018596f7 100644 --- a/lib/cpp/src/thrift/protocol/THeaderProtocol.h +++ b/lib/cpp/src/thrift/protocol/THeaderProtocol.h @@ -63,7 +63,7 @@ class THeaderProtocol : public TVirtualProtocol { resetProtocol(); } - ~THeaderProtocol() {} + ~THeaderProtocol() override = default; /** * Functions to work with headers by calling into THeaderTransport @@ -190,16 +190,16 @@ class THeaderProtocol : public TVirtualProtocol { class THeaderProtocolFactory : public TProtocolFactory { public: - virtual std::shared_ptr getProtocol(std::shared_ptr trans) { - THeaderProtocol* headerProtocol + std::shared_ptr getProtocol(std::shared_ptr trans) override { + auto* headerProtocol = new THeaderProtocol(trans, trans, T_BINARY_PROTOCOL); return std::shared_ptr(headerProtocol); } - virtual std::shared_ptr getProtocol( + std::shared_ptr getProtocol( std::shared_ptr inTrans, - std::shared_ptr outTrans) { - THeaderProtocol* headerProtocol = new THeaderProtocol(inTrans, outTrans, T_BINARY_PROTOCOL); + std::shared_ptr outTrans) override { + auto* headerProtocol = new THeaderProtocol(inTrans, outTrans, T_BINARY_PROTOCOL); return std::shared_ptr(headerProtocol); } }; diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp index db407f2c666..dcd498f7b51 100644 --- a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp @@ -303,9 +303,9 @@ static bool isLowSurrogate(uint16_t val) { class TJSONContext { public: - TJSONContext(){}; + TJSONContext()= default;; - virtual ~TJSONContext(){}; + virtual ~TJSONContext()= default;; /** * Write context data to the transport. Default is to do nothing. @@ -336,7 +336,7 @@ class JSONPairContext : public TJSONContext { public: JSONPairContext() : first_(true), colon_(true) {} - uint32_t write(TTransport& trans) { + uint32_t write(TTransport& trans) override { if (first_) { first_ = false; colon_ = true; @@ -348,7 +348,7 @@ class JSONPairContext : public TJSONContext { } } - uint32_t read(TJSONProtocol::LookaheadReader& reader) { + uint32_t read(TJSONProtocol::LookaheadReader& reader) override { if (first_) { first_ = false; colon_ = true; @@ -361,7 +361,7 @@ class JSONPairContext : public TJSONContext { } // Numbers must be turned into strings if they are the key part of a pair - virtual bool escapeNum() { return colon_; } + bool escapeNum() override { return colon_; } private: bool first_; @@ -374,7 +374,7 @@ class JSONListContext : public TJSONContext { public: JSONListContext() : first_(true) {} - uint32_t write(TTransport& trans) { + uint32_t write(TTransport& trans) override { if (first_) { first_ = false; return 0; @@ -384,7 +384,7 @@ class JSONListContext : public TJSONContext { } } - uint32_t read(TJSONProtocol::LookaheadReader& reader) { + uint32_t read(TJSONProtocol::LookaheadReader& reader) override { if (first_) { first_ = false; return 0; @@ -404,8 +404,7 @@ TJSONProtocol::TJSONProtocol(std::shared_ptr ptrans) reader_(*ptrans) { } -TJSONProtocol::~TJSONProtocol() { -} +TJSONProtocol::~TJSONProtocol() = default; void TJSONProtocol::pushContext(std::shared_ptr c) { contexts_.push(context_); @@ -477,10 +476,10 @@ uint32_t TJSONProtocol::writeJSONBase64(const std::string& str) { result += 2; // For quotes trans_->write(&kJSONStringDelimiter, 1); uint8_t b[4]; - const uint8_t* bytes = (const uint8_t*)str.c_str(); + const auto* bytes = (const uint8_t*)str.c_str(); if (str.length() > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); - uint32_t len = static_cast(str.length()); + auto len = static_cast(str.length()); while (len >= 3) { // Encode 3 bytes at a time base64_encode(bytes, 3, b); @@ -798,10 +797,10 @@ uint32_t TJSONProtocol::readJSONString(std::string& str, bool skipContext) { uint32_t TJSONProtocol::readJSONBase64(std::string& str) { std::string tmp; uint32_t result = readJSONString(tmp); - uint8_t* b = (uint8_t*)tmp.c_str(); + auto* b = (uint8_t*)tmp.c_str(); if (tmp.length() > (std::numeric_limits::max)()) throw TProtocolException(TProtocolException::SIZE_LIMIT); - uint32_t len = static_cast(tmp.length()); + auto len = static_cast(tmp.length()); str.clear(); // Ignore padding if (len >= 2) { @@ -1065,7 +1064,7 @@ uint32_t TJSONProtocol::readBool(bool& value) { // readByte() must be handled properly because boost::lexical cast sees int8_t // as a text type instead of an integer type uint32_t TJSONProtocol::readByte(int8_t& byte) { - int16_t tmp = (int16_t)byte; + auto tmp = (int16_t)byte; uint32_t result = readJSONInteger(tmp); assert(tmp < 256); byte = (int8_t)tmp; diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.h b/lib/cpp/src/thrift/protocol/TJSONProtocol.h index 9c2f8726978..020e61ce8e8 100644 --- a/lib/cpp/src/thrift/protocol/TJSONProtocol.h +++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.h @@ -98,7 +98,7 @@ class TJSONProtocol : public TVirtualProtocol { public: TJSONProtocol(std::shared_ptr ptrans); - ~TJSONProtocol(); + ~TJSONProtocol() override; private: void pushContext(std::shared_ptr c); @@ -286,11 +286,11 @@ class TJSONProtocol : public TVirtualProtocol { */ class TJSONProtocolFactory : public TProtocolFactory { public: - TJSONProtocolFactory() {} + TJSONProtocolFactory() = default; - virtual ~TJSONProtocolFactory() {} + ~TJSONProtocolFactory() override = default; - std::shared_ptr getProtocol(std::shared_ptr trans) { + std::shared_ptr getProtocol(std::shared_ptr trans) override { return std::shared_ptr(new TJSONProtocol(trans)); } }; @@ -308,7 +308,7 @@ template std::string ThriftJSONString(const ThriftStruct& ts) { using namespace apache::thrift::transport; using namespace apache::thrift::protocol; - TMemoryBuffer* buffer = new TMemoryBuffer; + auto* buffer = new TMemoryBuffer; std::shared_ptr trans(buffer); TJSONProtocol protocol(trans); diff --git a/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h b/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h index 94bd82eaed2..0dc9605840c 100644 --- a/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h +++ b/lib/cpp/src/thrift/protocol/TMultiplexedProtocol.h @@ -69,7 +69,7 @@ class TMultiplexedProtocol : public TProtocolDecorator { */ TMultiplexedProtocol(shared_ptr _protocol, const std::string& _serviceName) : TProtocolDecorator(_protocol), serviceName(_serviceName), separator(":") {} - virtual ~TMultiplexedProtocol() {} + ~TMultiplexedProtocol() override = default; /** * Prepends the service name to the function name, separated by TMultiplexedProtocol::SEPARATOR. @@ -82,7 +82,7 @@ class TMultiplexedProtocol : public TProtocolDecorator { */ uint32_t writeMessageBegin_virt(const std::string& _name, const TMessageType _type, - const int32_t _seqid); + const int32_t _seqid) override; private: const std::string serviceName; diff --git a/lib/cpp/src/thrift/protocol/TProtocol.cpp b/lib/cpp/src/thrift/protocol/TProtocol.cpp index c378aca6143..b460455ffbe 100644 --- a/lib/cpp/src/thrift/protocol/TProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/TProtocol.cpp @@ -23,11 +23,11 @@ namespace apache { namespace thrift { namespace protocol { -TProtocol::~TProtocol() {} +TProtocol::~TProtocol() = default; uint32_t TProtocol::skip_virt(TType type) { return ::apache::thrift::protocol::skip(*this, type); } -TProtocolFactory::~TProtocolFactory() {} +TProtocolFactory::~TProtocolFactory() = default; }}} // apache::thrift::protocol diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h index bbc6816cedf..a38660fb733 100644 --- a/lib/cpp/src/thrift/protocol/TProtocol.h +++ b/lib/cpp/src/thrift/protocol/TProtocol.h @@ -583,7 +583,7 @@ class TProtocol { std::shared_ptr ptrans_; private: - TProtocol() {} + TProtocol() = default; uint32_t input_recursion_depth_; uint32_t output_recursion_depth_; uint32_t recursion_limit_; @@ -594,7 +594,7 @@ class TProtocol { */ class TProtocolFactory { public: - TProtocolFactory() {} + TProtocolFactory() = default; virtual ~TProtocolFactory(); diff --git a/lib/cpp/src/thrift/protocol/TProtocolDecorator.h b/lib/cpp/src/thrift/protocol/TProtocolDecorator.h index 743a0f472d0..5258159f149 100644 --- a/lib/cpp/src/thrift/protocol/TProtocolDecorator.h +++ b/lib/cpp/src/thrift/protocol/TProtocolDecorator.h @@ -39,107 +39,107 @@ using std::shared_ptr; */ class TProtocolDecorator : public TProtocol { public: - virtual ~TProtocolDecorator() {} + ~TProtocolDecorator() override = default; // Desc: Initializes the protocol decorator object. TProtocolDecorator(shared_ptr proto) : TProtocol(proto->getTransport()), protocol(proto) {} - virtual uint32_t writeMessageBegin_virt(const std::string& name, + uint32_t writeMessageBegin_virt(const std::string& name, const TMessageType messageType, - const int32_t seqid) { + const int32_t seqid) override { return protocol->writeMessageBegin(name, messageType, seqid); } - virtual uint32_t writeMessageEnd_virt() { return protocol->writeMessageEnd(); } - virtual uint32_t writeStructBegin_virt(const char* name) { + uint32_t writeMessageEnd_virt() override { return protocol->writeMessageEnd(); } + uint32_t writeStructBegin_virt(const char* name) override { return protocol->writeStructBegin(name); } - virtual uint32_t writeStructEnd_virt() { return protocol->writeStructEnd(); } + uint32_t writeStructEnd_virt() override { return protocol->writeStructEnd(); } - virtual uint32_t writeFieldBegin_virt(const char* name, + uint32_t writeFieldBegin_virt(const char* name, const TType fieldType, - const int16_t fieldId) { + const int16_t fieldId) override { return protocol->writeFieldBegin(name, fieldType, fieldId); } - virtual uint32_t writeFieldEnd_virt() { return protocol->writeFieldEnd(); } - virtual uint32_t writeFieldStop_virt() { return protocol->writeFieldStop(); } + uint32_t writeFieldEnd_virt() override { return protocol->writeFieldEnd(); } + uint32_t writeFieldStop_virt() override { return protocol->writeFieldStop(); } - virtual uint32_t writeMapBegin_virt(const TType keyType, + uint32_t writeMapBegin_virt(const TType keyType, const TType valType, - const uint32_t size) { + const uint32_t size) override { return protocol->writeMapBegin(keyType, valType, size); } - virtual uint32_t writeMapEnd_virt() { return protocol->writeMapEnd(); } + uint32_t writeMapEnd_virt() override { return protocol->writeMapEnd(); } - virtual uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) { + uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) override { return protocol->writeListBegin(elemType, size); } - virtual uint32_t writeListEnd_virt() { return protocol->writeListEnd(); } + uint32_t writeListEnd_virt() override { return protocol->writeListEnd(); } - virtual uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) { + uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) override { return protocol->writeSetBegin(elemType, size); } - virtual uint32_t writeSetEnd_virt() { return protocol->writeSetEnd(); } + uint32_t writeSetEnd_virt() override { return protocol->writeSetEnd(); } - virtual uint32_t writeBool_virt(const bool value) { return protocol->writeBool(value); } - virtual uint32_t writeByte_virt(const int8_t byte) { return protocol->writeByte(byte); } - virtual uint32_t writeI16_virt(const int16_t i16) { return protocol->writeI16(i16); } - virtual uint32_t writeI32_virt(const int32_t i32) { return protocol->writeI32(i32); } - virtual uint32_t writeI64_virt(const int64_t i64) { return protocol->writeI64(i64); } + uint32_t writeBool_virt(const bool value) override { return protocol->writeBool(value); } + uint32_t writeByte_virt(const int8_t byte) override { return protocol->writeByte(byte); } + uint32_t writeI16_virt(const int16_t i16) override { return protocol->writeI16(i16); } + uint32_t writeI32_virt(const int32_t i32) override { return protocol->writeI32(i32); } + uint32_t writeI64_virt(const int64_t i64) override { return protocol->writeI64(i64); } - virtual uint32_t writeDouble_virt(const double dub) { return protocol->writeDouble(dub); } - virtual uint32_t writeString_virt(const std::string& str) { return protocol->writeString(str); } - virtual uint32_t writeBinary_virt(const std::string& str) { return protocol->writeBinary(str); } + uint32_t writeDouble_virt(const double dub) override { return protocol->writeDouble(dub); } + uint32_t writeString_virt(const std::string& str) override { return protocol->writeString(str); } + uint32_t writeBinary_virt(const std::string& str) override { return protocol->writeBinary(str); } - virtual uint32_t readMessageBegin_virt(std::string& name, + uint32_t readMessageBegin_virt(std::string& name, TMessageType& messageType, - int32_t& seqid) { + int32_t& seqid) override { return protocol->readMessageBegin(name, messageType, seqid); } - virtual uint32_t readMessageEnd_virt() { return protocol->readMessageEnd(); } + uint32_t readMessageEnd_virt() override { return protocol->readMessageEnd(); } - virtual uint32_t readStructBegin_virt(std::string& name) { + uint32_t readStructBegin_virt(std::string& name) override { return protocol->readStructBegin(name); } - virtual uint32_t readStructEnd_virt() { return protocol->readStructEnd(); } + uint32_t readStructEnd_virt() override { return protocol->readStructEnd(); } - virtual uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) { + uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) override { return protocol->readFieldBegin(name, fieldType, fieldId); } - virtual uint32_t readFieldEnd_virt() { return protocol->readFieldEnd(); } + uint32_t readFieldEnd_virt() override { return protocol->readFieldEnd(); } - virtual uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) { + uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) override { return protocol->readMapBegin(keyType, valType, size); } - virtual uint32_t readMapEnd_virt() { return protocol->readMapEnd(); } + uint32_t readMapEnd_virt() override { return protocol->readMapEnd(); } - virtual uint32_t readListBegin_virt(TType& elemType, uint32_t& size) { + uint32_t readListBegin_virt(TType& elemType, uint32_t& size) override { return protocol->readListBegin(elemType, size); } - virtual uint32_t readListEnd_virt() { return protocol->readListEnd(); } + uint32_t readListEnd_virt() override { return protocol->readListEnd(); } - virtual uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) { + uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) override { return protocol->readSetBegin(elemType, size); } - virtual uint32_t readSetEnd_virt() { return protocol->readSetEnd(); } + uint32_t readSetEnd_virt() override { return protocol->readSetEnd(); } - virtual uint32_t readBool_virt(bool& value) { return protocol->readBool(value); } - virtual uint32_t readBool_virt(std::vector::reference value) { + uint32_t readBool_virt(bool& value) override { return protocol->readBool(value); } + uint32_t readBool_virt(std::vector::reference value) override { return protocol->readBool(value); } - virtual uint32_t readByte_virt(int8_t& byte) { return protocol->readByte(byte); } + uint32_t readByte_virt(int8_t& byte) override { return protocol->readByte(byte); } - virtual uint32_t readI16_virt(int16_t& i16) { return protocol->readI16(i16); } - virtual uint32_t readI32_virt(int32_t& i32) { return protocol->readI32(i32); } - virtual uint32_t readI64_virt(int64_t& i64) { return protocol->readI64(i64); } + uint32_t readI16_virt(int16_t& i16) override { return protocol->readI16(i16); } + uint32_t readI32_virt(int32_t& i32) override { return protocol->readI32(i32); } + uint32_t readI64_virt(int64_t& i64) override { return protocol->readI64(i64); } - virtual uint32_t readDouble_virt(double& dub) { return protocol->readDouble(dub); } + uint32_t readDouble_virt(double& dub) override { return protocol->readDouble(dub); } - virtual uint32_t readString_virt(std::string& str) { return protocol->readString(str); } - virtual uint32_t readBinary_virt(std::string& str) { return protocol->readBinary(str); } + uint32_t readString_virt(std::string& str) override { return protocol->readString(str); } + uint32_t readBinary_virt(std::string& str) override { return protocol->readBinary(str); } private: shared_ptr protocol; diff --git a/lib/cpp/src/thrift/protocol/TProtocolException.h b/lib/cpp/src/thrift/protocol/TProtocolException.h index 10178e11a71..3d44365b91c 100644 --- a/lib/cpp/src/thrift/protocol/TProtocolException.h +++ b/lib/cpp/src/thrift/protocol/TProtocolException.h @@ -59,7 +59,7 @@ class TProtocolException : public apache::thrift::TException { TProtocolException(TProtocolExceptionType type, const std::string& message) : apache::thrift::TException(message), type_(type) {} - virtual ~TProtocolException() noexcept {} + ~TProtocolException() noexcept override = default; /** * Returns an error code that provides information about the type of error @@ -69,7 +69,7 @@ class TProtocolException : public apache::thrift::TException { */ TProtocolExceptionType getType() const { return type_; } - virtual const char* what() const noexcept { + const char* what() const noexcept override { if (message_.empty()) { switch (type_) { case UNKNOWN: diff --git a/lib/cpp/src/thrift/protocol/TVirtualProtocol.h b/lib/cpp/src/thrift/protocol/TVirtualProtocol.h index 4eea5791614..b7fe929af20 100644 --- a/lib/cpp/src/thrift/protocol/TVirtualProtocol.h +++ b/lib/cpp/src/thrift/protocol/TVirtualProtocol.h @@ -315,81 +315,81 @@ class TVirtualProtocol : public Super_ { * Writing functions. */ - virtual uint32_t writeMessageBegin_virt(const std::string& name, + uint32_t writeMessageBegin_virt(const std::string& name, const TMessageType messageType, - const int32_t seqid) { + const int32_t seqid) override { return static_cast(this)->writeMessageBegin(name, messageType, seqid); } - virtual uint32_t writeMessageEnd_virt() { + uint32_t writeMessageEnd_virt() override { return static_cast(this)->writeMessageEnd(); } - virtual uint32_t writeStructBegin_virt(const char* name) { + uint32_t writeStructBegin_virt(const char* name) override { return static_cast(this)->writeStructBegin(name); } - virtual uint32_t writeStructEnd_virt() { return static_cast(this)->writeStructEnd(); } + uint32_t writeStructEnd_virt() override { return static_cast(this)->writeStructEnd(); } - virtual uint32_t writeFieldBegin_virt(const char* name, + uint32_t writeFieldBegin_virt(const char* name, const TType fieldType, - const int16_t fieldId) { + const int16_t fieldId) override { return static_cast(this)->writeFieldBegin(name, fieldType, fieldId); } - virtual uint32_t writeFieldEnd_virt() { return static_cast(this)->writeFieldEnd(); } + uint32_t writeFieldEnd_virt() override { return static_cast(this)->writeFieldEnd(); } - virtual uint32_t writeFieldStop_virt() { return static_cast(this)->writeFieldStop(); } + uint32_t writeFieldStop_virt() override { return static_cast(this)->writeFieldStop(); } - virtual uint32_t writeMapBegin_virt(const TType keyType, + uint32_t writeMapBegin_virt(const TType keyType, const TType valType, - const uint32_t size) { + const uint32_t size) override { return static_cast(this)->writeMapBegin(keyType, valType, size); } - virtual uint32_t writeMapEnd_virt() { return static_cast(this)->writeMapEnd(); } + uint32_t writeMapEnd_virt() override { return static_cast(this)->writeMapEnd(); } - virtual uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) { + uint32_t writeListBegin_virt(const TType elemType, const uint32_t size) override { return static_cast(this)->writeListBegin(elemType, size); } - virtual uint32_t writeListEnd_virt() { return static_cast(this)->writeListEnd(); } + uint32_t writeListEnd_virt() override { return static_cast(this)->writeListEnd(); } - virtual uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) { + uint32_t writeSetBegin_virt(const TType elemType, const uint32_t size) override { return static_cast(this)->writeSetBegin(elemType, size); } - virtual uint32_t writeSetEnd_virt() { return static_cast(this)->writeSetEnd(); } + uint32_t writeSetEnd_virt() override { return static_cast(this)->writeSetEnd(); } - virtual uint32_t writeBool_virt(const bool value) { + uint32_t writeBool_virt(const bool value) override { return static_cast(this)->writeBool(value); } - virtual uint32_t writeByte_virt(const int8_t byte) { + uint32_t writeByte_virt(const int8_t byte) override { return static_cast(this)->writeByte(byte); } - virtual uint32_t writeI16_virt(const int16_t i16) { + uint32_t writeI16_virt(const int16_t i16) override { return static_cast(this)->writeI16(i16); } - virtual uint32_t writeI32_virt(const int32_t i32) { + uint32_t writeI32_virt(const int32_t i32) override { return static_cast(this)->writeI32(i32); } - virtual uint32_t writeI64_virt(const int64_t i64) { + uint32_t writeI64_virt(const int64_t i64) override { return static_cast(this)->writeI64(i64); } - virtual uint32_t writeDouble_virt(const double dub) { + uint32_t writeDouble_virt(const double dub) override { return static_cast(this)->writeDouble(dub); } - virtual uint32_t writeString_virt(const std::string& str) { + uint32_t writeString_virt(const std::string& str) override { return static_cast(this)->writeString(str); } - virtual uint32_t writeBinary_virt(const std::string& str) { + uint32_t writeBinary_virt(const std::string& str) override { return static_cast(this)->writeBinary(str); } @@ -397,81 +397,81 @@ class TVirtualProtocol : public Super_ { * Reading functions */ - virtual uint32_t readMessageBegin_virt(std::string& name, + uint32_t readMessageBegin_virt(std::string& name, TMessageType& messageType, - int32_t& seqid) { + int32_t& seqid) override { return static_cast(this)->readMessageBegin(name, messageType, seqid); } - virtual uint32_t readMessageEnd_virt() { return static_cast(this)->readMessageEnd(); } + uint32_t readMessageEnd_virt() override { return static_cast(this)->readMessageEnd(); } - virtual uint32_t readStructBegin_virt(std::string& name) { + uint32_t readStructBegin_virt(std::string& name) override { return static_cast(this)->readStructBegin(name); } - virtual uint32_t readStructEnd_virt() { return static_cast(this)->readStructEnd(); } + uint32_t readStructEnd_virt() override { return static_cast(this)->readStructEnd(); } - virtual uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) { + uint32_t readFieldBegin_virt(std::string& name, TType& fieldType, int16_t& fieldId) override { return static_cast(this)->readFieldBegin(name, fieldType, fieldId); } - virtual uint32_t readFieldEnd_virt() { return static_cast(this)->readFieldEnd(); } + uint32_t readFieldEnd_virt() override { return static_cast(this)->readFieldEnd(); } - virtual uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) { + uint32_t readMapBegin_virt(TType& keyType, TType& valType, uint32_t& size) override { return static_cast(this)->readMapBegin(keyType, valType, size); } - virtual uint32_t readMapEnd_virt() { return static_cast(this)->readMapEnd(); } + uint32_t readMapEnd_virt() override { return static_cast(this)->readMapEnd(); } - virtual uint32_t readListBegin_virt(TType& elemType, uint32_t& size) { + uint32_t readListBegin_virt(TType& elemType, uint32_t& size) override { return static_cast(this)->readListBegin(elemType, size); } - virtual uint32_t readListEnd_virt() { return static_cast(this)->readListEnd(); } + uint32_t readListEnd_virt() override { return static_cast(this)->readListEnd(); } - virtual uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) { + uint32_t readSetBegin_virt(TType& elemType, uint32_t& size) override { return static_cast(this)->readSetBegin(elemType, size); } - virtual uint32_t readSetEnd_virt() { return static_cast(this)->readSetEnd(); } + uint32_t readSetEnd_virt() override { return static_cast(this)->readSetEnd(); } - virtual uint32_t readBool_virt(bool& value) { + uint32_t readBool_virt(bool& value) override { return static_cast(this)->readBool(value); } - virtual uint32_t readBool_virt(std::vector::reference value) { + uint32_t readBool_virt(std::vector::reference value) override { return static_cast(this)->readBool(value); } - virtual uint32_t readByte_virt(int8_t& byte) { + uint32_t readByte_virt(int8_t& byte) override { return static_cast(this)->readByte(byte); } - virtual uint32_t readI16_virt(int16_t& i16) { + uint32_t readI16_virt(int16_t& i16) override { return static_cast(this)->readI16(i16); } - virtual uint32_t readI32_virt(int32_t& i32) { + uint32_t readI32_virt(int32_t& i32) override { return static_cast(this)->readI32(i32); } - virtual uint32_t readI64_virt(int64_t& i64) { + uint32_t readI64_virt(int64_t& i64) override { return static_cast(this)->readI64(i64); } - virtual uint32_t readDouble_virt(double& dub) { + uint32_t readDouble_virt(double& dub) override { return static_cast(this)->readDouble(dub); } - virtual uint32_t readString_virt(std::string& str) { + uint32_t readString_virt(std::string& str) override { return static_cast(this)->readString(str); } - virtual uint32_t readBinary_virt(std::string& str) { + uint32_t readBinary_virt(std::string& str) override { return static_cast(this)->readBinary(str); } - virtual uint32_t skip_virt(TType type) { return static_cast(this)->skip(type); } + uint32_t skip_virt(TType type) override { return static_cast(this)->skip(type); } /* * Provide a default skip() implementation that uses non-virtual read @@ -484,7 +484,7 @@ class TVirtualProtocol : public Super_ { * correct parent implementation, if desired. */ uint32_t skip(TType type) { - Protocol_* const prot = static_cast(this); + auto* const prot = static_cast(this); return ::apache::thrift::protocol::skip(*prot, type); } diff --git a/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp b/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp index f77c993f4dc..78c3b399f57 100644 --- a/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp +++ b/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp @@ -157,7 +157,7 @@ void TQIODeviceTransport::flush() { uint8_t* TQIODeviceTransport::borrow(uint8_t* buf, uint32_t* len) { (void)buf; (void)len; - return NULL; + return nullptr; } void TQIODeviceTransport::consume(uint32_t len) { diff --git a/lib/cpp/src/thrift/qt/TQIODeviceTransport.h b/lib/cpp/src/thrift/qt/TQIODeviceTransport.h index 91ce8d5f680..e0cdd1831be 100644 --- a/lib/cpp/src/thrift/qt/TQIODeviceTransport.h +++ b/lib/cpp/src/thrift/qt/TQIODeviceTransport.h @@ -37,12 +37,12 @@ class TQIODeviceTransport : public apache::thrift::transport::TVirtualTransport { public: explicit TQIODeviceTransport(std::shared_ptr dev); - virtual ~TQIODeviceTransport(); + ~TQIODeviceTransport() override; - void open(); + void open() override; bool isOpen(); - bool peek(); - void close(); + bool peek() override; + void close() override; uint32_t readAll(uint8_t* buf, uint32_t len); uint32_t read(uint8_t* buf, uint32_t len); @@ -50,7 +50,7 @@ class TQIODeviceTransport void write(const uint8_t* buf, uint32_t len); uint32_t write_partial(const uint8_t* buf, uint32_t len); - void flush(); + void flush() override; uint8_t* borrow(uint8_t* buf, uint32_t* len); void consume(uint32_t len); diff --git a/lib/cpp/src/thrift/qt/TQTcpServer.cpp b/lib/cpp/src/thrift/qt/TQTcpServer.cpp index 99aad071a2c..bd39893e31e 100644 --- a/lib/cpp/src/thrift/qt/TQTcpServer.cpp +++ b/lib/cpp/src/thrift/qt/TQTcpServer.cpp @@ -67,8 +67,7 @@ TQTcpServer::TQTcpServer(shared_ptr server, connect(server.get(), SIGNAL(newConnection()), SLOT(processIncoming())); } -TQTcpServer::~TQTcpServer() { -} +TQTcpServer::~TQTcpServer() = default; void TQTcpServer::processIncoming() { while (server_->hasPendingConnections()) { @@ -100,7 +99,7 @@ void TQTcpServer::processIncoming() { } void TQTcpServer::beginDecode() { - QTcpSocket* connection(qobject_cast(sender())); + auto* connection(qobject_cast(sender())); Q_ASSERT(connection); if (ctxMap_.find(connection) == ctxMap_.end()) { @@ -125,7 +124,7 @@ void TQTcpServer::beginDecode() { } void TQTcpServer::socketClosed() { - QTcpSocket* connection(qobject_cast(sender())); + auto* connection(qobject_cast(sender())); Q_ASSERT(connection); scheduleDeleteConnectionContext(connection); } diff --git a/lib/cpp/src/thrift/qt/TQTcpServer.h b/lib/cpp/src/thrift/qt/TQTcpServer.h index 8e3fe3a83d2..25994ab8d01 100644 --- a/lib/cpp/src/thrift/qt/TQTcpServer.h +++ b/lib/cpp/src/thrift/qt/TQTcpServer.h @@ -50,8 +50,8 @@ class TQTcpServer : public QObject { TQTcpServer(std::shared_ptr server, std::shared_ptr processor, std::shared_ptr protocolFactory, - QObject* parent = NULL); - virtual ~TQTcpServer(); + QObject* parent = nullptr); + ~TQTcpServer() override; private Q_SLOTS: void processIncoming(); diff --git a/lib/cpp/src/thrift/server/TConnectedClient.cpp b/lib/cpp/src/thrift/server/TConnectedClient.cpp index acdaa77cb71..9a78e3e9b18 100644 --- a/lib/cpp/src/thrift/server/TConnectedClient.cpp +++ b/lib/cpp/src/thrift/server/TConnectedClient.cpp @@ -42,11 +42,10 @@ TConnectedClient::TConnectedClient(const shared_ptr& processor, outputProtocol_(outputProtocol), eventHandler_(eventHandler), client_(client), - opaqueContext_(0) { + opaqueContext_(nullptr) { } -TConnectedClient::~TConnectedClient() { -} +TConnectedClient::~TConnectedClient() = default; void TConnectedClient::run() { if (eventHandler_) { diff --git a/lib/cpp/src/thrift/server/TConnectedClient.h b/lib/cpp/src/thrift/server/TConnectedClient.h index 19e70c1801d..071571a8867 100644 --- a/lib/cpp/src/thrift/server/TConnectedClient.h +++ b/lib/cpp/src/thrift/server/TConnectedClient.h @@ -58,7 +58,7 @@ class TConnectedClient : public apache::thrift::concurrency::Runnable { /** * Destructor. */ - virtual ~TConnectedClient(); + ~TConnectedClient() override; /** * Drive the client until it is done. @@ -76,7 +76,7 @@ class TConnectedClient : public apache::thrift::concurrency::Runnable { * handle unexpected exceptions by logging * cleanup() */ - virtual void run() /* override */; + void run() override /* override */; protected: /** diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.cpp b/lib/cpp/src/thrift/server/TNonblockingServer.cpp index bee3e3b4938..4e62324cb51 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.cpp +++ b/lib/cpp/src/thrift/server/TNonblockingServer.cpp @@ -215,7 +215,7 @@ class TNonblockingServer::TConnection { /// Constructor TConnection(std::shared_ptr socket, TNonblockingIOThread* ioThread) { - readBuffer_ = NULL; + readBuffer_ = nullptr; readBufferSize_ = 0; ioThread_ = ioThread; @@ -327,7 +327,7 @@ class TNonblockingServer::TConnection::Task : public Runnable { serverEventHandler_(connection_->getServerEventHandler()), connectionContext_(connection_->getConnectionContext()) {} - void run() { + void run() override { try { for (;;) { if (serverEventHandler_) { @@ -380,7 +380,7 @@ void TNonblockingServer::TConnection::init(TNonblockingIOThread* ioThread) { readBufferPos_ = 0; readWant_ = 0; - writeBuffer_ = NULL; + writeBuffer_ = nullptr; writeBufferSize_ = 0; writeBufferPos_ = 0; largestWriteBufferSize_ = 0; @@ -407,7 +407,7 @@ void TNonblockingServer::TConnection::init(TNonblockingIOThread* ioThread) { if (serverEventHandler_) { connectionContext_ = serverEventHandler_->createContext(inputProtocol_, outputProtocol_); } else { - connectionContext_ = NULL; + connectionContext_ = nullptr; } // Get the processor @@ -570,7 +570,7 @@ bool TNonblockingServer::getHeaderTransport() { // Currently if there is no output protocol factory, // we assume header transport (without having to create // a new transport and check) - return getOutputProtocolFactory() == NULL; + return getOutputProtocolFactory() == nullptr; } /** @@ -687,7 +687,7 @@ void TNonblockingServer::TConnection::transition() { socketState_ = SOCKET_SEND; // Put the frame size into the write buffer - int32_t frameSize = (int32_t)htonl(writeBufferSize_ - 4); + auto frameSize = (int32_t)htonl(writeBufferSize_ - 4); memcpy(writeBuffer_, &frameSize, 4); // Socket into write mode @@ -720,7 +720,7 @@ void TNonblockingServer::TConnection::transition() { case APP_INIT: // Clear write buffer variables - writeBuffer_ = NULL; + writeBuffer_ = nullptr; writeBufferPos_ = 0; writeBufferSize_ = 0; @@ -749,8 +749,8 @@ void TNonblockingServer::TConnection::transition() { newSize *= 2; } - uint8_t* newBuffer = (uint8_t*)std::realloc(readBuffer_, newSize); - if (newBuffer == NULL) { + auto* newBuffer = (uint8_t*)std::realloc(readBuffer_, newSize); + if (newBuffer == nullptr) { // nothing else to be done... throw std::bad_alloc(); } @@ -829,7 +829,7 @@ void TNonblockingServer::TConnection::setFlags(short eventFlags) { event_base_set(ioThread_->getEventBase(), &event_); // Add the event - if (event_add(&event_, 0) == -1) { + if (event_add(&event_, nullptr) == -1) { GlobalOutput.perror("TConnection::setFlags(): could not event_add", THRIFT_GET_SOCKET_ERROR); } } @@ -843,7 +843,7 @@ void TNonblockingServer::TConnection::close() { if (serverEventHandler_) { serverEventHandler_->deleteContext(connectionContext_, inputProtocol_, outputProtocol_); } - ioThread_ = NULL; + ioThread_ = nullptr; // Close the socket tSocket_->close(); @@ -862,7 +862,7 @@ void TNonblockingServer::TConnection::close() { void TNonblockingServer::TConnection::checkIdleBufferMemLimit(size_t readLimit, size_t writeLimit) { if (readLimit > 0 && readBufferSize_ > readLimit) { free(readBuffer_); - readBuffer_ = NULL; + readBuffer_ = nullptr; readBufferSize_ = 0; } @@ -910,7 +910,7 @@ TNonblockingServer::TConnection* TNonblockingServer::createConnection(std::share TNonblockingIOThread* ioThread = ioThreads_[selectedThreadIdx].get(); // Check the connection stack to see if we can re-use - TConnection* result = NULL; + TConnection* result = nullptr; if (connectionStack_.empty()) { result = new TConnection(socket, ioThread); ++numTConnections_; @@ -979,7 +979,7 @@ void TNonblockingServer::handleEvent(THRIFT_SOCKET fd, short which) { TConnection* clientConnection = createConnection(clientSocket); // Fail fast if we could not create a TConnection object - if (clientConnection == NULL) { + if (clientConnection == nullptr) { GlobalOutput.printf("thriftServerEventHandler: failed TConnection factory"); clientSocket->close(); return; @@ -1143,7 +1143,7 @@ void TNonblockingServer::registerEvents(event_base* user_event_base) { void TNonblockingServer::serve() { if (ioThreads_.empty()) - registerEvents(NULL); + registerEvents(nullptr); // Run the primary (listener) IO thread loop in our main thread; this will // only return when the server is shutting down. @@ -1164,7 +1164,7 @@ TNonblockingIOThread::TNonblockingIOThread(TNonblockingServer* server, number_(number), listenSocket_(listenSocket), useHighPriority_(useHighPriority), - eventBase_(NULL), + eventBase_(nullptr), ownEventBase_(false) { notificationPipeFDs_[0] = -1; notificationPipeFDs_[1] = -1; @@ -1231,9 +1231,9 @@ void TNonblockingIOThread::createNotificationPipe() { void TNonblockingIOThread::registerEvents() { threadId_ = Thread::get_current(); - assert(eventBase_ == 0); + assert(eventBase_ == nullptr); eventBase_ = getServer()->getUserEventBase(); - if (eventBase_ == NULL) { + if (eventBase_ == nullptr) { eventBase_ = event_base_new(); ownEventBase_ = true; } @@ -1255,7 +1255,7 @@ void TNonblockingIOThread::registerEvents() { event_base_set(eventBase_, &serverEvent_); // Add the event and start up the server - if (-1 == event_add(&serverEvent_, 0)) { + if (-1 == event_add(&serverEvent_, nullptr)) { throw TException( "TNonblockingServer::serve(): " "event_add() failed on server listen event"); @@ -1276,7 +1276,7 @@ void TNonblockingIOThread::registerEvents() { event_base_set(eventBase_, ¬ificationEvent_); // Add the event and start up the server - if (-1 == event_add(¬ificationEvent_, 0)) { + if (-1 == event_add(¬ificationEvent_, nullptr)) { throw TException( "TNonblockingServer::serve(): " "event_add() failed on task-done notification event"); @@ -1368,16 +1368,16 @@ bool TNonblockingIOThread::notify(TNonblockingServer::TConnection* conn) { /* static */ void TNonblockingIOThread::notifyHandler(evutil_socket_t fd, short which, void* v) { - TNonblockingIOThread* ioThread = (TNonblockingIOThread*)v; + auto* ioThread = (TNonblockingIOThread*)v; assert(ioThread); (void)which; while (true) { - TNonblockingServer::TConnection* connection = 0; + TNonblockingServer::TConnection* connection = nullptr; const int kSize = sizeof(connection); long nBytes = recv(fd, cast_sockopt(&connection), kSize, 0); if (nBytes == kSize) { - if (connection == NULL) { + if (connection == nullptr) { // this is the command to stop our thread, exit the handler! ioThread->breakLoop(false); return; @@ -1420,7 +1420,7 @@ void TNonblockingIOThread::breakLoop(bool error) { // same thread, this means the thread can't be blocking in the event // loop either. if (!Thread::is_current(threadId_)) { - notify(NULL); + notify(nullptr); } else { // cause the loop to stop ASAP - even if it has things to do in it event_base_loopbreak(eventBase_); @@ -1457,14 +1457,14 @@ void TNonblockingIOThread::setCurrentThreadHighPriority(bool value) { } void TNonblockingIOThread::run() { - if (eventBase_ == NULL) { + if (eventBase_ == nullptr) { registerEvents(); } if (useHighPriority_) { setCurrentThreadHighPriority(true); } - if (eventBase_ != NULL) + if (eventBase_ != nullptr) { GlobalOutput.printf("TNonblockingServer: IO thread #%d entering loop...", number_); // Run libevent engine, never returns, invokes calls to eventHandler diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.h b/lib/cpp/src/thrift/server/TNonblockingServer.h index 2c2389c3c1f..82bc375bd6e 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.h +++ b/lib/cpp/src/thrift/server/TNonblockingServer.h @@ -280,7 +280,7 @@ class TNonblockingServer : public TServer { numIOThreads_ = DEFAULT_IO_THREADS; nextIOThread_ = 0; useHighPriorityIOThreads_ = false; - userEventBase_ = NULL; + userEventBase_ = nullptr; threadPoolProcessing_ = false; numTConnections_ = 0; numActiveProcessors_ = 0; @@ -376,7 +376,7 @@ class TNonblockingServer : public TServer { setThreadManager(threadManager); } - ~TNonblockingServer(); + ~TNonblockingServer() override; void setThreadManager(std::shared_ptr threadManager); @@ -669,12 +669,12 @@ class TNonblockingServer : public TServer { * Main workhorse function, starts up the server listening on a port and * loops over the libevent handler. */ - void serve(); + void serve() override; /** * Causes the server to terminate gracefully (can be called from any thread). */ - void stop(); + void stop() override; /// Creates a socket to listen on and binds it to the local port. void createAndListenOnSocket(); @@ -741,7 +741,7 @@ class TNonblockingIOThread : public Runnable { THRIFT_SOCKET listenSocket, bool useHighPriority); - ~TNonblockingIOThread(); + ~TNonblockingIOThread() override; // Returns the event-base for this thread. event_base* getEventBase() const { return eventBase_; } @@ -772,7 +772,7 @@ class TNonblockingIOThread : public Runnable { bool notify(TNonblockingServer::TConnection* conn); // Enters the event loop and does not return until a call to stop(). - virtual void run(); + void run() override; // Exits the event loop as soon as possible. void stop(); diff --git a/lib/cpp/src/thrift/server/TServer.h b/lib/cpp/src/thrift/server/TServer.h index 3c6d8185082..d2eabde1211 100644 --- a/lib/cpp/src/thrift/server/TServer.h +++ b/lib/cpp/src/thrift/server/TServer.h @@ -48,7 +48,7 @@ using apache::thrift::transport::TTransportFactory; */ class TServerEventHandler { public: - virtual ~TServerEventHandler() {} + virtual ~TServerEventHandler() = default; /** * Called before the server begins. @@ -62,7 +62,7 @@ class TServerEventHandler { std::shared_ptr output) { (void)input; (void)output; - return NULL; + return nullptr; } /** @@ -89,7 +89,7 @@ class TServerEventHandler { /** * Prevent direct instantiation. */ - TServerEventHandler() {} + TServerEventHandler() = default; }; /** @@ -98,14 +98,14 @@ class TServerEventHandler { */ class TServer : public concurrency::Runnable { public: - virtual ~TServer() {} + ~TServer() override = default; virtual void serve() = 0; virtual void stop() {} // Allows running the server as a Runnable thread - virtual void run() { serve(); } + void run() override { serve(); } std::shared_ptr getProcessorFactory() { return processorFactory_; } diff --git a/lib/cpp/src/thrift/server/TServerFramework.cpp b/lib/cpp/src/thrift/server/TServerFramework.cpp index cbeaa24ff5c..35f3b254d88 100644 --- a/lib/cpp/src/thrift/server/TServerFramework.cpp +++ b/lib/cpp/src/thrift/server/TServerFramework.cpp @@ -91,8 +91,7 @@ TServerFramework::TServerFramework(const shared_ptr& processor, limit_(INT64_MAX) { } -TServerFramework::~TServerFramework() { -} +TServerFramework::~TServerFramework() = default; template static void releaseOneDescriptor(const string& name, T& pTransport) { diff --git a/lib/cpp/src/thrift/server/TServerFramework.h b/lib/cpp/src/thrift/server/TServerFramework.h index eaacce5f263..dac79ef5959 100644 --- a/lib/cpp/src/thrift/server/TServerFramework.h +++ b/lib/cpp/src/thrift/server/TServerFramework.h @@ -75,7 +75,7 @@ class TServerFramework : public TServer { const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory); - virtual ~TServerFramework(); + ~TServerFramework() override; /** * Accept clients from the TServerTransport and add them for processing. @@ -84,12 +84,12 @@ class TServerFramework : public TServer { * Post-conditions (return guarantees): * The serverTransport will be closed. */ - virtual void serve(); + void serve() override; /** * Interrupt serve() so that it meets post-conditions and returns. */ - virtual void stop(); + void stop() override; /** * Get the concurrent client limit. diff --git a/lib/cpp/src/thrift/server/TSimpleServer.cpp b/lib/cpp/src/thrift/server/TSimpleServer.cpp index 716234d0e12..ba7a183db03 100644 --- a/lib/cpp/src/thrift/server/TSimpleServer.cpp +++ b/lib/cpp/src/thrift/server/TSimpleServer.cpp @@ -78,8 +78,7 @@ TSimpleServer::TSimpleServer(const shared_ptr& processor, TServerFramework::setConcurrentClientLimit(1); } -TSimpleServer::~TSimpleServer() { -} +TSimpleServer::~TSimpleServer() = default; /** * The main body of customized implementation for TSimpleServer is quite simple: diff --git a/lib/cpp/src/thrift/server/TSimpleServer.h b/lib/cpp/src/thrift/server/TSimpleServer.h index 454922591c4..3afeb79d51d 100644 --- a/lib/cpp/src/thrift/server/TSimpleServer.h +++ b/lib/cpp/src/thrift/server/TSimpleServer.h @@ -61,14 +61,14 @@ class TSimpleServer : public TServerFramework { const std::shared_ptr& inputProtocolFactory, const std::shared_ptr& outputProtocolFactory); - virtual ~TSimpleServer(); + ~TSimpleServer() override; protected: - virtual void onClientConnected(const std::shared_ptr& pClient) /* override */; - virtual void onClientDisconnected(TConnectedClient* pClient) /* override */; + void onClientConnected(const std::shared_ptr& pClient) override /* override */; + void onClientDisconnected(TConnectedClient* pClient) override /* override */; private: - void setConcurrentClientLimit(int64_t newLimit); // hide + void setConcurrentClientLimit(int64_t newLimit) override; // hide }; } } diff --git a/lib/cpp/src/thrift/server/TThreadPoolServer.cpp b/lib/cpp/src/thrift/server/TThreadPoolServer.cpp index ee345a98966..121dde3ead1 100644 --- a/lib/cpp/src/thrift/server/TThreadPoolServer.cpp +++ b/lib/cpp/src/thrift/server/TThreadPoolServer.cpp @@ -91,8 +91,7 @@ TThreadPoolServer::TThreadPoolServer(const shared_ptr& processor, taskExpiration_(0) { } -TThreadPoolServer::~TThreadPoolServer() { -} +TThreadPoolServer::~TThreadPoolServer() = default; void TThreadPoolServer::serve() { TServerFramework::serve(); diff --git a/lib/cpp/src/thrift/server/TThreadPoolServer.h b/lib/cpp/src/thrift/server/TThreadPoolServer.h index 121998c4d2f..a9411b86ca7 100644 --- a/lib/cpp/src/thrift/server/TThreadPoolServer.h +++ b/lib/cpp/src/thrift/server/TThreadPoolServer.h @@ -69,13 +69,13 @@ class TThreadPoolServer : public TServerFramework { const std::shared_ptr& threadManager = apache::thrift::concurrency::ThreadManager::newSimpleThreadManager()); - virtual ~TThreadPoolServer(); + ~TThreadPoolServer() override; /** * Post-conditions (return guarantees): * There will be no clients connected. */ - virtual void serve(); + void serve() override; virtual int64_t getTimeout() const; virtual void setTimeout(int64_t value); @@ -86,8 +86,8 @@ class TThreadPoolServer : public TServerFramework { virtual std::shared_ptr getThreadManager() const; protected: - virtual void onClientConnected(const std::shared_ptr& pClient) /* override */; - virtual void onClientDisconnected(TConnectedClient* pClient) /* override */; + void onClientConnected(const std::shared_ptr& pClient) override /* override */; + void onClientDisconnected(TConnectedClient* pClient) override /* override */; std::shared_ptr threadManager_; std::atomic timeout_; diff --git a/lib/cpp/src/thrift/server/TThreadedServer.cpp b/lib/cpp/src/thrift/server/TThreadedServer.cpp index ed2d80d000e..79dcc70f79c 100644 --- a/lib/cpp/src/thrift/server/TThreadedServer.cpp +++ b/lib/cpp/src/thrift/server/TThreadedServer.cpp @@ -89,8 +89,7 @@ TThreadedServer::TThreadedServer(const shared_ptr& processor, threadFactory_(threadFactory) { } -TThreadedServer::~TThreadedServer() { -} +TThreadedServer::~TThreadedServer() = default; void TThreadedServer::serve() { TServerFramework::serve(); @@ -107,7 +106,7 @@ void TThreadedServer::serve() { void TThreadedServer::drainDeadClients() { // we're in a monitor here while (!deadClientMap_.empty()) { - ClientMap::iterator it = deadClientMap_.begin(); + auto it = deadClientMap_.begin(); it->second->join(); deadClientMap_.erase(it); } @@ -125,9 +124,9 @@ void TThreadedServer::onClientConnected(const shared_ptr& pCli void TThreadedServer::onClientDisconnected(TConnectedClient* pClient) { Synchronized sync(clientMonitor_); drainDeadClients(); // use the outgoing thread to do some maintenance on our dead client backlog - ClientMap::iterator it = activeClientMap_.find(pClient); + auto it = activeClientMap_.find(pClient); if (it != activeClientMap_.end()) { - ClientMap::iterator end = it; + auto end = it; deadClientMap_.insert(it, ++end); activeClientMap_.erase(it); } @@ -140,8 +139,7 @@ TThreadedServer::TConnectedClientRunner::TConnectedClientRunner(const shared_ptr : pClient_(pClient) { } -TThreadedServer::TConnectedClientRunner::~TConnectedClientRunner() { -} +TThreadedServer::TConnectedClientRunner::~TConnectedClientRunner() = default; void TThreadedServer::TConnectedClientRunner::run() /* override */ { pClient_->run(); // Run the client diff --git a/lib/cpp/src/thrift/server/TThreadedServer.h b/lib/cpp/src/thrift/server/TThreadedServer.h index 9fc9d1125b5..756e5a06377 100644 --- a/lib/cpp/src/thrift/server/TThreadedServer.h +++ b/lib/cpp/src/thrift/server/TThreadedServer.h @@ -77,13 +77,13 @@ class TThreadedServer : public TServerFramework { = std::shared_ptr( new apache::thrift::concurrency::ThreadFactory(false))); - virtual ~TThreadedServer(); + ~TThreadedServer() override; /** * Post-conditions (return guarantees): * There will be no clients connected. */ - virtual void serve(); + void serve() override; protected: /** @@ -95,12 +95,12 @@ class TThreadedServer : public TServerFramework { /** * Implementation of TServerFramework::onClientConnected */ - virtual void onClientConnected(const std::shared_ptr& pClient) /* override */; + void onClientConnected(const std::shared_ptr& pClient) override /* override */; /** * Implementation of TServerFramework::onClientDisconnected */ - virtual void onClientDisconnected(TConnectedClient *pClient) /* override */; + void onClientDisconnected(TConnectedClient *pClient) override /* override */; std::shared_ptr threadFactory_; @@ -115,8 +115,8 @@ class TThreadedServer : public TServerFramework { { public: TConnectedClientRunner(const std::shared_ptr& pClient); - virtual ~TConnectedClientRunner(); - void run() /* override */; + ~TConnectedClientRunner() override; + void run() override /* override */; private: std::shared_ptr pClient_; }; diff --git a/lib/cpp/src/thrift/transport/TBufferTransports.cpp b/lib/cpp/src/thrift/transport/TBufferTransports.cpp index 9ac2f844b90..4bb8713de02 100644 --- a/lib/cpp/src/thrift/transport/TBufferTransports.cpp +++ b/lib/cpp/src/thrift/transport/TBufferTransports.cpp @@ -29,7 +29,7 @@ namespace thrift { namespace transport { uint32_t TBufferedTransport::readSlow(uint8_t* buf, uint32_t len) { - uint32_t have = static_cast(rBound_ - rBase_); + auto have = static_cast(rBound_ - rBase_); // We should only take the slow path if we can't satisfy the read // with the data already in the buffer. @@ -61,8 +61,8 @@ uint32_t TBufferedTransport::readSlow(uint8_t* buf, uint32_t len) { } void TBufferedTransport::writeSlow(const uint8_t* buf, uint32_t len) { - uint32_t have_bytes = static_cast(wBase_ - wBuf_.get()); - uint32_t space = static_cast(wBound_ - wBase_); + auto have_bytes = static_cast(wBase_ - wBuf_.get()); + auto space = static_cast(wBound_ - wBase_); // We should only take the slow path if we can't accommodate the write // with the free space already in the buffer. assert(wBound_ - wBase_ < static_cast(len)); @@ -114,12 +114,12 @@ const uint8_t* TBufferedTransport::borrowSlow(uint8_t* buf, uint32_t* len) { (void)len; // Simply return NULL. We don't know if there is actually data available on // the underlying transport, so calling read() might block. - return NULL; + return nullptr; } void TBufferedTransport::flush() { // Write out any data waiting in the write buffer. - uint32_t have_bytes = static_cast(wBase_ - wBuf_.get()); + auto have_bytes = static_cast(wBase_ - wBuf_.get()); if (have_bytes > 0) { // Note that we reset wBase_ prior to the underlying write // to ensure we're in a sane state (i.e. internal buffer cleaned) @@ -134,7 +134,7 @@ void TBufferedTransport::flush() { uint32_t TFramedTransport::readSlow(uint8_t* buf, uint32_t len) { uint32_t want = len; - uint32_t have = static_cast(rBound_ - rBase_); + auto have = static_cast(rBound_ - rBase_); // We should only take the slow path if we can't satisfy the read // with the data already in the buffer. @@ -217,7 +217,7 @@ bool TFramedTransport::readFrame() { void TFramedTransport::writeSlow(const uint8_t* buf, uint32_t len) { // Double buffer size until sufficient. - uint32_t have = static_cast(wBase_ - wBuf_.get()); + auto have = static_cast(wBase_ - wBuf_.get()); uint32_t new_size = wBufSize_; if (len + have < have /* overflow */ || len + have > 0x7fffffff) { throw TTransportException(TTransportException::BAD_ARGS, @@ -231,7 +231,7 @@ void TFramedTransport::writeSlow(const uint8_t* buf, uint32_t len) { // so we can use realloc here. // Allocate new buffer. - uint8_t* new_buf = new uint8_t[new_size]; + auto* new_buf = new uint8_t[new_size]; // Copy the old buffer to the new one. memcpy(new_buf, wBuf_.get(), have); @@ -292,12 +292,12 @@ const uint8_t* TFramedTransport::borrowSlow(uint8_t* buf, uint32_t* len) { // Don't try to be clever with shifting buffers. // If the fast path failed let the protocol use its slow path. // Besides, who is going to try to borrow across messages? - return NULL; + return nullptr; } uint32_t TFramedTransport::readEnd() { // include framing bytes - uint32_t bytes_read = static_cast(rBound_ - rBuf_.get() + sizeof(uint32_t)); + auto bytes_read = static_cast(rBound_ - rBuf_.get() + sizeof(uint32_t)); if (rBufSize_ > bufReclaimThresh_) { rBufSize_ = 0; @@ -335,7 +335,7 @@ uint32_t TMemoryBuffer::readSlow(uint8_t* buf, uint32_t len) { uint32_t TMemoryBuffer::readAppendToString(std::string& str, uint32_t len) { // Don't get some stupid assertion failure. - if (buffer_ == NULL) { + if (buffer_ == nullptr) { return 0; } @@ -372,8 +372,8 @@ void TMemoryBuffer::ensureCanWrite(uint32_t len) { } // Allocate into a new pointer so we don't bork ours if it fails. - uint8_t* new_buffer = static_cast(std::realloc(buffer_, new_size)); - if (new_buffer == NULL) { + auto* new_buffer = static_cast(std::realloc(buffer_, new_size)); + if (new_buffer == nullptr) { throw std::bad_alloc(); } @@ -408,7 +408,7 @@ const uint8_t* TMemoryBuffer::borrowSlow(uint8_t* buf, uint32_t* len) { *len = available_read(); return rBase_; } - return NULL; + return nullptr; } } } diff --git a/lib/cpp/src/thrift/transport/TBufferTransports.h b/lib/cpp/src/thrift/transport/TBufferTransports.h index 70122753505..a008fa19da8 100644 --- a/lib/cpp/src/thrift/transport/TBufferTransports.h +++ b/lib/cpp/src/thrift/transport/TBufferTransports.h @@ -148,7 +148,7 @@ class TBufferBase : public TVirtualTransport { * performance-sensitive operation, so it is okay to just leave it to * the concrete class to set up pointers correctly. */ - TBufferBase() : rBase_(NULL), rBound_(NULL), wBase_(NULL), wBound_(NULL) {} + TBufferBase() : rBase_(nullptr), rBound_(nullptr), wBase_(nullptr), wBound_(nullptr) {} /// Convenience mutator for setting the read buffer. void setReadBuffer(uint8_t* buf, uint32_t len) { @@ -162,7 +162,7 @@ class TBufferBase : public TVirtualTransport { wBound_ = buf + len; } - virtual ~TBufferBase() {} + ~TBufferBase() override = default; /// Reads begin here. uint8_t* rBase_; @@ -215,32 +215,32 @@ class TBufferedTransport : public TVirtualTransportopen(); } + void open() override { transport_->open(); } bool isOpen() { return transport_->isOpen(); } - bool peek() { + bool peek() override { if (rBase_ == rBound_) { setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_)); } return (rBound_ > rBase_); } - void close() { + void close() override { flush(); transport_->close(); } - virtual uint32_t readSlow(uint8_t* buf, uint32_t len); + uint32_t readSlow(uint8_t* buf, uint32_t len) override; - virtual void writeSlow(const uint8_t* buf, uint32_t len); + void writeSlow(const uint8_t* buf, uint32_t len) override; void flush() override; /** * Returns the origin of the underlying transport */ - virtual const std::string getOrigin() { return transport_->getOrigin(); } + const std::string getOrigin() const override { return transport_->getOrigin(); } /** * The following behavior is currently implemented by TBufferedTransport, @@ -253,7 +253,7 @@ class TBufferedTransport : public TVirtualTransport getUnderlyingTransport() { return transport_; } @@ -284,9 +284,9 @@ class TBufferedTransport : public TVirtualTransport initPointers(); } - void open() { transport_->open(); } + void open() override { transport_->open(); } bool isOpen() { return transport_->isOpen(); } - bool peek() { return (rBase_ < rBound_) || transport_->peek(); } + bool peek() override { return (rBase_ < rBound_) || transport_->peek(); } - void close() { + void close() override { flush(); transport_->close(); } @@ -360,11 +360,11 @@ class TFramedTransport : public TVirtualTransport void flush() override; - uint32_t readEnd(); + uint32_t readEnd() override; - uint32_t writeEnd(); + uint32_t writeEnd() override; - const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len); + const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) override; std::shared_ptr getUnderlyingTransport() { return transport_; } @@ -377,7 +377,7 @@ class TFramedTransport : public TVirtualTransport /** * Returns the origin of the underlying transport */ - virtual const std::string getOrigin() { return transport_->getOrigin(); } + const std::string getOrigin() const override { return transport_->getOrigin(); } /** * Set the maximum size of the frame at read @@ -399,7 +399,7 @@ class TFramedTransport : public TVirtualTransport virtual bool readFrame(); void initPointers() { - setReadBuffer(NULL, 0); + setReadBuffer(nullptr, 0); setWriteBuffer(wBuf_.get(), wBufSize_); // Pad the buffer so we can insert the size later. @@ -423,9 +423,9 @@ class TFramedTransport : public TVirtualTransport */ class TFramedTransportFactory : public TTransportFactory { public: - TFramedTransportFactory() {} + TFramedTransportFactory() = default; - virtual ~TFramedTransportFactory() {} + ~TFramedTransportFactory() override = default; /** * Wraps the transport into a framed one. @@ -451,10 +451,10 @@ class TMemoryBuffer : public TVirtualTransport { maxBufferSize_ = (std::numeric_limits::max)(); - if (buf == NULL && size != 0) { + if (buf == nullptr && size != 0) { assert(owner); buf = (uint8_t*)std::malloc(size); - if (buf == NULL) { + if (buf == nullptr) { throw std::bad_alloc(); } } @@ -503,7 +503,7 @@ class TMemoryBuffer : public TVirtualTransport { * Construct a TMemoryBuffer with a default-sized buffer, * owned by the TMemoryBuffer object. */ - TMemoryBuffer() { initCommon(NULL, defaultSize, true, 0); } + TMemoryBuffer() { initCommon(nullptr, defaultSize, true, 0); } /** * Construct a TMemoryBuffer with a buffer of a specified size, @@ -511,7 +511,7 @@ class TMemoryBuffer : public TVirtualTransport { * * @param sz The initial size of the buffer. */ - TMemoryBuffer(uint32_t sz) { initCommon(NULL, sz, true, 0); } + TMemoryBuffer(uint32_t sz) { initCommon(nullptr, sz, true, 0); } /** * Construct a TMemoryBuffer with buf as its initial contents. @@ -524,7 +524,7 @@ class TMemoryBuffer : public TVirtualTransport { * @param policy See @link MemoryPolicy @endlink . */ TMemoryBuffer(uint8_t* buf, uint32_t sz, MemoryPolicy policy = OBSERVE) { - if (buf == NULL && sz != 0) { + if (buf == nullptr && sz != 0) { throw TTransportException(TTransportException::BAD_ARGS, "TMemoryBuffer given null buffer with non-zero size."); } @@ -535,7 +535,7 @@ class TMemoryBuffer : public TVirtualTransport { initCommon(buf, sz, policy == TAKE_OWNERSHIP, sz); break; case COPY: - initCommon(NULL, sz, true, 0); + initCommon(nullptr, sz, true, 0); this->write(buf, sz); break; default: @@ -544,7 +544,7 @@ class TMemoryBuffer : public TVirtualTransport { } } - ~TMemoryBuffer() { + ~TMemoryBuffer() override { if (owner_) { std::free(buffer_); } @@ -552,11 +552,11 @@ class TMemoryBuffer : public TVirtualTransport { bool isOpen() { return true; } - bool peek() { return (rBase_ < wBase_); } + bool peek() override { return (rBase_ < wBase_); } - void open() {} + void open() override {} - void close() {} + void close() override {} // TODO(dreiss): Make bufPtr const. void getBuffer(uint8_t** bufPtr, uint32_t* sz) { @@ -565,7 +565,7 @@ class TMemoryBuffer : public TVirtualTransport { } std::string getBufferAsString() { - if (buffer_ == NULL) { + if (buffer_ == nullptr) { return ""; } uint8_t* buf; @@ -575,7 +575,7 @@ class TMemoryBuffer : public TVirtualTransport { } void appendBufferToString(std::string& str) { - if (buffer_ == NULL) { + if (buffer_ == nullptr) { return; } uint8_t* buf; @@ -634,9 +634,9 @@ class TMemoryBuffer : public TVirtualTransport { uint32_t readAppendToString(std::string& str, uint32_t len); // return number of bytes read - uint32_t readEnd() { + uint32_t readEnd() override { // This cast should be safe, because buffer_'s size is a uint32_t - uint32_t bytes = static_cast(rBase_ - buffer_); + auto bytes = static_cast(rBase_ - buffer_); if (rBase_ == wBase_) { resetBuffer(); } @@ -644,7 +644,7 @@ class TMemoryBuffer : public TVirtualTransport { } // Return number of bytes written - uint32_t writeEnd() { + uint32_t writeEnd() override { // This cast should be safe, because buffer_'s size is a uint32_t return static_cast(wBase_ - buffer_); } @@ -719,11 +719,11 @@ class TMemoryBuffer : public TVirtualTransport { // Compute the position and available data for reading. void computeRead(uint32_t len, uint8_t** out_start, uint32_t* out_give); - uint32_t readSlow(uint8_t* buf, uint32_t len); + uint32_t readSlow(uint8_t* buf, uint32_t len) override; - void writeSlow(const uint8_t* buf, uint32_t len); + void writeSlow(const uint8_t* buf, uint32_t len) override; - const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len); + const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) override; // Data buffer uint8_t* buffer_; diff --git a/lib/cpp/src/thrift/transport/TFDTransport.h b/lib/cpp/src/thrift/transport/TFDTransport.h index 5593d43dff0..ede5ccb5bd0 100644 --- a/lib/cpp/src/thrift/transport/TFDTransport.h +++ b/lib/cpp/src/thrift/transport/TFDTransport.h @@ -43,7 +43,7 @@ class TFDTransport : public TVirtualTransport { TFDTransport(int fd, ClosePolicy close_policy = NO_CLOSE_ON_DESTROY) : fd_(fd), close_policy_(close_policy) {} - ~TFDTransport() { + ~TFDTransport() override { if (close_policy_ == CLOSE_ON_DESTROY) { try { close(); @@ -55,9 +55,9 @@ class TFDTransport : public TVirtualTransport { bool isOpen() { return fd_ >= 0; } - void open() {} + void open() override {} - void close(); + void close() override; uint32_t read(uint8_t* buf, uint32_t len); diff --git a/lib/cpp/src/thrift/transport/TFileTransport.cpp b/lib/cpp/src/thrift/transport/TFileTransport.cpp index 5df2778e5e2..1eefb899310 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.cpp +++ b/lib/cpp/src/thrift/transport/TFileTransport.cpp @@ -65,8 +65,8 @@ using namespace apache::thrift::concurrency; TFileTransport::TFileTransport(string path, bool readOnly) : readState_(), - readBuff_(NULL), - currentEvent_(NULL), + readBuff_(nullptr), + currentEvent_(nullptr), readBuffSize_(DEFAULT_READ_BUFF_SIZE), readTimeout_(NO_TAIL_READ_TIMEOUT), chunkSize_(DEFAULT_CHUNK_SIZE), @@ -78,8 +78,8 @@ TFileTransport::TFileTransport(string path, bool readOnly) eofSleepTime_(DEFAULT_EOF_SLEEP_TIME_US), corruptedEventSleepTime_(DEFAULT_CORRUPTED_SLEEP_TIME_US), writerThreadIOErrorSleepTime_(DEFAULT_WRITER_THREAD_SLEEP_TIME_US), - dequeueBuffer_(NULL), - enqueueBuffer_(NULL), + dequeueBuffer_(nullptr), + enqueueBuffer_(nullptr), notFull_(&mutex_), notEmpty_(&mutex_), closing_(false), @@ -141,22 +141,22 @@ TFileTransport::~TFileTransport() { if (dequeueBuffer_) { delete dequeueBuffer_; - dequeueBuffer_ = NULL; + dequeueBuffer_ = nullptr; } if (enqueueBuffer_) { delete enqueueBuffer_; - enqueueBuffer_ = NULL; + enqueueBuffer_ = nullptr; } if (readBuff_) { delete[] readBuff_; - readBuff_ = NULL; + readBuff_ = nullptr; } if (currentEvent_) { delete currentEvent_; - currentEvent_ = NULL; + currentEvent_ = nullptr; } // close logfile @@ -275,7 +275,7 @@ bool TFileTransport::swapEventBuffers(const std::chrono::time_pointgetNext())) { + while (nullptr != (outEvent = dequeueBuffer_->getNext())) { // Remove an event from the buffer and write it out to disk. If there is any IO error, for // instance, // the output file is unmounted or deleted, then this event is dropped. However, the writer @@ -422,9 +422,9 @@ void TFileTransport::writerThread() { if (chunk1 != chunk2) { // refetch the offset to keep in sync offset_ = THRIFT_LSEEK(fd_, 0, SEEK_CUR); - int32_t padding = (int32_t)((offset_ / chunkSize_ + 1) * chunkSize_ - offset_); + auto padding = (int32_t)((offset_ / chunkSize_ + 1) * chunkSize_ - offset_); - uint8_t* zeros = new uint8_t[padding]; + auto* zeros = new uint8_t[padding]; memset(zeros, '\0', padding); boost::scoped_array array(zeros); if (-1 == ::write(fd_, zeros, padding)) { @@ -587,7 +587,7 @@ uint32_t TFileTransport::read(uint8_t* buf, uint32_t len) { memcpy(buf, currentEvent_->eventBuff_ + currentEvent_->eventBuffPos_, remaining); } delete (currentEvent_); - currentEvent_ = NULL; + currentEvent_ = nullptr; return remaining; } @@ -630,12 +630,12 @@ eventInfo* TFileTransport::readEvent() { } else if (readTimeout_ == NO_TAIL_READ_TIMEOUT) { // reset state readState_.resetState(0); - return NULL; + return nullptr; } else if (readTimeout_ > 0) { // timeout already expired once if (readTries > 0) { readState_.resetState(0); - return NULL; + return nullptr; } else { THRIFT_SLEEP_USEC(readTimeout_ * 1000); readTries++; @@ -709,7 +709,7 @@ eventInfo* TFileTransport::readEvent() { eventInfo* completeEvent = readState_.event_; completeEvent->eventBuffPos_ = 0; - readState_.event_ = NULL; + readState_.event_ = nullptr; readState_.resetState(readState_.bufferPtr_); // exit criteria @@ -778,7 +778,7 @@ void TFileTransport::performRecovery() { // pretty hosed at this stage, rewind the file back to the last successful // point and punt on the error readState_.resetState(readState_.lastDispatchPtr_); - currentEvent_ = NULL; + currentEvent_ = nullptr; char errorMsg[1024]; sprintf(errorMsg, "TFileTransport: log file corrupted at offset: %lu", @@ -827,7 +827,7 @@ void TFileTransport::seekToChunk(int32_t chunk) { off_t newOffset = off_t(chunk) * chunkSize_; offset_ = ::THRIFT_LSEEK(fd_, newOffset, SEEK_SET); readState_.resetAllValues(); - currentEvent_ = NULL; + currentEvent_ = nullptr; if (offset_ == -1) { GlobalOutput("TFileTransport: lseek error in seekToChunk"); throw TTransportException("TFileTransport: lseek error in seekToChunk"); @@ -841,7 +841,7 @@ void TFileTransport::seekToChunk(int32_t chunk) { shared_ptr event; while ((offset_ + readState_.bufferPtr_) < minEndOffset) { event.reset(readEvent()); - if (event.get() == NULL) { + if (event.get() == nullptr) { break; } } @@ -918,7 +918,7 @@ TFileTransportBuffer::~TFileTransportBuffer() { delete buffer_[i]; } delete[] buffer_; - buffer_ = NULL; + buffer_ = nullptr; } } @@ -943,7 +943,7 @@ eventInfo* TFileTransportBuffer::getNext() { return buffer_[readPoint_++]; } else { // no more entries - return NULL; + return nullptr; } } @@ -1020,7 +1020,7 @@ void TFileProcessor::process(uint32_t numEvents, bool tail) { // bad form to use exceptions for flow control but there is really // no other way around it try { - processor_->process(inputProtocol, outputProtocol, NULL); + processor_->process(inputProtocol, outputProtocol, nullptr); numProcessed++; if ((numEvents > 0) && (numProcessed == numEvents)) { return; @@ -1051,7 +1051,7 @@ void TFileProcessor::processChunk() { // bad form to use exceptions for flow control but there is really // no other way around it try { - processor_->process(inputProtocol, outputProtocol, NULL); + processor_->process(inputProtocol, outputProtocol, nullptr); if (curChunk != inputTransport_->getCurChunk()) { break; } diff --git a/lib/cpp/src/thrift/transport/TFileTransport.h b/lib/cpp/src/thrift/transport/TFileTransport.h index e7c1ca626a5..0df5cf909d4 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.h +++ b/lib/cpp/src/thrift/transport/TFileTransport.h @@ -48,7 +48,7 @@ typedef struct eventInfo { uint32_t eventSize_; uint32_t eventBuffPos_; - eventInfo() : eventBuff_(NULL), eventSize_(0), eventBuffPos_(0){}; + eventInfo() : eventBuff_(nullptr), eventSize_(0), eventBuffPos_(0){}; ~eventInfo() { if (eventBuff_) { delete[] eventBuff_; @@ -85,7 +85,7 @@ typedef struct readState { if (event_) { delete (event_); } - event_ = 0; + event_ = nullptr; } inline uint32_t getEventSize() { @@ -94,7 +94,7 @@ typedef struct readState { } readState() { - event_ = 0; + event_ = nullptr; resetAllValues(); } @@ -174,24 +174,24 @@ class TFileWriterTransport : virtual public TTransport { class TFileTransport : public TFileReaderTransport, public TFileWriterTransport { public: TFileTransport(std::string path, bool readOnly = false); - ~TFileTransport(); + ~TFileTransport() override; // TODO: what is the correct behaviour for this? // the log file is generally always open bool isOpen() const override { return true; } void write(const uint8_t* buf, uint32_t len); - void flush(); + void flush() override; uint32_t readAll(uint8_t* buf, uint32_t len); uint32_t read(uint8_t* buf, uint32_t len); bool peek() override; // log-file specific functions - void seekToChunk(int32_t chunk); - void seekToEnd(); - uint32_t getNumChunks(); - uint32_t getCurChunk(); + void seekToChunk(int32_t chunk) override; + void seekToEnd() override; + uint32_t getNumChunks() override; + uint32_t getCurChunk() override; // for changing the output file void resetOutputFile(int fd, std::string filename, off_t offset); @@ -206,15 +206,15 @@ class TFileTransport : public TFileReaderTransport, public TFileWriterTransport static const int32_t TAIL_READ_TIMEOUT = -1; static const int32_t NO_TAIL_READ_TIMEOUT = 0; - void setReadTimeout(int32_t readTimeout) { readTimeout_ = readTimeout; } - int32_t getReadTimeout() { return readTimeout_; } + void setReadTimeout(int32_t readTimeout) override { readTimeout_ = readTimeout; } + int32_t getReadTimeout() override { return readTimeout_; } - void setChunkSize(uint32_t chunkSize) { + void setChunkSize(uint32_t chunkSize) override { if (chunkSize) { chunkSize_ = chunkSize; } } - uint32_t getChunkSize() { return chunkSize_; } + uint32_t getChunkSize() override { return chunkSize_; } void setEventBufferSize(uint32_t bufferSize) { if (bufferAndThreadInitialized_) { @@ -273,7 +273,7 @@ class TFileTransport : public TFileReaderTransport, public TFileWriterTransport // control for writer thread static void* startWriterThread(void* ptr) { static_cast(ptr)->writerThread(); - return NULL; + return nullptr; } void writerThread(); diff --git a/lib/cpp/src/thrift/transport/THeaderTransport.cpp b/lib/cpp/src/thrift/transport/THeaderTransport.cpp index 25084ec59cb..b582d8da7b2 100644 --- a/lib/cpp/src/thrift/transport/THeaderTransport.cpp +++ b/lib/cpp/src/thrift/transport/THeaderTransport.cpp @@ -197,7 +197,7 @@ void THeaderTransport::readHeaderFormat(uint16_t headerSize, uint32_t sz) { readHeaders_.clear(); // Clear out any previous headers. // skip over already processed magic(4), seqId(4), headerSize(2) - uint8_t* ptr = reinterpret_cast(rBuf_.get() + 10); + auto* ptr = reinterpret_cast(rBuf_.get() + 10); // Catch integer overflow, check for reasonable header size if (headerSize >= 16384) { @@ -275,9 +275,9 @@ void THeaderTransport::untransform(uint8_t* ptr, uint32_t sz) { stream.avail_in = sz; // Setting these to 0 means use the default free/alloc functions - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; + stream.zalloc = (alloc_func)nullptr; + stream.zfree = (free_func)nullptr; + stream.opaque = (voidpf)nullptr; err = inflateInit(&stream); if (err != Z_OK) { throw TApplicationException(TApplicationException::MISSING_RESULT, @@ -317,7 +317,7 @@ void THeaderTransport::untransform(uint8_t* ptr, uint32_t sz) { void THeaderTransport::resizeTransformBuffer(uint32_t additionalSize) { if (tBufSize_ < wBufSize_ + DEFAULT_BUFFER_SIZE) { uint32_t new_size = wBufSize_ + DEFAULT_BUFFER_SIZE + additionalSize; - uint8_t* new_buf = new uint8_t[new_size]; + auto* new_buf = new uint8_t[new_size]; tBuf_.reset(new_buf); tBufSize_ = new_size; } @@ -337,9 +337,9 @@ void THeaderTransport::transform(uint8_t* ptr, uint32_t sz) { stream.next_in = ptr; stream.avail_in = sz; - stream.zalloc = (alloc_func)0; - stream.zfree = (free_func)0; - stream.opaque = (voidpf)0; + stream.zalloc = (alloc_func)nullptr; + stream.zfree = (free_func)nullptr; + stream.opaque = (voidpf)nullptr; err = deflateInit(&stream, Z_DEFAULT_COMPRESSION); if (err != Z_OK) { throw TTransportException(TTransportException::CORRUPTED_DATA, @@ -389,7 +389,7 @@ uint32_t THeaderTransport::getWriteBytes() { * Automatically advances ptr to after the written portion */ void THeaderTransport::writeString(uint8_t*& ptr, const string& str) { - int32_t strLen = safe_numeric_cast(str.length()); + auto strLen = safe_numeric_cast(str.length()); ptr += writeVarint32(strLen, ptr); memcpy(ptr, str.c_str(), strLen); // no need to write \0 ptr += strLen; @@ -484,7 +484,7 @@ void THeaderTransport::flush() { // write info headers // for now only write kv-headers - int32_t headerCount = safe_numeric_cast(writeHeaders_.size()); + auto headerCount = safe_numeric_cast(writeHeaders_.size()); if (headerCount > 0) { pkt += writeVarint32(infoIdType::KEYVALUE, pkt); // Write key-value headers count @@ -526,7 +526,7 @@ void THeaderTransport::flush() { outTransport_->write(pktStart, szHbo - haveBytes + 4); outTransport_->write(wBuf_.get(), haveBytes); } else if (clientType == THRIFT_FRAMED_BINARY || clientType == THRIFT_FRAMED_COMPACT) { - uint32_t szHbo = (uint32_t)haveBytes; + auto szHbo = (uint32_t)haveBytes; uint32_t szNbo = htonl(szHbo); outTransport_->write(reinterpret_cast(&szNbo), 4); diff --git a/lib/cpp/src/thrift/transport/THeaderTransport.h b/lib/cpp/src/thrift/transport/THeaderTransport.h index 350702dcf51..d1e9d433922 100644 --- a/lib/cpp/src/thrift/transport/THeaderTransport.h +++ b/lib/cpp/src/thrift/transport/THeaderTransport.h @@ -82,7 +82,7 @@ class THeaderTransport : public TVirtualTransport transport) : THttpTransport(transport) { } -THttpServer::~THttpServer() { -} +THttpServer::~THttpServer() = default; #if defined(_MSC_VER) || defined(__MINGW32__) #define THRIFT_GMTIME(TM, TIME) gmtime_s(&TM, &TIME) @@ -52,14 +51,14 @@ THttpServer::~THttpServer() { void THttpServer::parseHeader(char* header) { char* colon = strchr(header, ':'); - if (colon == NULL) { + if (colon == nullptr) { return; } size_t sz = colon - header; char* value = colon + 1; if (THRIFT_strncasecmp(header, "Transfer-Encoding", sz) == 0) { - if (THRIFT_strcasestr(value, "chunked") != NULL) { + if (THRIFT_strcasestr(value, "chunked") != nullptr) { chunked_ = true; } } else if (THRIFT_strncasecmp(header, "Content-length", sz) == 0) { @@ -74,7 +73,7 @@ bool THttpServer::parseStatusLine(char* status) { char* method = status; char* path = strchr(method, ' '); - if (path == NULL) { + if (path == nullptr) { throw TTransportException(string("Bad Status: ") + status); } @@ -83,7 +82,7 @@ bool THttpServer::parseStatusLine(char* status) { }; char* http = strchr(path, ' '); - if (http == NULL) { + if (http == nullptr) { throw TTransportException(string("Bad Status: ") + status); } *http = '\0'; @@ -149,7 +148,7 @@ std::string THttpServer::getTimeRFC1123() { = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; char buff[128]; - time_t t = time(NULL); + time_t t = time(nullptr); struct tm tmb; THRIFT_GMTIME(tmb, t); diff --git a/lib/cpp/src/thrift/transport/THttpServer.h b/lib/cpp/src/thrift/transport/THttpServer.h index d72cb13cd67..0e83399d110 100644 --- a/lib/cpp/src/thrift/transport/THttpServer.h +++ b/lib/cpp/src/thrift/transport/THttpServer.h @@ -30,14 +30,14 @@ class THttpServer : public THttpTransport { public: THttpServer(std::shared_ptr transport); - virtual ~THttpServer(); + ~THttpServer() override; void flush() override; protected: void readHeaders(); - virtual void parseHeader(char* header); - virtual bool parseStatusLine(char* status); + void parseHeader(char* header) override; + bool parseStatusLine(char* status) override; std::string getTimeRFC1123(); }; @@ -46,9 +46,9 @@ class THttpServer : public THttpTransport { */ class THttpServerTransportFactory : public TTransportFactory { public: - THttpServerTransportFactory() {} + THttpServerTransportFactory() = default; - virtual ~THttpServerTransportFactory() {} + ~THttpServerTransportFactory() override = default; /** * Wraps the transport into a buffered one. diff --git a/lib/cpp/src/thrift/transport/THttpTransport.cpp b/lib/cpp/src/thrift/transport/THttpTransport.cpp index 6ccc03427a3..aea2b2847d7 100644 --- a/lib/cpp/src/thrift/transport/THttpTransport.cpp +++ b/lib/cpp/src/thrift/transport/THttpTransport.cpp @@ -39,7 +39,7 @@ THttpTransport::THttpTransport(std::shared_ptr transport) chunkedDone_(false), chunkSize_(0), contentLength_(0), - httpBuf_(NULL), + httpBuf_(nullptr), httpPos_(0), httpBufLen_(0), httpBufSize_(1024) { @@ -48,14 +48,14 @@ THttpTransport::THttpTransport(std::shared_ptr transport) void THttpTransport::init() { httpBuf_ = (char*)std::malloc(httpBufSize_ + 1); - if (httpBuf_ == NULL) { + if (httpBuf_ == nullptr) { throw std::bad_alloc(); } httpBuf_[httpBufLen_] = '\0'; } THttpTransport::~THttpTransport() { - if (httpBuf_ != NULL) { + if (httpBuf_ != nullptr) { std::free(httpBuf_); } } @@ -132,7 +132,7 @@ void THttpTransport::readChunkedFooters() { uint32_t THttpTransport::parseChunkSize(char* line) { char* semi = strchr(line, ';'); - if (semi != NULL) { + if (semi != nullptr) { *semi = '\0'; } uint32_t size = 0; @@ -166,12 +166,12 @@ uint32_t THttpTransport::readContent(uint32_t size) { char* THttpTransport::readLine() { while (true) { - char* eol = NULL; + char* eol = nullptr; eol = strstr(httpBuf_ + httpPos_, CRLF); // No CRLF yet? - if (eol == NULL) { + if (eol == nullptr) { // Shift whatever we have now to front and refill shift(); refill(); @@ -203,7 +203,7 @@ void THttpTransport::refill() { if (avail <= (httpBufSize_ / 4)) { httpBufSize_ *= 2; char* tmpBuf = (char*)std::realloc(httpBuf_, httpBufSize_ + 1); - if (tmpBuf == NULL) { + if (tmpBuf == nullptr) { throw std::bad_alloc(); } httpBuf_ = tmpBuf; @@ -257,7 +257,7 @@ void THttpTransport::write(const uint8_t* buf, uint32_t len) { writeBuffer_.write(buf, len); } -const std::string THttpTransport::getOrigin() { +const std::string THttpTransport::getOrigin() const { std::ostringstream oss; if (!origin_.empty()) { oss << origin_ << ", "; diff --git a/lib/cpp/src/thrift/transport/THttpTransport.h b/lib/cpp/src/thrift/transport/THttpTransport.h index e46ab7f66b4..1cf36b20680 100644 --- a/lib/cpp/src/thrift/transport/THttpTransport.h +++ b/lib/cpp/src/thrift/transport/THttpTransport.h @@ -38,25 +38,25 @@ class THttpTransport : public TVirtualTransport { public: THttpTransport(std::shared_ptr transport); - virtual ~THttpTransport(); + ~THttpTransport() override; - void open() { transport_->open(); } + void open() override { transport_->open(); } bool isOpen() { return transport_->isOpen(); } - bool peek() { return transport_->peek(); } + bool peek() override { return transport_->peek(); } - void close() { transport_->close(); } + void close() override { transport_->close(); } uint32_t read(uint8_t* buf, uint32_t len); - uint32_t readEnd(); + uint32_t readEnd() override; void write(const uint8_t* buf, uint32_t len); - virtual void flush() = 0; + void flush() override = 0; - virtual const std::string getOrigin(); + const std::string getOrigin() const override; protected: std::shared_ptr transport_; diff --git a/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h b/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h index 215c405e3b0..a38bf126631 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h +++ b/lib/cpp/src/thrift/transport/TNonblockingSSLServerSocket.h @@ -66,7 +66,7 @@ class TNonblockingSSLServerSocket : public TNonblockingServerSocket { std::shared_ptr factory); protected: - std::shared_ptr createSocket(THRIFT_SOCKET socket); + std::shared_ptr createSocket(THRIFT_SOCKET socket) override; std::shared_ptr factory_; }; } diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp index 3d34ccac526..51990b0e4e4 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp @@ -193,7 +193,7 @@ void TNonblockingServerSocket::listen() { hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; // If address is not specified use wildcard address (NULL) - TGetAddrInfoWrapper info(address_.empty() ? NULL : &address_[0], port, &hints); + TGetAddrInfoWrapper info(address_.empty() ? nullptr : &address_[0], port, &hints); error = info.init(); if (error) { @@ -206,13 +206,13 @@ void TNonblockingServerSocket::listen() { // Pick the ipv6 address first since ipv4 addresses can be mapped // into ipv6 space. for (res = info.res(); res; res = res->ai_next) { - if (res->ai_family == AF_INET6 || res->ai_next == NULL) + if (res->ai_family == AF_INET6 || res->ai_next == nullptr) break; } if (!path_.empty()) { serverSocket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP); - } else if (res != NULL) { + } else if (res != nullptr) { serverSocket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol); } @@ -372,7 +372,7 @@ void TNonblockingServerSocket::listen() { // Unix Domain Socket size_t len = path_.size() + 1; - if (len > sizeof(((sockaddr_un*)NULL)->sun_path)) { + if (len > sizeof(((sockaddr_un*)nullptr)->sun_path)) { errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::listen() Unix Domain socket path too long", errno_copy); throw TTransportException(TTransportException::NOT_OPEN, @@ -384,7 +384,7 @@ void TNonblockingServerSocket::listen() { address.sun_family = AF_UNIX; memcpy(address.sun_path, path_.c_str(), len); - socklen_t structlen = static_cast(sizeof(address)); + auto structlen = static_cast(sizeof(address)); if (!address.sun_path[0]) { // abstract namespace socket #ifdef __linux__ @@ -428,10 +428,10 @@ void TNonblockingServerSocket::listen() { GlobalOutput.perror("TNonblockingServerSocket::getPort() getsockname() ", errno_copy); } else { if (sa.ss_family == AF_INET6) { - const struct sockaddr_in6* sin = reinterpret_cast(&sa); + const auto* sin = reinterpret_cast(&sa); listenPort_ = ntohs(sin->sin6_port); } else { - const struct sockaddr_in* sin = reinterpret_cast(&sa); + const auto* sin = reinterpret_cast(&sa); listenPort_ = ntohs(sin->sin_port); } } diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h index 8466512ab57..a68c28d22ce 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h +++ b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.h @@ -71,7 +71,7 @@ class TNonblockingServerSocket : public TNonblockingServerTransport { */ TNonblockingServerSocket(const std::string& path); - virtual ~TNonblockingServerSocket(); + ~TNonblockingServerSocket() override; void setSendTimeout(int sendTimeout); void setRecvTimeout(int recvTimeout); @@ -97,17 +97,17 @@ class TNonblockingServerSocket : public TNonblockingServerTransport { // socket, this is the place to do it. void setAcceptCallback(const socket_func_t& acceptCallback) { acceptCallback_ = acceptCallback; } - THRIFT_SOCKET getSocketFD() { return serverSocket_; } + THRIFT_SOCKET getSocketFD() override { return serverSocket_; } - int getPort(); + int getPort() override; - int getListenPort(); + int getListenPort() override; void listen() override; void close() override; protected: - std::shared_ptr acceptImpl(); + std::shared_ptr acceptImpl() override; virtual std::shared_ptr createSocket(THRIFT_SOCKET client); private: diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h b/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h index 3142e19dbac..f8113286992 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h +++ b/lib/cpp/src/thrift/transport/TNonblockingServerTransport.h @@ -35,7 +35,7 @@ namespace transport { */ class TNonblockingServerTransport { public: - virtual ~TNonblockingServerTransport() {} + virtual ~TNonblockingServerTransport() = default; /** * Starts the server transport listening for new connections. Prior to this @@ -82,7 +82,7 @@ class TNonblockingServerTransport { virtual void close() = 0; protected: - TNonblockingServerTransport() {} + TNonblockingServerTransport() = default; /** * Subclasses should implement this function for accept. diff --git a/lib/cpp/src/thrift/transport/TSSLServerSocket.h b/lib/cpp/src/thrift/transport/TSSLServerSocket.h index 8b75de84d40..44df4327687 100644 --- a/lib/cpp/src/thrift/transport/TSSLServerSocket.h +++ b/lib/cpp/src/thrift/transport/TSSLServerSocket.h @@ -66,7 +66,7 @@ class TSSLServerSocket : public TServerSocket { std::shared_ptr factory); protected: - std::shared_ptr createSocket(THRIFT_SOCKET socket); + std::shared_ptr createSocket(THRIFT_SOCKET socket) override; std::shared_ptr factory_; }; } diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp index 718e9b1533d..636bb2d7ef1 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp @@ -95,7 +95,7 @@ static CRYPTO_dynlock_value* dyn_create(const char*, int) { } static void dyn_lock(int mode, struct CRYPTO_dynlock_value* lock, const char*, int) { - if (lock != NULL) { + if (lock != nullptr) { if (mode & CRYPTO_LOCK) { lock->mutex.lock(); } else { @@ -180,7 +180,7 @@ SSLContext::SSLContext(const SSLProtocol& protocol) { throw TSSLException("SSL_CTX_new: Unknown protocol"); } - if (ctx_ == NULL) { + if (ctx_ == nullptr) { string errors; buildErrors(errors); throw TSSLException("SSL_CTX_new: " + errors); @@ -196,15 +196,15 @@ SSLContext::SSLContext(const SSLProtocol& protocol) { } SSLContext::~SSLContext() { - if (ctx_ != NULL) { + if (ctx_ != nullptr) { SSL_CTX_free(ctx_); - ctx_ = NULL; + ctx_ = nullptr; } } SSL* SSLContext::createSSL() { SSL* ssl = SSL_new(ctx_); - if (ssl == NULL) { + if (ssl == nullptr) { string errors; buildErrors(errors); throw TSSLException("SSL_new: " + errors); @@ -214,33 +214,33 @@ SSL* SSLContext::createSSL() { // TSSLSocket implementation TSSLSocket::TSSLSocket(std::shared_ptr ctx) - : TSocket(), server_(false), ssl_(NULL), ctx_(ctx) { + : TSocket(), server_(false), ssl_(nullptr), ctx_(ctx) { init(); } TSSLSocket::TSSLSocket(std::shared_ptr ctx, std::shared_ptr interruptListener) - : TSocket(), server_(false), ssl_(NULL), ctx_(ctx) { + : TSocket(), server_(false), ssl_(nullptr), ctx_(ctx) { init(); interruptListener_ = interruptListener; } TSSLSocket::TSSLSocket(std::shared_ptr ctx, THRIFT_SOCKET socket) - : TSocket(socket), server_(false), ssl_(NULL), ctx_(ctx) { + : TSocket(socket), server_(false), ssl_(nullptr), ctx_(ctx) { init(); } TSSLSocket::TSSLSocket(std::shared_ptr ctx, THRIFT_SOCKET socket, std::shared_ptr interruptListener) - : TSocket(socket, interruptListener), server_(false), ssl_(NULL), ctx_(ctx) { + : TSocket(socket, interruptListener), server_(false), ssl_(nullptr), ctx_(ctx) { init(); } TSSLSocket::TSSLSocket(std::shared_ptr ctx, string host, int port) - : TSocket(host, port), server_(false), ssl_(NULL), ctx_(ctx) { + : TSocket(host, port), server_(false), ssl_(nullptr), ctx_(ctx) { init(); } TSSLSocket::TSSLSocket(std::shared_ptr ctx, string host, int port, std::shared_ptr interruptListener) - : TSocket(host, port), server_(false), ssl_(NULL), ctx_(ctx) { + : TSocket(host, port), server_(false), ssl_(nullptr), ctx_(ctx) { init(); interruptListener_ = interruptListener; } @@ -267,7 +267,7 @@ void TSSLSocket::init() { } bool TSSLSocket::isOpen() { - if (ssl_ == NULL || !TSocket::isOpen()) { + if (ssl_ == nullptr || !TSocket::isOpen()) { return false; } int shutdown = SSL_get_shutdown(ssl_); @@ -334,7 +334,7 @@ void TSSLSocket::open() { * Note: This method is not libevent safe. */ void TSSLSocket::close() { - if (ssl_ != NULL) { + if (ssl_ != nullptr) { try { int rc; int errno_copy = 0; @@ -375,7 +375,7 @@ void TSSLSocket::close() { GlobalOutput.printf("SSL_shutdown: %s", te.what()); } SSL_free(ssl_); - ssl_ = NULL; + ssl_ = nullptr; handshakeCompleted_ = false; ERR_remove_state(0); } @@ -552,14 +552,14 @@ uint32_t TSSLSocket::write_partial(const uint8_t* buf, uint32_t len) { void TSSLSocket::flush() { // Don't throw exception if not open. Thrift servers close socket twice. - if (ssl_ == NULL) { + if (ssl_ == nullptr) { return; } initializeHandshake(); if (!checkHandshake()) throw TSSLException("BIO_flush: Handshake is not completed"); BIO* bio = SSL_get_wbio(ssl_); - if (bio == NULL) { + if (bio == nullptr) { throw TSSLException("SSL_get_wbio returns NULL"); } if (BIO_flush(bio) != 1) { @@ -597,7 +597,7 @@ void TSSLSocket::initializeHandshake() { return; } - if (ssl_ == NULL) { + if (ssl_ == nullptr) { initializeHandshakeParams(); } @@ -683,19 +683,19 @@ void TSSLSocket::authorize() { } X509* cert = SSL_get_peer_certificate(ssl_); - if (cert == NULL) { + if (cert == nullptr) { // certificate is not present if (SSL_get_verify_mode(ssl_) & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) { throw TSSLException("authorize: required certificate not present"); } // certificate was optional: didn't intend to authorize remote - if (server() && access_ != NULL) { + if (server() && access_ != nullptr) { throw TSSLException("authorize: certificate required for authorization"); } return; } // certificate is present - if (access_ == NULL) { + if (access_ == nullptr) { X509_free(cert); return; } @@ -720,13 +720,13 @@ void TSSLSocket::authorize() { } // extract subjectAlternativeName - STACK_OF(GENERAL_NAME)* alternatives - = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - if (alternatives != NULL) { + auto* alternatives + = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr); + if (alternatives != nullptr) { const int count = sk_GENERAL_NAME_num(alternatives); for (int i = 0; decision == AccessManager::SKIP && i < count; i++) { const GENERAL_NAME* name = sk_GENERAL_NAME_value(alternatives, i); - if (name == NULL) { + if (name == nullptr) { continue; } char* data = (char*)ASN1_STRING_data(name->d.ia5); @@ -756,7 +756,7 @@ void TSSLSocket::authorize() { // extract commonName X509_NAME* name = X509_get_subject_name(cert); - if (name != NULL) { + if (name != nullptr) { X509_NAME_ENTRY* entry; unsigned char* utf8; int last = -1; @@ -765,7 +765,7 @@ void TSSLSocket::authorize() { if (last == -1) break; entry = X509_NAME_get_entry(name, last); - if (entry == NULL) + if (entry == nullptr) continue; ASN1_STRING* common = X509_NAME_ENTRY_get_data(entry); int size = ASN1_STRING_to_UTF8(&utf8, common); @@ -795,7 +795,7 @@ unsigned int TSSLSocket::waitForEvent(bool wantRead) { bio = SSL_get_wbio(ssl_); } - if (bio == NULL) { + if (bio == nullptr) { throw TSSLException("SSL_get_?bio returned NULL"); } @@ -908,10 +908,10 @@ std::shared_ptr TSSLSocketFactory::createSocket(const string& host, void TSSLSocketFactory::setup(std::shared_ptr ssl) { ssl->server(server()); - if (access_ == NULL && !server()) { + if (access_ == nullptr && !server()) { access_ = std::shared_ptr(new DefaultClientAccessManager); } - if (access_ != NULL) { + if (access_ != nullptr) { ssl->access(access_); } } @@ -935,11 +935,11 @@ void TSSLSocketFactory::authenticate(bool required) { } else { mode = SSL_VERIFY_NONE; } - SSL_CTX_set_verify(ctx_->get(), mode, NULL); + SSL_CTX_set_verify(ctx_->get(), mode, nullptr); } void TSSLSocketFactory::loadCertificate(const char* path, const char* format) { - if (path == NULL || format == NULL) { + if (path == nullptr || format == nullptr) { throw TTransportException(TTransportException::BAD_ARGS, "loadCertificateChain: either or is NULL"); } @@ -956,7 +956,7 @@ void TSSLSocketFactory::loadCertificate(const char* path, const char* format) { } void TSSLSocketFactory::loadPrivateKey(const char* path, const char* format) { - if (path == NULL || format == NULL) { + if (path == nullptr || format == nullptr) { throw TTransportException(TTransportException::BAD_ARGS, "loadPrivateKey: either or is NULL"); } @@ -971,7 +971,7 @@ void TSSLSocketFactory::loadPrivateKey(const char* path, const char* format) { } void TSSLSocketFactory::loadTrustedCertificates(const char* path, const char* capath) { - if (path == NULL) { + if (path == nullptr) { throw TTransportException(TTransportException::BAD_ARGS, "loadTrustedCertificates: is NULL"); } @@ -993,7 +993,7 @@ void TSSLSocketFactory::overrideDefaultPasswordCallback() { } int TSSLSocketFactory::passwordCallback(char* password, int size, int, void* data) { - TSSLSocketFactory* factory = (TSSLSocketFactory*)data; + auto* factory = (TSSLSocketFactory*)data; string userPassword; factory->getPassword(userPassword, size); int length = static_cast(userPassword.size()); @@ -1016,7 +1016,7 @@ void buildErrors(string& errors, int errno_copy, int sslerrno) { errors += "; "; } const char* reason = ERR_reason_error_string(errorCode); - if (reason == NULL) { + if (reason == nullptr) { THRIFT_SNPRINTF(message, sizeof(message) - 1, "SSL error # %lu", errorCode); reason = message; } @@ -1054,7 +1054,7 @@ Decision DefaultClientAccessManager::verify(const sockaddr_storage& sa) noexcept Decision DefaultClientAccessManager::verify(const string& host, const char* name, int size) noexcept { - if (host.empty() || name == NULL || size <= 0) { + if (host.empty() || name == nullptr || size <= 0) { return SKIP; } return (matchName(host.c_str(), name, size) ? ALLOW : SKIP); diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.h b/lib/cpp/src/thrift/transport/TSSLSocket.h index 5a87d1e360c..8f095dc8c13 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.h +++ b/lib/cpp/src/thrift/transport/TSSLSocket.h @@ -69,19 +69,19 @@ void cleanupOpenSSL(); */ class TSSLSocket : public TSocket { public: - ~TSSLSocket(); + ~TSSLSocket() override; /** * TTransport interface. */ bool isOpen(); - bool peek(); - void open(); - void close(); - bool hasPendingDataToRead(); - uint32_t read(uint8_t* buf, uint32_t len); - void write(const uint8_t* buf, uint32_t len); - uint32_t write_partial(const uint8_t* buf, uint32_t len); - void flush(); + bool peek() override; + void open() override; + void close() override; + bool hasPendingDataToRead() override; + uint32_t read(uint8_t* buf, uint32_t len) override; + void write(const uint8_t* buf, uint32_t len) override; + uint32_t write_partial(const uint8_t* buf, uint32_t len) override; + void flush() override; /** * Set whether to use client or server side SSL handshake protocol. * @@ -273,7 +273,7 @@ class TSSLSocketFactory { * * @param path Path to trusted certificate file */ - virtual void loadTrustedCertificates(const char* path, const char* capath = NULL); + virtual void loadTrustedCertificates(const char* path, const char* capath = nullptr); /** * Default randomize method. */ @@ -334,7 +334,7 @@ class TSSLException : public TTransportException { TSSLException(const std::string& message) : TTransportException(TTransportException::INTERNAL_ERROR, message) {} - virtual const char* what() const noexcept { + const char* what() const noexcept override { if (message_.empty()) { return "TSSLException"; } else { @@ -373,7 +373,7 @@ class AccessManager { /** * Destructor */ - virtual ~AccessManager() {} + virtual ~AccessManager() = default; /** * Determine whether the peer should be granted access or not. It's called * once after the SSL handshake completes successfully, before peer certificate @@ -425,9 +425,9 @@ typedef AccessManager::Decision Decision; class DefaultClientAccessManager : public AccessManager { public: // AccessManager interface - Decision verify(const sockaddr_storage& sa) noexcept; - Decision verify(const std::string& host, const char* name, int size) noexcept; - Decision verify(const sockaddr_storage& sa, const char* data, int size) noexcept; + Decision verify(const sockaddr_storage& sa) noexcept override; + Decision verify(const std::string& host, const char* name, int size) noexcept override; + Decision verify(const sockaddr_storage& sa, const char* data, int size) noexcept override; }; } } diff --git a/lib/cpp/src/thrift/transport/TServerSocket.cpp b/lib/cpp/src/thrift/transport/TServerSocket.cpp index 118b9936d9c..1732c827234 100644 --- a/lib/cpp/src/thrift/transport/TServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TServerSocket.cpp @@ -85,15 +85,15 @@ using std::shared_ptr; TGetAddrInfoWrapper::TGetAddrInfoWrapper(const char* node, const char* service, const struct addrinfo* hints) - : node_(node), service_(service), hints_(hints), res_(NULL) {} + : node_(node), service_(service), hints_(hints), res_(nullptr) {} TGetAddrInfoWrapper::~TGetAddrInfoWrapper() { - if (this->res_ != NULL) + if (this->res_ != nullptr) freeaddrinfo(this->res_); } int TGetAddrInfoWrapper::init() { - if (this->res_ == NULL) + if (this->res_ == nullptr) return getaddrinfo(this->node_, this->service_, this->hints_, &(this->res_)); return 0; } @@ -268,7 +268,7 @@ void TServerSocket::listen() { hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; // If address is not specified use wildcard address (NULL) - TGetAddrInfoWrapper info(address_.empty() ? NULL : &address_[0], port, &hints); + TGetAddrInfoWrapper info(address_.empty() ? nullptr : &address_[0], port, &hints); error = info.init(); if (error) { @@ -281,13 +281,13 @@ void TServerSocket::listen() { // Pick the ipv6 address first since ipv4 addresses can be mapped // into ipv6 space. for (res = info.res(); res; res = res->ai_next) { - if (res->ai_family == AF_INET6 || res->ai_next == NULL) + if (res->ai_family == AF_INET6 || res->ai_next == nullptr) break; } if (!path_.empty()) { serverSocket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP); - } else if (res != NULL) { + } else if (res != nullptr) { serverSocket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol); } @@ -434,7 +434,7 @@ void TServerSocket::listen() { // Unix Domain Socket size_t len = path_.size() + 1; - if (len > sizeof(((sockaddr_un*)NULL)->sun_path)) { + if (len > sizeof(((sockaddr_un*)nullptr)->sun_path)) { errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::listen() Unix Domain socket path too long", errno_copy); throw TTransportException(TTransportException::NOT_OPEN, @@ -446,7 +446,7 @@ void TServerSocket::listen() { address.sun_family = AF_UNIX; memcpy(address.sun_path, path_.c_str(), len); - socklen_t structlen = static_cast(sizeof(address)); + auto structlen = static_cast(sizeof(address)); if (!address.sun_path[0]) { // abstract namespace socket #ifdef __linux__ @@ -490,10 +490,10 @@ void TServerSocket::listen() { GlobalOutput.perror("TServerSocket::getPort() getsockname() ", errno_copy); } else { if (sa.ss_family == AF_INET6) { - const struct sockaddr_in6* sin = reinterpret_cast(&sa); + const auto* sin = reinterpret_cast(&sa); port_ = ntohs(sin->sin6_port); } else { - const struct sockaddr_in* sin = reinterpret_cast(&sa); + const auto* sin = reinterpret_cast(&sa); port_ = ntohs(sin->sin_port); } } diff --git a/lib/cpp/src/thrift/transport/TServerSocket.h b/lib/cpp/src/thrift/transport/TServerSocket.h index b23d2c19dfd..d640968033e 100644 --- a/lib/cpp/src/thrift/transport/TServerSocket.h +++ b/lib/cpp/src/thrift/transport/TServerSocket.h @@ -96,7 +96,7 @@ class TServerSocket : public TServerTransport { */ TServerSocket(const std::string& path); - virtual ~TServerSocket(); + ~TServerSocket() override; void setSendTimeout(int sendTimeout); void setRecvTimeout(int recvTimeout); @@ -136,17 +136,17 @@ class TServerSocket : public TServerTransport { // \throws std::logic_error if listen() has been called void setInterruptableChildren(bool enable); - THRIFT_SOCKET getSocketFD() { return serverSocket_; } + THRIFT_SOCKET getSocketFD() override { return serverSocket_; } int getPort(); - void listen(); - void interrupt(); - void interruptChildren(); - void close(); + void listen() override; + void interrupt() override; + void interruptChildren() override; + void close() override; protected: - std::shared_ptr acceptImpl(); + std::shared_ptr acceptImpl() override; virtual std::shared_ptr createSocket(THRIFT_SOCKET client); bool interruptableChildren_; std::shared_ptr pChildInterruptSockReader_; // if interruptableChildren_ this is shared with child TSockets diff --git a/lib/cpp/src/thrift/transport/TServerTransport.h b/lib/cpp/src/thrift/transport/TServerTransport.h index db7632a03a9..f465bb38a08 100644 --- a/lib/cpp/src/thrift/transport/TServerTransport.h +++ b/lib/cpp/src/thrift/transport/TServerTransport.h @@ -35,7 +35,7 @@ namespace transport { */ class TServerTransport { public: - virtual ~TServerTransport() {} + virtual ~TServerTransport() = default; /** * Starts the server transport listening for new connections. Prior to this @@ -96,7 +96,7 @@ class TServerTransport { virtual void close() = 0; protected: - TServerTransport() {} + TServerTransport() = default; /** * Subclasses should implement this function for accept. diff --git a/lib/cpp/src/thrift/transport/TShortReadTransport.h b/lib/cpp/src/thrift/transport/TShortReadTransport.h index 118252d75d5..2151606cf53 100644 --- a/lib/cpp/src/thrift/transport/TShortReadTransport.h +++ b/lib/cpp/src/thrift/transport/TShortReadTransport.h @@ -43,11 +43,11 @@ class TShortReadTransport : public TVirtualTransport { bool isOpen() { return transport_->isOpen(); } - bool peek() { return transport_->peek(); } + bool peek() override { return transport_->peek(); } - void open() { transport_->open(); } + void open() override { transport_->open(); } - void close() { transport_->close(); } + void close() override { transport_->close(); } uint32_t read(uint8_t* buf, uint32_t len) { if (len == 0) { @@ -62,7 +62,7 @@ class TShortReadTransport : public TVirtualTransport { void write(const uint8_t* buf, uint32_t len) { transport_->write(buf, len); } - void flush() { transport_->flush(); } + void flush() override { transport_->flush(); } const uint8_t* borrow(uint8_t* buf, uint32_t* len) { return transport_->borrow(buf, len); } diff --git a/lib/cpp/src/thrift/transport/TSocket.cpp b/lib/cpp/src/thrift/transport/TSocket.cpp index 6d5f932c511..977834d48b9 100644 --- a/lib/cpp/src/thrift/transport/TSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSocket.cpp @@ -324,7 +324,7 @@ void TSocket::openConnection(struct addrinfo* res) { #ifndef _WIN32 size_t len = path_.size() + 1; - if (len > sizeof(((sockaddr_un*)NULL)->sun_path)) { + if (len > sizeof(((sockaddr_un*)nullptr)->sun_path)) { int errno_copy = THRIFT_GET_SOCKET_ERROR; GlobalOutput.perror("TSocket::open() Unix Domain socket path too long", errno_copy); throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path too long"); @@ -334,7 +334,7 @@ void TSocket::openConnection(struct addrinfo* res) { address.sun_family = AF_UNIX; memcpy(address.sun_path, path_.c_str(), len); - socklen_t structlen = static_cast(sizeof(address)); + auto structlen = static_cast(sizeof(address)); if (!address.sun_path[0]) { // abstract namespace socket #ifdef __linux__ @@ -433,7 +433,7 @@ void TSocket::open() { void TSocket::unix_open() { if (!path_.empty()) { // Unix Domain SOcket does not need addrinfo struct, so we pass NULL - openConnection(NULL); + openConnection(nullptr); } } @@ -453,8 +453,8 @@ void TSocket::local_open() { } struct addrinfo hints, *res, *res0; - res = NULL; - res0 = NULL; + res = nullptr; + res0 = nullptr; int error; char port[sizeof("65535")]; std::memset(&hints, 0, sizeof(hints)); @@ -540,7 +540,7 @@ uint32_t TSocket::read(uint8_t* buf, uint32_t len) { // Read from the socket struct timeval begin; if (recvTimeout_ > 0) { - THRIFT_GETTIMEOFDAY(&begin, NULL); + THRIFT_GETTIMEOFDAY(&begin, nullptr); } else { // if there is no read timeout we don't need the TOD to determine whether // an THRIFT_EAGAIN is due to a timeout or an out-of-resource condition. @@ -592,8 +592,8 @@ uint32_t TSocket::read(uint8_t* buf, uint32_t len) { } // check if this is the lack of resources or timeout case struct timeval end; - THRIFT_GETTIMEOFDAY(&end, NULL); - uint32_t readElapsedMicros = static_cast(((end.tv_sec - begin.tv_sec) * 1000 * 1000) + THRIFT_GETTIMEOFDAY(&end, nullptr); + auto readElapsedMicros = static_cast(((end.tv_sec - begin.tv_sec) * 1000 * 1000) + (end.tv_usec - begin.tv_usec)); if (!eagainThresholdMicros || (readElapsedMicros < eagainThresholdMicros)) { @@ -807,7 +807,7 @@ void TSocket::setMaxRecvRetries(int maxRecvRetries) { maxRecvRetries_ = maxRecvRetries; } -string TSocket::getSocketInfo() { +string TSocket::getSocketInfo() const { std::ostringstream oss; if (path_.empty()) { if (host_.empty() || port_ == 0) { @@ -822,7 +822,7 @@ string TSocket::getSocketInfo() { return oss.str(); } -std::string TSocket::getPeerHost() { +std::string TSocket::getPeerHost() const { if (peerHost_.empty() && path_.empty()) { struct sockaddr_storage addr; struct sockaddr* addrPtr; @@ -834,14 +834,14 @@ std::string TSocket::getPeerHost() { addrPtr = getCachedAddress(&addrLen); - if (addrPtr == NULL) { + if (addrPtr == nullptr) { addrLen = sizeof(addr); if (getpeername(socket_, (sockaddr*)&addr, &addrLen) != 0) { return peerHost_; } addrPtr = (sockaddr*)&addr; - setCachedAddress(addrPtr, addrLen); + const_cast(*this).setCachedAddress(addrPtr, addrLen); } char clienthost[NI_MAXHOST]; @@ -860,7 +860,7 @@ std::string TSocket::getPeerHost() { return peerHost_; } -std::string TSocket::getPeerAddress() { +std::string TSocket::getPeerAddress() const { if (peerAddress_.empty() && path_.empty()) { struct sockaddr_storage addr; struct sockaddr* addrPtr; @@ -872,14 +872,14 @@ std::string TSocket::getPeerAddress() { addrPtr = getCachedAddress(&addrLen); - if (addrPtr == NULL) { + if (addrPtr == nullptr) { addrLen = sizeof(addr); if (getpeername(socket_, (sockaddr*)&addr, &addrLen) != 0) { return peerAddress_; } addrPtr = (sockaddr*)&addr; - setCachedAddress(addrPtr, addrLen); + const_cast(*this).setCachedAddress(addrPtr, addrLen); } char clienthost[NI_MAXHOST]; @@ -899,7 +899,7 @@ std::string TSocket::getPeerAddress() { return peerAddress_; } -int TSocket::getPeerPort() { +int TSocket::getPeerPort() const { getPeerAddress(); return peerPort_; } @@ -937,7 +937,7 @@ sockaddr* TSocket::getCachedAddress(socklen_t* len) const { return (sockaddr*)&cachedPeerAddr_.ipv6; default: - return NULL; + return nullptr; } } @@ -949,7 +949,7 @@ bool TSocket::getUseLowMinRto() { return useLowMinRto_; } -const std::string TSocket::getOrigin() { +const std::string TSocket::getOrigin() const { std::ostringstream oss; oss << getPeerHost() << ":" << getPeerPort(); return oss.str(); diff --git a/lib/cpp/src/thrift/transport/TSocket.h b/lib/cpp/src/thrift/transport/TSocket.h index 9dcd2d63e14..b0e8ade83d5 100644 --- a/lib/cpp/src/thrift/transport/TSocket.h +++ b/lib/cpp/src/thrift/transport/TSocket.h @@ -74,7 +74,7 @@ class TSocket : public TVirtualTransport { /** * Destroyes the socket object, closing it if necessary. */ - virtual ~TSocket(); + ~TSocket() override; /** * Whether the socket is alive. @@ -208,22 +208,22 @@ class TSocket : public TVirtualTransport { /** * Get socket information formatted as a string */ - std::string getSocketInfo(); + std::string getSocketInfo() const; /** * Returns the DNS name of the host to which the socket is connected */ - std::string getPeerHost(); + std::string getPeerHost() const; /** * Returns the address of the host to which the socket is connected */ - std::string getPeerAddress(); + std::string getPeerAddress() const; /** * Returns the port of the host to which the socket is connected **/ - int getPeerPort(); + int getPeerPort() const; /** * Returns the underlying socket file descriptor. @@ -259,7 +259,7 @@ class TSocket : public TVirtualTransport { * * @return string peer host identifier and port */ - virtual const std::string getOrigin(); + const std::string getOrigin() const override; /** * Constructor to create socket from file descriptor. @@ -295,13 +295,13 @@ class TSocket : public TVirtualTransport { THRIFT_SOCKET socket_; /** Peer hostname */ - std::string peerHost_; + mutable std::string peerHost_; /** Peer address */ - std::string peerAddress_; + mutable std::string peerAddress_; /** Peer port */ - int peerPort_; + mutable int peerPort_; /** * A shared socket pointer that will interrupt a blocking read if data diff --git a/lib/cpp/src/thrift/transport/TSocketPool.cpp b/lib/cpp/src/thrift/transport/TSocketPool.cpp index 5477bbb8e68..89eee6edae3 100644 --- a/lib/cpp/src/thrift/transport/TSocketPool.cpp +++ b/lib/cpp/src/thrift/transport/TSocketPool.cpp @@ -216,7 +216,7 @@ void TSocketPool::open() { if (server->lastFailTime_ > 0) { // The server was marked as down, so check if enough time has elapsed to retry - time_t elapsedTime = time(NULL) - server->lastFailTime_; + time_t elapsedTime = time(nullptr) - server->lastFailTime_; if (elapsedTime > retryInterval_) { retryIntervalPassed = true; } @@ -245,7 +245,7 @@ void TSocketPool::open() { if (server->consecutiveFailures_ > maxConsecutiveFailures_) { // Mark server as down server->consecutiveFailures_ = 0; - server->lastFailTime_ = time(NULL); + server->lastFailTime_ = time(nullptr); } } } diff --git a/lib/cpp/src/thrift/transport/TSocketPool.h b/lib/cpp/src/thrift/transport/TSocketPool.h index 18f101c1cff..97a2b906332 100644 --- a/lib/cpp/src/thrift/transport/TSocketPool.h +++ b/lib/cpp/src/thrift/transport/TSocketPool.h @@ -105,7 +105,7 @@ class TSocketPool : public TSocket { /** * Destroyes the socket object, closing it if necessary. */ - virtual ~TSocketPool(); + ~TSocketPool() override; /** * Add a server to the pool @@ -155,12 +155,12 @@ class TSocketPool : public TSocket { /** * Creates and opens the UNIX socket. */ - void open(); + void open() override; /* * Closes the UNIX socket */ - void close(); + void close() override; protected: void setCurrentServer(const std::shared_ptr& server); diff --git a/lib/cpp/src/thrift/transport/TTransport.h b/lib/cpp/src/thrift/transport/TTransport.h index 0f922779997..891bfe151bb 100644 --- a/lib/cpp/src/thrift/transport/TTransport.h +++ b/lib/cpp/src/thrift/transport/TTransport.h @@ -58,7 +58,7 @@ class TTransport { /** * Virtual deconstructor. */ - virtual ~TTransport() {} + virtual ~TTransport() = default; /** * Whether this transport is open. @@ -209,7 +209,7 @@ class TTransport { T_VIRTUAL_CALL(); return borrow_virt(buf, len); } - virtual const uint8_t* borrow_virt(uint8_t* /* buf */, uint32_t* /* len */) { return NULL; } + virtual const uint8_t* borrow_virt(uint8_t* /* buf */, uint32_t* /* len */) { return nullptr; } /** * Remove len bytes from the transport. This should always follow a borrow @@ -236,13 +236,13 @@ class TTransport { * * The returned value can be used in a log message for example */ - virtual const std::string getOrigin() { return "Unknown"; } + virtual const std::string getOrigin() const { return "Unknown"; } protected: /** * Simple constructor. */ - TTransport() {} + TTransport() = default; }; /** @@ -253,9 +253,9 @@ class TTransport { */ class TTransportFactory { public: - TTransportFactory() {} + TTransportFactory() = default; - virtual ~TTransportFactory() {} + virtual ~TTransportFactory() = default; /** * Default implementation does nothing, just returns the transport given. diff --git a/lib/cpp/src/thrift/transport/TTransportException.h b/lib/cpp/src/thrift/transport/TTransportException.h index fb5f00cd359..38b75211fe6 100644 --- a/lib/cpp/src/thrift/transport/TTransportException.h +++ b/lib/cpp/src/thrift/transport/TTransportException.h @@ -65,7 +65,7 @@ class TTransportException : public apache::thrift::TException { TTransportException(TTransportExceptionType type, const std::string& message, int errno_copy) : apache::thrift::TException(message + ": " + TOutput::strerror_s(errno_copy)), type_(type) {} - virtual ~TTransportException() noexcept {} + ~TTransportException() noexcept override = default; /** * Returns an error code that provides information about the type of error @@ -75,7 +75,7 @@ class TTransportException : public apache::thrift::TException { */ TTransportExceptionType getType() const noexcept { return type_; } - virtual const char* what() const noexcept; + const char* what() const noexcept override; protected: /** Just like strerror_r but returns a C++ string object. */ diff --git a/lib/cpp/src/thrift/transport/TTransportUtils.cpp b/lib/cpp/src/thrift/transport/TTransportUtils.cpp index eedcde1a748..69372f3e233 100644 --- a/lib/cpp/src/thrift/transport/TTransportUtils.cpp +++ b/lib/cpp/src/thrift/transport/TTransportUtils.cpp @@ -41,8 +41,8 @@ uint32_t TPipedTransport::read(uint8_t* buf, uint32_t len) { // Double the size of the underlying buffer if it is full if (rLen_ == rBufSize_) { rBufSize_ *= 2; - uint8_t *tmpBuf = (uint8_t*)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_); - if (tmpBuf == NULL) { + auto *tmpBuf = (uint8_t*)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_); + if (tmpBuf == nullptr) { throw std::bad_alloc(); } rBuf_ = tmpBuf; @@ -77,8 +77,8 @@ void TPipedTransport::write(const uint8_t* buf, uint32_t len) { while ((len + wLen_) >= newBufSize) { newBufSize *= 2; } - uint8_t *tmpBuf= (uint8_t*)std::realloc(wBuf_, sizeof(uint8_t) * newBufSize); - if (tmpBuf == NULL) { + auto *tmpBuf= (uint8_t*)std::realloc(wBuf_, sizeof(uint8_t) * newBufSize); + if (tmpBuf == nullptr) { throw std::bad_alloc(); } wBuf_ = tmpBuf; @@ -108,8 +108,7 @@ TPipedFileReaderTransport::TPipedFileReaderTransport( : TPipedTransport(srcTrans, dstTrans), srcTrans_(srcTrans) { } -TPipedFileReaderTransport::~TPipedFileReaderTransport() { -} +TPipedFileReaderTransport::~TPipedFileReaderTransport() = default; bool TPipedFileReaderTransport::isOpen() const { return TPipedTransport::isOpen(); diff --git a/lib/cpp/src/thrift/transport/TTransportUtils.h b/lib/cpp/src/thrift/transport/TTransportUtils.h index 8d67763f8bb..6cff76a2cce 100644 --- a/lib/cpp/src/thrift/transport/TTransportUtils.h +++ b/lib/cpp/src/thrift/transport/TTransportUtils.h @@ -42,13 +42,13 @@ namespace transport { */ class TNullTransport : public TVirtualTransport { public: - TNullTransport() {} + TNullTransport() = default; - ~TNullTransport() {} + ~TNullTransport() override = default; bool isOpen() { return true; } - void open() {} + void open() override {} void write(const uint8_t* /* buf */, uint32_t /* len */) { return; } }; @@ -77,11 +77,11 @@ class TPipedTransport : virtual public TTransport { pipeOnWrite_ = false; rBuf_ = (uint8_t*)std::malloc(sizeof(uint8_t) * rBufSize_); - if (rBuf_ == NULL) { + if (rBuf_ == nullptr) { throw std::bad_alloc(); } wBuf_ = (uint8_t*)std::malloc(sizeof(uint8_t) * wBufSize_); - if (wBuf_ == NULL) { + if (wBuf_ == nullptr) { throw std::bad_alloc(); } } @@ -98,16 +98,16 @@ class TPipedTransport : virtual public TTransport { wLen_(0) { rBuf_ = (uint8_t*)std::malloc(sizeof(uint8_t) * rBufSize_); - if (rBuf_ == NULL) { + if (rBuf_ == nullptr) { throw std::bad_alloc(); } wBuf_ = (uint8_t*)std::malloc(sizeof(uint8_t) * wBufSize_); - if (wBuf_ == NULL) { + if (wBuf_ == nullptr) { throw std::bad_alloc(); } } - ~TPipedTransport() { + ~TPipedTransport() override { std::free(rBuf_); std::free(wBuf_); } @@ -119,8 +119,8 @@ class TPipedTransport : virtual public TTransport { // Double the size of the underlying buffer if it is full if (rLen_ == rBufSize_) { rBufSize_ *= 2; - uint8_t * tmpBuf = (uint8_t*)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_); - if (tmpBuf == NULL) { + auto * tmpBuf = (uint8_t*)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_); + if (tmpBuf == nullptr) { throw std::bad_alloc(); } rBuf_ = tmpBuf; @@ -142,7 +142,7 @@ class TPipedTransport : virtual public TTransport { uint32_t read(uint8_t* buf, uint32_t len); - uint32_t readEnd() { + uint32_t readEnd() override { if (pipeOnRead_) { dstTrans_->write(rBuf_, rPos_); @@ -164,7 +164,7 @@ class TPipedTransport : virtual public TTransport { void write(const uint8_t* buf, uint32_t len); - uint32_t writeEnd() { + uint32_t writeEnd() override { if (pipeOnWrite_) { dstTrans_->write(wBuf_, wLen_); dstTrans_->flush(); @@ -172,7 +172,7 @@ class TPipedTransport : virtual public TTransport { return wLen_; } - void flush(); + void flush() override; std::shared_ptr getTargetTransport() { return dstTrans_; } @@ -207,11 +207,11 @@ class TPipedTransport : virtual public TTransport { */ class TPipedTransportFactory : public TTransportFactory { public: - TPipedTransportFactory() {} + TPipedTransportFactory() = default; TPipedTransportFactory(std::shared_ptr dstTrans) { initializeTargetTransport(dstTrans); } - virtual ~TPipedTransportFactory() {} + ~TPipedTransportFactory() override = default; /** * Wraps the base transport into a piped transport. @@ -221,7 +221,7 @@ class TPipedTransportFactory : public TTransportFactory { } virtual void initializeTargetTransport(std::shared_ptr dstTrans) { - if (dstTrans_.get() == NULL) { + if (dstTrans_.get() == nullptr) { dstTrans_ = dstTrans; } else { throw TException("Target transport already initialized"); @@ -243,7 +243,7 @@ class TPipedFileReaderTransport : public TPipedTransport, public TFileReaderTran TPipedFileReaderTransport(std::shared_ptr srcTrans, std::shared_ptr dstTrans); - ~TPipedFileReaderTransport(); + ~TPipedFileReaderTransport() override; // TTransport functions bool isOpen() const override; @@ -252,18 +252,18 @@ class TPipedFileReaderTransport : public TPipedTransport, public TFileReaderTran void close() override; uint32_t read(uint8_t* buf, uint32_t len); uint32_t readAll(uint8_t* buf, uint32_t len); - uint32_t readEnd(); + uint32_t readEnd() override; void write(const uint8_t* buf, uint32_t len); - uint32_t writeEnd(); - void flush(); + uint32_t writeEnd() override; + void flush() override; // TFileReaderTransport functions - int32_t getReadTimeout(); - void setReadTimeout(int32_t readTimeout); - uint32_t getNumChunks(); - uint32_t getCurChunk(); - void seekToChunk(int32_t chunk); - void seekToEnd(); + int32_t getReadTimeout() override; + void setReadTimeout(int32_t readTimeout) override; + uint32_t getNumChunks() override; + uint32_t getCurChunk() override; + void seekToChunk(int32_t chunk) override; + void seekToEnd() override; /* * Override TTransport *_virt() functions to invoke our implementations. @@ -286,15 +286,15 @@ class TPipedFileReaderTransport : public TPipedTransport, public TFileReaderTran */ class TPipedFileReaderTransportFactory : public TPipedTransportFactory { public: - TPipedFileReaderTransportFactory() {} + TPipedFileReaderTransportFactory() = default; TPipedFileReaderTransportFactory(std::shared_ptr dstTrans) : TPipedTransportFactory(dstTrans) {} - virtual ~TPipedFileReaderTransportFactory() {} + ~TPipedFileReaderTransportFactory() override = default; - std::shared_ptr getTransport(std::shared_ptr srcTrans) { + std::shared_ptr getTransport(std::shared_ptr srcTrans) override { std::shared_ptr pFileReaderTransport = std::dynamic_pointer_cast(srcTrans); - if (pFileReaderTransport.get() != NULL) { + if (pFileReaderTransport.get() != nullptr) { return getFileReaderTransport(pFileReaderTransport); } else { return std::shared_ptr(); diff --git a/lib/cpp/src/thrift/transport/TVirtualTransport.h b/lib/cpp/src/thrift/transport/TVirtualTransport.h index b5518cc752a..0a048574210 100644 --- a/lib/cpp/src/thrift/transport/TVirtualTransport.h +++ b/lib/cpp/src/thrift/transport/TVirtualTransport.h @@ -57,7 +57,7 @@ class TTransportDefaults : public TTransport { void consume(uint32_t len) { this->TTransport::consume_virt(len); } protected: - TTransportDefaults() {} + TTransportDefaults() = default; }; /** @@ -113,12 +113,12 @@ class TVirtualTransport : public Super_ { * the correct parent implementation, if desired. */ uint32_t readAll(uint8_t* buf, uint32_t len) { - Transport_* trans = static_cast(this); + auto* trans = static_cast(this); return ::apache::thrift::transport::readAll(*trans, buf, len); } protected: - TVirtualTransport() {} + TVirtualTransport() = default; /* * Templatized constructors, to allow arguments to be passed to the Super_ diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.cpp b/lib/cpp/src/thrift/transport/TZlibTransport.cpp index e426dc390c8..ddceb9937c7 100644 --- a/lib/cpp/src/thrift/transport/TZlibTransport.cpp +++ b/lib/cpp/src/thrift/transport/TZlibTransport.cpp @@ -331,7 +331,7 @@ const uint8_t* TZlibTransport::borrow(uint8_t* buf, uint32_t* len) { *len = (uint32_t)readAvail(); return urbuf_ + urpos_; } - return NULL; + return nullptr; } void TZlibTransport::consume(uint32_t len) { diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.h b/lib/cpp/src/thrift/transport/TZlibTransport.h index a9b26642d6f..be2d19898ae 100644 --- a/lib/cpp/src/thrift/transport/TZlibTransport.h +++ b/lib/cpp/src/thrift/transport/TZlibTransport.h @@ -36,9 +36,9 @@ class TZlibTransportException : public TTransportException { TZlibTransportException(int status, const char* msg) : TTransportException(TTransportException::INTERNAL_ERROR, errorMessage(status, msg)), zlib_status_(status), - zlib_msg_(msg == NULL ? "(null)" : msg) {} + zlib_msg_(msg == nullptr ? "(null)" : msg) {} - virtual ~TZlibTransportException() noexcept {} + ~TZlibTransportException() noexcept override = default; int getZlibStatus() { return zlib_status_; } std::string getZlibMessage() { return zlib_msg_; } @@ -93,12 +93,12 @@ class TZlibTransport : public TVirtualTransport { crbuf_size_(crbuf_size), uwbuf_size_(uwbuf_size), cwbuf_size_(cwbuf_size), - urbuf_(NULL), - crbuf_(NULL), - uwbuf_(NULL), - cwbuf_(NULL), - rstream_(NULL), - wstream_(NULL), + urbuf_(nullptr), + crbuf_(nullptr), + uwbuf_(nullptr), + cwbuf_(nullptr), + rstream_(nullptr), + wstream_(nullptr), comp_level_(comp_level) { if (uwbuf_size_ < MIN_DIRECT_DEFLATE_SIZE) { // Have to copy this into a local because of a linking issue. @@ -136,20 +136,20 @@ class TZlibTransport : public TVirtualTransport { * unflushed data. You must explicitly call flush() or finish() to ensure * that data is actually written and flushed to the underlying transport. */ - ~TZlibTransport(); + ~TZlibTransport() override; bool isOpen(); - bool peek(); + bool peek() override; - void open() { transport_->open(); } + void open() override { transport_->open(); } - void close() { transport_->close(); } + void close() override { transport_->close(); } uint32_t read(uint8_t* buf, uint32_t len); void write(const uint8_t* buf, uint32_t len); - void flush(); + void flush() override; /** * Finalize the zlib stream. @@ -227,9 +227,9 @@ class TZlibTransport : public TVirtualTransport { */ class TZlibTransportFactory : public TTransportFactory { public: - TZlibTransportFactory() {} + TZlibTransportFactory() = default; - virtual ~TZlibTransportFactory() {} + ~TZlibTransportFactory() override = default; std::shared_ptr getTransport(std::shared_ptr trans) override { return std::shared_ptr(new TZlibTransport(trans)); diff --git a/lib/cpp/test/Benchmark.cpp b/lib/cpp/test/Benchmark.cpp index 5ff77aab95f..56adac0b203 100644 --- a/lib/cpp/test/Benchmark.cpp +++ b/lib/cpp/test/Benchmark.cpp @@ -36,12 +36,12 @@ class Timer { public: timeval vStart; - Timer() { THRIFT_GETTIMEOFDAY(&vStart, 0); } - void start() { THRIFT_GETTIMEOFDAY(&vStart, 0); } + Timer() { THRIFT_GETTIMEOFDAY(&vStart, nullptr); } + void start() { THRIFT_GETTIMEOFDAY(&vStart, nullptr); } double frame() { timeval vEnd; - THRIFT_GETTIMEOFDAY(&vEnd, 0); + THRIFT_GETTIMEOFDAY(&vEnd, nullptr); double dstart = vStart.tv_sec + ((double)vStart.tv_usec / 1000000.0); double dend = vEnd.tv_sec + ((double)vEnd.tv_usec / 1000000.0); return dend - dstart; @@ -70,7 +70,7 @@ int main() { int num = 100000; std::shared_ptr buf(new TMemoryBuffer(num*1000)); - uint8_t* data = NULL; + uint8_t* data = nullptr; uint32_t datasize = 0; { @@ -157,7 +157,7 @@ int main() { } - data = NULL; + data = nullptr; datasize = 0; num = 10000000; diff --git a/lib/cpp/test/EnumTest.cpp b/lib/cpp/test/EnumTest.cpp index c935bc41f44..6487906324e 100644 --- a/lib/cpp/test/EnumTest.cpp +++ b/lib/cpp/test/EnumTest.cpp @@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(test_enum_ostream) BOOST_CHECK_EQUAL(EnumToString(MyEnumWithCustomOstream::CustoM2), "{2:CUSTOM!}"); // some invalid or unknown value - MyEnum5::type uut = (MyEnum5::type)44; + auto uut = (MyEnum5::type)44; BOOST_CHECK_EQUAL(EnumToString(uut), "44"); } diff --git a/lib/cpp/test/OneWayHTTPTest.cpp b/lib/cpp/test/OneWayHTTPTest.cpp index f369d8ce16f..55d919bbaf4 100644 --- a/lib/cpp/test/OneWayHTTPTest.cpp +++ b/lib/cpp/test/OneWayHTTPTest.cpp @@ -66,14 +66,14 @@ namespace utf = boost::unit_test; class OneWayServiceHandler : public onewaytest::OneWayServiceIf { public: - OneWayServiceHandler() {} + OneWayServiceHandler() = default; void roundTripRPC() override { #ifdef ENABLE_STDERR_LOGGING cerr << "roundTripRPC()" << endl; #endif } - void oneWayRPC() { + void oneWayRPC() override { #ifdef ENABLE_STDERR_LOGGING cerr << "oneWayRPC()" << std::endl ; #endif @@ -82,13 +82,13 @@ class OneWayServiceHandler : public onewaytest::OneWayServiceIf { class OneWayServiceCloneFactory : virtual public onewaytest::OneWayServiceIfFactory { public: - virtual ~OneWayServiceCloneFactory() {} - virtual onewaytest::OneWayServiceIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) + ~OneWayServiceCloneFactory() override = default; + onewaytest::OneWayServiceIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) override { (void)connInfo ; return new OneWayServiceHandler; } - virtual void releaseHandler( onewaytest::OneWayServiceIf* handler) { + void releaseHandler( onewaytest::OneWayServiceIf* handler) override { delete handler; } }; @@ -96,7 +96,7 @@ class OneWayServiceCloneFactory : virtual public onewaytest::OneWayServiceIfFact class RPC0ThreadClass { public: RPC0ThreadClass(TThreadedServer& server) : server_(server) { } // Constructor -~RPC0ThreadClass() { } // Destructor +~RPC0ThreadClass() = default; // Destructor void Run() { server_.serve() ; @@ -112,21 +112,21 @@ using apache::thrift::concurrency::Synchronized; class TServerReadyEventHandler : public TServerEventHandler, public Monitor { public: TServerReadyEventHandler() : isListening_(false), accepted_(0) {} - virtual ~TServerReadyEventHandler() {} - virtual void preServe() { + ~TServerReadyEventHandler() override = default; + void preServe() override { Synchronized sync(*this); isListening_ = true; notify(); } - virtual void* createContext(shared_ptr input, - shared_ptr output) { + void* createContext(shared_ptr input, + shared_ptr output) override { Synchronized sync(*this); ++accepted_; notify(); (void)input; (void)output; - return NULL; + return nullptr; } bool isListening() const { return isListening_; } uint64_t acceptedCount() const { return accepted_; } @@ -144,7 +144,7 @@ class TBlockableBufferedTransport : public TBufferedTransport { } uint32_t write_buffer_length() { - uint32_t have_bytes = static_cast(wBase_ - wBuf_.get()); + auto have_bytes = static_cast(wBase_ - wBuf_.get()); return have_bytes ; } diff --git a/lib/cpp/test/OpenSSLManualInitTest.cpp b/lib/cpp/test/OpenSSLManualInitTest.cpp index a30b3039a92..a7518064e76 100644 --- a/lib/cpp/test/OpenSSLManualInitTest.cpp +++ b/lib/cpp/test/OpenSSLManualInitTest.cpp @@ -62,7 +62,7 @@ void test_openssl_availability() { // uninitialized. It might also fail on very old versions of // OpenSSL... const EVP_MD* md = EVP_get_digestbyname("SHA256"); - BOOST_CHECK(md != NULL); + BOOST_CHECK(md != nullptr); openssl_cleanup(); } diff --git a/lib/cpp/test/RecursiveTest.cpp b/lib/cpp/test/RecursiveTest.cpp index 15f234cfa1c..ab2e46dd7a9 100644 --- a/lib/cpp/test/RecursiveTest.cpp +++ b/lib/cpp/test/RecursiveTest.cpp @@ -60,8 +60,8 @@ BOOST_AUTO_TEST_CASE(test_recursive_2) { RecList resultlist; resultlist.read(prot.get()); - BOOST_CHECK(resultlist.nextitem != NULL); - BOOST_CHECK(resultlist.nextitem->nextitem == NULL); + BOOST_CHECK(resultlist.nextitem != nullptr); + BOOST_CHECK(resultlist.nextitem->nextitem == nullptr); } BOOST_AUTO_TEST_CASE(test_recursive_3) { @@ -75,8 +75,8 @@ BOOST_AUTO_TEST_CASE(test_recursive_3) { c.write(prot.get()); c.read(prot.get()); - BOOST_CHECK(c.other != NULL); - BOOST_CHECK(c.other->other.other == NULL); + BOOST_CHECK(c.other != nullptr); + BOOST_CHECK(c.other->other.other == nullptr); } BOOST_AUTO_TEST_CASE(test_recursive_4) { diff --git a/lib/cpp/test/TFileTransportTest.cpp b/lib/cpp/test/TFileTransportTest.cpp index d0c26b3a0c7..ad32185540d 100644 --- a/lib/cpp/test/TFileTransportTest.cpp +++ b/lib/cpp/test/TFileTransportTest.cpp @@ -64,12 +64,12 @@ class FsyncLog { }; typedef std::list CallList; - FsyncLog() {} + FsyncLog() = default; void fsync(int fd) { (void)fd; FsyncCall call; - THRIFT_GETTIMEOFDAY(&call.time, NULL); + THRIFT_GETTIMEOFDAY(&call.time, nullptr); calls_.push_back(call); } @@ -123,7 +123,7 @@ class TempFile { if (path_) { ::unlink(path_); delete[] path_; - path_ = NULL; + path_ = nullptr; } } @@ -195,9 +195,9 @@ BOOST_AUTO_TEST_CASE(test_destructor) { struct timeval start; struct timeval end; - THRIFT_GETTIMEOFDAY(&start, NULL); + THRIFT_GETTIMEOFDAY(&start, nullptr); delete transport; - THRIFT_GETTIMEOFDAY(&end, NULL); + THRIFT_GETTIMEOFDAY(&end, nullptr); int delta = time_diff(&start, &end); @@ -264,7 +264,7 @@ void test_flush_max_us_impl(uint32_t flush_us, uint32_t write_us, uint32_t test_ delete transport; // Stop logging new fsync() calls - fsync_log = NULL; + fsync_log = nullptr; // Examine the fsync() log // @@ -278,8 +278,8 @@ void test_flush_max_us_impl(uint32_t flush_us, uint32_t write_us, uint32_t test_ // Make sure TFileTransport called fsync at least once BOOST_WARN_GE(calls->size(), static_cast(1)); - const struct timeval* prev_time = NULL; - for (FsyncLog::CallList::const_iterator it = calls->begin(); it != calls->end(); ++it) { + const struct timeval* prev_time = nullptr; + for (auto it = calls->begin(); it != calls->end(); ++it) { if (prev_time) { int delta = time_diff(prev_time, &it->time); BOOST_WARN( delta < max_allowed_delta ); @@ -318,13 +318,13 @@ BOOST_AUTO_TEST_CASE(test_noop_flush) { transport.write(buf, 1); struct timeval start; - THRIFT_GETTIMEOFDAY(&start, NULL); + THRIFT_GETTIMEOFDAY(&start, nullptr); for (unsigned int n = 0; n < 10; ++n) { transport.flush(); struct timeval now; - THRIFT_GETTIMEOFDAY(&now, NULL); + THRIFT_GETTIMEOFDAY(&now, nullptr); // Fail if at any point we've been running for longer than half a second. // (With the buggy code, TFileTransport used to take 3 seconds per flush()) @@ -349,11 +349,11 @@ void print_usage(FILE* f, const char* argv0) { void parse_args(int argc, char* argv[]) { struct option long_opts[] - = {{"help", false, NULL, 'h'}, {"tmp-dir", true, NULL, 't'}, {NULL, 0, NULL, 0}}; + = {{"help", false, nullptr, 'h'}, {"tmp-dir", true, nullptr, 't'}, {nullptr, 0, nullptr, 0}}; while (true) { optopt = 1; - int optchar = getopt_long(argc, argv, "ht:", long_opts, NULL); + int optchar = getopt_long(argc, argv, "ht:", long_opts, nullptr); if (optchar == -1) { break; } @@ -378,7 +378,7 @@ void parse_args(int argc, char* argv[]) { #ifdef BOOST_TEST_DYN_LINK static int myArgc = 0; -static char **myArgv = NULL; +static char **myArgv = nullptr; bool init_unit_test_suite() { boost::unit_test::framework::master_test_suite().p_name.value = "TFileTransportTest"; diff --git a/lib/cpp/test/TNonblockingSSLServerTest.cpp b/lib/cpp/test/TNonblockingSSLServerTest.cpp index 2111de8b0cb..d0d86889623 100644 --- a/lib/cpp/test/TNonblockingSSLServerTest.cpp +++ b/lib/cpp/test/TNonblockingSSLServerTest.cpp @@ -39,17 +39,17 @@ using apache::thrift::transport::TSSLSocketFactory; using apache::thrift::transport::TSSLSocket; struct Handler : public test::ParentServiceIf { - void addString(const std::string& s) { strings_.push_back(s); } - void getStrings(std::vector& _return) { _return = strings_; } + void addString(const std::string& s) override { strings_.push_back(s); } + void getStrings(std::vector& _return) override { _return = strings_; } std::vector strings_; // dummy overrides not used in this test - int32_t incrementGeneration() { return 0; } - int32_t getGeneration() { return 0; } - void getDataWait(std::string&, const int32_t) {} - void onewayWait() {} - void exceptionWait(const std::string&) {} - void unexpectedExceptionWait(const std::string&) {} + int32_t incrementGeneration() override { return 0; } + int32_t getGeneration() override { return 0; } + void getDataWait(std::string&, const int32_t) override {} + void onewayWait() override {} + void exceptionWait(const std::string&) override {} + void unexpectedExceptionWait(const std::string&) override {} }; boost::filesystem::path keyDir; @@ -131,7 +131,7 @@ class Fixture { public: ListenEventHandler(Mutex* mutex) : listenMonitor_(mutex), ready_(false) {} - void preServe() /* override */ { + void preServe() override /* override */ { Guard g(listenMonitor_.mutex()); ready_ = true; listenMonitor_.notify(); @@ -155,7 +155,7 @@ class Fixture { listenHandler.reset(new ListenEventHandler(&mutex_)); } - virtual void run() { + void run() override { // When binding to explicit port, allow retrying to workaround bind failures on ports in use int retryCount = port ? 10 : 0; pServerSocketFactory = createServerSocketFactory(); diff --git a/lib/cpp/test/TNonblockingServerTest.cpp b/lib/cpp/test/TNonblockingServerTest.cpp index f2f59220376..434217e4884 100644 --- a/lib/cpp/test/TNonblockingServerTest.cpp +++ b/lib/cpp/test/TNonblockingServerTest.cpp @@ -44,17 +44,17 @@ using std::shared_ptr; using namespace apache::thrift; struct Handler : public test::ParentServiceIf { - void addString(const std::string& s) { strings_.push_back(s); } - void getStrings(std::vector& _return) { _return = strings_; } + void addString(const std::string& s) override { strings_.push_back(s); } + void getStrings(std::vector& _return) override { _return = strings_; } std::vector strings_; // dummy overrides not used in this test - int32_t incrementGeneration() { return 0; } - int32_t getGeneration() { return 0; } - void getDataWait(std::string&, const int32_t) {} - void onewayWait() {} - void exceptionWait(const std::string&) {} - void unexpectedExceptionWait(const std::string&) {} + int32_t incrementGeneration() override { return 0; } + int32_t getGeneration() override { return 0; } + void getDataWait(std::string&, const int32_t) override {} + void onewayWait() override {} + void exceptionWait(const std::string&) override {} + void unexpectedExceptionWait(const std::string&) override {} }; class Fixture { @@ -63,7 +63,7 @@ class Fixture { public: ListenEventHandler(Mutex* mutex) : listenMonitor_(mutex), ready_(false) {} - void preServe() /* override */ { + void preServe() override /* override */ { Guard g(listenMonitor_.mutex()); ready_ = true; listenMonitor_.notify(); @@ -86,7 +86,7 @@ class Fixture { listenHandler.reset(new ListenEventHandler(&mutex_)); } - virtual void run() { + void run() override { // When binding to explicit port, allow retrying to workaround bind failures on ports in use int retryCount = port ? 10 : 0; startServer(retryCount); diff --git a/lib/cpp/test/TServerIntegrationTest.cpp b/lib/cpp/test/TServerIntegrationTest.cpp index a7680d89e0e..b88c35bf4e3 100644 --- a/lib/cpp/test/TServerIntegrationTest.cpp +++ b/lib/cpp/test/TServerIntegrationTest.cpp @@ -74,21 +74,21 @@ using boost::posix_time::milliseconds; class TServerReadyEventHandler : public TServerEventHandler, public Monitor { public: TServerReadyEventHandler() : isListening_(false), accepted_(0) {} - virtual ~TServerReadyEventHandler() {} - virtual void preServe() { + ~TServerReadyEventHandler() override = default; + void preServe() override { Synchronized sync(*this); isListening_ = true; notify(); } - virtual void* createContext(shared_ptr input, - shared_ptr output) { + void* createContext(shared_ptr input, + shared_ptr output) override { Synchronized sync(*this); ++accepted_; notify(); (void)input; (void)output; - return NULL; + return nullptr; } bool isListening() const { return isListening_; } uint64_t acceptedCount() const { return accepted_; } @@ -105,36 +105,36 @@ class ParentHandler : public ParentServiceIf { public: ParentHandler() : generation_(0) {} - int32_t incrementGeneration() { + int32_t incrementGeneration() override { Guard g(mutex_); return ++generation_; } - int32_t getGeneration() { + int32_t getGeneration() override { Guard g(mutex_); return generation_; } - void addString(const std::string& s) { + void addString(const std::string& s) override { Guard g(mutex_); strings_.push_back(s); } - void getStrings(std::vector& _return) { + void getStrings(std::vector& _return) override { Guard g(mutex_); _return = strings_; } - void getDataWait(std::string& _return, const int32_t length) { + void getDataWait(std::string& _return, const int32_t length) override { THRIFT_UNUSED_VARIABLE(_return); THRIFT_UNUSED_VARIABLE(length); } - void onewayWait() {} + void onewayWait() override {} - void exceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); } + void exceptionWait(const std::string& message) override { THRIFT_UNUSED_VARIABLE(message); } - void unexpectedExceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); } + void unexpectedExceptionWait(const std::string& message) override { THRIFT_UNUSED_VARIABLE(message); } protected: Mutex mutex_; @@ -264,7 +264,7 @@ class TServerIntegrationTestFixture { * \returns the server port number */ int getServerPort() { - TServerSocket* pSock = dynamic_cast(pServer->getServerTransport().get()); + auto* pSock = dynamic_cast(pServer->getServerTransport().get()); if (!pSock) { throw std::logic_error("how come?"); } return pSock->getPort(); } diff --git a/lib/cpp/test/TServerTransportTest.cpp b/lib/cpp/test/TServerTransportTest.cpp index 539bd28cdc0..15177a85085 100644 --- a/lib/cpp/test/TServerTransportTest.cpp +++ b/lib/cpp/test/TServerTransportTest.cpp @@ -34,11 +34,11 @@ class TestTTransport : public TTransport {}; class TestTServerTransport : public TServerTransport { public: TestTServerTransport() : valid_(true) {} - void close() {} + void close() override {} bool valid_; protected: - shared_ptr acceptImpl() { + shared_ptr acceptImpl() override { return valid_ ? shared_ptr(new TestTTransport) : shared_ptr(); } diff --git a/lib/cpp/test/TransportTest.cpp b/lib/cpp/test/TransportTest.cpp index 0d900d9dae8..b0c84b63f39 100644 --- a/lib/cpp/test/TransportTest.cpp +++ b/lib/cpp/test/TransportTest.cpp @@ -57,7 +57,7 @@ void initrand(unsigned int seed) { class SizeGenerator { public: - virtual ~SizeGenerator() {} + virtual ~SizeGenerator() = default; virtual uint32_t nextSize() = 0; virtual std::string describe() const = 0; }; @@ -65,8 +65,8 @@ class SizeGenerator { class ConstantSizeGenerator : public SizeGenerator { public: ConstantSizeGenerator(uint32_t value) : value_(value) {} - uint32_t nextSize() { return value_; } - std::string describe() const { + uint32_t nextSize() override { return value_; } + std::string describe() const override { std::ostringstream desc; desc << value_; return desc.str(); @@ -81,9 +81,9 @@ class RandomSizeGenerator : public SizeGenerator { RandomSizeGenerator(uint32_t min, uint32_t max) : generator_(rng, boost::uniform_int(min, max)) {} - uint32_t nextSize() { return generator_(); } + uint32_t nextSize() override { return generator_(); } - std::string describe() const { + std::string describe() const override { std::ostringstream desc; desc << "rand(" << getMin() << ", " << getMax() << ")"; return desc.str(); @@ -109,8 +109,8 @@ class GenericSizeGenerator : public SizeGenerator { GenericSizeGenerator(uint32_t min, uint32_t max) : generator_(new RandomSizeGenerator(min, max)) {} - uint32_t nextSize() { return generator_->nextSize(); } - std::string describe() const { return generator_->describe(); } + uint32_t nextSize() override { return generator_->nextSize(); } + std::string describe() const override { return generator_->describe(); } private: std::shared_ptr generator_; @@ -131,7 +131,7 @@ class GenericSizeGenerator : public SizeGenerator { template class CoupledTransports { public: - virtual ~CoupledTransports() {} + virtual ~CoupledTransports() = default; typedef Transport_ TransportType; CoupledTransports() : in(), out() {} @@ -282,7 +282,7 @@ class CoupledFileTransports : public CoupledTransports { out.reset(new TFileTransport(filename)); } - ~CoupledFileTransports() { remove(filename.c_str()); } + ~CoupledFileTransports() override { remove(filename.c_str()); } std::string filename; }; @@ -341,7 +341,7 @@ class CoupledBufferBases : public CoupledTransports { struct TriggerInfo { TriggerInfo(int seconds, const std::shared_ptr& transport, uint32_t writeLength) - : timeoutSeconds(seconds), transport(transport), writeLength(writeLength), next(NULL) {} + : timeoutSeconds(seconds), transport(transport), writeLength(writeLength), next(nullptr) {} int timeoutSeconds; std::shared_ptr transport; @@ -355,7 +355,7 @@ unsigned int g_numTriggersFired; bool g_teardown = false; void alarm_handler() { - TriggerInfo* info = NULL; + TriggerInfo* info = nullptr; { apache::thrift::concurrency::Synchronized s(g_alarm_monitor); // The alarm timed out, which almost certainly means we're stuck @@ -366,7 +366,7 @@ void alarm_handler() { // tools/test/runner only records stdout messages in the failure messages for // boost tests. (boost prints its test info to stdout.) printf("Timeout alarm expired; attempting to unblock transport\n"); - if (g_triggerInfo == NULL) { + if (g_triggerInfo == nullptr) { printf(" trigger stack is empty!\n"); } @@ -377,7 +377,7 @@ void alarm_handler() { } // Write some data to the transport to hopefully unblock it. - uint8_t* buf = new uint8_t[info->writeLength]; + auto* buf = new uint8_t[info->writeLength]; memset(buf, 'b', info->writeLength); boost::scoped_array array(buf); info->transport->write(buf, info->writeLength); @@ -395,7 +395,7 @@ void alarm_handler_wrapper() { if (g_teardown) return; // calculate timeout - if (g_triggerInfo == NULL) { + if (g_triggerInfo == nullptr) { timeout = 0; } else { timeout = g_triggerInfo->timeoutSeconds * 1000; @@ -421,10 +421,10 @@ void alarm_handler_wrapper() { void add_trigger(unsigned int seconds, const std::shared_ptr& transport, uint32_t write_len) { - TriggerInfo* info = new TriggerInfo(seconds, transport, write_len); + auto* info = new TriggerInfo(seconds, transport, write_len); { apache::thrift::concurrency::Synchronized s(g_alarm_monitor); - if (g_triggerInfo == NULL) { + if (g_triggerInfo == nullptr) { // This is the first trigger. // Set g_triggerInfo, and schedule the alarm g_triggerInfo = info; @@ -441,17 +441,17 @@ void add_trigger(unsigned int seconds, } void clear_triggers() { - TriggerInfo* info = NULL; + TriggerInfo* info = nullptr; { apache::thrift::concurrency::Synchronized s(g_alarm_monitor); info = g_triggerInfo; - g_triggerInfo = NULL; + g_triggerInfo = nullptr; g_numTriggersFired = 0; g_alarm_monitor.notify(); } - while (info != NULL) { + while (info != nullptr) { TriggerInfo* next = info->next; delete info; info = next; @@ -500,8 +500,8 @@ void test_rw(uint32_t totalSize, SizeGenerator& rChunkGenerator, uint32_t maxOutstanding) { CoupledTransports transports; - BOOST_REQUIRE(transports.in != NULL); - BOOST_REQUIRE(transports.out != NULL); + BOOST_REQUIRE(transports.in != nullptr); + BOOST_REQUIRE(transports.out != nullptr); boost::shared_array wbuf = boost::shared_array(new uint8_t[totalSize]); boost::shared_array rbuf = boost::shared_array(new uint8_t[totalSize]); @@ -593,8 +593,8 @@ void test_rw(uint32_t totalSize, template void test_read_part_available() { CoupledTransports transports; - BOOST_REQUIRE(transports.in != NULL); - BOOST_REQUIRE(transports.out != NULL); + BOOST_REQUIRE(transports.in != nullptr); + BOOST_REQUIRE(transports.out != nullptr); uint8_t write_buf[16]; uint8_t read_buf[16]; @@ -615,8 +615,8 @@ void test_read_part_available() { template void test_read_part_available_in_chunks() { CoupledTransports transports; - BOOST_REQUIRE(transports.in != NULL); - BOOST_REQUIRE(transports.out != NULL); + BOOST_REQUIRE(transports.in != nullptr); + BOOST_REQUIRE(transports.out != nullptr); uint8_t write_buf[16]; uint8_t read_buf[16]; @@ -642,8 +642,8 @@ void test_read_part_available_in_chunks() { template void test_read_partial_midframe() { CoupledTransports transports; - BOOST_REQUIRE(transports.in != NULL); - BOOST_REQUIRE(transports.out != NULL); + BOOST_REQUIRE(transports.in != nullptr); + BOOST_REQUIRE(transports.out != nullptr); uint8_t write_buf[16]; uint8_t read_buf[16]; @@ -700,8 +700,8 @@ void test_read_partial_midframe() { template void test_borrow_part_available() { CoupledTransports transports; - BOOST_REQUIRE(transports.in != NULL); - BOOST_REQUIRE(transports.out != NULL); + BOOST_REQUIRE(transports.in != nullptr); + BOOST_REQUIRE(transports.out != nullptr); uint8_t write_buf[16]; uint8_t read_buf[16]; @@ -715,7 +715,7 @@ void test_borrow_part_available() { uint32_t borrow_len = 10; const uint8_t* borrowed_buf = transports.in->borrow(read_buf, &borrow_len); BOOST_CHECK_EQUAL(g_numTriggersFired, (unsigned int)0); - BOOST_CHECK(borrowed_buf == NULL); + BOOST_CHECK(borrowed_buf == nullptr); clear_triggers(); } @@ -723,8 +723,8 @@ void test_borrow_part_available() { template void test_read_none_available() { CoupledTransports transports; - BOOST_REQUIRE(transports.in != NULL); - BOOST_REQUIRE(transports.out != NULL); + BOOST_REQUIRE(transports.in != nullptr); + BOOST_REQUIRE(transports.out != nullptr); uint8_t read_buf[16]; @@ -751,8 +751,8 @@ void test_read_none_available() { template void test_borrow_none_available() { CoupledTransports transports; - BOOST_REQUIRE(transports.in != NULL); - BOOST_REQUIRE(transports.out != NULL); + BOOST_REQUIRE(transports.in != nullptr); + BOOST_REQUIRE(transports.out != nullptr); uint8_t write_buf[16]; memset(write_buf, 'a', sizeof(write_buf)); @@ -760,8 +760,8 @@ void test_borrow_none_available() { // Attempting to borrow when no data is available should fail immediately set_trigger(1, transports.out, 10); uint32_t borrow_len = 10; - const uint8_t* borrowed_buf = transports.in->borrow(NULL, &borrow_len); - BOOST_CHECK(borrowed_buf == NULL); + const uint8_t* borrowed_buf = transports.in->borrow(nullptr, &borrow_len); + BOOST_CHECK(borrowed_buf == nullptr); BOOST_CHECK_EQUAL(g_numTriggersFired, (unsigned int)0); clear_triggers(); @@ -1055,7 +1055,7 @@ BOOST_GLOBAL_FIXTURE(global_fixture) #ifdef BOOST_TEST_DYN_LINK bool init_unit_test_suite() { struct timeval tv; - THRIFT_GETTIMEOFDAY(&tv, NULL); + THRIFT_GETTIMEOFDAY(&tv, nullptr); int seed = tv.tv_sec ^ tv.tv_usec; initrand(seed); diff --git a/lib/cpp/test/ZlibTest.cpp b/lib/cpp/test/ZlibTest.cpp index c8268149e3b..3e2eb816c1d 100644 --- a/lib/cpp/test/ZlibTest.cpp +++ b/lib/cpp/test/ZlibTest.cpp @@ -58,14 +58,14 @@ boost::mt19937 rng; class SizeGenerator { public: - virtual ~SizeGenerator() {} + virtual ~SizeGenerator() = default; virtual unsigned int getSize() = 0; }; class ConstantSizeGenerator : public SizeGenerator { public: ConstantSizeGenerator(unsigned int value) : value_(value) {} - virtual unsigned int getSize() { return value_; } + unsigned int getSize() override { return value_; } private: unsigned int value_; @@ -76,10 +76,10 @@ class LogNormalSizeGenerator : public SizeGenerator { LogNormalSizeGenerator(double mean, double std_dev) : gen_(rng, boost::lognormal_distribution(mean, std_dev)) {} - virtual unsigned int getSize() { + unsigned int getSize() override { // Loop until we get a size of 1 or more while (true) { - unsigned int value = static_cast(gen_()); + auto value = static_cast(gen_()); if (value >= 1) { return value; } @@ -91,13 +91,13 @@ class LogNormalSizeGenerator : public SizeGenerator { }; boost::shared_array gen_uniform_buffer(uint32_t buf_len, uint8_t c) { - uint8_t* buf = new uint8_t[buf_len]; + auto* buf = new uint8_t[buf_len]; memset(buf, c, buf_len); return boost::shared_array(buf); } boost::shared_array gen_compressible_buffer(uint32_t buf_len) { - uint8_t* buf = new uint8_t[buf_len]; + auto* buf = new uint8_t[buf_len]; // Generate small runs of alternately increasing and decreasing bytes boost::uniform_smallint run_length_distribution(1, 64); @@ -129,7 +129,7 @@ boost::shared_array gen_compressible_buffer(uint32_t buf_len) { } boost::shared_array gen_random_buffer(uint32_t buf_len) { - uint8_t* buf = new uint8_t[buf_len]; + auto* buf = new uint8_t[buf_len]; boost::uniform_smallint distribution(0, UINT8_MAX); boost::variate_generator > @@ -427,7 +427,7 @@ void print_usage(FILE* f, const char* argv0) { #ifdef BOOST_TEST_DYN_LINK bool init_unit_test_suite() { - uint32_t seed = static_cast(time(NULL)); + auto seed = static_cast(time(nullptr)); #ifdef HAVE_INTTYPES_H printf("seed: %" PRIu32 "\n", seed); #endif diff --git a/lib/cpp/test/concurrency/Tests.cpp b/lib/cpp/test/concurrency/Tests.cpp index 019ae67f299..f2b0111e34c 100644 --- a/lib/cpp/test/concurrency/Tests.cpp +++ b/lib/cpp/test/concurrency/Tests.cpp @@ -41,7 +41,7 @@ int main(int argc, char** argv) { args[ix - 1] = std::string(argv[ix]); } - if (getenv("VALGRIND") != 0) { + if (getenv("VALGRIND") != nullptr) { // lower the scale of every test WEIGHT = 1; } diff --git a/lib/cpp/test/concurrency/ThreadFactoryTests.h b/lib/cpp/test/concurrency/ThreadFactoryTests.h index ad1613ba9f0..febe3f8b3f1 100644 --- a/lib/cpp/test/concurrency/ThreadFactoryTests.h +++ b/lib/cpp/test/concurrency/ThreadFactoryTests.h @@ -51,7 +51,7 @@ class ThreadFactoryTests { public: ReapNTask(Monitor& monitor, int& activeCount) : _monitor(monitor), _count(activeCount) {} - void run() { + void run() override { Synchronized s(_monitor); if (--_count == 0) { @@ -122,7 +122,7 @@ class ThreadFactoryTests { SynchStartTask(Monitor& monitor, volatile STATE& state) : _monitor(monitor), _state(state) {} - void run() { + void run() override { { Synchronized s(_monitor); if (_state == SynchStartTask::STARTING) { @@ -247,14 +247,14 @@ class ThreadFactoryTests { class FloodTask : public Runnable { public: FloodTask(const size_t id, Monitor& mon) : _id(id), _mon(mon) {} - ~FloodTask() { + ~FloodTask() override { if (_id % 10000 == 0) { Synchronized sync(_mon); std::cout << "\t\tthread " << _id << " done" << std::endl; } } - void run() { + void run() override { if (_id % 10000 == 0) { Synchronized sync(_mon); std::cout << "\t\tthread " << _id << " started" << std::endl; diff --git a/lib/cpp/test/concurrency/ThreadManagerTests.h b/lib/cpp/test/concurrency/ThreadManagerTests.h index e9ed75653bc..fee7c7c51a1 100644 --- a/lib/cpp/test/concurrency/ThreadManagerTests.h +++ b/lib/cpp/test/concurrency/ThreadManagerTests.h @@ -63,7 +63,7 @@ class ThreadManagerTests { Task(Monitor& monitor, size_t& count, int64_t timeout) : _monitor(monitor), _count(count), _timeout(timeout), _startTime(0), _endTime(0), _done(false) {} - void run() { + void run() override { _startTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); @@ -124,7 +124,7 @@ class ThreadManagerTests { int64_t time00 = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); - for (std::set >::iterator ix = tasks.begin(); + for (auto ix = tasks.begin(); ix != tasks.end(); ix++) { @@ -151,7 +151,7 @@ class ThreadManagerTests { int64_t minTime = 9223372036854775807LL; int64_t maxTime = 0; - for (std::set >::iterator ix = tasks.begin(); + for (auto ix = tasks.begin(); ix != tasks.end(); ix++) { @@ -201,7 +201,7 @@ class ThreadManagerTests { BlockTask(Monitor& entryMonitor, Monitor& blockMonitor, bool& blocked, Monitor& doneMonitor, size_t& count) : _entryMonitor(entryMonitor), _entered(false), _blockMonitor(blockMonitor), _blocked(blocked), _doneMonitor(doneMonitor), _count(count) {} - void run() { + void run() override { { Synchronized s(_entryMonitor); _entered = true; @@ -275,7 +275,7 @@ class ThreadManagerTests { new ThreadManagerTests::BlockTask(entryMonitor, blockMonitor, blocked[1], doneMonitor, activeCounts[1]))); } - for (std::vector >::iterator ix = tasks.begin(); + for (auto ix = tasks.begin(); ix != tasks.end(); ix++) { threadManager->add(*ix); diff --git a/lib/cpp/test/concurrency/TimerManagerTests.h b/lib/cpp/test/concurrency/TimerManagerTests.h index a922826e93b..313572aff77 100644 --- a/lib/cpp/test/concurrency/TimerManagerTests.h +++ b/lib/cpp/test/concurrency/TimerManagerTests.h @@ -44,9 +44,9 @@ class TimerManagerTests { _success(false), _done(false) {} - ~Task() { std::cerr << this << std::endl; } + ~Task() override { std::cerr << this << std::endl; } - void run() { + void run() override { _endTime = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); _success = (_endTime - _startTime) >= _timeout; @@ -215,7 +215,7 @@ class TimerManagerTests { // Verify behavior when removing the removed task try { timerManager.remove(timer); - assert(0 == "ERROR: This remove should send a NoSuchTaskException exception."); + assert(nullptr == "ERROR: This remove should send a NoSuchTaskException exception."); } catch (NoSuchTaskException&) { } @@ -244,7 +244,7 @@ class TimerManagerTests { // Verify behavior when removing the expired task try { timerManager.remove(timer); - assert(0 == "ERROR: This remove should send a NoSuchTaskException exception."); + assert(nullptr == "ERROR: This remove should send a NoSuchTaskException exception."); } catch (NoSuchTaskException&) { } diff --git a/lib/cpp/test/processor/EventLog.cpp b/lib/cpp/test/processor/EventLog.cpp index e3ddbccc41b..c8e0d9b0247 100644 --- a/lib/cpp/test/processor/EventLog.cpp +++ b/lib/cpp/test/processor/EventLog.cpp @@ -110,7 +110,7 @@ Event EventLog::waitForEvent(int64_t timeout) { Event EventLog::waitForConnEvent(uint32_t connId, int64_t timeout) { Synchronized s(monitor_); - EventList::iterator it = events_.begin(); + auto it = events_.begin(); while (true) { try { // TODO: it would be nicer to honor timeout for the duration of this diff --git a/lib/cpp/test/processor/Handlers.h b/lib/cpp/test/processor/Handlers.h index 29784d84591..05d19edd967 100644 --- a/lib/cpp/test/processor/Handlers.h +++ b/lib/cpp/test/processor/Handlers.h @@ -32,31 +32,31 @@ class ParentHandler : virtual public ParentServiceIf { ParentHandler(const std::shared_ptr& log) : triggerMonitor(&mutex_), generation_(0), wait_(false), log_(log) {} - int32_t incrementGeneration() { + int32_t incrementGeneration() override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_INCREMENT_GENERATION, 0, 0); return ++generation_; } - int32_t getGeneration() { + int32_t getGeneration() override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_GET_GENERATION, 0, 0); return generation_; } - void addString(const std::string& s) { + void addString(const std::string& s) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_ADD_STRING, 0, 0); strings_.push_back(s); } - void getStrings(std::vector& _return) { + void getStrings(std::vector& _return) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_GET_STRINGS, 0, 0); _return = strings_; } - void getDataWait(std::string& _return, const int32_t length) { + void getDataWait(std::string& _return, const int32_t length) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_GET_DATA_WAIT, 0, 0); @@ -65,14 +65,14 @@ class ParentHandler : virtual public ParentServiceIf { _return.append(length, 'a'); } - void onewayWait() { + void onewayWait() override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_ONEWAY_WAIT, 0, 0); blockUntilTriggered(); } - void exceptionWait(const std::string& message) { + void exceptionWait(const std::string& message) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_EXCEPTION_WAIT, 0, 0); @@ -83,7 +83,7 @@ class ParentHandler : virtual public ParentServiceIf { throw e; } - void unexpectedExceptionWait(const std::string& message) { + void unexpectedExceptionWait(const std::string& message) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_UNEXPECTED_EXCEPTION_WAIT, 0, 0); @@ -148,7 +148,7 @@ class ChildHandler : public ParentHandler, virtual public ChildServiceIf { public: ChildHandler(const std::shared_ptr& log) : ParentHandler(log), value_(0) {} - int32_t setValue(const int32_t value) { + int32_t setValue(const int32_t value) override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_SET_VALUE, 0, 0); @@ -157,7 +157,7 @@ class ChildHandler : public ParentHandler, virtual public ChildServiceIf { return oldValue; } - int32_t getValue() { + int32_t getValue() override { concurrency::Guard g(mutex_); log_->append(EventLog::ET_CALL_GET_VALUE, 0, 0); @@ -198,20 +198,20 @@ class ServerEventHandler : public server::TServerEventHandler { public: ServerEventHandler(const std::shared_ptr& log) : nextId_(1), log_(log) {} - virtual void preServe() {} + void preServe() override {} - virtual void* createContext(std::shared_ptr input, - std::shared_ptr output) { + void* createContext(std::shared_ptr input, + std::shared_ptr output) override { ConnContext* context = new ConnContext(input, output, nextId_); ++nextId_; log_->append(EventLog::ET_CONN_CREATED, context->id, 0); return context; } - virtual void deleteContext(void* serverContext, + void deleteContext(void* serverContext, std::shared_ptr input, - std::shared_ptr output) { - ConnContext* context = reinterpret_cast(serverContext); + std::shared_ptr output) override { + auto* context = reinterpret_cast(serverContext); if (input != context->input) { abort(); @@ -225,8 +225,8 @@ class ServerEventHandler : public server::TServerEventHandler { delete context; } - virtual void processContext(void* serverContext, - std::shared_ptr transport) { + void processContext(void* serverContext, + std::shared_ptr transport) override { // TODO: We currently don't test the behavior of the processContext() // calls. The various server implementations call processContext() at // slightly different times, and it is too annoying to try and account for @@ -258,8 +258,8 @@ class ProcessorEventHandler : public TProcessorEventHandler { public: ProcessorEventHandler(const std::shared_ptr& log) : nextId_(1), log_(log) {} - void* getContext(const char* fnName, void* serverContext) { - ConnContext* connContext = reinterpret_cast(serverContext); + void* getContext(const char* fnName, void* serverContext) override { + auto* connContext = reinterpret_cast(serverContext); CallContext* context = new CallContext(connContext, nextId_, fnName); ++nextId_; @@ -268,47 +268,47 @@ class ProcessorEventHandler : public TProcessorEventHandler { return context; } - void freeContext(void* ctx, const char* fnName) { - CallContext* context = reinterpret_cast(ctx); + void freeContext(void* ctx, const char* fnName) override { + auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_CALL_FINISHED, context->connContext->id, context->id, fnName); delete context; } - void preRead(void* ctx, const char* fnName) { - CallContext* context = reinterpret_cast(ctx); + void preRead(void* ctx, const char* fnName) override { + auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_PRE_READ, context->connContext->id, context->id, fnName); } - void postRead(void* ctx, const char* fnName, uint32_t bytes) { + void postRead(void* ctx, const char* fnName, uint32_t bytes) override { THRIFT_UNUSED_VARIABLE(bytes); - CallContext* context = reinterpret_cast(ctx); + auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_POST_READ, context->connContext->id, context->id, fnName); } - void preWrite(void* ctx, const char* fnName) { - CallContext* context = reinterpret_cast(ctx); + void preWrite(void* ctx, const char* fnName) override { + auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_PRE_WRITE, context->connContext->id, context->id, fnName); } - void postWrite(void* ctx, const char* fnName, uint32_t bytes) { + void postWrite(void* ctx, const char* fnName, uint32_t bytes) override { THRIFT_UNUSED_VARIABLE(bytes); - CallContext* context = reinterpret_cast(ctx); + auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_POST_WRITE, context->connContext->id, context->id, fnName); } - void asyncComplete(void* ctx, const char* fnName) { - CallContext* context = reinterpret_cast(ctx); + void asyncComplete(void* ctx, const char* fnName) override { + auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_ASYNC_COMPLETE, context->connContext->id, context->id, fnName); } - void handlerError(void* ctx, const char* fnName) { - CallContext* context = reinterpret_cast(ctx); + void handlerError(void* ctx, const char* fnName) override { + auto* context = reinterpret_cast(ctx); checkName(context, fnName); log_->append(EventLog::ET_HANDLER_ERROR, context->connContext->id, context->id, fnName); } diff --git a/lib/cpp/test/processor/ProcessorTest.cpp b/lib/cpp/test/processor/ProcessorTest.cpp index 9483a0e913d..a36ef3eec44 100644 --- a/lib/cpp/test/processor/ProcessorTest.cpp +++ b/lib/cpp/test/processor/ProcessorTest.cpp @@ -116,9 +116,9 @@ class TNonblockingServerTraits { // TNonblockingServer automatically uses TFramedTransport. // Raise an exception if the supplied transport factory is not a // TFramedTransportFactory - TFramedTransportFactory* framedFactory + auto* framedFactory = dynamic_cast(transportFactory.get()); - if (framedFactory == NULL) { + if (framedFactory == nullptr) { throw TException("TNonblockingServer must use TFramedTransport"); } @@ -145,9 +145,9 @@ class TNonblockingServerNoThreadsTraits { // TNonblockingServer automatically uses TFramedTransport. // Raise an exception if the supplied transport factory is not a // TFramedTransportFactory - TFramedTransportFactory* framedFactory + auto* framedFactory = dynamic_cast(transportFactory.get()); - if (framedFactory == NULL) { + if (framedFactory == nullptr) { throw TException("TNonblockingServer must use TFramedTransport"); } @@ -244,14 +244,14 @@ class ServiceState : public ServerState { processor_->setEventHandler(processorEventHandler_); } - std::shared_ptr createServer(uint16_t port) { + std::shared_ptr createServer(uint16_t port) override { ServerTraits_ serverTraits; return serverTraits.createServer(processor_, port, transportFactory_, protocolFactory_); } - std::shared_ptr getServerEventHandler() { return serverEventHandler_; } + std::shared_ptr getServerEventHandler() override { return serverEventHandler_; } - void bindSuccessful(uint16_t port) { port_ = port; } + void bindSuccessful(uint16_t port) override { port_ = port; } uint16_t getPort() const { return port_; } @@ -524,7 +524,7 @@ void testEventSequencing() { // can test the timing for the preRead() call. string requestName = "getDataWait"; string eventName = "ParentService.getDataWait"; - int32_t seqid = int32_t(time(NULL)); + auto seqid = int32_t(time(nullptr)); TBinaryProtocol protocol(socket); protocol.writeMessageBegin(requestName, T_CALL, seqid); socket->flush(); diff --git a/lib/cpp/test/processor/ServerThread.h b/lib/cpp/test/processor/ServerThread.h index 61e31a35e9f..9cca2d6002e 100644 --- a/lib/cpp/test/processor/ServerThread.h +++ b/lib/cpp/test/processor/ServerThread.h @@ -35,7 +35,7 @@ namespace test { */ class ServerState { public: - virtual ~ServerState() {} + virtual ~ServerState() = default; /** * Create a server to listen on the specified port. @@ -105,9 +105,9 @@ class ServerThread { public: Helper(ServerThread* serverThread) : serverThread_(serverThread) {} - void run() { serverThread_->run(); } + void run() override { serverThread_->run(); } - void preServe() { serverThread_->preServe(); } + void preServe() override { serverThread_->preServe(); } private: ServerThread* serverThread_; diff --git a/lib/cpp/test/qt/TQTcpServerTest.cpp b/lib/cpp/test/qt/TQTcpServerTest.cpp index 58d0c6dbf60..3371a9ae824 100644 --- a/lib/cpp/test/qt/TQTcpServerTest.cpp +++ b/lib/cpp/test/qt/TQTcpServerTest.cpp @@ -20,25 +20,25 @@ using namespace apache::thrift; struct AsyncHandler : public test::ParentServiceCobSvIf { std::vector strings; - virtual void addString(std::function cob, const std::string& s) { + void addString(std::function cob, const std::string& s) override { strings.push_back(s); cob(); } - virtual void getStrings(std::function const& _return)> cob) { + void getStrings(std::function const& _return)> cob) override { cob(strings); } // Overrides not used in this test - virtual void incrementGeneration(std::function cob) {} - virtual void getGeneration(std::function cob) {} - virtual void getDataWait(std::function cob, - const int32_t length) {} - virtual void onewayWait(std::function cob) {} - virtual void exceptionWait( + void incrementGeneration(std::function cob) override {} + void getGeneration(std::function cob) override {} + void getDataWait(std::function cob, + const int32_t length) override {} + void onewayWait(std::function cob) override {} + void exceptionWait( std::function cob, std::function /* exn_cob */, - const std::string& message) {} - virtual void unexpectedExceptionWait(std::function cob, const std::string& message) {} + const std::string& message) override {} + void unexpectedExceptionWait(std::function cob, const std::string& message) override {} }; class TQTcpServerTest : public QObject { diff --git a/test/cpp/src/StressTest.cpp b/test/cpp/src/StressTest.cpp index 930261e4611..16831252f18 100644 --- a/test/cpp/src/StressTest.cpp +++ b/test/cpp/src/StressTest.cpp @@ -64,7 +64,7 @@ typedef map count_map; class Server : public ServiceIf { public: - Server() {} + Server() = default; void count(const char* method) { Guard m(lock_); @@ -72,7 +72,7 @@ class Server : public ServiceIf { counts_[method] = ++ct; } - void echoVoid() { + void echoVoid() override { count("echoVoid"); return; } @@ -82,18 +82,18 @@ class Server : public ServiceIf { return counts_; } - int8_t echoByte(const int8_t arg) { return arg; } - int32_t echoI32(const int32_t arg) { return arg; } - int64_t echoI64(const int64_t arg) { return arg; } - void echoString(string& out, const string& arg) { + int8_t echoByte(const int8_t arg) override { return arg; } + int32_t echoI32(const int32_t arg) override { return arg; } + int64_t echoI64(const int64_t arg) override { return arg; } + void echoString(string& out, const string& arg) override { if (arg != "hello") { T_ERROR_ABORT("WRONG STRING (%s)!!!!", arg.c_str()); } out = arg; } - void echoList(vector& out, const vector& arg) { out = arg; } - void echoSet(set& out, const set& arg) { out = arg; } - void echoMap(map& out, const map& arg) { out = arg; } + void echoList(vector& out, const vector& arg) override { out = arg; } + void echoSet(set& out, const set& arg) override { out = arg; } + void echoMap(map& out, const map& arg) override { out = arg; } private: count_map counts_; @@ -121,7 +121,7 @@ class ClientThread : public Runnable { _loopType(loopType), _behavior(behavior) {} - void run() { + void run() override { // Wait for all worker threads to start @@ -239,7 +239,7 @@ class ClientThread : public Runnable { class TStartObserver : public apache::thrift::server::TServerEventHandler { public: TStartObserver() : awake_(false) {} - virtual void preServe() { + void preServe() override { apache::thrift::concurrency::Synchronized s(m_); awake_ = true; m_.notifyAll(); @@ -524,7 +524,7 @@ int main(int argc, char** argv) { } } - for (std::set >::const_iterator thread = clientThreads.begin(); + for (auto thread = clientThreads.begin(); thread != clientThreads.end(); thread++) { (*thread)->start(); @@ -557,7 +557,7 @@ int main(int argc, char** argv) { int64_t minTime = 9223372036854775807LL; int64_t maxTime = 0; - for (set >::iterator ix = clientThreads.begin(); + for (auto ix = clientThreads.begin(); ix != clientThreads.end(); ix++) { diff --git a/test/cpp/src/StressTestNonBlocking.cpp b/test/cpp/src/StressTestNonBlocking.cpp index ead2df57020..e94ecb2db11 100644 --- a/test/cpp/src/StressTestNonBlocking.cpp +++ b/test/cpp/src/StressTestNonBlocking.cpp @@ -67,7 +67,7 @@ typedef map count_map; class Server : public ServiceIf { public: - Server() {} + Server() = default; void count(const char* method) { Guard m(lock_); @@ -75,7 +75,7 @@ class Server : public ServiceIf { counts_[method] = ++ct; } - void echoVoid() { + void echoVoid() override { count("echoVoid"); // Sleep to simulate work THRIFT_SLEEP_USEC(1); @@ -87,18 +87,18 @@ class Server : public ServiceIf { return counts_; } - int8_t echoByte(const int8_t arg) { return arg; } - int32_t echoI32(const int32_t arg) { return arg; } - int64_t echoI64(const int64_t arg) { return arg; } - void echoString(string& out, const string& arg) { + int8_t echoByte(const int8_t arg) override { return arg; } + int32_t echoI32(const int32_t arg) override { return arg; } + int64_t echoI64(const int64_t arg) override { return arg; } + void echoString(string& out, const string& arg) override { if (arg != "hello") { T_ERROR_ABORT("WRONG STRING (%s)!!!!", arg.c_str()); } out = arg; } - void echoList(vector& out, const vector& arg) { out = arg; } - void echoSet(set& out, const set& arg) { out = arg; } - void echoMap(map& out, const map& arg) { out = arg; } + void echoList(vector& out, const vector& arg) override { out = arg; } + void echoSet(set& out, const set& arg) override { out = arg; } + void echoMap(map& out, const map& arg) override { out = arg; } private: count_map counts_; @@ -120,7 +120,7 @@ class ClientThread : public Runnable { _loopCount(loopCount), _loopType(loopType) {} - void run() { + void run() override { // Wait for all worker threads to start @@ -462,7 +462,7 @@ int main(int argc, char** argv) { new ClientThread(socket, serviceClient, monitor, threadCount, loopCount, loopType)))); } - for (std::set >::const_iterator thread = clientThreads.begin(); + for (auto thread = clientThreads.begin(); thread != clientThreads.end(); thread++) { (*thread)->start(); @@ -495,7 +495,7 @@ int main(int argc, char** argv) { int64_t minTime = 9223372036854775807LL; int64_t maxTime = 0; - for (set >::iterator ix = clientThreads.begin(); + for (auto ix = clientThreads.begin(); ix != clientThreads.end(); ix++) { diff --git a/test/cpp/src/TestClient.cpp b/test/cpp/src/TestClient.cpp index 89f3fd13c35..2a065780655 100644 --- a/test/cpp/src/TestClient.cpp +++ b/test/cpp/src/TestClient.cpp @@ -65,7 +65,7 @@ uint64_t now() { int64_t ret; struct timeval tv; - THRIFT_GETTIMEOFDAY(&tv, NULL); + THRIFT_GETTIMEOFDAY(&tv, nullptr); ret = tv.tv_sec; ret = ret * 1000 * 1000 + tv.tv_usec; return ret; @@ -942,11 +942,11 @@ int main(int argc, char** argv) { if (it1 == whoa.end()) { failed = true; } else { - map::const_iterator it12 = it1->second.find(Numberz::TWO); + auto it12 = it1->second.find(Numberz::TWO); if (it12 == it1->second.end() || it12->second != insane) { failed = true; } - map::const_iterator it13 = it1->second.find(Numberz::THREE); + auto it13 = it1->second.find(Numberz::THREE); if (it13 == it1->second.end() || it13->second != insane) { failed = true; } @@ -955,7 +955,7 @@ int main(int argc, char** argv) { if (it2 == whoa.end()) { failed = true; } else { - map::const_iterator it26 = it2->second.find(Numberz::SIX); + auto it26 = it2->second.find(Numberz::SIX); if (it26 == it2->second.end() || it26->second != Insanity()) { failed = true; } diff --git a/test/cpp/src/TestServer.cpp b/test/cpp/src/TestServer.cpp index 410662819fc..8d5b4d93e2f 100644 --- a/test/cpp/src/TestServer.cpp +++ b/test/cpp/src/TestServer.cpp @@ -90,48 +90,48 @@ void signal_handler(int signum) class TestHandler : public ThriftTestIf { public: - TestHandler() {} + TestHandler() = default; - void testVoid() { printf("testVoid()\n"); } + void testVoid() override { printf("testVoid()\n"); } - void testString(string& out, const string& thing) { + void testString(string& out, const string& thing) override { printf("testString(\"%s\")\n", thing.c_str()); out = thing; } - bool testBool(const bool thing) { + bool testBool(const bool thing) override { printf("testBool(%s)\n", thing ? "true" : "false"); return thing; } - int8_t testByte(const int8_t thing) { + int8_t testByte(const int8_t thing) override { printf("testByte(%d)\n", (int)thing); return thing; } - int32_t testI32(const int32_t thing) { + int32_t testI32(const int32_t thing) override { printf("testI32(%d)\n", thing); return thing; } - int64_t testI64(const int64_t thing) { + int64_t testI64(const int64_t thing) override { printf("testI64(%" PRId64 ")\n", thing); return thing; } - double testDouble(const double thing) { + double testDouble(const double thing) override { printf("testDouble(%f)\n", thing); return thing; } - void testBinary(std::string& _return, const std::string& thing) { + void testBinary(std::string& _return, const std::string& thing) override { std::ostringstream hexstr; hexstr << std::hex << thing; printf("testBinary(%lu: %s)\n", safe_numeric_cast(thing.size()), hexstr.str().c_str()); _return = thing; } - void testStruct(Xtruct& out, const Xtruct& thing) { + void testStruct(Xtruct& out, const Xtruct& thing) override { printf("testStruct({\"%s\", %d, %d, %" PRId64 "})\n", thing.string_thing.c_str(), (int)thing.byte_thing, @@ -140,7 +140,7 @@ class TestHandler : public ThriftTestIf { out = thing; } - void testNest(Xtruct2& out, const Xtruct2& nest) { + void testNest(Xtruct2& out, const Xtruct2& nest) override { const Xtruct& thing = nest.struct_thing; printf("testNest({%d, {\"%s\", %d, %d, %" PRId64 "}, %d})\n", (int)nest.byte_thing, @@ -152,7 +152,7 @@ class TestHandler : public ThriftTestIf { out = nest; } - void testMap(map& out, const map& thing) { + void testMap(map& out, const map& thing) override { printf("testMap({"); map::const_iterator m_iter; bool first = true; @@ -169,7 +169,7 @@ class TestHandler : public ThriftTestIf { } void testStringMap(map& out, - const map& thing) { + const map& thing) override { printf("testMap({"); map::const_iterator m_iter; bool first = true; @@ -185,7 +185,7 @@ class TestHandler : public ThriftTestIf { out = thing; } - void testSet(set& out, const set& thing) { + void testSet(set& out, const set& thing) override { printf("testSet({"); set::const_iterator s_iter; bool first = true; @@ -201,7 +201,7 @@ class TestHandler : public ThriftTestIf { out = thing; } - void testList(vector& out, const vector& thing) { + void testList(vector& out, const vector& thing) override { printf("testList({"); vector::const_iterator l_iter; bool first = true; @@ -217,17 +217,17 @@ class TestHandler : public ThriftTestIf { out = thing; } - Numberz::type testEnum(const Numberz::type thing) { + Numberz::type testEnum(const Numberz::type thing) override { printf("testEnum(%d)\n", thing); return thing; } - UserId testTypedef(const UserId thing) { + UserId testTypedef(const UserId thing) override { printf("testTypedef(%" PRId64 ")\n", thing); return thing; } - void testMapMap(map >& mapmap, const int32_t hello) { + void testMapMap(map >& mapmap, const int32_t hello) override { printf("testMapMap(%d)\n", hello); map pos; @@ -241,7 +241,7 @@ class TestHandler : public ThriftTestIf { mapmap.insert(make_pair(-4, neg)); } - void testInsanity(map >& insane, const Insanity& argument) { + void testInsanity(map >& insane, const Insanity& argument) override { printf("testInsanity()\n"); Insanity looney; @@ -297,7 +297,7 @@ class TestHandler : public ThriftTestIf { const int64_t arg2, const std::map& arg3, const Numberz::type arg4, - const UserId arg5) { + const UserId arg5) override { (void)arg3; (void)arg4; (void)arg5; @@ -310,7 +310,7 @@ class TestHandler : public ThriftTestIf { hello.i64_thing = (int64_t)arg2; } - void testException(const std::string& arg) { + void testException(const std::string& arg) override { printf("testException(%s)\n", arg.c_str()); if (arg.compare("Xception") == 0) { Xception e; @@ -329,7 +329,7 @@ class TestHandler : public ThriftTestIf { void testMultiException(Xtruct& result, const std::string& arg0, - const std::string& arg1) { + const std::string& arg1) override { printf("testMultiException(%s, %s)\n", arg0.c_str(), arg1.c_str()); @@ -349,7 +349,7 @@ class TestHandler : public ThriftTestIf { } } - void testOneway(const int32_t aNum) { + void testOneway(const int32_t aNum) override { printf("testOneway(%d): call received\n", aNum); } }; @@ -357,33 +357,33 @@ class TestHandler : public ThriftTestIf { class SecondHandler : public SecondServiceIf { public: - void secondtestString(std::string& result, const std::string& thing) + void secondtestString(std::string& result, const std::string& thing) override { result = "testString(\"" + thing + "\")"; } }; class TestProcessorEventHandler : public TProcessorEventHandler { - virtual void* getContext(const char* fn_name, void* serverContext) { + void* getContext(const char* fn_name, void* serverContext) override { (void)serverContext; return new std::string(fn_name); } - virtual void freeContext(void* ctx, const char* fn_name) { + void freeContext(void* ctx, const char* fn_name) override { (void)fn_name; delete static_cast(ctx); } - virtual void preRead(void* ctx, const char* fn_name) { communicate("preRead", ctx, fn_name); } - virtual void postRead(void* ctx, const char* fn_name, uint32_t bytes) { + void preRead(void* ctx, const char* fn_name) override { communicate("preRead", ctx, fn_name); } + void postRead(void* ctx, const char* fn_name, uint32_t bytes) override { (void)bytes; communicate("postRead", ctx, fn_name); } - virtual void preWrite(void* ctx, const char* fn_name) { communicate("preWrite", ctx, fn_name); } - virtual void postWrite(void* ctx, const char* fn_name, uint32_t bytes) { + void preWrite(void* ctx, const char* fn_name) override { communicate("preWrite", ctx, fn_name); } + void postWrite(void* ctx, const char* fn_name, uint32_t bytes) override { (void)bytes; communicate("postWrite", ctx, fn_name); } - virtual void asyncComplete(void* ctx, const char* fn_name) { + void asyncComplete(void* ctx, const char* fn_name) override { communicate("asyncComplete", ctx, fn_name); } - virtual void handlerError(void* ctx, const char* fn_name) { + void handlerError(void* ctx, const char* fn_name) override { communicate("handlerError", ctx, fn_name); } @@ -395,136 +395,136 @@ class TestProcessorEventHandler : public TProcessorEventHandler { class TestHandlerAsync : public ThriftTestCobSvIf { public: TestHandlerAsync(std::shared_ptr& handler) : _delegate(handler) {} - virtual ~TestHandlerAsync() {} + ~TestHandlerAsync() override = default; - virtual void testVoid(std::function cob) { + void testVoid(std::function cob) override { _delegate->testVoid(); cob(); } - virtual void testString(std::function cob, - const std::string& thing) { + void testString(std::function cob, + const std::string& thing) override { std::string res; _delegate->testString(res, thing); cob(res); } - virtual void testBool(std::function cob, const bool thing) { + void testBool(std::function cob, const bool thing) override { bool res = _delegate->testBool(thing); cob(res); } - virtual void testByte(std::function cob, const int8_t thing) { + void testByte(std::function cob, const int8_t thing) override { int8_t res = _delegate->testByte(thing); cob(res); } - virtual void testI32(std::function cob, const int32_t thing) { + void testI32(std::function cob, const int32_t thing) override { int32_t res = _delegate->testI32(thing); cob(res); } - virtual void testI64(std::function cob, const int64_t thing) { + void testI64(std::function cob, const int64_t thing) override { int64_t res = _delegate->testI64(thing); cob(res); } - virtual void testDouble(std::function cob, const double thing) { + void testDouble(std::function cob, const double thing) override { double res = _delegate->testDouble(thing); cob(res); } - virtual void testBinary(std::function cob, - const std::string& thing) { + void testBinary(std::function cob, + const std::string& thing) override { std::string res; _delegate->testBinary(res, thing); cob(res); } - virtual void testStruct(std::function cob, const Xtruct& thing) { + void testStruct(std::function cob, const Xtruct& thing) override { Xtruct res; _delegate->testStruct(res, thing); cob(res); } - virtual void testNest(std::function cob, const Xtruct2& thing) { + void testNest(std::function cob, const Xtruct2& thing) override { Xtruct2 res; _delegate->testNest(res, thing); cob(res); } - virtual void testMap(std::function const& _return)> cob, - const std::map& thing) { + void testMap(std::function const& _return)> cob, + const std::map& thing) override { std::map res; _delegate->testMap(res, thing); cob(res); } - virtual void testStringMap( + void testStringMap( std::function const& _return)> cob, - const std::map& thing) { + const std::map& thing) override { std::map res; _delegate->testStringMap(res, thing); cob(res); } - virtual void testSet(std::function const& _return)> cob, - const std::set& thing) { + void testSet(std::function const& _return)> cob, + const std::set& thing) override { std::set res; _delegate->testSet(res, thing); cob(res); } - virtual void testList(std::function const& _return)> cob, - const std::vector& thing) { + void testList(std::function const& _return)> cob, + const std::vector& thing) override { std::vector res; _delegate->testList(res, thing); cob(res); } - virtual void testEnum(std::function cob, - const Numberz::type thing) { + void testEnum(std::function cob, + const Numberz::type thing) override { Numberz::type res = _delegate->testEnum(thing); cob(res); } - virtual void testTypedef(std::function cob, const UserId thing) { + void testTypedef(std::function cob, const UserId thing) override { UserId res = _delegate->testTypedef(thing); cob(res); } - virtual void testMapMap( + void testMapMap( std::function > const& _return)> cob, - const int32_t hello) { + const int32_t hello) override { std::map > res; _delegate->testMapMap(res, hello); cob(res); } - virtual void testInsanity( + void testInsanity( std::function > const& _return)> cob, - const Insanity& argument) { + const Insanity& argument) override { std::map > res; _delegate->testInsanity(res, argument); cob(res); } - virtual void testMulti(std::function cob, + void testMulti(std::function cob, const int8_t arg0, const int32_t arg1, const int64_t arg2, const std::map& arg3, const Numberz::type arg4, - const UserId arg5) { + const UserId arg5) override { Xtruct res; _delegate->testMulti(res, arg0, arg1, arg2, arg3, arg4, arg5); cob(res); } - virtual void testException( + void testException( std::function cob, std::function exn_cob, - const std::string& arg) { + const std::string& arg) override { try { _delegate->testException(arg); } catch (const apache::thrift::TException& e) { @@ -534,11 +534,11 @@ class TestHandlerAsync : public ThriftTestCobSvIf { cob(); } - virtual void testMultiException( + void testMultiException( std::function cob, std::function exn_cob, const std::string& arg0, - const std::string& arg1) { + const std::string& arg1) override { Xtruct res; try { _delegate->testMultiException(res, arg0, arg1); @@ -549,7 +549,7 @@ class TestHandlerAsync : public ThriftTestCobSvIf { cob(res); } - virtual void testOneway(std::function cob, const int32_t secondsToSleep) { + void testOneway(std::function cob, const int32_t secondsToSleep) override { _delegate->testOneway(secondsToSleep); cob(); } @@ -672,7 +672,7 @@ int main(int argc, char** argv) { std::shared_ptr jsonProtocolFactory(new TJSONProtocolFactory()); protocolFactory = jsonProtocolFactory; } else if (protocol_type == "compact" || protocol_type == "multic") { - TCompactProtocolFactoryT *compactProtocolFactory = new TCompactProtocolFactoryT(); + auto *compactProtocolFactory = new TCompactProtocolFactoryT(); compactProtocolFactory->setContainerSizeLimit(container_limit); compactProtocolFactory->setStringSizeLimit(string_limit); protocolFactory.reset(compactProtocolFactory); @@ -680,7 +680,7 @@ int main(int argc, char** argv) { std::shared_ptr headerProtocolFactory(new THeaderProtocolFactory()); protocolFactory = headerProtocolFactory; } else { - TBinaryProtocolFactoryT* binaryProtocolFactory = new TBinaryProtocolFactoryT(); + auto* binaryProtocolFactory = new TBinaryProtocolFactoryT(); binaryProtocolFactory->setContainerSizeLimit(container_limit); binaryProtocolFactory->setStringSizeLimit(string_limit); protocolFactory.reset(binaryProtocolFactory); @@ -810,7 +810,7 @@ int main(int argc, char** argv) { } } - if (server.get() != NULL) { + if (server.get() != nullptr) { if (protocol_type == "header") { // Tell the server to use the same protocol for input / output // if using header diff --git a/tutorial/cpp/CppServer.cpp b/tutorial/cpp/CppServer.cpp index 3b5ce4012bf..635afefda0d 100644 --- a/tutorial/cpp/CppServer.cpp +++ b/tutorial/cpp/CppServer.cpp @@ -46,16 +46,16 @@ using namespace shared; class CalculatorHandler : public CalculatorIf { public: - CalculatorHandler() {} + CalculatorHandler() = default; - void ping() { cout << "ping()" << endl; } + void ping() override { cout << "ping()" << endl; } - int32_t add(const int32_t n1, const int32_t n2) { + int32_t add(const int32_t n1, const int32_t n2) override { cout << "add(" << n1 << ", " << n2 << ")" << endl; return n1 + n2; } - int32_t calculate(const int32_t logid, const Work& work) { + int32_t calculate(const int32_t logid, const Work& work) override { cout << "calculate(" << logid << ", " << work << ")" << endl; int32_t val; @@ -94,12 +94,12 @@ class CalculatorHandler : public CalculatorIf { return val; } - void getStruct(SharedStruct& ret, const int32_t logid) { + void getStruct(SharedStruct& ret, const int32_t logid) override { cout << "getStruct(" << logid << ")" << endl; ret = log[logid]; } - void zip() { cout << "zip()" << endl; } + void zip() override { cout << "zip()" << endl; } protected: map log; @@ -113,8 +113,8 @@ class CalculatorHandler : public CalculatorIf { */ class CalculatorCloneFactory : virtual public CalculatorIfFactory { public: - virtual ~CalculatorCloneFactory() {} - virtual CalculatorIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) + ~CalculatorCloneFactory() override = default; + CalculatorIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) override { std::shared_ptr sock = std::dynamic_pointer_cast(connInfo.transport); cout << "Incoming connection\n"; @@ -124,7 +124,7 @@ class CalculatorCloneFactory : virtual public CalculatorIfFactory { cout << "\tPeerPort: " << sock->getPeerPort() << "\n"; return new CalculatorHandler; } - virtual void releaseHandler( ::shared::SharedServiceIf* handler) { + void releaseHandler( ::shared::SharedServiceIf* handler) override { delete handler; } }; From 7489ed6ac8bad64e72fa83ec9d53e1eeddca6c23 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 5 Mar 2018 11:34:21 -0500 Subject: [PATCH 190/756] THRIFT-4506: fix use of assert for correctness in Java SASL negotiation Client: java --- lib/java/src/org/apache/thrift/transport/TSaslTransport.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java index 7938916b035..0709342eaba 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java @@ -287,7 +287,7 @@ public void open() throws TTransportException { if (message.status == NegotiationStatus.COMPLETE && getRole() == SaslRole.CLIENT) { LOGGER.debug("{}: All done!", getRole()); - break; + continue; } sendSaslMessage(sasl.isComplete() ? NegotiationStatus.COMPLETE : NegotiationStatus.OK, @@ -295,8 +295,6 @@ public void open() throws TTransportException { } 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 From 91a4fd7076a703975f1b901fbddbeee854ae0d7b Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Wed, 30 Jan 2019 10:24:33 -0500 Subject: [PATCH 191/756] Update the pull request template [ci skip] --- pull_request_template.md | 69 +++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/pull_request_template.md b/pull_request_template.md index b719fc3ca2d..df2fdded4ec 100644 --- a/pull_request_template.md +++ b/pull_request_template.md @@ -1,37 +1,48 @@ -### Pull Request Guidance ### +### Pull Request ### -Review the following items to ensure a smooth pull request experience. +The [Contributing Guide](https://github.com/apache/thrift/blob/master/CONTRIBUTING.md) has more details and tips for +committing properly. -- [ ] Did you make a breaking change? If so: + - - [ ] Add (or reference) an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) THRIFT ticket. - - [ ] Add a `Breaking-Change` label to the Jira ticket. - - [ ] Add a note to the `lib//README.md` file. - - [ ] Add a line to the `CHANGES.md` file. -- [ ] Is this change significant enough to be in release notes? - All release-note worthy changes require an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) THRIFT ticket. - For example: - - Breaking Changes - - New, Deprecated, or Removed Languages - - Security Fix - - Significant Refactoring - -- [ ] If there is an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) ticket: - - - [ ] Is the [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) THRIFT ticket identifier in the PR title? - - THRIFT-9999: an example pull request title - - - [ ] Is the [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) THRIFT ticket identifier and affected languages in the commit message? - - THRIFT-9999: [summary of fix, one line if possible] - Client: [language(s) affected, comma separated, use lib/ directory names please] + +Review the following checklist to ensure a smooth pull request experience. - [ ] Did you squash your changes to a single commit? - Committers can squash when they merge, but sometimes we forget, and it makes the history - pretty dirty. Please squash your pull requests to a single commit if you can. - -For more information about committing, see CONTRIBUTING.md +- [ ] Do you need an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) ticket?
Expand for guidance... + - `Yes` if your change requires a release note. + - `Yes` if your change is a breaking change. + - `No` if you change is trivial, such as fixing a typo. +
+ +- [ ] Is this change worthy of a release note?
Examples of Release Note-worthy examples... + - Breaking Changes + - New, Deprecated, or Removed Languages + - Security Fixes + - Significant Refactoring + - Changing how the product is built +
+ +- [ ] Breaking changes have additional requirements:
Expand for instructions... + - Add or reference an existing Apache Jira THRIFT ticket. + - Add a `Breaking-Change` label to the Jira ticket. + - Add a note to the `lib//README.md` file. + - Add a line to the `CHANGES.md` file. +
+ +- [ ] Does this change require a build?
Expand for guidance... + - `Yes` for any code change + - `Yes` for any build script change + - `Yes` for any docker build environment change + - `Yes` for any change affecting the cross test suite + - `No` for documentation-only changes + - `No` for trivial changes, for example fixing a typo. +
+ If your change does not require a build, you can add [ci skip] to the end of your commit message.
+ This will avoid costly and unnecessary builds in both the pull request and once it is merged. +
+ +For more information about committing, see the [Contributing Guide](https://github.com/apache/thrift/blob/master/CONTRIBUTING.md). From 06ecaae4f3ff10a607d85e2c8ccb8fcaed3e68ab Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Wed, 30 Jan 2019 10:29:08 -0500 Subject: [PATCH 192/756] Updated the Contributing Guide [ci skip] Added details about trivial changes not needing a Jira ticket. --- CONTRIBUTING.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7a1d710aeb9..7a199f73c2e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,17 +13,17 @@ it activates the continuous integration (CI) build systems at Appveyor and Travi on a variety of Linux and Windows configurations and run all the test suites. Follow these requirements for a successful pull request: - 1. All code changes require an [Apache Jira THRIFT Issue](http://issues.apache.org/jira/browse/THRIFT) ticket. + 1. All significant changes require an [Apache Jira THRIFT Issue](http://issues.apache.org/jira/browse/THRIFT) ticket. Trivial changes such as fixing a typo or a compiler warning do not. 1. All pull requests should contain a single commit per issue, or we will ask you to squash it. - 1. The pull request title must begin with the Jira THRIFT ticket identifier, for example: + 1. The pull request title must begin with the Jira THRIFT ticket identifier if it has an associated ticket, for example: THRIFT-9999: an example pull request title 1. Commit messages must follow this pattern for code changes (deviations will not be merged): THRIFT-9999: [summary of fix, one line if possible] - Client: [language(s) affected, comma separated, use lib/ directory names please] + Client: [language(s) affected, comma separated, for example: "cpp,erl,perl"] Instructions: @@ -64,11 +64,11 @@ For unix systems, see our detailed instructions on the [Docker README](/build/do ## Contributing via Patch ## -Some changes do not require a build, for example in documentation. For changes that are not code or build related, you can submit a patch on Jira for review. To create a patch from changes in your local directory: +To create a patch from changes in your local directory: git diff > ../THRIFT-NNNN.patch -then wait for contributors or committers to review your changes, and then for a committer to apply your patch. +then wait for contributors or committers to review your changes, and then for a committer to apply your patch. This is not the preferred way to submit changes and incurs additional overhead for committers who must then create a pull request for you. ## GitHub recipes for Pull Requests ## From 4f7d93d8c35565fc9c5a43e4637505352c974c69 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Wed, 30 Jan 2019 10:42:33 -0500 Subject: [PATCH 193/756] Update grunt-shell-spawn javascript dependency --- lib/js/package-lock.json | 29 ++++++++++------------------- lib/js/package.json | 2 +- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/lib/js/package-lock.json b/lib/js/package-lock.json index 5a6ab05872c..9110814c9a6 100644 --- a/lib/js/package-lock.json +++ b/lib/js/package-lock.json @@ -236,8 +236,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true + "dev": true }, "assign-symbols": { "version": "1.0.0", @@ -884,7 +883,6 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "dev": true, - "optional": true, "requires": { "delayed-stream": "~1.0.0" } @@ -1155,8 +1153,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "optional": true + "dev": true }, "deps-sort": { "version": "2.0.0", @@ -1553,8 +1550,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true, - "optional": true + "dev": true }, "eyes": { "version": "0.1.8", @@ -2086,9 +2082,9 @@ } }, "grunt-shell-spawn": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/grunt-shell-spawn/-/grunt-shell-spawn-0.3.12.tgz", - "integrity": "sha512-TprZct92sQ4M2Q92piaeLsCrx4+gq/ageuxjZsRG6cglKt7x7rGA3YHt8D30+G789v+/pw4l0tDjEyrkMXx2tA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/grunt-shell-spawn/-/grunt-shell-spawn-0.4.0.tgz", + "integrity": "sha512-lfYvEQjbO1Wv+1Fk3d3XlcEpuQjyXiErZMkiz/i/tDQeMHHGF1LziqA4ZcietBAo/bM2RHdEEUJfnNWt1VRMwQ==", "dev": true, "requires": { "grunt": ">=0.4.x" @@ -2599,8 +2595,7 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true, - "optional": true + "dev": true }, "js-yaml": { "version": "3.5.5", @@ -2624,8 +2619,7 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true + "dev": true }, "jsdoc": { "version": "3.5.5", @@ -3073,15 +3067,13 @@ "version": "1.37.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", - "dev": true, - "optional": true + "dev": true }, "mime-types": { "version": "2.1.21", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", "dev": true, - "optional": true, "requires": { "mime-db": "~1.37.0" } @@ -4696,8 +4688,7 @@ "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true + "dev": true }, "typedarray": { "version": "0.0.6", diff --git a/lib/js/package.json b/lib/js/package.json index 8b16d95b825..a10aaf1e6e8 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -19,7 +19,7 @@ "grunt-contrib-qunit": "^3.1.0", "grunt-contrib-uglify": "^1.0.1", "grunt-jsdoc": "^2.2.1", - "grunt-shell-spawn": "^0.3.12", + "grunt-shell-spawn": "^0.4.0", "jslint": "^0.12.0", "node-int64": "^0.4.0" }, From 2ec93c8a2da2531755078ab6d5a65a96e26cf4c2 Mon Sep 17 00:00:00 2001 From: Sebastian Zenker Date: Thu, 31 Jan 2019 02:14:27 +0100 Subject: [PATCH 194/756] THRIFT-4763: HTML compiler produces invalid HTML document (#1720) * HTML: the html generator did generate a closing tag without a match * THRIFT-4763: added HTML test and fixed up additional HTML generation issues --- .../src/thrift/generate/t_html_generator.cc | 39 +- package-lock.json | 362 ++++++++++++++++++ package.json | 1 + test/Makefile.am | 9 +- 4 files changed, 390 insertions(+), 21 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_html_generator.cc b/compiler/cpp/src/thrift/generate/t_html_generator.cc index 8dfa3897ebf..00c9a0a9dce 100644 --- a/compiler/cpp/src/thrift/generate/t_html_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_html_generator.cc @@ -127,10 +127,10 @@ class t_html_generator : public t_generator { */ void t_html_generator::generate_program_toc() { f_out_ << "" - << "" << endl; + "table-condensed\">" + << "" << endl; generate_program_toc_row(program_); - f_out_ << "
ModuleServicesData typesConstants
ModuleServicesData typesConstants
" << endl; + f_out_ << "" << endl; } /** @@ -240,7 +240,7 @@ void t_html_generator::generate_program_toc_row(t_program* tprog) { f_out_ << con_iter->second << "
" << endl; } } - f_out_ << "
" << endl << ""; + f_out_ << "" << endl << ""; } /** @@ -253,9 +253,8 @@ void t_html_generator::generate_program() { current_file_ = program_->get_name() + ".html"; string fname = get_out_dir() + current_file_; f_out_.open(fname.c_str()); - f_out_ << "" << endl; - f_out_ << "" << endl; + f_out_ << "" << endl; + f_out_ << "" << endl; f_out_ << "" << endl; f_out_ << "" << endl; generate_style_tag(); @@ -271,9 +270,9 @@ void t_html_generator::generate_program() { f_out_ << "

Constants

" << endl; vector consts = program_->get_consts(); f_out_ << ""; - f_out_ << "" << endl; + f_out_ << "" << endl; generate_consts(consts); - f_out_ << "
ConstantTypeValue
ConstantTypeValue
"; + f_out_ << ""; } if (!program_->get_enums().empty()) { @@ -335,16 +334,16 @@ void t_html_generator::generate_index() { current_file_ = "index.html"; string index_fname = get_out_dir() + current_file_; f_out_.open(index_fname.c_str()); - f_out_ << "" << endl; + f_out_ << "" << endl << "" << endl; generate_style_tag(); f_out_ << "All Thrift declarations" << endl << "
" << endl << "

All Thrift declarations

" << endl; f_out_ << "" - << "" << endl; + "table-condensed\">" + << "" << endl; vector programs; generate_program_toc_rows(program_, programs); - f_out_ << "
ModuleServicesData typesConstants
ModuleServicesData typesConstants
" << endl; + f_out_ << "" << endl; f_out_ << "
" << endl; f_out_.close(); } @@ -861,14 +860,14 @@ void t_html_generator::print_fn_args_doc(t_function* tfunction) { f_out_ << "

get_name() << "\">Parameters

" << endl; f_out_ << ""; - f_out_ << ""; + f_out_ << ""; for (; arg_iter != args.end(); arg_iter++) { f_out_ << "" << endl; } - f_out_ << "
NameDescription
NameDescription
" << (*arg_iter)->get_name(); f_out_ << ""; f_out_ << escape_html((*arg_iter)->get_doc()); f_out_ << "
"; + f_out_ << ""; } } @@ -885,14 +884,14 @@ void t_html_generator::print_fn_args_doc(t_function* tfunction) { f_out_ << "

get_name() << "\">Exceptions

" << endl; f_out_ << ""; - f_out_ << ""; + f_out_ << ""; for (; ex_iter != excepts.end(); ex_iter++) { f_out_ << "" << endl; } - f_out_ << "
TypeDescription
TypeDescription
" << (*ex_iter)->get_type()->get_name(); f_out_ << ""; f_out_ << escape_html((*ex_iter)->get_doc()); f_out_ << "
"; + f_out_ << ""; } } } @@ -975,8 +974,8 @@ void t_html_generator::generate_struct(t_struct* tstruct) { vector members = tstruct->get_members(); vector::iterator mem_iter = members.begin(); f_out_ << ""; - f_out_ << "" << endl; + f_out_ << "" << endl; for (; mem_iter != members.end(); mem_iter++) { f_out_ << "" << endl; } - f_out_ << "
KeyFieldTypeDescriptionRequirednessDefault value
KeyFieldTypeDescriptionRequirednessDefault value
" << (*mem_iter)->get_key() << ""; f_out_ << (*mem_iter)->get_name(); @@ -1001,7 +1000,7 @@ void t_html_generator::generate_struct(t_struct* tstruct) { } f_out_ << "

"; + f_out_ << "
"; print_doc(tstruct); f_out_ << ""; } diff --git a/package-lock.json b/package-lock.json index 8a6645fc610..8eb8a212236 100644 --- a/package-lock.json +++ b/package-lock.json @@ -149,6 +149,21 @@ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, "async": { "version": "1.5.2", "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -160,6 +175,24 @@ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, "babylon": { "version": "7.0.0-beta.19", "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", @@ -172,6 +205,15 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, "bindings": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", @@ -247,6 +289,12 @@ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, "catharsis": { "version": "0.8.9", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", @@ -321,6 +369,15 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", @@ -370,6 +427,15 @@ "which": "^1.2.9" } }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -436,6 +502,12 @@ "rimraf": "^2.2.8" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -457,6 +529,16 @@ "esutils": "^2.0.2" } }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -697,6 +779,12 @@ "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==", "dev": true }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, "external-editor": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", @@ -708,6 +796,12 @@ "tmp": "^0.0.33" } }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, "fast-deep-equal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", @@ -787,6 +881,23 @@ "is-callable": "^1.1.3" } }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -870,6 +981,15 @@ "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", "dev": true }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, "github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -945,6 +1065,36 @@ } } }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + } + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -972,6 +1122,45 @@ "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true }, + "html-validator": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/html-validator/-/html-validator-3.1.3.tgz", + "integrity": "sha512-RhjcQIHS/SfYzQ+/JrFWKU6AVve6AuwftAG/cWX3+bpvBK/tGMqbOleKlsAxLrKD84+GSJ1oJGnkyhdVLBGCqg==", + "dev": true, + "requires": { + "request": "2.88.0", + "valid-url": "1.0.9" + } + }, + "html-validator-cli": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/html-validator-cli/-/html-validator-cli-4.1.4.tgz", + "integrity": "sha512-4vGP107UDhhNHeWA5N8j/nUPlQbtB/W/K2x/P7aElbWMWrOkJA0MRSVFsMFrTPSAAjZWCG9uki2+1cQDzFtVcQ==", + "dev": true, + "requires": { + "html-validator": "3.1.3", + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1108,6 +1297,12 @@ "has-symbols": "^1.0.0" } }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -1120,6 +1315,12 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, "istanbul": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", @@ -1203,6 +1404,12 @@ "xmlcreate": "^1.0.1" } }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, "jsdoc": { "version": "3.5.5", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", @@ -1232,6 +1439,12 @@ "node-int64": "0.4.0" } }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -1244,6 +1457,24 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, "klaw": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz", @@ -1275,6 +1506,21 @@ "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", "dev": true }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "dev": true + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "dev": true, + "requires": { + "mime-db": "~1.37.0" + } + }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", @@ -1388,6 +1634,12 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1507,6 +1759,12 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, "pify": { "version": "2.3.0", "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -1598,6 +1856,12 @@ "integrity": "sha512-OE+a6vzqazc+K6LxJrX5UPyKFvGnL5CYmq2jFGNIBWHpc4QyE49/YOumcrpQFJpfejmvRtbJzgO1zPmMCqlbBg==", "dev": true }, + "psl": { + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", + "dev": true + }, "pump": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", @@ -1619,6 +1883,12 @@ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -1660,6 +1930,34 @@ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -1832,6 +2130,23 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", @@ -2014,6 +2329,24 @@ "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", "dev": true }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -2029,6 +2362,12 @@ "safe-buffer": "^5.0.1" } }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -2132,6 +2471,29 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", "dev": true }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "valid-url": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index 729e9bfc1d9..6393ee7128d 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "eslint": "^5.7.0", "eslint-config-prettier": "^3.1.0", "eslint-plugin-prettier": "^3.0.0", + "html-validator-cli": "^4.1.4", "istanbul": "^0.4.5", "jsdoc": "^3.5.5", "json-int64": "^1.0.0", diff --git a/test/Makefile.am b/test/Makefile.am index 682e04a6eeb..f6b867cf138 100755 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -103,10 +103,17 @@ PRECROSS_TARGET += precross-rs endif # -# generate html for ThriftTest.thrift +# generate html for ThriftTest.thrift AND validate it! # +if WITH_NODEJS check-local: $(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/test/ThriftTest.thrift + $(top_builddir)/node_modules/.bin/html-validator --file=gen-html/index.html --verbose + $(top_builddir)/node_modules/.bin/html-validator --file=gen-html/ThriftTest.html --verbose +else +check-local: + $(top_builddir)/compiler/cpp/thrift --gen html -r $(top_srcdir)/test/ThriftTest.thrift +endif clean-local: $(RM) -r $(top_srcdir)/test/gen-html/ From f6511c904bcac1dd8c7e24aa3432326738865f1b Mon Sep 17 00:00:00 2001 From: Jun Date: Fri, 1 Feb 2019 12:07:58 +0800 Subject: [PATCH 195/756] THRIFT-4767: Added TSocket/TSSLSocket support tcp keep-alive in python (#1725) * THRIFT-4767: Added TSocket support tcp keep-alive in python * TSSLSocket support tcp keep-alive --- lib/py/src/transport/TSSLSocket.py | 5 ++++- lib/py/src/transport/TSocket.py | 11 ++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/py/src/transport/TSSLSocket.py b/lib/py/src/transport/TSSLSocket.py index 00d1f10f572..c87e81c14c0 100644 --- a/lib/py/src/transport/TSSLSocket.py +++ b/lib/py/src/transport/TSSLSocket.py @@ -232,6 +232,7 @@ def __init__(self, host='localhost', port=9090, *args, **kwargs): ``validate_callback`` (cert, hostname) -> None: Called after SSL handshake. Can raise when hostname does not match the cert. + ``socket_keepalive`` enable TCP keepalive, default off. """ self.is_valid = False self.peercert = None @@ -259,9 +260,11 @@ def __init__(self, host='localhost', port=9090, *args, **kwargs): kwargs['cert_reqs'] = ssl.CERT_REQUIRED if validate else ssl.CERT_NONE unix_socket = kwargs.pop('unix_socket', None) + socket_keepalive = kwargs.pop('socket_keepalive', False) self._validate_callback = kwargs.pop('validate_callback', _match_hostname) TSSLBase.__init__(self, False, host, kwargs) - TSocket.TSocket.__init__(self, host, port, unix_socket) + TSocket.TSocket.__init__(self, host, port, unix_socket, + socket_keepalive=socket_keepalive) def close(self): try: diff --git a/lib/py/src/transport/TSocket.py b/lib/py/src/transport/TSocket.py index a7d661703dc..c8be25a4c2b 100644 --- a/lib/py/src/transport/TSocket.py +++ b/lib/py/src/transport/TSocket.py @@ -50,7 +50,9 @@ def close(self): class TSocket(TSocketBase): """Socket implementation of TTransport base.""" - def __init__(self, host='localhost', port=9090, unix_socket=None, socket_family=socket.AF_UNSPEC): + def __init__(self, host='localhost', port=9090, unix_socket=None, + socket_family=socket.AF_UNSPEC, + socket_keepalive=False): """Initialize a TSocket @param host(str) The host to connect to. @@ -58,6 +60,7 @@ def __init__(self, host='localhost', port=9090, unix_socket=None, socket_family= @param unix_socket(str) The filename of a unix socket to connect to. (host and port will be ignored.) @param socket_family(int) The socket family to use with this socket. + @param socket_keepalive(bool) enable TCP keepalive, default off. """ self.host = host self.port = port @@ -65,6 +68,7 @@ def __init__(self, host='localhost', port=9090, unix_socket=None, socket_family= self._unix_socket = unix_socket self._timeout = None self._socket_family = socket_family + self._socket_keepalive = socket_keepalive def setHandle(self, h): self.handle = h @@ -99,6 +103,11 @@ def open(self): raise TTransportException(TTransportException.NOT_OPEN, msg) for family, socktype, _, _, sockaddr in addrs: handle = self._do_open(family, socktype) + + # TCP_KEEPALIVE + if self._socket_keepalive: + handle.setsockopt(socket.IPPROTO_TCP, socket.SO_KEEPALIVE, 1) + handle.settimeout(self._timeout) try: handle.connect(sockaddr) From f95620d2b17ddd913f8108b39aa8138abe7d6027 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 28 Jan 2019 18:15:13 -0500 Subject: [PATCH 196/756] THRIFT-4405: sanity tests relating to sequence numbers - prove all servers return the sequence ID given - prove that sequences that wrap around the int32_t space are handled ok --- CHANGES.md | 4 +- Makefile.am | 1 + lib/cpp/src/thrift/TBase.h | 2 +- lib/cpp/src/thrift/Thrift.h | 2 +- lib/cpp/src/thrift/concurrency/Thread.h | 2 +- lib/cpp/src/thrift/protocol/TJSONProtocol.cpp | 4 +- test/cpp/src/TestClient.cpp | 65 +++++++++++++++++-- 7 files changed, 66 insertions(+), 14 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b77003bcaa6..77893e038ad 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,18 +16,18 @@ ### Breaking Changes -- [THRIFT-4743](https://issues.apache.org/jira/browse/THRIFT-4743) - compiler: remove plug-in mechanism +- [THRIFT-4743](https://issues.apache.org/jira/browse/THRIFT-4743) - compiler: removed the plug-in mechanism - [THRIFT-4720](https://issues.apache.org/jira/browse/THRIFT-4720) - cpp: C++03/C++98 support has been removed; also removed boost as a runtime dependency - [THRIFT-4730](https://issues.apache.org/jira/browse/THRIFT-4730) - cpp: BoostThreadFactory, PosixThreadFactory, StdThreadFactory removed - [THRIFT-4732](https://issues.apache.org/jira/browse/THRIFT-4732) - cpp: CMake build changed to use BUILD_SHARED_LIBS - [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735) - cpp: Removed Qt4 support - [THRIFT-4740](https://issues.apache.org/jira/browse/THRIFT-4740) - cpp: Use std::chrono::duration for timeouts +- [THRIFT-4672](https://issues.apache.org/jira/browse/THRIFT-4672) - cpp: TTransport::getOrigin() is now const - [THRIFT-4702](https://issues.apache.org/jira/browse/THRIFT-4702) - java: class org.apache.thrift.AutoExpandingBuffer is no longer public - [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - java: changes to UTF-8 handling require JDK 1.7 at a minimum - [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - java: class org.apache.thrift.ShortStack is no longer public - [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - java: change return type signature of 'process' methods - [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - js: now uses node-int64 for 64 bit integer constants -- [THRIFT-4672](https://issues.apache.org/jira/browse/THRIFT-4672) - C++: TTransport::getOrigin() is now const ### Known Issues (Blocker or Critical) diff --git a/Makefile.am b/Makefile.am index 1f2d4836ab0..bacd0082a65 100755 --- a/Makefile.am +++ b/Makefile.am @@ -43,6 +43,7 @@ CLEANFILES = \ DISTCLEANFILES = \ Makefile \ Makefile.in \ + aclocal.m4 \ apache-thrift-test-library \ autoscan.log \ compile \ diff --git a/lib/cpp/src/thrift/TBase.h b/lib/cpp/src/thrift/TBase.h index cc31c346af7..e2e78e72545 100644 --- a/lib/cpp/src/thrift/TBase.h +++ b/lib/cpp/src/thrift/TBase.h @@ -28,7 +28,7 @@ namespace thrift { class TBase { public: - virtual ~TBase()= default;; + virtual ~TBase() = default; virtual uint32_t read(protocol::TProtocol* iprot) = 0; virtual uint32_t write(protocol::TProtocol* oprot) const = 0; }; diff --git a/lib/cpp/src/thrift/Thrift.h b/lib/cpp/src/thrift/Thrift.h index 951cc2865ba..6cb24e660e1 100644 --- a/lib/cpp/src/thrift/Thrift.h +++ b/lib/cpp/src/thrift/Thrift.h @@ -98,7 +98,7 @@ class TDelayedException { template static TDelayedException* delayException(const E& e); virtual void throw_it() = 0; - virtual ~TDelayedException()= default;; + virtual ~TDelayedException() = default; }; template diff --git a/lib/cpp/src/thrift/concurrency/Thread.h b/lib/cpp/src/thrift/concurrency/Thread.h index bced240f019..e803a82ce78 100644 --- a/lib/cpp/src/thrift/concurrency/Thread.h +++ b/lib/cpp/src/thrift/concurrency/Thread.h @@ -39,7 +39,7 @@ class Thread; class Runnable { public: - virtual ~Runnable()= default;; + virtual ~Runnable() = default; virtual void run() = 0; /** diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp index dcd498f7b51..53cc140b6e6 100644 --- a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp @@ -303,9 +303,9 @@ static bool isLowSurrogate(uint16_t val) { class TJSONContext { public: - TJSONContext()= default;; + TJSONContext() = default; - virtual ~TJSONContext()= default;; + virtual ~TJSONContext() = default; /** * Write context data to the transport. Default is to do nothing. diff --git a/test/cpp/src/TestClient.cpp b/test/cpp/src/TestClient.cpp index 2a065780655..f7c491239ff 100644 --- a/test/cpp/src/TestClient.cpp +++ b/test/cpp/src/TestClient.cpp @@ -60,6 +60,53 @@ using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using namespace thrift::test; +// +// A pedantic protocol that checks to make sure the response sequence ID +// is the same as the sent sequence ID. lib/cpp always sends zero for +// synchronous clients, so this bumps the number to make sure it gets +// returned properly from the remote server. Any server that does not +// respond with the same sequence number is violating the sequence ID +// agreement between client and server. +// + +template +class TPedanticProtocol : public _P +{ + public: + TPedanticProtocol(std::shared_ptr& transport) + : _P(transport), m_last_seqid(std::numeric_limits::max() - 10) { } + + virtual uint32_t writeMessageBegin_virt(const std::string& name, + const TMessageType messageType, + const int32_t in_seqid) override + { + int32_t seqid = in_seqid; + if (!seqid) { // this is typical for normal cpp generated code + seqid = ++m_last_seqid; + } + + return _P::writeMessageBegin_virt(name, messageType, seqid); + } + + virtual uint32_t readMessageBegin_virt(std::string& name, + TMessageType& messageType, + int32_t& seqid) override + { + uint32_t result = _P::readMessageBegin_virt(name, messageType, seqid); + if (seqid != m_last_seqid) { + std::stringstream ss; + ss << "ERROR: send request with seqid " << m_last_seqid << " and got reply with seqid " << seqid; + throw std::logic_error(ss.str()); + } /* else { + std::cout << "verified seqid " << m_last_seqid << " round trip OK" << std::endl; + } */ + return result; + } + + private: + int32_t m_last_seqid; +}; + // Current time, microseconds since the epoch uint64_t now() { int64_t ret; @@ -299,19 +346,23 @@ int main(int argc, char** argv) { } if (protocol_type == "json" || protocol_type == "multij") { - protocol = std::make_shared(transport); + typedef TPedanticProtocol TPedanticJSONProtocol; + protocol = std::make_shared(transport); } else if (protocol_type == "compact" || protocol_type == "multic") { - protocol = std::make_shared(transport); + typedef TPedanticProtocol TPedanticCompactProtocol; + protocol = std::make_shared(transport); } else if (protocol_type == "header" || protocol_type == "multih") { - protocol = std::make_shared(transport); + typedef TPedanticProtocol TPedanticHeaderProtocol; + protocol = std::make_shared(transport); } else { - protocol = std::make_shared(transport); + typedef TPedanticProtocol TPedanticBinaryProtocol; + protocol = std::make_shared(transport); } if (boost::starts_with(protocol_type, "multi")) { - protocol2 = std::make_shared(protocol, "SecondService"); - // we don't need access to the original protocol any more, so... - protocol = std::make_shared(protocol, "ThriftTest"); + protocol2 = std::make_shared(protocol, "SecondService"); + // we don't need access to the original protocol any more, so... + protocol = std::make_shared(protocol, "ThriftTest"); } // Connection info From 43f689d153b07e2c513964f537204824042bf99f Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Wed, 30 Jan 2019 13:15:10 -0500 Subject: [PATCH 197/756] THRIFT-4405: fix c_glib seqid limited to min 0 instead of full int32_t range --- .../src/thrift/c_glib/protocol/thrift_stored_message_protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.c index a0d560bfcfd..22aca8a29f8 100644 --- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.c +++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_stored_message_protocol.c @@ -172,7 +172,7 @@ thrift_stored_message_protocol_class_init (ThriftStoredMessageProtocolClass *kla g_param_spec_int ("seqid", "Sequence id type in the wire", "Set the Sequence id in the wire", - 0, G_MAXINT, + G_MININT, G_MAXINT, 0, (G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE)); From 973c8552e0516cea35810d8870dbb33e4f05f9c5 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Wed, 30 Jan 2019 20:11:15 -0500 Subject: [PATCH 198/756] THRIFT-4405: fix parsing bug in cpp json header read if sequence ID wrapped around to negative --- lib/cpp/src/thrift/protocol/TJSONProtocol.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp index 53cc140b6e6..35592f006c6 100644 --- a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp @@ -948,7 +948,7 @@ uint32_t TJSONProtocol::readMessageBegin(std::string& name, TMessageType& messageType, int32_t& seqid) { uint32_t result = readJSONArrayStart(); - uint64_t tmpVal = 0; + int64_t tmpVal = 0; result += readJSONInteger(tmpVal); if (tmpVal != kThriftVersion1) { throw TProtocolException(TProtocolException::BAD_VERSION, "Message contained bad version."); @@ -957,8 +957,9 @@ uint32_t TJSONProtocol::readMessageBegin(std::string& name, result += readJSONInteger(tmpVal); messageType = (TMessageType)tmpVal; result += readJSONInteger(tmpVal); - if (tmpVal > static_cast((std::numeric_limits::max)())) - throw TProtocolException(TProtocolException::SIZE_LIMIT); + if (tmpVal > (std::numeric_limits::max)() || + tmpVal < (std::numeric_limits::min)()) + throw TProtocolException(TProtocolException::INVALID_DATA, "sequence id is not int32_t"); seqid = static_cast(tmpVal); return result; } From 84d9cd27f9a7a5062c9cc270583a001a7aaec196 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 31 Jan 2019 11:47:58 -0500 Subject: [PATCH 199/756] THRIFT-4405: Enhance python cross test client for pedantic sequence id handling --- test/py/TestClient.py | 77 +++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/test/py/TestClient.py b/test/py/TestClient.py index ddcce8db0a5..cc9185cfe7e 100755 --- a/test/py/TestClient.py +++ b/test/py/TestClient.py @@ -23,10 +23,15 @@ import sys import time import unittest -from optparse import OptionParser +from optparse import OptionParser from util import local_libpath +sys.path.insert(0, local_libpath()) + +from thrift.protocol import TProtocolDecorator +from thrift.protocol import TProtocol + SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) @@ -268,6 +273,43 @@ def testOnewayThenNormal(self): self.assertEqual(self.client.testString('Python'), 'Python') +# LAST_SEQID is a global because we have one transport and multiple protocols +# running on it (when multiplexec) +LAST_SEQID = None + +class TPedanticSequenceIdProtocolWrapper(TProtocolDecorator.TProtocolDecorator): + """ + Wraps any protocol with sequence ID checking: looks for outbound + uniqueness as well as request/response alignment. + """ + def __init__(self, protocol): + # TProtocolDecorator.__new__ does all the heavy lifting + pass + + def writeMessageBegin(self, name, type, seqid): + global LAST_SEQID + if LAST_SEQID and LAST_SEQID == seqid: + raise TProtocol.TProtocolException(INVALID_DATA, + "Python client reused sequence ID {0}".format(seqid)) + LAST_SEQID = seqid + super(TPedanticSequenceIdProtocolWrapper, self).writeMessageBegin( + name, type, seqid) + + def readMessageBegin(self): + global LAST_SEQID + (name, type, seqid) =\ + super(TPedanticSequenceIdProtocolWrapper, self).readMessageBegin() + if LAST_SEQID != seqid: + raise TProtocol.TProtocolException(INVALID_DATA, + "We sent seqid {0} and server returned seqid {1}".format( + self.last, seqid)) + return (name, type, seqid) + + +def make_pedantic(proto): + """ Wrap a protocol in the pedantic sequence ID wrapper. """ + return TPedanticSequenceIdProtocolWrapper(proto) + class MultiplexedOptionalTest(AbstractTest): def get_protocol2(self, transport): return None @@ -275,83 +317,83 @@ def get_protocol2(self, transport): class BinaryTest(MultiplexedOptionalTest): def get_protocol(self, transport): - return TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport) + return make_pedantic(TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)) class MultiplexedBinaryTest(MultiplexedOptionalTest): def get_protocol(self, transport): - wrapped_proto = TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport) + wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") def get_protocol2(self, transport): - wrapped_proto = TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport) + wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") class AcceleratedBinaryTest(MultiplexedOptionalTest): def get_protocol(self, transport): - return TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport) + return make_pedantic(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) class MultiplexedAcceleratedBinaryTest(MultiplexedOptionalTest): def get_protocol(self, transport): - wrapped_proto = TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport) + wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") def get_protocol2(self, transport): - wrapped_proto = TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport) + wrapped_proto = make_pedantic(TBinaryProtocol.TBinaryProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") class CompactTest(MultiplexedOptionalTest): def get_protocol(self, transport): - return TCompactProtocol.TCompactProtocolFactory().getProtocol(transport) + return make_pedantic(TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)) class MultiplexedCompactTest(MultiplexedOptionalTest): def get_protocol(self, transport): - wrapped_proto = TCompactProtocol.TCompactProtocolFactory().getProtocol(transport) + wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") def get_protocol2(self, transport): - wrapped_proto = TCompactProtocol.TCompactProtocolFactory().getProtocol(transport) + wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") class AcceleratedCompactTest(MultiplexedOptionalTest): def get_protocol(self, transport): - return TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport) + return make_pedantic(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) class MultiplexedAcceleratedCompactTest(MultiplexedOptionalTest): def get_protocol(self, transport): - wrapped_proto = TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport) + wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") def get_protocol2(self, transport): - wrapped_proto = TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport) + wrapped_proto = make_pedantic(TCompactProtocol.TCompactProtocolAcceleratedFactory(fallback=False).getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") class JSONTest(MultiplexedOptionalTest): def get_protocol(self, transport): - return TJSONProtocol.TJSONProtocolFactory().getProtocol(transport) + return make_pedantic(TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)) class MultiplexedJSONTest(MultiplexedOptionalTest): def get_protocol(self, transport): - wrapped_proto = TJSONProtocol.TJSONProtocolFactory().getProtocol(transport) + wrapped_proto = make_pedantic(TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") def get_protocol2(self, transport): - wrapped_proto = TJSONProtocol.TJSONProtocolFactory().getProtocol(transport) + wrapped_proto = make_pedantic(TJSONProtocol.TJSONProtocolFactory().getProtocol(transport)) return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") class HeaderTest(MultiplexedOptionalTest): def get_protocol(self, transport): factory = THeaderProtocol.THeaderProtocolFactory() - return factory.getProtocol(transport) + return make_pedantic(factory.getProtocol(transport)) def suite(): @@ -424,7 +466,6 @@ def parseArgs(self, argv): if options.genpydir: sys.path.insert(0, os.path.join(SCRIPT_DIR, options.genpydir)) - sys.path.insert(0, local_libpath()) if options.http_path: options.trans = 'http' From f15b4152b9ea8e73a24e37e3f54a999060ea68bf Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 31 Jan 2019 13:01:56 -0500 Subject: [PATCH 200/756] THRIFT-4405: fix negative sequence id handling in python TCompactProtocol --- lib/py/src/protocol/TCompactProtocol.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/py/src/protocol/TCompactProtocol.py b/lib/py/src/protocol/TCompactProtocol.py index e485cffb145..da50513142e 100644 --- a/lib/py/src/protocol/TCompactProtocol.py +++ b/lib/py/src/protocol/TCompactProtocol.py @@ -58,6 +58,7 @@ def fromZigZag(n): def writeVarint(trans, n): + assert n >= 0, "Input to TCompactProtocol writeVarint cannot be negative!" out = bytearray() while True: if n & ~0x7f == 0: @@ -156,7 +157,14 @@ def writeMessageBegin(self, name, type, seqid): assert self.state == CLEAR self.__writeUByte(self.PROTOCOL_ID) self.__writeUByte(self.VERSION | (type << self.TYPE_SHIFT_AMOUNT)) - self.__writeVarint(seqid) + # The sequence id is a signed 32-bit integer but the compact protocol + # writes this out as a "var int" which is always positive, and attempting + # to write a negative number results in an infinite loop, so we may + # need to do some conversion here... + tseqid = seqid; + if tseqid < 0: + tseqid = 2147483648 + (2147483648 + tseqid) + self.__writeVarint(tseqid) self.__writeBinary(str_to_binary(name)) self.state = VALUE_WRITE @@ -334,6 +342,10 @@ def readMessageBegin(self): raise TProtocolException(TProtocolException.BAD_VERSION, 'Bad version: %d (expect %d)' % (version, self.VERSION)) seqid = self.__readVarint() + # the sequence is a compact "var int" which is treaded as unsigned, + # however the sequence is actually signed... + if seqid > 2147483647: + seqid = -2147483648 - (2147483648 - seqid) name = binary_to_str(self.__readBinary()) return (name, type, seqid) From 2be45e566dd490aabf7a45ec3474545a0817024e Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 31 Jan 2019 13:17:46 -0500 Subject: [PATCH 201/756] THRIFT-4405: add documentation on sequence number rules --- doc/specs/SequenceNumbers.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 doc/specs/SequenceNumbers.md diff --git a/doc/specs/SequenceNumbers.md b/doc/specs/SequenceNumbers.md new file mode 100644 index 00000000000..fef3fcff198 --- /dev/null +++ b/doc/specs/SequenceNumbers.md @@ -0,0 +1,23 @@ +# Sequence Number # + +Apache Thrift built sequence numbers into every protocol exchange to allow +for clients that may submit multiple outstanding requests on a single transport +connection. This is typically done by asynchronous clients. + +The following rules apply to sequence numbers: + +1. A sequence number is a signed 32-bit integer. Negative values are allowed. +1. Sequence numbers `MUST` be unique across all outstanding requests on a + given transport connection. There is no requirement for unique numbers + between different transport connections even if they are from the same client. +1. A server `MUST` reply to a client with the same sequence number that was + used in the request. This includes any exception-based reply. +1. A client `MAY` use sequence numbers if it needs them for proper operation. +1. A client `SHOULD` set the sequence number to zero if it does not rely + on them. +1. Wrapped protocols (such as THeaderProtocol) `SHOULD` use the same sequence + number on the wrapping as is used on the payload protocol. + +Servers will not inspect or make any logic choices based on the sequence number +sent by the client. The server's only job is to process the request and reply +with the same sequence number. From 53bd0e6295547e76ab00913cfd62f8d040bd996c Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 31 Jan 2019 17:11:04 -0500 Subject: [PATCH 202/756] THRIFT-4745: fixes compiler warnings --- compiler/cpp/src/thrift/generate/t_js_generator.cc | 4 ++-- lib/py/src/ext/endian.h | 4 ++++ lib/py/src/protocol/TCompactProtocol.py | 2 +- test/cpp/src/TestClient.cpp | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc index d30ce41537c..e7f625c8588 100644 --- a/compiler/cpp/src/thrift/generate/t_js_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc @@ -42,9 +42,9 @@ using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes // largest consecutive integer representable by a double (2 ^ 53 - 1) -static const long max_safe_integer = 0x1fffffffffffff; +static const int64_t max_safe_integer = 0x1fffffffffffff; // smallest consecutive number representable by a double (-2 ^ 53 + 1) -static const long min_safe_integer = -max_safe_integer; +static const int64_t min_safe_integer = -max_safe_integer; #include "thrift/generate/t_oop_generator.h" diff --git a/lib/py/src/ext/endian.h b/lib/py/src/ext/endian.h index 91372a7b6b7..1660cbd98e0 100644 --- a/lib/py/src/ext/endian.h +++ b/lib/py/src/ext/endian.h @@ -79,6 +79,10 @@ #include #define ntohll(n) bswap_64(n) #define htonll(n) bswap_64(n) +#elif defined(_MSC_VER) +#include +#define ntohll(n) _byteswap_uint64(n) +#define htonll(n) _byteswap_uint64(n) #else /* GNUC & GLIBC */ #define ntohll(n) ((((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32)) #define htonll(n) ((((unsigned long long)htonl(n)) << 32) + htonl(n >> 32)) diff --git a/lib/py/src/protocol/TCompactProtocol.py b/lib/py/src/protocol/TCompactProtocol.py index da50513142e..baaec65b27d 100644 --- a/lib/py/src/protocol/TCompactProtocol.py +++ b/lib/py/src/protocol/TCompactProtocol.py @@ -161,7 +161,7 @@ def writeMessageBegin(self, name, type, seqid): # writes this out as a "var int" which is always positive, and attempting # to write a negative number results in an infinite loop, so we may # need to do some conversion here... - tseqid = seqid; + tseqid = seqid if tseqid < 0: tseqid = 2147483648 + (2147483648 + tseqid) self.__writeVarint(tseqid) diff --git a/test/cpp/src/TestClient.cpp b/test/cpp/src/TestClient.cpp index f7c491239ff..33ba2034330 100644 --- a/test/cpp/src/TestClient.cpp +++ b/test/cpp/src/TestClient.cpp @@ -74,7 +74,7 @@ class TPedanticProtocol : public _P { public: TPedanticProtocol(std::shared_ptr& transport) - : _P(transport), m_last_seqid(std::numeric_limits::max() - 10) { } + : _P(transport), m_last_seqid((std::numeric_limits::max)() - 10) { } virtual uint32_t writeMessageBegin_virt(const std::string& name, const TMessageType messageType, From 3ec4031a4c6d685bcc02fa10dd13b2df58732b82 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 31 Jan 2019 18:35:51 -0500 Subject: [PATCH 203/756] THRIFT-4405: fix cygwin on appveyor --- .flake8 | 5 +++++ build/appveyor/CYGW-appveyor-install.bat | 6 ++++++ build/docker/scripts/sca.sh | 10 +--------- lib/nodejs/examples/httpServer.py | 8 +++++--- test/cpp/src/TestClient.cpp | 10 +++++----- test/crossrunner/run.py | 2 +- test/py/TestClient.py | 10 ++++++---- tutorial/php/runserver.py | 1 + tutorial/py.twisted/PythonClient.py | 1 + tutorial/py.twisted/PythonServer.py | 1 + 10 files changed, 32 insertions(+), 22 deletions(-) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 00000000000..df8fdb261fd --- /dev/null +++ b/.flake8 @@ -0,0 +1,5 @@ +[flake8] +exclude = .git,__pycache__,**/gen-*/**,contrib/**,docs/source/conf.py,old,build,dist +ignore = W504,E402,E501 +max-complexity = 30 +max-line-length = 120 diff --git a/build/appveyor/CYGW-appveyor-install.bat b/build/appveyor/CYGW-appveyor-install.bat index 79b6ef06bc0..72712b20e01 100644 --- a/build/appveyor/CYGW-appveyor-install.bat +++ b/build/appveyor/CYGW-appveyor-install.bat @@ -25,6 +25,12 @@ CALL cl_banner_install.bat || EXIT /B CALL cl_setenv.bat || EXIT /B CALL cl_showenv.bat || EXIT /B +:: +:: Upgrades cygwin to the latest, if you want... +:: +:: appveyor DownloadFile "https://cygwin.com/setup-x86_64.exe" +:: setup-x86_64.exe --quiet-mode --wait --upgrade-also --packages="gcc-g++" + :: :: Install apt-cyg for package management :: diff --git a/build/docker/scripts/sca.sh b/build/docker/scripts/sca.sh index 16d5826198d..42128fc671e 100755 --- a/build/docker/scripts/sca.sh +++ b/build/docker/scripts/sca.sh @@ -39,15 +39,7 @@ cppcheck --force --quiet --inline-suppr --error-exitcode=1 -j2 lib/cpp/src lib/c cppcheck --force --quiet --inline-suppr --error-exitcode=1 -j2 lib/c_glib/src lib/c_glib/test test/c_glib/src tutorial/c_glib # Python code style -flake8 --ignore=W504,E501 lib/py -flake8 --exclude=tutorial/py/build tutorial/py -# THRIFT-4371 : generated files are excluded because they haven't been scrubbed yet -flake8 --ignore=E501 --exclude="*/gen-py*/*",test/py/build test/py -flake8 test/py.twisted -flake8 test/py.tornado -flake8 --ignore=E501 test/test.py -flake8 --ignore=E501,E722 test/crossrunner -flake8 test/features +flake8 # PHP code style composer install --quiet diff --git a/lib/nodejs/examples/httpServer.py b/lib/nodejs/examples/httpServer.py index b712fcd7f95..76e9f4aa3c8 100644 --- a/lib/nodejs/examples/httpServer.py +++ b/lib/nodejs/examples/httpServer.py @@ -5,10 +5,12 @@ from thrift.protocol import TJSONProtocol from thrift.server import THttpServer + class HelloSvcHandler: - def hello_func(self): - print("Hello Called") - return "hello from Python" + def hello_func(self): + print("Hello Called") + return "hello from Python" + processor = HelloSvc.Processor(HelloSvcHandler()) protoFactory = TJSONProtocol.TJSONProtocolFactory() diff --git a/test/cpp/src/TestClient.cpp b/test/cpp/src/TestClient.cpp index 33ba2034330..c4146cc5cf5 100644 --- a/test/cpp/src/TestClient.cpp +++ b/test/cpp/src/TestClient.cpp @@ -69,12 +69,12 @@ using namespace thrift::test; // agreement between client and server. // -template -class TPedanticProtocol : public _P +template +class TPedanticProtocol : public Proto { public: TPedanticProtocol(std::shared_ptr& transport) - : _P(transport), m_last_seqid((std::numeric_limits::max)() - 10) { } + : Proto(transport), m_last_seqid((std::numeric_limits::max)() - 10) { } virtual uint32_t writeMessageBegin_virt(const std::string& name, const TMessageType messageType, @@ -85,14 +85,14 @@ class TPedanticProtocol : public _P seqid = ++m_last_seqid; } - return _P::writeMessageBegin_virt(name, messageType, seqid); + return Proto::writeMessageBegin_virt(name, messageType, seqid); } virtual uint32_t readMessageBegin_virt(std::string& name, TMessageType& messageType, int32_t& seqid) override { - uint32_t result = _P::readMessageBegin_virt(name, messageType, seqid); + uint32_t result = Proto::readMessageBegin_virt(name, messageType, seqid); if (seqid != m_last_seqid) { std::stringstream ss; ss << "ERROR: send request with seqid " << m_last_seqid << " and got reply with seqid " << seqid; diff --git a/test/crossrunner/run.py b/test/crossrunner/run.py index ef8fb60f3ca..bb06d25efc5 100644 --- a/test/crossrunner/run.py +++ b/test/crossrunner/run.py @@ -259,7 +259,7 @@ def ensure_socket_open(sv, port, test): raise logger.warn('Error executing [%s]', test.name, exc_info=True) return (retry_count, RESULT_ERROR) - except: + except Exception: logger.info('Interrupted execution', exc_info=True) if not async_mode: raise diff --git a/test/py/TestClient.py b/test/py/TestClient.py index cc9185cfe7e..a85098eb4d2 100755 --- a/test/py/TestClient.py +++ b/test/py/TestClient.py @@ -26,9 +26,7 @@ from optparse import OptionParser from util import local_libpath - sys.path.insert(0, local_libpath()) - from thrift.protocol import TProtocolDecorator from thrift.protocol import TProtocol @@ -277,6 +275,7 @@ def testOnewayThenNormal(self): # running on it (when multiplexec) LAST_SEQID = None + class TPedanticSequenceIdProtocolWrapper(TProtocolDecorator.TProtocolDecorator): """ Wraps any protocol with sequence ID checking: looks for outbound @@ -289,7 +288,8 @@ def __init__(self, protocol): def writeMessageBegin(self, name, type, seqid): global LAST_SEQID if LAST_SEQID and LAST_SEQID == seqid: - raise TProtocol.TProtocolException(INVALID_DATA, + raise TProtocol.TProtocolException( + TProtocol.TProtocolException.INVALID_DATA, "Python client reused sequence ID {0}".format(seqid)) LAST_SEQID = seqid super(TPedanticSequenceIdProtocolWrapper, self).writeMessageBegin( @@ -300,7 +300,8 @@ def readMessageBegin(self): (name, type, seqid) =\ super(TPedanticSequenceIdProtocolWrapper, self).readMessageBegin() if LAST_SEQID != seqid: - raise TProtocol.TProtocolException(INVALID_DATA, + raise TProtocol.TProtocolException( + TProtocol.TProtocolException.INVALID_DATA, "We sent seqid {0} and server returned seqid {1}".format( self.last, seqid)) return (name, type, seqid) @@ -310,6 +311,7 @@ def make_pedantic(proto): """ Wrap a protocol in the pedantic sequence ID wrapper. """ return TPedanticSequenceIdProtocolWrapper(proto) + class MultiplexedOptionalTest(AbstractTest): def get_protocol2(self, transport): return None diff --git a/tutorial/php/runserver.py b/tutorial/php/runserver.py index 077daa102ac..8cc30fbe5ce 100755 --- a/tutorial/php/runserver.py +++ b/tutorial/php/runserver.py @@ -30,4 +30,5 @@ class Handler(CGIHTTPServer.CGIHTTPRequestHandler): cgi_directories = ['/php'] + BaseHTTPServer.HTTPServer(('', 8080), Handler).serve_forever() diff --git a/tutorial/py.twisted/PythonClient.py b/tutorial/py.twisted/PythonClient.py index 63dde7e7a89..2976495e314 100755 --- a/tutorial/py.twisted/PythonClient.py +++ b/tutorial/py.twisted/PythonClient.py @@ -67,6 +67,7 @@ def main(client): print(('Check log: %s' % (log.value))) reactor.stop() + if __name__ == '__main__': d = ClientCreator(reactor, TTwisted.ThriftClientProtocol, diff --git a/tutorial/py.twisted/PythonServer.py b/tutorial/py.twisted/PythonServer.py index 1b0e2d5b968..034e4a3129d 100755 --- a/tutorial/py.twisted/PythonServer.py +++ b/tutorial/py.twisted/PythonServer.py @@ -85,6 +85,7 @@ def getStruct(self, key): def zip(self): print('zip()') + if __name__ == '__main__': handler = CalculatorHandler() processor = Calculator.Processor(handler) From 1686c87024766015d510fc007aeef548a9c1a2a0 Mon Sep 17 00:00:00 2001 From: Fokko Driesprong Date: Fri, 1 Feb 2019 20:31:58 +0100 Subject: [PATCH 204/756] THRIFT-4766: Fix JDK11 build (#1723) * [THRIFT-4766] Enable JDK9 build * THRIFT-4766: build on bionic using native jdk (java-11-openjdk) Change from headless to the normal JDK. Maybe the libasound is pulled in transitively. --- build/docker/ubuntu-bionic/Dockerfile | 8 +++++--- debian/control | 2 +- lib/java/gradle.properties | 1 + lib/java/gradle/environment.gradle | 2 ++ 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index a75af31c3e9..356619910c3 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -68,6 +68,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ debhelper \ flex \ gdb \ + libasound2 \ + libatk-bridge2.0-0 \ + libgtk-3-0 \ llvm \ ninja-build \ pkg-config \ @@ -174,9 +177,8 @@ RUN apt-get install -y --no-install-recommends \ `# Java dependencies` \ ant \ ant-optional \ - openjdk-8-jdk \ - maven && \ - update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java + maven \ + openjdk-11-jdk-headless RUN apt-get install -y --no-install-recommends \ `# Lua dependencies` \ diff --git a/debian/control b/debian/control index 9818a37a23a..9de66fc272a 100644 --- a/debian/control +++ b/debian/control @@ -6,7 +6,7 @@ Build-Depends: debhelper (>= 9), build-essential, mono-mcs, python-dev, ant, pkg-config, libtool, bison, flex, libboost-dev | libboost1.53-dev | libboost1.63-all-dev, python-all, python-setuptools, python-all-dev, python-all-dbg, python3-all, python3-setuptools, python3-all-dev, python3-all-dbg, - openjdk-7-jdk | openjdk-8-jdk | default-jdk, + openjdk-8-jdk | openjdk-8-jdk-headless | openjdk-11-jdk | openjdk-11-jdk-headless | default-jdk, libboost-test-dev | libboost-test1.53-dev | libboost-test1.63-dev, libevent-dev, libssl-dev, perl (>= 5.8.0-7), php (>= 5), php-dev (>= 5), libglib2.0-dev, qtchooser, qtbase5-dev-tools Maintainer: Thrift Developer's diff --git a/lib/java/gradle.properties b/lib/java/gradle.properties index a964675a34d..0811659106a 100644 --- a/lib/java/gradle.properties +++ b/lib/java/gradle.properties @@ -31,3 +31,4 @@ slf4j.version=1.7.25 servlet.version=2.5 junit.version=4.12 mockito.version=1.9.5 +javax.annotation.version=1.3.2 diff --git a/lib/java/gradle/environment.gradle b/lib/java/gradle/environment.gradle index 9b7eb1ed625..45fa63a1754 100644 --- a/lib/java/gradle/environment.gradle +++ b/lib/java/gradle/environment.gradle @@ -48,6 +48,7 @@ ext.servletVersion = property('servlet.version') ext.slf4jVersion = property('slf4j.version') ext.junitVersion = property('junit.version') ext.mockitoVersion = property('mockito.version') +ext.javaxAnnotationVersion = property('javax.annotation.version') // In this section you declare where to find the dependencies of your project repositories { @@ -66,6 +67,7 @@ dependencies { compile "org.apache.httpcomponents:httpclient:${httpclientVersion}" compile "org.apache.httpcomponents:httpcore:${httpcoreVersion}" compile "javax.servlet:servlet-api:${servletVersion}" + compile "javax.annotation:javax.annotation-api:${javaxAnnotationVersion}" testCompile "junit:junit:${junitVersion}" testCompile "org.mockito:mockito-all:${mockitoVersion}" From ef9405f9302831c0c7a23988aae1643747943c50 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 1 Feb 2019 16:14:19 -0500 Subject: [PATCH 205/756] fix java-ruby test timeouts in ci --- test/tests.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/tests.json b/test/tests.json index a022951ba9c..043b8265017 100644 --- a/test/tests.json +++ b/test/tests.json @@ -385,7 +385,7 @@ ] }, "client": { - "timeout": 5, + "timeout": 10, "command": [ "ruby", "../integration/TestClient.rb", From d77e0977260fa8d82d56836ed07cdca0f23cadcb Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 1 Feb 2019 19:17:59 -0500 Subject: [PATCH 206/756] fix minor glib warning --- lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c index 6dd0f0d3a11..560c24e28ab 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c @@ -163,7 +163,7 @@ thrift_socket_open (ThriftTransport *transport, GError **error) /* open a connection */ if (connect (tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) { - thrift_socket_close(tsocket, NULL); + thrift_socket_close(transport, NULL); g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_CONNECT, "failed to connect to host %s:%d - %s", tsocket->hostname, tsocket->port, strerror(errno)); From 4c57be0b609924f6516dd293985fc6d76f738c16 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sun, 27 Jan 2019 11:12:43 -0500 Subject: [PATCH 207/756] THRIFT-4384: fix concurrent sync in cpp async client code --- build/cmake/DefineOptions.cmake | 32 ++++++++----- .../src/thrift/generate/t_cpp_generator.cc | 48 ++++++++++++++----- test/cpp/CMakeLists.txt | 1 + test/cpp/src/StressTest.cpp | 9 ++-- 4 files changed, 60 insertions(+), 30 deletions(-) diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index eea0b2915e1..778be8dffa2 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -146,24 +146,34 @@ macro(PRINT_CONFIG_SUMMARY) message(STATUS "----------------------------------------------------------") message(STATUS "Thrift version: ${thrift_VERSION} (${thrift_VERSION_MAJOR}.${thrift_VERSION_MINOR}.${thrift_VERSION_PATCH})") message(STATUS "Thrift package version: ${PACKAGE_VERSION}") -message(STATUS "Build configuration Summary") +message(STATUS) +message(STATUS "Build configuration summary") message(STATUS " Build compiler: ${BUILD_COMPILER}") message(STATUS " Build libraries: ${BUILD_LIBRARIES}") message(STATUS " Build tests: ${BUILD_TESTING}") MESSAGE_DEP(HAVE_COMPILER "Disabled because BUILD_THRIFT=OFF and no valid THRIFT_COMPILER is given") -if (UNIX) - message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") -endif () -message(STATUS " Language libraries:") +message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") +message(STATUS) +message(STATUS "Language libraries:") +message(STATUS) message(STATUS " Build as3 library: ${BUILD_AS3}") MESSAGE_DEP(WITH_AS3 "Disabled by WITH_AS3=OFF") MESSAGE_DEP(HAVE_COMPC "Adobe Flex compc was not found - did you set env var FLEX_HOME?") +message(STATUS) message(STATUS " Build C++ library: ${BUILD_CPP}") MESSAGE_DEP(WITH_CPP "Disabled by WITH_CPP=OFF") -message(STATUS " C++ Language Level: ${CXX_LANGUAGE_LEVEL}") +if (BUILD_CPP) + message(STATUS " C++ Language Level: ${CXX_LANGUAGE_LEVEL}") + message(STATUS " Build shared libraries: ${BUILD_SHARED_LIBS}") + message(STATUS " Build with libevent support: ${WITH_LIBEVENT}") + message(STATUS " Build with Qt5 support: ${WITH_QT5}") + message(STATUS " Build with ZLIB support: ${WITH_ZLIB}") +endif () +message(STATUS) message(STATUS " Build C (GLib) library: ${BUILD_C_GLIB}") MESSAGE_DEP(WITH_C_GLIB "Disabled by WITH_C_GLIB=OFF") MESSAGE_DEP(GLIB_FOUND "GLib missing") +message(STATUS) message(STATUS " Build Java library: ${BUILD_JAVA}") MESSAGE_DEP(WITH_JAVA "Disabled by WITH_JAVA=OFF") if(ANDROID) @@ -172,19 +182,15 @@ else() MESSAGE_DEP(JAVA_FOUND "Java Runtime missing") MESSAGE_DEP(GRADLEW_FOUND "Gradle Wrapper missing") endif() +message(STATUS) message(STATUS " Build Python library: ${BUILD_PYTHON}") MESSAGE_DEP(WITH_PYTHON "Disabled by WITH_PYTHON=OFF") MESSAGE_DEP(PYTHONLIBS_FOUND "Python libraries missing") +message(STATUS) message(STATUS " Build Haskell library: ${BUILD_HASKELL}") MESSAGE_DEP(WITH_HASKELL "Disabled by WITH_HASKELL=OFF") MESSAGE_DEP(GHC_FOUND "GHC missing") MESSAGE_DEP(CABAL_FOUND "Cabal missing") -if (BUILD_CPP) - message(STATUS " Library features:") - message(STATUS " Build shared libraries: ${BUILD_SHARED_LIBS}") - message(STATUS " Build with libevent support: ${WITH_LIBEVENT}") - message(STATUS " Build with Qt5 support: ${WITH_QT5}") - message(STATUS " Build with ZLIB support: ${WITH_ZLIB}") -endif () +message(STATUS) message(STATUS "----------------------------------------------------------") endmacro(PRINT_CONFIG_SUMMARY) diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc index cf3036390ff..617ba7ec864 100644 --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc @@ -1720,7 +1720,6 @@ void t_cpp_generator::generate_service(t_service* tservice) { if (gen_cob_style_) { f_header_ << "#include " << endl // TMemoryBuffer << "#include " << endl - << "#include " << endl << "namespace apache { namespace thrift { namespace async {" << endl << "class TAsyncChannel;" << endl << "}}}" << endl; } @@ -1729,6 +1728,7 @@ void t_cpp_generator::generate_service(t_service* tservice) { f_header_ << "#include " << endl; } f_header_ << "#include " << endl; + f_header_ << "#include " << endl; f_header_ << "#include \"" << get_include_prefix(*get_program()) << program_name_ << "_types.h\"" << endl; @@ -2284,27 +2284,49 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) indent_up(); if (style != "Cob") { f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr - << " prot) "; + << " prot"; + if (style == "Concurrent") { + f_header_ << ", std::shared_ptr<::apache::thrift::async::TConcurrentClientSyncInfo> sync"; + } + f_header_ << ") "; if (extends.empty()) { + if (style == "Concurrent") { + f_header_ << ": sync_(sync)" << endl; + } f_header_ << "{" << endl; f_header_ << indent() << " setProtocol" << short_suffix << "(prot);" << endl << indent() << "}" << endl; } else { f_header_ << ":" << endl; - f_header_ << indent() << " " << extends << style << client_suffix << "(prot, prot) {}" - << endl; + f_header_ << indent() << " " << extends << style << client_suffix << "(prot, prot"; + if (style == "Concurrent") { + f_header_ << ", sync"; + } + f_header_ << ") {}" << endl; } f_header_ << indent() << service_name_ << style << "Client" << short_suffix << "(" << prot_ptr - << " iprot, " << prot_ptr << " oprot) "; + << " iprot, " << prot_ptr << " oprot"; + if (style == "Concurrent") { + f_header_ << ", std::shared_ptr<::apache::thrift::async::TConcurrentClientSyncInfo> sync"; + } + f_header_ << ") "; + if (extends.empty()) { + if (style == "Concurrent") { + f_header_ << ": sync_(sync)" << endl; + } f_header_ << "{" << endl; f_header_ << indent() << " setProtocol" << short_suffix << "(iprot,oprot);" << endl << indent() << "}" << endl; } else { f_header_ << ":" << indent() << " " << extends << style << client_suffix - << "(iprot, oprot) {}" << endl; + << "(iprot, oprot"; + if (style == "Concurrent") { + f_header_ << ", sync"; + } + f_header_ << ") {}" << endl; } // create the setProtocol methods @@ -2443,7 +2465,7 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) if (style == "Concurrent") { f_header_ << - indent() << "::apache::thrift::async::TConcurrentClientSyncInfo sync_;"< sync_;"<is_oneway()) { - cseqidVal = "this->sync_.generateSeqId()"; + cseqidVal = "this->sync_->generateSeqId()"; } } // Serialize the request @@ -2557,7 +2579,7 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) indent() << "int32_t cseqid = " << cseqidVal << ";" << endl; if(style == "Concurrent") { out << - indent() << "::apache::thrift::async::TConcurrentSendSentry sentry(&this->sync_);" << endl; + indent() << "::apache::thrift::async::TConcurrentSendSentry sentry(this->sync_.get());" << endl; } if (style == "Cob") { out << @@ -2622,7 +2644,7 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) endl << indent() << "// the read mutex gets dropped and reacquired as part of waitForWork()" << endl << indent() << "// The destructor of this sentry wakes up other clients" << endl << - indent() << "::apache::thrift::async::TConcurrentRecvSentry sentry(&this->sync_, seqid);" << endl; + indent() << "::apache::thrift::async::TConcurrentRecvSentry sentry(this->sync_.get(), seqid);" << endl; } if (style == "Cob" && !gen_no_client_completion_) { out << indent() << "bool completed = false;" << endl << endl << indent() << "try {"; @@ -2632,7 +2654,7 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) if (style == "Concurrent") { out << indent() << "while(true) {" << endl << - indent() << " if(!this->sync_.getPending(fname, mtype, rseqid)) {" << endl; + indent() << " if(!this->sync_->getPending(fname, mtype, rseqid)) {" << endl; indent_up(); indent_up(); } @@ -2776,10 +2798,10 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) out << indent() << " }" << endl << indent() << " // seqid != rseqid" << endl << - indent() << " this->sync_.updatePending(fname, mtype, rseqid);" << endl << + indent() << " this->sync_->updatePending(fname, mtype, rseqid);" << endl << endl << indent() << " // this will temporarily unlock the readMutex, and let other clients get work done" << endl << - indent() << " this->sync_.waitForWork(seqid);" << endl << + indent() << " this->sync_->waitForWork(seqid);" << endl << indent() << "} // end while(true)" << endl; } if (style == "Cob" && !gen_no_client_completion_) { diff --git a/test/cpp/CMakeLists.txt b/test/cpp/CMakeLists.txt index 0c0bd2f5758..90af7826c10 100755 --- a/test/cpp/CMakeLists.txt +++ b/test/cpp/CMakeLists.txt @@ -75,6 +75,7 @@ target_link_libraries(StressTest crossstressgencpp ${Boost_LIBRARIES} ${LIBEVENT LINK_AGAINST_THRIFT_LIBRARY(StressTest thrift) LINK_AGAINST_THRIFT_LIBRARY(StressTest thriftnb) add_test(NAME StressTest COMMAND StressTest) +add_test(NAME StressTestConcurrent COMMAND StressTest --client-type=concurrent) add_executable(StressTestNonBlocking src/StressTestNonBlocking.cpp) target_link_libraries(StressTestNonBlocking crossstressgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB}) diff --git a/test/cpp/src/StressTest.cpp b/test/cpp/src/StressTest.cpp index 16831252f18..79a708e8f57 100644 --- a/test/cpp/src/StressTest.cpp +++ b/test/cpp/src/StressTest.cpp @@ -44,6 +44,7 @@ using namespace std; using namespace apache::thrift; +using namespace apache::thrift::async; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using namespace apache::thrift::server; @@ -264,8 +265,8 @@ int main(int argc, char** argv) { string clientType = "regular"; string serverType = "thread-pool"; string protocolType = "binary"; - size_t workerCount = 4; - size_t clientCount = 20; + size_t workerCount = 8; + size_t clientCount = 4; size_t loopCount = 50000; TType loopType = T_VOID; string callName = "echoVoid"; @@ -515,8 +516,8 @@ int main(int argc, char** argv) { std::shared_ptr socket(new TSocket("127.0.0.1", port)); std::shared_ptr bufferedSocket(new TBufferedTransport(socket, 2048)); std::shared_ptr protocol(new TBinaryProtocol(bufferedSocket)); - //std::shared_ptr serviceClient(new ServiceClient(protocol)); - std::shared_ptr serviceClient(new ServiceConcurrentClient(protocol)); + auto sync = std::make_shared(); + std::shared_ptr serviceClient(new ServiceConcurrentClient(protocol, sync)); socket->open(); for (size_t ix = 0; ix < clientCount; ix++) { clientThreads.insert(threadFactory->newThread(std::shared_ptr( From 71afec0ea3fc700d5f0d1c46512723963bf1e2f7 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 2 Feb 2019 11:22:26 -0500 Subject: [PATCH 208/756] THRIFT-4739: fix concurrency_test (test-only fix) --- appveyor.yml | 8 ++++---- lib/cpp/test/concurrency/TimerManagerTests.h | 21 +++++++++++++++----- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 2dee45fa882..39aba4f95b9 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -45,7 +45,7 @@ environment: PYTHON_VERSION: 3.6 QT_VERSION: 5.10 ZLIB_VERSION: 1.2.11 - DISABLED_TESTS: (concurrency_test|StressTestNonBlocking) + DISABLED_TESTS: (StressTestNonBlocking) - PROFILE: MSVC2015 PLATFORM: x86 @@ -56,18 +56,18 @@ environment: PYTHON_VERSION: 3.5 QT_VERSION: 5.8 ZLIB_VERSION: 1.2.8 - DISABLED_TESTS: (concurrency_test|StressTestNonBlocking) + DISABLED_TESTS: (StressTestNonBlocking) APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - PROFILE: MINGW PLATFORM: x64 CONFIGURATION: RelWithDebInfo - DISABLED_TESTS: (concurrency_test|StressTestNonBlocking) + DISABLED_TESTS: (StressTestNonBlocking) - PROFILE: CYGWIN PLATFORM: x64 CONFIGURATION: RelWithDebInfo - DISABLED_TESTS: (concurrency_test|ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest|StressTestNonBlocking) + DISABLED_TESTS: (ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest|StressTestNonBlocking) install: - cd %APPVEYOR_BUILD_FOLDER% diff --git a/lib/cpp/test/concurrency/TimerManagerTests.h b/lib/cpp/test/concurrency/TimerManagerTests.h index 313572aff77..2d1a2620ab5 100644 --- a/lib/cpp/test/concurrency/TimerManagerTests.h +++ b/lib/cpp/test/concurrency/TimerManagerTests.h @@ -22,6 +22,8 @@ #include #include +#include +#include #include namespace apache { @@ -223,7 +225,7 @@ class TimerManagerTests { } /** - * This test creates one tasks, and tries to remove it after it has expired. + * This test creates one task, and tries to remove it after it has expired. */ bool test04(uint64_t timeout = 1000LL) { TimerManager timerManager; @@ -237,15 +239,24 @@ class TimerManagerTests { shared_ptr task = shared_ptr(new TimerManagerTests::Task(_monitor, timeout / 10)); TimerManager::Timer timer = timerManager.add(task, task->_timeout); + task.reset(); // Wait until the task has completed _monitor.wait(timeout); // Verify behavior when removing the expired task - try { - timerManager.remove(timer); - assert(nullptr == "ERROR: This remove should send a NoSuchTaskException exception."); - } catch (NoSuchTaskException&) { + // notify is called inside the task so the task may still + // be running when we get here, so we need to loop... + for (;;) { + try { + timerManager.remove(timer); + assert(nullptr == "ERROR: This remove should throw NoSuchTaskException, or UncancellableTaskException."); + } catch (const NoSuchTaskException&) { + break; + } catch (const UncancellableTaskException&) { + // the thread was still exiting; try again... + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } } return true; From 8fdb7587e688ae66a0e30e9f22bf8dc09599b2e9 Mon Sep 17 00:00:00 2001 From: cyy Date: Tue, 5 Feb 2019 02:57:21 +0800 Subject: [PATCH 209/756] THRIFT-4759:add thrift export to fix windows shared lib building (#1714) * add THRIFT_EXPORT to fix windows shared lib building * use shared libraries on vs2017 appveyor build, leave msvc2017 static link --- appveyor.yml | 2 +- lib/cpp/CMakeLists.txt | 4 ++++ lib/cpp/Makefile.am | 1 + lib/cpp/src/thrift/TOutput.cpp | 2 +- lib/cpp/src/thrift/TOutput.h | 4 +++- lib/cpp/src/thrift/thrift_export.h | 20 +++++++++++++++++++ .../src/thrift/transport/TSSLServerSocket.cpp | 1 + lib/cpp/src/thrift/transport/TSSLSocket.h | 2 +- 8 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 lib/cpp/src/thrift/thrift_export.h diff --git a/appveyor.yml b/appveyor.yml index 39aba4f95b9..74c92f1fa66 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -39,7 +39,7 @@ environment: - PROFILE: MSVC2017 PLATFORM: x64 CONFIGURATION: Release - BUILD_SHARED_LIBS: OFF + BUILD_SHARED_LIBS: ON BOOST_VERSION: 1.67.0 LIBEVENT_VERSION: 2.1.8 PYTHON_VERSION: 3.6 diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index dd90c808bed..e92da606bce 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -23,6 +23,10 @@ REQUIRE_BOOST_HEADERS() include_directories(src) +if(NOT BUILD_SHARED_LIBS) + add_definitions("-DTHRIFT_STATIC_DEFINE") +endif() + # SYSLIBS contains libraries that need to be linked to all lib targets set(SYSLIBS "") diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index 616effddd9a..114ff176798 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -132,6 +132,7 @@ include_thriftdir = $(includedir)/thrift include_thrift_HEADERS = \ $(top_builddir)/config.h \ src/thrift/thrift-config.h \ + src/thrift/thrift_export.h \ src/thrift/TDispatchProcessor.h \ src/thrift/Thrift.h \ src/thrift/TOutput.h \ diff --git a/lib/cpp/src/thrift/TOutput.cpp b/lib/cpp/src/thrift/TOutput.cpp index f25b5665393..8d163a94183 100644 --- a/lib/cpp/src/thrift/TOutput.cpp +++ b/lib/cpp/src/thrift/TOutput.cpp @@ -27,7 +27,7 @@ namespace apache { namespace thrift { -TOutput GlobalOutput; +THRIFT_EXPORT TOutput GlobalOutput; TOutput::TOutput() : f_(&errorTimeWrapper) {} diff --git a/lib/cpp/src/thrift/TOutput.h b/lib/cpp/src/thrift/TOutput.h index 6135cfa15ee..26c9a563aed 100644 --- a/lib/cpp/src/thrift/TOutput.h +++ b/lib/cpp/src/thrift/TOutput.h @@ -20,6 +20,8 @@ #ifndef _THRIFT_OUTPUT_H_ #define _THRIFT_OUTPUT_H_ 1 +#include + namespace apache { namespace thrift { @@ -51,7 +53,7 @@ class TOutput { void (*f_)(const char*); }; -extern TOutput GlobalOutput; +THRIFT_EXPORT extern TOutput GlobalOutput; } } // namespace apache::thrift diff --git a/lib/cpp/src/thrift/thrift_export.h b/lib/cpp/src/thrift/thrift_export.h new file mode 100644 index 00000000000..f5c059fb7c2 --- /dev/null +++ b/lib/cpp/src/thrift/thrift_export.h @@ -0,0 +1,20 @@ +#ifndef THRIFT_EXPORT_H +#define THRIFT_EXPORT_H + +#ifdef THRIFT_STATIC_DEFINE +# define THRIFT_EXPORT +#elif defined(_MSC_VER ) +# ifndef THRIFT_EXPORT +# ifdef thrift_EXPORTS + /* We are building this library */ +# define THRIFT_EXPORT __declspec(dllexport) +# else + /* We are using this library */ +# define THRIFT_EXPORT __declspec(dllimport) +# endif +# endif +#else +# define THRIFT_EXPORT +#endif + +#endif /* THRIFT_EXPORT_H */ diff --git a/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp b/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp index 34605c09f68..b20c174087d 100644 --- a/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSSLServerSocket.cpp @@ -17,6 +17,7 @@ * under the License. */ +#include #include #include diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.h b/lib/cpp/src/thrift/transport/TSSLSocket.h index 8f095dc8c13..4d46998c40a 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.h +++ b/lib/cpp/src/thrift/transport/TSSLSocket.h @@ -321,7 +321,7 @@ class TSSLSocketFactory { std::shared_ptr access_; static concurrency::Mutex mutex_; static uint64_t count_; - static bool manualOpenSSLInitialization_; + THRIFT_EXPORT static bool manualOpenSSLInitialization_; void setup(std::shared_ptr ssl); static int passwordCallback(char* password, int size, int, void* data); }; From adde44b0f542c97dc7e9b2678be53705006c05e3 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Tue, 5 Feb 2019 01:00:02 +0100 Subject: [PATCH 210/756] THRIFT-4772 fully enable server-side usage of framed/buffered transports Client: netstd Patch: Jens Geyer This closes #1729 --- lib/netstd/Thrift/Server/TServer.cs | 6 +- lib/netstd/Thrift/TApplicationException.cs | 2 +- .../{Client => }/TBufferedTransport.cs | 10 +- .../{Client => }/TFramedTransport.cs | 10 +- .../Thrift/Transport/TTransportException.cs | 2 +- test/netstd/Client/Program.cs | 1 + test/netstd/Client/TestClient.cs | 167 ++++++++++++----- test/netstd/Server/Program.cs | 3 +- test/netstd/Server/TestServer.cs | 168 ++++++++++++------ 9 files changed, 258 insertions(+), 111 deletions(-) rename lib/netstd/Thrift/Transport/{Client => }/TBufferedTransport.cs (96%) rename lib/netstd/Thrift/Transport/{Client => }/TFramedTransport.cs (96%) diff --git a/lib/netstd/Thrift/Server/TServer.cs b/lib/netstd/Thrift/Server/TServer.cs index 3a70c07735e..b351913cef4 100644 --- a/lib/netstd/Thrift/Server/TServer.cs +++ b/lib/netstd/Thrift/Server/TServer.cs @@ -45,8 +45,8 @@ protected TServer(ITProcessorFactory processorFactory, TServerTransport serverTr { ProcessorFactory = processorFactory ?? throw new ArgumentNullException(nameof(processorFactory)); ServerTransport = serverTransport; - InputTransportFactory = inputTransportFactory ?? throw new ArgumentNullException(nameof(inputTransportFactory)); - OutputTransportFactory = outputTransportFactory ?? throw new ArgumentNullException(nameof(outputTransportFactory)); + InputTransportFactory = inputTransportFactory ?? new TTransportFactory(); + OutputTransportFactory = outputTransportFactory ?? new TTransportFactory(); InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory)); OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory)); Logger = logger; // null is absolutely legal @@ -84,4 +84,4 @@ public virtual async Task ServeAsync(CancellationToken cancellationToken) } } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/TApplicationException.cs b/lib/netstd/Thrift/TApplicationException.cs index 50f65d647db..9c86898af6e 100644 --- a/lib/netstd/Thrift/TApplicationException.cs +++ b/lib/netstd/Thrift/TApplicationException.cs @@ -44,7 +44,7 @@ public enum ExceptionType private const int MessageTypeFieldId = 1; private const int ExTypeFieldId = 2; - protected ExceptionType Type; + public ExceptionType Type { get; private set; } public TApplicationException() { diff --git a/lib/netstd/Thrift/Transport/Client/TBufferedTransport.cs b/lib/netstd/Thrift/Transport/TBufferedTransport.cs similarity index 96% rename from lib/netstd/Thrift/Transport/Client/TBufferedTransport.cs rename to lib/netstd/Thrift/Transport/TBufferedTransport.cs index b8b5f53dc38..c648f5cdb1a 100644 --- a/lib/netstd/Thrift/Transport/Client/TBufferedTransport.cs +++ b/lib/netstd/Thrift/Transport/TBufferedTransport.cs @@ -20,7 +20,7 @@ using System.Threading; using System.Threading.Tasks; -namespace Thrift.Transport.Client +namespace Thrift.Transport { // ReSharper disable once InconsistentNaming public class TBufferedTransport : TTransport @@ -31,6 +31,14 @@ public class TBufferedTransport : TTransport private readonly TTransport _transport; private bool _isDisposed; + public class Factory : TTransportFactory + { + public override TTransport GetTransport(TTransport trans) + { + return new TBufferedTransport(trans); + } + } + //TODO: should support only specified input transport? public TBufferedTransport(TTransport transport, int bufSize = 1024) { diff --git a/lib/netstd/Thrift/Transport/Client/TFramedTransport.cs b/lib/netstd/Thrift/Transport/TFramedTransport.cs similarity index 96% rename from lib/netstd/Thrift/Transport/Client/TFramedTransport.cs rename to lib/netstd/Thrift/Transport/TFramedTransport.cs index 7b764dfbe28..59963f1e9f0 100644 --- a/lib/netstd/Thrift/Transport/Client/TFramedTransport.cs +++ b/lib/netstd/Thrift/Transport/TFramedTransport.cs @@ -20,7 +20,7 @@ using System.Threading; using System.Threading.Tasks; -namespace Thrift.Transport.Client +namespace Thrift.Transport { //TODO: check for correct implementation @@ -35,6 +35,14 @@ public class TFramedTransport : TTransport private bool _isDisposed; + public class Factory : TTransportFactory + { + public override TTransport GetTransport(TTransport trans) + { + return new TFramedTransport(trans); + } + } + public TFramedTransport(TTransport transport) { _transport = transport ?? throw new ArgumentNullException(nameof(transport)); diff --git a/lib/netstd/Thrift/Transport/TTransportException.cs b/lib/netstd/Thrift/Transport/TTransportException.cs index 7469b8ba278..760a178e6ce 100644 --- a/lib/netstd/Thrift/Transport/TTransportException.cs +++ b/lib/netstd/Thrift/Transport/TTransportException.cs @@ -32,7 +32,7 @@ public enum ExceptionType Interrupted } - protected ExceptionType ExType; + public ExceptionType ExType { get; private set; } public TTransportException() { diff --git a/test/netstd/Client/Program.cs b/test/netstd/Client/Program.cs index 72139d9def5..8d973c4804a 100644 --- a/test/netstd/Client/Program.cs +++ b/test/netstd/Client/Program.cs @@ -52,6 +52,7 @@ public static int Main(string[] args) PrintHelp(); return 0; default: + Console.WriteLine("Invalid argument: {0}", firstArg); PrintHelp(); return -1; } diff --git a/test/netstd/Client/TestClient.cs b/test/netstd/Client/TestClient.cs index b2e8cbf5c88..f48084627f9 100644 --- a/test/netstd/Client/TestClient.cs +++ b/test/netstd/Client/TestClient.cs @@ -35,6 +35,29 @@ namespace ThriftTest { + internal enum ProtocolChoice + { + Binary, + Compact, + Json + } + + // it does not make much sense to use buffered when we already use framed + internal enum LayeredChoice + { + None, + Buffered, + Framed + } + + + internal enum TransportChoice + { + Socket, + TlsSocket, + NamedPipe + } + public class TestClient { private class TestParams @@ -45,10 +68,9 @@ private class TestParams public int numThreads = 1; public string url; public string pipe; - public bool buffered; - public bool framed; - public string protocol; - public bool encrypted = false; + public LayeredChoice layered = LayeredChoice.None; + public ProtocolChoice protocol = ProtocolChoice.Binary; + public TransportChoice transport = TransportChoice.Socket; internal void Parse( List args) { @@ -65,26 +87,28 @@ internal void Parse( List args) else if (args[i].StartsWith("--pipe=")) { pipe = args[i].Substring(args[i].IndexOf("=") + 1); - Console.WriteLine("Using named pipes transport"); + transport = TransportChoice.NamedPipe; } else if (args[i].StartsWith("--host=")) { // check there for ipaddress host = new IPAddress(Encoding.Unicode.GetBytes(args[i].Substring(args[i].IndexOf("=") + 1))); + if (transport != TransportChoice.TlsSocket) + transport = TransportChoice.Socket; } else if (args[i].StartsWith("--port=")) { port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); + if (transport != TransportChoice.TlsSocket) + transport = TransportChoice.Socket; } else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") { - buffered = true; - Console.WriteLine("Using buffered sockets"); + layered = LayeredChoice.Buffered; } else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") { - framed = true; - Console.WriteLine("Using framed transport"); + layered = LayeredChoice.Framed; } else if (args[i] == "-t") { @@ -92,29 +116,77 @@ internal void Parse( List args) } else if (args[i] == "--binary" || args[i] == "--protocol=binary") { - protocol = "binary"; - Console.WriteLine("Using binary protocol"); + protocol = ProtocolChoice.Binary; } else if (args[i] == "--compact" || args[i] == "--protocol=compact") { - protocol = "compact"; - Console.WriteLine("Using compact protocol"); + protocol = ProtocolChoice.Compact; } else if (args[i] == "--json" || args[i] == "--protocol=json") { - protocol = "json"; - Console.WriteLine("Using JSON protocol"); + protocol = ProtocolChoice.Json; } else if (args[i] == "--ssl") { - encrypted = true; - Console.WriteLine("Using encrypted transport"); + transport = TransportChoice.TlsSocket; + } + else if (args[i] == "--help") + { + PrintOptionsHelp(); + return; } else { - //throw new ArgumentException(args[i]); + Console.WriteLine("Invalid argument: {0}", args[i]); + PrintOptionsHelp(); + return; } } + + switch (transport) + { + case TransportChoice.Socket: + Console.WriteLine("Using socket transport"); + break; + case TransportChoice.TlsSocket: + Console.WriteLine("Using encrypted transport"); + break; + case TransportChoice.NamedPipe: + Console.WriteLine("Using named pipes transport"); + break; + default: // unhandled case + Debug.Assert(false); + break; + } + + switch (layered) + { + case LayeredChoice.Framed: + Console.WriteLine("Using framed transport"); + break; + case LayeredChoice.Buffered: + Console.WriteLine("Using buffered transport"); + break; + default: // unhandled case? + Debug.Assert(layered == LayeredChoice.None); + break; + } + + switch (protocol) + { + case ProtocolChoice.Binary: + Console.WriteLine("Using binary protocol"); + break; + case ProtocolChoice.Compact: + Console.WriteLine("Using compact protocol"); + break; + case ProtocolChoice.Json: + Console.WriteLine("Using JSON protocol"); + break; + default: // unhandled case? + Debug.Assert(false); + break; + } } private static X509Certificate2 GetClientCert() @@ -156,16 +228,15 @@ public TTransport CreateTransport() // endpoint transport TTransport trans = null; - if (pipe != null) - { - trans = new TNamedPipeTransport(pipe); - } - else + switch(transport) { - if (encrypted) - { + case TransportChoice.NamedPipe: + Debug.Assert(pipe != null); + trans = new TNamedPipeTransport(pipe); + break; + + case TransportChoice.TlsSocket: var cert = GetClientCert(); - if (cert == null || !cert.HasPrivateKey) { throw new InvalidOperationException("Certificate doesn't contain private key"); @@ -174,22 +245,27 @@ public TTransport CreateTransport() trans = new TTlsSocketTransport(host, port, 0, cert, (sender, certificate, chain, errors) => true, null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); - } - else - { + break; + + case TransportChoice.Socket: + default: trans = new TSocketTransport(host, port); - } + break; } - // layered transport - if (buffered) - { - trans = new TBufferedTransport(trans); - } - if (framed) + // layered transport + switch(layered) { - trans = new TFramedTransport(trans); + case LayeredChoice.Buffered: + trans = new TBufferedTransport(trans); + break; + case LayeredChoice.Framed: + trans = new TFramedTransport(trans); + break; + default: + Debug.Assert(layered == LayeredChoice.None); + break; } return trans; @@ -200,17 +276,16 @@ public TTransport CreateTransport() public TProtocol CreateProtocol(TTransport transport) { - if (protocol == "compact") + switch (protocol) { - return new TCompactProtocol(transport); + case ProtocolChoice.Compact: + return new TCompactProtocol(transport); + case ProtocolChoice.Json: + return new TJsonProtocol(transport); + case ProtocolChoice.Binary: + default: + return new TBinaryProtocol(transport); } - - if (protocol == "json") - { - return new TJsonProtocol(transport); - } - - return new TBinaryProtocol(transport); } } diff --git a/test/netstd/Server/Program.cs b/test/netstd/Server/Program.cs index e647e5b2a58..8bfa3714fd3 100644 --- a/test/netstd/Server/Program.cs +++ b/test/netstd/Server/Program.cs @@ -52,6 +52,7 @@ public static int Main(string[] args) PrintHelp(); return 0; default: + Console.WriteLine("Invalid argument: {0}", firstArg); PrintHelp(); return -1; } @@ -64,7 +65,7 @@ private static void PrintHelp() Console.WriteLine(" Server --help"); Console.WriteLine(""); - TestServer.PrintOptionsHelp(); + ServerParam.PrintOptionsHelp(); } } } diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs index 8a7410f95fc..e25e6116d9c 100644 --- a/test/netstd/Server/TestServer.cs +++ b/test/netstd/Server/TestServer.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Security.Authentication; @@ -35,13 +36,34 @@ namespace ThriftTest { + internal enum ProtocolChoice + { + Binary, + Compact, + Json + } + + // it does not make much sense to use buffered when we already use framed + internal enum LayeredChoice + { + None, + Buffered, + Framed + } + + + internal enum TransportChoice + { + Socket, + TlsSocket, + NamedPipe + } + internal class ServerParam { - internal bool useBufferedSockets = false; - internal bool useFramed = false; - internal bool useEncryption = false; - internal bool compact = false; - internal bool json = false; + internal LayeredChoice layered = LayeredChoice.None; + internal ProtocolChoice protocol = ProtocolChoice.Binary; + internal TransportChoice transport = TransportChoice.Socket; internal int port = 9090; internal string pipe = null; @@ -52,30 +74,33 @@ internal void Parse(List args) if (args[i].StartsWith("--pipe=")) { pipe = args[i].Substring(args[i].IndexOf("=") + 1); + transport = TransportChoice.NamedPipe; } else if (args[i].StartsWith("--port=")) { port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); + if(transport != TransportChoice.TlsSocket) + transport = TransportChoice.Socket; } else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") { - useBufferedSockets = true; + layered = LayeredChoice.Buffered; } else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") { - useFramed = true; + layered = LayeredChoice.Framed; } else if (args[i] == "--binary" || args[i] == "--protocol=binary") { - // nothing needed + protocol = ProtocolChoice.Binary; } else if (args[i] == "--compact" || args[i] == "--protocol=compact") { - compact = true; + protocol = ProtocolChoice.Compact; } else if (args[i] == "--json" || args[i] == "--protocol=json") { - json = true; + protocol = ProtocolChoice.Json; } else if (args[i] == "--threaded" || args[i] == "--server-type=threaded") { @@ -91,15 +116,35 @@ internal void Parse(List args) } else if (args[i] == "--ssl") { - useEncryption = true; + transport = TransportChoice.TlsSocket; + } + else if (args[i] == "--help") + { + PrintOptionsHelp(); + return; } else { - //throw new ArgumentException(args[i]); + Console.WriteLine("Invalid argument: {0}", args[i]); + PrintOptionsHelp(); + return; } } } + + internal static void PrintOptionsHelp() + { + Console.WriteLine("Server options:"); + Console.WriteLine(" --pipe="); + Console.WriteLine(" --port="); + Console.WriteLine(" --transport= one of buffered,framed (defaults to none)"); + Console.WriteLine(" --protocol= one of compact,json (defaults to binary)"); + Console.WriteLine(" --server-type= one of threaded,threadpool (defaults to simple)"); + Console.WriteLine(" --processor="); + Console.WriteLine(" --ssl"); + Console.WriteLine(); + } } public class TestServer @@ -448,18 +493,6 @@ public Task testOnewayAsync(int secondsToSleep, CancellationToken cancellationTo } } - internal static void PrintOptionsHelp() - { - Console.WriteLine("Server options:"); - Console.WriteLine(" --pipe="); - Console.WriteLine(" --port="); - Console.WriteLine(" --transport= one of buffered,framed (defaults to none)"); - Console.WriteLine(" --protocol= one of compact,json (defaults to binary)"); - Console.WriteLine(" --server-type= one of threaded,threadpool (defaults to simple)"); - Console.WriteLine(" --processor="); - Console.WriteLine(" --ssl"); - Console.WriteLine(); - } private static X509Certificate2 GetServerCert() { @@ -515,53 +548,74 @@ public static int Execute(List args) } + TTransportFactory transFactory = null; + // Transport TServerTransport trans; - if (param.pipe != null) - { - trans = new TNamedPipeServerTransport(param.pipe); - } -// else if (param.useFramed) -// { -// trans = new TServerFramedTransport(param.port); -// } - else + var useBuffered = (param.layered == LayeredChoice.Buffered); + var useFramed = (param.layered == LayeredChoice.Framed); + switch (param.transport) { - if (param.useEncryption) - { + case TransportChoice.NamedPipe: + Debug.Assert(param.pipe != null); + trans = new TNamedPipeServerTransport(param.pipe); + break; + + + case TransportChoice.TlsSocket: var cert = GetServerCert(); - if (cert == null || !cert.HasPrivateKey) { throw new InvalidOperationException("Certificate doesn't contain private key"); } - - trans = new TTlsServerSocketTransport(param.port, param.useBufferedSockets, param.useFramed, cert, + + transFactory = new TTransportFactory(); // framed/buffered is built into socket transports + trans = new TTlsServerSocketTransport( param.port, useBuffered, useFramed, cert, (sender, certificate, chain, errors) => true, null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); - } - else + break; + + case TransportChoice.Socket: + default: + transFactory = new TTransportFactory(); // framed/buffered is built into socket transports + trans = new TServerSocketTransport(param.port, 0, useBuffered, useFramed); + break; + } + + // add layered transport, if not already set above + if (transFactory == null) + { + switch (param.layered) { - trans = new TServerSocketTransport(param.port, 0, param.useBufferedSockets, param.useFramed); + case LayeredChoice.Framed: + transFactory = new TFramedTransport.Factory(); + break; + case LayeredChoice.Buffered: + transFactory = new TBufferedTransport.Factory(); + break; } } + // Protocol ITProtocolFactory proto; - if (param.compact) - proto = new TCompactProtocol.Factory(); - else if (param.json) - proto = new TJsonProtocol.Factory(); - else - proto = new TBinaryProtocol.Factory(); - - ITProcessorFactory processorFactory; + switch (param.protocol) + { + case ProtocolChoice.Compact: + proto = new TCompactProtocol.Factory(); + break; + case ProtocolChoice.Json: + proto = new TJsonProtocol.Factory(); + break; + case ProtocolChoice.Binary: + default: + proto = new TBinaryProtocol.Factory(); + break; + } // Processor var testHandler = new TestHandlerAsync(); var testProcessor = new ThriftTest.AsyncProcessor(testHandler); - processorFactory = new TSingletonProcessorFactory(testProcessor); - - TTransportFactory transFactory = new TTransportFactory(); + var processorFactory = new TSingletonProcessorFactory(testProcessor); TServer serverEngine = new TSimpleAsyncServer(processorFactory, trans, transFactory, transFactory, proto, proto, logger); @@ -573,11 +627,11 @@ public static int Execute(List args) var where = (! string.IsNullOrEmpty(param.pipe)) ? "on pipe " + param.pipe : "on port " + param.port; Console.WriteLine("Starting the AsyncBaseServer " + where + " with processor TPrototypeProcessorFactory prototype factory " + - (param.useBufferedSockets ? " with buffered socket" : "") + - (param.useFramed ? " with framed transport" : "") + - (param.useEncryption ? " with encryption" : "") + - (param.compact ? " with compact protocol" : "") + - (param.json ? " with json protocol" : "") + + (param.layered == LayeredChoice.Buffered ? " with buffered transport" : "") + + (param.layered == LayeredChoice.Framed ? " with framed transport" : "") + + (param.transport == TransportChoice.TlsSocket ? " with encryption" : "") + + (param.protocol == ProtocolChoice.Compact ? " with compact protocol" : "") + + (param.protocol == ProtocolChoice.Json ? " with json protocol" : "") + "..."); serverEngine.ServeAsync(CancellationToken.None).GetAwaiter().GetResult(); Console.ReadLine(); From 4a898564f936b39d45490f370737ce55d4c2b3f5 Mon Sep 17 00:00:00 2001 From: Qinghui Xu Date: Wed, 6 Feb 2019 16:12:07 +0100 Subject: [PATCH 211/756] THRIFT-4773: Provide root cause for sasl negotiation failure Client: java The error for sasl negotiation failure dropped the root cause, which makes troubleshooting sometimes difficult. --- lib/java/src/org/apache/thrift/transport/TSaslTransport.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java index bed3b395ede..c8584259184 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java @@ -317,7 +317,7 @@ public void open() throws TTransportException { 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 new TSaslTransportException("No data or no sasl data in the stream during negotiation", e); } throw e; } From a6a3a787ec3d3bd71b276e85c9a02a53ad1105c4 Mon Sep 17 00:00:00 2001 From: cyy Date: Thu, 7 Feb 2019 22:27:33 +0800 Subject: [PATCH 212/756] THRIFT-4732:refine cmake scripts (#1688) * add cmake support for clib and remove unused variables * add targets for code analysis * add wall to all compilers and add utf-8 options for msvc --- CMakeLists.txt | 6 ++ build/cmake/DefinePlatformSpecifc.cmake | 30 ++++++++-- build/cmake/FindClangTools.cmake | 28 ++++++++++ build/cmake/StaticCodeAnalysis.cmake | 9 +++ lib/c_glib/CMakeLists.txt | 3 +- .../protocol/thrift_multiplexed_protocol.c | 1 - .../c_glib/transport/thrift_ssl_socket.c | 2 - test/c_glib/CMakeLists.txt | 55 +++++++++++++++++++ 8 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 build/cmake/FindClangTools.cmake create mode 100644 build/cmake/StaticCodeAnalysis.cmake create mode 100644 test/c_glib/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index f0165f8f480..c77a6010cde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,9 @@ include(DefineInstallationPaths) # Based on the options set some platform specifics include(DefinePlatformSpecifc) +# Add CMake targets for static code analysis +include(StaticCodeAnalysis) + # Generate the config.h file include(ConfigureChecks) @@ -98,6 +101,9 @@ endif() if(BUILD_C_GLIB) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/c_glib) + if(BUILD_TESTING) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/test/c_glib) + endif() endif() if(BUILD_JAVA) diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index b87fd6524c2..c0bb529c350 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -23,6 +23,31 @@ # For Debug build types, append a "d" to the library names. set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Set debug library postfix" FORCE) +# basic options +foreach(lang IN ITEMS C CXX) + if(CMAKE_${lang}_COMPILER_ID STREQUAL "Clang") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wall") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -ferror-limit=1") + elseif(CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wall -Wextra") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -fmax-errors=1") + elseif(CMAKE_${lang}_COMPILER_ID STREQUAL "MSVC") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} /MP") # parallel build + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} /W3") # warning level 3 + include(CheckCXXCompilerFlag) + set(CMAKE_REQUIRED_QUIET ON) + check_cxx_compiler_flag("/source-charset:utf-8" res_var) + if (res_var) + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} /source-charset:utf-8") + endif() + check_cxx_compiler_flag("/execution-charset:utf-8" res_var) + if (res_var) + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} /execution-charset:utf-8") + endif() + add_definitions("-DUNICODE -D_UNICODE") + endif() +endforeach() + # Visual Studio specific options if(MSVC) # Allow for shared library builds @@ -66,11 +91,6 @@ if(MSVC) # Disable boost auto linking pragmas - cmake includes the right files add_definitions("-DBOOST_ALL_NO_LIB") - - add_definitions("/MP") # parallel build - add_definitions("/W3") # warning level 3 - - add_definitions("-DUNICODE -D_UNICODE") elseif(UNIX) find_program( MEMORYCHECK_COMMAND valgrind ) set( MEMORYCHECK_COMMAND_OPTIONS "--gen-suppressions=all --leak-check=full" ) diff --git a/build/cmake/FindClangTools.cmake b/build/cmake/FindClangTools.cmake new file mode 100644 index 00000000000..b72bea765d5 --- /dev/null +++ b/build/cmake/FindClangTools.cmake @@ -0,0 +1,28 @@ +# - Try to find Clang tools +# +# The following are set after configuration is done: +# clang-tidy_FOUND +# ClangTools::clang-tidy +# clang-apply-replacements_FOUND +# ClangTools::clang-apply-replacements +# run-clang-tidy_FOUND +# ClangTools::run-clang-tidy + +include_guard() +include(FindPackageHandleStandardArgs) + +foreach(program_name IN ITEMS clang-tidy clang-apply-replacements) + find_program(${program_name}_BINARY NAMES ${program_name}-devel ${program_name}-8 ${program_name} PATH_SUFFIXES "LLVM/bin") + find_package_handle_standard_args(${program_name} DEFAULT_MSG ${program_name}_BINARY) + if(${program_name}_FOUND AND NOT TARGET ClangTools::${program_name}) + add_executable(ClangTools::${program_name} IMPORTED) + set_property(TARGET ClangTools::${program_name} PROPERTY IMPORTED_LOCATION "${${program_name}_BINARY}") + endif() +endforeach() + +find_program(run-clang-tidy_BINARY NAMES run-clang-tidy run-clang-tidy.py PATH_SUFFIXES "LLVM/bin" "llvm-devel/share/clang") +find_package_handle_standard_args(run-clang-tidy DEFAULT_MSG run-clang-tidy_BINARY) +if(run-clang-tidy_FOUND AND NOT TARGET ClangTools::run-clang-tidy) + add_executable(ClangTools::run-clang-tidy IMPORTED) + set_property(TARGET ClangTools::run-clang-tidy PROPERTY IMPORTED_LOCATION "${run-clang-tidy_BINARY}") +endif() diff --git a/build/cmake/StaticCodeAnalysis.cmake b/build/cmake/StaticCodeAnalysis.cmake new file mode 100644 index 00000000000..3356c761dc6 --- /dev/null +++ b/build/cmake/StaticCodeAnalysis.cmake @@ -0,0 +1,9 @@ +find_package(ClangTools QUIET) +if(clang-tidy_FOUND AND run-clang-tidy_FOUND AND NOT TARGET do_run_clang_tidy) + add_custom_target( + do_run_clang_tidy + COMMAND ClangTools::run-clang-tidy -clang-tidy-binary "$" -p ${CMAKE_BINARY_DIR} "-quiet" > ./run-clang-tidy.txt + DEPENDS ${CMAKE_BINARY_DIR}/compile_commands.json + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) +endif() diff --git a/lib/c_glib/CMakeLists.txt b/lib/c_glib/CMakeLists.txt index 3743a68dd85..3e4a154b8e3 100644 --- a/lib/c_glib/CMakeLists.txt +++ b/lib/c_glib/CMakeLists.txt @@ -39,6 +39,7 @@ set(thrift_c_glib_SOURCES src/thrift/c_glib/protocol/thrift_protocol_decorator.c src/thrift/c_glib/protocol/thrift_binary_protocol.c src/thrift/c_glib/protocol/thrift_stored_message_protocol.c + src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c src/thrift/c_glib/protocol/thrift_binary_protocol_factory.c src/thrift/c_glib/protocol/thrift_compact_protocol.c src/thrift/c_glib/protocol/thrift_compact_protocol_factory.c @@ -60,7 +61,7 @@ set(thrift_c_glib_SOURCES # If OpenSSL is not found just ignore the OpenSSL stuff find_package(OpenSSL) if(OPENSSL_FOUND AND WITH_OPENSSL) - list( APPEND thriftcpp_SOURCES + list( APPEND thrift_c_glib_SOURCES src/thrift/c_glib/transport/thrift_ssl_socket.c ) include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c index 727f4a87c44..352e3016c82 100644 --- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c +++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c @@ -49,7 +49,6 @@ thrift_multiplexed_protocol_write_message_begin (ThriftMultiplexedProtocol *prot g_return_val_if_fail (THRIFT_IS_MULTIPLEXED_PROTOCOL (protocol), -1); ThriftMultiplexedProtocol *self = THRIFT_MULTIPLEXED_PROTOCOL (protocol); - ThriftMultiplexedProtocolClass *multiplexClass = THRIFT_MULTIPLEXED_PROTOCOL_GET_CLASS(self); if( (message_type == T_CALL || message_type == T_ONEWAY) && self->service_name != NULL) { service_name = g_strdup_printf("%s%s%s", self->service_name, THRIFT_MULTIPLEXED_PROTOCOL_DEFAULT_SEPARATOR, name); diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c index ee55406857e..df17fa6ee20 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c @@ -369,8 +369,6 @@ gboolean thrift_ssl_socket_flush (ThriftTransport *transport, GError **error) { ThriftSSLSocket *ssl_socket = THRIFT_SSL_SOCKET (transport); - gint ret = 0; - guint sent = 0; ThriftSocket *socket = THRIFT_SOCKET (transport); g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET && ssl_socket->ssl!=NULL, FALSE); diff --git a/test/c_glib/CMakeLists.txt b/test/c_glib/CMakeLists.txt new file mode 100644 index 00000000000..98173155bde --- /dev/null +++ b/test/c_glib/CMakeLists.txt @@ -0,0 +1,55 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# Contains the thrift specific LINK_AGAINST_THRIFT_LIBRARY +include(ThriftMacros) + +find_package(GLIB REQUIRED COMPONENTS gobject) +include_directories(SYSTEM "${GLIB_INCLUDE_DIR}") +include_directories(SYSTEM "${GLIBCONFIG_INCLUDE_DIR}") + +#Make sure gen-c_glib files can be included +include_directories("${CMAKE_CURRENT_BINARY_DIR}") +include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-c_glib") +include_directories("${PROJECT_SOURCE_DIR}/lib/c_glib/src") + +set(crosstestgencglib_SOURCES + gen-c_glib/t_test_second_service.c + gen-c_glib/t_test_second_service.h + gen-c_glib/t_test_thrift_test.c + gen-c_glib/t_test_thrift_test.h + gen-c_glib/t_test_thrift_test_types.c + gen-c_glib/t_test_thrift_test_types.h +) +add_library(crosstestgencglib STATIC ${crosstestgencglib_SOURCES}) +LINK_AGAINST_THRIFT_LIBRARY(crosstestgencglib thrift_c_glib) + +add_executable(test_server src/test_server.c src/thrift_test_handler.c src/thrift_second_service_handler.c) +target_link_libraries(test_server crosstestgencglib) + +add_executable(test_client src/test_client.c) +target_link_libraries(test_client crosstestgencglib) + +# +# Common thrift code generation rules +# + +add_custom_command(OUTPUT gen-c_glib/t_test_second_service.c gen-c_glib/t_test_second_service.h gen-c_glib/t_test_thrift_test.c gen-c_glib/t_test_thrift_test.h gen-c_glib/t_test_thrift_test_types.c gen-c_glib/t_test_thrift_test_types.h + COMMAND ${THRIFT_COMPILER} --gen c_glib -r ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift +) From fc6c15c83de4f9d34e570c1f1465e7a1f6abc798 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 7 Feb 2019 17:16:59 -0500 Subject: [PATCH 213/756] Update the pull request template [ci skip] --- .../pull_request_template.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) rename pull_request_template.md => .github/pull_request_template.md (79%) diff --git a/pull_request_template.md b/.github/pull_request_template.md similarity index 79% rename from pull_request_template.md rename to .github/pull_request_template.md index df2fdded4ec..a6b4382b431 100644 --- a/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,14 +1,8 @@ -### Pull Request ### - -The [Contributing Guide](https://github.com/apache/thrift/blob/master/CONTRIBUTING.md) has more details and tips for -committing properly. - - - + + -Review the following checklist to ensure a smooth pull request experience. - [ ] Did you squash your changes to a single commit? @@ -45,4 +39,8 @@ Review the following checklist to ensure a smooth pull request experience. This will avoid costly and unnecessary builds in both the pull request and once it is merged. -For more information about committing, see the [Contributing Guide](https://github.com/apache/thrift/blob/master/CONTRIBUTING.md). + From e44f6a9e06aa0ae42463a791357c0e5c18020c59 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 7 Feb 2019 17:11:21 -0500 Subject: [PATCH 214/756] THRIFT-4778: fix inheritance for protocol factories --- lib/py/src/protocol/TBinaryProtocol.py | 6 +++--- lib/py/src/protocol/TCompactProtocol.py | 6 +++--- lib/py/src/protocol/THeaderProtocol.py | 4 ++-- lib/py/src/protocol/TJSONProtocol.py | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/py/src/protocol/TBinaryProtocol.py b/lib/py/src/protocol/TBinaryProtocol.py index f6be7721a5c..6b2facc4f72 100644 --- a/lib/py/src/protocol/TBinaryProtocol.py +++ b/lib/py/src/protocol/TBinaryProtocol.py @@ -17,7 +17,7 @@ # under the License. # -from .TProtocol import TType, TProtocolBase, TProtocolException +from .TProtocol import TType, TProtocolBase, TProtocolException, TProtocolFactory from struct import pack, unpack @@ -235,7 +235,7 @@ def readBinary(self): return s -class TBinaryProtocolFactory(object): +class TBinaryProtocolFactory(TProtocolFactory): def __init__(self, strictRead=False, strictWrite=True, **kwargs): self.strictRead = strictRead self.strictWrite = strictWrite @@ -284,7 +284,7 @@ def __init__(self, *args, **kwargs): self._fast_encode = fastbinary.encode_binary -class TBinaryProtocolAcceleratedFactory(object): +class TBinaryProtocolAcceleratedFactory(TProtocolFactory): def __init__(self, string_length_limit=None, container_length_limit=None, diff --git a/lib/py/src/protocol/TCompactProtocol.py b/lib/py/src/protocol/TCompactProtocol.py index baaec65b27d..700e792f79b 100644 --- a/lib/py/src/protocol/TCompactProtocol.py +++ b/lib/py/src/protocol/TCompactProtocol.py @@ -17,7 +17,7 @@ # under the License. # -from .TProtocol import TType, TProtocolBase, TProtocolException, checkIntegerLimits +from .TProtocol import TType, TProtocolBase, TProtocolException, TProtocolFactory, checkIntegerLimits from struct import pack, unpack from ..compat import binary_to_str, str_to_binary @@ -428,7 +428,7 @@ def __getTType(self, byte): return TTYPES[byte & 0x0f] -class TCompactProtocolFactory(object): +class TCompactProtocolFactory(TProtocolFactory): def __init__(self, string_length_limit=None, container_length_limit=None): @@ -470,7 +470,7 @@ def __init__(self, *args, **kwargs): self._fast_encode = fastbinary.encode_compact -class TCompactProtocolAcceleratedFactory(object): +class TCompactProtocolAcceleratedFactory(TProtocolFactory): def __init__(self, string_length_limit=None, container_length_limit=None, diff --git a/lib/py/src/protocol/THeaderProtocol.py b/lib/py/src/protocol/THeaderProtocol.py index b27a7499539..13982e898f2 100644 --- a/lib/py/src/protocol/THeaderProtocol.py +++ b/lib/py/src/protocol/THeaderProtocol.py @@ -19,7 +19,7 @@ from thrift.protocol.TBinaryProtocol import TBinaryProtocolAccelerated from thrift.protocol.TCompactProtocol import TCompactProtocolAccelerated -from thrift.protocol.TProtocol import TProtocolBase, TProtocolException +from thrift.protocol.TProtocol import TProtocolBase, TProtocolException, TProtocolFactory from thrift.Thrift import TApplicationException, TMessageType from thrift.transport.THeaderTransport import THeaderTransport, THeaderSubprotocolID, THeaderClientType @@ -217,7 +217,7 @@ def readBinary(self): return self._protocol.readBinary() -class THeaderProtocolFactory(object): +class THeaderProtocolFactory(TProtocolFactory): def __init__(self, allowed_client_types=(THeaderClientType.HEADERS,)): self.allowed_client_types = allowed_client_types diff --git a/lib/py/src/protocol/TJSONProtocol.py b/lib/py/src/protocol/TJSONProtocol.py index db2099a345b..17417027a0a 100644 --- a/lib/py/src/protocol/TJSONProtocol.py +++ b/lib/py/src/protocol/TJSONProtocol.py @@ -18,7 +18,7 @@ # from .TProtocol import (TType, TProtocolBase, TProtocolException, - checkIntegerLimits) + TProtocolFactory, checkIntegerLimits) import base64 import math import sys @@ -577,7 +577,7 @@ def writeBinary(self, binary): self.writeJSONBase64(binary) -class TJSONProtocolFactory(object): +class TJSONProtocolFactory(TProtocolFactory): def getProtocol(self, trans): return TJSONProtocol(trans) @@ -671,7 +671,7 @@ def writeBinary(self, binary): self.writeJSONBase64(binary) -class TSimpleJSONProtocolFactory(object): +class TSimpleJSONProtocolFactory(TProtocolFactory): def getProtocol(self, trans): return TSimpleJSONProtocol(trans) From 74a3e0923d9425fd0c3c854b770782148f91ec19 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 7 Feb 2019 19:33:52 -0500 Subject: [PATCH 215/756] THRIFT-4779: fix exception type in TMultiplexedProcessor --- .../apache/thrift/TMultiplexedProcessor.java | 15 ++++++++------ lib/py/src/TMultiplexedProcessor.py | 20 ++++++++++++++----- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/lib/java/src/org/apache/thrift/TMultiplexedProcessor.java b/lib/java/src/org/apache/thrift/TMultiplexedProcessor.java index 14b541d81c9..c4948621756 100644 --- a/lib/java/src/org/apache/thrift/TMultiplexedProcessor.java +++ b/lib/java/src/org/apache/thrift/TMultiplexedProcessor.java @@ -87,7 +87,7 @@ public void registerDefault(TProcessor processor) { * that allows readMessageBegin() to return the original TMessage. * * - * @throws TException If the message type is not CALL or ONEWAY, if + * @throws TProtocolException 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? :) @@ -101,7 +101,8 @@ Use the actual underlying protocol (e.g. TBinaryProtocol) to read the TMessage message = iprot.readMessageBegin(); if (message.type != TMessageType.CALL && message.type != TMessageType.ONEWAY) { - throw new TException("This should not have happened!?"); + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, + "This should not have happened!?"); } // Extract the service name @@ -112,16 +113,18 @@ Use the actual underlying protocol (e.g. TBinaryProtocol) to read the defaultProcessor.process(new StoredMessageProtocol(iprot, message), oprot); return; } - throw new TException("Service name not found in message name: " + message.name + ". Did you " + - "forget to use a TMultiplexProtocol in your client?"); + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, + "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()?"); + throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, + "Service name not found: " + serviceName + ". Did you forget " + + "to call registerProcessor()?"); } // Create a new TMessage, removing the service name diff --git a/lib/py/src/TMultiplexedProcessor.py b/lib/py/src/TMultiplexedProcessor.py index 3ac5af05c9e..8d929ac389c 100644 --- a/lib/py/src/TMultiplexedProcessor.py +++ b/lib/py/src/TMultiplexedProcessor.py @@ -17,8 +17,9 @@ # under the License. # -from thrift.Thrift import TProcessor, TMessageType, TException +from thrift.Thrift import TProcessor, TMessageType from thrift.protocol import TProtocolDecorator, TMultiplexedProtocol +from thrift.protocol.TProtocol import TProtocolException class TMultiplexedProcessor(TProcessor): @@ -31,19 +32,28 @@ def registerProcessor(self, serviceName, processor): def process(self, iprot, oprot): (name, type, seqid) = iprot.readMessageBegin() if type != TMessageType.CALL and type != TMessageType.ONEWAY: - raise TException("TMultiplexed protocol only supports CALL & ONEWAY") + raise TProtocolException( + TProtocolException.NOT_IMPLEMENTED, + "TMultiplexedProtocol only supports CALL & ONEWAY") index = name.find(TMultiplexedProtocol.SEPARATOR) if index < 0: - raise TException("Service name not found in message name: " + name + ". Did you forget to use TMultiplexedProtocol in your client?") + raise TProtocolException( + TProtocolException.NOT_IMPLEMENTED, + "Service name not found in message name: " + name + ". " + + "Did you forget to use TMultiplexedProtocol in your client?") serviceName = name[0:index] call = name[index + len(TMultiplexedProtocol.SEPARATOR):] if serviceName not in self.services: - raise TException("Service name not found: " + serviceName + ". Did you forget to call registerProcessor()?") + raise TProtocolException( + TProtocolException.NOT_IMPLEMENTED, + "Service name not found: " + serviceName + ". " + + "Did you forget to call registerProcessor()?") standardMessage = (call, type, seqid) - return self.services[serviceName].process(StoredMessageProtocol(iprot, standardMessage), oprot) + return self.services[serviceName].process( + StoredMessageProtocol(iprot, standardMessage), oprot) class StoredMessageProtocol(TProtocolDecorator.TProtocolDecorator): From 647501693bd14256df8839c13cb03659bdee4202 Mon Sep 17 00:00:00 2001 From: cyy Date: Fri, 8 Feb 2019 13:40:59 +0800 Subject: [PATCH 216/756] THRIFT-4776:Modernize c++11 code by clang-tidy (#1732) * use override * use make_shared * use emplace * use range for * fix error on MSVC * replace boost functions with std functions * fix static analyzer warnings * check api return value * initialize member * check the return value of SSL_peek > 0 * add override --- compiler/cpp/src/thrift/audit/t_audit.cpp | 42 ++--- .../src/thrift/generate/t_as3_generator.cc | 22 ++- .../src/thrift/generate/t_c_glib_generator.cc | 32 ++-- .../cpp/src/thrift/generate/t_cl_generator.cc | 32 ++-- .../src/thrift/generate/t_cpp_generator.cc | 37 ++-- .../src/thrift/generate/t_csharp_generator.cc | 18 +- .../cpp/src/thrift/generate/t_d_generator.cc | 20 +-- .../src/thrift/generate/t_dart_generator.cc | 32 ++-- .../src/thrift/generate/t_delphi_generator.cc | 28 +-- .../src/thrift/generate/t_erl_generator.cc | 20 +-- .../cpp/src/thrift/generate/t_go_generator.cc | 43 +++-- .../cpp/src/thrift/generate/t_gv_generator.cc | 14 +- .../src/thrift/generate/t_haxe_generator.cc | 22 ++- .../cpp/src/thrift/generate/t_hs_generator.cc | 165 ++++++++---------- .../src/thrift/generate/t_html_generator.cc | 41 ++--- .../src/thrift/generate/t_java_generator.cc | 20 +-- .../src/thrift/generate/t_javame_generator.cc | 30 ++-- .../cpp/src/thrift/generate/t_js_generator.cc | 34 ++-- .../src/thrift/generate/t_json_generator.cc | 50 +++--- .../src/thrift/generate/t_lua_generator.cc | 18 +- .../thrift/generate/t_netcore_generator.cc | 2 +- .../src/thrift/generate/t_netstd_generator.cc | 2 +- .../src/thrift/generate/t_ocaml_generator.cc | 18 +- .../src/thrift/generate/t_perl_generator.cc | 18 +- .../src/thrift/generate/t_php_generator.cc | 32 ++-- .../cpp/src/thrift/generate/t_py_generator.cc | 28 +-- .../cpp/src/thrift/generate/t_rb_generator.cc | 32 ++-- .../cpp/src/thrift/generate/t_rs_generator.cc | 20 +-- .../cpp/src/thrift/generate/t_st_generator.cc | 22 +-- .../src/thrift/generate/t_swift_generator.cc | 26 +-- .../src/thrift/generate/t_xml_generator.cc | 22 +-- .../src/thrift/generate/t_xsd_generator.cc | 14 +- compiler/cpp/src/thrift/main.cc | 10 +- compiler/cpp/src/thrift/parse/t_program.h | 1 - .../async/TConcurrentClientSyncInfo.cpp | 11 +- .../src/thrift/concurrency/ThreadFactory.cpp | 2 +- .../src/thrift/concurrency/ThreadManager.cpp | 23 ++- .../src/thrift/concurrency/TimerManager.cpp | 9 +- lib/cpp/src/thrift/protocol/TJSONProtocol.cpp | 6 +- lib/cpp/src/thrift/protocol/TJSONProtocol.h | 2 +- lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp | 2 +- lib/cpp/src/thrift/qt/TQIODeviceTransport.h | 2 +- lib/cpp/src/thrift/qt/TQTcpServer.cpp | 2 +- .../src/thrift/server/TNonblockingServer.cpp | 25 +-- .../src/thrift/transport/TBufferTransports.h | 6 +- lib/cpp/src/thrift/transport/TFDTransport.h | 2 +- .../src/thrift/transport/TFileTransport.cpp | 4 +- lib/cpp/src/thrift/transport/THttpTransport.h | 2 +- .../transport/TNonblockingServerSocket.cpp | 3 +- lib/cpp/src/thrift/transport/TPipeServer.cpp | 34 +++- lib/cpp/src/thrift/transport/TSSLSocket.cpp | 12 +- lib/cpp/src/thrift/transport/TSSLSocket.h | 2 +- .../src/thrift/transport/TServerSocket.cpp | 5 +- .../thrift/transport/TShortReadTransport.h | 2 +- lib/cpp/src/thrift/transport/TSocketPool.cpp | 7 +- .../src/thrift/transport/TTransportUtils.h | 2 +- .../src/thrift/transport/TZlibTransport.cpp | 4 +- lib/cpp/src/thrift/transport/TZlibTransport.h | 4 +- lib/cpp/test/TBufferBaseTest.cpp | 131 +++++++------- lib/cpp/test/TFileTransportTest.cpp | 6 +- lib/cpp/test/TMemoryBufferTest.cpp | 6 +- lib/cpp/test/TNonblockingSSLServerTest.cpp | 2 +- lib/cpp/test/TNonblockingServerTest.cpp | 1 + lib/cpp/test/TServerTransportTest.cpp | 2 +- lib/cpp/test/TransportTest.cpp | 4 +- lib/cpp/test/concurrency/Tests.cpp | 2 - 66 files changed, 635 insertions(+), 659 deletions(-) diff --git a/compiler/cpp/src/thrift/audit/t_audit.cpp b/compiler/cpp/src/thrift/audit/t_audit.cpp index 4ae9a1fcec0..fbce15c7758 100644 --- a/compiler/cpp/src/thrift/audit/t_audit.cpp +++ b/compiler/cpp/src/thrift/audit/t_audit.cpp @@ -54,18 +54,16 @@ void compare_namespace(t_program* newProgram, t_program* oldProgram) const std::map& newNamespaceMap = newProgram->get_all_namespaces(); const std::map& oldNamespaceMap = oldProgram->get_all_namespaces(); - for(auto oldNamespaceMapIt = oldNamespaceMap.begin(); - oldNamespaceMapIt != oldNamespaceMap.end(); - oldNamespaceMapIt++) + for(const auto & oldNamespaceMapIt : oldNamespaceMap) { - auto newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt->first); + auto newNamespaceMapIt = newNamespaceMap.find(oldNamespaceMapIt.first); if(newNamespaceMapIt == newNamespaceMap.end()) { - thrift_audit_warning(1, "Language %s not found in new thrift file\n", (oldNamespaceMapIt->first).c_str()); + thrift_audit_warning(1, "Language %s not found in new thrift file\n", (oldNamespaceMapIt.first).c_str()); } - else if((newNamespaceMapIt->second) != oldNamespaceMapIt->second) + else if((newNamespaceMapIt->second) != oldNamespaceMapIt.second) { - thrift_audit_warning(1, "Namespace %s changed in new thrift file\n", (oldNamespaceMapIt->second).c_str()); + thrift_audit_warning(1, "Namespace %s changed in new thrift file\n", (oldNamespaceMapIt.second).c_str()); } } } @@ -73,15 +71,13 @@ void compare_namespace(t_program* newProgram, t_program* oldProgram) void compare_enum_values(t_enum* newEnum,t_enum* oldEnum) { const std::vector& oldEnumValues = oldEnum->get_constants(); - for(auto oldEnumValuesIt = oldEnumValues.begin(); - oldEnumValuesIt != oldEnumValues.end(); - oldEnumValuesIt++) + for(auto oldEnumValue : oldEnumValues) { - int enumValue = (*oldEnumValuesIt)->get_value(); + int enumValue = oldEnumValue->get_value(); t_enum_value* newEnumValue = newEnum->get_constant_by_value(enumValue); if(newEnumValue != nullptr) { - std::string enumName = (*oldEnumValuesIt)->get_name(); + std::string enumName = oldEnumValue->get_name(); if(enumName != newEnumValue->get_name()) { thrift_audit_warning(1, "Name of the value %d changed in enum %s\n", enumValue, oldEnum->get_name().c_str()); @@ -352,27 +348,23 @@ void compare_functions(const std::vector& newFunctionList, const st { std::map newFunctionMap; std::map::iterator newFunctionMapIt; - for(auto newFunctionIt = newFunctionList.begin(); - newFunctionIt != newFunctionList.end(); - newFunctionIt++) + for(auto newFunctionIt : newFunctionList) { - newFunctionMap[(*newFunctionIt)->get_name()] = *newFunctionIt; + newFunctionMap[newFunctionIt->get_name()] = newFunctionIt; } - for(auto oldFunctionIt = oldFunctionList.begin(); - oldFunctionIt != oldFunctionList.end(); - oldFunctionIt++) + for(auto oldFunctionIt : oldFunctionList) { - newFunctionMapIt = newFunctionMap.find((*oldFunctionIt)->get_name()); + newFunctionMapIt = newFunctionMap.find(oldFunctionIt->get_name()); if(newFunctionMapIt == newFunctionMap.end()) { - thrift_audit_failure("New Thrift File has missing function %s\n",(*oldFunctionIt)->get_name().c_str()); + thrift_audit_failure("New Thrift File has missing function %s\n",oldFunctionIt->get_name().c_str()); continue; } else { //Function is found in both thrift files. Compare return type and argument list - compare_single_function(newFunctionMapIt->second, *oldFunctionIt); + compare_single_function(newFunctionMapIt->second, oldFunctionIt); } } @@ -383,11 +375,9 @@ void compare_services(const std::vector& newServices, const std::vec std::vector::const_iterator oldServiceIt; std::map newServiceMap; - for(auto newServiceIt = newServices.begin(); - newServiceIt != newServices.end(); - newServiceIt++) + for(auto newService : newServices) { - newServiceMap[(*newServiceIt)->get_name()] = *newServiceIt; + newServiceMap[newService->get_name()] = newService; } diff --git a/compiler/cpp/src/thrift/generate/t_as3_generator.cc b/compiler/cpp/src/thrift/generate/t_as3_generator.cc index 41724fe4999..dd4d166ca3e 100644 --- a/compiler/cpp/src/thrift/generate/t_as3_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_as3_generator.cc @@ -68,20 +68,20 @@ class t_as3_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; - void generate_consts(std::vector consts); + void generate_consts(std::vector consts) override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; void print_const_value(std::ostream& out, std::string name, @@ -191,7 +191,7 @@ class t_as3_generator : public t_oop_generator { std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string argument_list(t_struct* tstruct); std::string type_to_enum(t_type* ttype); - std::string get_enum_class_name(t_type* type); + std::string get_enum_class_name(t_type* type) override; bool type_can_be_null(t_type* ttype) { ttype = get_true_type(ttype); @@ -2519,9 +2519,7 @@ string t_as3_generator::constant_name(string name) { bool is_first = true; bool was_previous_char_upper = false; - for (string::iterator iter = name.begin(); iter != name.end(); ++iter) { - string::value_type character = (*iter); - + for (char character : name) { bool is_upper = isupper(character); if (is_upper && !is_first && !was_previous_char_upper) { diff --git a/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc b/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc index 306086397fb..f1531cc83c9 100644 --- a/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_c_glib_generator.cc @@ -103,16 +103,16 @@ class t_c_glib_generator : public t_oop_generator { } /* initialization and destruction */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /* generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_consts(vector consts); - void generate_struct(t_struct* tstruct); - void generate_service(t_service* tservice); - void generate_xception(t_struct* tstruct); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_consts(vector consts) override; + void generate_struct(t_struct* tstruct) override; + void generate_service(t_service* tservice) override; + void generate_xception(t_struct* tstruct) override; private: /* file streams */ @@ -253,15 +253,13 @@ void t_c_glib_generator::init_generator() { if (!includes.empty()) { f_types_ << "/* other thrift includes */" << endl; - for (vector::const_iterator iter = includes.begin(); - iter != includes.end(); - ++iter) { - const std::string& include_nspace = (*iter)->get_namespace("c_glib"); + for (auto include : includes) { + const std::string& include_nspace = include->get_namespace("c_glib"); std::string include_nspace_prefix = include_nspace.empty() ? "" : initial_caps_to_underscores(include_nspace) + "_"; f_types_ << "#include \"" << include_nspace_prefix - << initial_caps_to_underscores((*iter)->get_name()) << "_types.h\"" << endl; + << initial_caps_to_underscores(include->get_name()) << "_types.h\"" << endl; } f_types_ << endl; } @@ -269,11 +267,11 @@ void t_c_glib_generator::init_generator() { /* include custom headers */ const vector& c_includes = program_->get_c_includes(); f_types_ << "/* custom thrift includes */" << endl; - for (size_t i = 0; i < c_includes.size(); ++i) { - if (c_includes[i][0] == '<') { - f_types_ << "#include " << c_includes[i] << endl; + for (const auto & c_include : c_includes) { + if (c_include[0] == '<') { + f_types_ << "#include " << c_include << endl; } else { - f_types_ << "#include \"" << c_includes[i] << "\"" << endl; + f_types_ << "#include \"" << c_include << "\"" << endl; } } f_types_ << endl; diff --git a/compiler/cpp/src/thrift/generate/t_cl_generator.cc b/compiler/cpp/src/thrift/generate/t_cl_generator.cc index 38807f45a1a..ad7c0ef175f 100644 --- a/compiler/cpp/src/thrift/generate/t_cl_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cl_generator.cc @@ -70,15 +70,15 @@ class t_cl_generator : public t_oop_generator { copy_options_ = option_string; } - void init_generator(); - void close_generator(); - - void generate_typedef (t_typedef* ttypedef); - void generate_enum (t_enum* tenum); - void generate_const (t_const* tconst); - void generate_struct (t_struct* tstruct); - void generate_xception (t_struct* txception); - void generate_service (t_service* tservice); + void init_generator() override; + void close_generator() override; + + void generate_typedef (t_typedef* ttypedef) override; + void generate_enum (t_enum* tenum) override; + void generate_const (t_const* tconst) override; + void generate_struct (t_struct* tstruct) override; + void generate_xception (t_struct* txception) override; + void generate_service (t_service* tservice) override; void generate_cl_struct (std::ostream& out, t_struct* tstruct, bool is_exception); void generate_cl_struct_internal (std::ostream& out, t_struct* tstruct, bool is_exception); void generate_exception_sig(std::ostream& out, t_function* f); @@ -128,9 +128,9 @@ void t_cl_generator::init_generator() { string f_types_name = program_dir + "/" + program_name_ + "-types.lisp"; string f_vars_name = program_dir + "/" + program_name_ + "-vars.lisp"; - f_types_.open(f_types_name.c_str()); + f_types_.open(f_types_name); f_types_ << cl_autogen_comment() << endl; - f_vars_.open(f_vars_name.c_str()); + f_vars_.open(f_vars_name); f_vars_ << cl_autogen_comment() << endl; package_def(f_types_); @@ -139,7 +139,7 @@ void t_cl_generator::init_generator() { if (!no_asd) { string f_asd_name = program_dir + "/" + system_prefix + program_name_ + ".asd"; - f_asd_.open(f_asd_name.c_str()); + f_asd_.open(f_asd_name); f_asd_ << cl_autogen_comment() << endl; asdf_def(f_asd_); } @@ -152,8 +152,8 @@ string t_cl_generator::render_includes() { const vector& includes = program_->get_includes(); string result = ""; result += ":depends-on (:thrift"; - for (size_t i = 0; i < includes.size(); ++i) { - result += " :" + system_prefix + underscore(includes[i]->get_name()); + for (auto include : includes) { + result += " :" + system_prefix + underscore(include->get_name()); } result += ")\n"; return result; @@ -215,8 +215,8 @@ void t_cl_generator::package_def(std::ostream &out) { out << "(thrift:def-package :" << package(); if ( includes.size() > 0 ) { out << " :use ("; - for (size_t i = 0; i < includes.size(); ++i) { - out << " :" << includes[i]->get_name(); + for (auto include : includes) { + out << " :" << include->get_name(); } out << ")"; } diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc index 617ba7ec864..dca3167df2d 100644 --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc @@ -101,25 +101,25 @@ class t_cpp_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; - void generate_consts(std::vector consts); + void generate_consts(std::vector consts) override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; void generate_enum_ostream_operator_decl(std::ostream& out, t_enum* tenum); void generate_enum_ostream_operator(std::ostream& out, t_enum* tenum); - void generate_forward_declaration(t_struct* tstruct); - void generate_struct(t_struct* tstruct) { generate_cpp_struct(tstruct, false); } - void generate_xception(t_struct* txception) { generate_cpp_struct(txception, true); } + void generate_forward_declaration(t_struct* tstruct) override; + void generate_struct(t_struct* tstruct) override { generate_cpp_struct(tstruct, false); } + void generate_xception(t_struct* txception) override { generate_cpp_struct(txception, true); } void generate_cpp_struct(t_struct* tstruct, bool is_exception); - void generate_service(t_service* tservice); + void generate_service(t_service* tservice) override; void print_const_value(std::ostream& out, std::string name, t_type* type, t_const_value* value); std::string render_const_value(std::ostream& out, @@ -424,24 +424,24 @@ void t_cpp_generator::init_generator() { // Include other Thrift includes const vector& includes = program_->get_includes(); - for (size_t i = 0; i < includes.size(); ++i) { - f_types_ << "#include \"" << get_include_prefix(*(includes[i])) << includes[i]->get_name() + for (auto include : includes) { + f_types_ << "#include \"" << get_include_prefix(*include) << include->get_name() << "_types.h\"" << endl; // XXX(simpkins): If gen_templates_ is enabled, we currently assume all // included files were also generated with templates enabled. - f_types_tcc_ << "#include \"" << get_include_prefix(*(includes[i])) << includes[i]->get_name() + f_types_tcc_ << "#include \"" << get_include_prefix(*include) << include->get_name() << "_types.tcc\"" << endl; } f_types_ << endl; // Include custom headers const vector& cpp_includes = program_->get_cpp_includes(); - for (size_t i = 0; i < cpp_includes.size(); ++i) { - if (cpp_includes[i][0] == '<') { - f_types_ << "#include " << cpp_includes[i] << endl; + for (const auto & cpp_include : cpp_includes) { + if (cpp_include[0] == '<') { + f_types_ << "#include " << cpp_include << endl; } else { - f_types_ << "#include \"" << cpp_includes[i] << "\"" << endl; + f_types_ << "#include \"" << cpp_include << "\"" << endl; } } f_types_ << endl; @@ -1238,7 +1238,6 @@ void t_cpp_generator::generate_struct_definition(ostream& out, if (setters) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { if (is_reference((*m_iter))) { - std::string type = type_name((*m_iter)->get_type()); out << endl << indent() << "void " << tstruct->get_name() << "::__set_" << (*m_iter)->get_name() << "(::std::shared_ptr<" << type_name((*m_iter)->get_type(), false, false) << ">"; @@ -1538,9 +1537,7 @@ void t_cpp_generator::generate_struct_swap(ostream& out, t_struct* tstruct) { bool has_nonrequired_fields = false; const vector& fields = tstruct->get_members(); - for (vector::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - t_field* tfield = *f_iter; - + for (auto tfield : fields) { if (tfield->get_req() != t_field::T_REQUIRED) { has_nonrequired_fields = true; } diff --git a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc index 6e99a3e68cd..e4d99b2cc1a 100644 --- a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc @@ -89,17 +89,17 @@ class t_csharp_generator : public t_oop_generator { out_dir_base_ = "gen-csharp"; } - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; - void generate_consts(std::vector consts); + void generate_consts(std::vector consts) override; - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_struct(t_struct* tstruct); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_struct(t_struct* tstruct) override; void generate_union(t_struct* tunion); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; void generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset); void generate_csharp_property(ostream& out, t_field* tfield, @@ -207,7 +207,7 @@ class t_csharp_generator : public t_oop_generator { std::string argument_list(t_struct* tstruct); std::string type_to_enum(t_type* ttype); std::string prop_name(t_field* tfield, bool suppress_mapping = false); - std::string get_enum_class_name(t_type* type); + std::string get_enum_class_name(t_type* type) override; bool field_has_default(t_field* tfield) { return tfield->get_value() != NULL; } diff --git a/compiler/cpp/src/thrift/generate/t_d_generator.cc b/compiler/cpp/src/thrift/generate/t_d_generator.cc index df56cfc03d5..56519e410f3 100644 --- a/compiler/cpp/src/thrift/generate/t_d_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_d_generator.cc @@ -71,7 +71,7 @@ class t_d_generator : public t_oop_generator { } protected: - virtual void init_generator() { + void init_generator() override { // Make output directory MKDIR(get_out_dir().c_str()); @@ -102,20 +102,20 @@ class t_d_generator : public t_oop_generator { // Include type modules from other imported programs. const vector& includes = program_->get_includes(); - for (size_t i = 0; i < includes.size(); ++i) { - f_types_ << "public import " << render_package(*(includes[i])) << includes[i]->get_name() + for (auto include : includes) { + f_types_ << "public import " << render_package(*include) << include->get_name() << "_types;" << endl; } if (!includes.empty()) f_types_ << endl; } - virtual void close_generator() { + void close_generator() override { // Close output file f_types_.close(); } - virtual void generate_consts(std::vector consts) { + void generate_consts(std::vector consts) override { if (!consts.empty()) { string f_consts_name = package_dir_ + program_name_ + "_constants.d"; ofstream_with_content_based_conditional_update f_consts; @@ -159,13 +159,13 @@ class t_d_generator : public t_oop_generator { } } - virtual void generate_typedef(t_typedef* ttypedef) { + void generate_typedef(t_typedef* ttypedef) override { this->emit_doc(ttypedef, f_types_); f_types_ << indent() << "alias " << render_type_name(ttypedef->get_type()) << " " << ttypedef->get_symbolic() << ";" << endl << endl; } - virtual void generate_enum(t_enum* tenum) { + void generate_enum(t_enum* tenum) override { vector constants = tenum->get_constants(); this->emit_doc(tenum, f_types_); @@ -188,15 +188,15 @@ class t_d_generator : public t_oop_generator { f_types_ << endl; } - virtual void generate_struct(t_struct* tstruct) { + void generate_struct(t_struct* tstruct) override { print_struct_definition(f_types_, tstruct, false); } - virtual void generate_xception(t_struct* txception) { + void generate_xception(t_struct* txception) override { print_struct_definition(f_types_, txception, true); } - virtual void generate_service(t_service* tservice) { + void generate_service(t_service* tservice) override { string svc_name = tservice->get_name(); // Service implementation file includes diff --git a/compiler/cpp/src/thrift/generate/t_dart_generator.cc b/compiler/cpp/src/thrift/generate/t_dart_generator.cc index c82d26c1017..fbbb9e6d3c5 100644 --- a/compiler/cpp/src/thrift/generate/t_dart_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_dart_generator.cc @@ -121,25 +121,25 @@ class t_dart_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; void export_class_to_library(string file_name, string class_name); void generate_dart_library(); void generate_dart_pubspec(); - void generate_consts(std::vector consts); + void generate_consts(std::vector consts) override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; void print_const_value(std::ostream& out, std::string name, @@ -359,8 +359,8 @@ string t_dart_generator::dart_thrift_imports() { // add imports for included thrift files const vector& includes = program_->get_includes(); - for (size_t i = 0; i < includes.size(); ++i) { - string include_name = find_library_name(includes[i]); + for (auto include : includes) { + string include_name = find_library_name(include); string named_import = "t_" + include_name; if (package_prefix_.empty()) { imports += "import 'package:" + include_name + "/" + include_name + ".dart' as " + named_import + ";" + endl; @@ -438,15 +438,15 @@ void t_dart_generator::generate_dart_pubspec() { indent_down(); } else { const vector lines = split(pubspec_lib_, '|'); - for (size_t line_index = 0; line_index < lines.size(); line_index++) { - indent(f_pubspec) << lines[line_index] << endl; + for (const auto & line : lines) { + indent(f_pubspec) << line << endl; } } // add included thrift files as dependencies const vector& includes = program_->get_includes(); - for (size_t i = 0; i < includes.size(); ++i) { - string include_name = find_library_name(includes[i]); + for (auto include : includes) { + string include_name = find_library_name(include); indent(f_pubspec) << include_name << ":" << endl; indent_up(); indent(f_pubspec) << "path: ../" << include_name << endl; @@ -2432,9 +2432,7 @@ string t_dart_generator::constant_name(string name) { bool is_first = true; bool was_previous_char_upper = false; - for (string::iterator iter = name.begin(); iter != name.end(); ++iter) { - string::value_type character = (*iter); - + for (char character : name) { bool is_upper = isupper(character); if (is_upper && !is_first && !was_previous_char_upper) { diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc index 737aa5aaab7..505120e40c2 100644 --- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc @@ -89,17 +89,17 @@ class t_delphi_generator : public t_oop_generator { escape_['\''] = "''"; } - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; - void generate_consts(std::vector consts); + void generate_consts(std::vector consts) override; - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_forward_declaration(t_struct* tstruct); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_forward_declaration(t_struct* tstruct) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; void generate_property(ostream& out, t_field* tfield, bool isPublic, bool is_xception); void generate_property_writer_(ostream& out, t_field* tfield, bool isPublic); @@ -343,7 +343,7 @@ class t_delphi_generator : public t_oop_generator { void write_struct(std::string line); void write_service(std::string line); - virtual std::string autogen_comment() { + std::string autogen_comment() override { return std::string("(**\n") + " * Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + " *\n" + " * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + " *)\n"; @@ -757,9 +757,9 @@ void t_delphi_generator::init_generator() { string unitname, nsname; const vector& includes = program_->get_includes(); - for (size_t i = 0; i < includes.size(); ++i) { - unitname = includes[i]->get_name(); - nsname = includes[i]->get_namespace("delphi"); + for (auto include : includes) { + unitname = include->get_name(); + nsname = include->get_namespace("delphi"); if ("" != nsname) { unitname = normalize_name(nsname); } @@ -786,7 +786,7 @@ void t_delphi_generator::close_generator() { std::string f_name = get_out_dir() + "/" + unitname + ".pas"; ofstream_with_content_based_conditional_update f_all; - f_all.open(f_name.c_str()); + f_all.open(f_name); f_all << autogen_comment() << endl; generate_delphi_doc(f_all, program_); diff --git a/compiler/cpp/src/thrift/generate/t_erl_generator.cc b/compiler/cpp/src/thrift/generate/t_erl_generator.cc index d4fe12c3160..d331eccc3fc 100644 --- a/compiler/cpp/src/thrift/generate/t_erl_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_erl_generator.cc @@ -83,19 +83,19 @@ class t_erl_generator : public t_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; void generate_member_type(std::ostream& out, t_type* type); void generate_member_value(std::ostream& out, t_type* type, t_const_value* value); @@ -310,8 +310,8 @@ void t_erl_generator::hrl_footer(ostream& out, string name) { string t_erl_generator::render_includes() { const vector& includes = program_->get_includes(); string result = ""; - for (size_t i = 0; i < includes.size(); ++i) { - result += "-include(\"" + make_safe_for_module_name(includes[i]->get_name()) + for (auto include : includes) { + result += "-include(\"" + make_safe_for_module_name(include->get_name()) + "_types.hrl\").\n"; } if (includes.size() > 0) { diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index 11246f36247..66bb65301f3 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -105,19 +105,19 @@ class t_go_generator : public t_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value, const string& name, bool opt = false); @@ -743,10 +743,10 @@ void t_go_generator::init_generator() { // Make output files f_types_name_ = package_dir_ + "/" + program_name_ + ".go"; - f_types_.open(f_types_name_.c_str()); + f_types_.open(f_types_name_); f_consts_name_ = package_dir_ + "/" + program_name_ + "-consts.go"; - f_consts_.open(f_consts_name_.c_str()); + f_consts_.open(f_consts_name_); // Print header f_types_ << go_autogen_comment() << go_package() << render_includes(false); @@ -771,12 +771,12 @@ string t_go_generator::render_included_programs(string& unused_protection) { unused_protection = ""; string local_namespace = program_->get_namespace("go"); - for (size_t i = 0; i < includes.size(); ++i) { - if (!local_namespace.empty() && local_namespace == includes[i]->get_namespace("go")) { + for (auto include : includes) { + if (!local_namespace.empty() && local_namespace == include->get_namespace("go")) { continue; } - string go_module = get_real_go_module(includes[i]); + string go_module = get_real_go_module(include); size_t found = 0; for (size_t j = 0; j < go_module.size(); j++) { // Import statement uses slashes ('/') in namespace @@ -803,12 +803,12 @@ string t_go_generator::render_includes(bool consts) { string unused_prot = ""; string local_namespace = program_->get_namespace("go"); - for (size_t i = 0; i < includes.size(); ++i) { - if (!local_namespace.empty() && local_namespace == includes[i]->get_namespace("go")) { + for (auto include : includes) { + if (!local_namespace.empty() && local_namespace == include->get_namespace("go")) { continue; } - string go_module = get_real_go_module(includes[i]); + string go_module = get_real_go_module(include); size_t found = 0; for (size_t j = 0; j < go_module.size(); j++) { // Import statement uses slashes ('/') in namespace @@ -1255,15 +1255,14 @@ void t_go_generator::generate_go_struct_initializer(ostream& out, bool is_args_or_result) { out << publicize(type_name(tstruct), is_args_or_result) << "{"; const vector& members = tstruct->get_members(); - for (vector::const_iterator m_iter = members.begin(); m_iter != members.end(); - ++m_iter) { - bool pointer_field = is_pointer_field(*m_iter); + for (auto member : members) { + bool pointer_field = is_pointer_field(member); string publicized_name; t_const_value* def_value; - get_publicized_name_and_def_value(*m_iter, &publicized_name, &def_value); - if (!pointer_field && def_value != NULL && !omit_initialization(*m_iter)) { + get_publicized_name_and_def_value(member, &publicized_name, &def_value); + if (!pointer_field && def_value != NULL && !omit_initialization(member)) { out << endl << indent() << publicized_name << ": " - << render_field_initial_value(*m_iter, (*m_iter)->get_name(), pointer_field) << "," + << render_field_initial_value(member, member->get_name(), pointer_field) << "," << endl; } } diff --git a/compiler/cpp/src/thrift/generate/t_gv_generator.cc b/compiler/cpp/src/thrift/generate/t_gv_generator.cc index 7f8301a1844..2c0acf979bf 100644 --- a/compiler/cpp/src/thrift/generate/t_gv_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_gv_generator.cc @@ -67,17 +67,17 @@ class t_gv_generator : public t_generator { /** * Init and end of generator */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_service(t_service* tservice) override; protected: /** diff --git a/compiler/cpp/src/thrift/generate/t_haxe_generator.cc b/compiler/cpp/src/thrift/generate/t_haxe_generator.cc index 3b88c4da79b..13f2cd1ba78 100644 --- a/compiler/cpp/src/thrift/generate/t_haxe_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_haxe_generator.cc @@ -74,20 +74,20 @@ class t_haxe_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; - void generate_consts(std::vector consts); + void generate_consts(std::vector consts) override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; void print_const_value(std::ostream& out, std::string name, @@ -190,7 +190,7 @@ class t_haxe_generator : public t_oop_generator { std::string function_signature_normal(t_function* tfunction); std::string argument_list(t_struct* tstruct); std::string type_to_enum(t_type* ttype); - std::string get_enum_class_name(t_type* type); + std::string get_enum_class_name(t_type* type) override; string generate_service_method_onsuccess(t_function* tfunction, bool as_type, bool omit_name); void generate_service_method_signature_callback(t_function* tfunction, bool is_interface); void generate_service_method_signature_normal(t_function* tfunction, bool is_interface); @@ -2884,9 +2884,7 @@ string t_haxe_generator::constant_name(string name) { bool is_first = true; bool was_previous_char_upper = false; - for (string::iterator iter = name.begin(); iter != name.end(); ++iter) { - string::value_type character = (*iter); - + for (char character : name) { bool is_upper = isupper(character); if (is_upper && !is_first && !was_previous_char_upper) { diff --git a/compiler/cpp/src/thrift/generate/t_hs_generator.cc b/compiler/cpp/src/thrift/generate/t_hs_generator.cc index 8f6d4b0c731..a59dee5d2d4 100644 --- a/compiler/cpp/src/thrift/generate/t_hs_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_hs_generator.cc @@ -66,18 +66,18 @@ class t_hs_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; string render_const_value(t_type* type, t_const_value* value); @@ -261,8 +261,8 @@ string t_hs_generator::hs_imports() { "import qualified Thrift.Arbitraries as T\n" "\n"); - for (size_t i = 0; i < includes.size(); ++i) - result += "import qualified " + capitalize(includes[i]->get_name()) + "_Types\n"; + for (auto include : includes) + result += "import qualified " + capitalize(include->get_name()) + "_Types\n"; if (includes.size() > 0) result += "\n"; @@ -407,14 +407,13 @@ string t_hs_generator::render_const_value(t_type* type, t_const_value* value) { } else if (type->is_enum()) { t_enum* tenum = (t_enum*)type; vector constants = tenum->get_constants(); - for (vector::iterator c_iter = constants.begin(); c_iter != constants.end(); - ++c_iter) { - int val = (*c_iter)->get_value(); + for (auto & constant : constants) { + int val = constant->get_value(); if (val == value->get_integer()) { t_program* prog = type->get_program(); if (prog != NULL && prog != program_) out << capitalize(prog->get_name()) << "_Types."; - out << capitalize((*c_iter)->get_name()); + out << capitalize(constant->get_name()); break; } } @@ -427,21 +426,18 @@ string t_hs_generator::render_const_value(t_type* type, t_const_value* value) { const map& val = value->get_map(); bool first = true; - for (map::const_iterator v_iter = val.begin(); - v_iter != val.end(); - ++v_iter) { + for (auto v_iter : val) { t_field* field = NULL; - for (vector::const_iterator f_iter = fields.begin(); f_iter != fields.end(); - ++f_iter) - if ((*f_iter)->get_name() == v_iter->first->get_string()) - field = (*f_iter); + for (auto f_iter : fields) + if (f_iter->get_name() == v_iter.first->get_string()) + field = f_iter; if (field == NULL) - throw "type error: " + cname + " has no field " + v_iter->first->get_string(); + throw "type error: " + cname + " has no field " + v_iter.first->get_string(); - string fname = v_iter->first->get_string(); - string const_value = render_const_value(field->get_type(), v_iter->second); + string fname = v_iter.first->get_string(); + string const_value = render_const_value(field->get_type(), v_iter.second); out << (first ? "" : ", "); out << field_name(cname, fname) << " = "; @@ -543,21 +539,20 @@ void t_hs_generator::generate_hs_struct_definition(ostream& out, if (members.size() > 0) { indent_up(); bool first = true; - for (vector::const_iterator m_iter = members.begin(); m_iter != members.end(); - ++m_iter) { + for (auto member : members) { if (first) { indent(out) << "{ "; first = false; } else { indent(out) << ", "; } - string mname = (*m_iter)->get_name(); + string mname = member->get_name(); out << field_name(tname, mname) << " :: "; - if ((*m_iter)->get_req() == t_field::T_OPTIONAL - || ((t_type*)(*m_iter)->get_type())->is_xception()) { + if (member->get_req() == t_field::T_OPTIONAL + || ((t_type*)member->get_type())->is_xception()) { out << "P.Maybe "; } - out << render_hs_type((*m_iter)->get_type(), true) << endl; + out << render_hs_type(member->get_type(), true) << endl; } indent(out) << "}"; indent_down(); @@ -571,9 +566,8 @@ void t_hs_generator::generate_hs_struct_definition(ostream& out, indent(out) << "instance H.Hashable " << tname << " where" << endl; indent_up(); indent(out) << "hashWithSalt salt record = salt"; - for (vector::const_iterator m_iter = members.begin(); m_iter != members.end(); - ++m_iter) { - string mname = (*m_iter)->get_name(); + for (auto member : members) { + string mname = member->get_name(); indent(out) << " `H.hashWithSalt` " << field_name(tname, mname) << " record"; } indent(out) << endl; @@ -600,8 +594,7 @@ void t_hs_generator::generate_hs_struct_arbitrary(ostream& out, t_struct* tstruc indent_up(); indent_up(); bool first = true; - for (vector::const_iterator m_iter = members.begin(); m_iter != members.end(); - ++m_iter) { + for (auto member : members) { if (first) { first = false; out << " "; @@ -609,8 +602,8 @@ void t_hs_generator::generate_hs_struct_arbitrary(ostream& out, t_struct* tstruc indent(out) << "`M.ap`"; } out << "("; - if ((*m_iter)->get_req() == t_field::T_OPTIONAL - || ((t_type*)(*m_iter)->get_type())->is_xception()) { + if (member->get_req() == t_field::T_OPTIONAL + || ((t_type*)member->get_type())->is_xception()) { out << "M.liftM P.Just "; } out << "QC.arbitrary)" << endl; @@ -625,15 +618,14 @@ void t_hs_generator::generate_hs_struct_arbitrary(ostream& out, t_struct* tstruc indent(out) << " | P.otherwise = M.catMaybes" << endl; indent_up(); first = true; - for (vector::const_iterator m_iter = members.begin(); m_iter != members.end(); - ++m_iter) { + for (auto member : members) { if (first) { first = false; indent(out) << "[ "; } else { indent(out) << ", "; } - string fname = field_name(tname, (*m_iter)->get_name()); + string fname = field_name(tname, member->get_name()); out << "if obj == default_" << tname; out << "{" << fname << " = " << fname << " obj} "; out << "then P.Nothing "; @@ -665,10 +657,10 @@ void t_hs_generator::generate_hs_struct_reader(ostream& out, t_struct* tstruct) bool first = true; // Generate deserialization code for known cases - for (vector::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - int32_t key = (*f_iter)->get_key(); - string etype = type_to_enum((*f_iter)->get_type()); - string fname = (*f_iter)->get_name(); + for (auto field : fields) { + int32_t key = field->get_key(); + string etype = type_to_enum(field->get_type()); + string fname = field->get_name(); if (first) { first = false; @@ -680,11 +672,11 @@ void t_hs_generator::generate_hs_struct_reader(ostream& out, t_struct* tstruct) indent(out) << field_name(sname, fname) << " = "; out << "P.maybe ("; - if ((*f_iter)->get_req() == t_field::T_REQUIRED) { + if (field->get_req() == t_field::T_REQUIRED) { out << "P.error \"Missing required field: " << fname << "\""; } else { - if (((*f_iter)->get_req() == t_field::T_OPTIONAL - || ((t_type*)(*f_iter)->get_type())->is_xception()) && (*f_iter)->get_value() == NULL) { + if ((field->get_req() == t_field::T_OPTIONAL + || ((t_type*)field->get_type())->is_xception()) && field->get_value() == NULL) { out << "P.Nothing"; } else { out << field_name(sname, fname) << " default_" << sname; @@ -693,10 +685,10 @@ void t_hs_generator::generate_hs_struct_reader(ostream& out, t_struct* tstruct) out << ") "; out << "(\\(_," << val << ") -> "; - if ((*f_iter)->get_req() == t_field::T_OPTIONAL - || ((t_type*)(*f_iter)->get_type())->is_xception()) + if (field->get_req() == t_field::T_OPTIONAL + || ((t_type*)field->get_type())->is_xception()) out << "P.Just "; - generate_deserialize_field(out, *f_iter, val); + generate_deserialize_field(out, field, val); out << ")"; out << " (Map.lookup (" << key << ") fields)"; } @@ -733,8 +725,8 @@ void t_hs_generator::generate_hs_struct_writer(ostream& out, t_struct* tstruct) // Get Exceptions bool hasExn = false; - for (vector::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (((t_type*)(*f_iter)->get_type())->is_xception()) { + for (auto field : fields) { + if (((t_type*)field->get_type())->is_xception()) { hasExn = true; break; } @@ -745,19 +737,18 @@ void t_hs_generator::generate_hs_struct_writer(ostream& out, t_struct* tstruct) out << endl; indent(out) << "(let exns = M.catMaybes "; indent_up(); - for (vector::const_iterator f_iter = fields.begin(); f_iter != fields.end(); - ++f_iter) { - if (((t_type*)(*f_iter)->get_type())->is_xception()) { + for (auto field : fields) { + if (((t_type*)field->get_type())->is_xception()) { if (isfirst) { out << "[ "; isfirst = false; } else { out << ", "; } - string mname = (*f_iter)->get_name(); - int32_t key = (*f_iter)->get_key(); + string mname = field->get_name(); + int32_t key = field->get_key(); out << "(\\" << v << " -> (" << key << ", (\"" << mname << "\","; - generate_serialize_type(out, (*f_iter)->get_type(), v); + generate_serialize_type(out, field->get_type(), v); out << "))) <$> " << field_name(name, mname) << " record"; } } @@ -774,7 +765,7 @@ void t_hs_generator::generate_hs_struct_writer(ostream& out, t_struct* tstruct) out << "M.catMaybes" << endl; // Get the Rest isfirst = true; - for (vector::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + for (auto field : fields) { // Write field header if (isfirst) { indent(out) << "[ "; @@ -782,19 +773,19 @@ void t_hs_generator::generate_hs_struct_writer(ostream& out, t_struct* tstruct) } else { indent(out) << ", "; } - string mname = (*f_iter)->get_name(); - int32_t key = (*f_iter)->get_key(); + string mname = field->get_name(); + int32_t key = field->get_key(); out << "(\\"; out << v << " -> "; - if ((*f_iter)->get_req() != t_field::T_OPTIONAL - && !((t_type*)(*f_iter)->get_type())->is_xception()) { + if (field->get_req() != t_field::T_OPTIONAL + && !((t_type*)field->get_type())->is_xception()) { out << "P.Just "; } out << "(" << key << ", (\"" << mname << "\","; - generate_serialize_type(out, (*f_iter)->get_type(), v); + generate_serialize_type(out, field->get_type(), v); out << "))) "; - if ((*f_iter)->get_req() != t_field::T_OPTIONAL - && !((t_type*)(*f_iter)->get_type())->is_xception()) { + if (field->get_req() != t_field::T_OPTIONAL + && !((t_type*)field->get_type())->is_xception()) { out << "$"; } else { out << "<$>"; @@ -910,14 +901,14 @@ void t_hs_generator::generate_hs_typemap(ostream& out, t_struct* tstruct) { indent(out) << "typemap_" << name << " :: T.TypeMap" << endl; indent(out) << "typemap_" << name << " = Map.fromList ["; bool first = true; - for (vector::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - string mname = (*f_iter)->get_name(); + for (auto field : fields) { + string mname = field->get_name(); if (!first) { out << ","; } - t_type* type = get_true_type((*f_iter)->get_type()); - int32_t key = (*f_iter)->get_key(); + t_type* type = get_true_type(field->get_type()); + int32_t key = field->get_key(); out << "(" << key << ",(\"" << mname << "\"," << type_to_enum(type) << "))"; first = false; } @@ -937,19 +928,19 @@ void t_hs_generator::generate_hs_default(ostream& out, t_struct* tstruct) { indent(out) << fname << " = " << name << "{" << endl; indent_up(); bool first = true; - for (vector::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - string mname = (*f_iter)->get_name(); + for (auto field : fields) { + string mname = field->get_name(); if (first) { first = false; } else { out << "," << endl; } - t_type* type = get_true_type((*f_iter)->get_type()); - t_const_value* value = (*f_iter)->get_value(); + t_type* type = get_true_type(field->get_type()); + t_const_value* value = field->get_value(); indent(out) << field_name(name, mname) << " = "; - if ((*f_iter)->get_req() == t_field::T_OPTIONAL - || ((t_type*)(*f_iter)->get_type())->is_xception()) { + if (field->get_req() == t_field::T_OPTIONAL + || ((t_type*)field->get_type())->is_xception()) { if (value == NULL) { out << "P.Nothing"; } else { @@ -1087,13 +1078,12 @@ void t_hs_generator::generate_service_client(t_service* tservice) { indent(f_client_) << "write_" << argsname << " op (" << argsname << "{"; bool first = true; - for (vector::const_iterator fld_iter = fields.begin(); fld_iter != fields.end(); - ++fld_iter) { - string fieldname = (*fld_iter)->get_name(); + for (auto field : fields) { + string fieldname = field->get_name(); f_client_ << (first ? "" : ","); f_client_ << field_name(argsname, fieldname) << "="; - if ((*fld_iter)->get_req() == t_field::T_OPTIONAL - || ((t_type*)(*fld_iter)->get_type())->is_xception()) + if (field->get_req() == t_field::T_OPTIONAL + || ((t_type*)field->get_type())->is_xception()) f_client_ << "P.Just "; f_client_ << "arg_" << fieldname; first = false; @@ -1123,10 +1113,9 @@ void t_hs_generator::generate_service_client(t_service* tservice) { t_struct* xs = (*f_iter)->get_xceptions(); const vector& xceptions = xs->get_members(); - for (vector::const_iterator x_iter = xceptions.begin(); x_iter != xceptions.end(); - ++x_iter) { + for (auto xception : xceptions) { indent(f_client_) << "P.maybe (P.return ()) X.throw (" - << field_name(resultname, (*x_iter)->get_name()) << " res)" << endl; + << field_name(resultname, xception->get_name()) << " res)" << endl; } if (!(*f_iter)->get_returntype()->is_void()) @@ -1499,11 +1488,11 @@ string t_hs_generator::function_type(t_function* tfunc, bool options, bool io, b string result = ""; const vector& fields = tfunc->get_arglist()->get_members(); - for (vector::const_iterator f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if ((*f_iter)->get_req() == t_field::T_OPTIONAL - || ((t_type*)(*f_iter)->get_type())->is_xception()) + for (auto field : fields) { + if (field->get_req() == t_field::T_OPTIONAL + || ((t_type*)field->get_type())->is_xception()) result += "P.Maybe "; - result += render_hs_type((*f_iter)->get_type(), options); + result += render_hs_type(field->get_type(), options); result += " -> "; } diff --git a/compiler/cpp/src/thrift/generate/t_html_generator.cc b/compiler/cpp/src/thrift/generate/t_html_generator.cc index 00c9a0a9dce..b61a712e380 100644 --- a/compiler/cpp/src/thrift/generate/t_html_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_html_generator.cc @@ -82,7 +82,7 @@ class t_html_generator : public t_generator { init_allowed__markup(); } - void generate_program(); + void generate_program() override; void generate_program_toc(); void generate_program_toc_row(t_program* tprog); void generate_program_toc_rows(t_program* tprog, std::vector& finished); @@ -101,12 +101,12 @@ class t_html_generator : public t_generator { * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_service(t_service* tservice); - void generate_xception(t_struct* txception); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_service(t_service* tservice) override; + void generate_xception(t_struct* txception) override; void print_doc(t_doc* tdoc); int print_type(t_type* ttype); @@ -140,16 +140,16 @@ void t_html_generator::generate_program_toc() { */ void t_html_generator::generate_program_toc_rows(t_program* tprog, std::vector& finished) { - for (vector::iterator iter = finished.begin(); iter != finished.end(); iter++) { - if (tprog->get_path() == (*iter)->get_path()) { + for (auto & iter : finished) { + if (tprog->get_path() == iter->get_path()) { return; } } finished.push_back(tprog); generate_program_toc_row(tprog); vector includes = tprog->get_includes(); - for (vector::iterator iter = includes.begin(); iter != includes.end(); iter++) { - generate_program_toc_rows(*iter, finished); + for (auto & include : includes) { + generate_program_toc_rows(include, finished); } } @@ -176,9 +176,8 @@ void t_html_generator::generate_program_toc_row(t_program* tprog) { + "\">" + fn_name + ""; fn_html.insert(pair(fn_name, html)); } - for (map::iterator html_iter = fn_html.begin(); html_iter != fn_html.end(); - html_iter++) { - f_out_ << html_iter->second << endl; + for (auto & html_iter : fn_html) { + f_out_ << html_iter.second << endl; } f_out_ << "" << endl; } @@ -220,9 +219,8 @@ void t_html_generator::generate_program_toc_row(t_program* tprog) { data_types.insert(pair(name, html)); } } - for (map::iterator dt_iter = data_types.begin(); dt_iter != data_types.end(); - dt_iter++) { - f_out_ << dt_iter->second << "
" << endl; + for (auto & data_type : data_types) { + f_out_ << data_type.second << "
" << endl; } f_out_ << "" << endl << ""; if (!tprog->get_consts().empty()) { @@ -235,9 +233,8 @@ void t_html_generator::generate_program_toc_row(t_program* tprog) { + ""; const_html.insert(pair(name, html)); } - for (map::iterator con_iter = const_html.begin(); con_iter != const_html.end(); - con_iter++) { - f_out_ << con_iter->second << "
" << endl; + for (auto & con_iter : const_html) { + f_out_ << con_iter.second << "
" << endl; } } f_out_ << "" << endl << ""; @@ -572,8 +569,8 @@ std::string t_html_generator::escape_html_tags(std::string const& str) { if (first_white != string::npos) { tag_key.erase(first_white); } - for (std::string::size_type i = 0; i < tag_key.length(); ++i) { - tag_key[i] = tolower(tag_key[i]); + for (char & i : tag_key) { + i = tolower(i); } if (allowed_markup.find(tag_key) != allowed_markup.end()) { result << "<" << tag_content << ">"; diff --git a/compiler/cpp/src/thrift/generate/t_java_generator.cc b/compiler/cpp/src/thrift/generate/t_java_generator.cc index 2c845512ccb..2fb1f1aeb1d 100644 --- a/compiler/cpp/src/thrift/generate/t_java_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_java_generator.cc @@ -122,21 +122,21 @@ class t_java_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; - void generate_consts(std::vector consts); + void generate_consts(std::vector consts) override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_struct(t_struct* tstruct); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_struct(t_struct* tstruct) override; void generate_union(t_struct* tunion); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; void print_const_value(std::ostream& out, std::string name, @@ -4652,9 +4652,7 @@ string t_java_generator::constant_name(string name) { bool is_first = true; bool was_previous_char_upper = false; - for (string::iterator iter = name.begin(); iter != name.end(); ++iter) { - string::value_type character = (*iter); - + for (char character : name) { bool is_upper = isupper(character); if (is_upper && !is_first && !was_previous_char_upper) { diff --git a/compiler/cpp/src/thrift/generate/t_javame_generator.cc b/compiler/cpp/src/thrift/generate/t_javame_generator.cc index fa743ca3d38..e1694abdf24 100644 --- a/compiler/cpp/src/thrift/generate/t_javame_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_javame_generator.cc @@ -65,21 +65,21 @@ class t_javame_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; - void generate_consts(std::vector consts); + void generate_consts(std::vector consts) override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_struct(t_struct* tstruct); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_struct(t_struct* tstruct) override; void generate_union(t_struct* tunion); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; void print_const_value(std::ostream& out, std::string name, @@ -185,13 +185,13 @@ class t_javame_generator : public t_oop_generator { void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); - void generate_java_doc(std::ostream& out, t_field* field); + void generate_java_doc(std::ostream& out, t_field* field) override; - void generate_java_doc(std::ostream& out, t_doc* tdoc); + void generate_java_doc(std::ostream& out, t_doc* tdoc) override; - void generate_java_doc(std::ostream& out, t_function* tdoc); + void generate_java_doc(std::ostream& out, t_function* tdoc) override; - void generate_java_docstring_comment(std::ostream& out, string contents); + void generate_java_docstring_comment(std::ostream& out, string contents) override; void generate_deep_copy_container(std::ostream& out, std::string source_name_p1, @@ -221,7 +221,7 @@ class t_javame_generator : public t_oop_generator { std::string function_signature(t_function* tfunction, std::string prefix = ""); std::string argument_list(t_struct* tstruct, bool include_types = true); std::string type_to_enum(t_type* ttype); - std::string get_enum_class_name(t_type* type); + std::string get_enum_class_name(t_type* type) override; void generate_struct_desc(ostream& out, t_struct* tstruct); void generate_field_descs(ostream& out, t_struct* tstruct); std::string box_type(t_type* type, string value); @@ -2980,9 +2980,7 @@ string t_javame_generator::constant_name(string name) { bool is_first = true; bool was_previous_char_upper = false; - for (string::iterator iter = name.begin(); iter != name.end(); ++iter) { - string::value_type character = (*iter); - + for (char character : name) { bool is_upper = isupper(character); if (is_upper && !is_first && !was_previous_char_upper) { diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc index e7f625c8588..af402a439de 100644 --- a/compiler/cpp/src/thrift/generate/t_js_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc @@ -121,19 +121,19 @@ class t_js_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; std::string render_recv_throw(std::string var); std::string render_recv_return(std::string var); @@ -215,7 +215,7 @@ class t_js_generator : public t_oop_generator { std::string type_to_enum(t_type* ttype); std::string make_valid_nodeJs_identifier(std::string const& name); - std::string autogen_comment() { + std::string autogen_comment() override { return std::string("//\n") + "// Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "//\n" + "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "//\n"; @@ -499,8 +499,8 @@ string t_js_generator::render_includes() { if (gen_node_) { const vector& includes = program_->get_includes(); - for (size_t i = 0; i < includes.size(); ++i) { - result += js_const_type_ + make_valid_nodeJs_identifier(includes[i]->get_name()) + "_ttypes = require('./" + includes[i]->get_name() + for (auto include : includes) { + result += js_const_type_ + make_valid_nodeJs_identifier(include->get_name()) + "_ttypes = require('./" + include->get_name() + "_types');\n"; } if (includes.size() > 0) { @@ -521,8 +521,8 @@ string t_js_generator::render_ts_includes() { return result; } const vector& includes = program_->get_includes(); - for (size_t i = 0; i < includes.size(); ++i) { - result += "import " + make_valid_nodeJs_identifier(includes[i]->get_name()) + "_ttypes = require('./" + includes[i]->get_name() + for (auto include : includes) { + result += "import " + make_valid_nodeJs_identifier(include->get_name()) + "_ttypes = require('./" + include->get_name() + "_types');\n"; } if (includes.size() > 0) { @@ -1440,8 +1440,8 @@ void t_js_generator::generate_process_function(t_service* tservice, t_function* t_struct* exceptions = tfunction->get_xceptions(); if (exceptions) { const vector& members = exceptions->get_members(); - for (vector::const_iterator it = members.begin(); it != members.end(); ++it) { - t_type* t = get_true_type((*it)->get_type()); + for (auto member : members) { + t_type* t = get_true_type(member->get_type()); if (t->is_xception()) { if (!has_exception) { has_exception = true; @@ -1504,8 +1504,8 @@ void t_js_generator::generate_process_function(t_service* tservice, t_function* indent(f_service_) << "if ((err === null || typeof err === 'undefined')"; if (has_exception) { const vector& members = exceptions->get_members(); - for (vector::const_iterator it = members.begin(); it != members.end(); ++it) { - t_type* t = get_true_type((*it)->get_type()); + for (auto member : members) { + t_type* t = get_true_type(member->get_type()); if (t->is_xception()) { f_service_ << " || err instanceof " << js_type_namespace(t->get_program()) << t->get_name(); } diff --git a/compiler/cpp/src/thrift/generate/t_json_generator.cc b/compiler/cpp/src/thrift/generate/t_json_generator.cc index cd5361274c8..eb4ef790be8 100644 --- a/compiler/cpp/src/thrift/generate/t_json_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_json_generator.cc @@ -68,23 +68,23 @@ class t_json_generator : public t_generator { out_dir_base_ = "gen-json"; } - virtual ~t_json_generator() {} + ~t_json_generator() override = default; /** * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_program(); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_program() override; void generate_function(t_function* tfunc); void generate_field(t_field* field); - void generate_service(t_service* tservice); - void generate_struct(t_struct* tstruct); + void generate_service(t_service* tservice) override; + void generate_struct(t_struct* tstruct) override; private: bool should_merge_includes_; @@ -147,8 +147,8 @@ void t_json_generator::init_generator() { string t_json_generator::escape_json_string(const string& input) { std::ostringstream ss; - for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) { - switch (*iter) { + for (char iter : input) { + switch (iter) { case '\\': ss << "\\\\"; break; @@ -174,7 +174,7 @@ string t_json_generator::escape_json_string(const string& input) { ss << "\\t"; break; default: - ss << *iter; + ss << iter; break; } } @@ -267,8 +267,8 @@ void t_json_generator::write_type_spec(t_type* ttype) { if (ttype->annotations_.size() > 0) { write_key_and("annotations"); start_object(); - for (map::iterator it = ttype->annotations_.begin(); it != ttype->annotations_.end(); ++it) { - write_key_and_string(it->first, it->second); + for (auto & annotation : ttype->annotations_) { + write_key_and_string(annotation.first, annotation.second); } end_object(); } @@ -457,8 +457,8 @@ void t_json_generator::generate_typedef(t_typedef* ttypedef) { if (ttypedef->annotations_.size() > 0) { write_key_and("annotations"); start_object(); - for (map::iterator it = ttypedef->annotations_.begin(); it != ttypedef->annotations_.end(); ++it) { - write_key_and_string(it->first, it->second); + for (auto & annotation : ttypedef->annotations_) { + write_key_and_string(annotation.first, annotation.second); } end_object(); } @@ -564,8 +564,8 @@ void t_json_generator::generate_enum(t_enum* tenum) { if (tenum->annotations_.size() > 0) { write_key_and("annotations"); start_object(); - for (map::iterator it = tenum->annotations_.begin(); it != tenum->annotations_.end(); ++it) { - write_key_and_string(it->first, it->second); + for (auto & annotation : tenum->annotations_) { + write_key_and_string(annotation.first, annotation.second); } end_object(); } @@ -603,8 +603,8 @@ void t_json_generator::generate_struct(t_struct* tstruct) { if (tstruct->annotations_.size() > 0) { write_key_and("annotations"); start_object(); - for (map::iterator it = tstruct->annotations_.begin(); it != tstruct->annotations_.end(); ++it) { - write_key_and_string(it->first, it->second); + for (auto & annotation : tstruct->annotations_) { + write_key_and_string(annotation.first, annotation.second); } end_object(); } @@ -643,8 +643,8 @@ void t_json_generator::generate_service(t_service* tservice) { if (tservice->annotations_.size() > 0) { write_key_and("annotations"); start_object(); - for (map::iterator it = tservice->annotations_.begin(); it != tservice->annotations_.end(); ++it) { - write_key_and_string(it->first, it->second); + for (auto & annotation : tservice->annotations_) { + write_key_and_string(annotation.first, annotation.second); } end_object(); } @@ -680,8 +680,8 @@ void t_json_generator::generate_function(t_function* tfunc) { if (tfunc->annotations_.size() > 0) { write_key_and("annotations"); start_object(); - for (map::iterator it = tfunc->annotations_.begin(); it != tfunc->annotations_.end(); ++it) { - write_key_and_string(it->first, it->second); + for (auto & annotation : tfunc->annotations_) { + write_key_and_string(annotation.first, annotation.second); } end_object(); } @@ -726,8 +726,8 @@ void t_json_generator::generate_field(t_field* field) { if (field->annotations_.size() > 0) { write_key_and("annotations"); start_object(); - for (map::iterator it = field->annotations_.begin(); it != field->annotations_.end(); ++it) { - write_key_and_string(it->first, it->second); + for (auto & annotation : field->annotations_) { + write_key_and_string(annotation.first, annotation.second); } end_object(); } diff --git a/compiler/cpp/src/thrift/generate/t_lua_generator.cc b/compiler/cpp/src/thrift/generate/t_lua_generator.cc index adee8968a69..e6432c89835 100644 --- a/compiler/cpp/src/thrift/generate/t_lua_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_lua_generator.cc @@ -56,18 +56,18 @@ class t_lua_generator : public t_oop_generator { /** * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value); @@ -149,7 +149,7 @@ class t_lua_generator : public t_oop_generator { std::string type_to_enum(t_type* ttype); static std::string get_namespace(const t_program* program); - std::string autogen_comment() { + std::string autogen_comment() override { return std::string("--\n") + "-- Autogenerated by Thrift\n" + "--\n" + "-- DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "-- @" "generated\n" diff --git a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc b/compiler/cpp/src/thrift/generate/t_netcore_generator.cc index 6f346a3d7c6..1a5c3842f2d 100644 --- a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netcore_generator.cc @@ -2734,7 +2734,7 @@ void t_netcore_generator::prepare_member_name_mapping(t_struct* tstruct) void t_netcore_generator::prepare_member_name_mapping(void* scope, const vector& members, const string& structname) { // begin new scope - member_mapping_scopes.push_back(member_mapping_scope()); + member_mapping_scopes.emplace_back(); member_mapping_scope& active = member_mapping_scopes.back(); active.scope_member = scope; diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index 8cb302736a6..593bb645a4f 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -2719,7 +2719,7 @@ void t_netstd_generator::prepare_member_name_mapping(t_struct* tstruct) void t_netstd_generator::prepare_member_name_mapping(void* scope, const vector& members, const string& structname) { // begin new scope - member_mapping_scopes.push_back(member_mapping_scope()); + member_mapping_scopes.emplace_back(); member_mapping_scope& active = member_mapping_scopes.back(); active.scope_member = scope; diff --git a/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc b/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc index 0ec81ba5eb5..a3781e8ee0f 100644 --- a/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_ocaml_generator.cc @@ -65,19 +65,19 @@ class t_ocaml_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_program(); - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_program() override; + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value); bool struct_member_persistent(t_field* tmember); diff --git a/compiler/cpp/src/thrift/generate/t_perl_generator.cc b/compiler/cpp/src/thrift/generate/t_perl_generator.cc index 8924a76001b..80729cbfde0 100644 --- a/compiler/cpp/src/thrift/generate/t_perl_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_perl_generator.cc @@ -66,19 +66,19 @@ class t_perl_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value); @@ -152,7 +152,7 @@ class t_perl_generator : public t_oop_generator { std::string argument_list(t_struct* tstruct); std::string type_to_enum(t_type* ttype); - std::string autogen_comment() { + std::string autogen_comment() override { return std::string("#\n") + "# Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "#\n" + "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" + "#\n"; } diff --git a/compiler/cpp/src/thrift/generate/t_php_generator.cc b/compiler/cpp/src/thrift/generate/t_php_generator.cc index 50a44155173..79bd5a28328 100644 --- a/compiler/cpp/src/thrift/generate/t_php_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_php_generator.cc @@ -99,7 +99,7 @@ class t_php_generator : public t_oop_generator { escape_['$'] = "\\$"; } - virtual std::string indent_str() const { + std::string indent_str() const override { return " "; } @@ -109,19 +109,19 @@ class t_php_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_consts(vector consts); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_consts(vector consts) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value); @@ -284,9 +284,9 @@ class t_php_generator : public t_oop_generator { } // Transform the java-style namespace into a path. - for (std::string::iterator it = ns.begin(); it != ns.end(); ++it) { - if (*it == '.') { - *it = '/'; + for (char & n : ns) { + if (n == '.') { + n = '/'; } } @@ -304,8 +304,8 @@ class t_php_generator : public t_oop_generator { vector x = split(str, '_'); - for (size_t i = 0; i < x.size(); ++i) { - classe = classe + capitalize(x[i]); + for (const auto & i : x) { + classe = classe + capitalize(i); } return classe; @@ -420,8 +420,8 @@ void t_php_generator::init_generator() { vector NSx = split(php_namespace_suffix(get_program()), '\\'); package_dir_ = get_out_dir(); - for (size_t i = 0; i < NSx.size(); ++i) { - package_dir_ = package_dir_ + "/" + NSx[i] + "/"; + for (const auto & i : NSx) { + package_dir_ = package_dir_ + "/" + i + "/"; MKDIR(package_dir_.c_str()); } diff --git a/compiler/cpp/src/thrift/generate/t_py_generator.cc b/compiler/cpp/src/thrift/generate/t_py_generator.cc index e46207a7c7a..c16d6d3ae9a 100644 --- a/compiler/cpp/src/thrift/generate/t_py_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_py_generator.cc @@ -136,7 +136,7 @@ class t_py_generator : public t_generator { } } - virtual std::string indent_str() const { + std::string indent_str() const override { return " "; } @@ -144,20 +144,20 @@ class t_py_generator : public t_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_forward_declaration(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_forward_declaration(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; std::string render_const_value(t_type* type, t_const_value* value); @@ -335,7 +335,7 @@ class t_py_generator : public t_generator { std::string module_; protected: - virtual std::set lang_keywords() const { + std::set lang_keywords() const override { std::string keywords[] = { "False", "None", "True", "and", "as", "assert", "break", "class", "continue", "def", "del", "elif", "else", "except", "exec", "finally", "for", "from", "global", "if", "import", "in", "is", "lambda", "nonlocal", "not", "or", "pass", "print", @@ -415,8 +415,8 @@ void t_py_generator::init_generator() { string t_py_generator::render_includes() { const vector& includes = program_->get_includes(); string result = ""; - for (size_t i = 0; i < includes.size(); ++i) { - result += "import " + get_real_py_module(includes[i], gen_twisted_, package_prefix_) + ".ttypes\n"; + for (auto include : includes) { + result += "import " + get_real_py_module(include, gen_twisted_, package_prefix_) + ".ttypes\n"; } return result; } @@ -2607,7 +2607,7 @@ string t_py_generator::function_signature(t_function* tfunction, bool interface) string signature = tfunction->get_name() + "("; if (!(gen_zope_interface_ && interface)) { - pre.push_back("self"); + pre.emplace_back("self"); } signature += argument_list(tfunction->get_arglist(), &pre, &post) + ")"; diff --git a/compiler/cpp/src/thrift/generate/t_rb_generator.cc b/compiler/cpp/src/thrift/generate/t_rb_generator.cc index 13ea2490ebd..61c34811d9a 100644 --- a/compiler/cpp/src/thrift/generate/t_rb_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_rb_generator.cc @@ -102,21 +102,21 @@ class t_rb_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_forward_declaration(t_struct* tstruct); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_forward_declaration(t_struct* tstruct) override; void generate_union(t_struct* tunion); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; t_rb_ofstream& render_const_value(t_rb_ofstream& out, t_type* type, t_const_value* value); @@ -307,15 +307,15 @@ string t_rb_generator::render_require_thrift() { string t_rb_generator::render_includes() { const vector& includes = program_->get_includes(); string result = ""; - for (size_t i = 0; i < includes.size(); ++i) { + for (auto include : includes) { if (namespaced_) { - t_program* included = includes[i]; + t_program* included = include; std::string included_require_prefix = rb_namespace_to_path_prefix(included->get_namespace("rb")); std::string included_name = included->get_name(); result += "require '" + included_require_prefix + underscore(included_name) + "_types'\n"; } else { - result += "require '" + underscore(includes[i]->get_name()) + "_types'\n"; + result += "require '" + underscore(include->get_name()) + "_types'\n"; } } if (includes.size() > 0) { @@ -763,8 +763,8 @@ void t_rb_generator::generate_field_data(t_rb_ofstream& out, } void t_rb_generator::begin_namespace(t_rb_ofstream& out, vector modules) { - for (vector::iterator m_iter = modules.begin(); m_iter != modules.end(); ++m_iter) { - out.indent() << "module " << *m_iter << endl; + for (auto & module : modules) { + out.indent() << "module " << module << endl; out.indent_up(); } } @@ -1140,8 +1140,8 @@ string t_rb_generator::type_name(const t_type* ttype) { string t_rb_generator::full_type_name(const t_type* ttype) { string prefix = "::"; vector modules = ruby_modules(ttype->get_program()); - for (vector::iterator m_iter = modules.begin(); m_iter != modules.end(); ++m_iter) { - prefix += *m_iter + "::"; + for (auto & module : modules) { + prefix += module + "::"; } return prefix + type_name(ttype); } diff --git a/compiler/cpp/src/thrift/generate/t_rs_generator.cc b/compiler/cpp/src/thrift/generate/t_rs_generator.cc index 9843d7acb9f..fdf6861635c 100644 --- a/compiler/cpp/src/thrift/generate/t_rs_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_rs_generator.cc @@ -74,19 +74,19 @@ class t_rs_generator : public t_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; private: // struct type @@ -3285,8 +3285,8 @@ string t_rs_generator::rust_sync_processor_impl_name(t_service *tservice) { string t_rs_generator::rust_enum_variant_name(const string &name) { bool all_uppercase = true; - for (size_t i = 0; i < name.size(); i++) { - if (isalnum(name[i]) && islower(name[i])) { + for (char i : name) { + if (isalnum(i) && islower(i)) { all_uppercase = false; break; } diff --git a/compiler/cpp/src/thrift/generate/t_st_generator.cc b/compiler/cpp/src/thrift/generate/t_st_generator.cc index 595a9497d59..bc95feb66af 100644 --- a/compiler/cpp/src/thrift/generate/t_st_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_st_generator.cc @@ -71,19 +71,19 @@ class t_st_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_const(t_const* tconst); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_const(t_const* tconst) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; void generate_class_side_definition(); void generate_force_consts(); @@ -233,9 +233,9 @@ string t_st_generator::generated_category() { string cat = program_->get_namespace("smalltalk.category"); // For compatibility with the Thrift grammar, the category must // be punctuated by dots. Replaces them with dashes here. - for (string::iterator iter = cat.begin(); iter != cat.end(); ++iter) { - if (*iter == '.') { - *iter = '-'; + for (char & iter : cat) { + if (iter == '.') { + iter = '-'; } } return cat.size() ? cat : "Generated-" + class_name(); diff --git a/compiler/cpp/src/thrift/generate/t_swift_generator.cc b/compiler/cpp/src/thrift/generate/t_swift_generator.cc index 31db04dbabd..eb746c10966 100644 --- a/compiler/cpp/src/thrift/generate/t_swift_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_swift_generator.cc @@ -94,20 +94,20 @@ class t_swift_generator : public t_oop_generator { * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; - void generate_consts(vector consts); + void generate_consts(vector consts) override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; + void generate_struct(t_struct* tstruct) override; + void generate_xception(t_struct* txception) override; + void generate_service(t_service* tservice) override; void render_const_value(ostream& out, @@ -336,7 +336,7 @@ void t_swift_generator::init_generator() { string t_swift_generator::swift_imports() { vector includes_list; - includes_list.push_back("Foundation"); + includes_list.emplace_back("Foundation"); ostringstream includes; @@ -347,8 +347,8 @@ string t_swift_generator::swift_imports() { if (namespaced_) { const vector& program_includes = program_->get_includes(); - for (size_t i = 0; i < program_includes.size(); ++i) { - includes << ("import " + get_real_swift_module(program_includes[i])) << endl; + for (auto program_include : program_includes) { + includes << ("import " + get_real_swift_module(program_include)) << endl; } } includes << endl; @@ -364,10 +364,10 @@ string t_swift_generator::swift_imports() { string t_swift_generator::swift_thrift_imports() { vector includes_list; - includes_list.push_back("Thrift"); + includes_list.emplace_back("Thrift"); if (gen_cocoa_ && promise_kit_) { - includes_list.push_back("PromiseKit"); + includes_list.emplace_back("PromiseKit"); } ostringstream includes; diff --git a/compiler/cpp/src/thrift/generate/t_xml_generator.cc b/compiler/cpp/src/thrift/generate/t_xml_generator.cc index 35fed14d84c..b6692938f61 100644 --- a/compiler/cpp/src/thrift/generate/t_xml_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_xml_generator.cc @@ -79,20 +79,20 @@ class t_xml_generator : public t_generator { out_dir_base_ = "gen-xml"; } - virtual ~t_xml_generator() {} + ~t_xml_generator() override = default; - void init_generator(); - void close_generator(); - void generate_program(); + void init_generator() override; + void close_generator() override; + void generate_program() override; void iterate_program(t_program* program); - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override; void generate_function(t_function* tfunc); void generate_field(t_field* field); - void generate_service(t_service* tservice); - void generate_struct(t_struct* tstruct); + void generate_service(t_service* tservice) override; + void generate_struct(t_struct* tstruct) override; void generate_annotations(std::map annotations); @@ -245,8 +245,8 @@ void t_xml_generator::write_element_string(string name, string val) { string t_xml_generator::escape_xml_string(const string& input) { std::ostringstream ss; - for (std::string::const_iterator iter = input.begin(); iter != input.end(); iter++) { - switch (*iter) { + for (char iter : input) { + switch (iter) { case '&': ss << "&"; break; @@ -263,7 +263,7 @@ string t_xml_generator::escape_xml_string(const string& input) { ss << ">"; break; default: - ss << *iter; + ss << iter; break; } } diff --git a/compiler/cpp/src/thrift/generate/t_xsd_generator.cc b/compiler/cpp/src/thrift/generate/t_xsd_generator.cc index e487ffca3bb..379e5a4485a 100644 --- a/compiler/cpp/src/thrift/generate/t_xsd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_xsd_generator.cc @@ -59,24 +59,24 @@ class t_xsd_generator : public t_generator { out_dir_base_ = "gen-xsd"; } - virtual ~t_xsd_generator() {} + ~t_xsd_generator() override = default; /** * Init and close methods */ - void init_generator(); - void close_generator(); + void init_generator() override; + void close_generator() override; /** * Program-level generation functions */ - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum) { (void)tenum; } + void generate_typedef(t_typedef* ttypedef) override; + void generate_enum(t_enum* tenum) override { (void)tenum; } - void generate_service(t_service* tservice); - void generate_struct(t_struct* tstruct); + void generate_service(t_service* tservice) override; + void generate_struct(t_struct* tstruct) override; private: void generate_element(std::ostream& out, diff --git a/compiler/cpp/src/thrift/main.cc b/compiler/cpp/src/thrift/main.cc index adcab83c19e..5b69dc502ee 100644 --- a/compiler/cpp/src/thrift/main.cc +++ b/compiler/cpp/src/thrift/main.cc @@ -983,11 +983,11 @@ void generate(t_program* program, const vector& generator_strings) { // Oooohh, recursive code generation, hot!! if (gen_recurse) { const vector& includes = program->get_includes(); - for (size_t i = 0; i < includes.size(); ++i) { + for (auto include : includes) { // Propagate output path from parent to child programs - includes[i]->set_out_path(program->get_out_path(), program->is_out_path_absolute()); + include->set_out_path(program->get_out_path(), program->is_out_path_absolute()); - generate(includes[i], generator_strings); + generate(include, generator_strings); } } @@ -1110,7 +1110,7 @@ int main(int argc, char** argv) { fprintf(stderr, "Missing generator specification\n"); usage(); } - generator_strings.push_back(arg); + generator_strings.emplace_back(arg); } else if (strcmp(arg, "-I") == 0) { // An argument of "-I\ asdf" is invalid and has unknown results arg = argv[++i]; @@ -1119,7 +1119,7 @@ int main(int argc, char** argv) { fprintf(stderr, "Missing Include directory\n"); usage(); } - g_incl_searchpath.push_back(arg); + g_incl_searchpath.emplace_back(arg); } else if ((strcmp(arg, "-o") == 0) || (strcmp(arg, "-out") == 0)) { out_path_is_absolute = (strcmp(arg, "-out") == 0) ? true : false; arg = argv[++i]; diff --git a/compiler/cpp/src/thrift/parse/t_program.h b/compiler/cpp/src/thrift/parse/t_program.h index 8b60611f8b2..13cb26e5fa2 100644 --- a/compiler/cpp/src/thrift/parse/t_program.h +++ b/compiler/cpp/src/thrift/parse/t_program.h @@ -286,7 +286,6 @@ class t_program : public t_doc { if (language != "*") { size_t sub_index = language.find('.'); std::string base_language = language.substr(0, sub_index); - std::string sub_namespace; if (base_language == "smalltalk") { pwarning(1, "Namespace 'smalltalk' is deprecated. Use 'st' instead"); diff --git a/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.cpp b/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.cpp index 952394bca4f..0dac52458d6 100644 --- a/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.cpp +++ b/lib/cpp/src/thrift/async/TConcurrentClientSyncInfo.cpp @@ -17,10 +17,11 @@ * under the License. */ -#include +#include +#include #include +#include #include -#include namespace apache { namespace thrift { namespace async { @@ -140,15 +141,15 @@ void TConcurrentClientSyncInfo::markBad_(const Guard &) { wakeupSomeone_ = true; stop_ = true; - for(auto i = seqidToMonitorMap_.begin(); i != seqidToMonitorMap_.end(); ++i) - i->second->notify(); + for(auto & i : seqidToMonitorMap_) + i.second->notify(); } TConcurrentClientSyncInfo::MonitorPtr TConcurrentClientSyncInfo::newMonitor_(const Guard &) { if(freeMonitors_.empty()) - return MonitorPtr(new Monitor(&readMutex_)); + return std::make_shared(&readMutex_); MonitorPtr retval; //swapping to avoid an atomic operation retval.swap(freeMonitors_.back()); diff --git a/lib/cpp/src/thrift/concurrency/ThreadFactory.cpp b/lib/cpp/src/thrift/concurrency/ThreadFactory.cpp index 941b993712b..becb3b2447f 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadFactory.cpp +++ b/lib/cpp/src/thrift/concurrency/ThreadFactory.cpp @@ -27,7 +27,7 @@ namespace thrift { namespace concurrency { std::shared_ptr ThreadFactory::newThread(std::shared_ptr runnable) const { - std::shared_ptr result = std::shared_ptr(new Thread(isDetached(), runnable)); + std::shared_ptr result = std::make_shared(isDetached(), runnable); runnable->thread(result); return result; } diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp index c889660cfb3..25b838aefbc 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp +++ b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp @@ -344,7 +344,7 @@ void ThreadManager::Impl::addWorker(size_t value) { std::set > newThreads; for (size_t ix = 0; ix < value; ix++) { shared_ptr worker - = shared_ptr(new ThreadManager::Worker(this)); + = std::make_shared(this); newThreads.insert(threadFactory_->newThread(worker)); } @@ -352,13 +352,12 @@ void ThreadManager::Impl::addWorker(size_t value) { workerMaxCount_ += value; workers_.insert(newThreads.begin(), newThreads.end()); - for (auto ix = newThreads.begin(); ix != newThreads.end(); - ++ix) { + for (const auto & newThread : newThreads) { shared_ptr worker - = dynamic_pointer_cast((*ix)->runnable()); + = dynamic_pointer_cast(newThread->runnable()); worker->state_ = ThreadManager::Worker::STARTING; - (*ix)->start(); - idMap_.insert(std::pair >((*ix)->getId(), *ix)); + newThread->start(); + idMap_.insert(std::pair >(newThread->getId(), newThread)); } while (workerCount_ != workerMaxCount_) { @@ -430,17 +429,15 @@ void ThreadManager::Impl::removeWorkersUnderLock(size_t value) { workerMonitor_.wait(); } - for (auto ix = deadWorkers_.begin(); - ix != deadWorkers_.end(); - ++ix) { + for (const auto & deadWorker : deadWorkers_) { // when used with a joinable thread factory, we join the threads as we remove them if (!threadFactory_->isDetached()) { - (*ix)->join(); + deadWorker->join(); } - idMap_.erase((*ix)->getId()); - workers_.erase(*ix); + idMap_.erase(deadWorker->getId()); + workers_.erase(deadWorker); } deadWorkers_.clear(); @@ -480,7 +477,7 @@ void ThreadManager::Impl::add(shared_ptr value, int64_t timeout, int64 } } - tasks_.push_back(shared_ptr(new ThreadManager::Task(value, expiration))); + tasks_.push_back(std::make_shared(value, expiration)); // If idle thread is available notify it, otherwise all worker threads are // running and will get around to this task in time. diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.cpp b/lib/cpp/src/thrift/concurrency/TimerManager.cpp index df599009527..003f5647c94 100644 --- a/lib/cpp/src/thrift/concurrency/TimerManager.cpp +++ b/lib/cpp/src/thrift/concurrency/TimerManager.cpp @@ -22,6 +22,7 @@ #include #include +#include #include namespace apache { @@ -121,10 +122,8 @@ class TimerManager::Dispatcher : public Runnable { } } - for (auto ix = expiredTasks.begin(); - ix != expiredTasks.end(); - ++ix) { - (*ix)->run(); + for (const auto & expiredTask : expiredTasks) { + expiredTask->run(); } } while (manager_->state_ == TimerManager::STARTED); @@ -152,7 +151,7 @@ class TimerManager::Dispatcher : public Runnable { TimerManager::TimerManager() : taskCount_(0), state_(TimerManager::UNINITIALIZED), - dispatcher_(shared_ptr(new Dispatcher(this))) { + dispatcher_(std::make_shared(this)) { } #if defined(_MSC_VER) diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp index 35592f006c6..28d0da29918 100644 --- a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp +++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp @@ -20,8 +20,6 @@ #include #include -#include -#include #include #include @@ -537,9 +535,9 @@ uint32_t TJSONProtocol::writeJSONDouble(double num) { std::string val; bool special = false; - switch (boost::math::fpclassify(num)) { + switch (std::fpclassify(num)) { case FP_INFINITE: - if (boost::math::signbit(num)) { + if (std::signbit(num)) { val = kThriftNegativeInfinity; } else { val = kThriftInfinity; diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.h b/lib/cpp/src/thrift/protocol/TJSONProtocol.h index 020e61ce8e8..420995ef34d 100644 --- a/lib/cpp/src/thrift/protocol/TJSONProtocol.h +++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.h @@ -248,7 +248,7 @@ class TJSONProtocol : public TVirtualProtocol { class LookaheadReader { public: - LookaheadReader(TTransport& trans) : trans_(&trans), hasData_(false) {} + LookaheadReader(TTransport& trans) : trans_(&trans), hasData_(false), data_(0) {} uint8_t read() { if (hasData_) { diff --git a/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp b/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp index 78c3b399f57..1537fc60d92 100644 --- a/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp +++ b/lib/cpp/src/thrift/qt/TQIODeviceTransport.cpp @@ -46,7 +46,7 @@ void TQIODeviceTransport::open() { } } -bool TQIODeviceTransport::isOpen() { +bool TQIODeviceTransport::isOpen() const { return dev_->isOpen(); } diff --git a/lib/cpp/src/thrift/qt/TQIODeviceTransport.h b/lib/cpp/src/thrift/qt/TQIODeviceTransport.h index e0cdd1831be..a3b511def0c 100644 --- a/lib/cpp/src/thrift/qt/TQIODeviceTransport.h +++ b/lib/cpp/src/thrift/qt/TQIODeviceTransport.h @@ -40,7 +40,7 @@ class TQIODeviceTransport ~TQIODeviceTransport() override; void open() override; - bool isOpen(); + bool isOpen() const override; bool peek() override; void close() override; diff --git a/lib/cpp/src/thrift/qt/TQTcpServer.cpp b/lib/cpp/src/thrift/qt/TQTcpServer.cpp index bd39893e31e..04044823e56 100644 --- a/lib/cpp/src/thrift/qt/TQTcpServer.cpp +++ b/lib/cpp/src/thrift/qt/TQTcpServer.cpp @@ -90,7 +90,7 @@ void TQTcpServer::processIncoming() { } ctxMap_[connection.get()] - = shared_ptr(new ConnectionContext(connection, transport, iprot, oprot)); + = std::make_shared(connection, transport, iprot, oprot); connect(connection.get(), SIGNAL(readyRead()), SLOT(beginDecode())); diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.cpp b/lib/cpp/src/thrift/server/TNonblockingServer.cpp index 4e62324cb51..eea0427d253 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.cpp +++ b/lib/cpp/src/thrift/server/TNonblockingServer.cpp @@ -1074,8 +1074,8 @@ void TNonblockingServer::expireClose(std::shared_ptr task) { void TNonblockingServer::stop() { // Breaks the event loop in all threads so that they end ASAP. - for (uint32_t i = 0; i < ioThreads_.size(); ++i) { - ioThreads_[i]->stop(); + for (auto & ioThread : ioThreads_) { + ioThread->stop(); } } @@ -1162,10 +1162,13 @@ TNonblockingIOThread::TNonblockingIOThread(TNonblockingServer* server, bool useHighPriority) : server_(server), number_(number), + threadId_{}, listenSocket_(listenSocket), useHighPriority_(useHighPriority), eventBase_(nullptr), - ownEventBase_(false) { + ownEventBase_(false), + serverEvent_{}, + notificationEvent_{} { notificationPipeFDs_[0] = -1; notificationPipeFDs_[1] = -1; } @@ -1186,13 +1189,13 @@ TNonblockingIOThread::~TNonblockingIOThread() { listenSocket_ = THRIFT_INVALID_SOCKET; } - for (int i = 0; i < 2; ++i) { - if (notificationPipeFDs_[i] >= 0) { - if (0 != ::THRIFT_CLOSESOCKET(notificationPipeFDs_[i])) { + for (auto notificationPipeFD : notificationPipeFDs_) { + if (notificationPipeFD >= 0) { + if (0 != ::THRIFT_CLOSESOCKET(notificationPipeFD)) { GlobalOutput.perror("TNonblockingIOThread notificationPipe close(): ", THRIFT_GET_SOCKET_ERROR); } - notificationPipeFDs_[i] = THRIFT_INVALID_SOCKET; + notificationPipeFD = THRIFT_INVALID_SOCKET; } } } @@ -1208,13 +1211,13 @@ void TNonblockingIOThread::createNotificationPipe() { ::THRIFT_CLOSESOCKET(notificationPipeFDs_[1]); throw TException("TNonblockingServer::createNotificationPipe() THRIFT_O_NONBLOCK"); } - for (int i = 0; i < 2; ++i) { + for (auto notificationPipeFD : notificationPipeFDs_) { #if LIBEVENT_VERSION_NUMBER < 0x02000000 int flags; - if ((flags = THRIFT_FCNTL(notificationPipeFDs_[i], F_GETFD, 0)) < 0 - || THRIFT_FCNTL(notificationPipeFDs_[i], F_SETFD, flags | FD_CLOEXEC) < 0) { + if ((flags = THRIFT_FCNTL(notificationPipeFD, F_GETFD, 0)) < 0 + || THRIFT_FCNTL(notificationPipeFD, F_SETFD, flags | FD_CLOEXEC) < 0) { #else - if (evutil_make_socket_closeonexec(notificationPipeFDs_[i]) < 0) { + if (evutil_make_socket_closeonexec(notificationPipeFD) < 0) { #endif ::THRIFT_CLOSESOCKET(notificationPipeFDs_[0]); ::THRIFT_CLOSESOCKET(notificationPipeFDs_[1]); diff --git a/lib/cpp/src/thrift/transport/TBufferTransports.h b/lib/cpp/src/thrift/transport/TBufferTransports.h index a008fa19da8..df06586bd1e 100644 --- a/lib/cpp/src/thrift/transport/TBufferTransports.h +++ b/lib/cpp/src/thrift/transport/TBufferTransports.h @@ -217,7 +217,7 @@ class TBufferedTransport : public TVirtualTransportopen(); } - bool isOpen() { return transport_->isOpen(); } + bool isOpen() const override { return transport_->isOpen(); } bool peek() override { if (rBase_ == rBound_) { @@ -345,7 +345,7 @@ class TFramedTransport : public TVirtualTransport void open() override { transport_->open(); } - bool isOpen() { return transport_->isOpen(); } + bool isOpen() const override { return transport_->isOpen(); } bool peek() override { return (rBase_ < rBound_) || transport_->peek(); } @@ -550,7 +550,7 @@ class TMemoryBuffer : public TVirtualTransport { } } - bool isOpen() { return true; } + bool isOpen() const override { return true; } bool peek() override { return (rBase_ < wBase_); } diff --git a/lib/cpp/src/thrift/transport/TFDTransport.h b/lib/cpp/src/thrift/transport/TFDTransport.h index ede5ccb5bd0..a3cf519484c 100644 --- a/lib/cpp/src/thrift/transport/TFDTransport.h +++ b/lib/cpp/src/thrift/transport/TFDTransport.h @@ -53,7 +53,7 @@ class TFDTransport : public TVirtualTransport { } } - bool isOpen() { return fd_ >= 0; } + bool isOpen() const override { return fd_ >= 0; } void open() override {} diff --git a/lib/cpp/src/thrift/transport/TFileTransport.cpp b/lib/cpp/src/thrift/transport/TFileTransport.cpp index 1eefb899310..53e5136c053 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.cpp +++ b/lib/cpp/src/thrift/transport/TFileTransport.cpp @@ -977,7 +977,7 @@ TFileProcessor::TFileProcessor(shared_ptr processor, inputTransport_(inputTransport) { // default the output transport to a null transport (common case) - outputTransport_ = shared_ptr(new TNullTransport()); + outputTransport_ = std::make_shared(); } TFileProcessor::TFileProcessor(shared_ptr processor, @@ -990,7 +990,7 @@ TFileProcessor::TFileProcessor(shared_ptr processor, inputTransport_(inputTransport) { // default the output transport to a null transport (common case) - outputTransport_ = shared_ptr(new TNullTransport()); + outputTransport_ = std::make_shared(); } TFileProcessor::TFileProcessor(shared_ptr processor, diff --git a/lib/cpp/src/thrift/transport/THttpTransport.h b/lib/cpp/src/thrift/transport/THttpTransport.h index 1cf36b20680..75f0d8c070a 100644 --- a/lib/cpp/src/thrift/transport/THttpTransport.h +++ b/lib/cpp/src/thrift/transport/THttpTransport.h @@ -42,7 +42,7 @@ class THttpTransport : public TVirtualTransport { void open() override { transport_->open(); } - bool isOpen() { return transport_->isOpen(); } + bool isOpen() const override { return transport_->isOpen(); } bool peek() override { return transport_->peek(); } diff --git a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp index 51990b0e4e4..9902b9063c1 100644 --- a/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TNonblockingServerSocket.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #ifdef HAVE_SYS_SOCKET_H @@ -532,7 +533,7 @@ shared_ptr TNonblockingServerSocket::acceptImpl() { } shared_ptr TNonblockingServerSocket::createSocket(THRIFT_SOCKET clientSocket) { - return shared_ptr(new TSocket(clientSocket)); + return std::make_shared(clientSocket); } void TNonblockingServerSocket::close() { diff --git a/lib/cpp/src/thrift/transport/TPipeServer.cpp b/lib/cpp/src/thrift/transport/TPipeServer.cpp index 55c35800458..47d882251b5 100644 --- a/lib/cpp/src/thrift/transport/TPipeServer.cpp +++ b/lib/cpp/src/thrift/transport/TPipeServer.cpp @@ -333,8 +333,22 @@ bool TNamedPipeServer::createNamedPipe(const TAutoCrit & /*lockProof*/) { SetEntriesInAcl(1, &ea, NULL, &acl); PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); - InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); - SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE); + if (!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION)) { + auto lastError = GetLastError(); + LocalFree(sd); + LocalFree(acl); + GlobalOutput.perror("TPipeServer::InitializeSecurityDescriptor() GLE=", lastError); + throw TTransportException(TTransportException::NOT_OPEN, "InitializeSecurityDescriptor() failed", + lastError); + } + if (!SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE)) { + auto lastError = GetLastError(); + LocalFree(sd); + LocalFree(acl); + GlobalOutput.perror("TPipeServer::SetSecurityDescriptorDacl() GLE=", lastError); + throw TTransportException(TTransportException::NOT_OPEN, + "SetSecurityDescriptorDacl() failed", lastError); + } SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(SECURITY_ATTRIBUTES); @@ -353,7 +367,7 @@ bool TNamedPipeServer::createNamedPipe(const TAutoCrit & /*lockProof*/) { 0, // client time-out &sa)); // security attributes - DWORD lastError = GetLastError(); + auto lastError = GetLastError(); LocalFree(sd); LocalFree(acl); FreeSid(everyone_sid); @@ -364,7 +378,6 @@ bool TNamedPipeServer::createNamedPipe(const TAutoCrit & /*lockProof*/) { throw TTransportException(TTransportException::NOT_OPEN, "TCreateNamedPipe() failed", lastError); - return false; } Pipe_.reset(hPipe.release()); @@ -375,8 +388,17 @@ bool TAnonPipeServer::createAnonPipe() { SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; // security information for pipes - InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); - SetSecurityDescriptorDacl(&sd, true, NULL, false); + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) + { + GlobalOutput.perror("TPipeServer InitializeSecurityDescriptor (anon) failed, GLE=", GetLastError()); + return false; + } + if (!SetSecurityDescriptorDacl(&sd, true, NULL, false)) + { + GlobalOutput.perror("TPipeServer SetSecurityDescriptorDacl (anon) failed, GLE=", + GetLastError()); + return false; + } sa.lpSecurityDescriptor = &sd; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = true; // allow passing handle to child diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp index 636bb2d7ef1..b413002f1f0 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp @@ -19,9 +19,10 @@ #include +#include #include +#include #include -#include #ifdef HAVE_ARPA_INET_H #include #endif @@ -266,7 +267,7 @@ void TSSLSocket::init() { eventSafe_ = false; } -bool TSSLSocket::isOpen() { +bool TSSLSocket::isOpen() const { if (ssl_ == nullptr || !TSocket::isOpen()) { return false; } @@ -291,11 +292,10 @@ bool TSSLSocket::peek() { if (!checkHandshake()) throw TSSLException("SSL_peek: Handshake is not completed"); int rc; - uint8_t byte; do { + uint8_t byte; rc = SSL_peek(ssl_, &byte, 1); if (rc < 0) { - int errno_copy = THRIFT_GET_SOCKET_ERROR; int error = SSL_get_error(ssl_, rc); switch (error) { @@ -318,6 +318,8 @@ bool TSSLSocket::peek() { } else if (rc == 0) { ERR_clear_error(); break; + } else { + break; } } while (true); return (rc > 0); @@ -857,7 +859,7 @@ TSSLSocketFactory::TSSLSocketFactory(SSLProtocol protocol) : server_(false) { randomize(); } count_++; - ctx_ = std::shared_ptr(new SSLContext(protocol)); + ctx_ = std::make_shared(protocol); } TSSLSocketFactory::~TSSLSocketFactory() { diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.h b/lib/cpp/src/thrift/transport/TSSLSocket.h index 4d46998c40a..87a9601476b 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.h +++ b/lib/cpp/src/thrift/transport/TSSLSocket.h @@ -73,7 +73,7 @@ class TSSLSocket : public TSocket { /** * TTransport interface. */ - bool isOpen(); + bool isOpen() const override; bool peek() override; void open() override; void close() override; diff --git a/lib/cpp/src/thrift/transport/TServerSocket.cpp b/lib/cpp/src/thrift/transport/TServerSocket.cpp index 1732c827234..ece05445a34 100644 --- a/lib/cpp/src/thrift/transport/TServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TServerSocket.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #ifdef HAVE_SYS_SOCKET_H @@ -641,9 +642,9 @@ shared_ptr TServerSocket::acceptImpl() { shared_ptr TServerSocket::createSocket(THRIFT_SOCKET clientSocket) { if (interruptableChildren_) { - return shared_ptr(new TSocket(clientSocket, pChildInterruptSockReader_)); + return std::make_shared(clientSocket, pChildInterruptSockReader_); } else { - return shared_ptr(new TSocket(clientSocket)); + return std::make_shared(clientSocket); } } diff --git a/lib/cpp/src/thrift/transport/TShortReadTransport.h b/lib/cpp/src/thrift/transport/TShortReadTransport.h index 2151606cf53..185c78dc7fe 100644 --- a/lib/cpp/src/thrift/transport/TShortReadTransport.h +++ b/lib/cpp/src/thrift/transport/TShortReadTransport.h @@ -41,7 +41,7 @@ class TShortReadTransport : public TVirtualTransport { TShortReadTransport(std::shared_ptr transport, double full_prob) : transport_(transport), fullProb_(full_prob) {} - bool isOpen() { return transport_->isOpen(); } + bool isOpen() const override { return transport_->isOpen(); } bool peek() override { return transport_->peek(); } diff --git a/lib/cpp/src/thrift/transport/TSocketPool.cpp b/lib/cpp/src/thrift/transport/TSocketPool.cpp index 89eee6edae3..b6e79d3f605 100644 --- a/lib/cpp/src/thrift/transport/TSocketPool.cpp +++ b/lib/cpp/src/thrift/transport/TSocketPool.cpp @@ -21,6 +21,7 @@ #include #include +#include #if __cplusplus >= 201703L #include #endif @@ -94,8 +95,8 @@ TSocketPool::TSocketPool(const vector >& servers) maxConsecutiveFailures_(1), randomize_(true), alwaysTryLast_(true) { - for (unsigned i = 0; i < servers.size(); ++i) { - addServer(servers[i].first, servers[i].second); + for (const auto & server : servers) { + addServer(server.first, server.second); } } @@ -129,7 +130,7 @@ TSocketPool::~TSocketPool() { } void TSocketPool::addServer(const string& host, int port) { - servers_.push_back(shared_ptr(new TSocketPoolServer(host, port))); + servers_.push_back(std::make_shared(host, port)); } void TSocketPool::addServer(shared_ptr& server) { diff --git a/lib/cpp/src/thrift/transport/TTransportUtils.h b/lib/cpp/src/thrift/transport/TTransportUtils.h index 6cff76a2cce..28c93d2a183 100644 --- a/lib/cpp/src/thrift/transport/TTransportUtils.h +++ b/lib/cpp/src/thrift/transport/TTransportUtils.h @@ -46,7 +46,7 @@ class TNullTransport : public TVirtualTransport { ~TNullTransport() override = default; - bool isOpen() { return true; } + bool isOpen() const override { return true; } void open() override {} diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.cpp b/lib/cpp/src/thrift/transport/TZlibTransport.cpp index ddceb9937c7..437190b2925 100644 --- a/lib/cpp/src/thrift/transport/TZlibTransport.cpp +++ b/lib/cpp/src/thrift/transport/TZlibTransport.cpp @@ -110,7 +110,7 @@ TZlibTransport::~TZlibTransport() { delete wstream_; } -bool TZlibTransport::isOpen() { +bool TZlibTransport::isOpen() const { return (readAvail() > 0) || (rstream_->avail_in > 0) || transport_->isOpen(); } @@ -131,7 +131,7 @@ bool TZlibTransport::peek() { // In standalone objects, we set input_ended_ to true when inflate returns // Z_STREAM_END. This allows to make sure that a checksum was verified. -inline int TZlibTransport::readAvail() { +inline int TZlibTransport::readAvail() const { return urbuf_size_ - rstream_->avail_out - urpos_; } diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.h b/lib/cpp/src/thrift/transport/TZlibTransport.h index be2d19898ae..29afae0d416 100644 --- a/lib/cpp/src/thrift/transport/TZlibTransport.h +++ b/lib/cpp/src/thrift/transport/TZlibTransport.h @@ -138,7 +138,7 @@ class TZlibTransport : public TVirtualTransport { */ ~TZlibTransport() override; - bool isOpen(); + bool isOpen() const override; bool peek() override; void open() override { transport_->open(); } @@ -185,7 +185,7 @@ class TZlibTransport : public TVirtualTransport { protected: inline void checkZlibRv(int status, const char* msg); inline void checkZlibRvNothrow(int status, const char* msg); - inline int readAvail(); + inline int readAvail() const; void flushToTransport(int flush); void flushToZlib(const uint8_t* buf, int len, int flush); bool readFromZlib(); diff --git a/lib/cpp/test/TBufferBaseTest.cpp b/lib/cpp/test/TBufferBaseTest.cpp index 430302cc2ad..7203f829bb2 100644 --- a/lib/cpp/test/TBufferBaseTest.cpp +++ b/lib/cpp/test/TBufferBaseTest.cpp @@ -165,8 +165,8 @@ void init_data() { // Repeatability. Kind of. std::srand(42); - for (size_t i = 0; i < (sizeof(data)/sizeof(data[0])); ++i) { - data[i] = (uint8_t)rand(); + for (unsigned char & i : data) { + i = (uint8_t)rand(); } data_str.assign((char*)data, sizeof(data)); @@ -178,14 +178,14 @@ BOOST_AUTO_TEST_SUITE( TBufferBaseTest ) BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_GetBuffer ) { init_data(); - for (int d1 = 0; d1 < 3; d1++) { + for (auto & d1 : dist) { TMemoryBuffer buffer(16); int offset = 0; int index = 0; while (offset < 1<<15) { - buffer.write(&data[offset], dist[d1][index]); - offset += dist[d1][index]; + buffer.write(&data[offset], d1[index]); + offset += d1[index]; index++; } @@ -197,8 +197,8 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_GetBuffer ) { BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read ) { init_data(); - for (int d1 = 0; d1 < 3; d1++) { - for (int d2 = 0; d2 < 3; d2++) { + for (auto & d1 : dist) { + for (auto & d2 : dist) { TMemoryBuffer buffer(16); uint8_t data_out[1<<15]; int offset; @@ -207,17 +207,17 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read ) { offset = 0; index = 0; while (offset < 1<<15) { - buffer.write(&data[offset], dist[d1][index]); - offset += dist[d1][index]; + buffer.write(&data[offset], d1[index]); + offset += d1[index]; index++; } offset = 0; index = 0; while (offset < 1<<15) { - unsigned int got = buffer.read(&data_out[offset], dist[d2][index]); - BOOST_CHECK_EQUAL(got, dist[d2][index]); - offset += dist[d2][index]; + unsigned int got = buffer.read(&data_out[offset], d2[index]); + BOOST_CHECK_EQUAL(got, d2[index]); + offset += d2[index]; index++; } @@ -229,8 +229,8 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read ) { BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_ReadString ) { init_data(); - for (int d1 = 0; d1 < 3; d1++) { - for (int d2 = 0; d2 < 3; d2++) { + for (auto & d1 : dist) { + for (auto & d2 : dist) { TMemoryBuffer buffer(16); string output; int offset; @@ -239,17 +239,17 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_ReadString ) { offset = 0; index = 0; while (offset < 1<<15) { - buffer.write(&data[offset], dist[d1][index]); - offset += dist[d1][index]; + buffer.write(&data[offset], d1[index]); + offset += d1[index]; index++; } offset = 0; index = 0; while (offset < 1<<15) { - unsigned int got = buffer.readAppendToString(output, dist[d2][index]); - BOOST_CHECK_EQUAL(got, dist[d2][index]); - offset += dist[d2][index]; + unsigned int got = buffer.readAppendToString(output, d2[index]); + BOOST_CHECK_EQUAL(got, d2[index]); + offset += d2[index]; index++; } @@ -263,8 +263,8 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Multi1 ) { // Do shorter writes and reads so we don't align to power-of-two boundaries. - for (int d1 = 0; d1 < 3; d1++) { - for (int d2 = 0; d2 < 3; d2++) { + for (auto & d1 : dist) { + for (auto & d2 : dist) { TMemoryBuffer buffer(16); uint8_t data_out[1<<15]; int offset; @@ -274,16 +274,16 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Multi1 ) { offset = 0; index = 0; while (offset < (1<<15)-42) { - buffer.write(&data[offset], dist[d1][index]); - offset += dist[d1][index]; + buffer.write(&data[offset], d1[index]); + offset += d1[index]; index++; } offset = 0; index = 0; while (offset < (1<<15)-42) { - buffer.read(&data_out[offset], dist[d2][index]); - offset += dist[d2][index]; + buffer.read(&data_out[offset], d2[index]); + offset += d2[index]; index++; } @@ -303,8 +303,8 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Multi2 ) { // Pull the buffer out of the loop so its state gets worked harder. TMemoryBuffer buffer(16); - for (int d1 = 0; d1 < 3; d1++) { - for (int d2 = 0; d2 < 3; d2++) { + for (auto & d1 : dist) { + for (auto & d2 : dist) { uint8_t data_out[1<<15]; int offset; int index; @@ -313,16 +313,16 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Multi2 ) { offset = 0; index = 0; while (offset < (1<<15)-42) { - buffer.write(&data[offset], dist[d1][index]); - offset += dist[d1][index]; + buffer.write(&data[offset], d1[index]); + offset += d1[index]; index++; } offset = 0; index = 0; while (offset < (1<<15)-42) { - buffer.read(&data_out[offset], dist[d2][index]); - offset += dist[d2][index]; + buffer.read(&data_out[offset], d2[index]); + offset += d2[index]; index++; } @@ -341,8 +341,8 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Incomplete ) { // Do shorter writes and reads so we don't align to power-of-two boundaries. // Pull the buffer out of the loop so its state gets worked harder. - for (int d1 = 0; d1 < 3; d1++) { - for (int d2 = 0; d2 < 3; d2++) { + for (auto & d1 : dist) { + for (auto & d2 : dist) { TMemoryBuffer buffer(16); uint8_t data_out[1<<13]; @@ -350,7 +350,7 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Incomplete ) { int write_index = 0; unsigned int to_write = (1<<14)-42; while (to_write > 0) { - int write_amt = (std::min)(dist[d1][write_index], to_write); + int write_amt = (std::min)(d1[write_index], to_write); buffer.write(&data[write_offset], write_amt); write_offset += write_amt; write_index++; @@ -361,7 +361,7 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Incomplete ) { int read_index = 0; unsigned int to_read = (1<<13)-42; while (to_read > 0) { - int read_amt = (std::min)(dist[d2][read_index], to_read); + int read_amt = (std::min)(d2[read_index], to_read); int got = buffer.read(&data_out[read_offset], read_amt); BOOST_CHECK_EQUAL(got, read_amt); read_offset += read_amt; @@ -375,7 +375,7 @@ BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Incomplete ) { int second_index = write_index-1; unsigned int to_second = (1<<14)+42; while (to_second > 0) { - int second_amt = (std::min)(dist[d1][second_index], to_second); + int second_amt = (std::min)(d1[second_index], to_second); //printf("%d\n", second_amt); buffer.write(&data[second_offset], second_amt); second_offset += second_amt; @@ -399,17 +399,16 @@ BOOST_AUTO_TEST_CASE( test_BufferedTransport_Write ) { 1<<14, 1<<17, }; - for (size_t i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++) { - int size = sizes[i]; - for (int d1 = 0; d1 < 3; d1++) { + for (int size : sizes) { + for (auto & d1 : dist) { shared_ptr buffer(new TMemoryBuffer(16)); TBufferedTransport trans(buffer, size); int offset = 0; int index = 0; while (offset < 1<<15) { - trans.write(&data[offset], dist[d1][index]); - offset += dist[d1][index]; + trans.write(&data[offset], d1[index]); + offset += d1[index]; index++; } trans.flush(); @@ -430,9 +429,8 @@ BOOST_AUTO_TEST_CASE( test_BufferedTransport_Read_Full ) { 1<<14, 1<<17, }; - for (size_t i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++) { - int size = sizes[i]; - for (int d1 = 0; d1 < 3; d1++) { + for (int size : sizes) { + for (auto & d1 : dist) { shared_ptr buffer(new TMemoryBuffer(data, sizeof(data))); TBufferedTransport trans(buffer, size); uint8_t data_out[1<<15]; @@ -443,8 +441,8 @@ BOOST_AUTO_TEST_CASE( test_BufferedTransport_Read_Full ) { // Note: this doesn't work with "read" because TBufferedTransport // doesn't try loop over reads, so we get short reads. We don't // check the return value, so that messes us up. - trans.readAll(&data_out[offset], dist[d1][index]); - offset += dist[d1][index]; + trans.readAll(&data_out[offset], d1[index]); + offset += d1[index]; index++; } @@ -463,9 +461,8 @@ BOOST_AUTO_TEST_CASE( test_BufferedTransport_Read_Short ) { 1<<14, 1<<17, }; - for (size_t i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++) { - int size = sizes[i]; - for (int d1 = 0; d1 < 3; d1++) { + for (int size : sizes) { + for (auto & d1 : dist) { shared_ptr buffer(new TMemoryBuffer(data, sizeof(data))); shared_ptr tshort(new TShortReadTransport(buffer, 0.125)); TBufferedTransport trans(buffer, size); @@ -477,8 +474,8 @@ BOOST_AUTO_TEST_CASE( test_BufferedTransport_Read_Short ) { // Note: this doesn't work with "read" because TBufferedTransport // doesn't try loop over reads, so we get short reads. We don't // check the return value, so that messes us up. - trans.readAll(&data_out[offset], dist[d1][index]); - offset += dist[d1][index]; + trans.readAll(&data_out[offset], d1[index]); + offset += d1[index]; index++; } @@ -497,17 +494,16 @@ BOOST_AUTO_TEST_CASE( test_FramedTransport_Write ) { 1<<14, 1<<17, }; - for (size_t i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++) { - int size = sizes[i]; - for (int d1 = 0; d1 < 3; d1++) { + for (int size : sizes) { + for (auto & d1 : dist) { shared_ptr buffer(new TMemoryBuffer(16)); TFramedTransport trans(buffer, size); int offset = 0; int index = 0; while (offset < 1<<15) { - trans.write(&data[offset], dist[d1][index]); - offset += dist[d1][index]; + trans.write(&data[offset], d1[index]); + offset += d1[index]; index++; } trans.flush(); @@ -526,7 +522,7 @@ BOOST_AUTO_TEST_CASE( test_FramedTransport_Write ) { BOOST_AUTO_TEST_CASE( test_FramedTransport_Read ) { init_data(); - for (int d1 = 0; d1 < 3; d1++) { + for (auto & d1 : dist) { uint8_t data_out[1<<15]; shared_ptr buffer(new TMemoryBuffer()); TFramedTransport trans(buffer); @@ -539,8 +535,8 @@ BOOST_AUTO_TEST_CASE( test_FramedTransport_Read ) { int index = 0; while (offset < 1<<15) { // This should work with read because we have one huge frame. - trans.read(&data_out[offset], dist[d1][index]); - offset += dist[d1][index]; + trans.read(&data_out[offset], d1[index]); + offset += d1[index]; index++; } @@ -560,11 +556,9 @@ BOOST_AUTO_TEST_CASE( test_FramedTransport_Write_Read ) { int probs[] = { 1, 2, 4, 8, 16, 32, }; - for (size_t i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++) { - int size = sizes[i]; - for (size_t j = 0; j < sizeof (probs) / sizeof (probs[0]); j++) { - int prob = probs[j]; - for (int d1 = 0; d1 < 3; d1++) { + for (int size : sizes) { + for (int prob : probs) { + for (auto & d1 : dist) { shared_ptr buffer(new TMemoryBuffer(16)); TFramedTransport trans(buffer, size); std::vector data_out(1<<17, 0); @@ -574,9 +568,9 @@ BOOST_AUTO_TEST_CASE( test_FramedTransport_Write_Read ) { int write_index = 0; int flush_size = 0; while (write_offset < 1<<15) { - trans.write(&data[write_offset], dist[d1][write_index]); - write_offset += dist[d1][write_index]; - flush_size += dist[d1][write_index]; + trans.write(&data[write_offset], d1[write_index]); + write_offset += d1[write_index]; + flush_size += d1[write_index]; write_index++; if (flush_size > 0 && rand()%prob == 0) { flush_sizes.push_back(flush_size); @@ -593,8 +587,7 @@ BOOST_AUTO_TEST_CASE( test_FramedTransport_Write_Read ) { int read_offset = 0; int read_index = 0; - for (unsigned int k = 0; k < flush_sizes.size(); k++) { - int fsize = flush_sizes[k]; + for (int fsize : flush_sizes) { // We are exploiting an implementation detail of TFramedTransport. // The read buffer starts empty and it will never do more than one // readFrame per read, so we should always get exactly one frame. diff --git a/lib/cpp/test/TFileTransportTest.cpp b/lib/cpp/test/TFileTransportTest.cpp index ad32185540d..21c1f3b3315 100644 --- a/lib/cpp/test/TFileTransportTest.cpp +++ b/lib/cpp/test/TFileTransportTest.cpp @@ -279,12 +279,12 @@ void test_flush_max_us_impl(uint32_t flush_us, uint32_t write_us, uint32_t test_ BOOST_WARN_GE(calls->size(), static_cast(1)); const struct timeval* prev_time = nullptr; - for (auto it = calls->begin(); it != calls->end(); ++it) { + for (const auto & call : *calls) { if (prev_time) { - int delta = time_diff(prev_time, &it->time); + int delta = time_diff(prev_time, &call.time); BOOST_WARN( delta < max_allowed_delta ); } - prev_time = &it->time; + prev_time = &call.time; } } diff --git a/lib/cpp/test/TMemoryBufferTest.cpp b/lib/cpp/test/TMemoryBufferTest.cpp index 92068729517..42f97112b3f 100644 --- a/lib/cpp/test/TMemoryBufferTest.cpp +++ b/lib/cpp/test/TMemoryBufferTest.cpp @@ -81,9 +81,9 @@ BOOST_AUTO_TEST_CASE(test_roundtrip) { } BOOST_AUTO_TEST_CASE(test_readAppendToString) { - string* str1 = new string("abcd1234"); - TMemoryBuffer buf((uint8_t*)str1->data(), - static_cast(str1->length()), + string str1 = "abcd1234"; + TMemoryBuffer buf((uint8_t*)str1.data(), + static_cast(str1.length()), TMemoryBuffer::COPY); string str3 = "wxyz", str4 = "6789"; diff --git a/lib/cpp/test/TNonblockingSSLServerTest.cpp b/lib/cpp/test/TNonblockingSSLServerTest.cpp index d0d86889623..dc40c125703 100644 --- a/lib/cpp/test/TNonblockingSSLServerTest.cpp +++ b/lib/cpp/test/TNonblockingSSLServerTest.cpp @@ -151,7 +151,7 @@ class Fixture { std::shared_ptr socket; Mutex mutex_; - Runner() { + Runner():port(0) { listenHandler.reset(new ListenEventHandler(&mutex_)); } diff --git a/lib/cpp/test/TNonblockingServerTest.cpp b/lib/cpp/test/TNonblockingServerTest.cpp index 434217e4884..f9aab4cc1b8 100644 --- a/lib/cpp/test/TNonblockingServerTest.cpp +++ b/lib/cpp/test/TNonblockingServerTest.cpp @@ -83,6 +83,7 @@ class Fixture { Mutex mutex_; Runner() { + port = 0; listenHandler.reset(new ListenEventHandler(&mutex_)); } diff --git a/lib/cpp/test/TServerTransportTest.cpp b/lib/cpp/test/TServerTransportTest.cpp index 15177a85085..18a393ee005 100644 --- a/lib/cpp/test/TServerTransportTest.cpp +++ b/lib/cpp/test/TServerTransportTest.cpp @@ -39,7 +39,7 @@ class TestTServerTransport : public TServerTransport { protected: shared_ptr acceptImpl() override { - return valid_ ? shared_ptr(new TestTTransport) + return valid_ ? std::make_shared() : shared_ptr(); } }; diff --git a/lib/cpp/test/TransportTest.cpp b/lib/cpp/test/TransportTest.cpp index b0c84b63f39..a890aa8ce3e 100644 --- a/lib/cpp/test/TransportTest.cpp +++ b/lib/cpp/test/TransportTest.cpp @@ -140,8 +140,8 @@ class CoupledTransports { std::shared_ptr out; private: - CoupledTransports(const CoupledTransports&); - CoupledTransports& operator=(const CoupledTransports&); + CoupledTransports(const CoupledTransports&) = delete; + CoupledTransports& operator=(const CoupledTransports&) = delete; }; /** diff --git a/lib/cpp/test/concurrency/Tests.cpp b/lib/cpp/test/concurrency/Tests.cpp index f2b0111e34c..8c734c2d5af 100644 --- a/lib/cpp/test/concurrency/Tests.cpp +++ b/lib/cpp/test/concurrency/Tests.cpp @@ -31,8 +31,6 @@ static int WEIGHT = 10; int main(int argc, char** argv) { - std::string arg; - std::vector args(argc - 1 > 1 ? argc - 1 : 1); args[0] = "all"; From 9804ab983a6c43dec56e0dcc4155cc2c21073822 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 7 Feb 2019 16:59:05 -0500 Subject: [PATCH 217/756] THRIFT-4780: finish the server implementation of multi in python server - Add default processor handling to python multi --- lib/py/src/TMultiplexedProcessor.py | 22 ++++- lib/py/src/protocol/__init__.py | 2 +- test/known_failures_Linux.json | 122 ++++++++++++++++++++++++++++ test/py/TestClient.py | 19 ++++- test/py/TestServer.py | 92 ++++++++++++++++++--- test/rs/src/bin/test_client.rs | 2 +- test/tests.json | 42 +++++----- 7 files changed, 260 insertions(+), 41 deletions(-) diff --git a/lib/py/src/TMultiplexedProcessor.py b/lib/py/src/TMultiplexedProcessor.py index 8d929ac389c..bd10d9b6acc 100644 --- a/lib/py/src/TMultiplexedProcessor.py +++ b/lib/py/src/TMultiplexedProcessor.py @@ -24,8 +24,18 @@ class TMultiplexedProcessor(TProcessor): def __init__(self): + self.defaultProcessor = None self.services = {} + def registerDefault(self, processor): + """ + If a non-multiplexed processor connects to the server and wants to + communicate, use the given processor to handle it. This mechanism + allows servers to upgrade from non-multiplexed to multiplexed in a + backwards-compatible way and still handle old clients. + """ + self.defaultProcessor = processor + def registerProcessor(self, serviceName, processor): self.services[serviceName] = processor @@ -38,10 +48,14 @@ def process(self, iprot, oprot): index = name.find(TMultiplexedProtocol.SEPARATOR) if index < 0: - raise TProtocolException( - TProtocolException.NOT_IMPLEMENTED, - "Service name not found in message name: " + name + ". " + - "Did you forget to use TMultiplexedProtocol in your client?") + if self.defaultProcessor: + return self.defaultProcessor.process( + StoredMessageProtocol(iprot, (name, type, seqid)), oprot) + else: + raise TProtocolException( + TProtocolException.NOT_IMPLEMENTED, + "Service name not found in message name: " + name + ". " + + "Did you forget to use TMultiplexedProtocol in your client?") serviceName = name[0:index] call = name[index + len(TMultiplexedProtocol.SEPARATOR):] diff --git a/lib/py/src/protocol/__init__.py b/lib/py/src/protocol/__init__.py index 7148f66b334..06647a24b9f 100644 --- a/lib/py/src/protocol/__init__.py +++ b/lib/py/src/protocol/__init__.py @@ -18,4 +18,4 @@ # __all__ = ['fastbinary', 'TBase', 'TBinaryProtocol', 'TCompactProtocol', - 'TJSONProtocol', 'TProtocol'] + 'TJSONProtocol', 'TProtocol', 'TProtocolDecorator'] diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index 1ab2af5fde3..dd7fb6b8181 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -139,6 +139,8 @@ "cpp-py_multic_http-ip-ssl", "cpp-py_multih-header_http-ip", "cpp-py_multih-header_http-ip-ssl", + "cpp-py_multih_http-ip", + "cpp-py_multih_http-ip-ssl", "cpp-py_multij-json_http-ip", "cpp-py_multij-json_http-ip-ssl", "cpp-py_multij_http-ip", @@ -397,6 +399,38 @@ "py-cpp_header_http-ip-ssl", "py-cpp_json_http-ip", "py-cpp_json_http-ip-ssl", + "py-cpp_multi-binary_http-ip", + "py-cpp_multi-binary_http-ip-ssl", + "py-cpp_multi_http-ip", + "py-cpp_multi_http-ip-ssl", + "py-cpp_multia-binary_http-ip", + "py-cpp_multia-binary_http-ip-ssl", + "py-cpp_multia-binary_zlib-ip", + "py-cpp_multia-binary_zlib-ip-ssl", + "py-cpp_multia-multi_http-ip", + "py-cpp_multia-multi_http-ip-ssl", + "py-cpp_multia-multi_zlib-ip", + "py-cpp_multia-multi_zlib-ip-ssl", + "py-cpp_multiac-compact_http-ip", + "py-cpp_multiac-compact_http-ip-ssl", + "py-cpp_multiac-compact_zlib-ip", + "py-cpp_multiac-compact_zlib-ip-ssl", + "py-cpp_multiac-multic_http-ip", + "py-cpp_multiac-multic_http-ip-ssl", + "py-cpp_multiac-multic_zlib-ip", + "py-cpp_multiac-multic_zlib-ip-ssl", + "py-cpp_multic-compact_http-ip", + "py-cpp_multic-compact_http-ip-ssl", + "py-cpp_multic_http-ip", + "py-cpp_multic_http-ip-ssl", + "py-cpp_multih-header_http-ip", + "py-cpp_multih-header_http-ip-ssl", + "py-cpp_multih_http-ip", + "py-cpp_multih_http-ip-ssl", + "py-cpp_multij-json_http-ip", + "py-cpp_multij-json_http-ip-ssl", + "py-cpp_multij_http-ip", + "py-cpp_multij_http-ip-ssl", "py-d_accel-binary_http-ip", "py-d_accel-binary_http-ip-ssl", "py-d_accelc-compact_http-ip", @@ -428,11 +462,39 @@ "py-java_compact_http-ip-ssl", "py-java_json_http-ip", "py-java_json_http-ip-ssl", + "py-java_multi-binary_http-ip", + "py-java_multi-binary_http-ip-ssl", + "py-java_multi_http-ip", + "py-java_multi_http-ip-ssl", + "py-java_multia-binary_http-ip", + "py-java_multia-binary_http-ip-ssl", + "py-java_multia-multi_http-ip", + "py-java_multia-multi_http-ip-ssl", + "py-java_multiac-compact_http-ip", + "py-java_multiac-compact_http-ip-ssl", + "py-java_multiac-multic_http-ip", + "py-java_multiac-multic_http-ip-ssl", + "py-java_multic-compact_http-ip", + "py-java_multic-compact_http-ip-ssl", + "py-java_multic_http-ip", + "py-java_multic_http-ip-ssl", + "py-java_multij-json_http-ip", + "py-java_multij-json_http-ip-ssl", + "py-java_multij_http-ip", + "py-java_multij_http-ip-ssl", "py-lua_accel-binary_http-ip", "py-lua_accelc-compact_http-ip", "py-lua_binary_http-ip", "py-lua_compact_http-ip", "py-lua_json_http-ip", + "py-rs_multi_buffered-ip", + "py-rs_multi_framed-ip", + "py-rs_multia-multi_buffered-ip", + "py-rs_multia-multi_framed-ip", + "py-rs_multiac-multic_buffered-ip", + "py-rs_multiac-multic_framed-ip", + "py-rs_multic_buffered-ip", + "py-rs_multic_framed-ip", "py3-cpp_accel-binary_http-ip", "py3-cpp_accel-binary_http-ip-ssl", "py3-cpp_accel-binary_zlib-ip", @@ -449,6 +511,38 @@ "py3-cpp_header_http-ip-ssl", "py3-cpp_json_http-ip", "py3-cpp_json_http-ip-ssl", + "py3-cpp_multi-binary_http-ip", + "py3-cpp_multi-binary_http-ip-ssl", + "py3-cpp_multi_http-ip", + "py3-cpp_multi_http-ip-ssl", + "py3-cpp_multia-binary_http-ip", + "py3-cpp_multia-binary_http-ip-ssl", + "py3-cpp_multia-binary_zlib-ip", + "py3-cpp_multia-binary_zlib-ip-ssl", + "py3-cpp_multia-multi_http-ip", + "py3-cpp_multia-multi_http-ip-ssl", + "py3-cpp_multia-multi_zlib-ip", + "py3-cpp_multia-multi_zlib-ip-ssl", + "py3-cpp_multiac-compact_http-ip", + "py3-cpp_multiac-compact_http-ip-ssl", + "py3-cpp_multiac-compact_zlib-ip", + "py3-cpp_multiac-compact_zlib-ip-ssl", + "py3-cpp_multiac-multic_http-ip", + "py3-cpp_multiac-multic_http-ip-ssl", + "py3-cpp_multiac-multic_zlib-ip", + "py3-cpp_multiac-multic_zlib-ip-ssl", + "py3-cpp_multic-compact_http-ip", + "py3-cpp_multic-compact_http-ip-ssl", + "py3-cpp_multic_http-ip", + "py3-cpp_multic_http-ip-ssl", + "py3-cpp_multih-header_http-ip", + "py3-cpp_multih-header_http-ip-ssl", + "py3-cpp_multih_http-ip", + "py3-cpp_multih_http-ip-ssl", + "py3-cpp_multij-json_http-ip", + "py3-cpp_multij-json_http-ip-ssl", + "py3-cpp_multij_http-ip", + "py3-cpp_multij_http-ip-ssl", "py3-d_accel-binary_http-ip", "py3-d_accel-binary_http-ip-ssl", "py3-d_accelc-compact_http-ip", @@ -480,11 +574,39 @@ "py3-java_compact_http-ip-ssl", "py3-java_json_http-ip", "py3-java_json_http-ip-ssl", + "py3-java_multi-binary_http-ip", + "py3-java_multi-binary_http-ip-ssl", + "py3-java_multi_http-ip", + "py3-java_multi_http-ip-ssl", + "py3-java_multia-binary_http-ip", + "py3-java_multia-binary_http-ip-ssl", + "py3-java_multia-multi_http-ip", + "py3-java_multia-multi_http-ip-ssl", + "py3-java_multiac-compact_http-ip", + "py3-java_multiac-compact_http-ip-ssl", + "py3-java_multiac-multic_http-ip", + "py3-java_multiac-multic_http-ip-ssl", + "py3-java_multic-compact_http-ip", + "py3-java_multic-compact_http-ip-ssl", + "py3-java_multic_http-ip", + "py3-java_multic_http-ip-ssl", + "py3-java_multij-json_http-ip", + "py3-java_multij-json_http-ip-ssl", + "py3-java_multij_http-ip", + "py3-java_multij_http-ip-ssl", "py3-lua_accel-binary_http-ip", "py3-lua_accelc-compact_http-ip", "py3-lua_binary_http-ip", "py3-lua_compact_http-ip", "py3-lua_json_http-ip", + "py3-rs_multi_buffered-ip", + "py3-rs_multi_framed-ip", + "py3-rs_multia-multi_buffered-ip", + "py3-rs_multia-multi_framed-ip", + "py3-rs_multiac-multic_buffered-ip", + "py3-rs_multiac-multic_framed-ip", + "py3-rs_multic_buffered-ip", + "py3-rs_multic_framed-ip", "rb-cpp_json_buffered-domain", "rb-cpp_json_buffered-ip", "rb-cpp_json_buffered-ip-ssl", diff --git a/test/py/TestClient.py b/test/py/TestClient.py index a85098eb4d2..e7a9a1a0e71 100755 --- a/test/py/TestClient.py +++ b/test/py/TestClient.py @@ -27,8 +27,7 @@ from optparse import OptionParser from util import local_libpath sys.path.insert(0, local_libpath()) -from thrift.protocol import TProtocolDecorator -from thrift.protocol import TProtocol +from thrift.protocol import TProtocol, TProtocolDecorator SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) @@ -272,7 +271,7 @@ def testOnewayThenNormal(self): # LAST_SEQID is a global because we have one transport and multiple protocols -# running on it (when multiplexec) +# running on it (when multiplexed) LAST_SEQID = None @@ -398,6 +397,16 @@ def get_protocol(self, transport): return make_pedantic(factory.getProtocol(transport)) +class MultiplexedHeaderTest(MultiplexedOptionalTest): + def get_protocol(self, transport): + wrapped_proto = make_pedantic(THeaderProtocol.THeaderProtocolFactory().getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "ThriftTest") + + def get_protocol2(self, transport): + wrapped_proto = make_pedantic(THeaderProtocol.THeaderProtocolFactory().getProtocol(transport)) + return TMultiplexedProtocol.TMultiplexedProtocol(wrapped_proto, "SecondService") + + def suite(): suite = unittest.TestSuite() loader = unittest.TestLoader() @@ -421,6 +430,8 @@ def suite(): suite.addTest(loader.loadTestsFromTestCase(MultiplexedAcceleratedCompactTest)) elif options.proto == 'multic': suite.addTest(loader.loadTestsFromTestCase(MultiplexedCompactTest)) + elif options.proto == 'multih': + suite.addTest(loader.loadTestsFromTestCase(MultiplexedHeaderTest)) elif options.proto == 'multij': suite.addTest(loader.loadTestsFromTestCase(MultiplexedJSONTest)) else: @@ -460,7 +471,7 @@ def parseArgs(self, argv): dest="verbose", const=0, help="minimal output") parser.add_option('--protocol', dest="proto", type="string", - help="protocol to use, one of: accel, accelc, binary, compact, header, json, multi, multia, multiac, multic, multij") + help="protocol to use, one of: accel, accelc, binary, compact, header, json, multi, multia, multiac, multic, multih, multij") parser.add_option('--transport', dest="trans", type="string", help="transport to use, one of: buffered, framed, http") parser.set_defaults(framed=False, http_path=None, verbose=1, host='localhost', port=9090, proto='binary') diff --git a/test/py/TestServer.py b/test/py/TestServer.py index aba0d42988b..d0a13e5f7e6 100755 --- a/test/py/TestServer.py +++ b/test/py/TestServer.py @@ -27,6 +27,8 @@ from optparse import OptionParser from util import local_libpath +sys.path.insert(0, local_libpath()) +from thrift.protocol import TProtocol, TProtocolDecorator SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__)) @@ -178,21 +180,79 @@ def testMulti(self, arg0, arg1, arg2, arg3, arg4, arg5): byte_thing=arg0, i32_thing=arg1, i64_thing=arg2) +class SecondHandler(object): + def secondtestString(self, argument): + return "testString(\"" + argument + "\")" + + +# LAST_SEQID is a global because we have one transport and multiple protocols +# running on it (when multiplexed) +LAST_SEQID = None + + +class TPedanticSequenceIdProtocolWrapper(TProtocolDecorator.TProtocolDecorator): + """ + Wraps any protocol with sequence ID checking: looks for outbound + uniqueness as well as request/response alignment. + """ + def __init__(self, protocol): + # TProtocolDecorator.__new__ does all the heavy lifting + pass + + def readMessageBegin(self): + global LAST_SEQID + (name, type, seqid) =\ + super(TPedanticSequenceIdProtocolWrapper, self).readMessageBegin() + if LAST_SEQID is not None and LAST_SEQID == seqid: + raise TProtocol.TProtocolException( + TProtocol.TProtocolException.INVALID_DATA, + "We received the same seqid {0} twice in a row".format(seqid)) + LAST_SEQID = seqid + return (name, type, seqid) + + +def make_pedantic(proto): + """ Wrap a protocol in the pedantic sequence ID wrapper. """ + # NOTE: this is disabled for now as many clients send seqid + # of zero and that is okay, need a way to identify + # clients that MUST send seqid unique to function right + # or just force all implementations to send unique seqids (preferred) + return proto # TPedanticSequenceIdProtocolWrapper(proto) + + +class TPedanticSequenceIdProtocolFactory(TProtocol.TProtocolFactory): + def __init__(self, encapsulated): + super(TPedanticSequenceIdProtocolFactory, self).__init__() + self.encapsulated = encapsulated + + def getProtocol(self, trans): + return make_pedantic(self.encapsulated.getProtocol(trans)) + + def main(options): + # common header allowed client types + allowed_client_types = [ + THeaderTransport.THeaderClientType.HEADERS, + THeaderTransport.THeaderClientType.FRAMED_BINARY, + THeaderTransport.THeaderClientType.UNFRAMED_BINARY, + THeaderTransport.THeaderClientType.FRAMED_COMPACT, + THeaderTransport.THeaderClientType.UNFRAMED_COMPACT, + ] + # set up the protocol factory form the --protocol option prot_factories = { 'accel': TBinaryProtocol.TBinaryProtocolAcceleratedFactory(), + 'multia': TBinaryProtocol.TBinaryProtocolAcceleratedFactory(), 'accelc': TCompactProtocol.TCompactProtocolAcceleratedFactory(), - 'binary': TBinaryProtocol.TBinaryProtocolFactory(), + 'multiac': TCompactProtocol.TCompactProtocolAcceleratedFactory(), + 'binary': TPedanticSequenceIdProtocolFactory(TBinaryProtocol.TBinaryProtocolFactory()), + 'multi': TPedanticSequenceIdProtocolFactory(TBinaryProtocol.TBinaryProtocolFactory()), 'compact': TCompactProtocol.TCompactProtocolFactory(), - 'header': THeaderProtocol.THeaderProtocolFactory(allowed_client_types=[ - THeaderTransport.THeaderClientType.HEADERS, - THeaderTransport.THeaderClientType.FRAMED_BINARY, - THeaderTransport.THeaderClientType.UNFRAMED_BINARY, - THeaderTransport.THeaderClientType.FRAMED_COMPACT, - THeaderTransport.THeaderClientType.UNFRAMED_COMPACT, - ]), + 'multic': TCompactProtocol.TCompactProtocolFactory(), + 'header': THeaderProtocol.THeaderProtocolFactory(allowed_client_types), + 'multih': THeaderProtocol.THeaderProtocolFactory(allowed_client_types), 'json': TJSONProtocol.TJSONProtocolFactory(), + 'multij': TJSONProtocol.TJSONProtocolFactory(), } pfactory = prot_factories.get(options.proto, None) if pfactory is None: @@ -215,6 +275,16 @@ def main(options): handler = TestHandler() processor = ThriftTest.Processor(handler) + if options.proto.startswith('multi'): + secondHandler = SecondHandler() + secondProcessor = SecondService.Processor(secondHandler) + + multiplexedProcessor = TMultiplexedProcessor() + multiplexedProcessor.registerDefault(processor) + multiplexedProcessor.registerProcessor('ThriftTest', processor) + multiplexedProcessor.registerProcessor('SecondService', secondProcessor) + processor = multiplexedProcessor + global server # Handle THttpServer as a special case @@ -312,7 +382,7 @@ def exit_gracefully(signum, frame): dest="verbose", const=0, help="minimal output") parser.add_option('--protocol', dest="proto", type="string", - help="protocol to use, one of: accel, accelc, binary, compact, json") + help="protocol to use, one of: accel, accelc, binary, compact, json, multi, multia, multiac, multic, multih, multij") parser.add_option('--transport', dest="trans", type="string", help="transport to use, one of: buffered, framed, http") parser.add_option('--container-limit', dest='container_limit', type='int', default=None) @@ -324,11 +394,11 @@ def exit_gracefully(signum, frame): logging.basicConfig(level=options.verbose) sys.path.insert(0, os.path.join(SCRIPT_DIR, options.genpydir)) - sys.path.insert(0, local_libpath()) - from ThriftTest import ThriftTest + from ThriftTest import ThriftTest, SecondService from ThriftTest.ttypes import Xtruct, Xception, Xception2, Insanity from thrift.Thrift import TException + from thrift.TMultiplexedProcessor import TMultiplexedProcessor from thrift.transport import THeaderTransport from thrift.transport import TTransport from thrift.transport import TSocket diff --git a/test/rs/src/bin/test_client.rs b/test/rs/src/bin/test_client.rs index 29b5b88e888..8016ca67469 100644 --- a/test/rs/src/bin/test_client.rs +++ b/test/rs/src/bin/test_client.rs @@ -65,7 +65,7 @@ fn run() -> thrift::Result<()> { (@arg host: --host +takes_value "Host on which the Thrift test server is located") (@arg port: --port +takes_value "Port on which the Thrift test server is listening") (@arg transport: --transport +takes_value "Thrift transport implementation to use (\"buffered\", \"framed\")") - (@arg protocol: --protocol +takes_value "Thrift protocol implementation to use (\"binary\", \"compact\")") + (@arg protocol: --protocol +takes_value "Thrift protocol implementation to use (\"binary\", \"compact\", \"multi\", \"multic\")") (@arg testloops: -n --testloops +takes_value "Number of times to run tests") ) .get_matches(); diff --git a/test/tests.json b/test/tests.json index 043b8265017..02ae28ad9ad 100644 --- a/test/tests.json +++ b/test/tests.json @@ -251,13 +251,6 @@ "--verbose", "--host=localhost", "--genpydir=gen-py" - ], - "protocols": [ - "multi", - "multi:multia", - "multic", - "multic:multiac", - "multij" ] }, "transports": [ @@ -271,12 +264,20 @@ "ip-ssl" ], "protocols": [ - "compact", "binary", - "json", "binary:accel", + "compact", "compact:accelc", - "header" + "header", + "json", + "multi", + "multi:multia", + "multia", + "multiac", + "multic", + "multic:multiac", + "multih", + "multij" ], "workdir": "py" }, @@ -299,13 +300,6 @@ "TestClient.py", "--host=localhost", "--genpydir=gen-py" - ], - "protocols": [ - "multi", - "multi:multia", - "multic", - "multic:multiac", - "multij" ] }, "transports": [ @@ -319,12 +313,20 @@ "ip-ssl" ], "protocols": [ - "compact", "binary", - "json", "binary:accel", + "compact", "compact:accelc", - "header" + "header", + "json", + "multi", + "multi:multia", + "multia", + "multiac", + "multic", + "multic:multiac", + "multih", + "multij" ], "workdir": "py" }, From 6c26e098cab78a965ff14460f2fee52e6940b2ed Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 7 Feb 2019 12:48:27 -0500 Subject: [PATCH 218/756] THRIFT-4037: get as3 builds working in cmake for windows too --- LANGUAGES.md | 2 +- build/appveyor/MSVC-appveyor-install.bat | 7 +++++++ build/docker/msvc2017/Dockerfile | 11 +++++++++-- build/docker/msvc2017/build.bat | 3 ++- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/LANGUAGES.md b/LANGUAGES.md index c610d15d06b..b74fd3eaedf 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -36,7 +36,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u ActionScript 0.3.0 - +YesYes FLEX SDK 4.6 Yes Yes diff --git a/build/appveyor/MSVC-appveyor-install.bat b/build/appveyor/MSVC-appveyor-install.bat index f973d29cff8..bc4655a762f 100644 --- a/build/appveyor/MSVC-appveyor-install.bat +++ b/build/appveyor/MSVC-appveyor-install.bat @@ -57,3 +57,10 @@ pip.exe ^ twisted || EXIT /B cinst -y ghc || EXIT /B + +:: Adobe Flex SDK 4.6 for ActionScript +MKDIR "C:\Adobe\Flex\SDK\4.6" || EXIT /B +appveyor DownloadFile http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip -FileName C:\Adobe\Flex\SDK\4.6\SDK.zip || EXIT /B +CD "C:\Adobe\Flex\SDK\4.6" || EXIT /B +7z x SDK.zip || EXIT /B +SETX FLEX_HOME "C:\Adobe\Flex\SDK\4.6" diff --git a/build/docker/msvc2017/Dockerfile b/build/docker/msvc2017/Dockerfile index 7da895cb562..a2b3cd7e221 100644 --- a/build/docker/msvc2017/Dockerfile +++ b/build/docker/msvc2017/Dockerfile @@ -31,7 +31,7 @@ RUN C:\TEMP\vs_buildtools.exe --quiet --wait --norestart --nocache ` RUN DEL C:\TEMP\vs_buildtools.exe # Install CMake -ADD https://github.com/Kitware/CMake/releases/download/v3.13.2/cmake-3.13.2-win64-x64.msi C:\TEMP\cmake.msi +ADD https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4-win64-x64.msi C:\TEMP\cmake.msi RUN msiexec.exe /i C:\TEMP\cmake.msi /qn && ` SETX PATH "%PATH%;C:\Program Files\CMake\bin" && ` DEL C:\TEMP\cmake.msi @@ -89,8 +89,15 @@ RUN choco install ghc -y # Install python3 RUN choco install python3 -y +# Install Adobe Flex 4.6 SDK and set FLEX_HOME so it can be found +ADD http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip C:\Adobe\Flex\SDK\4.6\SDK.zip +RUN CD C:\Adobe\Flex\SDK\4.6 && ` + 7z x SDK.zip && ` + DEL SDK.zip && ` + SETX FLEX_HOME "C:\Adobe\Flex\SDK\4.6" + # Start developer command prompt with any other commands specified. ENTRYPOINT C:\BuildTools\Common7\Tools\VsDevCmd.bat -arch=amd64 && # Default to PowerShell if no other command specified. -CMD ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"] \ No newline at end of file +CMD ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"] diff --git a/build/docker/msvc2017/build.bat b/build/docker/msvc2017/build.bat index ac7b68a1c05..018805bca69 100644 --- a/build/docker/msvc2017/build.bat +++ b/build/docker/msvc2017/build.bat @@ -28,6 +28,7 @@ cd c:\build cmake^ -DBOOST_ROOT=C:\Libraries\boost_1_69_0^ -DBOOST_LIBRARYDIR=C:\Libraries\boost_1_69_0\lib64-msvc-14.1^ + -DFLEX_HOME=C:\Adobe\Flex\SDK\4.6^ -DLIBEVENT_ROOT=C:\Libraries\libevent-2.1.8^ -DZLIB_ROOT=C:\Libraries\zlib-1.2.11^ -DCMAKE_BUILD_TYPE=Release^ @@ -41,4 +42,4 @@ cmake --build . --config Release || EXIT /B cmake --build . --target check || EXIT /B :: Install -cmake --build . --target install \ No newline at end of file +cmake --build . --target install From 2b70c1df2bb2c1667f30dff6d4b263459fabe91a Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 9 Feb 2019 11:50:03 +0100 Subject: [PATCH 219/756] THRIFT-4784 Thrift should throw when skipping over unexpected data Client: as3 Patch: Jens Geyer --- lib/as3/src/org/apache/thrift/protocol/TProtocolUtil.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/as3/src/org/apache/thrift/protocol/TProtocolUtil.as b/lib/as3/src/org/apache/thrift/protocol/TProtocolUtil.as index 513df954bee..22877b75b2b 100644 --- a/lib/as3/src/org/apache/thrift/protocol/TProtocolUtil.as +++ b/lib/as3/src/org/apache/thrift/protocol/TProtocolUtil.as @@ -141,7 +141,7 @@ package org.apache.thrift.protocol { break; } default: - break; + throw new TProtocolError(TProtocolError.INVALID_DATA, "invalid data"); } } } From e53d23c16c806c6da62ebaa7f205328cf710d9a5 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sun, 10 Feb 2019 11:13:23 -0500 Subject: [PATCH 220/756] THRIFT-4794: finish php json cross test --- build/docker/ubuntu-bionic/Dockerfile | 1 + build/docker/ubuntu-xenial/Dockerfile | 1 + test/php/Makefile.am | 1 + test/php/test_php.ini | 1 + test/tests.json | 3 ++- 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index 356619910c3..a0ed317519d 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -217,6 +217,7 @@ RUN apt-get install -y --no-install-recommends \ php \ php-cli \ php-dev \ + php-json \ php-pear \ re2c \ composer diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index 88895a0c423..5693a2c0a0c 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -218,6 +218,7 @@ RUN apt-get install -y --no-install-recommends \ php7.0 \ php7.0-cli \ php7.0-dev \ + php-json \ php-pear \ re2c \ composer diff --git a/test/php/Makefile.am b/test/php/Makefile.am index 5c42321c18b..52765ee3b89 100755 --- a/test/php/Makefile.am +++ b/test/php/Makefile.am @@ -26,6 +26,7 @@ stubs: ../ThriftTest.thrift php_ext_dir: mkdir -p php_ext_dir ln -s ../../../lib/php/src/ext/thrift_protocol/modules/thrift_protocol.so php_ext_dir/ + ln -s "$$(php-config --extension-dir)/json.so" php_ext_dir/ ln -s "$$(php-config --extension-dir)/sockets.so" php_ext_dir/ precross: stubs php_ext_dir diff --git a/test/php/test_php.ini b/test/php/test_php.ini index 3f9bb21e22f..aeb67cbd411 100644 --- a/test/php/test_php.ini +++ b/test/php/test_php.ini @@ -1,2 +1,3 @@ extension=thrift_protocol.so +extension=json.so extension=sockets.so diff --git a/test/tests.json b/test/tests.json index 02ae28ad9ad..acede24dc60 100644 --- a/test/tests.json +++ b/test/tests.json @@ -545,8 +545,9 @@ ], "protocols": [ "binary", + "binary:accel", "compact", - "binary:accel" + "json" ], "command": [ "php", From 393f6c93e1a65b7be74d79b5a6b00f878e88a630 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 9 Feb 2019 10:35:44 -0500 Subject: [PATCH 221/756] THRIFT-3877: fix py/py3 server, java client with http transport The java TestClient asks the server to runa oneway request that sleeps for 3 seconds. If the java TestClient sees the duration of the call exceed one second, it fails the test. This means the server did not participate in the "fire and forget" dynamics of ONEWAY requests. In this case the THttpServer was processing the RPC before sending the transport response. The fix was to enhance the TProcessor so that the THttpServer has an opportunity to inspect the message header before processing the RPC. This is partly due to the violation of the THttpServer in the layered architecture. It is essentially implementing a combined server and transport, whereas there should be a distinct server, protocol, and transport separation. Many languages seem to have this problem where HTTP was introduced. --- .../cpp/src/thrift/generate/t_py_generator.cc | 11 ++++++ .../org/apache/thrift/test/TestClient.java | 11 ++++-- lib/py/src/TMultiplexedProcessor.py | 4 ++ lib/py/src/Thrift.py | 12 ++++++ lib/py/src/server/THttpServer.py | 37 ++++++++++++++++--- test/known_failures_Linux.json | 32 +--------------- 6 files changed, 67 insertions(+), 40 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_py_generator.cc b/compiler/cpp/src/thrift/generate/t_py_generator.cc index c16d6d3ae9a..83462f48093 100644 --- a/compiler/cpp/src/thrift/generate/t_py_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_py_generator.cc @@ -1831,6 +1831,13 @@ void t_py_generator::generate_service_server(t_service* tservice) { f_service_ << indent() << "self._processMap[\"" << (*f_iter)->get_name() << "\"] = Processor.process_" << (*f_iter)->get_name() << endl; } + f_service_ << indent() << "self._on_message_begin = None" << endl; + indent_down(); + f_service_ << endl; + + f_service_ << indent() << "def on_message_begin(self, func):" << endl; + indent_up(); + f_service_ << indent() << "self._on_message_begin = func" << endl; indent_down(); f_service_ << endl; @@ -1839,6 +1846,10 @@ void t_py_generator::generate_service_server(t_service* tservice) { indent_up(); f_service_ << indent() << "(name, type, seqid) = iprot.readMessageBegin()" << endl; + f_service_ << indent() << "if self._on_message_begin:" << endl; + indent_up(); + f_service_ << indent() << "self._on_message_begin(name, type, seqid)" << endl; + indent_down(); // TODO(mcslee): validate message diff --git a/lib/java/test/org/apache/thrift/test/TestClient.java b/lib/java/test/org/apache/thrift/test/TestClient.java index feaa97220ad..84410cea0c2 100644 --- a/lib/java/test/org/apache/thrift/test/TestClient.java +++ b/lib/java/test/org/apache/thrift/test/TestClient.java @@ -752,13 +752,18 @@ public static void main(String [] args) { testClient.testOneway(3); long onewayElapsedMillis = (System.nanoTime() - startOneway) / 1000000; if (onewayElapsedMillis > 200) { - System.out.println("Oneway test failed: took " + + System.out.println("Oneway test took too long to execute failed: took " + Long.toString(onewayElapsedMillis) + "ms"); - System.out.printf("*** FAILURE ***\n"); + System.out.println("oneway calls are 'fire and forget' and therefore should not cause blocking."); + System.out.println("Some transports (HTTP) have a required response, and typically this failure"); + System.out.println("means the transport response was delayed until after the execution"); + System.out.println("of the RPC. The server should post the transport response immediately and"); + System.out.println("before executing the RPC."); + System.out.println("*** FAILURE ***"); returnCode |= ERR_BASETYPES; } else { - System.out.println("Success - took " + + System.out.println("Success - fire and forget only took " + Long.toString(onewayElapsedMillis) + "ms"); } diff --git a/lib/py/src/TMultiplexedProcessor.py b/lib/py/src/TMultiplexedProcessor.py index bd10d9b6acc..ff88430bd0b 100644 --- a/lib/py/src/TMultiplexedProcessor.py +++ b/lib/py/src/TMultiplexedProcessor.py @@ -39,6 +39,10 @@ def registerDefault(self, processor): def registerProcessor(self, serviceName, processor): self.services[serviceName] = processor + def on_message_begin(self, func): + for key in self.services.keys(): + self.services[key].on_message_begin(func) + def process(self, iprot, oprot): (name, type, seqid) = iprot.readMessageBegin() if type != TMessageType.CALL and type != TMessageType.ONEWAY: diff --git a/lib/py/src/Thrift.py b/lib/py/src/Thrift.py index 00941d8d536..c390cbb54c1 100644 --- a/lib/py/src/Thrift.py +++ b/lib/py/src/Thrift.py @@ -72,6 +72,18 @@ class TProcessor(object): """Base class for processor, which works on two streams.""" def process(self, iprot, oprot): + """ + Process a request. The normal behvaior is to have the + processor invoke the correct handler and then it is the + server's responsibility to write the response to oprot. + """ + pass + + def on_message_begin(self, func): + """ + Install a callback that receives (name, type, seqid) + after the message header is read. + """ pass diff --git a/lib/py/src/server/THttpServer.py b/lib/py/src/server/THttpServer.py index 85cf4005eab..47e817df773 100644 --- a/lib/py/src/server/THttpServer.py +++ b/lib/py/src/server/THttpServer.py @@ -21,6 +21,7 @@ from six.moves import BaseHTTPServer +from thrift.Thrift import TMessageType from thrift.server import TServer from thrift.transport import TTransport @@ -32,7 +33,9 @@ class ResponseException(Exception): to override this behavior (e.g., to simulate a misconfigured or overloaded web server during testing), it can raise a ResponseException. The function passed to the constructor will be called with the - RequestHandler as its only argument. + RequestHandler as its only argument. Note that this is irrelevant + for ONEWAY requests, as the HTTP response must be sent before the + RPC is processed. """ def __init__(self, handler): self.handler = handler @@ -43,6 +46,9 @@ class THttpServer(TServer.TServer): This class is not very performant, but it is useful (for example) for acting as a mock version of an Apache-based PHP Thrift endpoint. + Also important to note the HTTP implementation pretty much violates the + transport/protocol/processor/server layering, by performing the transport + functions here. This means things like oneway handling are oddly exposed. """ def __init__(self, processor, @@ -68,26 +74,45 @@ def __init__(self, inputProtocolFactory, outputProtocolFactory) thttpserver = self + self._replied = None class RequestHander(BaseHTTPServer.BaseHTTPRequestHandler): def do_POST(self): # Don't care about the request path. - itrans = TTransport.TFileObjectTransport(self.rfile) - otrans = TTransport.TFileObjectTransport(self.wfile) + thttpserver._replied = False + iftrans = TTransport.TFileObjectTransport(self.rfile) itrans = TTransport.TBufferedTransport( - itrans, int(self.headers['Content-Length'])) + iftrans, int(self.headers['Content-Length'])) otrans = TTransport.TMemoryBuffer() iprot = thttpserver.inputProtocolFactory.getProtocol(itrans) oprot = thttpserver.outputProtocolFactory.getProtocol(otrans) try: + thttpserver.processor.on_message_begin(self.on_begin) thttpserver.processor.process(iprot, oprot) except ResponseException as exn: exn.handler(self) else: + if not thttpserver._replied: + # If the request was ONEWAY we would have replied already + data = otrans.getvalue() + self.send_response(200) + self.send_header("Content-Length", len(data)) + self.send_header("Content-Type", "application/x-thrift") + self.end_headers() + self.wfile.write(data) + + def on_begin(self, name, type, seqid): + """ + Inspect the message header. + + This allows us to post an immediate transport response + if the request is a ONEWAY message type. + """ + if type == TMessageType.ONEWAY: self.send_response(200) - self.send_header("content-type", "application/x-thrift") + self.send_header("Content-Type", "application/x-thrift") self.end_headers() - self.wfile.write(otrans.getvalue()) + thttpserver._replied = True self.httpd = server_class(server_address, RequestHander) diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index dd7fb6b8181..5beaa58605f 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -452,35 +452,20 @@ "py-hs_compact_http-ip", "py-hs_header_http-ip", "py-hs_json_http-ip", - "py-java_accel-binary_http-ip", "py-java_accel-binary_http-ip-ssl", - "py-java_accelc-compact_http-ip", "py-java_accelc-compact_http-ip-ssl", - "py-java_binary_http-ip", "py-java_binary_http-ip-ssl", - "py-java_compact_http-ip", "py-java_compact_http-ip-ssl", - "py-java_json_http-ip", "py-java_json_http-ip-ssl", - "py-java_multi-binary_http-ip", "py-java_multi-binary_http-ip-ssl", - "py-java_multi_http-ip", "py-java_multi_http-ip-ssl", - "py-java_multia-binary_http-ip", "py-java_multia-binary_http-ip-ssl", - "py-java_multia-multi_http-ip", "py-java_multia-multi_http-ip-ssl", - "py-java_multiac-compact_http-ip", "py-java_multiac-compact_http-ip-ssl", - "py-java_multiac-multic_http-ip", "py-java_multiac-multic_http-ip-ssl", - "py-java_multic-compact_http-ip", "py-java_multic-compact_http-ip-ssl", - "py-java_multic_http-ip", "py-java_multic_http-ip-ssl", - "py-java_multij-json_http-ip", "py-java_multij-json_http-ip-ssl", - "py-java_multij_http-ip", "py-java_multij_http-ip-ssl", "py-lua_accel-binary_http-ip", "py-lua_accelc-compact_http-ip", @@ -564,35 +549,20 @@ "py3-hs_compact_http-ip", "py3-hs_header_http-ip", "py3-hs_json_http-ip", - "py3-java_accel-binary_http-ip", "py3-java_accel-binary_http-ip-ssl", - "py3-java_accelc-compact_http-ip", "py3-java_accelc-compact_http-ip-ssl", - "py3-java_binary_http-ip", "py3-java_binary_http-ip-ssl", - "py3-java_compact_http-ip", "py3-java_compact_http-ip-ssl", - "py3-java_json_http-ip", "py3-java_json_http-ip-ssl", - "py3-java_multi-binary_http-ip", "py3-java_multi-binary_http-ip-ssl", - "py3-java_multi_http-ip", "py3-java_multi_http-ip-ssl", - "py3-java_multia-binary_http-ip", "py3-java_multia-binary_http-ip-ssl", - "py3-java_multia-multi_http-ip", "py3-java_multia-multi_http-ip-ssl", - "py3-java_multiac-compact_http-ip", "py3-java_multiac-compact_http-ip-ssl", - "py3-java_multiac-multic_http-ip", "py3-java_multiac-multic_http-ip-ssl", - "py3-java_multic-compact_http-ip", "py3-java_multic-compact_http-ip-ssl", - "py3-java_multic_http-ip", "py3-java_multic_http-ip-ssl", - "py3-java_multij-json_http-ip", "py3-java_multij-json_http-ip-ssl", - "py3-java_multij_http-ip", "py3-java_multij_http-ip-ssl", "py3-lua_accel-binary_http-ip", "py3-lua_accelc-compact_http-ip", @@ -613,4 +583,4 @@ "rb-cpp_json_framed-domain", "rb-cpp_json_framed-ip", "rb-cpp_json_framed-ip-ssl" -] \ No newline at end of file +] From 3ca88065dfdb24c5bad6fbd1e3a7e01812628d3b Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 12 Feb 2019 13:26:45 -0500 Subject: [PATCH 222/756] re-disable hs-csharp_json_framed-ip cross test --- test/known_failures_Linux.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index 5beaa58605f..de2f74a2e97 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -323,6 +323,8 @@ "hs-csharp_binary_framed-ip", "hs-csharp_compact_buffered-ip", "hs-csharp_compact_framed-ip", + "hs-csharp_json_buffered-ip", + "hs-csharp_json_framed-ip", "nodejs-cpp_binary_http-domain", "nodejs-cpp_binary_http-ip", "nodejs-cpp_binary_http-ip-ssl", From dbc1f8def5018ce5d85d38b9875c6c6b6b424478 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 14 Feb 2019 16:46:38 -0500 Subject: [PATCH 223/756] THRIFT-4024, THRIFT-4783: throw when skipping invalid type (#1742) * THRIFT-4024: make c_glib throw on unsupported type when skipping * THRIFT-4783: throw on invalid skip (py) * THRIFT-4024: make cpp throw on unsupported type when skipping * THRIFT-4024: uniform skip behavior on unsupported type --- .../thrift/c_glib/protocol/thrift_protocol.c | 72 ++++++++++++------- lib/cpp/src/thrift/protocol/TProtocol.h | 12 ++-- lib/d/src/thrift/protocol/base.d | 8 +-- .../lib/src/protocol/t_protocol_util.dart | 2 +- lib/go/thrift/protocol.go | 2 - .../apache/thrift/protocol/TProtocolUtil.java | 3 +- lib/js/src/thrift.js | 3 - lib/lua/TProtocol.lua | 8 ++- lib/nodejs/lib/thrift/binary_protocol.js | 2 - lib/nodejs/lib/thrift/compact_protocol.js | 2 - lib/nodejs/lib/thrift/json_protocol.js | 2 - lib/ocaml/src/Thrift.ml | 3 +- lib/py/src/protocol/TProtocol.py | 8 ++- lib/rb/lib/thrift/protocol/base_protocol.rb | 4 +- lib/rb/spec/base_protocol_spec.rb | 1 - lib/swift/Sources/TProtocol.swift | 3 +- 16 files changed, 73 insertions(+), 62 deletions(-) diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c index 8296a8cad13..6e6ae4d9a0e 100644 --- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c +++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c @@ -419,6 +419,13 @@ thrift_protocol_read_binary (ThriftProtocol *protocol, gpointer *buf, len, error); } +#define THRIFT_SKIP_RESULT_OR_RETURN(_RES, _CALL) \ + { \ + gint32 _x = (_CALL); \ + if (_x < 0) { return _x; } \ + (_RES) += _x; \ + } + gint32 thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) { @@ -469,24 +476,24 @@ thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) gchar *name; gint16 fid; ThriftType ftype; - result += thrift_protocol_read_struct_begin (protocol, &name, error); - + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_struct_begin (protocol, &name, error)) while (1) { - result += thrift_protocol_read_field_begin (protocol, &name, &ftype, - &fid, error); - if (result < 0) - { - return result; - } + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_field_begin (protocol, &name, &ftype, + &fid, error)) if (ftype == T_STOP) { break; } - result += thrift_protocol_skip (protocol, ftype, error); - result += thrift_protocol_read_field_end (protocol, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, ftype, error)) + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_field_end (protocol, error)) } - result += thrift_protocol_read_struct_end (protocol, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_struct_end (protocol, error)) return result; } case T_SET: @@ -494,13 +501,16 @@ thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) gint32 result = 0; ThriftType elem_type; guint32 i, size; - result += thrift_protocol_read_set_begin (protocol, &elem_type, &size, - error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_set_begin (protocol, &elem_type, &size, + error)) for (i = 0; i < size; i++) { - result += thrift_protocol_skip (protocol, elem_type, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, elem_type, error)) } - result += thrift_protocol_read_set_end (protocol, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_set_end (protocol, error)) return result; } case T_MAP: @@ -509,14 +519,18 @@ thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) ThriftType elem_type; ThriftType key_type; guint32 i, size; - result += thrift_protocol_read_map_begin (protocol, &key_type, &elem_type, &size, - error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_map_begin (protocol, &key_type, &elem_type, &size, + error)) for (i = 0; i < size; i++) { - result += thrift_protocol_skip (protocol, key_type, error); - result += thrift_protocol_skip (protocol, elem_type, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, key_type, error)) + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, elem_type, error)) } - result += thrift_protocol_read_map_end (protocol, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_map_end (protocol, error)) return result; } case T_LIST: @@ -524,18 +538,26 @@ thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) gint32 result = 0; ThriftType elem_type; guint32 i, size; - result += thrift_protocol_read_list_begin (protocol, &elem_type, &size, - error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_list_begin (protocol, &elem_type, &size, + error)) for (i = 0; i < size; i++) { - result += thrift_protocol_skip (protocol, elem_type, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, elem_type, error)) } - result += thrift_protocol_read_list_end (protocol, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_list_end (protocol, error)) return result; } default: - return 0; + break; } + + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_INVALID_DATA, + "unrecognized type"); + return -1; } /* define the GError domain for Thrift protocols */ diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h index a38660fb733..7566a258f41 100644 --- a/lib/cpp/src/thrift/protocol/TProtocol.h +++ b/lib/cpp/src/thrift/protocol/TProtocol.h @@ -746,16 +746,12 @@ uint32_t skip(Protocol_& prot, TType type) { result += prot.readListEnd(); return result; } - case T_STOP: - case T_VOID: - case T_U64: - case T_UTF8: - case T_UTF16: - break; default: - throw TProtocolException(TProtocolException::INVALID_DATA); + break; } - return 0; + + throw TProtocolException(TProtocolException::INVALID_DATA, + "invalid TType"); } }}} // apache::thrift::protocol diff --git a/lib/d/src/thrift/protocol/base.d b/lib/d/src/thrift/protocol/base.d index 70648b3c39f..5b6d84514cb 100644 --- a/lib/d/src/thrift/protocol/base.d +++ b/lib/d/src/thrift/protocol/base.d @@ -260,7 +260,7 @@ protected: * in generated code. */ void skip(Protocol)(Protocol prot, TType type) if (is(Protocol : TProtocol)) { - final switch (type) { + switch (type) { case TType.BOOL: prot.readBool(); break; @@ -324,9 +324,9 @@ void skip(Protocol)(Protocol prot, TType type) if (is(Protocol : TProtocol)) { } prot.readSetEnd(); break; - case TType.STOP: goto case; - case TType.VOID: - assert(false, "Invalid field type passed."); + + default: + throw new TProtocolException(TProtocolException.Type.INVALID_DATA); } } diff --git a/lib/dart/lib/src/protocol/t_protocol_util.dart b/lib/dart/lib/src/protocol/t_protocol_util.dart index ad20068c201..841ea8217d7 100644 --- a/lib/dart/lib/src/protocol/t_protocol_util.dart +++ b/lib/dart/lib/src/protocol/t_protocol_util.dart @@ -101,7 +101,7 @@ class TProtocolUtil { break; default: - break; + throw new TProtocolError(TProtocolErrorType.INVALID_DATA, "Invalid data"); } } } diff --git a/lib/go/thrift/protocol.go b/lib/go/thrift/protocol.go index 615b7a4a8f3..2e6bc4b1619 100644 --- a/lib/go/thrift/protocol.go +++ b/lib/go/thrift/protocol.go @@ -96,8 +96,6 @@ func Skip(self TProtocol, fieldType TType, maxDepth int) (err error) { } switch fieldType { - case STOP: - return case BOOL: _, err = self.ReadBool() return diff --git a/lib/javame/src/org/apache/thrift/protocol/TProtocolUtil.java b/lib/javame/src/org/apache/thrift/protocol/TProtocolUtil.java index 9bf10f67ea4..c327448efbf 100644 --- a/lib/javame/src/org/apache/thrift/protocol/TProtocolUtil.java +++ b/lib/javame/src/org/apache/thrift/protocol/TProtocolUtil.java @@ -152,7 +152,8 @@ public static void skip(TProtocol prot, byte type, int maxDepth) break; } default: - break; + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Unrecognized type " + type); } } } diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 0b4a29241a6..21a3d65fc20 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -1434,9 +1434,6 @@ Thrift.Protocol.prototype = { skip: function(type) { var ret, i; switch (type) { - case Thrift.Type.STOP: - return null; - case Thrift.Type.BOOL: return this.readBool(); diff --git a/lib/lua/TProtocol.lua b/lib/lua/TProtocol.lua index 616e167a958..1306fb3d8c3 100644 --- a/lib/lua/TProtocol.lua +++ b/lib/lua/TProtocol.lua @@ -107,9 +107,7 @@ function TProtocolBase:readDouble() end function TProtocolBase:readString() end function TProtocolBase:skip(ttype) - if type == TType.STOP then - return - elseif ttype == TType.BOOL then + if ttype == TType.BOOL then self:readBool() elseif ttype == TType.BYTE then self:readByte() @@ -153,6 +151,10 @@ function TProtocolBase:skip(ttype) self:skip(ettype) end self:readListEnd() + else + terror(TProtocolException:new{ + message = 'Invalid data' + }) end end diff --git a/lib/nodejs/lib/thrift/binary_protocol.js b/lib/nodejs/lib/thrift/binary_protocol.js index b57c8c57635..6ab9c05a948 100644 --- a/lib/nodejs/lib/thrift/binary_protocol.js +++ b/lib/nodejs/lib/thrift/binary_protocol.js @@ -302,8 +302,6 @@ TBinaryProtocol.prototype.getTransport = function() { TBinaryProtocol.prototype.skip = function(type) { switch (type) { - case Type.STOP: - return; case Type.BOOL: this.readBool(); break; diff --git a/lib/nodejs/lib/thrift/compact_protocol.js b/lib/nodejs/lib/thrift/compact_protocol.js index 5c531e5d60e..302a88d4d84 100644 --- a/lib/nodejs/lib/thrift/compact_protocol.js +++ b/lib/nodejs/lib/thrift/compact_protocol.js @@ -854,8 +854,6 @@ TCompactProtocol.prototype.zigzagToI64 = function(n) { TCompactProtocol.prototype.skip = function(type) { switch (type) { - case Type.STOP: - return; case Type.BOOL: this.readBool(); break; diff --git a/lib/nodejs/lib/thrift/json_protocol.js b/lib/nodejs/lib/thrift/json_protocol.js index 727a3b2ffb1..7e2b7c90891 100644 --- a/lib/nodejs/lib/thrift/json_protocol.js +++ b/lib/nodejs/lib/thrift/json_protocol.js @@ -738,8 +738,6 @@ TJSONProtocol.prototype.getTransport = function() { */ TJSONProtocol.prototype.skip = function(type) { switch (type) { - case Type.STOP: - return; case Type.BOOL: this.readBool(); break; diff --git a/lib/ocaml/src/Thrift.ml b/lib/ocaml/src/Thrift.ml index f0d7a429659..063459ba0c1 100644 --- a/lib/ocaml/src/Thrift.ml +++ b/lib/ocaml/src/Thrift.ml @@ -206,8 +206,6 @@ struct (* skippage *) method skip typ = match typ with - | T_STOP -> () - | T_VOID -> () | T_BOOL -> ignore self#readBool | T_BYTE | T_I08 -> ignore self#readByte @@ -248,6 +246,7 @@ struct self#readListEnd) | T_UTF8 -> () | T_UTF16 -> () + | _ -> raise (Protocol.E (Protocol.INVALID_DATA, "Invalid data")) end class virtual factory = diff --git a/lib/py/src/protocol/TProtocol.py b/lib/py/src/protocol/TProtocol.py index 8314cf69df8..3456e8f0e85 100644 --- a/lib/py/src/protocol/TProtocol.py +++ b/lib/py/src/protocol/TProtocol.py @@ -191,9 +191,7 @@ def readUtf8(self): return self.readString().decode('utf8') def skip(self, ttype): - if ttype == TType.STOP: - return - elif ttype == TType.BOOL: + if ttype == TType.BOOL: self.readBool() elif ttype == TType.BYTE: self.readByte() @@ -232,6 +230,10 @@ def skip(self, ttype): for i in range(size): self.skip(etype) self.readListEnd() + else: + raise TProtocolException( + TProtocolException.INVALID_DATA, + "invalid TType") # tuple of: ( 'reader method' name, is_container bool, 'writer_method' name ) _TTYPE_HANDLERS = ( diff --git a/lib/rb/lib/thrift/protocol/base_protocol.rb b/lib/rb/lib/thrift/protocol/base_protocol.rb index 5c693e99f1a..4d83a21ddb7 100644 --- a/lib/rb/lib/thrift/protocol/base_protocol.rb +++ b/lib/rb/lib/thrift/protocol/base_protocol.rb @@ -323,8 +323,6 @@ def read_type(field_info) def skip(type) case type - when Types::STOP - nil when Types::BOOL read_bool when Types::BYTE @@ -367,6 +365,8 @@ def skip(type) skip(etype) end read_list_end + else + raise ProtocolException.new(ProtocolException::INVALID_DATA, 'Invalid data') end end diff --git a/lib/rb/spec/base_protocol_spec.rb b/lib/rb/spec/base_protocol_spec.rb index eca936b239d..cfa7573d8c5 100644 --- a/lib/rb/spec/base_protocol_spec.rb +++ b/lib/rb/spec/base_protocol_spec.rb @@ -163,7 +163,6 @@ @prot.skip(Thrift::Types::I64) @prot.skip(Thrift::Types::DOUBLE) @prot.skip(Thrift::Types::STRING) - @prot.skip(Thrift::Types::STOP) # should do absolutely nothing end it "should skip structs" do diff --git a/lib/swift/Sources/TProtocol.swift b/lib/swift/Sources/TProtocol.swift index a4e4a20fa91..b111e71bbbf 100644 --- a/lib/swift/Sources/TProtocol.swift +++ b/lib/swift/Sources/TProtocol.swift @@ -175,8 +175,9 @@ public extension TProtocol { try skip(type: elemType) } try readListEnd() + default: - return + throw TProtocolError(error: .invalidData, message: "Invalid data") } } } From b000bc02df16a16a21d0fe3467227c3bc6d62a0c Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 14 Feb 2019 17:58:04 -0500 Subject: [PATCH 224/756] Update the pull request template [ci skip] --- .github/pull_request_template.md | 37 +++----------------------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a6b4382b431..edd7befe83e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,43 +1,12 @@ - +- [ ] Did you create an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) ticket? (not required for trivial changes) +- [ ] Does your pull request title follow the pattern "THRIFT-NNNN: describe my issue"? (not required for trivial changes) - [ ] Did you squash your changes to a single commit? - -- [ ] Do you need an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) ticket?
Expand for guidance... - - `Yes` if your change requires a release note. - - `Yes` if your change is a breaking change. - - `No` if you change is trivial, such as fixing a typo. -
- -- [ ] Is this change worthy of a release note?
Examples of Release Note-worthy examples... - - Breaking Changes - - New, Deprecated, or Removed Languages - - Security Fixes - - Significant Refactoring - - Changing how the product is built -
- -- [ ] Breaking changes have additional requirements:
Expand for instructions... - - Add or reference an existing Apache Jira THRIFT ticket. - - Add a `Breaking-Change` label to the Jira ticket. - - Add a note to the `lib//README.md` file. - - Add a line to the `CHANGES.md` file. -
- -- [ ] Does this change require a build?
Expand for guidance... - - `Yes` for any code change - - `Yes` for any build script change - - `Yes` for any docker build environment change - - `Yes` for any change affecting the cross test suite - - `No` for documentation-only changes - - `No` for trivial changes, for example fixing a typo. -
- If your change does not require a build, you can add [ci skip] to the end of your commit message.
- This will avoid costly and unnecessary builds in both the pull request and once it is merged. -
+- [ ] Did you do your best to avoid breaking changes? If one was needed, did you label the Jira ticket with "Breaking-Change" autoconfcmake MinMax Domain File Memory Pipe Socket TLS  -Framed http  zlib  +FramedHeader http  zlib  BinaryCompact JSON Multiplex ForkingNonblockingSimpleThreadedThreadPool @@ -39,7 +63,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes FLEX SDK 4.6 Yes -Yes +Yes Yes ActionScript @@ -50,7 +74,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes 2.48.22.56.0 YesYesYesYes -Yes +Yes YesYesYes Yes C (glib) @@ -59,42 +83,31 @@ The Language/Library Levels indicate the minimum and maximum versions that are u C++ 0.2.0 YesYes -C++98 (through 0.12.0)C++11 (after 0.12.0) +C++11 YesYesYesYesYesYes -YesYesYes +YesYesYesYes YesYesYesYes YesYesYesYes C++ C# -0.2.0 +0.2.0
Deprecated
use netstd Yes .NET 3.5 / mono 3.2.8.0.NET 4.6.1 / mono 4.6.2.7 YesYesYesYes -YesYes +YesYes YesYesYesYes YesYesYes C# (.NET) -Cocoa -0.2.0 - -unknown -YesYesYesYes -YesYes -YesYesYes -Yes -Cocoa - - Common LISP 0.12.0 Yes -SBCL 1.4.5SBCL 1.4.15 +SBCL 1.4.x YesYes -Yes +Yes YesYesYes Yes Common LISP @@ -105,7 +118,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 2.075.12.083.2 YesYesYesYesYes -YesYesYes +YesYesYes YesYesYes YesYesYesYes D @@ -114,9 +127,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Dart 0.10.0 Yes -1.22.11.24.3 +1.24.32.x Yes -YesYes +YesYes YesYesYesYes Dart @@ -127,18 +140,29 @@ The Language/Library Levels indicate the minimum and maximum versions that are u 2010unknown Yes -YesYes +YesYes YesYesYesYes Yes Delphi .NET Core -0.11.0 +0.11.0
Deprecated
use netstd Yes 2.1.42.2.101 YesYesYesYes -YesYes +YesYes +YesYesYesYes +Yes +.NET Core + + +.NET Standard +0.13.0 +Yes +.NET 4.5+, .NET Standard 2.x +YesYesYesYes +YesYes YesYesYesYes Yes .NET Core @@ -149,7 +173,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 18.320.0.4 YesYesYesYes -YesYes +YesYes YesYesYesYes Yes Erlang @@ -160,7 +184,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 1.7.61.11.4 YesYesYes -YesYesYes +YesYesYes YesYesYesYes Yes Go @@ -171,7 +195,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes 7.10.38.0.2 YesYesYesYes -YesYes +YesYes YesYesYes YesYes Haskell @@ -182,7 +206,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 3.2.13.4.4 YesYes -YesYes +YesYes YesYesYesYes Yes Haxe @@ -193,7 +217,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes 1.8.0_1511.8.0_191 YesYesYesYes -YesYesYes +YesYesYes YesYesYesYes YesYesYesYes Java SE @@ -204,7 +228,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u unknown YesYesYes -Yes +Yes YesYes Java ME @@ -213,9 +237,9 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Javascript 0.3.0 Yes -unknown +ES5ES6 YesYes -Yes +Yes YesYes Javascript @@ -226,7 +250,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 5.1.55.2.4 YesYes -YesYes +YesYes YesYesYes Yes Lua @@ -237,7 +261,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 6.x8.x YesYesYes -YesYes +YesYesYes YesYesYesYes Yes node.js @@ -248,7 +272,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 3.1.6 YesYes - + Yes Yes node.ts @@ -259,7 +283,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u 4.04.0 Yes -Yes +Yes Yes YesYes OCaml @@ -270,7 +294,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 5.22.15.26.1 YesYesYesYes -YesYes +YesYes YesYesYes YesYes Perl @@ -281,7 +305,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 7.0.227.2.10 YesYesYes -YesYes +YesYes YesYesYesYes YesYes PHP @@ -292,7 +316,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u YesYes 2.7.12, 3.5.22.7.15rc1, 3.6.7 YesYes -YesYes +YesYesYes YesYesYesYes YesYesYes Python @@ -303,7 +327,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 2.3.1p1122.5.1p57 YesYesYesYes -YesYes +YesYes YesYesYesYes YesYesYesYes Ruby @@ -314,7 +338,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 1.17.01.30.0 YesYes -Yes +Yes YesYesYes Yes Rust @@ -325,7 +349,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u unknown Yes - + Yes Smalltalk @@ -336,7 +360,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Yes 4.2.1 YesYesYesYes -YesYes +YesYes YesYesYes Yes Swift @@ -349,7 +373,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u autoconfcmake MinMax Domain File Memory Pipe Socket TLS  -Framed http  zlib  +FramedHeader http  zlib  BinaryCompact JSON Multiplex ForkingNonblockingSimpleThreadedThreadPool Open Issues @@ -358,7 +382,7 @@ The Language/Library Levels indicate the minimum and maximum versions that are u Build Systems Lang/Lib Levels (Tested) Low-Level Transports -Transport Wrappers +Transport Wrappers Protocols Servers From c63eacc684f4e4bada8381a9f8c06ea4644f6def Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 22 Feb 2019 09:11:35 -0500 Subject: [PATCH 230/756] Minor fix to LANGUAGES.md [ci skip] --- LANGUAGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LANGUAGES.md b/LANGUAGES.md index e84fecb62ed..4602ded6821 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -165,7 +165,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr YesYes YesYesYesYes Yes -.NET Core +.NET Standard Erlang From 6e5c0f6e315ea1cd8526789558bfd10d6cee2173 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 22 Feb 2019 09:14:17 -0500 Subject: [PATCH 231/756] Minor update to LANGUAGES.md [ci skip] --- LANGUAGES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LANGUAGES.md b/LANGUAGES.md index 4602ded6821..351013808cf 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -154,7 +154,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr YesYes YesYesYesYes Yes -.NET Core +.NET Core .NET Standard @@ -165,7 +165,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr YesYes YesYesYesYes Yes -.NET Standard +.NET Standard Erlang From 264a3f318ed3e9e51573f67f963c8509786bcec2 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 23 Feb 2019 13:11:40 +0100 Subject: [PATCH 232/756] additional test for TSimpleJSONProtocol --- lib/go/thrift/json_protocol.go | 5 +---- lib/go/thrift/simple_json_protocol.go | 4 ++-- lib/go/thrift/simple_json_protocol_test.go | 22 ++++++++++++++++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/lib/go/thrift/json_protocol.go b/lib/go/thrift/json_protocol.go index 7be685d43f2..800ac22c7bc 100644 --- a/lib/go/thrift/json_protocol.go +++ b/lib/go/thrift/json_protocol.go @@ -32,10 +32,7 @@ const ( // for references to _ParseContext see tsimplejson_protocol.go // JSON protocol implementation for thrift. -// -// This protocol produces/consumes a simple output format -// suitable for parsing by scripting languages. It should not be -// confused with the full-featured TJSONProtocol. +// Utilizes Simple JSON protocol // type TJSONProtocol struct { *TSimpleJSONProtocol diff --git a/lib/go/thrift/simple_json_protocol.go b/lib/go/thrift/simple_json_protocol.go index 2e8a71112a4..f5e0c05d189 100644 --- a/lib/go/thrift/simple_json_protocol.go +++ b/lib/go/thrift/simple_json_protocol.go @@ -60,7 +60,7 @@ func (p _ParseContext) String() string { return "UNKNOWN-PARSE-CONTEXT" } -// JSON protocol implementation for thrift. +// Simple JSON protocol implementation for thrift. // // This protocol produces/consumes a simple output format // suitable for parsing by scripting languages. It should not be @@ -1316,7 +1316,7 @@ func (p *TSimpleJSONProtocol) readNumeric() (Numeric, error) { func (p *TSimpleJSONProtocol) safePeekContains(b []byte) bool { for i := 0; i < len(b); i++ { a, _ := p.reader.Peek(i + 1) - if len(a) == 0 || a[i] != b[i] { + if len(a) < (i+1) || a[i] != b[i] { return false } } diff --git a/lib/go/thrift/simple_json_protocol_test.go b/lib/go/thrift/simple_json_protocol_test.go index 7b98082a4ee..0126da0a8e4 100644 --- a/lib/go/thrift/simple_json_protocol_test.go +++ b/lib/go/thrift/simple_json_protocol_test.go @@ -714,3 +714,25 @@ func TestWriteSimpleJSONProtocolMap(t *testing.T) { } trans.Close() } + +func TestWriteSimpleJSONProtocolSafePeek(t *testing.T) { + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + trans.Write([]byte{'a', 'b'}) + trans.Flush(context.Background()) + + test1 := p.safePeekContains([]byte{'a', 'b'}) + if !test1 { + t.Fatalf("Should match at test 1") + } + + test2 := p.safePeekContains([]byte{'a', 'b', 'c', 'd'}) + if test2 { + t.Fatalf("Should not match at test 2") + } + + test3 := p.safePeekContains([]byte{'x', 'y'}) + if test3 { + t.Fatalf("Should not match at test 3") + } +} From 1e41be40d8c0bcccda698c57f77fb5cb2a66f044 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 9 Feb 2019 11:50:03 +0100 Subject: [PATCH 233/756] THRIFT-4784 Thrift should throw when skipping over unexpected data Client: as3 Patch: Jens Geyer --- lib/as3/src/org/apache/thrift/protocol/TProtocolUtil.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/as3/src/org/apache/thrift/protocol/TProtocolUtil.as b/lib/as3/src/org/apache/thrift/protocol/TProtocolUtil.as index 513df954bee..22877b75b2b 100644 --- a/lib/as3/src/org/apache/thrift/protocol/TProtocolUtil.as +++ b/lib/as3/src/org/apache/thrift/protocol/TProtocolUtil.as @@ -141,7 +141,7 @@ package org.apache.thrift.protocol { break; } default: - break; + throw new TProtocolError(TProtocolError.INVALID_DATA, "invalid data"); } } } From 798e90aa8715ed0deff68ef4784926fe2be5c0ea Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 14 Feb 2019 16:46:38 -0500 Subject: [PATCH 234/756] THRIFT-4024, THRIFT-4783: throw when skipping invalid type (#1742) * THRIFT-4024: make c_glib throw on unsupported type when skipping * THRIFT-4783: throw on invalid skip (py) * THRIFT-4024: make cpp throw on unsupported type when skipping * THRIFT-4024: uniform skip behavior on unsupported type --- .../thrift/c_glib/protocol/thrift_protocol.c | 72 ++++++++++++------- lib/cpp/src/thrift/protocol/TProtocol.h | 12 ++-- lib/d/src/thrift/protocol/base.d | 8 +-- .../lib/src/protocol/t_protocol_util.dart | 2 +- lib/go/thrift/protocol.go | 2 - .../apache/thrift/protocol/TProtocolUtil.java | 3 +- lib/js/src/thrift.js | 3 - lib/lua/TProtocol.lua | 8 ++- lib/nodejs/lib/thrift/binary_protocol.js | 2 - lib/nodejs/lib/thrift/compact_protocol.js | 2 - lib/nodejs/lib/thrift/json_protocol.js | 2 - lib/ocaml/src/Thrift.ml | 3 +- lib/py/src/protocol/TProtocol.py | 8 ++- lib/rb/lib/thrift/protocol/base_protocol.rb | 4 +- lib/rb/spec/base_protocol_spec.rb | 1 - lib/swift/Sources/TProtocol.swift | 3 +- 16 files changed, 73 insertions(+), 62 deletions(-) diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c index 8296a8cad13..6e6ae4d9a0e 100644 --- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c +++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_protocol.c @@ -419,6 +419,13 @@ thrift_protocol_read_binary (ThriftProtocol *protocol, gpointer *buf, len, error); } +#define THRIFT_SKIP_RESULT_OR_RETURN(_RES, _CALL) \ + { \ + gint32 _x = (_CALL); \ + if (_x < 0) { return _x; } \ + (_RES) += _x; \ + } + gint32 thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) { @@ -469,24 +476,24 @@ thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) gchar *name; gint16 fid; ThriftType ftype; - result += thrift_protocol_read_struct_begin (protocol, &name, error); - + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_struct_begin (protocol, &name, error)) while (1) { - result += thrift_protocol_read_field_begin (protocol, &name, &ftype, - &fid, error); - if (result < 0) - { - return result; - } + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_field_begin (protocol, &name, &ftype, + &fid, error)) if (ftype == T_STOP) { break; } - result += thrift_protocol_skip (protocol, ftype, error); - result += thrift_protocol_read_field_end (protocol, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, ftype, error)) + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_field_end (protocol, error)) } - result += thrift_protocol_read_struct_end (protocol, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_struct_end (protocol, error)) return result; } case T_SET: @@ -494,13 +501,16 @@ thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) gint32 result = 0; ThriftType elem_type; guint32 i, size; - result += thrift_protocol_read_set_begin (protocol, &elem_type, &size, - error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_set_begin (protocol, &elem_type, &size, + error)) for (i = 0; i < size; i++) { - result += thrift_protocol_skip (protocol, elem_type, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, elem_type, error)) } - result += thrift_protocol_read_set_end (protocol, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_set_end (protocol, error)) return result; } case T_MAP: @@ -509,14 +519,18 @@ thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) ThriftType elem_type; ThriftType key_type; guint32 i, size; - result += thrift_protocol_read_map_begin (protocol, &key_type, &elem_type, &size, - error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_map_begin (protocol, &key_type, &elem_type, &size, + error)) for (i = 0; i < size; i++) { - result += thrift_protocol_skip (protocol, key_type, error); - result += thrift_protocol_skip (protocol, elem_type, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, key_type, error)) + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, elem_type, error)) } - result += thrift_protocol_read_map_end (protocol, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_map_end (protocol, error)) return result; } case T_LIST: @@ -524,18 +538,26 @@ thrift_protocol_skip (ThriftProtocol *protocol, ThriftType type, GError **error) gint32 result = 0; ThriftType elem_type; guint32 i, size; - result += thrift_protocol_read_list_begin (protocol, &elem_type, &size, - error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_list_begin (protocol, &elem_type, &size, + error)) for (i = 0; i < size; i++) { - result += thrift_protocol_skip (protocol, elem_type, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_skip (protocol, elem_type, error)) } - result += thrift_protocol_read_list_end (protocol, error); + THRIFT_SKIP_RESULT_OR_RETURN(result, + thrift_protocol_read_list_end (protocol, error)) return result; } default: - return 0; + break; } + + g_set_error (error, THRIFT_PROTOCOL_ERROR, + THRIFT_PROTOCOL_ERROR_INVALID_DATA, + "unrecognized type"); + return -1; } /* define the GError domain for Thrift protocols */ diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h index aa5beea92e9..6e2ddd25eb5 100644 --- a/lib/cpp/src/thrift/protocol/TProtocol.h +++ b/lib/cpp/src/thrift/protocol/TProtocol.h @@ -747,16 +747,12 @@ uint32_t skip(Protocol_& prot, TType type) { result += prot.readListEnd(); return result; } - case T_STOP: - case T_VOID: - case T_U64: - case T_UTF8: - case T_UTF16: - break; default: - throw TProtocolException(TProtocolException::INVALID_DATA); + break; } - return 0; + + throw TProtocolException(TProtocolException::INVALID_DATA, + "invalid TType"); } }}} // apache::thrift::protocol diff --git a/lib/d/src/thrift/protocol/base.d b/lib/d/src/thrift/protocol/base.d index 70648b3c39f..5b6d84514cb 100644 --- a/lib/d/src/thrift/protocol/base.d +++ b/lib/d/src/thrift/protocol/base.d @@ -260,7 +260,7 @@ protected: * in generated code. */ void skip(Protocol)(Protocol prot, TType type) if (is(Protocol : TProtocol)) { - final switch (type) { + switch (type) { case TType.BOOL: prot.readBool(); break; @@ -324,9 +324,9 @@ void skip(Protocol)(Protocol prot, TType type) if (is(Protocol : TProtocol)) { } prot.readSetEnd(); break; - case TType.STOP: goto case; - case TType.VOID: - assert(false, "Invalid field type passed."); + + default: + throw new TProtocolException(TProtocolException.Type.INVALID_DATA); } } diff --git a/lib/dart/lib/src/protocol/t_protocol_util.dart b/lib/dart/lib/src/protocol/t_protocol_util.dart index ad20068c201..841ea8217d7 100644 --- a/lib/dart/lib/src/protocol/t_protocol_util.dart +++ b/lib/dart/lib/src/protocol/t_protocol_util.dart @@ -101,7 +101,7 @@ class TProtocolUtil { break; default: - break; + throw new TProtocolError(TProtocolErrorType.INVALID_DATA, "Invalid data"); } } } diff --git a/lib/go/thrift/protocol.go b/lib/go/thrift/protocol.go index 615b7a4a8f3..2e6bc4b1619 100644 --- a/lib/go/thrift/protocol.go +++ b/lib/go/thrift/protocol.go @@ -96,8 +96,6 @@ func Skip(self TProtocol, fieldType TType, maxDepth int) (err error) { } switch fieldType { - case STOP: - return case BOOL: _, err = self.ReadBool() return diff --git a/lib/javame/src/org/apache/thrift/protocol/TProtocolUtil.java b/lib/javame/src/org/apache/thrift/protocol/TProtocolUtil.java index 9bf10f67ea4..c327448efbf 100644 --- a/lib/javame/src/org/apache/thrift/protocol/TProtocolUtil.java +++ b/lib/javame/src/org/apache/thrift/protocol/TProtocolUtil.java @@ -152,7 +152,8 @@ public static void skip(TProtocol prot, byte type, int maxDepth) break; } default: - break; + throw new TProtocolException(TProtocolException.INVALID_DATA, + "Unrecognized type " + type); } } } diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 9418ca37023..68b89248900 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -1376,9 +1376,6 @@ Thrift.Protocol.prototype = { skip: function(type) { var ret, i; switch (type) { - case Thrift.Type.STOP: - return null; - case Thrift.Type.BOOL: return this.readBool(); diff --git a/lib/lua/TProtocol.lua b/lib/lua/TProtocol.lua index 616e167a958..1306fb3d8c3 100644 --- a/lib/lua/TProtocol.lua +++ b/lib/lua/TProtocol.lua @@ -107,9 +107,7 @@ function TProtocolBase:readDouble() end function TProtocolBase:readString() end function TProtocolBase:skip(ttype) - if type == TType.STOP then - return - elseif ttype == TType.BOOL then + if ttype == TType.BOOL then self:readBool() elseif ttype == TType.BYTE then self:readByte() @@ -153,6 +151,10 @@ function TProtocolBase:skip(ttype) self:skip(ettype) end self:readListEnd() + else + terror(TProtocolException:new{ + message = 'Invalid data' + }) end end diff --git a/lib/nodejs/lib/thrift/binary_protocol.js b/lib/nodejs/lib/thrift/binary_protocol.js index b57c8c57635..6ab9c05a948 100644 --- a/lib/nodejs/lib/thrift/binary_protocol.js +++ b/lib/nodejs/lib/thrift/binary_protocol.js @@ -302,8 +302,6 @@ TBinaryProtocol.prototype.getTransport = function() { TBinaryProtocol.prototype.skip = function(type) { switch (type) { - case Type.STOP: - return; case Type.BOOL: this.readBool(); break; diff --git a/lib/nodejs/lib/thrift/compact_protocol.js b/lib/nodejs/lib/thrift/compact_protocol.js index 5c531e5d60e..302a88d4d84 100644 --- a/lib/nodejs/lib/thrift/compact_protocol.js +++ b/lib/nodejs/lib/thrift/compact_protocol.js @@ -854,8 +854,6 @@ TCompactProtocol.prototype.zigzagToI64 = function(n) { TCompactProtocol.prototype.skip = function(type) { switch (type) { - case Type.STOP: - return; case Type.BOOL: this.readBool(); break; diff --git a/lib/nodejs/lib/thrift/json_protocol.js b/lib/nodejs/lib/thrift/json_protocol.js index 727a3b2ffb1..7e2b7c90891 100644 --- a/lib/nodejs/lib/thrift/json_protocol.js +++ b/lib/nodejs/lib/thrift/json_protocol.js @@ -738,8 +738,6 @@ TJSONProtocol.prototype.getTransport = function() { */ TJSONProtocol.prototype.skip = function(type) { switch (type) { - case Type.STOP: - return; case Type.BOOL: this.readBool(); break; diff --git a/lib/ocaml/src/Thrift.ml b/lib/ocaml/src/Thrift.ml index f0d7a429659..063459ba0c1 100644 --- a/lib/ocaml/src/Thrift.ml +++ b/lib/ocaml/src/Thrift.ml @@ -206,8 +206,6 @@ struct (* skippage *) method skip typ = match typ with - | T_STOP -> () - | T_VOID -> () | T_BOOL -> ignore self#readBool | T_BYTE | T_I08 -> ignore self#readByte @@ -248,6 +246,7 @@ struct self#readListEnd) | T_UTF8 -> () | T_UTF16 -> () + | _ -> raise (Protocol.E (Protocol.INVALID_DATA, "Invalid data")) end class virtual factory = diff --git a/lib/py/src/protocol/TProtocol.py b/lib/py/src/protocol/TProtocol.py index 8314cf69df8..3456e8f0e85 100644 --- a/lib/py/src/protocol/TProtocol.py +++ b/lib/py/src/protocol/TProtocol.py @@ -191,9 +191,7 @@ def readUtf8(self): return self.readString().decode('utf8') def skip(self, ttype): - if ttype == TType.STOP: - return - elif ttype == TType.BOOL: + if ttype == TType.BOOL: self.readBool() elif ttype == TType.BYTE: self.readByte() @@ -232,6 +230,10 @@ def skip(self, ttype): for i in range(size): self.skip(etype) self.readListEnd() + else: + raise TProtocolException( + TProtocolException.INVALID_DATA, + "invalid TType") # tuple of: ( 'reader method' name, is_container bool, 'writer_method' name ) _TTYPE_HANDLERS = ( diff --git a/lib/rb/lib/thrift/protocol/base_protocol.rb b/lib/rb/lib/thrift/protocol/base_protocol.rb index 5c693e99f1a..4d83a21ddb7 100644 --- a/lib/rb/lib/thrift/protocol/base_protocol.rb +++ b/lib/rb/lib/thrift/protocol/base_protocol.rb @@ -323,8 +323,6 @@ def read_type(field_info) def skip(type) case type - when Types::STOP - nil when Types::BOOL read_bool when Types::BYTE @@ -367,6 +365,8 @@ def skip(type) skip(etype) end read_list_end + else + raise ProtocolException.new(ProtocolException::INVALID_DATA, 'Invalid data') end end diff --git a/lib/rb/spec/base_protocol_spec.rb b/lib/rb/spec/base_protocol_spec.rb index eca936b239d..cfa7573d8c5 100644 --- a/lib/rb/spec/base_protocol_spec.rb +++ b/lib/rb/spec/base_protocol_spec.rb @@ -163,7 +163,6 @@ @prot.skip(Thrift::Types::I64) @prot.skip(Thrift::Types::DOUBLE) @prot.skip(Thrift::Types::STRING) - @prot.skip(Thrift::Types::STOP) # should do absolutely nothing end it "should skip structs" do diff --git a/lib/swift/Sources/TProtocol.swift b/lib/swift/Sources/TProtocol.swift index a4e4a20fa91..b111e71bbbf 100644 --- a/lib/swift/Sources/TProtocol.swift +++ b/lib/swift/Sources/TProtocol.swift @@ -175,8 +175,9 @@ public extension TProtocol { try skip(type: elemType) } try readListEnd() + default: - return + throw TProtocolError(error: .invalidData, message: "Invalid data") } } } From a34f78385f3cd5105d9d82a8922837ffab56e281 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Mon, 25 Feb 2019 23:16:31 +0100 Subject: [PATCH 235/756] THRIFT-4812 haxelib readme still points to old ASF git repo Client: haxe Patch: Jens Geyer --- lib/haxe/README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/haxe/README.md b/lib/haxe/README.md index e74b7734fc6..c9f74b578d6 100644 --- a/lib/haxe/README.md +++ b/lib/haxe/README.md @@ -69,14 +69,12 @@ Thrift Haxe bindings Thrift Haxe bindings can be set up via the `haxelib` tool either from the official ASF repo, or via the github mirror. -- To set up any **stable version**, choose the appropriate branch (e.g. `1.0.0`, etc.): +- To set up any **stable version**, choose the appropriate branch (e.g. `0.12.0`): - - `haxelib git thrift https://git.apache.org/thrift.git 1.0.0 lib/haxe` - - `haxelib git thrift https://github.com/apache/thrift.git 1.0.0 lib/haxe` + - `haxelib git thrift https://github.com/apache/thrift.git 0.12.0 lib/haxe` - To set up the current **development version**, use the `master` branch: - - `haxelib git thrift https://git.apache.org/thrift.git master lib/haxe` - `haxelib git thrift https://github.com/apache/thrift.git master lib/haxe` As usual, the installed library can be updated using `haxelib upgrade` From 7a51197bed35f39118e705fc85a2bf5229a3251e Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Wed, 27 Feb 2019 08:36:37 -0500 Subject: [PATCH 236/756] 0.9.3.1 packaging fixups --- configure.ac | 14 -------------- lib/java/build.properties | 5 +---- lib/java/build.xml | 13 +++++++------ 3 files changed, 8 insertions(+), 24 deletions(-) diff --git a/configure.ac b/configure.ac index 18e323341b4..316fb3d19cc 100755 --- a/configure.ac +++ b/configure.ac @@ -553,20 +553,6 @@ AC_CHECK_LIB(rt, clock_gettime) AC_CHECK_LIB(socket, setsockopt) if test "$have_cpp" = "yes" ; then -# mingw toolchain used to build "Thrift Compiler for Windows" -# does not support libcrypto, so we just check if we building the cpp library -AC_CHECK_LIB(crypto, - BN_init, - [AC_CHECK_LIB(ssl, - SSL_ctrl, - [LIBS="-lssl -lcrypto $LIBS"], - [AC_MSG_ERROR(["Error: libssl required"])], - -lcrypto - )], - [AC_MSG_ERROR(["Error: libcrypto required."])] -) -fi - AC_TYPE_INT16_T AC_TYPE_INT32_T AC_TYPE_INT64_T diff --git a/lib/java/build.properties b/lib/java/build.properties index abe1c10d0da..2eef66b4a80 100644 --- a/lib/java/build.properties +++ b/lib/java/build.properties @@ -1,10 +1,7 @@ -thrift.version=0.9.3 +thrift.version=0.9.3-1 thrift.groupid=org.apache.thrift release=true -# Jar Versions -mvn.ant.task.version=2.1.3 - # Local Install paths install.path=/usr/local/lib install.javadoc.path=${install.path} diff --git a/lib/java/build.xml b/lib/java/build.xml index 679142e90bd..24628df984f 100755 --- a/lib/java/build.xml +++ b/lib/java/build.xml @@ -325,10 +325,10 @@ - + + @@ -390,7 +390,8 @@ - + + @@ -403,7 +404,7 @@ - + From 68ff6cddc055acd9f5611c297c7721a573745678 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Tue, 26 Feb 2019 21:38:04 +0100 Subject: [PATCH 237/756] THRIFT-4813 NamedPipes may not work in all cases Client: netstd Patch: Jens Geyer --- .../Thrift.IntegrationTests.csproj | 10 +- ...rift.PublicInterfaces.Compile.Tests.csproj | 2 +- .../Tests/Thrift.Tests/Thrift.Tests.csproj | 10 +- lib/netstd/Thrift/Thrift.csproj | 19 ++- .../Server/TNamedPipeServerTransport.cs | 141 ++++++++++++++++-- test/netstd/Client/Client.csproj | 4 +- test/netstd/Server/Server.csproj | 6 +- tutorial/netstd/Interfaces/Interfaces.csproj | 2 +- tutorial/netstd/Server/Server.csproj | 8 +- 9 files changed, 160 insertions(+), 42 deletions(-) diff --git a/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj b/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj index 4a235edc034..381d8aa471a 100644 --- a/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj +++ b/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj @@ -32,11 +32,11 @@ - - - - - + + + + + diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj index 6687a9d5ec1..58f61a2f16c 100644 --- a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj @@ -33,7 +33,7 @@ - + diff --git a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj index 3150910ce99..434424dbae0 100644 --- a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj +++ b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj @@ -21,11 +21,11 @@ netcoreapp2.0 - - - - - + + + + + diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj index e2f17250990..86de1f8bacf 100644 --- a/lib/netstd/Thrift/Thrift.csproj +++ b/lib/netstd/Thrift/Thrift.csproj @@ -34,17 +34,22 @@ false + + true + + - - - - - + + + + + - + + - + diff --git a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs index be6d0fc59bb..cd5683b46c2 100644 --- a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs @@ -1,13 +1,13 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -15,10 +15,15 @@ // specific language governing permissions and limitations // under the License. +using Microsoft.Win32.SafeHandles; using System; using System.IO.Pipes; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; +using System.ComponentModel; +using System.Security.AccessControl; +using System.Security.Principal; namespace Thrift.Transport.Server { @@ -51,8 +56,8 @@ public override void Close() { try { - //TODO: check for disconection - _stream.Disconnect(); + if (_stream.IsConnected) + _stream.Disconnect(); _stream.Dispose(); } finally @@ -72,25 +77,34 @@ private void EnsurePipeInstance() { if (_stream == null) { - var direction = PipeDirection.InOut; - var maxconn = 254; - var mode = PipeTransmissionMode.Byte; + const PipeDirection direction = PipeDirection.InOut; + const int maxconn = NamedPipeServerStream.MaxAllowedServerInstances; + const PipeTransmissionMode mode = PipeTransmissionMode.Byte; + const int inbuf = 4096; + const int outbuf = 4096; var options = _asyncMode ? PipeOptions.Asynchronous : PipeOptions.None; - var inbuf = 4096; - var outbuf = 4096; - // TODO: security + + + // TODO: "CreatePipeNative" ist only a workaround, and there are have basically two possible outcomes: + // - once NamedPipeServerStream() gets a CTOR that supports pipesec, remove CreatePipeNative() + // - if 31190 gets resolved before, use _stream.SetAccessControl(pipesec) instead of CreatePipeNative() + // EITHER WAY, + // - if CreatePipeNative() finally gets removed, also remove "allow unsafe code" from the project settings try { - _stream = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, outbuf); + var handle = CreatePipeNative(_pipeAddress, inbuf, outbuf); + if( (handle != null) && (!handle.IsInvalid)) + _stream = new NamedPipeServerStream(PipeDirection.InOut, _asyncMode, false, handle); + else + _stream = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, outbuf/*, pipesec*/); } catch (NotImplementedException) // Mono still does not support async, fallback to sync { if (_asyncMode) { options &= (~PipeOptions.Asynchronous); - _stream = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, - outbuf); + _stream = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, outbuf); _asyncMode = false; } else @@ -101,6 +115,103 @@ private void EnsurePipeInstance() } } + + #region CreatePipeNative workaround + + + [StructLayout(LayoutKind.Sequential)] + internal class SECURITY_ATTRIBUTES + { + internal int nLength = 0; + internal IntPtr lpSecurityDescriptor = IntPtr.Zero; + internal int bInheritHandle = 0; + } + + + private const string Kernel32 = "kernel32.dll"; + + [DllImport(Kernel32, SetLastError = true)] + internal static extern IntPtr CreateNamedPipe( + string lpName, uint dwOpenMode, uint dwPipeMode, + uint nMaxInstances, uint nOutBufferSize, uint nInBufferSize, uint nDefaultTimeOut, + SECURITY_ATTRIBUTES pipeSecurityDescriptor + ); + + + + // Workaround: create the pipe via API call + // we have to do it this way, since NamedPipeServerStream() for netstd still lacks a few CTORs + // and _stream.SetAccessControl(pipesec); only keeps throwing ACCESS_DENIED errors at us + // References: + // - https://github.com/dotnet/corefx/issues/30170 (closed, continued in 31190) + // - https://github.com/dotnet/corefx/issues/31190 System.IO.Pipes.AccessControl package does not work + // - https://github.com/dotnet/corefx/issues/24040 NamedPipeServerStream: Provide support for WRITE_DAC + // - https://github.com/dotnet/corefx/issues/34400 Have a mechanism for lower privileged user to connect to a privileged user's pipe + private SafePipeHandle CreatePipeNative(string name, int inbuf, int outbuf) + { + if (Environment.OSVersion.Platform != PlatformID.Win32NT) + return null; // Windows only + + var pinningHandle = new GCHandle(); + try + { + // owner gets full access, everyone else read/write + var pipesec = new PipeSecurity(); + using (var currentIdentity = WindowsIdentity.GetCurrent()) + { + var sidOwner = currentIdentity.Owner; + var sidWorld = new SecurityIdentifier(WellKnownSidType.WorldSid, null); + + pipesec.SetOwner(sidOwner); + pipesec.AddAccessRule(new PipeAccessRule(sidOwner, PipeAccessRights.FullControl, AccessControlType.Allow)); + pipesec.AddAccessRule(new PipeAccessRule(sidWorld, PipeAccessRights.ReadWrite, AccessControlType.Allow)); + } + + // create a security descriptor and assign it to the security attribs + var secAttrs = new SECURITY_ATTRIBUTES(); + byte[] sdBytes = pipesec.GetSecurityDescriptorBinaryForm(); + pinningHandle = GCHandle.Alloc(sdBytes, GCHandleType.Pinned); + unsafe { + fixed (byte* pSD = sdBytes) { + secAttrs.lpSecurityDescriptor = (IntPtr)pSD; + } + } + + // a bunch of constants we will need shortly + const int PIPE_ACCESS_DUPLEX = 0x00000003; + const int FILE_FLAG_OVERLAPPED = 0x40000000; + const int WRITE_DAC = 0x00040000; + const int PIPE_TYPE_BYTE = 0x00000000; + const int PIPE_READMODE_BYTE = 0x00000000; + const int PIPE_UNLIMITED_INSTANCES = 255; + + // create the pipe via API call + var rawHandle = CreateNamedPipe( + @"\\.\pipe\" + name, + PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | WRITE_DAC, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, + PIPE_UNLIMITED_INSTANCES, (uint)inbuf, (uint)outbuf, + 5 * 1000, + secAttrs + ); + + // make a SafePipeHandle() from it + var handle = new SafePipeHandle(rawHandle, true); + if (handle.IsInvalid) + throw new Win32Exception(Marshal.GetLastWin32Error()); + + // return it (to be packaged) + return handle; + } + finally + { + if (pinningHandle.IsAllocated) + pinningHandle.Free(); + } + } + + #endregion + protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) { try @@ -188,4 +299,4 @@ protected override void Dispose(bool disposing) } } } -} \ No newline at end of file +} diff --git a/test/netstd/Client/Client.csproj b/test/netstd/Client/Client.csproj index 38e455dbe03..ed30c30dd27 100644 --- a/test/netstd/Client/Client.csproj +++ b/test/netstd/Client/Client.csproj @@ -31,9 +31,9 @@ false - + - + diff --git a/test/netstd/Server/Server.csproj b/test/netstd/Server/Server.csproj index 60e1968b594..44f46c90c04 100644 --- a/test/netstd/Server/Server.csproj +++ b/test/netstd/Server/Server.csproj @@ -31,9 +31,11 @@ false - + + + - + diff --git a/tutorial/netstd/Interfaces/Interfaces.csproj b/tutorial/netstd/Interfaces/Interfaces.csproj index 68d87476e32..4ebeb4f4297 100644 --- a/tutorial/netstd/Interfaces/Interfaces.csproj +++ b/tutorial/netstd/Interfaces/Interfaces.csproj @@ -33,7 +33,7 @@ - + diff --git a/tutorial/netstd/Server/Server.csproj b/tutorial/netstd/Server/Server.csproj index 4b20a3b055a..fbc2c03706e 100644 --- a/tutorial/netstd/Server/Server.csproj +++ b/tutorial/netstd/Server/Server.csproj @@ -35,10 +35,10 @@ - - - - + + + + From 92c660f541fff657682f8239b6a995f3b71e6214 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 23 Feb 2019 13:11:40 +0100 Subject: [PATCH 238/756] additional test for TSimpleJSONProtocol --- lib/go/thrift/json_protocol.go | 5 +---- lib/go/thrift/simple_json_protocol.go | 4 ++-- lib/go/thrift/simple_json_protocol_test.go | 22 ++++++++++++++++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/lib/go/thrift/json_protocol.go b/lib/go/thrift/json_protocol.go index 7be685d43f2..800ac22c7bc 100644 --- a/lib/go/thrift/json_protocol.go +++ b/lib/go/thrift/json_protocol.go @@ -32,10 +32,7 @@ const ( // for references to _ParseContext see tsimplejson_protocol.go // JSON protocol implementation for thrift. -// -// This protocol produces/consumes a simple output format -// suitable for parsing by scripting languages. It should not be -// confused with the full-featured TJSONProtocol. +// Utilizes Simple JSON protocol // type TJSONProtocol struct { *TSimpleJSONProtocol diff --git a/lib/go/thrift/simple_json_protocol.go b/lib/go/thrift/simple_json_protocol.go index 2e8a71112a4..f5e0c05d189 100644 --- a/lib/go/thrift/simple_json_protocol.go +++ b/lib/go/thrift/simple_json_protocol.go @@ -60,7 +60,7 @@ func (p _ParseContext) String() string { return "UNKNOWN-PARSE-CONTEXT" } -// JSON protocol implementation for thrift. +// Simple JSON protocol implementation for thrift. // // This protocol produces/consumes a simple output format // suitable for parsing by scripting languages. It should not be @@ -1316,7 +1316,7 @@ func (p *TSimpleJSONProtocol) readNumeric() (Numeric, error) { func (p *TSimpleJSONProtocol) safePeekContains(b []byte) bool { for i := 0; i < len(b); i++ { a, _ := p.reader.Peek(i + 1) - if len(a) == 0 || a[i] != b[i] { + if len(a) < (i+1) || a[i] != b[i] { return false } } diff --git a/lib/go/thrift/simple_json_protocol_test.go b/lib/go/thrift/simple_json_protocol_test.go index 7b98082a4ee..0126da0a8e4 100644 --- a/lib/go/thrift/simple_json_protocol_test.go +++ b/lib/go/thrift/simple_json_protocol_test.go @@ -714,3 +714,25 @@ func TestWriteSimpleJSONProtocolMap(t *testing.T) { } trans.Close() } + +func TestWriteSimpleJSONProtocolSafePeek(t *testing.T) { + trans := NewTMemoryBuffer() + p := NewTSimpleJSONProtocol(trans) + trans.Write([]byte{'a', 'b'}) + trans.Flush(context.Background()) + + test1 := p.safePeekContains([]byte{'a', 'b'}) + if !test1 { + t.Fatalf("Should match at test 1") + } + + test2 := p.safePeekContains([]byte{'a', 'b', 'c', 'd'}) + if test2 { + t.Fatalf("Should not match at test 2") + } + + test3 := p.safePeekContains([]byte{'x', 'y'}) + if test3 { + t.Fatalf("Should not match at test 3") + } +} From 5e649973ebee6a0e272bff8979e92d1e8ce91737 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 14 Jan 2019 12:07:10 -0500 Subject: [PATCH 239/756] THRIFT-4691: ensure CPAN module runs unit tests --- configure.ac | 2 +- lib/perl/MANIFEST.SKIP | 5 +++-- lib/perl/Makefile.PL | 13 +++++++++++++ lib/perl/Makefile.am | 4 ++-- lib/perl/build-cpan-dist.sh | 5 ++++- lib/perl/{test => t}/Makefile.am | 0 lib/perl/{test => t}/memory_buffer.t | 0 lib/perl/{test => t}/multiplex.t | 0 lib/perl/{test => t}/processor.t | 0 9 files changed, 23 insertions(+), 6 deletions(-) rename lib/perl/{test => t}/Makefile.am (100%) rename lib/perl/{test => t}/memory_buffer.t (100%) rename lib/perl/{test => t}/multiplex.t (100%) rename lib/perl/{test => t}/processor.t (100%) diff --git a/configure.ac b/configure.ac index b07b5de5a90..ef5663b1c84 100755 --- a/configure.ac +++ b/configure.ac @@ -842,7 +842,7 @@ AC_CONFIG_FILES([ lib/nodejs/Makefile lib/nodets/Makefile lib/perl/Makefile - lib/perl/test/Makefile + lib/perl/t/Makefile lib/php/Makefile lib/php/test/Makefile lib/dart/Makefile diff --git a/lib/perl/MANIFEST.SKIP b/lib/perl/MANIFEST.SKIP index 7963b42ad80..9b044509e50 100644 --- a/lib/perl/MANIFEST.SKIP +++ b/lib/perl/MANIFEST.SKIP @@ -8,6 +8,7 @@ Makefile Makefile.am Makefile.in pm_to_blib -test/Makefile.am -test/Makefile.in +t/Makefile +t/Makefile.am +t/Makefile.in tools/FixupDist.pl diff --git a/lib/perl/Makefile.PL b/lib/perl/Makefile.PL index bdeaad2b7bc..5e60ab40aee 100644 --- a/lib/perl/Makefile.PL +++ b/lib/perl/Makefile.PL @@ -33,4 +33,17 @@ WriteMakefile( ABSTRACT => 'Apache Thrift is a software framework for scalable c 'Bit::Vector' => 0, 'Class::Accessor' => 0 }, +# SIGN => 1, VERSION_FROM => 'lib/Thrift.pm' ); + +# THRIFT-4691 +package MY; # so that "SUPER" works right +sub test { + # Adds gen-perl and gen-perl2 to the test execution as include paths + # Could not find anything in MakeMaker that would do this... + my @result; + for (@result = shift->SUPER::test(@_)) { + s/\$\(TEST_FILES\)/-Igen-perl -Igen-perl2 \$(TEST_FILES)/ig; + } + @result; +} diff --git a/lib/perl/Makefile.am b/lib/perl/Makefile.am index fa0f16b8af0..abae1e77fe4 100644 --- a/lib/perl/Makefile.am +++ b/lib/perl/Makefile.am @@ -17,7 +17,7 @@ # under the License. # -SUBDIRS = test +SUBDIRS = t Makefile-perl.mk : Makefile.PL $(PERL) Makefile.PL MAKEFILE=Makefile-perl.mk INSTALLDIRS=$(INSTALLDIRS) INSTALL_BASE=$(PERL_PREFIX) @@ -95,7 +95,7 @@ BUILT_SOURCES = $(PERL_GEN) check-local: $(PERL_GEN) $(PERL) -Iblib/lib -I@abs_srcdir@ -I@builddir@/gen-perl2 -I@builddir@/gen-perl \ - @abs_srcdir@/test.pl @abs_srcdir@/test/*.t + @abs_srcdir@/test.pl @abs_srcdir@/t/*.t $(THRIFTTEST_GEN): $(THRIFT_IF) $(THRIFT) $(THRIFT) --gen perl $< diff --git a/lib/perl/build-cpan-dist.sh b/lib/perl/build-cpan-dist.sh index ae22e7e623c..ac0ff0bc0b3 100755 --- a/lib/perl/build-cpan-dist.sh +++ b/lib/perl/build-cpan-dist.sh @@ -12,9 +12,10 @@ rm -rf Thrift-* # setup cpan without a prompt echo | cpan -cpan install HTTP::Date +cpan install HTTP::Date Log::Log4perl cpan install CPAN cpan install CPAN::Meta ExtUtils::MakeMaker JSON::PP +# cpan install Module::Signature perl Makefile.PL rm MYMETA.yml @@ -47,6 +48,8 @@ if [[ "$DISTDIR" != "$NEWDIR" ]]; then fi cd $DISTDIR cp -p ../Makefile.PL . +cp -pr ../gen-perl . +cp -pr ../gen-perl2 . perl ../tools/FixupDist.pl cd .. tar cvzf $DISTFILE $DISTDIR diff --git a/lib/perl/test/Makefile.am b/lib/perl/t/Makefile.am similarity index 100% rename from lib/perl/test/Makefile.am rename to lib/perl/t/Makefile.am diff --git a/lib/perl/test/memory_buffer.t b/lib/perl/t/memory_buffer.t similarity index 100% rename from lib/perl/test/memory_buffer.t rename to lib/perl/t/memory_buffer.t diff --git a/lib/perl/test/multiplex.t b/lib/perl/t/multiplex.t similarity index 100% rename from lib/perl/test/multiplex.t rename to lib/perl/t/multiplex.t diff --git a/lib/perl/test/processor.t b/lib/perl/t/processor.t similarity index 100% rename from lib/perl/test/processor.t rename to lib/perl/t/processor.t From 5ecaeb9d4a6a7ca8a553e3c346434f59cf265e78 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 22 Jan 2019 15:22:04 +0100 Subject: [PATCH 240/756] THRIFT-4746: changes for publishing 0.12.0 to maven; fix java debug vs. release build with cmake --- .travis.yml | 6 ++++++ lib/java/CMakeLists.txt | 17 ++++++++++++----- lib/java/README.md | 6 +++++- lib/java/build.gradle | 1 + lib/java/gradle.properties | 16 +++++++++++++--- lib/java/gradle/publishing.gradle | 6 +++--- .../gradle/wrapper/gradle-wrapper.properties | 2 +- 7 files changed, 41 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index e09b8a4a3be..54ebe00680b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -135,6 +135,12 @@ jobs: - script: build/docker/run.sh env: - JOB="CMake" + - BUILD_ARG="-DCMAKE_BUILD_TYPE=Debug" + + - script: build/docker/run.sh + env: + - JOB="CMake" + - BUILD_ARG="-DCMAKE_BUILD_TYPE=Release" # C++ specific options: compiler plug-in, threading model - script: build/docker/run.sh diff --git a/lib/java/CMakeLists.txt b/lib/java/CMakeLists.txt index 46064e6008a..a67845aba5d 100644 --- a/lib/java/CMakeLists.txt +++ b/lib/java/CMakeLists.txt @@ -18,6 +18,7 @@ # if(ANDROID) + set(THRIFT_AAR outputs/aar/thrift-debug.aar outputs/aar/thrift-release.aar) add_custom_command( OUTPUT ${THRIFT_AAR} @@ -27,7 +28,7 @@ if(ANDROID) ) add_custom_target(thrift_aar ALL DEPENDS ${THRIFT_AAR}) -else(ANDROID) +else() if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") set(JAVA_INSTALL_DIR "${LIB_INSTALL_DIR}/java") @@ -41,11 +42,16 @@ else(ANDROID) set(JAVA_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}/java") endif() + set(PRELEASE "true") + if (CMAKE_BUILD_TYPE MATCHES DEBUG) + set(PRELEASE "false") + endif () + add_custom_target(ThriftJava ALL COMMENT "Building Java library using Gradle Wrapper" COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} assemble --console=plain --no-daemon - -Prelease=true + -Prelease=${PRELEASE} -Pthrift.version=${thrift_VERSION} "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} @@ -56,7 +62,7 @@ else(ANDROID) COMMENT "Publishing Java Library to Apache Maven staging" COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} clean uploadArchives --console=plain --no-daemon - -Prelease=true + -Prelease=${PRELEASE} -Pthrift.version=${thrift_VERSION} "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} @@ -78,10 +84,11 @@ else(ANDROID) add_test(NAME JavaTest COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} test --console=plain --no-daemon - -Prelease=true + -Prelease=${PRELEASE} -Pthrift.version=${thrift_VERSION} "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" "-Pthrift.compiler=${THRIFT_COMPILER}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endif() -endif(ANDROID) + +endif() diff --git a/lib/java/README.md b/lib/java/README.md index 1e4aed22a23..de515a5ce7d 100644 --- a/lib/java/README.md +++ b/lib/java/README.md @@ -138,11 +138,15 @@ properties to it. mavenUser=meMyselfAndI mavenPassword=MySuperAwesomeSecretPassword +NOTE: If you do not have a secring.gpg file, see the +[gradle signing docs](https://docs.gradle.org/current/userguide/signing_plugin.html) +for instructions on how to generate it. + It is also possible to manually publish using the Gradle build directly. With the key information and credentials in place the following will generate if needed the build artifacts and proceed to publish the results. - ./gradlew -Prelease=true -Pthrift.version=0.11.0 uploadArchives + ./gradlew -Prelease=true uploadArchives It is also possible to override the target repository for the Maven Publication by using a Gradle property, for example you can publish signed JAR files to your diff --git a/lib/java/build.gradle b/lib/java/build.gradle index 4302f779db4..6dd35e45724 100644 --- a/lib/java/build.gradle +++ b/lib/java/build.gradle @@ -20,6 +20,7 @@ // Using the legacy plugin classpath for Clover so it can be loaded optionally buildscript { repositories { + mavenCentral() google() jcenter() gradlePluginPortal() diff --git a/lib/java/gradle.properties b/lib/java/gradle.properties index 4955b4cdb3e..58ca5f8a538 100644 --- a/lib/java/gradle.properties +++ b/lib/java/gradle.properties @@ -3,7 +3,7 @@ # the properties to minimize the changes in the dependencies. thrift.version=0.12.0 thrift.groupid=org.apache.thrift -release=true +release=false # Local Install paths install.path=/usr/local/lib @@ -25,9 +25,19 @@ maven-repository-url=https://repository.apache.org/service/local/staging/deploy/ maven-repository-id=apache.releases.https # Dependency versions -httpclient.version=4.4.1 +httpclient.version=4.5.6 httpcore.version=4.4.1 -slf4j.version=1.7.12 +slf4j.version=1.7.25 servlet.version=2.5 junit.version=4.12 mockito.version=1.9.5 + +# Signing key information for artifacts PGP signature (values are examples) +# signing.keyId=ABCD0123 +# signing.password=signingPassword +# signing.secretKeyRingFile=/root/.gnupg/secring.gpg + +# Apache Maven staging repository user credentials +# mavenUser=mavenUser +# mavenPassword=mySuperSecretPassword + diff --git a/lib/java/gradle/publishing.gradle b/lib/java/gradle/publishing.gradle index 961d58f7820..029bff93d77 100644 --- a/lib/java/gradle/publishing.gradle +++ b/lib/java/gradle/publishing.gradle @@ -61,9 +61,9 @@ def configurePom(pom) { url 'http://thrift.apache.org' scm { - url 'https://git-wip-us.apache.org/repos/asf?p=thrift.git' - connection 'scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git' - developerConnection 'scm:git:https://git-wip-us.apache.org/repos/asf/thrift.git' + url 'https://github.com/apache/thrift' + connection 'scm:git:https://github.com/apache/thrift.git' + developerConnection 'scm:git:git@github.com:apache/thrift.git' } licenses { diff --git a/lib/java/gradle/wrapper/gradle-wrapper.properties b/lib/java/gradle/wrapper/gradle-wrapper.properties index 2c2bbe5f9a8..826c82f1217 100644 --- a/lib/java/gradle/wrapper/gradle-wrapper.properties +++ b/lib/java/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip From 52da9ab8011da02fbf8947f5b371094cbcf93af9 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 22 Jan 2019 20:16:39 +0100 Subject: [PATCH 241/756] THRIFT-4750: as3 changes to build and publish to maven central --- .gitignore | 2 + build/docker/ubuntu-bionic/Dockerfile | 8 + configure.ac | 29 +++ lib/Makefile.am | 4 + lib/as3/CMakeLists.txt | 68 +++++++ lib/as3/Makefile.am | 60 ++++++ lib/as3/README.md | 37 ++++ lib/as3/build.gradle | 56 ++++++ lib/as3/build.properties | 5 - lib/as3/build.xml | 182 ------------------ lib/as3/gradle.properties | 22 +++ lib/as3/gradle/publishing.gradle | 96 +++++++++ lib/as3/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 55190 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + lib/as3/gradlew | 172 +++++++++++++++++ lib/as3/gradlew.bat | 84 ++++++++ lib/as3/settings.gradle | 20 ++ lib/java/build.gradle | 1 - lib/java/gradle.properties | 10 - 19 files changed, 663 insertions(+), 198 deletions(-) create mode 100644 lib/as3/CMakeLists.txt create mode 100644 lib/as3/Makefile.am create mode 100644 lib/as3/README.md create mode 100644 lib/as3/build.gradle delete mode 100644 lib/as3/build.properties delete mode 100755 lib/as3/build.xml create mode 100644 lib/as3/gradle.properties create mode 100644 lib/as3/gradle/publishing.gradle create mode 100644 lib/as3/gradle/wrapper/gradle-wrapper.jar create mode 100644 lib/as3/gradle/wrapper/gradle-wrapper.properties create mode 100755 lib/as3/gradlew create mode 100644 lib/as3/gradlew.bat create mode 100644 lib/as3/settings.gradle diff --git a/.gitignore b/.gitignore index b7f7b454bb2..4873d98217f 100644 --- a/.gitignore +++ b/.gitignore @@ -105,6 +105,8 @@ project.lock.json /contrib/fb303/py/fb303/ttypes.py /depcomp /install-sh +/lib/as3/.gradle/ +/lib/as3/build/ /lib/cl/backport-update.zip /lib/cl/lib /lib/cl/run-tests diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index a8c1417ac9f..aef35c558c5 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -72,10 +72,18 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ llvm \ ninja-build \ pkg-config \ + unzip \ valgrind \ vim ENV PATH /usr/lib/llvm-6.0/bin:$PATH +# lib/as3 (ActionScript) +RUN mkdir -p /usr/local/adobe/flex/4.6 && \ + cd /usr/local/adobe/flex/4.6 && \ + wget -q "http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip" && \ + unzip flex_sdk_4.6.zip +ENV FLEX_HOME /usr/local/adobe/flex/4.6 + RUN apt-get install -y --no-install-recommends \ `# C++ dependencies` \ libboost-all-dev \ diff --git a/configure.ac b/configure.ac index ef5663b1c84..bcda1e07e4a 100755 --- a/configure.ac +++ b/configure.ac @@ -119,6 +119,7 @@ AC_ARG_ENABLE([libs], have_libs=yes if test "$enable_libs" = "no"; then have_libs="no" + with_as3="no" with_cpp="no" with_c_glib="no" with_cl="no" @@ -143,6 +144,18 @@ if test "$enable_libs" = "no"; then with_rs="no" fi +AX_THRIFT_LIB(as3, [as3], yes) +have_as3=no +if test "$with_as3" = "yes"; then + if test "${FLEX_HOME+set}" = set; then + AC_PATH_PROGS([FLEX_COMPC], [compc], "fail", [$PATH$PATH_SEPARATOR$FLEX_HOME/bin]) + if test "$FLEX_COMPC" != "fail"; then + have_as3="yes" + fi + fi +fi +AM_CONDITIONAL(WITH_AS3, [test "$have_as3" = "yes"]) + AX_THRIFT_LIB(cpp, [C++], yes) have_cpp=no if test "$with_cpp" = "yes"; then @@ -202,6 +215,7 @@ if test "$with_c_glib" = "yes"; then PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.0], have_glib2=yes, have_glib2=no) PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.0], have_gobject2=yes, have_gobject2=no) if test "$have_glib2" = "yes" -a "$have_gobject2" = "yes" ; then + AC_PATH_PROG([GSETTINGS], [gsettings]) have_c_glib="yes" fi fi @@ -813,6 +827,7 @@ AC_CONFIG_FILES([ compiler/cpp/test/Makefile compiler/cpp/src/thrift/version.h lib/Makefile + lib/as3/Makefile lib/cl/Makefile lib/cpp/Makefile lib/cpp/test/Makefile @@ -893,6 +908,8 @@ AC_CONFIG_FILES([ tutorial/rs/Makefile ]) +if test "$have_as3" = "yes" ; then MAYBE_AS3="as3" ; else MAYBE_AS3="" ; fi +AC_SUBST([MAYBE_AS3]) if test "$have_cpp" = "yes" ; then MAYBE_CPP="cpp" ; else MAYBE_CPP="" ; fi AC_SUBST([MAYBE_CPP]) if test "$have_c_glib" = "yes" ; then MAYBE_C_GLIB="c_glib" ; else MAYBE_C_GLIB="" ; fi @@ -940,6 +957,7 @@ AC_OUTPUT echo echo "$PACKAGE $VERSION" echo +echo "Building ActionScript3 Library : $have_as3" echo "Building C (GLib) Library .... : $have_c_glib" echo "Building C# (Mono) Library ... : $have_csharp" echo "Building C++ Library ......... : $have_cpp" @@ -962,6 +980,17 @@ echo "Building Py3 Library ......... : $have_py3" echo "Building Ruby Library ........ : $have_ruby" echo "Building Rust Library ........ : $have_rs" +if test "$have_as3" = "yes" ; then + echo + echo "ActionScript Library:" + echo " FLEX_HOME ................. : $FLEX_HOME" + echo " Using compc version ....... : $($FLEX_COMPC --version)" +fi +if test "$have_c_glib" = "yes" ; then + echo + echo "C (glib):" + echo " Using glib version ........ : $($GSETTINGS --version)" +fi if test "$have_csharp" = "yes" ; then echo echo "C# Library:" diff --git a/lib/Makefile.am b/lib/Makefile.am index b31560915e7..1a9177a3f6c 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -20,6 +20,10 @@ SUBDIRS = json xml PRECROSS_TARGET = +if WITH_AS3 +SUBDIRS += as3 +endif + if WITH_CPP # cpp dir is picked directly by plugin build if !WITH_PLUGIN diff --git a/lib/as3/CMakeLists.txt b/lib/as3/CMakeLists.txt new file mode 100644 index 00000000000..999905da0aa --- /dev/null +++ b/lib/as3/CMakeLists.txt @@ -0,0 +1,68 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +if (IS_ABSOLUTE "${LIB_INSTALL_DIR}") + set(AS3_INSTALL_DIR "${LIB_INSTALL_DIR}/as3") +else () + set(AS3_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/as3") +endif () + +set(PRELEASE "true") +if (CMAKE_BUILD_TYPE MATCHES DEBUG) + set(PRELEASE "false") +endif () + +add_custom_target(ThriftAs3 ALL + COMMENT "Building as3 library using Gradle Wrapper" + COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} compileFlex + --console=plain --no-daemon + -Prelease=${PRELEASE} + "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + +# Enable publishing from CMake if the publishing information is provided +if (NOT CMAKE_BUILD_TYPE MATCHES DEBUG) + add_custom_target(MavenPublishAs3 + COMMENT "Publishing as3 library to Apache Maven staging" + COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} clean publishMavenPublicationToMavenRepository + --console=plain --no-daemon + -Prelease=${PRELEASE} + -Psign=${PRELEASE} + "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) +endif () + +# Hook the CMake install process to the results from make ALL. +# This works best when 'make all && sudo make install/fast' is used. +# Using slash to end the source location to avoid copying the directory path. +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build/libs/ + DESTINATION ${AS3_INSTALL_DIR} + FILES_MATCHING PATTERN "libthrift-as3.swc") + +if (BUILD_TESTING) + add_test(NAME As3Test + COMMAND ${GRADLEW_EXECUTABLE} ${GRADLE_OPTS} test + --console=plain --no-daemon + -Prelease=${PRELEASE} + "-Pbuild.dir=${CMAKE_CURRENT_BINARY_DIR}/build" + "-Pthrift.compiler=${THRIFT_COMPILER}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +endif () diff --git a/lib/as3/Makefile.am b/lib/as3/Makefile.am new file mode 100644 index 00000000000..0b3c3befc77 --- /dev/null +++ b/lib/as3/Makefile.am @@ -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. +# + +all-local: + ./gradlew $(GRADLE_OPTS) compile \ + -Prelease=true \ + --console=plain + +install-exec-hook: + ./gradlew $(GRADLE_OPTS) publishToMavenLocal \ + -Prelease=true \ + --console=plain + +clean-local: + ./gradlew $(GRADLE_OPTS) clean \ + -Prelease=true \ + --console=plain + $(RM) -r .gradle + +check-local: $(THRIFT) + ./gradlew $(GRADLE_OPTS) test \ + -Prelease=true \ + --console=plain + +maven-publish: + ./gradlew $(GRADLE_OPTS) publishMavenPublicationToMavenRepository \ + -Prelease=true \ + -Psign=true \ + --console=plain + +dist-hook: + $(RM) -r $(distdir)/.gradle/ + +EXTRA_DIST = \ + CMakeLists.txt \ + README.md \ + build.gradle \ + coding_standards.md \ + gradle \ + gradle.properties \ + gradlew \ + gradlew.bat \ + settings.gradle \ + src diff --git a/lib/as3/README.md b/lib/as3/README.md new file mode 100644 index 00000000000..c14f8c78b68 --- /dev/null +++ b/lib/as3/README.md @@ -0,0 +1,37 @@ +# Apache Thrift ActionScript Library + +## Building + +We use gradle and gradlefx to build the as3 library. Unfortunately gradlefx requires +an older version of gradle (2.5) but it still works - for now. If you use the docker +container to do the build, the Adobe Flex SDK 4.6 is installed and the FLEX_HOME +environment variable is configured: + + dev@ubuntu:~/thrift$ docker run -v $(pwd):/thrift/src:rw -it thrift/thrift-build:ubuntu-bionic /bin/bash + root@7624b61bbf84:/thrift/src# cd lib/as3 + root@7624b61bbf84:/thrift/src/lib/as3# ./gradlew -Prelease=true compileFlex + + ... + + :compileFlex UP-TO-DATE + + BUILD SUCCESSFUL + + Total time: 10.784 secs + + root@7624b61bbf84:/thrift/src/lib/as3# ls -ls build/ + total 4 + 4 -rw-r--r-- 1 root root 1379 Jan 22 19:23 libthrift-as3.swc + +## Publishing + +We use a similar gradle-based signing and publishing mechanism as in the java +library. See the java library [README.md](../java/README.md) for more details. + +To publish into a local .m2 repository you can mount a directory into the docker container, +for example: + + dev@ubuntu:~/thrift$ docker run -v~/.m2:/root/.m2 -v $(pwd):/thrift/src:rw -it thrift/thrift-build:ubuntu-bionic /bin/bash + root@7624b61bbf84:/thrift/src/lib/as3# ./gradlew -Prelease=true publishToMavenLocal + +You will find your `~/.m2` directory is now populated with a release build `swc`. diff --git a/lib/as3/build.gradle b/lib/as3/build.gradle new file mode 100644 index 00000000000..78534996ada --- /dev/null +++ b/lib/as3/build.gradle @@ -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. + */ + +buildscript { + repositories { + mavenLocal() + mavenCentral() + } + dependencies { + classpath group: 'org.gradlefx', name: 'gradlefx', version: '1.5.0' + } +} + +plugins { + id 'maven-publish' + id 'signing' +} + +apply plugin: 'gradlefx' + +description = 'Apache Thrift ActionScript Library' +frameworkLinkage = 'none' +group = property('thrift.groupid') +srcDirs = ['src'] +type = 'swc' + +// We use the SNAPSHOT suffix for non-release versions +if (Boolean.parseBoolean(project.release)) { + additionalCompilerOptions = ['-compiler.debug=false', '-compiler.strict=true'] + version = property('thrift.version') +} else { + additionalCompilerOptions = ['-compiler.debug=true', '-compiler.strict=true'] + version = property('thrift.version') + '-SNAPSHOT' +} + +defaultTasks 'compile' + +// Keeping the rest of the build logic in functional named scripts for clarity +apply from: 'gradle/publishing.gradle' + diff --git a/lib/as3/build.properties b/lib/as3/build.properties deleted file mode 100644 index 84636683c94..00000000000 --- a/lib/as3/build.properties +++ /dev/null @@ -1,5 +0,0 @@ -# Maven Ant tasks Jar details -mvn.ant.task.version=2.1.3 -mvn.repo=http://repo1.maven.org/maven2 -mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version} -mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar diff --git a/lib/as3/build.xml b/lib/as3/build.xml deleted file mode 100755 index 2b374ddde43..00000000000 --- a/lib/as3/build.xml +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/as3/gradle.properties b/lib/as3/gradle.properties new file mode 100644 index 00000000000..51179a12b77 --- /dev/null +++ b/lib/as3/gradle.properties @@ -0,0 +1,22 @@ +# This file is shared currently between this Gradle build and the +# Ant builds for fd303 and JavaScript. Keep the dotted notation for +# the properties to minimize the changes in the dependencies. +thrift.version=0.12.1thrift.groupid=org.apache.thrift +release=false +sign=false + +# Local Install paths +install.path=/usr/local/lib +install.javadoc.path=/usr/local/lib + +# Test execution properties +testPort=9090 + +# Maven dependency download locations +mvn.repo=http://repo1.maven.org/maven2 +apache.repo=https://repository.apache.org/content/repositories/releases + +# Apache Maven publish +license=http://www.apache.org/licenses/LICENSE-2.0.txt +maven-repository-url=https://repository.apache.org/service/local/staging/deploy/maven2 +maven-repository-id=apache.releases.https diff --git a/lib/as3/gradle/publishing.gradle b/lib/as3/gradle/publishing.gradle new file mode 100644 index 00000000000..3e0ecf3192d --- /dev/null +++ b/lib/as3/gradle/publishing.gradle @@ -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. + */ + +// Following Gradle best practices to keep build logic organized + +model { + tasks.signMavenPublication { + dependsOn compileFlex + } +} + +publishing { + publications { + maven(MavenPublication) { + + groupId = "$group" + artifactId = "${project.name}" + version = "$version" + + def swcFile = file("$buildDir/libthrift-as3.swc") + artifact(swcFile) + + pom { + description = 'Thrift is a software framework for scalable cross-language services development.' + packaging = 'swc' + + // older gradle doesn't recognize all the properties, so we inject them.. + withXml { + asNode().with { + appendNode('name', 'Apache Thrift') + appendNode('url', 'http://thrift.apache.org/') + appendNode('scm').with { + appendNode('url', 'https://github.com/apache/thrift/') + appendNode('connection', 'scm:git:https://github.com/apache/thrift.git') + appendNode('developerConnection', 'scm:git:git@github.com:apache/thrift.git') + } + appendNode('issueManagement').with { + appendNode('url', 'https://issues.apache.org/jira/projects/THRIFT/') + appendNode('system', 'Jira') + } + appendNode('licenses').with { + appendNode('license').with { + appendNode('name', 'The Apache Software License, Version 2.0') + appendNode('url', "${project.license}") + } + } + appendNode('organization').with { + appendNode('name', 'The Apache Software Foundation') + appendNode('url', 'http://www.apache.org/') + } + appendNode('developers').with { + appendNode('developer').with { + appendNode('id', 'dev') + appendNode('name', 'Apache Thrift Developers') + appendNode('email', 'dev@thrift.apache.org') + } + } + } + } + } + } + } + repositories { + maven { + url = property('maven-repository-url') + + if (project.hasProperty('mavenUser') && project.hasProperty('mavenPassword')) { + credentials { + username = property('mavenUser') + password = property('mavenPassword') + } + } + } + } +} + +signing { + required { property('sign') } + sign publishing.publications.maven +} diff --git a/lib/as3/gradle/wrapper/gradle-wrapper.jar b/lib/as3/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..87b738cbd051603d91cc39de6cb000dd98fe6b02 GIT binary patch literal 55190 zcmafaW0WS*vSoFbZQHhO+s0S6%`V%vZQJa!ZQHKus_B{g-pt%P_q|ywBQt-*Stldc z$+IJ3?^KWm27v+sf`9-50uuadKtMnL*BJ;1^6ynvR7H?hQcjE>7)art9Bu0Pcm@7C z@c%WG|JzYkP)<@zR9S^iR_sA`azaL$mTnGKnwDyMa;8yL_0^>Ba^)phg0L5rOPTbm7g*YIRLg-2^{qe^`rb!2KqS zk~5wEJtTdD?)3+}=eby3x6%i)sb+m??NHC^u=tcG8p$TzB<;FL(WrZGV&cDQb?O0GMe6PBV=V z?tTO*5_HTW$xea!nkc~Cnx#cL_rrUGWPRa6l+A{aiMY=<0@8y5OC#UcGeE#I>nWh}`#M#kIn-$A;q@u-p71b#hcSItS!IPw?>8 zvzb|?@Ahb22L(O4#2Sre&l9H(@TGT>#Py)D&eW-LNb!=S;I`ZQ{w;MaHW z#to!~TVLgho_Pm%zq@o{K3Xq?I|MVuVSl^QHnT~sHlrVxgsqD-+YD?Nz9@HA<;x2AQjxP)r6Femg+LJ-*)k%EZ}TTRw->5xOY z9#zKJqjZgC47@AFdk1$W+KhTQJKn7e>A&?@-YOy!v_(}GyV@9G#I?bsuto4JEp;5|N{orxi_?vTI4UF0HYcA( zKyGZ4<7Fk?&LZMQb6k10N%E*$gr#T&HsY4SPQ?yerqRz5c?5P$@6dlD6UQwZJ*Je9 z7n-@7!(OVdU-mg@5$D+R%gt82Lt%&n6Yr4=|q>XT%&^z_D*f*ug8N6w$`woqeS-+#RAOfSY&Rz z?1qYa5xi(7eTCrzCFJfCxc%j{J}6#)3^*VRKF;w+`|1n;Xaojr2DI{!<3CaP`#tXs z*`pBQ5k@JLKuCmovFDqh_`Q;+^@t_;SDm29 zCNSdWXbV?9;D4VcoV`FZ9Ggrr$i<&#Dx3W=8>bSQIU_%vf)#(M2Kd3=rN@^d=QAtC zI-iQ;;GMk|&A++W5#hK28W(YqN%?!yuW8(|Cf`@FOW5QbX|`97fxmV;uXvPCqxBD zJ9iI37iV)5TW1R+fV16y;6}2tt~|0J3U4E=wQh@sx{c_eu)t=4Yoz|%Vp<#)Qlh1V z0@C2ZtlT>5gdB6W)_bhXtcZS)`9A!uIOa`K04$5>3&8An+i9BD&GvZZ=7#^r=BN=k za+=Go;qr(M)B~KYAz|<^O3LJON}$Q6Yuqn8qu~+UkUKK~&iM%pB!BO49L+?AL7N7o z(OpM(C-EY753=G=WwJHE`h*lNLMNP^c^bBk@5MyP5{v7x>GNWH>QSgTe5 z!*GPkQ(lcbEs~)4ovCu!Zt&$${9$u(<4@9%@{U<-ksAqB?6F`bQ;o-mvjr)Jn7F&j$@`il1Mf+-HdBs<-`1FahTxmPMMI)@OtI&^mtijW6zGZ67O$UOv1Jj z;a3gmw~t|LjPkW3!EZ=)lLUhFzvO;Yvj9g`8hm%6u`;cuek_b-c$wS_0M4-N<@3l|88 z@V{Sd|M;4+H6guqMm4|v=C6B7mlpP(+It%0E;W`dxMOf9!jYwWj3*MRk`KpS_jx4c z=hrKBkFK;gq@;wUV2eqE3R$M+iUc+UD0iEl#-rECK+XmH9hLKrC={j@uF=f3UiceB zU5l$FF7#RKjx+6!JHMG5-!@zI-eG=a-!Bs^AFKqN_M26%cIIcSs61R$yuq@5a3c3& z4%zLs!g}+C5%`ja?F`?5-og0lv-;(^e<`r~p$x%&*89_Aye1N)9LNVk?9BwY$Y$$F^!JQAjBJvywXAesj7lTZ)rXuxv(FFNZVknJha99lN=^h`J2> zl5=~(tKwvHHvh|9-41@OV`c;Ws--PE%{7d2sLNbDp;A6_Ka6epzOSFdqb zBa0m3j~bT*q1lslHsHqaHIP%DF&-XMpCRL(v;MV#*>mB^&)a=HfLI7efblG z(@hzN`|n+oH9;qBklb=d^S0joHCsArnR1-h{*dIUThik>ot^!6YCNjg;J_i3h6Rl0ji)* zo(tQ~>xB!rUJ(nZjCA^%X;)H{@>uhR5|xBDA=d21p@iJ!cH?+%U|VSh2S4@gv`^)^ zNKD6YlVo$%b4W^}Rw>P1YJ|fTb$_(7C;hH+ z1XAMPb6*p^h8)e5nNPKfeAO}Ik+ZN_`NrADeeJOq4Ak;sD~ zTe77no{Ztdox56Xi4UE6S7wRVxJzWxKj;B%v7|FZ3cV9MdfFp7lWCi+W{}UqekdpH zdO#eoOuB3Fu!DU`ErfeoZWJbWtRXUeBzi zBTF-AI7yMC^ntG+8%mn(I6Dw}3xK8v#Ly{3w3_E?J4(Q5JBq~I>u3!CNp~Ekk&YH` z#383VO4O42NNtcGkr*K<+wYZ>@|sP?`AQcs5oqX@-EIqgK@Pmp5~p6O6qy4ml~N{D z{=jQ7k(9!CM3N3Vt|u@%ssTw~r~Z(}QvlROAkQQ?r8OQ3F0D$aGLh zny+uGnH5muJ<67Z=8uilKvGuANrg@s3Vu_lU2ajb?rIhuOd^E@l!Kl0hYIxOP1B~Q zggUmXbh$bKL~YQ#!4fos9UUVG#}HN$lIkM<1OkU@r>$7DYYe37cXYwfK@vrHwm;pg zbh(hEU|8{*d$q7LUm+x&`S@VbW*&p-sWrplWnRM|I{P;I;%U`WmYUCeJhYc|>5?&& zj}@n}w~Oo=l}iwvi7K6)osqa;M8>fRe}>^;bLBrgA;r^ZGgY@IC^ioRmnE&H4)UV5 zO{7egQ7sBAdoqGsso5q4R(4$4Tjm&&C|7Huz&5B0wXoJzZzNc5Bt)=SOI|H}+fbit z-PiF5(NHSy>4HPMrNc@SuEMDuKYMQ--G+qeUPqO_9mOsg%1EHpqoX^yNd~~kbo`cH zlV0iAkBFTn;rVb>EK^V6?T~t~3vm;csx+lUh_%ROFPy0(omy7+_wYjN!VRDtwDu^h4n|xpAMsLepm% zggvs;v8+isCW`>BckRz1MQ=l>K6k^DdT`~sDXTWQ<~+JtY;I~I>8XsAq3yXgxe>`O zZdF*{9@Z|YtS$QrVaB!8&`&^W->_O&-JXn1n&~}o3Z7FL1QE5R*W2W@=u|w~7%EeC1aRfGtJWxImfY-D3t!!nBkWM> zafu>^Lz-ONgT6ExjV4WhN!v~u{lt2-QBN&UxwnvdH|I%LS|J-D;o>@@sA62@&yew0 z)58~JSZP!(lX;da!3`d)D1+;K9!lyNlkF|n(UduR-%g>#{`pvrD^ClddhJyfL7C-(x+J+9&7EsC~^O`&}V%)Ut8^O_7YAXPDpzv8ir4 zl`d)(;imc6r16k_d^)PJZ+QPxxVJS5e^4wX9D=V2zH&wW0-p&OJe=}rX`*->XT=;_qI&)=WHkYnZx6bLoUh_)n-A}SF_ z9z7agNTM5W6}}ui=&Qs@pO5$zHsOWIbd_&%j^Ok5PJ3yUWQw*i4*iKO)_er2CDUME ztt+{Egod~W-fn^aLe)aBz)MOc_?i-stTj}~iFk7u^-gGSbU;Iem06SDP=AEw9SzuF zeZ|hKCG3MV(z_PJg0(JbqTRf4T{NUt%kz&}4S`)0I%}ZrG!jgW2GwP=WTtkWS?DOs znI9LY!dK+1_H0h+i-_~URb^M;4&AMrEO_UlDV8o?E>^3x%ZJyh$JuDMrtYL8|G3If zPf2_Qb_W+V?$#O; zydKFv*%O;Y@o_T_UAYuaqx1isMKZ^32JtgeceA$0Z@Ck0;lHbS%N5)zzAW9iz; z8tTKeK7&qw!8XVz-+pz>z-BeIzr*#r0nB^cntjQ9@Y-N0=e&ZK72vlzX>f3RT@i7@ z=z`m7jNk!9%^xD0ug%ptZnM>F;Qu$rlwo}vRGBIymPL)L|x}nan3uFUw(&N z24gdkcb7!Q56{0<+zu zEtc5WzG2xf%1<@vo$ZsuOK{v9gx^0`gw>@h>ZMLy*h+6ueoie{D#}}` zK2@6Xxq(uZaLFC%M!2}FX}ab%GQ8A0QJ?&!vaI8Gv=vMhd);6kGguDmtuOElru()) zuRk&Z{?Vp!G~F<1#s&6io1`poBqpRHyM^p;7!+L??_DzJ8s9mYFMQ0^%_3ft7g{PD zZd}8E4EV}D!>F?bzcX=2hHR_P`Xy6?FOK)mCj)Ym4s2hh z0OlOdQa@I;^-3bhB6mpw*X5=0kJv8?#XP~9){G-+0ST@1Roz1qi8PhIXp1D$XNqVG zMl>WxwT+K`SdO1RCt4FWTNy3!i?N>*-lbnn#OxFJrswgD7HjuKpWh*o@QvgF&j+CT z{55~ZsUeR1aB}lv#s_7~+9dCix!5(KR#c?K?e2B%P$fvrsZxy@GP#R#jwL{y#Ld$} z7sF>QT6m|}?V;msb?Nlohj7a5W_D$y+4O6eI;Zt$jVGymlzLKscqer9#+p2$0It&u zWY!dCeM6^B^Z;ddEmhi?8`scl=Lhi7W%2|pT6X6^%-=q90DS(hQ-%c+E*ywPvmoF(KqDoW4!*gmQIklm zk#!GLqv|cs(JRF3G?=AYY19{w@~`G3pa z@xR9S-Hquh*&5Yas*VI};(%9%PADn`kzm zeWMJVW=>>wap*9|R7n#!&&J>gq04>DTCMtj{P^d12|2wXTEKvSf?$AvnE!peqV7i4 zE>0G%CSn%WCW1yre?yi9*aFP{GvZ|R4JT}M%x_%Hztz2qw?&28l&qW<6?c6ym{f$d z5YCF+k#yEbjCN|AGi~-NcCG8MCF1!MXBFL{#7q z)HO+WW173?kuI}^Xat;Q^gb4Hi0RGyB}%|~j8>`6X4CPo+|okMbKy9PHkr58V4bX6<&ERU)QlF8%%huUz&f+dwTN|tk+C&&o@Q1RtG`}6&6;ncQuAcfHoxd5AgD7`s zXynq41Y`zRSiOY@*;&1%1z>oNcWTV|)sjLg1X8ijg1Y zbIGL0X*Sd}EXSQ2BXCKbJmlckY(@EWn~Ut2lYeuw1wg?hhj@K?XB@V_ZP`fyL~Yd3n3SyHU-RwMBr6t-QWE5TinN9VD4XVPU; zonIIR!&pGqrLQK)=#kj40Im%V@ij0&Dh0*s!lnTw+D`Dt-xmk-jmpJv$1-E-vfYL4 zqKr#}Gm}~GPE+&$PI@4ag@=M}NYi7Y&HW82Q`@Y=W&PE31D110@yy(1vddLt`P%N^ z>Yz195A%tnt~tvsSR2{m!~7HUc@x<&`lGX1nYeQUE(%sphTi>JsVqSw8xql*Ys@9B z>RIOH*rFi*C`ohwXjyeRBDt8p)-u{O+KWP;$4gg||%*u{$~yEj+Al zE(hAQRQ1k7MkCq9s4^N3ep*$h^L%2Vq?f?{+cicpS8lo)$Cb69b98au+m2J_e7nYwID0@`M9XIo1H~|eZFc8Hl!qly612ADCVpU zY8^*RTMX(CgehD{9v|^9vZ6Rab`VeZ2m*gOR)Mw~73QEBiktViBhR!_&3l$|be|d6 zupC`{g89Y|V3uxl2!6CM(RNpdtynaiJ~*DqSTq9Mh`ohZnb%^3G{k;6%n18$4nAqR zjPOrP#-^Y9;iw{J@XH9=g5J+yEVh|e=4UeY<^65`%gWtdQ=-aqSgtywM(1nKXh`R4 zzPP&7r)kv_uC7X9n=h=!Zrf<>X=B5f<9~Q>h#jYRD#CT7D~@6@RGNyO-#0iq0uHV1 zPJr2O4d_xLmg2^TmG7|dpfJ?GGa`0|YE+`2Rata9!?$j#e9KfGYuLL(*^z z!SxFA`$qm)q-YKh)WRJZ@S+-sD_1E$V?;(?^+F3tVcK6 z2fE=8hV*2mgiAbefU^uvcM?&+Y&E}vG=Iz!%jBF7iv){lyC`)*yyS~D8k+Mx|N3bm zI~L~Z$=W9&`x)JnO;8c>3LSDw!fzN#X3qi|0`sXY4?cz{*#xz!kvZ9bO=K3XbN z5KrgN=&(JbXH{Wsu9EdmQ-W`i!JWEmfI;yVTT^a-8Ch#D8xf2dtyi?7p z%#)W3n*a#ndFpd{qN|+9Jz++AJQO#-Y7Z6%*%oyEP5zs}d&kKIr`FVEY z;S}@d?UU=tCdw~EJ{b}=9x}S2iv!!8<$?d7VKDA8h{oeD#S-$DV)-vPdGY@x08n)@ zag?yLF_E#evvRTj4^CcrLvBL=fft&@HOhZ6Ng4`8ijt&h2y}fOTC~7GfJi4vpomA5 zOcOM)o_I9BKz}I`q)fu+Qnfy*W`|mY%LO>eF^a z;$)?T4F-(X#Q-m}!-k8L_rNPf`Mr<9IWu)f&dvt=EL+ESYmCvErd@8B9hd)afc(ZL94S z?rp#h&{7Ah5IJftK4VjATklo7@hm?8BX*~oBiz)jyc9FuRw!-V;Uo>p!CWpLaIQyt zAs5WN)1CCeux-qiGdmbIk8LR`gM+Qg=&Ve}w?zA6+sTL)abU=-cvU`3E?p5$Hpkxw znu0N659qR=IKnde*AEz_7z2pdi_Bh-sb3b=PdGO1Pdf_q2;+*Cx9YN7p_>rl``knY zRn%aVkcv1(W;`Mtp_DNOIECtgq%ufk-mu_<+Fu3Q17Tq4Rr(oeq)Yqk_CHA7LR@7@ zIZIDxxhS&=F2IQfusQ+Nsr%*zFK7S4g!U0y@3H^Yln|i;0a5+?RPG;ZSp6Tul>ezM z`40+516&719qT)mW|ArDSENle5hE2e8qY+zfeZoy12u&xoMgcP)4=&P-1Ib*-bAy` zlT?>w&B|ei-rCXO;sxo7*G;!)_p#%PAM-?m$JP(R%x1Hfas@KeaG%LO?R=lmkXc_MKZW}3f%KZ*rAN?HYvbu2L$ zRt_uv7~-IejlD1x;_AhwGXjB94Q=%+PbxuYzta*jw?S&%|qb=(JfJ?&6P=R7X zV%HP_!@-zO*zS}46g=J}#AMJ}rtWBr21e6hOn&tEmaM%hALH7nlm2@LP4rZ>2 zebe5aH@k!e?ij4Zwak#30|}>;`bquDQK*xmR=zc6vj0yuyC6+U=LusGnO3ZKFRpen z#pwzh!<+WBVp-!$MAc<0i~I%fW=8IO6K}bJ<-Scq>e+)951R~HKB?Mx2H}pxPHE@} zvqpq5j81_jtb_WneAvp<5kgdPKm|u2BdQx9%EzcCN&U{l+kbkhmV<1}yCTDv%&K^> zg;KCjwh*R1f_`6`si$h6`jyIKT7rTv5#k~x$mUyIw)_>Vr)D4fwIs@}{FSX|5GB1l z4vv;@oS@>Bu7~{KgUa_8eg#Lk6IDT2IY$41$*06{>>V;Bwa(-@N;ex4;D`(QK*b}{ z{#4$Hmt)FLqERgKz=3zXiV<{YX6V)lvYBr3V>N6ajeI~~hGR5Oe>W9r@sg)Na(a4- zxm%|1OKPN6^%JaD^^O~HbLSu=f`1px>RawOxLr+1b2^28U*2#h*W^=lSpSY4(@*^l z{!@9RSLG8Me&RJYLi|?$c!B0fP=4xAM4rerxX{xy{&i6=AqXueQAIBqO+pmuxy8Ib z4X^}r!NN3-upC6B#lt7&x0J;)nb9O~xjJMemm$_fHuP{DgtlU3xiW0UesTzS30L+U zQzDI3p&3dpONhd5I8-fGk^}@unluzu%nJ$9pzoO~Kk!>dLxw@M)M9?pNH1CQhvA`z zV;uacUtnBTdvT`M$1cm9`JrT3BMW!MNVBy%?@ZX%;(%(vqQAz<7I!hlDe|J3cn9=} zF7B;V4xE{Ss76s$W~%*$JviK?w8^vqCp#_G^jN0j>~Xq#Zru26e#l3H^{GCLEXI#n z?n~F-Lv#hU(bZS`EI9(xGV*jT=8R?CaK)t8oHc9XJ;UPY0Hz$XWt#QyLBaaz5+}xM zXk(!L_*PTt7gwWH*HLWC$h3Ho!SQ-(I||nn_iEC{WT3S{3V{8IN6tZ1C+DiFM{xlI zeMMk{o5;I6UvaC)@WKp9D+o?2Vd@4)Ue-nYci()hCCsKR`VD;hr9=vA!cgGL%3k^b(jADGyPi2TKr(JNh8mzlIR>n(F_hgiV(3@Ds(tjbNM7GoZ;T|3 zWzs8S`5PrA!9){jBJuX4y`f<4;>9*&NY=2Sq2Bp`M2(fox7ZhIDe!BaQUb@P(ub9D zlP8!p(AN&CwW!V&>H?yPFMJ)d5x#HKfwx;nS{Rr@oHqpktOg)%F+%1#tsPtq7zI$r zBo-Kflhq-=7_eW9B2OQv=@?|y0CKN77)N;z@tcg;heyW{wlpJ1t`Ap!O0`Xz{YHqO zI1${8Hag^r!kA<2_~bYtM=<1YzQ#GGP+q?3T7zYbIjN6Ee^V^b&9en$8FI*NIFg9G zPG$OXjT0Ku?%L7fat8Mqbl1`azf1ltmKTa(HH$Dqlav|rU{zP;Tbnk-XkGFQ6d+gi z-PXh?_kEJl+K98&OrmzgPIijB4!Pozbxd0H1;Usy!;V>Yn6&pu*zW8aYx`SC!$*ti zSn+G9p=~w6V(fZZHc>m|PPfjK6IN4(o=IFu?pC?+`UZAUTw!e`052{P=8vqT^(VeG z=psASIhCv28Y(;7;TuYAe>}BPk5Qg=8$?wZj9lj>h2kwEfF_CpK=+O6Rq9pLn4W)# zeXCKCpi~jsfqw7Taa0;!B5_C;B}e56W1s8@p*)SPzA;Fd$Slsn^=!_&!mRHV*Lmt| zBGIDPuR>CgS4%cQ4wKdEyO&Z>2aHmja;Pz+n|7(#l%^2ZLCix%>@_mbnyPEbyrHaz z>j^4SIv;ZXF-Ftzz>*t4wyq)ng8%0d;(Z_ExZ-cxwei=8{(br-`JYO(f23Wae_MqE z3@{Mlf^%M5G1SIN&en1*| zH~ANY1h3&WNsBy$G9{T=`kcxI#-X|>zLX2r*^-FUF+m0{k)n#GTG_mhG&fJfLj~K& zU~~6othMlvMm9<*SUD2?RD+R17|Z4mgR$L*R3;nBbo&Vm@39&3xIg;^aSxHS>}gwR zmzs?h8oPnNVgET&dx5^7APYx6Vv6eou07Zveyd+^V6_LzI$>ic+pxD_8s~ zC<}ucul>UH<@$KM zT4oI=62M%7qQO{}re-jTFqo9Z;rJKD5!X5$iwUsh*+kcHVhID08MB5cQD4TBWB(rI zuWc%CA}}v|iH=9gQ?D$1#Gu!y3o~p7416n54&Hif`U-cV?VrUMJyEqo_NC4#{puzU zzXEE@UppeeRlS9W*^N$zS`SBBi<@tT+<%3l@KhOy^%MWB9(A#*J~DQ;+MK*$rxo6f zcx3$3mcx{tly!q(p2DQrxcih|)0do_ZY77pyHGE#Q(0k*t!HUmmMcYFq%l$-o6%lS zDb49W-E?rQ#Hl``C3YTEdGZjFi3R<>t)+NAda(r~f1cT5jY}s7-2^&Kvo&2DLTPYP zhVVo-HLwo*vl83mtQ9)PR#VBg)FN}+*8c-p8j`LnNUU*Olm1O1Qqe62D#$CF#?HrM zy(zkX|1oF}Z=T#3XMLWDrm(|m+{1&BMxHY7X@hM_+cV$5-t!8HT(dJi6m9{ja53Yw z3f^`yb6Q;(e|#JQIz~B*=!-GbQ4nNL-NL z@^NWF_#w-Cox@h62;r^;Y`NX8cs?l^LU;5IWE~yvU8TqIHij!X8ydbLlT0gwmzS9} z@5BccG?vO;rvCs$mse1*ANi-cYE6Iauz$Fbn3#|ToAt5v7IlYnt6RMQEYLldva{~s zvr>1L##zmeoYgvIXJ#>bbuCVuEv2ZvZ8I~PQUN3wjP0UC)!U+wn|&`V*8?)` zMSCuvnuGec>QL+i1nCPGDAm@XSMIo?A9~C?g2&G8aNKjWd2pDX{qZ?04+2 zeyLw}iEd4vkCAWwa$ zbrHlEf3hfN7^1g~aW^XwldSmx1v~1z(s=1az4-wl} z`mM+G95*N*&1EP#u3}*KwNrPIgw8Kpp((rdEOO;bT1;6ea~>>sK+?!;{hpJ3rR<6UJb`O8P4@{XGgV%63_fs%cG8L zk9Fszbdo4tS$g0IWP1>t@0)E%-&9yj%Q!fiL2vcuL;90fPm}M==<>}Q)&sp@STFCY z^p!RzmN+uXGdtPJj1Y-khNyCb6Y$Vs>eZyW zPaOV=HY_T@FwAlleZCFYl@5X<<7%5DoO(7S%Lbl55?{2vIr_;SXBCbPZ(up;pC6Wx={AZL?shYOuFxLx1*>62;2rP}g`UT5+BHg(ju z&7n5QSvSyXbioB9CJTB#x;pexicV|9oaOpiJ9VK6EvKhl4^Vsa(p6cIi$*Zr0UxQ z;$MPOZnNae2Duuce~7|2MCfhNg*hZ9{+8H3?ts9C8#xGaM&sN;2lriYkn9W>&Gry! z3b(Xx1x*FhQkD-~V+s~KBfr4M_#0{`=Yrh90yj}Ph~)Nx;1Y^8<418tu!$1<3?T*~ z7Dl0P3Uok-7w0MPFQexNG1P5;y~E8zEvE49>$(f|XWtkW2Mj`udPn)pb%} zrA%wRFp*xvDgC767w!9`0vx1=q!)w!G+9(-w&p*a@WXg{?T&%;qaVcHo>7ca%KX$B z^7|KBPo<2;kM{2mRnF8vKm`9qGV%|I{y!pKm8B(q^2V;;x2r!1VJ^Zz8bWa)!-7a8 zSRf@dqEPlsj!7}oNvFFAA)75})vTJUwQ03hD$I*j6_5xbtd_JkE2`IJD_fQ;a$EkO z{fQ{~e%PKgPJsD&PyEvDmg+Qf&p*-qu!#;1k2r_(H72{^(Z)htgh@F?VIgK#_&eS- z$~(qInec>)XIkv@+{o6^DJLpAb>!d}l1DK^(l%#OdD9tKK6#|_R?-%0V!`<9Hj z3w3chDwG*SFte@>Iqwq`J4M&{aHXzyigT620+Vf$X?3RFfeTcvx_e+(&Q*z)t>c0e zpZH$1Z3X%{^_vylHVOWT6tno=l&$3 z9^eQ@TwU#%WMQaFvaYp_we%_2-9=o{+ck zF{cKJCOjpW&qKQquyp2BXCAP920dcrZ}T1@piukx_NY;%2W>@Wca%=Ch~x5Oj58Hv z;D-_ALOZBF(Mqbcqjd}P3iDbek#Dwzu`WRs`;hRIr*n0PV7vT+%Io(t}8KZ zpp?uc2eW!v28ipep0XNDPZt7H2HJ6oey|J3z!ng#1H~x_k%35P+Cp%mqXJ~cV0xdd z^4m5^K_dQ^Sg?$P`))ccV=O>C{Ds(C2WxX$LMC5vy=*44pP&)X5DOPYfqE${)hDg< z3hcG%U%HZ39=`#Ko4Uctg&@PQLf>?0^D|4J(_1*TFMOMB!Vv1_mnOq$BzXQdOGqgy zOp#LBZ!c>bPjY1NTXksZmbAl0A^Y&(%a3W-k>bE&>K?px5Cm%AT2E<&)Y?O*?d80d zgI5l~&Mve;iXm88Q+Fw7{+`PtN4G7~mJWR^z7XmYQ>uoiV!{tL)hp|= zS(M)813PM`d<501>{NqaPo6BZ^T{KBaqEVH(2^Vjeq zgeMeMpd*1tE@@);hGjuoVzF>Cj;5dNNwh40CnU+0DSKb~GEMb_# zT8Z&gz%SkHq6!;_6dQFYE`+b`v4NT7&@P>cA1Z1xmXy<2htaDhm@XXMp!g($ zw(7iFoH2}WR`UjqjaqOQ$ecNt@c|K1H1kyBArTTjLp%-M`4nzOhkfE#}dOpcd;b#suq8cPJ&bf5`6Tq>ND(l zib{VrPZ>{KuaIg}Y$W>A+nrvMg+l4)-@2jpAQ5h(Tii%Ni^-UPVg{<1KGU2EIUNGaXcEkOedJOusFT9X3%Pz$R+-+W+LlRaY-a$5r?4V zbPzgQl22IPG+N*iBRDH%l{Zh$fv9$RN1sU@Hp3m=M}{rX%y#;4(x1KR2yCO7Pzo>rw(67E{^{yUR`91nX^&MxY@FwmJJbyPAoWZ9Z zcBS$r)&ogYBn{DOtD~tIVJUiq|1foX^*F~O4hlLp-g;Y2wKLLM=?(r3GDqsPmUo*? zwKMEi*%f)C_@?(&&hk>;m07F$X7&i?DEK|jdRK=CaaNu-)pX>n3}@%byPKVkpLzBq z{+Py&!`MZ^4@-;iY`I4#6G@aWMv{^2VTH7|WF^u?3vsB|jU3LgdX$}=v7#EHRN(im zI(3q-eU$s~r=S#EWqa_2!G?b~ z<&brq1vvUTJH380=gcNntZw%7UT8tLAr-W49;9y^=>TDaTC|cKA<(gah#2M|l~j)w zY8goo28gj$n&zcNgqX1Qn6=<8?R0`FVO)g4&QtJAbW3G#D)uNeac-7cH5W#6i!%BH z=}9}-f+FrtEkkrQ?nkoMQ1o-9_b+&=&C2^h!&mWFga#MCrm85hW;)1pDt;-uvQG^D zntSB?XA*0%TIhtWDS!KcI}kp3LT>!(Nlc(lQN?k^bS8Q^GGMfo}^|%7s;#r+pybl@?KA++|FJ zr%se9(B|g*ERQU96az%@4gYrxRRxaM2*b}jNsG|0dQi;Rw{0WM0E>rko!{QYAJJKY z)|sX0N$!8d9E|kND~v|f>3YE|uiAnqbkMn)hu$if4kUkzKqoNoh8v|S>VY1EKmgO} zR$0UU2o)4i4yc1inx3}brso+sio{)gfbLaEgLahj8(_Z#4R-v) zglqwI%`dsY+589a8$Mu7#7_%kN*ekHupQ#48DIN^uhDxblDg3R1yXMr^NmkR z7J_NWCY~fhg}h!_aXJ#?wsZF$q`JH>JWQ9`jbZzOBpS`}-A$Vgkq7+|=lPx9H7QZG z8i8guMN+yc4*H*ANr$Q-3I{FQ-^;8ezWS2b8rERp9TMOLBxiG9J*g5=?h)mIm3#CGi4JSq1ohFrcrxx@`**K5%T}qbaCGldV!t zVeM)!U3vbf5FOy;(h08JnhSGxm)8Kqxr9PsMeWi=b8b|m_&^@#A3lL;bVKTBx+0v8 zLZeWAxJ~N27lsOT2b|qyp$(CqzqgW@tyy?CgwOe~^i;ZH zlL``i4r!>i#EGBNxV_P@KpYFQLz4Bdq{#zA&sc)*@7Mxsh9u%e6Ke`?5Yz1jkTdND zR8!u_yw_$weBOU}24(&^Bm|(dSJ(v(cBct}87a^X(v>nVLIr%%D8r|&)mi+iBc;B;x;rKq zd8*X`r?SZsTNCPQqoFOrUz8nZO?225Z#z(B!4mEp#ZJBzwd7jW1!`sg*?hPMJ$o`T zR?KrN6OZA1H{9pA;p0cSSu;@6->8aJm1rrO-yDJ7)lxuk#npUk7WNER1Wwnpy%u zF=t6iHzWU(L&=vVSSc^&D_eYP3TM?HN!Tgq$SYC;pSIPWW;zeNm7Pgub#yZ@7WPw#f#Kl)W4%B>)+8%gpfoH1qZ;kZ*RqfXYeGXJ_ zk>2otbp+1By`x^1V!>6k5v8NAK@T;89$`hE0{Pc@Q$KhG0jOoKk--Qx!vS~lAiypV zCIJ&6B@24`!TxhJ4_QS*S5;;Pk#!f(qIR7*(c3dN*POKtQe)QvR{O2@QsM%ujEAWEm) z+PM=G9hSR>gQ`Bv2(k}RAv2+$7qq(mU`fQ+&}*i%-RtSUAha>70?G!>?w%F(b4k!$ zvm;E!)2`I?etmSUFW7WflJ@8Nx`m_vE2HF#)_BiD#FaNT|IY@!uUbd4v$wTglIbIX zblRy5=wp)VQzsn0_;KdM%g<8@>#;E?vypTf=F?3f@SSdZ;XpX~J@l1;p#}_veWHp>@Iq_T z@^7|h;EivPYv1&u0~l9(a~>dV9Uw10QqB6Dzu1G~-l{*7IktljpK<_L8m0|7VV_!S zRiE{u97(%R-<8oYJ{molUd>vlGaE-C|^<`hppdDz<7OS13$#J zZ+)(*rZIDSt^Q$}CRk0?pqT5PN5TT`Ya{q(BUg#&nAsg6apPMhLTno!SRq1e60fl6GvpnwDD4N> z9B=RrufY8+g3_`@PRg+(+gs2(bd;5#{uTZk96CWz#{=&h9+!{_m60xJxC%r&gd_N! z>h5UzVX%_7@CUeAA1XFg_AF%(uS&^1WD*VPS^jcC!M2v@RHZML;e(H-=(4(3O&bX- zI6>usJOS+?W&^S&DL{l|>51ZvCXUKlH2XKJPXnHjs*oMkNM#ZDLx!oaM5(%^)5XaP zk6&+P16sA>vyFe9v`Cp5qnbE#r#ltR5E+O3!WnKn`56Grs2;sqr3r# zp@Zp<^q`5iq8OqOlJ`pIuyK@3zPz&iJ0Jcc`hDQ1bqos2;}O|$i#}e@ua*x5VCSx zJAp}+?Hz++tm9dh3Fvm_bO6mQo38al#>^O0g)Lh^&l82+&x)*<n7^Sw-AJo9tEzZDwyJ7L^i7|BGqHu+ea6(&7jKpBq>~V z8CJxurD)WZ{5D0?s|KMi=e7A^JVNM6sdwg@1Eg_+Bw=9j&=+KO1PG|y(mP1@5~x>d z=@c{EWU_jTSjiJl)d(>`qEJ;@iOBm}alq8;OK;p(1AdH$)I9qHNmxxUArdzBW0t+Qeyl)m3?D09770g z)hzXEOy>2_{?o%2B%k%z4d23!pZcoxyW1Ik{|m7Q1>fm4`wsRrl)~h z_=Z*zYL+EG@DV1{6@5@(Ndu!Q$l_6Qlfoz@79q)Kmsf~J7t1)tl#`MD<;1&CAA zH8;i+oBm89dTTDl{aH`cmTPTt@^K-%*sV+t4X9q0Z{A~vEEa!&rRRr=0Rbz4NFCJr zLg2u=0QK@w9XGE=6(-JgeP}G#WG|R&tfHRA3a9*zh5wNTBAD;@YYGx%#E4{C#Wlfo z%-JuW9=FA_T6mR2-Vugk1uGZvJbFvVVWT@QOWz$;?u6+CbyQsbK$>O1APk|xgnh_8 zc)s@Mw7#0^wP6qTtyNq2G#s?5j~REyoU6^lT7dpX{T-rhZWHD%dik*=EA7bIJgOVf_Ga!yC8V^tkTOEHe+JK@Fh|$kfNxO^= z#lpV^(ZQ-3!^_BhV>aXY~GC9{8%1lOJ}6vzXDvPhC>JrtXwFBC+!3a*Z-%#9}i z#<5&0LLIa{q!rEIFSFc9)>{-_2^qbOg5;_A9 ztQ))C6#hxSA{f9R3Eh^`_f${pBJNe~pIQ`tZVR^wyp}=gLK}e5_vG@w+-mp#Fu>e| z*?qBp5CQ5zu+Fi}xAs)YY1;bKG!htqR~)DB$ILN6GaChoiy%Bq@i+1ZnANC0U&D z_4k$=YP47ng+0NhuEt}6C;9-JDd8i5S>`Ml==9wHDQFOsAlmtrVwurYDw_)Ihfk35 zJDBbe!*LUpg%4n>BExWz>KIQ9vexUu^d!7rc_kg#Bf= z7TLz|l*y*3d2vi@c|pX*@ybf!+Xk|2*z$@F4K#MT8Dt4zM_EcFmNp31#7qT6(@GG? zdd;sSY9HHuDb=w&|K%sm`bYX#%UHKY%R`3aLMO?{T#EI@FNNFNO>p@?W*i0z(g2dt z{=9Ofh80Oxv&)i35AQN>TPMjR^UID-T7H5A?GI{MD_VeXZ%;uo41dVm=uT&ne2h0i zv*xI%9vPtdEK@~1&V%p1sFc2AA`9?H)gPnRdlO~URx!fiSV)j?Tf5=5F>hnO=$d$x zzaIfr*wiIc!U1K*$JO@)gP4%xp!<*DvJSv7p}(uTLUb=MSb@7_yO+IsCj^`PsxEl& zIxsi}s3L?t+p+3FXYqujGhGwTx^WXgJ1}a@Yq5mwP0PvGEr*qu7@R$9j>@-q1rz5T zriz;B^(ex?=3Th6h;7U`8u2sDlfS{0YyydK=*>-(NOm9>S_{U|eg(J~C7O zIe{|LK=Y`hXiF_%jOM8Haw3UtaE{hWdzo3BbD6ud7br4cODBtN(~Hl+odP0SSWPw;I&^m)yLw+nd#}3#z}?UIcX3=SssI}`QwY=% zAEXTODk|MqTx}2DVG<|~(CxgLyi*A{m>M@1h^wiC)4Hy>1K7@|Z&_VPJsaQoS8=ex zDL&+AZdQa>ylxhT_Q$q=60D5&%pi6+qlY3$3c(~rsITX?>b;({FhU!7HOOhSP7>bmTkC8KM%!LRGI^~y3Ug+gh!QM=+NZXznM)?L3G=4=IMvFgX3BAlyJ z`~jjA;2z+65D$j5xbv9=IWQ^&-K3Yh`vC(1Qz2h2`o$>Cej@XRGff!it$n{@WEJ^N z41qk%Wm=}mA*iwCqU_6}Id!SQd13aFER3unXaJJXIsSnxvG2(hSCP{i&QH$tL&TPx zDYJsuk+%laN&OvKb-FHK$R4dy%M7hSB*yj#-nJy?S9tVoxAuDei{s}@+pNT!vLOIC z8g`-QQW8FKp3cPsX%{)0B+x+OhZ1=L7F-jizt|{+f1Ga7%+!BXqjCjH&x|3%?UbN# zh?$I1^YokvG$qFz5ySK+Ja5=mkR&p{F}ev**rWdKMko+Gj^?Or=UH?SCg#0F(&a_y zXOh}dPv0D9l0RVedq1~jCNV=8?vZfU-Xi|nkeE->;ohG3U7z+^0+HV17~-_Mv#mV` zzvwUJJ15v5wwKPv-)i@dsEo@#WEO9zie7mdRAbgL2kjbW4&lk$vxkbq=w5mGKZK6@ zjXWctDkCRx58NJD_Q7e}HX`SiV)TZMJ}~zY6P1(LWo`;yDynY_5_L?N-P`>ALfmyl z8C$a~FDkcwtzK9m$tof>(`Vu3#6r#+v8RGy#1D2)F;vnsiL&P-c^PO)^B-4VeJteLlT@25sPa z%W~q5>YMjj!mhN})p$47VA^v$Jo6_s{!y?}`+h+VM_SN`!11`|;C;B};B&Z<@%FOG z_YQVN+zFF|q5zKab&e4GH|B;sBbKimHt;K@tCH+S{7Ry~88`si7}S)1E{21nldiu5 z_4>;XTJa~Yd$m4A9{Qbd)KUAm7XNbZ4xHbg3a8-+1uf*$1PegabbmCzgC~1WB2F(W zYj5XhVos!X!QHuZXCatkRsdEsSCc+D2?*S7a+(v%toqyxhjz|`zdrUvsxQS{J>?c& zvx*rHw^8b|v^7wq8KWVofj&VUitbm*a&RU_ln#ZFA^3AKEf<#T%8I!Lg3XEsdH(A5 zlgh&M_XEoal)i#0tcq8c%Gs6`xu;vvP2u)D9p!&XNt z!TdF_H~;`g@fNXkO-*t<9~;iEv?)Nee%hVe!aW`N%$cFJ(Dy9+Xk*odyFj72T!(b%Vo5zvCGZ%3tkt$@Wcx8BWEkefI1-~C_3y*LjlQ5%WEz9WD8i^ z2MV$BHD$gdPJV4IaV)G9CIFwiV=ca0cfXdTdK7oRf@lgyPx;_7*RRFk=?@EOb9Gcz zg~VZrzo*Snp&EE{$CWr)JZW)Gr;{B2ka6B!&?aknM-FENcl%45#y?oq9QY z3^1Y5yn&^D67Da4lI}ljDcphaEZw2;tlYuzq?uB4b9Mt6!KTW&ptxd^vF;NbX=00T z@nE1lIBGgjqs?ES#P{ZfRb6f!At51vk%<0X%d_~NL5b8UyfQMPDtfU@>ijA0NP3UU zh{lCf`Wu7cX!go`kUG`1K=7NN@SRGjUKuo<^;@GS!%iDXbJs`o6e`v3O8-+7vRkFm z)nEa$sD#-v)*Jb>&Me+YIW3PsR1)h=-Su)))>-`aRcFJG-8icomO4J@60 zw10l}BYxi{eL+Uu0xJYk-Vc~BcR49Qyyq!7)PR27D`cqGrik=?k1Of>gY7q@&d&Ds zt7&WixP`9~jjHO`Cog~RA4Q%uMg+$z^Gt&vn+d3&>Ux{_c zm|bc;k|GKbhZLr-%p_f%dq$eiZ;n^NxoS-Nu*^Nx5vm46)*)=-Bf<;X#?`YC4tLK; z?;u?shFbXeks+dJ?^o$l#tg*1NA?(1iFff@I&j^<74S!o;SWR^Xi);DM%8XiWpLi0 zQE2dL9^a36|L5qC5+&Pf0%>l&qQ&)OU4vjd)%I6{|H+pw<0(a``9w(gKD&+o$8hOC zNAiShtc}e~ob2`gyVZx59y<6Fpl*$J41VJ-H*e-yECWaDMmPQi-N8XI3 z%iI@ljc+d}_okL1CGWffeaejlxWFVDWu%e=>H)XeZ|4{HlbgC-Uvof4ISYQzZ0Um> z#Ov{k1c*VoN^f(gfiueuag)`TbjL$XVq$)aCUBL_M`5>0>6Ska^*Knk__pw{0I>jA zzh}Kzg{@PNi)fcAk7jMAdi-_RO%x#LQszDMS@_>iFoB+zJ0Q#CQJzFGa8;pHFdi`^ zxnTC`G$7Rctm3G8t8!SY`GwFi4gF|+dAk7rh^rA{NXzc%39+xSYM~($L(pJ(8Zjs* zYdN_R^%~LiGHm9|ElV4kVZGA*T$o@YY4qpJOxGHlUi*S*A(MrgQ{&xoZQo+#PuYRs zv3a$*qoe9gBqbN|y|eaH=w^LE{>kpL!;$wRahY(hhzRY;d33W)m*dfem@)>pR54Qy z ze;^F?mwdU?K+=fBabokSls^6_6At#1Sh7W*y?r6Ss*dmZP{n;VB^LDxM1QWh;@H0J z!4S*_5j_;+@-NpO1KfQd&;C7T`9ak;X8DTRz$hDNcjG}xAfg%gwZSb^zhE~O);NMO zn2$fl7Evn%=Lk!*xsM#(y$mjukN?A&mzEw3W5>_o+6oh62kq=4-`e3B^$rG=XG}Kd zK$blh(%!9;@d@3& zGFO60j1Vf54S}+XD?%*uk7wW$f`4U3F*p7@I4Jg7f`Il}2H<{j5h?$DDe%wG7jZQL zI{mj?t?Hu>$|2UrPr5&QyK2l3mas?zzOk0DV30HgOQ|~xLXDQ8M3o#;CNKO8RK+M; zsOi%)js-MU>9H4%Q)#K_me}8OQC1u;f4!LO%|5toa1|u5Q@#mYy8nE9IXmR}b#sZK z3sD395q}*TDJJA9Er7N`y=w*S&tA;mv-)Sx4(k$fJBxXva0_;$G6!9bGBw13c_Uws zXks4u(8JA@0O9g5f?#V~qR5*u5aIe2HQO^)RW9TTcJk28l`Syl>Q#ZveEE4Em+{?%iz6=V3b>rCm9F zPQQm@-(hfNdo2%n?B)u_&Qh7^^@U>0qMBngH8}H|v+Ejg*Dd(Y#|jgJ-A zQ_bQscil%eY}8oN7ZL+2r|qv+iJY?*l)&3W_55T3GU;?@Om*(M`u0DXAsQ7HSl56> z4P!*(%&wRCb?a4HH&n;lAmr4rS=kMZb74Akha2U~Ktni>>cD$6jpugjULq)D?ea%b zk;UW0pAI~TH59P+o}*c5Ei5L-9OE;OIBt>^(;xw`>cN2`({Rzg71qrNaE=cAH^$wP zNrK9Glp^3a%m+ilQj0SnGq`okjzmE7<3I{JLD6Jn^+oas=h*4>Wvy=KXqVBa;K&ri z4(SVmMXPG}0-UTwa2-MJ=MTfM3K)b~DzSVq8+v-a0&Dsv>4B65{dBhD;(d44CaHSM zb!0ne(*<^Q%|nuaL`Gb3D4AvyO8wyygm=1;9#u5x*k0$UOwx?QxR*6Od8>+ujfyo0 zJ}>2FgW_iv(dBK2OWC-Y=Tw!UwIeOAOUUC;h95&S1hn$G#if+d;*dWL#j#YWswrz_ zMlV=z+zjZJ%SlDhxf)vv@`%~$Afd)T+MS1>ZE7V$Rj#;J*<9Ld=PrK0?qrazRJWx) z(BTLF@Wk279nh|G%ZY7_lK7=&j;x`bMND=zgh_>>-o@6%8_#Bz!FnF*onB@_k|YCF z?vu!s6#h9bL3@tPn$1;#k5=7#s*L;FLK#=M89K^|$3LICYWIbd^qguQp02w5>8p-H z+@J&+pP_^iF4Xu>`D>DcCnl8BUwwOlq6`XkjHNpi@B?OOd`4{dL?kH%lt78(-L}eah8?36zw9d-dI6D{$s{f=M7)1 zRH1M*-82}DoFF^Mi$r}bTB5r6y9>8hjL54%KfyHxn$LkW=AZ(WkHWR;tIWWr@+;^^ zVomjAWT)$+rn%g`LHB6ZSO@M3KBA? z+W7ThSBgpk`jZHZUrp`F;*%6M5kLWy6AW#T{jFHTiKXP9ITrMlEdti7@&AT_a-BA!jc(Kt zWk>IdY-2Zbz?U1)tk#n_Lsl?W;0q`;z|t9*g-xE!(}#$fScX2VkjSiboKWE~afu5d z2B@9mvT=o2fB_>Mnie=TDJB+l`GMKCy%2+NcFsbpv<9jS@$X37K_-Y!cvF5NEY`#p z3sWEc<7$E*X*fp+MqsOyMXO=<2>o8)E(T?#4KVQgt=qa%5FfUG_LE`n)PihCz2=iNUt7im)s@;mOc9SR&{`4s9Q6)U31mn?}Y?$k3kU z#h??JEgH-HGt`~%)1ZBhT9~uRi8br&;a5Y3K_Bl1G)-y(ytx?ok9S*Tz#5Vb=P~xH z^5*t_R2It95=!XDE6X{MjLYn4Eszj9Y91T2SFz@eYlx9Z9*hWaS$^5r7=W5|>sY8}mS(>e9Ez2qI1~wtlA$yv2e-Hjn&K*P z2zWSrC~_8Wrxxf#%QAL&f8iH2%R)E~IrQLgWFg8>`Vnyo?E=uiALoRP&qT{V2{$79 z%9R?*kW-7b#|}*~P#cA@q=V|+RC9=I;aK7Pju$K-n`EoGV^-8Mk=-?@$?O37evGKn z3NEgpo_4{s>=FB}sqx21d3*=gKq-Zk)U+bM%Q_}0`XGkYh*+jRaP+aDnRv#Zz*n$pGp zEU9omuYVXH{AEx>=kk}h2iKt!yqX=EHN)LF}z1j zJx((`CesN1HxTFZ7yrvA2jTPmKYVij>45{ZH2YtsHuGzIRotIFj?(8T@ZWUv{_%AI zgMZlB03C&FtgJqv9%(acqt9N)`4jy4PtYgnhqev!r$GTIOvLF5aZ{tW5MN@9BDGu* zBJzwW3sEJ~Oy8is`l6Ly3an7RPtRr^1Iu(D!B!0O241Xua>Jee;Rc7tWvj!%#yX#m z&pU*?=rTVD7pF6va1D@u@b#V@bShFr3 zMyMbNCZwT)E-%L-{%$3?n}>EN>ai7b$zR_>=l59mW;tfKj^oG)>_TGCJ#HbLBsNy$ zqAqPagZ3uQ(Gsv_-VrZmG&hHaOD#RB#6J8&sL=^iMFB=gH5AIJ+w@sTf7xa&Cnl}@ zxrtzoNq>t?=(+8bS)s2p3>jW}tye0z2aY_Dh@(18-vdfvn;D?sv<>UgL{Ti08$1Q+ zZI3q}yMA^LK=d?YVg({|v?d1|R?5 zL0S3fw)BZazRNNX|7P4rh7!+3tCG~O8l+m?H} z(CB>8(9LtKYIu3ohJ-9ecgk+L&!FX~Wuim&;v$>M4 zUfvn<=Eok(63Ubc>mZrd8d7(>8bG>J?PtOHih_xRYFu1Hg{t;%+hXu2#x%a%qzcab zv$X!ccoj)exoOnaco_jbGw7KryOtuf(SaR-VJ0nAe(1*AA}#QV1lMhGtzD>RoUZ;WA?~!K{8%chYn?ttlz17UpDLlhTkGcVfHY6R<2r4E{mU zq-}D?+*2gAkQYAKrk*rB%4WFC-B!eZZLg4(tR#@kUQHIzEqV48$9=Q(~J_0 zy1%LSCbkoOhRO!J+Oh#;bGuXe;~(bIE*!J@i<%_IcB7wjhB5iF#jBn5+u~fEECN2* z!QFh!m<(>%49H12Y33+?$JxKV3xW{xSs=gxkxW-@Xds^|O1`AmorDKrE8N2-@ospk z=Au%h=f!`_X|G^A;XWL}-_L@D6A~*4Yf!5RTTm$!t8y&fp5_oqvBjW{FufS`!)5m% z2g(=9Ap6Y2y(9OYOWuUVGp-K=6kqQ)kM0P^TQT{X{V$*sN$wbFb-DaUuJF*!?EJPl zJev!UsOB^UHZ2KppYTELh+kqDw+5dPFv&&;;C~=u$Mt+Ywga!8YkL2~@g67}3wAQP zrx^RaXb1(c7vwU8a2se75X(cX^$M{FH4AHS7d2}heqqg4F0!1|Na>UtAdT%3JnS!B)&zelTEj$^b0>Oyfw=P-y-Wd^#dEFRUN*C{!`aJIHi<_YA2?piC%^ zj!p}+ZnBrM?ErAM+D97B*7L8U$K zo(IR-&LF(85p+fuct9~VTSdRjs`d-m|6G;&PoWvC&s8z`TotPSoksp;RsL4VL@CHf z_3|Tn%`ObgRhLmr60<;ya-5wbh&t z#ycN_)3P_KZN5CRyG%LRO4`Ot)3vY#dNX9!f!`_>1%4Q`81E*2BRg~A-VcN7pcX#j zrbl@7`V%n z6J53(m?KRzKb)v?iCuYWbH*l6M77dY4keS!%>}*8n!@ROE4!|7mQ+YS4dff1JJC(t z6Fnuf^=dajqHpH1=|pb(po9Fr8it^;2dEk|Ro=$fxqK$^Yix{G($0m-{RCFQJ~LqUnO7jJcjr zl*N*!6WU;wtF=dLCWzD6kW;y)LEo=4wSXQDIcq5WttgE#%@*m><@H;~Q&GniA-$in z`sjWFLgychS1kIJmPtd-w6%iKkj&dGhtB%0)pyy0M<4HZ@ZY0PWLAd7FCrj&i|NRh?>hZj*&FYnyu%Ur`JdiTu&+n z78d3n)Rl6q&NwVj_jcr#s5G^d?VtV8bkkYco5lV0LiT+t8}98LW>d)|v|V3++zLbHC(NC@X#Hx?21J0M*gP2V`Yd^DYvVIr{C zSc4V)hZKf|OMSm%FVqSRC!phWSyuUAu%0fredf#TDR$|hMZihJ__F!)Nkh6z)d=NC z3q4V*K3JTetxCPgB2_)rhOSWhuXzu+%&>}*ARxUaDeRy{$xK(AC0I=9%X7dmc6?lZNqe-iM(`?Xn3x2Ov>sej6YVQJ9Q42>?4lil?X zew-S>tm{=@QC-zLtg*nh5mQojYnvVzf3!4TpXPuobW_*xYJs;9AokrXcs!Ay z;HK>#;G$*TPN2M!WxdH>oDY6k4A6S>BM0Nimf#LfboKxJXVBC=RBuO&g-=+@O-#0m zh*aPG16zY^tzQLNAF7L(IpGPa+mDsCeAK3k=IL6^LcE8l0o&)k@?dz!79yxUquQIe($zm5DG z5RdXTv)AjHaOPv6z%99mPsa#8OD@9=URvHoJ1hYnV2bG*2XYBgB!-GEoP&8fLmWGg z9NG^xl5D&3L^io&3iYweV*qhc=m+r7C#Jppo$Ygg;jO2yaFU8+F*RmPL` zYxfGKla_--I}YUT353k}nF1zt2NO?+kofR8Efl$Bb^&llgq+HV_UYJUH7M5IoN0sT z4;wDA0gs55ZI|FmJ0}^Pc}{Ji-|#jdR$`!s)Di4^g3b_Qr<*Qu2rz}R6!B^;`Lj3sKWzjMYjexX)-;f5Y+HfkctE{PstO-BZan0zdXPQ=V8 zS8cBhnQyy4oN?J~oK0zl!#S|v6h-nx5to7WkdEk0HKBm;?kcNO*A+u=%f~l&aY*+J z>%^Dz`EQ6!+SEX$>?d(~|MNWU-}JTrk}&`IR|Ske(G^iMdk04)Cxd@}{1=P0U*%L5 zMFH_$R+HUGGv|ju2Z>5x(-aIbVJLcH1S+(E#MNe9g;VZX{5f%_|Kv7|UY-CM(>vf= z!4m?QS+AL+rUyfGJ;~uJGp4{WhOOc%2ybVP68@QTwI(8kDuYf?#^xv zBmOHCZU8O(x)=GVFn%tg@TVW1)qJJ_bU}4e7i>&V?r zh-03>d3DFj&@}6t1y3*yOzllYQ++BO-q!)zsk`D(z||)y&}o%sZ-tUF>0KsiYKFg6 zTONq)P+uL5Vm0w{D5Gms^>H1qa&Z##*X31=58*r%Z@Ko=IMXX{;aiMUp-!$As3{sq z0EEk02MOsgGm7$}E%H1ys2$yftNbB%1rdo@?6~0!a8Ym*1f;jIgfcYEF(I_^+;Xdr z2a>&oc^dF3pm(UNpazXgVzuF<2|zdPGjrNUKpdb$HOgNp*V56XqH`~$c~oSiqx;8_ zEz3fHoU*aJUbFJ&?W)sZB3qOSS;OIZ=n-*#q{?PCXi?Mq4aY@=XvlNQdA;yVC0Vy+ z{Zk6OO!lMYWd`T#bS8FV(`%flEA9El;~WjZKU1YmZpG#49`ku`oV{Bdtvzyz3{k&7 zlG>ik>eL1P93F zd&!aXluU_qV1~sBQf$F%sM4kTfGx5MxO0zJy<#5Z&qzNfull=k1_CZivd-WAuIQf> zBT3&WR|VD|=nKelnp3Q@A~^d_jN3@$x2$f@E~e<$dk$L@06Paw$);l*ewndzL~LuU zq`>vfKb*+=uw`}NsM}~oY}gW%XFwy&A>bi{7s>@(cu4NM;!%ieP$8r6&6jfoq756W z$Y<`J*d7nK4`6t`sZ;l%Oen|+pk|Ry2`p9lri5VD!Gq`U#Ms}pgX3ylAFr8(?1#&dxrtJgB>VqrlWZf61(r`&zMXsV~l{UGjI7R@*NiMJLUoK*kY&gY9kC@^}Fj* zd^l6_t}%Ku<0PY71%zQL`@}L}48M!@=r)Q^Ie5AWhv%#l+Rhu6fRpvv$28TH;N7Cl z%I^4ffBqx@Pxpq|rTJV)$CnxUPOIn`u278s9#ukn>PL25VMv2mff)-RXV&r`Dwid7}TEZxXX1q(h{R6v6X z&x{S_tW%f)BHc!jHNbnrDRjGB@cam{i#zZK*_*xlW@-R3VDmp)<$}S%t*@VmYX;1h zFWmpXt@1xJlc15Yjs2&e%)d`fimRfi?+fS^BoTcrsew%e@T^}wyVv6NGDyMGHSKIQ zC>qFr4GY?#S#pq!%IM_AOf`#}tPoMn7JP8dHXm(v3UTq!aOfEXNRtEJ^4ED@jx%le zvUoUs-d|2(zBsrN0wE(Pj^g5wx{1YPg9FL1)V1JupsVaXNzq4fX+R!oVX+q3tG?L= z>=s38J_!$eSzy0m?om6Wv|ZCbYVHDH*J1_Ndajoh&?L7h&(CVii&rmLu+FcI;1qd_ zHDb3Vk=(`WV?Uq;<0NccEh0s`mBXcEtmwt6oN99RQt7MNER3`{snV$qBTp={Hn!zz z1gkYi#^;P8s!tQl(Y>|lvz{5$uiXsitTD^1YgCp+1%IMIRLiSP`sJru0oY-p!FPbI)!6{XM%)(_Dolh1;$HlghB-&e><;zU&pc=ujpa-(+S&Jj zX1n4T#DJDuG7NP;F5TkoG#qjjZ8NdXxF0l58RK?XO7?faM5*Z17stidTP|a%_N z^e$D?@~q#Pf+708cLSWCK|toT1YSHfXVIs9Dnh5R(}(I;7KhKB7RD>f%;H2X?Z9eR z{lUMuO~ffT!^ew= z7u13>STI4tZpCQ?yb9;tSM-(EGb?iW$a1eBy4-PVejgMXFIV_Ha^XB|F}zK_gzdhM z!)($XfrFHPf&uyFQf$EpcAfk83}91Y`JFJOiQ;v5ca?)a!IxOi36tGkPk4S6EW~eq z>WiK`Vu3D1DaZ}515nl6>;3#xo{GQp1(=uTXl1~ z4gdWxr-8a$L*_G^UVd&bqW_nzMM&SlNW$8|$lAfo@zb+P>2q?=+T^qNwblP*RsN?N zdZE%^Zs;yAwero1qaoqMp~|KL=&npffh981>2om!fseU(CtJ=bW7c6l{U5(07*e0~ zJRbid6?&psp)ilmYYR3ZIg;t;6?*>hoZ3uq7dvyyq-yq$zH$yyImjfhpQb@WKENSP zl;KPCE+KXzU5!)mu12~;2trrLfs&nlEVOndh9&!SAOdeYd}ugwpE-9OF|yQs(w@C9 zoXVX`LP~V>%$<(%~tE*bsq(EFm zU5z{H@Fs^>nm%m%wZs*hRl=KD%4W3|(@j!nJr{Mmkl`e_uR9fZ-E{JY7#s6i()WXB0g-b`R{2r@K{2h3T+a>82>722+$RM*?W5;Bmo6$X3+Ieg9&^TU(*F$Q3 zT572!;vJeBr-)x?cP;^w1zoAM`nWYVz^<6N>SkgG3s4MrNtzQO|A?odKurb6DGZffo>DP_)S0$#gGQ_vw@a9JDXs2}hV&c>$ zUT0;1@cY5kozKOcbN6)n5v)l#>nLFL_x?2NQgurQH(KH@gGe>F|$&@ zq@2A!EXcIsDdzf@cWqElI5~t z4cL9gg7{%~4@`ANXnVAi=JvSsj95-7V& zME3o-%9~2?cvlH#twW~99=-$C=+b5^Yv}Zh4;Mg-!LS zw>gqc=}CzS9>v5C?#re>JsRY!w|Mtv#%O3%Ydn=S9cQarqkZwaM4z(gL~1&oJZ;t; zA5+g3O6itCsu93!G1J_J%Icku>b3O6qBW$1Ej_oUWc@MI)| zQ~eyS-EAAnVZp}CQnvG0N>Kc$h^1DRJkE7xZqJ0>p<>9*apXgBMI-v87E0+PeJ-K& z#(8>P_W^h_kBkI;&e_{~!M+TXt@z8Po*!L^8XBn{of)knd-xp{heZh~@EunB2W)gd zAVTw6ZZasTi>((qpBFh(r4)k zz&@Mc@ZcI-4d639AfcOgHOU+YtpZ)rC%Bc5gw5o~+E-i+bMm(A6!uE>=>1M;V!Wl4 z<#~muol$FsY_qQC{JDc8b=$l6Y_@_!$av^08`czSm!Xan{l$@GO-zPq1s>WF)G=wv zDD8j~Ht1pFj)*-b7h>W)@O&m&VyYci&}K|0_Z*w`L>1jnGfCf@6p}Ef*?wdficVe_ zmPRUZ(C+YJU+hIj@_#IiM7+$4kH#VS5tM!Ksz01siPc-WUe9Y3|pb4u2qnn zRavJiRpa zq?tr&YV?yKt<@-kAFl3s&Kq#jag$hN+Y%%kX_ytvpCsElgFoN3SsZLC>0f|m#&Jhu zp7c1dV$55$+k78FI2q!FT}r|}cIV;zp~#6X2&}22$t6cHx_95FL~T~1XW21VFuatb zpM@6w>c^SJ>Pq6{L&f9()uy)TAWf;6LyHH3BUiJ8A4}od)9sriz~e7}l7Vr0e%(=>KG1Jay zW0azuWC`(|B?<6;R)2}aU`r@mt_#W2VrO{LcX$Hg9f4H#XpOsAOX02x^w9+xnLVAt z^~hv2guE-DElBG+`+`>PwXn5kuP_ZiOO3QuwoEr)ky;o$n7hFoh}Aq0@Ar<8`H!n} zspCC^EB=6>$q*gf&M2wj@zzfBl(w_@0;h^*fC#PW9!-kT-dt*e7^)OIU{Uw%U4d#g zL&o>6`hKQUps|G4F_5AuFU4wI)(%9(av7-u40(IaI|%ir@~w9-rLs&efOR@oQy)}{ z&T#Qf`!|52W0d+>G!h~5A}7VJky`C3^fkJzt3|M&xW~x-8rSi-uz=qBsgODqbl(W#f{Ew#ui(K)(Hr&xqZs` zfrK^2)tF#|U=K|_U@|r=M_Hb;qj1GJG=O=d`~#AFAccecIaq3U`(Ds1*f*TIs=IGL zp_vlaRUtFNK8(k;JEu&|i_m39c(HblQkF8g#l|?hPaUzH2kAAF1>>Yykva0;U@&oRV8w?5yEK??A0SBgh?@Pd zJg{O~4xURt7!a;$rz9%IMHQeEZHR8KgFQixarg+MfmM_OeX#~#&?mx44qe!wt`~dd zqyt^~ML>V>2Do$huU<7}EF2wy9^kJJSm6HoAD*sRz%a|aJWz_n6?bz99h)jNMp}3k ztPVbos1$lC1nX_OK0~h>=F&v^IfgBF{#BIi&HTL}O7H-t4+wwa)kf3AE2-Dx@#mTA z!0f`>vz+d3AF$NH_-JqkuK1C+5>yns0G;r5ApsU|a-w9^j4c+FS{#+7- zH%skr+TJ~W_8CK_j$T1b;$ql_+;q6W|D^BNK*A+W5XQBbJy|)(IDA=L9d>t1`KX2b zOX(Ffv*m?e>! zS3lc>XC@IqPf1g-%^4XyGl*1v0NWnwZTW?z4Y6sncXkaA{?NYna3(n@(+n+#sYm}A zGQS;*Li$4R(Ff{obl3#6pUsA0fKuWurQo$mWXMNPV5K66V!XYOyc})^>889Hg3I<{V^Lj9($B4Zu$xRr=89-lDz9x`+I8q(vEAimx1K{sTbs|5x7S zZ+7o$;9&9>@3K;5-DVzGw=kp7ez%1*kxhGytdLS>Q)=xUWv3k_x(IsS8we39Tijvr z`GKk>gkZTHSht;5q%fh9z?vk%sWO}KR04G9^jleJ^@ovWrob7{1xy7V=;S~dDVt%S za$Q#Th%6g1(hiP>hDe}7lcuI94K-2~Q0R3A1nsb7Y*Z!DtQ(Ic<0;TDKvc6%1kBdJ z$hF!{uALB0pa?B^TC}#N5gZ|CKjy|BnT$7eaKj;f>Alqdb_FA3yjZ4CCvm)D&ibL) zZRi91HC!TIAUl<|`rK_6avGh`!)TKk=j|8*W|!vb9>HLv^E%t$`@r@piI(6V8pqDG zBON7~=cf1ZWF6jc{qkKm;oYBtUpIdau6s+<-o^5qNi-p%L%xAtn9OktFd{@EjVAT% z#?-MJ5}Q9QiK_jYYWs+;I4&!N^(mb!%4zx7qO6oCEDn=8oL6#*9XIJ&iJ30O`0vsFy|fEVkw}*jd&B6!IYi+~Y)qv6QlM&V9g0 zh)@^BVDB|P&#X{31>G*nAT}Mz-j~zd>L{v{9AxrxKFw8j;ccQ$NE0PZCc(7fEt1xd z`(oR2!gX6}R+Z77VkDz^{I)@%&HQT5q+1xlf*3R^U8q%;IT8-B53&}dNA7GW`Ki&= z$lrdH zDCu;j$GxW<&v_4Te7=AE2J0u1NM_7Hl9$u{z(8#%8vvrx2P#R7AwnY|?#LbWmROa; zOJzU_*^+n(+k;Jd{e~So9>OF>fPx$Hb$?~K1ul2xr>>o@**n^6IMu8+o3rDp(X$cC z`wQt9qIS>yjA$K~bg{M%kJ00A)U4L+#*@$8UlS#lN3YA{R{7{-zu#n1>0@(#^eb_% zY|q}2)jOEM8t~9p$X5fpT7BZQ1bND#^Uyaa{mNcFWL|MoYb@>y`d{VwmsF&haoJuS2W7azZU0{tu#Jj_-^QRc35tjW~ae&zhKk!wD}#xR1WHu z_7Fys#bp&R?VXy$WYa$~!dMxt2@*(>@xS}5f-@6eoT%rwH zv_6}M?+piNE;BqaKzm1kK@?fTy$4k5cqYdN8x-<(o6KelwvkTqC3VW5HEnr+WGQlF zs`lcYEm=HPpmM4;Ich7A3a5Mb3YyQs7(Tuz-k4O0*-YGvl+2&V(B&L1F8qfR0@vQM-rF<2h-l9T12eL}3LnNAVyY_z51xVr$%@VQ-lS~wf3mnHc zoM({3Z<3+PpTFCRn_Y6cbxu9v>_>eTN0>hHPl_NQQuaK^Mhrv zX{q#80ot;ptt3#js3>kD&uNs{G0mQp>jyc0GG?=9wb33hm z`y2jL=J)T1JD7eX3xa4h$bG}2ev=?7f>-JmCj6){Upo&$k{2WA=%f;KB;X5e;JF3IjQBa4e-Gp~xv- z|In&Rad7LjJVz*q*+splCj|{7=kvQLw0F@$vPuw4m^z=B^7=A4asK_`%lEf_oIJ-O z{L)zi4bd#&g0w{p1$#I&@bz3QXu%Y)j46HAJKWVfRRB*oXo4lIy7BcVl4hRs<%&iQ zr|)Z^LUJ>qn>{6y`JdabfNNFPX7#3`x|uw+z@h<`x{J4&NlDjnknMf(VW_nKWT!Jh zo1iWBqT6^BR-{T=4Ybe+?6zxP_;A5Uo{}Xel%*=|zRGm1)pR43K39SZ=%{MDCS2d$~}PE-xPw4ZK6)H;Zc&0D5p!vjCn0wCe&rVIhchR9ql!p2`g0b@JsC^J#n_r*4lZ~u0UHKwo(HaHUJDHf^gdJhTdTW z3i7Zp_`xyKC&AI^#~JMVZj^9WsW}UR#nc#o+ifY<4`M+?Y9NTBT~p`ONtAFf8(ltr*ER-Ig!yRs2xke#NN zkyFcaQKYv>L8mQdrL+#rjgVY>Z2_$bIUz(kaqL}cYENh-2S6BQK-a(VNDa_UewSW` zMgHi<3`f!eHsyL6*^e^W7#l?V|42CfAjsgyiJsA`yNfAMB*lAsJj^K3EcCzm1KT zDU2+A5~X%ax-JJ@&7>m`T;;}(-e%gcYQtj}?ic<*gkv)X2-QJI5I0tA2`*zZRX(;6 zJ0dYfMbQ+{9Rn3T@Iu4+imx3Y%bcf2{uT4j-msZ~eO)5Z_T7NC|Nr3)|NWjomhv=E zXaVin)MY)`1QtDyO7mUCjG{5+o1jD_anyKn73uflH*ASA8rm+S=gIfgJ);>Zx*hNG z!)8DDCNOrbR#9M7Ud_1kf6BP)x^p(|_VWCJ+(WGDbYmnMLWc?O4zz#eiP3{NfP1UV z(n3vc-axE&vko^f+4nkF=XK-mnHHQ7>w05$Q}iv(kJc4O3TEvuIDM<=U9@`~WdKN* zp4e4R1ncR_kghW}>aE$@OOc~*aH5OOwB5U*Z)%{LRlhtHuigxH8KuDwvq5{3Zg{Vr zrd@)KPwVKFP2{rXho(>MTZZfkr$*alm_lltPob4N4MmhEkv`J(9NZFzA>q0Ch;!Ut zi@jS_=0%HAlN+$-IZGPi_6$)ap>Z{XQGt&@ZaJ(es!Po5*3}>R4x66WZNsjE4BVgn z>}xm=V?F#tx#e+pimNPH?Md5hV7>0pAg$K!?mpt@pXg6UW9c?gvzlNe0 z3QtIWmw$0raJkjQcbv-7Ri&eX6Ks@@EZ&53N|g7HU<;V1pkc&$3D#8k!coJ=^{=vf z-pCP;vr2#A+i#6VA?!hs6A4P@mN62XYY$#W9;MwNia~89i`=1GoFESI+%Mbrmwg*0 zbBq4^bA^XT#1MAOum)L&ARDXJ6S#G>&*72f50M1r5JAnM1p7GFIv$Kf9eVR(u$KLt z9&hQ{t^i16zL1c(tRa~?qr?lbSN;1k;%;p*#gw_BwHJRjcYPTj6>y-rw*dFTnEs95 z`%-AoPL!P16{=#RI0 zUb6#`KR|v^?6uNnY`zglZ#Wd|{*rZ(x&Hk8N6ob6mpX~e^qu5kxvh$2TLJA$M=rx zc!#ot+sS+-!O<0KR6+Lx&~zgEhCsbFY{i_DQCihspM?e z-V}HemMAvFzXR#fV~a=Xf-;tJ1edd}Mry@^=9BxON;dYr8vDEK<<{ zW~rg(ZspxuC&aJo$GTM!9_sXu(EaQJNkV9AC(ob#uA=b4*!Uf}B*@TK=*dBvKKPAF z%14J$S)s-ws9~qKsf>DseEW(ssVQ9__YNg}r9GGx3AJiZR@w_QBlGP>yYh0lQCBtf zx+G;mP+cMAg&b^7J!`SiBwC81M_r0X9kAr2y$0(Lf1gZK#>i!cbww(hn$;fLIxRf? z!AtkSZc-h76KGSGz%48Oe`8ZBHkSXeVb!TJt_VC>$m<#}(Z}!(3h631ltKb3CDMw^fTRy%Ia!b&at`^g7Ew-%WLT9(#V0OP9CE?uj62s>`GI3NA z!`$U+i<`;IQyNBkou4|-7^9^ylac-Xu!M+V5p5l0Ve?J0wTSV+$gYtoc=+Ve*OJUJ z$+uIGALW?}+M!J9+M&#bT=Hz@{R2o>NtNGu1yS({pyteyb>*sg4N`KAD?`u3F#C1y z2K4FKOAPASGZTep54PqyCG(h3?kqQQAxDSW@>T2d!n;9C8NGS;3A8YMRcL>b=<<%M zMiWf$jY;`Ojq5S{kA!?28o)v$;)5bTL<4eM-_^h4)F#eeC2Dj*S`$jl^yn#NjJOYT zx%yC5Ww@eX*zsM)P(5#wRd=0+3~&3pdIH7CxF_2iZSw@>kCyd z%M}$1p((Bidw4XNtk&`BTkU{-PG)SXIZ)yQ!Iol6u8l*SQ1^%zC72FP zLvG>_Z0SReMvB%)1@+et0S{<3hV@^SY3V~5IY(KUtTR{*^xJ^2NN{sIMD9Mr9$~(C$GLNlSpzS=fsbw-DtHb_T|{s z9OR|sx!{?F``H!gVUltY7l~dx^a(2;OUV^)7 z%@hg`8+r&xIxmzZ;Q&v0X%9P)U0SE@r@(lKP%TO(>6I_iF{?PX(bez6v8Gp!W_nd5 z<8)`1jcT)ImNZp-9rr4_1MQ|!?#8sJQx{`~7)QZ75I=DPAFD9Mt{zqFrcrXCU9MG8 zEuGcy;nZ?J#M3!3DWW?Zqv~dnN6ijlIjPfJx(#S0cs;Z=jDjKY|$w2s4*Xa1Iz953sN2Lt!Vmk|%ZwOOqj`sA--5Hiaq8!C%LV zvWZ=bxeRV(&%BffMJ_F~~*FdcjhRVNUXu)MS(S#67rDe%Ler=GS+WysC1I2=Bmbh3s6wdS}o$0 zz%H08#SPFY9JPdL6blGD$D-AaYi;X!#zqib`(XX*i<*eh+2UEPzU4}V4RlC3{<>-~ zadGA8lSm>b7Z!q;D_f9DT4i)Q_}ByElGl*Cy~zX%IzHp)@g-itZB6xM70psn z;AY8II99e6P2drgtTG5>`^|7qg`9MTp%T~|1N3tBqV}2zgow3TFAH{XPor0%=HrkXnKyxyozHlJ6 zd3}OWkl?H$l#yZqOzZbMI+lDLoH48;s10!m1!K87g;t}^+A3f3e&w{EYhVPR0Km*- zh5-ku$Z|Ss{2?4pGm(Rz!0OQb^_*N`)rW{z)^Cw_`a(_L9j=&HEJl(!4rQy1IS)>- zeTIr>hOii`gc(fgYF(cs$R8l@q{mJzpoB5`5r>|sG zBpsY}RkY(g5`bj~D>(;F8v*DyjX(#nVLSs>)XneWI&%Wo>a0u#4A?N<1SK4D}&V1oN)76 z%S>a2n3n>G`YY1>0Hvn&AMtMuI_?`5?4y3w2Hnq4Qa2YH5 zxKdfM;k467djL31Y$0kd9FCPbU=pHBp@zaIi`Xkd80;%&66zvSqsq6%aY)jZacfvw ztkWE{ZV6V2WL9e}Dvz|!d96KqVkJU@5ryp#rReeWu>mSrOJxY^tWC9wd0)$+lZc%{ zY=c4#%OSyQJvQUuy^u}s8DN8|8T%TajOuaY^)R-&8s@r9D`(Ic4NmEu)fg1f!u`xUb;9t#rM z>}cY=648@d5(9A;J)d{a^*ORdVtJrZ77!g~^lZ9@)|-ojvW#>)Jhe8$7W3mhmQh@S zU=CSO+1gSsQ+Tv=x-BD}*py_Ox@;%#hPb&tqXqyUW9jV+fonnuCyVw=?HR>dAB~Fg z^vl*~y*4|)WUW*9RC%~O1gHW~*tJb^a-j;ae2LRNo|0S2`RX>MYqGKB^_ng7YRc@! zFxg1X!VsvXkNuv^3mI`F2=x6$(pZdw=jfYt1ja3FY7a41T07FPdCqFhU6%o|Yb6Z4 zpBGa=(ao3vvhUv#*S{li|EyujXQPUV;0sa5!0Ut)>tPWyC9e0_9(=v*z`TV5OUCcx zT=w=^8#5u~7<}8Mepqln4lDv*-~g^VoV{(+*4w(q{At6d^E-Usa2`JXty++Oh~on^ z;;WHkJsk2jvh#N|?(2PLl+g!M0#z_A;(#Uy=TzL&{Ei5G9#V{JbhKV$Qmkm%5tn!CMA? z@hM=b@2DZWTQ6>&F6WCq6;~~WALiS#@{|I+ucCmD6|tBf&e;$_)%JL8$oIQ%!|Xih1v4A$=7xNO zZVz$G8;G5)rxyD+M0$20L$4yukA_D+)xmK3DMTH3Q+$N&L%qB)XwYx&s1gkh=%qGCCPwnwhbT4p%*3R)I}S#w7HK3W^E%4w z2+7ctHPx3Q97MFYB48HfD!xKKb(U^K_4)Bz(5dvwyl*R?)k;uHEYVi|{^rvh)w7}t z`tnH{v9nlVHj2ign|1an_wz0vO)*`3RaJc#;(W-Q6!P&>+@#fptCgtUSn4!@b7tW0&pE2Qj@7}f#ugu4*C)8_}AMRuz^WG zc)XDcOPQjRaGptRD^57B83B-2NKRo!j6TBAJntJPHNQG;^Oz}zt5F^kId~miK3J@l ztc-IKp6qL!?u~q?qfGP0I~$5gvq#-0;R(oLU@sYayr*QH95fnrYA*E|n%&FP@Cz`a zSdJ~(c@O^>qaO`m9IQ8sd8!L<+)GPJDrL7{4{ko2gWOZel^3!($Gjt|B&$4dtfTmBmC>V`R&&6$wpgvdmns zxcmfS%9_ZoN>F~azvLFtA(9Q5HYT#A(byGkESnt{$Tu<73$W~reB4&KF^JBsoqJ6b zS?$D7DoUgzLO-?P`V?5_ub$nf1p0mF?I)StvPomT{uYjy!w&z$t~j&en=F~hw|O(1 zlV9$arQmKTc$L)Kupwz_zA~deT+-0WX6NzFPh&d+ly*3$%#?Ca9Z9lOJsGVoQ&1HNg+)tJ_sw)%oo*DK)iU~n zvL``LqTe=r=7SwZ@LB)9|3QB5`0(B9r(iR}0nUwJss-v=dXnwMRQFYSRK1blS#^g(3@z{`=8_CGDm!LESTWig zzm1{?AG&7`uYJ;PoFO$o8RWuYsV26V{>D-iYTnvq7igWx9@w$EC*FV^vpvDl@i9yp zPIqiX@hEZF4VqzI3Y)CHhR`xKN8poL&~ak|wgbE4zR%Dm(a@?bw%(7(!^>CM!^4@J z6Z)KhoQP;WBq_Z_&<@i2t2&xq>N>b;Np2rX?yK|-!14iE2T}E|jC+=wYe~`y38g3J z8QGZquvqBaG!vw&VtdXWX5*i5*% zJP~7h{?&E|<#l{klGPaun`IgAJ4;RlbRqgJz5rmHF>MtJHbfqyyZi53?Lhj=(Ku#& z__ubmZIxzSq3F90Xur!1)Vqe6b@!ueHA!93H~jdHmaS5Q^CULso}^poy)0Op6!{^9 zWyCyyIrdBP4fkliZ%*g+J-A!6VFSRF6Liu6G^^=W>cn81>4&7(c7(6vCGSAJ zQZ|S3mb|^Wf=yJ(h~rq`iiW~|n#$+KcblIR<@|lDtm!&NBzSG-1;7#YaU+-@=xIm4 zE}edTYd~e&_%+`dIqqgFntL-FxL3!m4yTNt<(^Vt9c6F(`?9`u>$oNxoKB29<}9FE zgf)VK!*F}nW?}l95%RRk8N4^Rf8)Xf;drT4<|lUDLPj^NPMrBPL;MX&0oGCsS za3}vWcF(IPx&W6{s%zwX{UxHX2&xLGfT{d9bWP!g;Lg#etpuno$}tHoG<4Kd*=kpU z;4%y(<^yj(UlG%l-7E9z_Kh2KoQ19qT3CR@Ghr>BAgr3Vniz3LmpC4g=g|A3968yD2KD$P7v$ zx9Q8`2&qH3&y-iv0#0+jur@}k`6C%7fKbCr|tHX2&O%r?rBpg`YNy~2m+ z*L7dP$RANzVUsG_Lb>=__``6vA*xpUecuGsL+AW?BeSwyoQfDlXe8R1*R1M{0#M?M zF+m19`3<`gM{+GpgW^=UmuK*yMh3}x)7P738wL8r@(Na6%ULPgbPVTa6gh5Q(SR0f znr6kdRpe^(LVM;6Rt(Z@Lsz3EX*ry6(WZ?w>#ZRelx)N%sE+MN>5G|Z8{%@b&D+Ov zPU{shc9}%;G7l;qbonIb_1m^Qc8ez}gTC-k02G8Rl?7={9zBz8uRX2{XJQ{vZhs67avlRn| zgRtWl0Lhjet&!YC47GIm%1gdq%T24_^@!W3pCywc89X4I5pnBCZDn(%!$lOGvS*`0!AoMtqxNPFgaMR zwoW$p;8l6v%a)vaNsesED3f}$%(>zICnoE|5JwP&+0XI}JxPccd+D^gx`g`=GsUc0 z9Uad|C+_@_0%JmcObGnS@3+J^0P!tg+fUZ_w#4rk#TlJYPXJiO>SBxzs9(J;XV9d{ zmTQE1(K8EYaz9p^XLbdWudyIPJlGPo0U*)fAh-jnbfm@SYD_2+?|DJ-^P+ojG{2{6 z>HJtedEjO@j_tqZ4;Zq1t5*5cWm~W?HGP!@_f6m#btM@46cEMhhK{(yI&jG)fwL1W z^n_?o@G8a-jYt!}$H*;{0#z8lANlo!9b@!c5K8<(#lPlpE!z86Yq#>WT&2} z;;G1$pD%iNoj#Z=&kij5&V1KHIhN-h<;{HC5wD)PvkF>CzlQOEx_0;-TJ*!#&{Wzt zKcvq^SZIdop}y~iouNqtU7K7+?eIz-v_rfNM>t#i+dD$s_`M;sjGubTdP)WI*uL@xPOLHt#~T<@Yz>xt50ZoTw;a(a}lNiDN-J${gOdE zx?8LOA|tv{Mb}=TTR=LcqMqbCJkKj+@;4Mu)Cu0{`~ohix6E$g&tff)aHeUAQQ%M? zIN4uSUTzC1iMEWL*W-in1y)C`E+R8j?4_?X4&2Zv5?QdkNMz(k} zw##^Ikx`#_s>i&CO_mu@vJJ*|3ePRDl5pq$9V^>D;g0R%l>lw;ttyM6Sy`NBF{)Lr zSk)V>mZr96+aHY%vTLLt%vO-+juw6^SO_ zYGJaGeWX6W(TOQx=5oTGXOFqMMU*uZyt>MR-Y`vxW#^&)H zk0!F8f*@v6NO@Z*@Qo)+hlX40EWcj~j9dGrLaq%1;DE_%#lffXCcJ;!ZyyyZTz74Q zb2WSly6sX{`gQeToQsi1-()5EJ1nJ*kXGD`xpXr~?F#V^sxE3qSOwRSaC9x9oa~jJ zTG9`E|q zC5Qs1xh}jzb5UPYF`3N9YuMnI7xsZ41P;?@c|%w zl=OxLr6sMGR+`LStLvh)g?fA5p|xbUD;yFAMQg&!PEDYxVYDfA>oTY;CFt`cg?Li1 z0b})!9Rvw&j#*&+D2))kXLL z0+j=?7?#~_}N-qdEIP>DQaZh#F(#e0WNLzwUAj@r694VJ8?Dr5_io2X49XYsG^ zREt0$HiNI~6VV!ycvao+0v7uT$_ilKCvsC+VDNg7yG1X+eNe^3D^S==F3ByiW0T^F zH6EsH^}Uj^VPIE&m)xlmOScYR(w750>hclqH~~dM2+;%GDXT`u4zG!p((*`Hwx41M z4KB+`hfT(YA%W)Ve(n+Gu9kuXWKzxg{1ff^xNQw>w%L-)RySTk9kAS92(X0Shg^Q? zx1YXg_TLC^?h6!4mBqZ9pKhXByu|u~gF%`%`vdoaGBN3^j4l!4x?Bw4Jd)Z4^di}! zXlG1;hFvc>H?bmmu1E7Vx=%vahd!P1#ZGJOJYNbaek^$DHt`EOE|Hlij+hX>ocQFSLVu|wz`|KVl@Oa;m2k6b*mNK2Vo{~l9>Qa3@B7G7#k?)aLx;w6U ze8bBq%vF?5v>#TspEoaII!N}sRT~>bh-VWJ7Q*1qsz%|G)CFmnttbq$Ogb{~YK_=! z{{0vhlW@g!$>|}$&4E3@k`KPElW6x#tSX&dfle>o!irek$NAbDzdd2pVeNzk4&qgJ zXvNF0$R96~g0x+R1igR=Xu&X_Hc5;!Ze&C)eUTB$9wW&?$&o8Yxhm5s(S`;?{> z*F?9Gr0|!OiKA>Rq-ae=_okB6&yMR?!JDer{@iQgIn=cGxs-u^!8Q$+N&pfg2WM&Z zulHu=Uh~U>fS{=Nm0x>ACvG*4R`Dx^kJ65&Vvfj`rSCV$5>c04N26Rt2S?*kh3JKq z9(3}5T?*x*AP(X2Ukftym0XOvg~r6Ms$2x&R&#}Sz23aMGU&7sU-cFvE3Eq`NBJe84VoftWF#v7PDAp`@V zRFCS24_k~;@~R*L)eCx@Q9EYmM)Sn}HLbVMyxx%{XnMBDc-YZ<(DXDBYUt8$u5Zh} zBK~=M9cG$?_m_M61YG+#|9Vef7LfbH>(C21&aC)x$^Lg}fa#SF){RX|?-xZjSOrn# z2ZAwUF)$VB<&S;R3FhNSQOV~8w%A`V9dWyLiy zgt7G=Z4t|zU3!dh5|s(@XyS|waBr$>@=^Dspmem8)@L`Ns{xl%rGdX!R(BiC5C7Vo zXetb$oC_iXS}2x_Hy}T(hUUNbO47Q@+^4Q`h>(R-;OxCyW#eoOeC51jzxnM1yxBrp zz6}z`(=cngs6X05e79o_B7@3K|Qpe3n38Py_~ zpi?^rj!`pq!7PHGliC$`-8A^Ib?2qgJJCW+(&TfOnFGJ+@-<<~`7BR0f4oSINBq&R z2CM`0%WLg_Duw^1SPwj-{?BUl2Y=M4e+7yL1{C&&f&zjF06#xf>VdLozgNye(BNgSD`=fFbBy0HIosLl@JwCQl^s;eTnc( z3!r8G=K>zb`|bLLI0N|eFJk%s)B>oJ^M@AQzqR;HUjLsOqW<0v>1ksT_#24*U@R3HJu*A^#1o#P3%3_jq>icD@<`tqU6ICEgZrME(xX#?i^Z z%Id$_uyQGlFD-CcaiRtRdGn|K`Lq5L-rx7`vYYGH7I=eLfHRozPiUtSe~Tt;IN2^gCXmf2#D~g2@9bhzK}3nphhG%d?V7+Zq{I2?Gt*!NSn_r~dd$ zqkUOg{U=MI?Ehx@`(X%rQB?LP=CjJ*V!rec{#0W2WshH$X#9zep!K)tzZoge*LYd5 z@g?-j5_mtMp>_WW`p*UNUZTFN{_+#m*bJzt{hvAdkF{W40{#L3w6gzPztnsA_4?&0 z(+>pv!zB16rR-(nm(^c>Z(its{ny677vT8sF564^mlZvJ!h65}OW%Hn|2OXbOQM%b z{6C54Z2v;^hyMQ;UH+HwFD2!F!VlQ}6Z{L0_9g5~CH0@Mqz?ZC`^QkhOU#$Lx<4`B zyZsa9uPF!rZDo8ZVfzzR#raQ>5|)k~_Ef*wDqG^76o)j!C4 zykvT*o$!-MBko@?{b~*Zf2*YMlImrK`cEp|#D7f%Twm<|C|dWD \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/lib/as3/gradlew.bat b/lib/as3/gradlew.bat new file mode 100644 index 00000000000..6d57edc706c --- /dev/null +++ b/lib/as3/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/lib/as3/settings.gradle b/lib/as3/settings.gradle new file mode 100644 index 00000000000..49323464190 --- /dev/null +++ b/lib/as3/settings.gradle @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +rootProject.name = 'libthrift-as3' diff --git a/lib/java/build.gradle b/lib/java/build.gradle index 6dd35e45724..5b0541b3bba 100644 --- a/lib/java/build.gradle +++ b/lib/java/build.gradle @@ -46,7 +46,6 @@ defaultTasks 'build' group = property('thrift.groupid') // Drop the -dev suffix, we use the SNAPSHOT suffix for non-release versions -def parsedVersion = property('thrift.version').toString().replace('-dev', '') if (Boolean.parseBoolean(project.release)) { version = parsedVersion } else { diff --git a/lib/java/gradle.properties b/lib/java/gradle.properties index 58ca5f8a538..7fef76de1d0 100644 --- a/lib/java/gradle.properties +++ b/lib/java/gradle.properties @@ -31,13 +31,3 @@ slf4j.version=1.7.25 servlet.version=2.5 junit.version=4.12 mockito.version=1.9.5 - -# Signing key information for artifacts PGP signature (values are examples) -# signing.keyId=ABCD0123 -# signing.password=signingPassword -# signing.secretKeyRingFile=/root/.gnupg/secring.gpg - -# Apache Maven staging repository user credentials -# mavenUser=mavenUser -# mavenPassword=mySuperSecretPassword - From c685cb05d4138ae5477ed0ebd37f36aaa6531082 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 24 Jan 2019 00:21:23 -0500 Subject: [PATCH 242/756] THRIFT-4698: add haskell hackage sdist target and fix cabal file --- lib/hs/Makefile.am | 3 +++ lib/hs/thrift.cabal | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/hs/Makefile.am b/lib/hs/Makefile.am index 3cd8b57d615..ba156a13044 100644 --- a/lib/hs/Makefile.am +++ b/lib/hs/Makefile.am @@ -39,6 +39,9 @@ install-exec-hook: clean-local: $(CABAL) clean +dist-local: + $(CABAL) sdist + maintainer-clean-local: $(CABAL) clean diff --git a/lib/hs/thrift.cabal b/lib/hs/thrift.cabal index c136480afa9..b13cff4882f 100644 --- a/lib/hs/thrift.cabal +++ b/lib/hs/thrift.cabal @@ -20,7 +20,7 @@ Name: thrift Version: 0.12.0 Cabal-Version: 1.24 -License: OtherLicense +License: Apache Category: Foreign Build-Type: Simple Synopsis: Haskell bindings for the Apache Thrift RPC system From 8d21d80cd151b3c4503955bf3eada915dd00f389 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Mon, 25 Feb 2019 22:27:59 +0100 Subject: [PATCH 243/756] Release 0.12.1 --- CHANGES | 15 +++++++++++++++ Thrift-swift3.podspec | 4 ++-- Thrift.podspec | 4 ++-- appveyor.yml | 2 +- bower.json | 2 +- build/cmake/DefineCMakeDefaults.cmake | 2 +- configure.ac | 2 +- contrib/Rebus/Properties/AssemblyInfo.cs | 4 ++-- contrib/fb303/py/setup.py | 2 +- contrib/thrift-maven-plugin/pom.xml | 2 +- contrib/thrift.spec | 2 +- contrib/vagrant/centos-6.5/README.md | 2 +- contrib/zeromq/csharp/ThriftZMQ.csproj | 2 +- debian/changelog | 6 ++++++ doap.rdf | 5 +++++ lib/as3/gradle.properties | 3 ++- lib/c_glib/README.md | 2 +- lib/cocoa/src/Thrift.h | 2 +- .../ThriftMSBuildTask/Properties/AssemblyInfo.cs | 4 ++-- .../ThriftMSBuildTask/ThriftMSBuildTask.csproj | 2 +- lib/csharp/src/Properties/AssemblyInfo.cs | 4 ++-- lib/csharp/src/Thrift.csproj | 2 +- .../test/Multiplex/Client/MultiplexClient.csproj | 2 +- .../Multiplex/Client/Properties/AssemblyInfo.cs | 4 ++-- .../test/Multiplex/Server/MultiplexServer.csproj | 2 +- .../Multiplex/Server/Properties/AssemblyInfo.cs | 4 ++-- .../test/ThriftMVCTest/Properties/AssemblyInfo.cs | 4 ++-- lib/d/src/thrift/base.d | 2 +- lib/dart/pubspec.yaml | 2 +- lib/delphi/src/Thrift.pas | 2 +- lib/erl/src/thrift.app.src | 2 +- lib/go/thrift/serializer_types_test.go | 2 +- lib/haxe/README.md | 4 ++-- lib/haxe/haxelib.json | 2 +- lib/hs/thrift.cabal | 2 +- lib/java/gradle.properties | 2 +- lib/js/package.json | 2 +- lib/js/src/thrift.js | 2 +- lib/lua/THttpTransport.lua | 2 +- lib/lua/Thrift.lua | 2 +- lib/netcore/Thrift/Properties/AssemblyInfo.cs | 4 ++-- .../Transports/Client/THttpClientTransport.cs | 2 +- lib/ocaml/_oasis | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/php/README.md | 2 +- lib/py/setup.py | 2 +- lib/rb/thrift.gemspec | 2 +- lib/rs/Cargo.toml | 2 +- lib/rs/README.md | 2 +- lib/st/package.xml | 2 +- package-lock.json | 2 +- package.json | 2 +- sonar-project.properties | 6 +++--- test/csharp/Properties/AssemblyInfo.cs | 4 ++-- test/csharp/ThriftTest.csproj | 2 +- test/dart/test_client/pubspec.yaml | 2 +- test/erl/src/thrift_test.app.src | 2 +- .../CsharpClient/Properties/AssemblyInfo.cs | 4 ++-- .../CsharpServer/Properties/AssemblyInfo.cs | 4 ++-- tutorial/dart/client/pubspec.yaml | 2 +- tutorial/dart/console_client/pubspec.yaml | 2 +- tutorial/dart/server/pubspec.yaml | 2 +- tutorial/delphi/DelphiClient/DelphiClient.dproj | 2 +- tutorial/delphi/DelphiServer/DelphiServer.dproj | 2 +- tutorial/hs/ThriftTutorial.cabal | 2 +- tutorial/ocaml/_oasis | 2 +- 66 files changed, 105 insertions(+), 78 deletions(-) diff --git a/CHANGES b/CHANGES index e3e50b6bc85..51d6b64e64a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,20 @@ Apache Thrift Changelog +================================================================================ +Thrift 0.12.1 +-------------------------------------------------------------------------------- + +## Bug fixes + * [THRIFT-4024] - Skip() should throw on unknown data types + * [THRIFT-4783] - Thrift should throw when skipping over unexpected data + * [THRIFT-4784] - Thrift should throw when skipping over unexpected data + * additional test for TSimpleJSONProtocol + * [THRIFT-4698] - add haskell hackage sdist target and fix cabal file + * [THRIFT-4750] - as3 changes to build and publish to maven central + * [THRIFT-4746] - changes for publishing to maven; fix java debug vs. release build with cmake + * [THRIFT-4691] - ensure CPAN module runs unit tests + + ================================================================================ Thrift 0.12.0 -------------------------------------------------------------------------------- diff --git a/Thrift-swift3.podspec b/Thrift-swift3.podspec index 542d81057bc..cebcdefebda 100644 --- a/Thrift-swift3.podspec +++ b/Thrift-swift3.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Thrift-swift3" - s.version = "0.12.0" + s.version = "0.12.1" s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC." s.description = <<-DESC The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages. @@ -11,6 +11,6 @@ The Apache Thrift software framework, for scalable cross-language services devel s.ios.deployment_target = '9.0' s.osx.deployment_target = '10.10' s.requires_arc = true - s.source = { :git => "https://github.com/apache/thrift.git", :tag => "0.12.0" } + s.source = { :git => "https://github.com/apache/thrift.git", :tag => "v0.12.1" } s.source_files = "lib/swift/Sources/*.swift" end diff --git a/Thrift.podspec b/Thrift.podspec index e5b8149b6d2..96ed0ebb3e9 100644 --- a/Thrift.podspec +++ b/Thrift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Thrift" - s.version = "0.12.0" + s.version = "0.12.1" s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC." s.description = <<-DESC The Apache Thrift software framework, for scalable cross-language services development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages. @@ -13,6 +13,6 @@ The Apache Thrift software framework, for scalable cross-language services devel s.osx.deployment_target = '10.8' s.ios.framework = 'CFNetwork' s.osx.framework = 'CoreServices' - s.source = { :git => "https://github.com/apache/thrift.git", :tag => "0.12.0" } + s.source = { :git => "https://github.com/apache/thrift.git", :tag => "v0.12.1" } s.source_files = 'lib/cocoa/src/**/*.{h,m,swift}' end diff --git a/appveyor.yml b/appveyor.yml index b126dc9edc0..2c3bd9b655e 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ # build Apache Thrift on AppVeyor - https://ci.appveyor.com -version: '0.12.0.{build}' +version: '0.12.1.{build}' shallow_clone: true diff --git a/bower.json b/bower.json index 5f407606ee0..c19b2a578ab 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.12.0", + "version": "0.12.1", "homepage": "https://git-wip-us.apache.org/repos/asf/thrift.git", "authors": [ "Apache Thrift " diff --git a/build/cmake/DefineCMakeDefaults.cmake b/build/cmake/DefineCMakeDefaults.cmake index dc2cc299ac5..d9f3d727858 100644 --- a/build/cmake/DefineCMakeDefaults.cmake +++ b/build/cmake/DefineCMakeDefaults.cmake @@ -35,7 +35,7 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON) set(CMAKE_COLOR_MAKEFILE ON) # Define the generic version of the libraries here -set(GENERIC_LIB_VERSION "0.12.0") +set(GENERIC_LIB_VERSION "0.12.1") set(GENERIC_LIB_SOVERSION "0") # Set the default build type to release with debug info diff --git a/configure.ac b/configure.ac index bcda1e07e4a..835ba7800f5 100755 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ(2.65) AC_CONFIG_MACRO_DIR([./aclocal]) -AC_INIT([thrift], [0.12.0]) +AC_INIT([thrift], [0.12.1]) AC_CONFIG_AUX_DIR([.]) diff --git a/contrib/Rebus/Properties/AssemblyInfo.cs b/contrib/Rebus/Properties/AssemblyInfo.cs index dde781324bd..4f265533ea0 100644 --- a/contrib/Rebus/Properties/AssemblyInfo.cs +++ b/contrib/Rebus/Properties/AssemblyInfo.cs @@ -34,5 +34,5 @@ [assembly: Guid("0af10984-40d3-453d-b1e5-421529e8c7e2")] -[assembly: AssemblyVersion("0.12.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] diff --git a/contrib/fb303/py/setup.py b/contrib/fb303/py/setup.py index 12d2d5c620b..8ad066c772f 100644 --- a/contrib/fb303/py/setup.py +++ b/contrib/fb303/py/setup.py @@ -26,7 +26,7 @@ from distutils.core import setup, Extension, Command setup(name='thrift_fb303', - version='0.12.0', + version='0.12.1', description='Python bindings for the Apache Thrift FB303', author=['Thrift Developers'], author_email=['dev@thrift.apache.org'], diff --git a/contrib/thrift-maven-plugin/pom.xml b/contrib/thrift-maven-plugin/pom.xml index e11fbbf0f3f..62c2ebedfd6 100644 --- a/contrib/thrift-maven-plugin/pom.xml +++ b/contrib/thrift-maven-plugin/pom.xml @@ -27,7 +27,7 @@ thrift-maven-plugin maven-plugin thrift-maven-plugin - 0.12.0 + 0.12.1 diff --git a/contrib/thrift.spec b/contrib/thrift.spec index 1fe0f9c5979..b777cb98528 100644 --- a/contrib/thrift.spec +++ b/contrib/thrift.spec @@ -28,7 +28,7 @@ Name: thrift License: Apache License v2.0 Group: Development Summary: RPC and serialization framework -Version: 0.12.0 +Version: 0.12.1 Release: 0 URL: http://thrift.apache.org Packager: Thrift Developers diff --git a/contrib/vagrant/centos-6.5/README.md b/contrib/vagrant/centos-6.5/README.md index 91ae67f2f57..6c24c524fbb 100644 --- a/contrib/vagrant/centos-6.5/README.md +++ b/contrib/vagrant/centos-6.5/README.md @@ -11,7 +11,7 @@ This will download and launch the base box VM under VirtualBox and run the Apach $ vagrant ssh [vagrant@thrift ~]$ cd /thrift [vagrant@thrift thrift]$ compiler/cpp/thrift --version - Thrift version 0.12.0 + Thrift version 0.12.1 The provisioning script (inside the Vagrantfile) runs ./bootstrap.sh, ./configure, make and make check, but does not install thrift. To install thrift run "make install". diff --git a/contrib/zeromq/csharp/ThriftZMQ.csproj b/contrib/zeromq/csharp/ThriftZMQ.csproj index 9143a6921d4..02a1188d4e9 100755 --- a/contrib/zeromq/csharp/ThriftZMQ.csproj +++ b/contrib/zeromq/csharp/ThriftZMQ.csproj @@ -25,7 +25,7 @@ false true 0 - 0.12.0 + 0.12.1 false false true diff --git a/debian/changelog b/debian/changelog index 5c8545fcb15..944e9353281 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +thrift (0.12.1) stable; urgency=low + + * update to 0.12.1 + + -- Jens Geyer Mon, 25 Feb 2019 22:42:00 +0100 + thrift (0.12.0) stable; urgency=low * update to 0.12.0 diff --git a/doap.rdf b/doap.rdf index cd4aeccee0f..12fb5f0a297 100755 --- a/doap.rdf +++ b/doap.rdf @@ -58,6 +58,11 @@ + + Apache Thrift + 2019-02-25 + 0.12.1 + Apache Thrift 2018-10-15 diff --git a/lib/as3/gradle.properties b/lib/as3/gradle.properties index 51179a12b77..d746018da28 100644 --- a/lib/as3/gradle.properties +++ b/lib/as3/gradle.properties @@ -1,7 +1,8 @@ # This file is shared currently between this Gradle build and the # Ant builds for fd303 and JavaScript. Keep the dotted notation for # the properties to minimize the changes in the dependencies. -thrift.version=0.12.1thrift.groupid=org.apache.thrift +thrift.version=0.12.1 +thrift.groupid=org.apache.thrift release=false sign=false diff --git a/lib/c_glib/README.md b/lib/c_glib/README.md index dd84f3d3506..0431e18b4d6 100644 --- a/lib/c_glib/README.md +++ b/lib/c_glib/README.md @@ -35,7 +35,7 @@ http://www.gtk.org/ Breaking Changes ================ -0.12.0 +0.12.x ------ The compiler's handling of namespaces when generating the name of types, diff --git a/lib/cocoa/src/Thrift.h b/lib/cocoa/src/Thrift.h index 502ba17596c..18488f9b9bc 100644 --- a/lib/cocoa/src/Thrift.h +++ b/lib/cocoa/src/Thrift.h @@ -17,4 +17,4 @@ * under the License. */ -#define ThriftVersion @"0.12.0" +#define ThriftVersion @"0.12.1" diff --git a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs index 19abcf7be13..043a6faaf4a 100644 --- a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs +++ b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs @@ -56,5 +56,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.12.0.*")] -[assembly: AssemblyFileVersion("0.12.0.*")] +[assembly: AssemblyVersion("0.12.1.*")] +[assembly: AssemblyFileVersion("0.12.1.*")] diff --git a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj index 68427c3def5..c2b631a8108 100644 --- a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj +++ b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj @@ -45,7 +45,7 @@ false true 0 - 0.12.0.%2a + 0.12.1.%2a false false true diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs index 23fbc73889e..3511b5f3f2b 100644 --- a/lib/csharp/src/Properties/AssemblyInfo.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.12.0.1")] -[assembly: AssemblyFileVersion("0.12.0.1")] +[assembly: AssemblyVersion("0.12.1.1")] +[assembly: AssemblyFileVersion("0.12.1.1")] diff --git a/lib/csharp/src/Thrift.csproj b/lib/csharp/src/Thrift.csproj index ede152d7841..d28f7dc9b2c 100644 --- a/lib/csharp/src/Thrift.csproj +++ b/lib/csharp/src/Thrift.csproj @@ -45,7 +45,7 @@ false true 0 - 0.12.0.%2a + 0.12.1.%2a false false true diff --git a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj index 4df1cbcf0c0..2e96f55e898 100644 --- a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj +++ b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj @@ -46,7 +46,7 @@ false true 0 - 0.12.0.%2a + 0.12.1.%2a false true diff --git a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs index 5ee34a1af1f..41ea3866ff5 100644 --- a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.12.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] diff --git a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj index 57ef76d4ebf..bd4e45ae688 100644 --- a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj +++ b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj @@ -46,7 +46,7 @@ false true 0 - 0.12.0.%2a + 0.12.1.%2a false true diff --git a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs index 65fb4ce4b53..1efbf127913 100644 --- a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.12.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] diff --git a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs b/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs index 186257d6984..02547666e86 100644 --- a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs @@ -49,5 +49,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.12.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] diff --git a/lib/d/src/thrift/base.d b/lib/d/src/thrift/base.d index 260e155b690..f15d2d24996 100644 --- a/lib/d/src/thrift/base.d +++ b/lib/d/src/thrift/base.d @@ -50,7 +50,7 @@ class TCompoundOperationException : TException { /// The Thrift version string, used for informative purposes. // Note: This is currently hardcoded, but will likely be filled in by the build // system in future versions. -enum VERSION = "0.12.0"; +enum VERSION = "0.12.1"; /** * Functions used for logging inside Thrift. diff --git a/lib/dart/pubspec.yaml b/lib/dart/pubspec.yaml index 365b2cdb810..4f205ebd47c 100644 --- a/lib/dart/pubspec.yaml +++ b/lib/dart/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: thrift -version: 0.12.0 +version: 0.12.1 description: > A Dart library for Apache Thrift author: Apache Thrift Developers diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index 8293d0778b1..dada330c699 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -27,7 +27,7 @@ interface Thrift.Protocol; const - Version = '0.12.0'; + Version = '0.12.1'; type TException = Thrift.Exception.TException; // compatibility alias diff --git a/lib/erl/src/thrift.app.src b/lib/erl/src/thrift.app.src index b02ab210fa6..ce49f61b9fc 100644 --- a/lib/erl/src/thrift.app.src +++ b/lib/erl/src/thrift.app.src @@ -22,7 +22,7 @@ {description, "Thrift bindings"}, % The version of the applicaton - {vsn, "0.12.0"}, + {vsn, "0.12.1"}, % All modules used by the application. {modules, [ diff --git a/lib/go/thrift/serializer_types_test.go b/lib/go/thrift/serializer_types_test.go index ef7cc3a16ad..cb9f8b019b7 100644 --- a/lib/go/thrift/serializer_types_test.go +++ b/lib/go/thrift/serializer_types_test.go @@ -19,7 +19,7 @@ package thrift -// Autogenerated by Thrift Compiler (0.12.0) +// Autogenerated by Thrift Compiler (0.12.1) // DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING /* THE FOLLOWING THRIFT FILE WAS USED TO CREATE THIS diff --git a/lib/haxe/README.md b/lib/haxe/README.md index 02e6919df79..29f88a81022 100644 --- a/lib/haxe/README.md +++ b/lib/haxe/README.md @@ -71,8 +71,8 @@ either from the official ASF repo, or via the github mirror. - To set up any **stable version**, choose the appropriate branch (e.g. `0.10.0`): - - `haxelib git thrift https://git.apache.org/thrift.git 0.12.0 lib/haxe` - - `haxelib git thrift https://github.com/apache/thrift.git 0.12.0 lib/haxe` + - `haxelib git thrift https://git.apache.org/thrift.git 0.12.1 lib/haxe` + - `haxelib git thrift https://github.com/apache/thrift.git 0.12.1 lib/haxe` - To set up the current **development version**, use the `master` branch: diff --git a/lib/haxe/haxelib.json b/lib/haxe/haxelib.json index 8d1bb11944b..df107f94eec 100644 --- a/lib/haxe/haxelib.json +++ b/lib/haxe/haxelib.json @@ -4,7 +4,7 @@ "license": "Apache", "tags": ["thrift", "rpc", "serialization", "cross", "framework"], "description": "Haxe bindings for the Apache Thrift RPC and serialization framework", - "version": "0.12.0", + "version": "0.12.1", "releasenote": "Licensed under Apache License, Version 2.0. The Apache Thrift compiler needs to be installed separately.", "contributors": ["Apache Software Foundation (ASF)"], "dependencies": { }, diff --git a/lib/hs/thrift.cabal b/lib/hs/thrift.cabal index b13cff4882f..cab9d1e31e1 100644 --- a/lib/hs/thrift.cabal +++ b/lib/hs/thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 0.12.0 +Version: 0.12.1 Cabal-Version: 1.24 License: Apache Category: Foreign diff --git a/lib/java/gradle.properties b/lib/java/gradle.properties index 7fef76de1d0..42c4010eacc 100644 --- a/lib/java/gradle.properties +++ b/lib/java/gradle.properties @@ -1,7 +1,7 @@ # This file is shared currently between this Gradle build and the # Ant builds for fd303 and JavaScript. Keep the dotted notation for # the properties to minimize the changes in the dependencies. -thrift.version=0.12.0 +thrift.version=0.12.1 thrift.groupid=org.apache.thrift release=false diff --git a/lib/js/package.json b/lib/js/package.json index 2ddd23861f4..429751d2ab5 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.12.0", + "version": "0.12.1", "devDependencies": { "grunt": "^1.0.2", "grunt-cli": "^1.2.0", diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 68b89248900..9c8ebff0a6d 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -46,7 +46,7 @@ var Thrift = { * @const {string} Version * @memberof Thrift */ - Version: '0.12.0', + Version: '0.12.1', /** * Thrift IDL type string to Id mapping. diff --git a/lib/lua/THttpTransport.lua b/lib/lua/THttpTransport.lua index 060a8ab5e09..df957cdcbd0 100644 --- a/lib/lua/THttpTransport.lua +++ b/lib/lua/THttpTransport.lua @@ -25,7 +25,7 @@ THttpTransport = TTransportBase:new{ wBuf = '', rBuf = '', CRLF = '\r\n', - VERSION = '0.12.0', + VERSION = '0.12.1', isServer = true } diff --git a/lib/lua/Thrift.lua b/lib/lua/Thrift.lua index d49572935c9..789a20c3efb 100644 --- a/lib/lua/Thrift.lua +++ b/lib/lua/Thrift.lua @@ -48,7 +48,7 @@ function ttable_size(t) return count end -version = '0.12.0' +version = '0.12.1' TType = { STOP = 0, diff --git a/lib/netcore/Thrift/Properties/AssemblyInfo.cs b/lib/netcore/Thrift/Properties/AssemblyInfo.cs index 68cd49cb100..11e66f948a9 100644 --- a/lib/netcore/Thrift/Properties/AssemblyInfo.cs +++ b/lib/netcore/Thrift/Properties/AssemblyInfo.cs @@ -52,5 +52,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.12.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] diff --git a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs index 60671414e9a..d24e537ee64 100644 --- a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs +++ b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs @@ -149,7 +149,7 @@ private HttpClient CreateClient() } httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); - httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "0.12.0")); + httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "0.12.1")); if (CustomHeaders != null) { diff --git a/lib/ocaml/_oasis b/lib/ocaml/_oasis index 315183f4df8..ed4a88b6b4e 100644 --- a/lib/ocaml/_oasis +++ b/lib/ocaml/_oasis @@ -1,5 +1,5 @@ Name: libthrift-ocaml -Version: 0.12.0 +Version: 0.12.1 OASISFormat: 0.3 Synopsis: OCaml bindings for the Apache Thrift RPC system Authors: Apache Thrift Developers diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm index 107b2a26218..71be7d5a168 100644 --- a/lib/perl/lib/Thrift.pm +++ b/lib/perl/lib/Thrift.pm @@ -31,6 +31,6 @@ use warnings; # package Thrift; -use version 0.77; our $VERSION = version->declare("v0.12.0_0"); +use version 0.77; our $VERSION = version->declare("v0.12.1"); 1; diff --git a/lib/php/README.md b/lib/php/README.md index 7170104dff4..f903c6e0801 100644 --- a/lib/php/README.md +++ b/lib/php/README.md @@ -53,7 +53,7 @@ apc_fetch(), apc_store() # Breaking Changes -## 0.12.0 +## 0.12.x 1. [PSR-4](https://www.php-fig.org/psr/psr-4/) loader is now the default. If you want to use class maps instead, use `-gen php:classmap`. diff --git a/lib/py/setup.py b/lib/py/setup.py index 6ee28df01d6..2043ab06057 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -90,7 +90,7 @@ def run_setup(with_binary): twisted_deps = ['twisted'] setup(name='thrift', - version='0.12.0', + version='0.12.1', description='Python bindings for the Apache Thrift RPC system', author='Thrift Developers', author_email='dev@thrift.apache.org', diff --git a/lib/rb/thrift.gemspec b/lib/rb/thrift.gemspec index 5a3a0ae1aaf..3dd38ecda9f 100644 --- a/lib/rb/thrift.gemspec +++ b/lib/rb/thrift.gemspec @@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__) Gem::Specification.new do |s| s.name = 'thrift' - s.version = '0.12.0' + s.version = '0.12.1' s.authors = ['Thrift Developers'] s.email = ['dev@thrift.apache.org'] s.homepage = 'http://thrift.apache.org' diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml index e79198dc665..44b35ebfa6e 100644 --- a/lib/rs/Cargo.toml +++ b/lib/rs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "thrift" description = "Rust bindings for the Apache Thrift RPC system" -version = "0.12.0" +version = "0.12.1" license = "Apache-2.0" authors = ["Apache Thrift Developers "] homepage = "http://thrift.apache.org" diff --git a/lib/rs/README.md b/lib/rs/README.md index 7c37a10bc6c..f611a918af6 100644 --- a/lib/rs/README.md +++ b/lib/rs/README.md @@ -46,7 +46,7 @@ It does not currently use any Rust 2018 features. Breaking changes are minimized. When they are made they will be outlined below with transition guidelines. -##### Thrift 0.12.0 +##### Thrift 0.12.x * **[THRIFT-4529]** - Rust enum variants are now camel-cased instead of uppercased to conform to Rust naming conventions diff --git a/lib/st/package.xml b/lib/st/package.xml index 7f6b2343de6..8ebbd6d8295 100644 --- a/lib/st/package.xml +++ b/lib/st/package.xml @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. --> - + libthrift-st thrift.st diff --git a/package-lock.json b/package-lock.json index 0342c15b2a0..a7e59e8b308 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.12.0", + "version": "0.12.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 722ae7dd17d..b7a4947d657 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://git-wip-us.apache.org/repos/asf/thrift.git" }, - "version": "0.12.0", + "version": "0.12.1", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", diff --git a/sonar-project.properties b/sonar-project.properties index ef11517cf5f..e8fcda834b9 100755 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -16,7 +16,7 @@ development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between all major languages. # Apache Thrift Version -sonar.projectVersion=0.12.0 +sonar.projectVersion=0.12.1 # use this to set another version string # $ sonar-runner -D sonar.projectVersion=`git rev-parse HEAD` # set projectDate in combination with projectVersion for imports of old releases @@ -54,7 +54,7 @@ module1.sonar.projectName=Apache Thrift - Java Library module1.sonar.projectBaseDir=lib/java module1.sonar.sources=src module1.sonar.tests=test -module1.sonar.binaries=build/libs/libthrift-0.12.0.jar +module1.sonar.binaries=build/libs/libthrift-0.12.1.jar module1.sonar.libraries=build/deps/*.jar module1.sonar.language=java @@ -62,7 +62,7 @@ module2.sonar.projectName=Apache Thrift - Java Tutorial module2.sonar.projectBaseDir=. module2.sonar.sources=tutorial/java/src, tutorial/java/gen-java module2.sonar.binaries=tutorial/java/tutorial.jar -module2.sonar.libraries=lib/java/build/deps/*.jar,lib/java/build/libs/libthrift-0.12.0.jar +module2.sonar.libraries=lib/java/build/deps/*.jar,lib/java/build/libs/libthrift-0.12.1.jar module2.sonar.language=java module3.sonar.projectName=Apache Thrift - JavaScript Library diff --git a/test/csharp/Properties/AssemblyInfo.cs b/test/csharp/Properties/AssemblyInfo.cs index d7e04b5d7c1..67a92434478 100644 --- a/test/csharp/Properties/AssemblyInfo.cs +++ b/test/csharp/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.12.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] diff --git a/test/csharp/ThriftTest.csproj b/test/csharp/ThriftTest.csproj index 363627fdfe2..2ee51e1ba3d 100644 --- a/test/csharp/ThriftTest.csproj +++ b/test/csharp/ThriftTest.csproj @@ -46,7 +46,7 @@ false true 0 - 0.12.0.%2a + 0.12.1.%2a false true diff --git a/test/dart/test_client/pubspec.yaml b/test/dart/test_client/pubspec.yaml index 63428b77982..9445722ccf5 100644 --- a/test/dart/test_client/pubspec.yaml +++ b/test/dart/test_client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: thrift_test_client -version: 0.12.0 +version: 0.12.1 description: A client integration test for the Dart Thrift library author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/test/erl/src/thrift_test.app.src b/test/erl/src/thrift_test.app.src index f166cc48a47..f8e550b40c1 100644 --- a/test/erl/src/thrift_test.app.src +++ b/test/erl/src/thrift_test.app.src @@ -22,7 +22,7 @@ {description, "Thrift cross language test"}, % The version of the applicaton - {vsn, "0.12.0"}, + {vsn, "0.12.1"}, % All modules used by the application. {modules, [ diff --git a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs index 2e7f736d76b..401374dac8a 100644 --- a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs +++ b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.12.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] diff --git a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs index 14067dd5d00..6067a02eb25 100644 --- a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs +++ b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.12.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] diff --git a/tutorial/dart/client/pubspec.yaml b/tutorial/dart/client/pubspec.yaml index 78ee5272224..5a0bcf8fbc1 100644 --- a/tutorial/dart/client/pubspec.yaml +++ b/tutorial/dart/client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_client -version: 0.12.0 +version: 0.12.1 description: A Dart client implementation of the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/tutorial/dart/console_client/pubspec.yaml b/tutorial/dart/console_client/pubspec.yaml index be7328efe11..710d4de3bbc 100644 --- a/tutorial/dart/console_client/pubspec.yaml +++ b/tutorial/dart/console_client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_console_client -version: 0.12.0 +version: 0.12.1 description: > A Dart console client to implementation of the Apache Thrift tutorial author: Apache Thrift Developers diff --git a/tutorial/dart/server/pubspec.yaml b/tutorial/dart/server/pubspec.yaml index 6c616b33afc..e9cb9382e4a 100644 --- a/tutorial/dart/server/pubspec.yaml +++ b/tutorial/dart/server/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_server -version: 0.12.0 +version: 0.12.1 description: A Dart server to support the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/tutorial/delphi/DelphiClient/DelphiClient.dproj b/tutorial/delphi/DelphiClient/DelphiClient.dproj index dd587811020..1d669ced197 100644 --- a/tutorial/delphi/DelphiClient/DelphiClient.dproj +++ b/tutorial/delphi/DelphiClient/DelphiClient.dproj @@ -97,7 +97,7 @@ Thrift Tutorial - 0.12.0.0 + 0.12.1.0 DelphiClient Copyright © 2012 The Apache Software Foundation diff --git a/tutorial/delphi/DelphiServer/DelphiServer.dproj b/tutorial/delphi/DelphiServer/DelphiServer.dproj index 3f9fc4dbafd..62aa8911584 100644 --- a/tutorial/delphi/DelphiServer/DelphiServer.dproj +++ b/tutorial/delphi/DelphiServer/DelphiServer.dproj @@ -96,7 +96,7 @@ Thrift Tutorial - 0.12.0.0 + 0.12.1.0 DelphiServer Copyright © 2012 The Apache Software Foundation diff --git a/tutorial/hs/ThriftTutorial.cabal b/tutorial/hs/ThriftTutorial.cabal index 64af3ecad04..40617a11817 100755 --- a/tutorial/hs/ThriftTutorial.cabal +++ b/tutorial/hs/ThriftTutorial.cabal @@ -18,7 +18,7 @@ -- Name: ThriftTutorial -Version: 0.12.0 +Version: 0.12.1 Cabal-Version: >= 1.4 License: OtherLicense Category: Foreign diff --git a/tutorial/ocaml/_oasis b/tutorial/ocaml/_oasis index a0ea6c526b2..9dbb6a03e2a 100644 --- a/tutorial/ocaml/_oasis +++ b/tutorial/ocaml/_oasis @@ -1,5 +1,5 @@ Name: tutorial -Version: 0.12.0 +Version: 0.12.1 OASISFormat: 0.3 Synopsis: OCaml Tutorial example Authors: Apache Thrift Developers From 17fa32f27556af3893beee9e1c364a4d997b3cbf Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 9 Mar 2019 09:19:54 -0500 Subject: [PATCH 244/756] fix java build issue --- lib/java/build.gradle | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/java/build.gradle b/lib/java/build.gradle index 5b0541b3bba..d03b27393a0 100644 --- a/lib/java/build.gradle +++ b/lib/java/build.gradle @@ -45,11 +45,10 @@ defaultTasks 'build' // Version components for this project group = property('thrift.groupid') -// Drop the -dev suffix, we use the SNAPSHOT suffix for non-release versions if (Boolean.parseBoolean(project.release)) { - version = parsedVersion + version = property('thrift.version') } else { - version = parsedVersion + '-SNAPSHOT' + version = property('thrift.version') + '-SNAPSHOT' } // Keeping the rest of the build logic in functional named scripts for clarity From a9b748bb0e02a2b6aaa3f39d09ec7f1fa47a0cf4 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 9 Mar 2019 10:25:29 -0500 Subject: [PATCH 245/756] Updated CHANGES --- CHANGES | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 86992614a86..db6841bc480 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,11 @@ Apache Thrift Changelog +Thrift 0.9.3.1 +-------------------------------------------------------------------------------- +## Bug + * [THRIFT-4506] - CVE-2018-1320 for Java SASL backported from 0.12.0 + + Thrift 0.9.3 -------------------------------------------------------------------------------- ## Bug @@ -249,7 +255,7 @@ Thrift 0.9.3 * [THRIFT-3176] - Union incorrectly implements == * [THRIFT-3177] - Fails to run rake test * [THRIFT-3180] - lua plugin: framed transport do not work - * [THRIFT-3179] - lua plugin cant connect to remote server because function l_socket_create_and_connect always bind socket to localhost + * [THRIFT-3179] - lua plugin cant connect to remote server because function l_socket_create_and_connect always bind socket to localhost * [THRIFT-3248] - TypeScript: additional comma in method signature without parameters * [THRIFT-3302] - Go JSON protocol should encode Thrift byte type as signed integer string * [THRIFT-3297] - c_glib: an abstract base class is not generated From dc1b301b311d8865eff2a49fad6343f7302fd9a9 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 9 Mar 2019 10:37:24 -0500 Subject: [PATCH 246/756] Fix svn commit command (publishing to apache dist) [ci skip] --- doc/ReleaseManagement.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ReleaseManagement.md b/doc/ReleaseManagement.md index 9cf02da8a0d..da944b8cb3c 100644 --- a/doc/ReleaseManagement.md +++ b/doc/ReleaseManagement.md @@ -208,7 +208,7 @@ All Apache Thrift releases go through a 72-hour final release candidate voting p ```bash ~/dist/dev/thrift$ svn status # verify everything is correct - ~/dist/dev/thrift$ svn add 1.0.0-rc0 -m "apache thrift 1.0.0-rc0 in dist dev" \ + ~/dist/dev/thrift$ svn commit -m "Apache Thrift 1.0.0-rc0 in dist dev" \ --username --password ``` @@ -293,7 +293,7 @@ All Apache Thrift releases go through a 72-hour final release candidate voting p ~/dist/release/thrift$ cp -p ../../dev/thrift/1.0.0-rc0/* 1.0.0/ ~/dist/release/thrift$ svn status # verify everything is correct - ~/dist/release/thrift$ svn add 1.0.0 -m "Apache Thrift 1.0.0 official release" \ + ~/dist/release/thrift$ svn commit -m "Apache Thrift 1.0.0 official release" \ --username --password ``` From 22c412e42d00d84c687725475f7f935953938e5f Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Tue, 12 Mar 2019 01:06:25 +0100 Subject: [PATCH 247/756] THRIFT-4817 Add string CTOR to TTlsSocketTransport Client: netstd Patch: Jens Geyer This closes #1753 --- .../Transport/Client/TTlsSocketTransport.cs | 30 +++++++++++++++++++ test/netstd/Client/TestClient.cs | 4 +-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs index 3bd9606d5cb..98fb982dc9f 100644 --- a/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs @@ -109,6 +109,36 @@ public TTlsSocketTransport(IPAddress host, int port, int timeout, InitSocket(); } + public TTlsSocketTransport(string host, int port, int timeout, + X509Certificate2 certificate, + RemoteCertificateValidationCallback certValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) + { + try + { + var entry = Dns.GetHostEntry(host); + if (entry.AddressList.Length == 0) + throw new TTransportException(TTransportException.ExceptionType.Unknown, "unable to resolve host name"); + + var addr = entry.AddressList[0]; + + _host = new IPAddress(addr.GetAddressBytes(), addr.ScopeId); ; + _port = port; + _timeout = timeout; + _certificate = certificate; + _certValidator = certValidator; + _localCertificateSelectionCallback = localCertificateSelectionCallback; + _sslProtocols = sslProtocols; + + InitSocket(); + } + catch (SocketException e) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, e.Message, e); + } + } + public int Timeout { set { _client.ReceiveTimeout = _client.SendTimeout = _timeout = value; } diff --git a/test/netstd/Client/TestClient.cs b/test/netstd/Client/TestClient.cs index f48084627f9..a85312b3d9b 100644 --- a/test/netstd/Client/TestClient.cs +++ b/test/netstd/Client/TestClient.cs @@ -63,7 +63,7 @@ public class TestClient private class TestParams { public int numIterations = 1; - public IPAddress host = IPAddress.Any; + public string host = "localhost"; public int port = 9090; public int numThreads = 1; public string url; @@ -92,7 +92,7 @@ internal void Parse( List args) else if (args[i].StartsWith("--host=")) { // check there for ipaddress - host = new IPAddress(Encoding.Unicode.GetBytes(args[i].Substring(args[i].IndexOf("=") + 1))); + host = args[i].Substring(args[i].IndexOf("=") + 1); if (transport != TransportChoice.TlsSocket) transport = TransportChoice.Socket; } From f26f4e1e6d7a56801ef676e503d9da93ad87f86a Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Wed, 13 Mar 2019 13:39:00 -0400 Subject: [PATCH 248/756] Add git gpg signing and public dev voting info [ci skip] --- doc/ReleaseManagement.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/ReleaseManagement.md b/doc/ReleaseManagement.md index da944b8cb3c..3889dd1c98d 100644 --- a/doc/ReleaseManagement.md +++ b/doc/ReleaseManagement.md @@ -267,6 +267,11 @@ All Apache Thrift releases go through a 72-hour final release candidate voting p 1. If any issues are brought up with the release candidate, you will need to package another and reset the voting clock. +Voting on the development mailing list provides additional benefits (wisdom from [Christopher Tubbs](https://issues.apache.org/jira/browse/THRIFT-4506?focusedCommentId=16791902&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-16791902)): +- It creates a public record for the vote, +- It allows for participation/evaluation from our wider user audience (more diversity in evaluators improves quality), and +- It provides more entry points for potential future committers/PMC members to earn merit through participation. + ### Official Release 1. Send a message to `dev@thrift.apache.org` with the voting results. Use this template as a guide: @@ -303,14 +308,18 @@ All Apache Thrift releases go through a 72-hour final release candidate voting p **NOTE:** All new releases must have the "v" prefix to satisfy third party package managers (dlang dub, golang, etc..) + **NOTE:** You **should** [sign the release tag](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work). Since you already have a GPG signing key for publishing the Apache Release, you want to [upload that key to your GitHub account](https://help.github.com/en/articles/adding-a-new-gpg-key-to-your-github-account). Once the key is known by GitHub you can sign the tag. + ```bash ~/thrift$ # make sure you are on the release branch ~/thrift$ git checkout release/1.0.0 ~/thrift$ git pull - ~/thrift$ git tag v1.0.0 + ~/thrift$ git tag -s v1.0.0 -m "Version 1.0.0" ~/thrift$ git push --tags ``` + **NOTE:** If you get the error "gpg failed to sign the data" when tagging, try this fix: "export GPG_TTY=$(tty)" + 1. Create a new release from the [GitHub Tags Page](https://github.com/apache/thrift/tags). Attach the statically built Windows thrift compiler as a binary here. 1. Merge the release branch into master. This ensures all changes made to fix up the release are in master. @@ -361,7 +370,7 @@ All Apache Thrift releases go through a 72-hour final release candidate voting p 1. **FIXME** Ask someone with admin access to Apache Jira to change the fixVersion in question from unreleased to released, for example: https://issues.apache.org/jira/browse/THRIFT-4686 -1. Ensure that the [Jira release page](https://issues.apache.org/jira/projects/THRIFT?selectedItem=com.atlassian.jira.jira-projects-plugin%3Arelease-page&status=unreleased) for the version has the same number of issues in the version as issues done, and that there are no issues in progress and no issues to do, and no warnings. +1. Ensure that the [Jira release page](https://issues.apache.org/jira/projects/THRIFT?selectedItem=com.atlassian.jira.jira-projects-plugin%3Arelease-page&status=unreleased) for the version has the same number of issues in the version as issues done, and that there are no issues in progress and no issues to do, and no warnings. Finally, mark it as released and set the date of the release. * [Report any CVEs](https://apache.org/security/committers.html) that were fixed. You can email `security@apache.org` if you are not sure if there are any CVEs to report. @@ -369,6 +378,8 @@ All Apache Thrift releases go through a 72-hour final release candidate voting p See https://thrift.apache.org/lib/ for the current status of each external package manager's distribution. Information below is from the 0.12.0 release: + > This section needs to be updated with detailed instructions for each language, or pointers to the README.md files in each language directory with detailed release instructions for the given package management system. + * [dart] Releasing this requires a google account. * You will need to install the same version of dart that is used in the docker image. * Go into lib/dart and run "pub publish --dry-run" and resolve any warnings. From 1b770f233f4470d61d0d133f8cb014a544bb255c Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Tue, 12 Mar 2019 01:19:43 +0100 Subject: [PATCH 249/756] THRIFT-4818 Test client should use cancellation token Client: netstd Patch: Jens Geyer This closes #1756 --- test/netstd/Client/TestClient.cs | 76 ++++++++++++++++---------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/test/netstd/Client/TestClient.cs b/test/netstd/Client/TestClient.cs index a85312b3d9b..c6b086fd586 100644 --- a/test/netstd/Client/TestClient.cs +++ b/test/netstd/Client/TestClient.cs @@ -314,8 +314,6 @@ public ClientTest(TestParams param) public void Execute() { - var token = CancellationToken.None; - if (done) { Console.WriteLine("Execute called more than once"); @@ -327,9 +325,7 @@ public void Execute() try { if (!transport.IsOpen) - { - transport.OpenAsync(token).GetAwaiter().GetResult(); - } + transport.OpenAsync(MakeTimeoutToken()).GetAwaiter().GetResult(); } catch (TTransportException ex) { @@ -471,17 +467,22 @@ public static byte[] PrepareTestData(bool randomDist) return retval; } + private static CancellationToken MakeTimeoutToken(int msec = 5000) + { + var token = new CancellationTokenSource(msec); + return token.Token; + } + public static async Task ExecuteClientTestAsync(ThriftTest.Client client) { - var token = CancellationToken.None; var returnCode = 0; Console.Write("testVoid()"); - await client.testVoidAsync(token); + await client.testVoidAsync(MakeTimeoutToken()); Console.WriteLine(" = void"); Console.Write("testString(\"Test\")"); - var s = await client.testStringAsync("Test", token); + var s = await client.testStringAsync("Test", MakeTimeoutToken()); Console.WriteLine(" = \"" + s + "\""); if ("Test" != s) { @@ -490,7 +491,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("testBool(true)"); - var t = await client.testBoolAsync((bool)true, token); + var t = await client.testBoolAsync((bool)true, MakeTimeoutToken()); Console.WriteLine(" = " + t); if (!t) { @@ -498,7 +499,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) returnCode |= ErrorBaseTypes; } Console.Write("testBool(false)"); - var f = await client.testBoolAsync((bool)false, token); + var f = await client.testBoolAsync((bool)false, MakeTimeoutToken()); Console.WriteLine(" = " + f); if (f) { @@ -507,7 +508,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("testByte(1)"); - var i8 = await client.testByteAsync((sbyte)1, token); + var i8 = await client.testByteAsync((sbyte)1, MakeTimeoutToken()); Console.WriteLine(" = " + i8); if (1 != i8) { @@ -516,7 +517,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("testI32(-1)"); - var i32 = await client.testI32Async(-1, token); + var i32 = await client.testI32Async(-1, MakeTimeoutToken()); Console.WriteLine(" = " + i32); if (-1 != i32) { @@ -525,7 +526,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("testI64(-34359738368)"); - var i64 = await client.testI64Async(-34359738368, token); + var i64 = await client.testI64Async(-34359738368, MakeTimeoutToken()); Console.WriteLine(" = " + i64); if (-34359738368 != i64) { @@ -535,7 +536,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) // TODO: Validate received message Console.Write("testDouble(5.325098235)"); - var dub = await client.testDoubleAsync(5.325098235, token); + var dub = await client.testDoubleAsync(5.325098235, MakeTimeoutToken()); Console.WriteLine(" = " + dub); if (5.325098235 != dub) { @@ -543,7 +544,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) returnCode |= ErrorBaseTypes; } Console.Write("testDouble(-0.000341012439638598279)"); - dub = await client.testDoubleAsync(-0.000341012439638598279, token); + dub = await client.testDoubleAsync(-0.000341012439638598279, MakeTimeoutToken()); Console.WriteLine(" = " + dub); if (-0.000341012439638598279 != dub) { @@ -555,7 +556,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) Console.Write("testBinary(" + BytesToHex(binOut) + ")"); try { - var binIn = await client.testBinaryAsync(binOut, token); + var binIn = await client.testBinaryAsync(binOut, MakeTimeoutToken()); Console.WriteLine(" = " + BytesToHex(binIn)); if (binIn.Length != binOut.Length) { @@ -601,7 +602,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) o.Byte_thing = (sbyte)1; o.I32_thing = -3; o.I64_thing = -5; - var i = await client.testStructAsync(o, token); + var i = await client.testStructAsync(o, MakeTimeoutToken()); Console.WriteLine(" = {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}"); // TODO: Validate received message @@ -610,7 +611,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) o2.Byte_thing = (sbyte)1; o2.Struct_thing = o; o2.I32_thing = 5; - var i2 = await client.testNestAsync(o2, token); + var i2 = await client.testNestAsync(o2, MakeTimeoutToken()); i = i2.Struct_thing; Console.WriteLine(" = {" + i2.Byte_thing + ", {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}, " + i2.I32_thing + "}"); @@ -635,7 +636,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("})"); - var mapin = await client.testMapAsync(mapout, token); + var mapin = await client.testMapAsync(mapout, MakeTimeoutToken()); Console.Write(" = {"); first = true; @@ -675,7 +676,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("})"); - var listin = await client.testListAsync(listout, token); + var listin = await client.testListAsync(listout, MakeTimeoutToken()); Console.Write(" = {"); first = true; @@ -716,7 +717,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("})"); - var setin = await client.testSetAsync(setout, token); + var setin = await client.testSetAsync(setout, MakeTimeoutToken()); Console.Write(" = {"); first = true; @@ -736,7 +737,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) Console.Write("testEnum(ONE)"); - var ret = await client.testEnumAsync(Numberz.ONE, token); + var ret = await client.testEnumAsync(Numberz.ONE, MakeTimeoutToken()); Console.WriteLine(" = " + ret); if (Numberz.ONE != ret) { @@ -745,7 +746,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("testEnum(TWO)"); - ret = await client.testEnumAsync(Numberz.TWO, token); + ret = await client.testEnumAsync(Numberz.TWO, MakeTimeoutToken()); Console.WriteLine(" = " + ret); if (Numberz.TWO != ret) { @@ -754,7 +755,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("testEnum(THREE)"); - ret = await client.testEnumAsync(Numberz.THREE, token); + ret = await client.testEnumAsync(Numberz.THREE, MakeTimeoutToken()); Console.WriteLine(" = " + ret); if (Numberz.THREE != ret) { @@ -763,7 +764,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("testEnum(FIVE)"); - ret = await client.testEnumAsync(Numberz.FIVE, token); + ret = await client.testEnumAsync(Numberz.FIVE, MakeTimeoutToken()); Console.WriteLine(" = " + ret); if (Numberz.FIVE != ret) { @@ -772,7 +773,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("testEnum(EIGHT)"); - ret = await client.testEnumAsync(Numberz.EIGHT, token); + ret = await client.testEnumAsync(Numberz.EIGHT, MakeTimeoutToken()); Console.WriteLine(" = " + ret); if (Numberz.EIGHT != ret) { @@ -781,7 +782,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) } Console.Write("testTypedef(309858235082523)"); - var uid = await client.testTypedefAsync(309858235082523L, token); + var uid = await client.testTypedefAsync(309858235082523L, MakeTimeoutToken()); Console.WriteLine(" = " + uid); if (309858235082523L != uid) { @@ -791,7 +792,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) // TODO: Validate received message Console.Write("testMapMap(1)"); - var mm = await client.testMapMapAsync(1, token); + var mm = await client.testMapMapAsync(1, MakeTimeoutToken()); Console.Write(" = {"); foreach (var key in mm.Keys) { @@ -817,7 +818,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) insane.Xtructs = new List(); insane.Xtructs.Add(truck); Console.Write("testInsanity()"); - var whoa = await client.testInsanityAsync(insane, token); + var whoa = await client.testInsanityAsync(insane, MakeTimeoutToken()); Console.Write(" = {"); foreach (var key in whoa.Keys) { @@ -880,14 +881,14 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) var arg4 = Numberz.FIVE; long arg5 = 5000000; Console.Write("Test Multi(" + arg0 + "," + arg1 + "," + arg2 + ",{" + string.Join(",", tmpMultiDict) + "}," + arg4 + "," + arg5 + ")"); - var multiResponse = await client.testMultiAsync(arg0, arg1, arg2, multiDict, arg4, arg5, token); + var multiResponse = await client.testMultiAsync(arg0, arg1, arg2, multiDict, arg4, arg5, MakeTimeoutToken()); Console.Write(" = Xtruct(byte_thing:" + multiResponse.Byte_thing + ",String_thing:" + multiResponse.String_thing + ",i32_thing:" + multiResponse.I32_thing + ",i64_thing:" + multiResponse.I64_thing + ")\n"); try { Console.WriteLine("testException(\"Xception\")"); - await client.testExceptionAsync("Xception", token); + await client.testExceptionAsync("Xception", MakeTimeoutToken()); Console.WriteLine("*** FAILED ***"); returnCode |= ErrorExceptions; } @@ -908,7 +909,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) try { Console.WriteLine("testException(\"TException\")"); - await client.testExceptionAsync("TException", token); + await client.testExceptionAsync("TException", MakeTimeoutToken()); Console.WriteLine("*** FAILED ***"); returnCode |= ErrorExceptions; } @@ -925,7 +926,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) try { Console.WriteLine("testException(\"ok\")"); - await client.testExceptionAsync("ok", token); + await client.testExceptionAsync("ok", MakeTimeoutToken()); // OK } catch (Exception ex) @@ -938,7 +939,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) try { Console.WriteLine("testMultiException(\"Xception\", ...)"); - await client.testMultiExceptionAsync("Xception", "ignore", token); + await client.testMultiExceptionAsync("Xception", "ignore", MakeTimeoutToken()); Console.WriteLine("*** FAILED ***"); returnCode |= ErrorExceptions; } @@ -959,7 +960,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) try { Console.WriteLine("testMultiException(\"Xception2\", ...)"); - await client.testMultiExceptionAsync("Xception2", "ignore", token); + await client.testMultiExceptionAsync("Xception2", "ignore", MakeTimeoutToken()); Console.WriteLine("*** FAILED ***"); returnCode |= ErrorExceptions; } @@ -980,7 +981,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) try { Console.WriteLine("testMultiException(\"success\", \"OK\")"); - if ("OK" != (await client.testMultiExceptionAsync("success", "OK", token)).String_thing) + if ("OK" != (await client.testMultiExceptionAsync("success", "OK", MakeTimeoutToken())).String_thing) { Console.WriteLine("*** FAILED ***"); returnCode |= ErrorExceptions; @@ -996,7 +997,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) var sw = new Stopwatch(); sw.Start(); Console.WriteLine("Test Oneway(1)"); - await client.testOnewayAsync(1, token); + await client.testOnewayAsync(1, MakeTimeoutToken()); sw.Stop(); if (sw.ElapsedMilliseconds > 1000) { @@ -1008,6 +1009,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) var times = 50; sw.Reset(); sw.Start(); + var token = MakeTimeoutToken(20000); for (var k = 0; k < times; ++k) await client.testVoidAsync(token); sw.Stop(); From cf51a843911e7d8fefe1018cfce3560a593cd808 Mon Sep 17 00:00:00 2001 From: Kyle Smith Date: Thu, 14 Mar 2019 06:59:49 -0400 Subject: [PATCH 250/756] THRIFT-4821 Normalized the constructors in TServerSocketTransport to allow parity between the TcpListerer and port options. Client: netstd Patch: Kyle Smith This closes #1758 --- .../Server/TServerSocketTransport.cs | 32 ++++--------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs index 710dedf00d1..bc06640ce5e 100644 --- a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs @@ -28,47 +28,27 @@ namespace Thrift.Transport.Server public class TServerSocketTransport : TServerTransport { private readonly int _clientTimeout; - private readonly int _port; private readonly bool _useBufferedSockets; private readonly bool _useFramedTransport; private TcpListener _server; - public TServerSocketTransport(TcpListener listener) - : this(listener, 0) - { - } - - public TServerSocketTransport(TcpListener listener, int clientTimeout) + public TServerSocketTransport(TcpListener listener, int clientTimeout = 0, bool useBufferedSockets = false, bool useFramedTransport = false) { _server = listener; _clientTimeout = clientTimeout; + _useBufferedSockets = useBufferedSockets; + _useFramedTransport = useFramedTransport; } - public TServerSocketTransport(int port) - : this(port, 0) - { - } - - public TServerSocketTransport(int port, int clientTimeout) - : this(port, clientTimeout, false) - { - } - - public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets): - this(port, clientTimeout, useBufferedSockets, false) - { - } - - public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets, bool useFramedTransport) + public TServerSocketTransport(int port, int clientTimeout = 0, bool useBufferedSockets = false, bool useFramedTransport = false) { - _port = port; _clientTimeout = clientTimeout; _useBufferedSockets = useBufferedSockets; _useFramedTransport = useFramedTransport; try { // Make server socket - _server = new TcpListener(IPAddress.Any, _port); + _server = new TcpListener(IPAddress.Any, port); _server.Server.NoDelay = true; } catch (Exception) @@ -171,4 +151,4 @@ public override void Close() } } } -} \ No newline at end of file +} From bf27637960aca6a6c3c5eb700a677e57b88b2409 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 14 Mar 2019 21:42:16 +0100 Subject: [PATCH 251/756] THRIFT-4822 Convert bool CTOR flags into enum type Client: netstd Patch: Jens Geyer This closes #1759 --- .../Server/TServerSocketTransport.cs | 32 +++++++------ .../Server/TTlsServerSocketTransport.cs | 45 ++++++++----------- .../Thrift/Transport/TFramedTransport.cs | 13 ++++-- test/netstd/Server/TestServer.cs | 32 +++++-------- tutorial/netstd/Server/Program.cs | 4 +- 5 files changed, 59 insertions(+), 67 deletions(-) diff --git a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs index bc06640ce5e..4f46f9915cd 100644 --- a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs @@ -16,6 +16,7 @@ // under the License. using System; +using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Threading; @@ -24,27 +25,25 @@ namespace Thrift.Transport.Server { + // ReSharper disable once InconsistentNaming public class TServerSocketTransport : TServerTransport { private readonly int _clientTimeout; - private readonly bool _useBufferedSockets; - private readonly bool _useFramedTransport; + private readonly Buffering _buffering; private TcpListener _server; - public TServerSocketTransport(TcpListener listener, int clientTimeout = 0, bool useBufferedSockets = false, bool useFramedTransport = false) + public TServerSocketTransport(TcpListener listener, int clientTimeout = 0, Buffering buffering = Buffering.None) { _server = listener; _clientTimeout = clientTimeout; - _useBufferedSockets = useBufferedSockets; - _useFramedTransport = useFramedTransport; + _buffering = buffering; } - public TServerSocketTransport(int port, int clientTimeout = 0, bool useBufferedSockets = false, bool useFramedTransport = false) + public TServerSocketTransport(int port, int clientTimeout = 0, Buffering buffering = Buffering.None) { _clientTimeout = clientTimeout; - _useBufferedSockets = useBufferedSockets; - _useFramedTransport = useFramedTransport; + _buffering = buffering; try { // Make server socket @@ -103,14 +102,19 @@ protected override async Task AcceptImplementationAsync(Cancellation Timeout = _clientTimeout }; - if (_useBufferedSockets) + switch (_buffering) { - tSocketTransport = new TBufferedTransport(tSocketTransport); - } + case Buffering.BufferedTransport: + tSocketTransport = new TBufferedTransport(tSocketTransport); + break; - if (_useFramedTransport) - { - tSocketTransport = new TFramedTransport(tSocketTransport); + case Buffering.FramedTransport: + tSocketTransport = new TFramedTransport(tSocketTransport); + break; + + default: + Debug.Assert(_buffering == Buffering.None); + break; } return tSocketTransport; diff --git a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs index 14d7ff25f36..2025b654989 100644 --- a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs @@ -16,6 +16,7 @@ // under the License. using System; +using System.Diagnostics; using System.Net; using System.Net.Security; using System.Net.Sockets; @@ -36,31 +37,17 @@ public class TTlsServerSocketTransport : TServerTransport private readonly int _port; private readonly X509Certificate2 _serverCertificate; private readonly SslProtocols _sslProtocols; - private readonly bool _useBufferedSockets; - private readonly bool _useFramedTransport; + private readonly Buffering _buffering; private TcpListener _server; public TTlsServerSocketTransport(int port, X509Certificate2 certificate) - : this(port, false, certificate) + : this(port, Buffering.None, certificate) { } public TTlsServerSocketTransport( int port, - bool useBufferedSockets, - X509Certificate2 certificate, - RemoteCertificateValidationCallback clientCertValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - SslProtocols sslProtocols = SslProtocols.Tls12) - : this(port, useBufferedSockets, false, certificate, - clientCertValidator, localCertificateSelectionCallback, sslProtocols) - { - } - - public TTlsServerSocketTransport( - int port, - bool useBufferedSockets, - bool useFramedTransport, + Buffering buffering, X509Certificate2 certificate, RemoteCertificateValidationCallback clientCertValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, @@ -74,8 +61,7 @@ public TTlsServerSocketTransport( _port = port; _serverCertificate = certificate; - _useBufferedSockets = useBufferedSockets; - _useFramedTransport = useFramedTransport; + _buffering = buffering; _clientCertValidator = clientCertValidator; _localCertificateSelectionCallback = localCertificateSelectionCallback; _sslProtocols = sslProtocols; @@ -138,15 +124,20 @@ protected override async Task AcceptImplementationAsync(Cancellation await tTlsSocket.SetupTlsAsync(); TTransport trans = tTlsSocket; - - if (_useBufferedSockets) - { - trans = new TBufferedTransport(trans); - } - if (_useFramedTransport) + switch(_buffering) { - trans = new TFramedTransport(trans); + case Buffering.BufferedTransport: + trans = new TBufferedTransport(trans); + break; + + case Buffering.FramedTransport: + trans = new TFramedTransport(trans); + break; + + default: + Debug.Assert(_buffering == Buffering.None); + break; } return trans; @@ -174,4 +165,4 @@ public override void Close() } } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Transport/TFramedTransport.cs b/lib/netstd/Thrift/Transport/TFramedTransport.cs index 59963f1e9f0..6d0802dac9a 100644 --- a/lib/netstd/Thrift/Transport/TFramedTransport.cs +++ b/lib/netstd/Thrift/Transport/TFramedTransport.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -22,7 +22,14 @@ namespace Thrift.Transport { - //TODO: check for correct implementation + // it does not make much sense to use buffered when we already use framed + public enum Buffering + { + None, + BufferedTransport, + FramedTransport + } + // ReSharper disable once InconsistentNaming public class TFramedTransport : TTransport @@ -206,4 +213,4 @@ protected override void Dispose(bool disposing) _isDisposed = true; } } -} \ No newline at end of file +} diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs index e25e6116d9c..8db92dc59f3 100644 --- a/test/netstd/Server/TestServer.cs +++ b/test/netstd/Server/TestServer.cs @@ -43,15 +43,6 @@ internal enum ProtocolChoice Json } - // it does not make much sense to use buffered when we already use framed - internal enum LayeredChoice - { - None, - Buffered, - Framed - } - - internal enum TransportChoice { Socket, @@ -61,7 +52,7 @@ internal enum TransportChoice internal class ServerParam { - internal LayeredChoice layered = LayeredChoice.None; + internal Buffering buffering = Buffering.None; internal ProtocolChoice protocol = ProtocolChoice.Binary; internal TransportChoice transport = TransportChoice.Socket; internal int port = 9090; @@ -84,11 +75,11 @@ internal void Parse(List args) } else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") { - layered = LayeredChoice.Buffered; + buffering = Buffering.BufferedTransport; } else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") { - layered = LayeredChoice.Framed; + buffering = Buffering.FramedTransport; } else if (args[i] == "--binary" || args[i] == "--protocol=binary") { @@ -552,8 +543,7 @@ public static int Execute(List args) // Transport TServerTransport trans; - var useBuffered = (param.layered == LayeredChoice.Buffered); - var useFramed = (param.layered == LayeredChoice.Framed); + switch (param.transport) { case TransportChoice.NamedPipe: @@ -570,7 +560,7 @@ public static int Execute(List args) } transFactory = new TTransportFactory(); // framed/buffered is built into socket transports - trans = new TTlsServerSocketTransport( param.port, useBuffered, useFramed, cert, + trans = new TTlsServerSocketTransport( param.port, param.buffering, cert, (sender, certificate, chain, errors) => true, null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); break; @@ -578,19 +568,19 @@ public static int Execute(List args) case TransportChoice.Socket: default: transFactory = new TTransportFactory(); // framed/buffered is built into socket transports - trans = new TServerSocketTransport(param.port, 0, useBuffered, useFramed); + trans = new TServerSocketTransport(param.port, 0, param.buffering); break; } // add layered transport, if not already set above if (transFactory == null) { - switch (param.layered) + switch (param.buffering) { - case LayeredChoice.Framed: + case Buffering.FramedTransport: transFactory = new TFramedTransport.Factory(); break; - case LayeredChoice.Buffered: + case Buffering.BufferedTransport: transFactory = new TBufferedTransport.Factory(); break; } @@ -627,8 +617,8 @@ public static int Execute(List args) var where = (! string.IsNullOrEmpty(param.pipe)) ? "on pipe " + param.pipe : "on port " + param.port; Console.WriteLine("Starting the AsyncBaseServer " + where + " with processor TPrototypeProcessorFactory prototype factory " + - (param.layered == LayeredChoice.Buffered ? " with buffered transport" : "") + - (param.layered == LayeredChoice.Framed ? " with framed transport" : "") + + (param.buffering == Buffering.BufferedTransport ? " with buffered transport" : "") + + (param.buffering == Buffering.FramedTransport ? " with framed transport" : "") + (param.transport == TransportChoice.TlsSocket ? " with encryption" : "") + (param.protocol == ProtocolChoice.Compact ? " with compact protocol" : "") + (param.protocol == ProtocolChoice.Json ? " with json protocol" : "") + diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs index 9a650c5aa74..1d9dd1584a0 100644 --- a/tutorial/netstd/Server/Program.cs +++ b/tutorial/netstd/Server/Program.cs @@ -143,13 +143,13 @@ private static async Task RunSelectedConfigurationAsync(Transport transport, Pro serverTransport = new TServerSocketTransport(9090); break; case Transport.TcpBuffered: - serverTransport = new TServerSocketTransport(port: 9090, clientTimeout: 10000, useBufferedSockets: true); + serverTransport = new TServerSocketTransport(port: 9090, clientTimeout: 10000, buffering: Buffering.BufferedTransport); break; case Transport.NamedPipe: serverTransport = new TNamedPipeServerTransport(".test"); break; case Transport.TcpTls: - serverTransport = new TTlsServerSocketTransport(9090, false, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback); + serverTransport = new TTlsServerSocketTransport(9090, Buffering.None, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback); break; case Transport.Framed: serverTransport = new TServerFramedTransport(9090); From 0c4e96f956cd7e3dc527ef215b14c0407148f46c Mon Sep 17 00:00:00 2001 From: soroshsabz Date: Fri, 15 Mar 2019 15:05:18 +0330 Subject: [PATCH 252/756] THRIFT-4811: Add CMake config file and targets. (see #4752) (#1748) * Add CMake config file and targets. (see #4752) * Exclude cygwin Co-Authored-By: soroshsabz --- CMakeLists.txt | 3 ++ build/cmake/DefineInstallationPaths.cmake | 3 +- build/cmake/GenerateConfigModule.cmake | 44 +++++++++++++++++++++++ build/cmake/ThriftConfig.cmake.in | 42 ++++++++++++++++++++++ build/cmake/ThriftMacros.cmake | 12 +++++-- 5 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 build/cmake/GenerateConfigModule.cmake create mode 100644 build/cmake/ThriftConfig.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index c77a6010cde..1880b790ba3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,9 @@ include(StaticCodeAnalysis) # Generate the config.h file include(ConfigureChecks) +# Generate the ThriftConfig.cmake module +include(GenerateConfigModule) + # Packaging include(CPackConfig) diff --git a/build/cmake/DefineInstallationPaths.cmake b/build/cmake/DefineInstallationPaths.cmake index d9a7174acc9..0c824cc7a1b 100644 --- a/build/cmake/DefineInstallationPaths.cmake +++ b/build/cmake/DefineInstallationPaths.cmake @@ -22,10 +22,11 @@ set(BIN_INSTALL_DIR "bin" CACHE PATH "The binary install dir (default: bin)") set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "The library install dir (default: lib${LIB_SUFFIX})") set(INCLUDE_INSTALL_DIR "include" CACHE PATH "The library install dir (default: include)") -set(CMAKE_INSTALL_DIR "cmake" CACHE PATH "The subdirectory to install cmake config files (default: cmake)") +set(CMAKE_INSTALL_DIR "lib/cmake" CACHE PATH "The subdirectory to install cmake config files (default: cmake)") set(PKGCONFIG_INSTALL_DIR "lib/pkgconfig" CACHE PATH "The subdirectory to install pkgconfig config files (default: lib/pkgconfig)") set(DOC_INSTALL_DIR "share/doc" CACHE PATH "The subdirectory to install documentation files (default: share/doc)") set(prefix "${CMAKE_INSTALL_PREFIX}") set(exec_prefix "${CMAKE_INSTALL_PREFIX}/bin") set(libdir "${CMAKE_INSTALL_PREFIX}/lib") set(includedir "${CMAKE_INSTALL_PREFIX}/include") +set(cmakedir "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DIR}") diff --git a/build/cmake/GenerateConfigModule.cmake b/build/cmake/GenerateConfigModule.cmake new file mode 100644 index 00000000000..9533c823593 --- /dev/null +++ b/build/cmake/GenerateConfigModule.cmake @@ -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. +# + +include(CMakePackageConfigHelpers) +set(PACKAGE_INCLUDE_INSTALL_DIR "${includedir}/thrift") +set(PACKAGE_CMAKE_INSTALL_DIR "${cmakedir}/thrift") +set(PACKAGE_BIN_INSTALL_DIR "${exec_prefix}") + +# In CYGWIN enviroment below commands does not work properly +if (NOT CYGWIN) + configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/build/cmake/ThriftConfig.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/ThriftConfig.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_DIR}/thrift" + PATH_VARS + PACKAGE_INCLUDE_INSTALL_DIR + PACKAGE_CMAKE_INSTALL_DIR + PACKAGE_BIN_INSTALL_DIR + ) + + write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/ThriftConfigVersion.cmake" + VERSION ${thrift_VERSION_MAJOR}.${thrift_VERSION_MINOR}.${thrift_VERSION_PATCH} + COMPATIBILITY SameMajorVersion + ) + + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ThriftConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/ThriftConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_DIR}/thrift") +endif() diff --git a/build/cmake/ThriftConfig.cmake.in b/build/cmake/ThriftConfig.cmake.in new file mode 100644 index 00000000000..c304da04dfa --- /dev/null +++ b/build/cmake/ThriftConfig.cmake.in @@ -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. +# + +set(THRIFT_VERSION ${thrift_VERSION}) + +@PACKAGE_INIT@ + +set_and_check(THRIFT_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") +set_and_check(THRIFT_CMAKE_DIR "@PACKAGE_CMAKE_INSTALL_DIR@") +set_and_check(THRIFT_BIN_DIR "@PACKAGE_BIN_INSTALL_DIR@") + +if (NOT TARGET thrift::thrift) + include("${THRIFT_CMAKE_DIR}/thriftTargets.cmake") +endif() + +set(THRIFT_LIBRARIES thrift::thrift) + +if ("${THRIFT_LIBRARIES}" STREQUAL "") + message(FATAL_ERROR "thrift libraries were not found") +endif() + +if (NOT Thrift_FIND_QUIETLY) + message(STATUS "Found thrift: ${PACKAGE_PREFIX_DIR}") +endif() + +check_required_components(Thrift) diff --git a/build/cmake/ThriftMacros.cmake b/build/cmake/ThriftMacros.cmake index 8f370df6c1d..d068b2ae63e 100644 --- a/build/cmake/ThriftMacros.cmake +++ b/build/cmake/ThriftMacros.cmake @@ -23,18 +23,26 @@ macro(ADD_PKGCONFIG_THRIFT name) DESTINATION "${PKGCONFIG_INSTALL_DIR}") endmacro(ADD_PKGCONFIG_THRIFT) - macro(ADD_LIBRARY_THRIFT name) add_library(${name} ${ARGN}) set_target_properties(${name} PROPERTIES OUTPUT_NAME ${name}${THRIFT_RUNTIME_POSTFIX} # windows link variants (/MT, /MD, /MTd, /MDd) get different names VERSION ${thrift_VERSION} ) # set_target_properties(${name} PROPERTIES PUBLIC_HEADER "${thriftcpp_HEADERS}") - install(TARGETS ${name} + install(TARGETS ${name} EXPORT "${name}Targets" RUNTIME DESTINATION "${BIN_INSTALL_DIR}" LIBRARY DESTINATION "${LIB_INSTALL_DIR}" ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" PUBLIC_HEADER DESTINATION "${INCLUDE_INSTALL_DIR}") + + export(EXPORT "${name}Targets" + FILE "${CMAKE_CURRENT_BINARY_DIR}/${name}/${name}Targets.cmake" + NAMESPACE "${name}::") + + install(EXPORT "${name}Targets" + FILE "${name}Targets.cmake" + NAMESPACE "${name}::" + DESTINATION "${CMAKE_INSTALL_DIR}/thrift") endmacro() macro(TARGET_INCLUDE_DIRECTORIES_THRIFT name) From b11f63c552b8ad47b23931177987ada0a92188cf Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 14 Mar 2019 21:12:38 +0100 Subject: [PATCH 253/756] THRIFT-4824 Logger deprecation warnings in tutorial Client: netstd Patch: Jens Geyer this closes #1760 --- .../Transport/Client/TTlsSocketTransport.cs | 6 ++--- test/netstd/Client/TestClient.cs | 2 +- tutorial/netstd/Client/Program.cs | 14 ++++++++++- tutorial/netstd/Server/Program.cs | 23 +++++++++++++++---- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs index 98fb982dc9f..9295bb01b43 100644 --- a/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -123,7 +123,7 @@ public TTlsSocketTransport(string host, int port, int timeout, var addr = entry.AddressList[0]; - _host = new IPAddress(addr.GetAddressBytes(), addr.ScopeId); ; + _host = new IPAddress(addr.GetAddressBytes(), addr.ScopeId); _port = port; _timeout = timeout; _certificate = certificate; @@ -264,4 +264,4 @@ public override void Close() } } } -} \ No newline at end of file +} diff --git a/test/netstd/Client/TestClient.cs b/test/netstd/Client/TestClient.cs index c6b086fd586..ddc36acc5a4 100644 --- a/test/netstd/Client/TestClient.cs +++ b/test/netstd/Client/TestClient.cs @@ -994,9 +994,9 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); } + Console.WriteLine("Test Oneway(1)"); var sw = new Stopwatch(); sw.Start(); - Console.WriteLine("Test Oneway(1)"); await client.testOnewayAsync(1, MakeTimeoutToken()); sw.Stop(); if (sw.ElapsedMilliseconds > 1000) diff --git a/tutorial/netstd/Client/Program.cs b/tutorial/netstd/Client/Program.cs index bf35746e323..4b68cee4aed 100644 --- a/tutorial/netstd/Client/Program.cs +++ b/tutorial/netstd/Client/Program.cs @@ -31,12 +31,14 @@ using Thrift.Transport.Client; using tutorial; using shared; +using Microsoft.Extensions.DependencyInjection; namespace Client { public class Program { - private static readonly ILogger Logger = new LoggerFactory().AddConsole().AddDebug().CreateLogger(nameof(Client)); + private static ServiceCollection ServiceCollection = new ServiceCollection(); + private static ILogger Logger; private static void DisplayHelp() { @@ -75,6 +77,9 @@ public static void Main(string[] args) { args = args ?? new string[0]; + ServiceCollection.AddLogging(logging => ConfigureLogging(logging)); + Logger = ServiceCollection.BuildServiceProvider().GetService().CreateLogger(nameof(Client)); + if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) { DisplayHelp(); @@ -89,6 +94,13 @@ public static void Main(string[] args) } } + private static void ConfigureLogging(ILoggingBuilder logging) + { + logging.SetMinimumLevel(LogLevel.Trace); + logging.AddConsole(); + logging.AddDebug(); + } + private static async Task RunAsync(string[] args, CancellationToken cancellationToken) { var numClients = GetNumberOfClients(args); diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs index 1d9dd1584a0..d27e90d24cd 100644 --- a/tutorial/netstd/Server/Program.cs +++ b/tutorial/netstd/Server/Program.cs @@ -41,12 +41,17 @@ namespace Server { public class Program { - private static readonly ILogger Logger = new LoggerFactory().AddConsole(LogLevel.Trace).AddDebug(LogLevel.Trace).CreateLogger(nameof(Server)); + private static ServiceCollection ServiceCollection = new ServiceCollection(); + private static ILogger Logger; public static void Main(string[] args) { args = args ?? new string[0]; + ServiceCollection.AddLogging(logging => ConfigureLogging(logging)); + Logger = ServiceCollection.BuildServiceProvider().GetService().CreateLogger(nameof(Server)); + + if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) { DisplayHelp(); @@ -66,6 +71,13 @@ public static void Main(string[] args) Logger.LogInformation("Server stopped"); } + private static void ConfigureLogging(ILoggingBuilder logging) + { + logging.SetMinimumLevel(LogLevel.Trace); + logging.AddConsole(); + logging.AddDebug(); + } + private static void DisplayHelp() { Logger.LogInformation(@" @@ -131,12 +143,10 @@ private static Transport GetTransport(string[] args) private static async Task RunSelectedConfigurationAsync(Transport transport, Protocol protocol, CancellationToken cancellationToken) { - var fabric = new LoggerFactory().AddConsole(LogLevel.Trace).AddDebug(LogLevel.Trace); var handler = new CalculatorAsyncHandler(); ITAsyncProcessor processor = null; TServerTransport serverTransport = null; - switch (transport) { case Transport.Tcp: @@ -209,6 +219,7 @@ private static async Task RunSelectedConfigurationAsync(Transport transport, Pro Logger.LogInformation( $"Selected TAsyncServer with {serverTransport} transport, {processor} processor and {inputProtocolFactory} protocol factories"); + var fabric = ServiceCollection.BuildServiceProvider().GetService(); var server = new TSimpleAsyncServer(processor, serverTransport, inputProtocolFactory, outputProtocolFactory, fabric); Logger.LogInformation("Starting the server..."); @@ -288,8 +299,11 @@ public void Run(CancellationToken cancellationToken) .UseUrls("http://localhost:9090") .UseContentRoot(Directory.GetCurrentDirectory()) .UseStartup() + .ConfigureLogging((ctx,logging) => ConfigureLogging(logging)) .Build(); + Logger.LogTrace("test"); + Logger.LogCritical("test"); host.RunAsync(cancellationToken).GetAwaiter().GetResult(); } @@ -315,8 +329,7 @@ public void ConfigureServices(IServiceCollection services) } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env, - ILoggerFactory loggerFactory) + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.UseMiddleware(); } From 6378ff69a624594dc4552076c9a24c5ae81b97a5 Mon Sep 17 00:00:00 2001 From: Kyle Smith Date: Fri, 15 Mar 2019 07:27:15 -0400 Subject: [PATCH 254/756] THRIFT-4825 Aligned the TTlsSocketServerTransport constructors with the TSocketServerTransport Client: C# Patch: Kyle Smith This closes #1762 --- .../Server/TTlsServerSocketTransport.cs | 29 ++++++++++++++----- test/netstd/Server/TestServer.cs | 2 +- tutorial/netstd/Server/Program.cs | 2 +- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs index 2025b654989..edfaced8824 100644 --- a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs @@ -34,21 +34,37 @@ public class TTlsServerSocketTransport : TServerTransport private readonly RemoteCertificateValidationCallback _clientCertValidator; private readonly int _clientTimeout = 0; private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; - private readonly int _port; private readonly X509Certificate2 _serverCertificate; private readonly SslProtocols _sslProtocols; private readonly Buffering _buffering; private TcpListener _server; - - public TTlsServerSocketTransport(int port, X509Certificate2 certificate) - : this(port, Buffering.None, certificate) + + public TTlsServerSocketTransport( + TcpListener listener, + X509Certificate2 certificate, + Buffering buffering = Buffering.None, + RemoteCertificateValidationCallback clientCertValidator = null, + LocalCertificateSelectionCallback localCertificateSelectionCallback = null, + SslProtocols sslProtocols = SslProtocols.Tls12) { + if (!certificate.HasPrivateKey) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, + "Your server-certificate needs to have a private key"); + } + + _serverCertificate = certificate; + _buffering = buffering; + _clientCertValidator = clientCertValidator; + _localCertificateSelectionCallback = localCertificateSelectionCallback; + _sslProtocols = sslProtocols; + _server = listener; } public TTlsServerSocketTransport( int port, - Buffering buffering, X509Certificate2 certificate, + Buffering buffering = Buffering.None, RemoteCertificateValidationCallback clientCertValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) @@ -59,7 +75,6 @@ public TTlsServerSocketTransport( "Your server-certificate needs to have a private key"); } - _port = port; _serverCertificate = certificate; _buffering = buffering; _clientCertValidator = clientCertValidator; @@ -69,7 +84,7 @@ public TTlsServerSocketTransport( try { // Create server socket - _server = new TcpListener(IPAddress.Any, _port); + _server = new TcpListener(IPAddress.Any, port); _server.Server.NoDelay = true; } catch (Exception) diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs index 8db92dc59f3..d15ca71c8a7 100644 --- a/test/netstd/Server/TestServer.cs +++ b/test/netstd/Server/TestServer.cs @@ -560,7 +560,7 @@ public static int Execute(List args) } transFactory = new TTransportFactory(); // framed/buffered is built into socket transports - trans = new TTlsServerSocketTransport( param.port, param.buffering, cert, + trans = new TTlsServerSocketTransport( param.port, cert, param.buffering, (sender, certificate, chain, errors) => true, null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); break; diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs index d27e90d24cd..e74a042173a 100644 --- a/tutorial/netstd/Server/Program.cs +++ b/tutorial/netstd/Server/Program.cs @@ -159,7 +159,7 @@ private static async Task RunSelectedConfigurationAsync(Transport transport, Pro serverTransport = new TNamedPipeServerTransport(".test"); break; case Transport.TcpTls: - serverTransport = new TTlsServerSocketTransport(9090, Buffering.None, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback); + serverTransport = new TTlsServerSocketTransport(9090, GetCertificate(), Buffering.None, ClientCertValidator, LocalCertificateSelectionCallback); break; case Transport.Framed: serverTransport = new TServerFramedTransport(9090); From 3b7798295b7aec5d65da9aff402d3292e25fe0ab Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 15 Mar 2019 15:59:27 -0400 Subject: [PATCH 255/756] fix xenial and bump go version on bionic --- build/docker/ubuntu-bionic/Dockerfile | 4 ++-- build/docker/ubuntu-xenial/Dockerfile | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index a0ed317519d..aae97475f98 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -151,9 +151,9 @@ RUN apt-get install -y --no-install-recommends \ libglib2.0-dev # golang -ENV GOLANG_VERSION 1.11.4 +ENV GOLANG_VERSION 1.12.1 ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz -ENV GOLANG_DOWNLOAD_SHA256 fb26c30e6a04ad937bbc657a1b5bba92f80096af1e8ee6da6430c045a8db3a5b +ENV GOLANG_DOWNLOAD_SHA256 2a3fdabf665496a0db5f41ec6af7a9b15a49fbe71a85a50ca38b1f13a103aeec RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index 5693a2c0a0c..e6069f81c55 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -16,7 +16,7 @@ # - d: does not come with Ubuntu so we're installing 2.075.1 for coverage # - dart: does not come with Ubuntu so we're installing 1.24.3 for coverage # - dotnet: does not come with Ubuntu -# - go: Xenial comes with 1.6, but we need 1.7 or later +# - go: Xenial comes with 1.6, but we need 1.10 or later # - nodejs: Xenial comes with 4.2.6 which exits LTS April 2018, so we're installing 6.x # - ocaml: causes stack overflow error, just started March 2018 not sure why # @@ -142,9 +142,9 @@ RUN apt-get install -y --no-install-recommends \ libglib2.0-dev # golang -ENV GOLANG_VERSION 1.7.6 +ENV GOLANG_VERSION 1.10.8 ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz -ENV GOLANG_DOWNLOAD_SHA256 ad5808bf42b014c22dd7646458f631385003049ded0bb6af2efc7f1f79fa29ea +ENV GOLANG_DOWNLOAD_SHA256 d8626fb6f9a3ab397d88c483b576be41fa81eefcec2fd18562c87626dbb3c39e RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ From 718ab46379b6b358f5b216b76e5031da04f0dcae Mon Sep 17 00:00:00 2001 From: Paco Date: Wed, 13 Mar 2019 02:05:30 +0000 Subject: [PATCH 256/756] [RS] Add clarification of where a constant comes from --- tutorial/rs/src/bin/tutorial_client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorial/rs/src/bin/tutorial_client.rs b/tutorial/rs/src/bin/tutorial_client.rs index c80fafc2f10..bfd81d4c397 100644 --- a/tutorial/rs/src/bin/tutorial_client.rs +++ b/tutorial/rs/src/bin/tutorial_client.rs @@ -75,7 +75,7 @@ fn run() -> thrift::Result<()> { println!("multiplied 7 and 8 and got {}", res); // let's get the log for it - let res = client.get_struct(32)?; + let res = client.get_struct(logid /* 32 */)?; println!("got log {:?} for operation {}", res, logid); // ok - let's be bad :( From 00dd9b6ff576c995136912d5964c0cbfbf7d369b Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 16 Mar 2019 19:14:27 +0100 Subject: [PATCH 257/756] added Github ZIP articats to release mail template [ci skip] --- doc/ReleaseManagement.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/ReleaseManagement.md b/doc/ReleaseManagement.md index 3889dd1c98d..ce0744b3a3b 100644 --- a/doc/ReleaseManagement.md +++ b/doc/ReleaseManagement.md @@ -252,6 +252,18 @@ All Apache Thrift releases go through a 72-hour final release candidate voting p sha1: sha256: + + The source tree as ZIP file to be published via Github releases: + https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.zip + + ZIP source tree GPG signature: + https://dist.apache.org/repos/dist/dev/thrift/1.0.0-rc0/thrift-1.0.0-rc0.zip.asc + + ZIP source tree checksums are: + md5: + sha1: + sha256: + The CHANGES list for this release is available at: https://github.com/apache/thrift/blob/release/1.0.0/CHANGES.md From 98c194103de11742b8785bdca49816265a84c32f Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 20 Mar 2019 21:53:13 +0100 Subject: [PATCH 258/756] THRIFT-4829 HTTP server transport lacks TransportFactory arguments Client: netstd Patch: Jens Geyer This closes #1766 --- .../Transport/Server/THttpServerTransport.cs | 35 +++++++++++++++---- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs index fab9fa7a5ec..953db70d2fb 100644 --- a/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs @@ -38,21 +38,34 @@ public class THttpServerTransport protected ITProtocolFactory InputProtocolFactory; protected ITProtocolFactory OutputProtocolFactory; + protected TTransportFactory InputTransportFactory; + protected TTransportFactory OutputTransportFactory; + protected ITAsyncProcessor Processor; public THttpServerTransport(ITAsyncProcessor processor, RequestDelegate next = null, ILoggerFactory loggerFactory = null) - : this(processor, new TBinaryProtocol.Factory(), next, loggerFactory) + : this(processor, new TBinaryProtocol.Factory(), null, next, loggerFactory) { } - public THttpServerTransport(ITAsyncProcessor processor, ITProtocolFactory protocolFactory, RequestDelegate next = null, + public THttpServerTransport( + ITAsyncProcessor processor, + ITProtocolFactory protocolFactory, + TTransportFactory transFactory = null, + RequestDelegate next = null, ILoggerFactory loggerFactory = null) - : this(processor, protocolFactory, protocolFactory, next, loggerFactory) + : this(processor, protocolFactory, protocolFactory, transFactory, transFactory, next, loggerFactory) { } - public THttpServerTransport(ITAsyncProcessor processor, ITProtocolFactory inputProtocolFactory, - ITProtocolFactory outputProtocolFactory, RequestDelegate next = null, ILoggerFactory loggerFactory = null) + public THttpServerTransport( + ITAsyncProcessor processor, + ITProtocolFactory inputProtocolFactory, + ITProtocolFactory outputProtocolFactory, + TTransportFactory inputTransFactory = null, + TTransportFactory outputTransFactory = null, + RequestDelegate next = null, + ILoggerFactory loggerFactory = null) { // loggerFactory == null is not illegal anymore @@ -60,6 +73,9 @@ public THttpServerTransport(ITAsyncProcessor processor, ITProtocolFactory inputP InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory)); OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory)); + InputTransportFactory = inputTransFactory; + OutputTransportFactory = outputTransFactory; + _next = next; _logger = (loggerFactory != null) ? loggerFactory.CreateLogger() : new NullLogger(); } @@ -76,8 +92,11 @@ public async Task ProcessRequestAsync(HttpContext context, CancellationToken can try { - var input = InputProtocolFactory.GetProtocol(transport); - var output = OutputProtocolFactory.GetProtocol(transport); + var intrans = (InputTransportFactory != null) ? InputTransportFactory.GetTransport(transport) : transport; + var outtrans = (OutputTransportFactory != null) ? OutputTransportFactory.GetTransport(transport) : transport; + + var input = InputProtocolFactory.GetProtocol(intrans); + var output = OutputProtocolFactory.GetProtocol(outtrans); while (await Processor.ProcessAsync(input, output, cancellationToken)) { @@ -86,6 +105,8 @@ public async Task ProcessRequestAsync(HttpContext context, CancellationToken can catch (TTransportException) { // Client died, just move on + if (!context.Response.HasStarted) + context.Response.StatusCode = 500; } finally { From 421444f2df2c27fcb1affdbd5bfac6cc972144fa Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 20 Mar 2019 22:13:25 +0100 Subject: [PATCH 259/756] THRIFT-4831 interface ITProtocolFactory should be class TProtocolFactory again Client: netstd Patch: Jens Geyer This closes #1767 --- lib/netstd/Thrift/Protocol/TBinaryProtocol.cs | 8 ++++---- lib/netstd/Thrift/Protocol/TCompactProtocol.cs | 8 ++++---- lib/netstd/Thrift/Protocol/TJSONProtocol.cs | 4 ++-- ...{ITProtocolFactory.cs => TProtocolFactory.cs} | 6 +++--- lib/netstd/Thrift/Server/TServer.cs | 6 +++--- lib/netstd/Thrift/Server/TSimpleAsyncServer.cs | 4 ++-- .../Thrift/Server/TThreadPoolAsyncServer.cs | 12 ++++++------ .../Transport/Server/THttpServerTransport.cs | 12 ++++++------ lib/netstd/Thrift/Transport/TTransportFactory.cs | 2 +- test/netstd/Server/TestServer.cs | 2 +- tutorial/netstd/Server/Program.cs | 16 ++++++---------- 11 files changed, 38 insertions(+), 42 deletions(-) rename lib/netstd/Thrift/Protocol/{ITProtocolFactory.cs => TProtocolFactory.cs} (89%) diff --git a/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs index 37bca8018b1..7a0243a95bd 100644 --- a/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -588,7 +588,7 @@ private async Task ReadStringBodyAsync(int size, CancellationToken cance return Encoding.UTF8.GetString(buf, 0, buf.Length); } - public class Factory : ITProtocolFactory + public class Factory : TProtocolFactory { protected bool StrictRead; protected bool StrictWrite; @@ -604,10 +604,10 @@ public Factory(bool strictRead, bool strictWrite) StrictWrite = strictWrite; } - public TProtocol GetProtocol(TTransport trans) + public override TProtocol GetProtocol(TTransport trans) { return new TBinaryProtocol(trans, StrictRead, StrictWrite); } } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs index 9ff640a2576..e6c5dbd5b89 100644 --- a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -891,9 +891,9 @@ private static void FixedLongToBytes(long n, byte[] buf, int off) buf[off + 7] = (byte) ((n >> 56) & 0xff); } - public class Factory : ITProtocolFactory + public class Factory : TProtocolFactory { - public TProtocol GetProtocol(TTransport trans) + public override TProtocol GetProtocol(TTransport trans) { return new TCompactProtocol(trans); } @@ -919,4 +919,4 @@ private static class Types public const byte Struct = 0x0C; } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs index fab13853ec4..8e40c481b25 100644 --- a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs @@ -785,9 +785,9 @@ public override async Task ReadBinaryAsync(CancellationToken cancellatio /// /// Factory for JSON protocol objects /// - public class Factory : ITProtocolFactory + public class Factory : TProtocolFactory { - public TProtocol GetProtocol(TTransport trans) + public override TProtocol GetProtocol(TTransport trans) { return new TJsonProtocol(trans); } diff --git a/lib/netstd/Thrift/Protocol/ITProtocolFactory.cs b/lib/netstd/Thrift/Protocol/TProtocolFactory.cs similarity index 89% rename from lib/netstd/Thrift/Protocol/ITProtocolFactory.cs rename to lib/netstd/Thrift/Protocol/TProtocolFactory.cs index 3abcbb0fde5..31b05148b32 100644 --- a/lib/netstd/Thrift/Protocol/ITProtocolFactory.cs +++ b/lib/netstd/Thrift/Protocol/TProtocolFactory.cs @@ -20,8 +20,8 @@ namespace Thrift.Protocol { // ReSharper disable once InconsistentNaming - public interface ITProtocolFactory + public abstract class TProtocolFactory { - TProtocol GetProtocol(TTransport trans); + public abstract TProtocol GetProtocol(TTransport trans); } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Server/TServer.cs b/lib/netstd/Thrift/Server/TServer.cs index b351913cef4..f40f2b7e7b9 100644 --- a/lib/netstd/Thrift/Server/TServer.cs +++ b/lib/netstd/Thrift/Server/TServer.cs @@ -29,10 +29,10 @@ namespace Thrift.Server public abstract class TServer { protected readonly ILogger Logger; - protected ITProtocolFactory InputProtocolFactory; + protected TProtocolFactory InputProtocolFactory; protected TTransportFactory InputTransportFactory; protected ITProcessorFactory ProcessorFactory; - protected ITProtocolFactory OutputProtocolFactory; + protected TProtocolFactory OutputProtocolFactory; protected TTransportFactory OutputTransportFactory; protected TServerEventHandler ServerEventHandler; @@ -40,7 +40,7 @@ public abstract class TServer protected TServer(ITProcessorFactory processorFactory, TServerTransport serverTransport, TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, - ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory, + TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, ILogger logger = null) { ProcessorFactory = processorFactory ?? throw new ArgumentNullException(nameof(processorFactory)); diff --git a/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs b/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs index a0a3e4c15f2..813d3f30ce4 100644 --- a/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs +++ b/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs @@ -34,7 +34,7 @@ public class TSimpleAsyncServer : TServer private volatile Task _serverTask; public TSimpleAsyncServer(ITAsyncProcessor processor, TServerTransport serverTransport, - ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory, + TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, ILoggerFactory loggerFactory, int clientWaitingDelay = 10) : this(new TSingletonProcessorFactory(processor), serverTransport, new TTransportFactory(), new TTransportFactory(), @@ -45,7 +45,7 @@ public TSimpleAsyncServer(ITAsyncProcessor processor, TServerTransport serverTra public TSimpleAsyncServer(ITProcessorFactory itProcessorFactory, TServerTransport serverTransport, TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, - ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory, + TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, ILogger logger, int clientWaitingDelay = 10) : base(itProcessorFactory, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory, logger) diff --git a/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs b/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs index e5c56607a36..1c76b681782 100644 --- a/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs +++ b/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs @@ -77,7 +77,7 @@ public TThreadPoolAsyncServer(ITAsyncProcessor processor, TServerTransport serve public TThreadPoolAsyncServer(ITAsyncProcessor processor, TServerTransport serverTransport, TTransportFactory transportFactory, - ITProtocolFactory protocolFactory) + TProtocolFactory protocolFactory) : this(new TSingletonProcessorFactory(processor), serverTransport, transportFactory, transportFactory, protocolFactory, protocolFactory, @@ -88,7 +88,7 @@ public TThreadPoolAsyncServer(ITAsyncProcessor processor, public TThreadPoolAsyncServer(ITProcessorFactory processorFactory, TServerTransport serverTransport, TTransportFactory transportFactory, - ITProtocolFactory protocolFactory) + TProtocolFactory protocolFactory) : this(processorFactory, serverTransport, transportFactory, transportFactory, protocolFactory, protocolFactory, @@ -100,8 +100,8 @@ public TThreadPoolAsyncServer(ITProcessorFactory processorFactory, TServerTransport serverTransport, TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, - ITProtocolFactory inputProtocolFactory, - ITProtocolFactory outputProtocolFactory, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, int minThreadPoolThreads, int maxThreadPoolThreads, ILogger logger= null) : this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory, @@ -114,8 +114,8 @@ public TThreadPoolAsyncServer(ITProcessorFactory processorFactory, TServerTransport serverTransport, TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, - ITProtocolFactory inputProtocolFactory, - ITProtocolFactory outputProtocolFactory, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, Configuration threadConfig, ILogger logger = null) : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, diff --git a/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs index 953db70d2fb..b5a500cf76f 100644 --- a/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs @@ -35,8 +35,8 @@ public class THttpServerTransport private readonly RequestDelegate _next; protected Encoding Encoding = Encoding.UTF8; - protected ITProtocolFactory InputProtocolFactory; - protected ITProtocolFactory OutputProtocolFactory; + protected TProtocolFactory InputProtocolFactory; + protected TProtocolFactory OutputProtocolFactory; protected TTransportFactory InputTransportFactory; protected TTransportFactory OutputTransportFactory; @@ -50,7 +50,7 @@ public THttpServerTransport(ITAsyncProcessor processor, RequestDelegate next = n public THttpServerTransport( ITAsyncProcessor processor, - ITProtocolFactory protocolFactory, + TProtocolFactory protocolFactory, TTransportFactory transFactory = null, RequestDelegate next = null, ILoggerFactory loggerFactory = null) @@ -60,8 +60,8 @@ public THttpServerTransport( public THttpServerTransport( ITAsyncProcessor processor, - ITProtocolFactory inputProtocolFactory, - ITProtocolFactory outputProtocolFactory, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, TTransportFactory inputTransFactory = null, TTransportFactory outputTransFactory = null, RequestDelegate next = null, @@ -114,4 +114,4 @@ public async Task ProcessRequestAsync(HttpContext context, CancellationToken can } } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Transport/TTransportFactory.cs b/lib/netstd/Thrift/Transport/TTransportFactory.cs index 69662f3f4d9..16e27ac8252 100644 --- a/lib/netstd/Thrift/Transport/TTransportFactory.cs +++ b/lib/netstd/Thrift/Transport/TTransportFactory.cs @@ -32,4 +32,4 @@ public virtual TTransport GetTransport(TTransport trans) return trans; } } -} \ No newline at end of file +} diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs index d15ca71c8a7..1aa8a77b757 100644 --- a/test/netstd/Server/TestServer.cs +++ b/test/netstd/Server/TestServer.cs @@ -587,7 +587,7 @@ public static int Execute(List args) } // Protocol - ITProtocolFactory proto; + TProtocolFactory proto; switch (param.protocol) { case ProtocolChoice.Compact: diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs index e74a042173a..c5e26d12d08 100644 --- a/tutorial/netstd/Server/Program.cs +++ b/tutorial/netstd/Server/Program.cs @@ -166,34 +166,30 @@ private static async Task RunSelectedConfigurationAsync(Transport transport, Pro break; } - ITProtocolFactory inputProtocolFactory; - ITProtocolFactory outputProtocolFactory; + TProtocolFactory inputProtocolFactory; + TProtocolFactory outputProtocolFactory; switch (protocol) { case Protocol.Binary: - { inputProtocolFactory = new TBinaryProtocol.Factory(); outputProtocolFactory = new TBinaryProtocol.Factory(); processor = new Calculator.AsyncProcessor(handler); - } break; + case Protocol.Compact: - { inputProtocolFactory = new TCompactProtocol.Factory(); outputProtocolFactory = new TCompactProtocol.Factory(); processor = new Calculator.AsyncProcessor(handler); - } break; + case Protocol.Json: - { inputProtocolFactory = new TJsonProtocol.Factory(); outputProtocolFactory = new TJsonProtocol.Factory(); processor = new Calculator.AsyncProcessor(handler); - } break; + case Protocol.Multiplexed: - { inputProtocolFactory = new TBinaryProtocol.Factory(); outputProtocolFactory = new TBinaryProtocol.Factory(); @@ -208,8 +204,8 @@ private static async Task RunSelectedConfigurationAsync(Transport transport, Pro multiplexedProcessor.RegisterProcessor(nameof(SharedService), sharedServiceProcessor); processor = multiplexedProcessor; - } break; + default: throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null); } From 73a0272d66b07bb6d64fc8fafd8faca9df8d0e32 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 20 Mar 2019 22:46:36 +0100 Subject: [PATCH 260/756] THRIFT-4832 superfluous backing field causes CS0169 "field never used" Client: netstd Patch: Jens Geyer This closes #1768 --- compiler/cpp/src/thrift/generate/t_netstd_generator.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index 47a1dd1309a..b76a34da7f4 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -918,7 +918,11 @@ void t_netstd_generator::generate_netstd_wcffault(ostream& out, t_struct* tstruc // make private members with public Properties for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - out << indent() << "private " << declare_field(*m_iter, false, "_") << endl; + // if the field is required, then we use auto-properties + if (!field_is_required((*m_iter))) + { + out << indent() << "private " << declare_field(*m_iter, false, "_") << endl; + } } out << endl; From ddec431b4a402258c3b56b873908c98a15f22de4 Mon Sep 17 00:00:00 2001 From: Danny Browning Date: Fri, 8 Mar 2019 14:20:41 -0700 Subject: [PATCH 261/756] TryFrom stable TryFrom is now stable, so use that. Additionally re-export OrderedFloat since it is used by the generated code. Relax dependencies to reduce downstream conflicts. --- compiler/cpp/src/thrift/generate/t_rs_generator.cc | 11 ++++------- lib/rs/Cargo.toml | 11 +++++------ lib/rs/src/errors.rs | 14 +++++++------- lib/rs/src/lib.rs | 5 ++++- lib/rs/src/protocol/binary.rs | 3 +-- lib/rs/src/protocol/compact.rs | 3 +-- lib/rs/src/protocol/mod.rs | 7 +++---- lib/rs/test/src/lib.rs | 2 -- 8 files changed, 25 insertions(+), 31 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_rs_generator.cc b/compiler/cpp/src/thrift/generate/t_rs_generator.cc index fdf6861635c..f6b4b6dca40 100644 --- a/compiler/cpp/src/thrift/generate/t_rs_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_rs_generator.cc @@ -550,20 +550,17 @@ void t_rs_generator::render_attributes_and_includes() { f_gen_ << endl; // add standard includes - f_gen_ << "extern crate ordered_float;" << endl; f_gen_ << "extern crate thrift;" << endl; - f_gen_ << "extern crate try_from;" << endl; f_gen_ << endl; - f_gen_ << "use ordered_float::OrderedFloat;" << endl; + f_gen_ << "use thrift::OrderedFloat;" << endl; f_gen_ << "use std::cell::RefCell;" << endl; f_gen_ << "use std::collections::{BTreeMap, BTreeSet};" << endl; - f_gen_ << "use std::convert::From;" << endl; + f_gen_ << "use std::convert::{From, TryFrom};" << endl; f_gen_ << "use std::default::Default;" << endl; f_gen_ << "use std::error::Error;" << endl; f_gen_ << "use std::fmt;" << endl; f_gen_ << "use std::fmt::{Display, Formatter};" << endl; f_gen_ << "use std::rc::Rc;" << endl; - f_gen_ << "use try_from::TryFrom;" << endl; f_gen_ << endl; f_gen_ << "use thrift::{ApplicationError, ApplicationErrorKind, ProtocolError, ProtocolErrorKind, TThriftClient};" << endl; f_gen_ << "use thrift::protocol::{TFieldIdentifier, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType, TInputProtocol, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType};" << endl; @@ -932,9 +929,9 @@ void t_rs_generator::render_enum_conversion(t_enum* tenum, const string& enum_na f_gen_ << "impl TryFrom for " << enum_name << " {" << endl; indent_up(); - f_gen_ << indent() << "type Err = thrift::Error;"; + f_gen_ << indent() << "type Error = thrift::Error;"; - f_gen_ << indent() << "fn try_from(i: i32) -> Result {" << endl; + f_gen_ << indent() << "fn try_from(i: i32) -> Result {" << endl; indent_up(); f_gen_ << indent() << "match i {" << endl; diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml index 3a25b16d4b0..bad2a3872f8 100644 --- a/lib/rs/Cargo.toml +++ b/lib/rs/Cargo.toml @@ -11,9 +11,8 @@ exclude = ["Makefile*", "test/**", "*.iml"] keywords = ["thrift"] [dependencies] -byteorder = "~1.2.1" -integer-encoding = "~1.0.4" -log = "~0.3.8" -threadpool = "~1.7.1" -try_from = "~0.2.2" - +ordered-float = "0.5" +byteorder = "1" +integer-encoding = "1" +log = "0.4" +threadpool = "1.7" diff --git a/lib/rs/src/errors.rs b/lib/rs/src/errors.rs index 16a25766a19..6fb1aee565f 100644 --- a/lib/rs/src/errors.rs +++ b/lib/rs/src/errors.rs @@ -19,7 +19,7 @@ use std::convert::{From, Into}; use std::error::Error as StdError; use std::fmt::{Debug, Display, Formatter}; use std::{error, fmt, io, string}; -use try_from::TryFrom; +use std::convert::TryFrom; use protocol::{TFieldIdentifier, TInputProtocol, TOutputProtocol, TStructIdentifier, TType}; @@ -413,8 +413,8 @@ impl Display for TransportError { } impl TryFrom for TransportErrorKind { - type Err = Error; - fn try_from(from: i32) -> Result { + type Error = Error; + fn try_from(from: i32) -> Result { match from { 0 => Ok(TransportErrorKind::Unknown), 1 => Ok(TransportErrorKind::NotOpen), @@ -543,8 +543,8 @@ impl Display for ProtocolError { } impl TryFrom for ProtocolErrorKind { - type Err = Error; - fn try_from(from: i32) -> Result { + type Error = Error; + fn try_from(from: i32) -> Result { match from { 0 => Ok(ProtocolErrorKind::Unknown), 1 => Ok(ProtocolErrorKind::InvalidData), @@ -647,8 +647,8 @@ impl Display for ApplicationError { } impl TryFrom for ApplicationErrorKind { - type Err = Error; - fn try_from(from: i32) -> Result { + type Error = Error; + fn try_from(from: i32) -> Result { match from { 0 => Ok(ApplicationErrorKind::Unknown), 1 => Ok(ApplicationErrorKind::UnknownMethod), diff --git a/lib/rs/src/lib.rs b/lib/rs/src/lib.rs index ca5c7d649dc..a36ec99c44a 100644 --- a/lib/rs/src/lib.rs +++ b/lib/rs/src/lib.rs @@ -49,9 +49,9 @@ #![doc(test(attr(allow(unused_variables), deny(warnings))))] extern crate byteorder; +extern crate ordered_float; extern crate integer_encoding; extern crate threadpool; -extern crate try_from; #[macro_use] extern crate log; @@ -85,3 +85,6 @@ pub use autogen::*; /// As is convention this is a typedef of `std::result::Result` /// with `E` defined as the `thrift::Error` type. pub type Result = std::result::Result; + +// Re-export ordered-float, since it is used by the generator +pub use ordered_float::OrderedFloat as OrderedFloat; \ No newline at end of file diff --git a/lib/rs/src/protocol/binary.rs b/lib/rs/src/protocol/binary.rs index 19aff3d6cf1..0920fc4e183 100644 --- a/lib/rs/src/protocol/binary.rs +++ b/lib/rs/src/protocol/binary.rs @@ -16,8 +16,7 @@ // under the License. use byteorder::{BigEndian, ByteOrder, ReadBytesExt, WriteBytesExt}; -use std::convert::From; -use try_from::TryFrom; +use std::convert::{From, TryFrom}; use super::{ TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier, diff --git a/lib/rs/src/protocol/compact.rs b/lib/rs/src/protocol/compact.rs index df5edaa8278..334e8201b9a 100644 --- a/lib/rs/src/protocol/compact.rs +++ b/lib/rs/src/protocol/compact.rs @@ -17,9 +17,8 @@ use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use integer_encoding::{VarIntReader, VarIntWriter}; -use std::convert::From; +use std::convert::{From, TryFrom}; use std::io; -use try_from::TryFrom; use super::{ TFieldIdentifier, TInputProtocol, TInputProtocolFactory, TListIdentifier, TMapIdentifier, diff --git a/lib/rs/src/protocol/mod.rs b/lib/rs/src/protocol/mod.rs index 11c0289f954..1ab16585e26 100644 --- a/lib/rs/src/protocol/mod.rs +++ b/lib/rs/src/protocol/mod.rs @@ -57,10 +57,9 @@ //! protocol.write_field_end().unwrap(); //! ``` -use std::convert::From; +use std::convert::{From, TryFrom}; use std::fmt; use std::fmt::{Display, Formatter}; -use try_from::TryFrom; use transport::{TReadTransport, TWriteTransport}; use {ProtocolError, ProtocolErrorKind}; @@ -770,8 +769,8 @@ impl From for u8 { } impl TryFrom for TMessageType { - type Err = ::Error; - fn try_from(b: u8) -> ::Result { + type Error = ::Error; + fn try_from(b: u8) -> Result { match b { 0x01 => Ok(TMessageType::Call), 0x02 => Ok(TMessageType::Reply), diff --git a/lib/rs/test/src/lib.rs b/lib/rs/test/src/lib.rs index e5e176e14b8..9debdca5477 100644 --- a/lib/rs/test/src/lib.rs +++ b/lib/rs/test/src/lib.rs @@ -15,9 +15,7 @@ // specific language governing permissions and limitations // under the License. -extern crate ordered_float; extern crate thrift; -extern crate try_from; pub mod base_one; pub mod base_two; From 7b94dd422117ffb6c646d1217c643efb80a8cf45 Mon Sep 17 00:00:00 2001 From: Kyle Smith Date: Sat, 23 Mar 2019 17:26:56 +0100 Subject: [PATCH 262/756] THRIFT-4839: Remove embedded buffering/framed options from TCP transports Client: netstd Patch: Kyle Smith + minor changes by Jens Geyer This closes #1770 --- .../Thrift/Server/TSimpleAsyncServer.cs | 62 ++++++++++---- .../Thrift/Server/TThreadPoolAsyncServer.cs | 2 +- lib/netstd/Thrift/Thrift.csproj | 1 - .../Server/TNamedPipeServerTransport.cs | 2 - .../Server/TServerSocketTransport.cs | 25 +----- .../Server/TTlsServerSocketTransport.cs | 37 +-------- .../Thrift/Transport/TFramedTransport.cs | 9 --- test/netstd/Server/TestServer.cs | 54 +++++++------ tutorial/netstd/Client/Client.csproj | 4 + tutorial/netstd/Client/Program.cs | 72 +++++++++++++---- tutorial/netstd/Server/Program.cs | 81 ++++++++++++++----- 11 files changed, 205 insertions(+), 144 deletions(-) diff --git a/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs b/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs index 813d3f30ce4..bdaa3489c98 100644 --- a/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs +++ b/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs @@ -33,24 +33,58 @@ public class TSimpleAsyncServer : TServer private readonly int _clientWaitingDelay; private volatile Task _serverTask; - public TSimpleAsyncServer(ITAsyncProcessor processor, TServerTransport serverTransport, - TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, - ILoggerFactory loggerFactory, int clientWaitingDelay = 10) - : this(new TSingletonProcessorFactory(processor), serverTransport, - new TTransportFactory(), new TTransportFactory(), - inputProtocolFactory, outputProtocolFactory, - loggerFactory.CreateLogger(nameof(TSimpleAsyncServer)), clientWaitingDelay) + public TSimpleAsyncServer(ITProcessorFactory itProcessorFactory, + TServerTransport serverTransport, + TTransportFactory inputTransportFactory, + TTransportFactory outputTransportFactory, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, + ILogger logger, + int clientWaitingDelay = 10) + : base(itProcessorFactory, + serverTransport, + inputTransportFactory, + outputTransportFactory, + inputProtocolFactory, + outputProtocolFactory, + logger) { + _clientWaitingDelay = clientWaitingDelay; } - public TSimpleAsyncServer(ITProcessorFactory itProcessorFactory, TServerTransport serverTransport, - TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, - TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, - ILogger logger, int clientWaitingDelay = 10) - : base(itProcessorFactory, serverTransport, inputTransportFactory, outputTransportFactory, - inputProtocolFactory, outputProtocolFactory, logger) + public TSimpleAsyncServer(ITProcessorFactory itProcessorFactory, + TServerTransport serverTransport, + TTransportFactory inputTransportFactory, + TTransportFactory outputTransportFactory, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, + ILoggerFactory loggerFactory, + int clientWaitingDelay = 10) + : this(itProcessorFactory, + serverTransport, + inputTransportFactory, + outputTransportFactory, + inputProtocolFactory, + outputProtocolFactory, + loggerFactory.CreateLogger()) + { + } + + public TSimpleAsyncServer(ITAsyncProcessor processor, + TServerTransport serverTransport, + TProtocolFactory inputProtocolFactory, + TProtocolFactory outputProtocolFactory, + ILoggerFactory loggerFactory, + int clientWaitingDelay = 10) + : this(new TSingletonProcessorFactory(processor), + serverTransport, + null, // defaults to TTransportFactory() + null, // defaults to TTransportFactory() + inputProtocolFactory, + outputProtocolFactory, + loggerFactory.CreateLogger(nameof(TSimpleAsyncServer)), + clientWaitingDelay) { - _clientWaitingDelay = clientWaitingDelay; } public override async Task ServeAsync(CancellationToken cancellationToken) diff --git a/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs b/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs index 1c76b681782..20e659d3aa2 100644 --- a/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs +++ b/lib/netstd/Thrift/Server/TThreadPoolAsyncServer.cs @@ -68,7 +68,7 @@ public Configuration(int minWork, int maxWork, int minIO, int maxIO) public TThreadPoolAsyncServer(ITAsyncProcessor processor, TServerTransport serverTransport, ILogger logger = null) : this(new TSingletonProcessorFactory(processor), serverTransport, - new TTransportFactory(), new TTransportFactory(), + null, null, // defaults to TTransportFactory() new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), new Configuration(), logger) { diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj index 86de1f8bacf..d09380342c4 100644 --- a/lib/netstd/Thrift/Thrift.csproj +++ b/lib/netstd/Thrift/Thrift.csproj @@ -39,7 +39,6 @@ - diff --git a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs index cd5683b46c2..8147d67927b 100644 --- a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs @@ -34,10 +34,8 @@ public class TNamedPipeServerTransport : TServerTransport /// This is the address of the Pipe on the localhost. /// private readonly string _pipeAddress; - private bool _asyncMode = true; private volatile bool _isPending = true; - private NamedPipeServerStream _stream = null; public TNamedPipeServerTransport(string pipeAddress) diff --git a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs index 4f46f9915cd..0f90841d23f 100644 --- a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs @@ -16,7 +16,6 @@ // under the License. using System; -using System.Diagnostics; using System.Net; using System.Net.Sockets; using System.Threading; @@ -30,20 +29,17 @@ namespace Thrift.Transport.Server public class TServerSocketTransport : TServerTransport { private readonly int _clientTimeout; - private readonly Buffering _buffering; private TcpListener _server; - public TServerSocketTransport(TcpListener listener, int clientTimeout = 0, Buffering buffering = Buffering.None) + public TServerSocketTransport(TcpListener listener, int clientTimeout = 0) { _server = listener; _clientTimeout = clientTimeout; - _buffering = buffering; } - public TServerSocketTransport(int port, int clientTimeout = 0, Buffering buffering = Buffering.None) + public TServerSocketTransport(int port, int clientTimeout = 0) + : this(null, clientTimeout) { - _clientTimeout = clientTimeout; - _buffering = buffering; try { // Make server socket @@ -102,21 +98,6 @@ protected override async Task AcceptImplementationAsync(Cancellation Timeout = _clientTimeout }; - switch (_buffering) - { - case Buffering.BufferedTransport: - tSocketTransport = new TBufferedTransport(tSocketTransport); - break; - - case Buffering.FramedTransport: - tSocketTransport = new TFramedTransport(tSocketTransport); - break; - - default: - Debug.Assert(_buffering == Buffering.None); - break; - } - return tSocketTransport; } catch (Exception) diff --git a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs index edfaced8824..5070919fcd4 100644 --- a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs @@ -16,7 +16,6 @@ // under the License. using System; -using System.Diagnostics; using System.Net; using System.Net.Security; using System.Net.Sockets; @@ -36,13 +35,11 @@ public class TTlsServerSocketTransport : TServerTransport private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; private readonly X509Certificate2 _serverCertificate; private readonly SslProtocols _sslProtocols; - private readonly Buffering _buffering; private TcpListener _server; public TTlsServerSocketTransport( TcpListener listener, X509Certificate2 certificate, - Buffering buffering = Buffering.None, RemoteCertificateValidationCallback clientCertValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) @@ -54,7 +51,6 @@ public TTlsServerSocketTransport( } _serverCertificate = certificate; - _buffering = buffering; _clientCertValidator = clientCertValidator; _localCertificateSelectionCallback = localCertificateSelectionCallback; _sslProtocols = sslProtocols; @@ -64,23 +60,11 @@ public TTlsServerSocketTransport( public TTlsServerSocketTransport( int port, X509Certificate2 certificate, - Buffering buffering = Buffering.None, RemoteCertificateValidationCallback clientCertValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) + : this(null, certificate, clientCertValidator, localCertificateSelectionCallback) { - if (!certificate.HasPrivateKey) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, - "Your server-certificate needs to have a private key"); - } - - _serverCertificate = certificate; - _buffering = buffering; - _clientCertValidator = clientCertValidator; - _localCertificateSelectionCallback = localCertificateSelectionCallback; - _sslProtocols = sslProtocols; - try { // Create server socket @@ -137,25 +121,8 @@ protected override async Task AcceptImplementationAsync(Cancellation _localCertificateSelectionCallback, _sslProtocols); await tTlsSocket.SetupTlsAsync(); - - TTransport trans = tTlsSocket; - - switch(_buffering) - { - case Buffering.BufferedTransport: - trans = new TBufferedTransport(trans); - break; - - case Buffering.FramedTransport: - trans = new TFramedTransport(trans); - break; - - default: - Debug.Assert(_buffering == Buffering.None); - break; - } - return trans; + return tTlsSocket; } catch (Exception ex) { diff --git a/lib/netstd/Thrift/Transport/TFramedTransport.cs b/lib/netstd/Thrift/Transport/TFramedTransport.cs index 6d0802dac9a..fe7793ec76b 100644 --- a/lib/netstd/Thrift/Transport/TFramedTransport.cs +++ b/lib/netstd/Thrift/Transport/TFramedTransport.cs @@ -22,15 +22,6 @@ namespace Thrift.Transport { - // it does not make much sense to use buffered when we already use framed - public enum Buffering - { - None, - BufferedTransport, - FramedTransport - } - - // ReSharper disable once InconsistentNaming public class TFramedTransport : TTransport { diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs index 1aa8a77b757..82b36ebadf7 100644 --- a/test/netstd/Server/TestServer.cs +++ b/test/netstd/Server/TestServer.cs @@ -50,9 +50,16 @@ internal enum TransportChoice NamedPipe } + internal enum BufferChoice + { + None, + Buffered, + Framed + } + internal class ServerParam { - internal Buffering buffering = Buffering.None; + internal BufferChoice buffering = BufferChoice.None; internal ProtocolChoice protocol = ProtocolChoice.Binary; internal TransportChoice transport = TransportChoice.Socket; internal int port = 9090; @@ -75,11 +82,11 @@ internal void Parse(List args) } else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") { - buffering = Buffering.BufferedTransport; + buffering = BufferChoice.Buffered; } else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") { - buffering = Buffering.FramedTransport; + buffering = BufferChoice.Framed; } else if (args[i] == "--binary" || args[i] == "--protocol=binary") { @@ -539,11 +546,8 @@ public static int Execute(List args) } - TTransportFactory transFactory = null; - - // Transport + // Endpoint transport (mandatory) TServerTransport trans; - switch (param.transport) { case TransportChoice.NamedPipe: @@ -559,34 +563,34 @@ public static int Execute(List args) throw new InvalidOperationException("Certificate doesn't contain private key"); } - transFactory = new TTransportFactory(); // framed/buffered is built into socket transports - trans = new TTlsServerSocketTransport( param.port, cert, param.buffering, + trans = new TTlsServerSocketTransport( param.port, cert, (sender, certificate, chain, errors) => true, null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); break; case TransportChoice.Socket: default: - transFactory = new TTransportFactory(); // framed/buffered is built into socket transports - trans = new TServerSocketTransport(param.port, 0, param.buffering); + trans = new TServerSocketTransport(param.port, 0); break; } - // add layered transport, if not already set above - if (transFactory == null) + // Layered transport (mandatory) + TTransportFactory transFactory = null; + switch (param.buffering) { - switch (param.buffering) - { - case Buffering.FramedTransport: - transFactory = new TFramedTransport.Factory(); - break; - case Buffering.BufferedTransport: - transFactory = new TBufferedTransport.Factory(); - break; - } + case BufferChoice.Framed: + transFactory = new TFramedTransport.Factory(); + break; + case BufferChoice.Buffered: + transFactory = new TBufferedTransport.Factory(); + break; + default: + Debug.Assert(param.buffering == BufferChoice.None, "unhandled case"); + transFactory = null; // no layered transprt + break; } - // Protocol + // Protocol (mandatory) TProtocolFactory proto; switch (param.protocol) { @@ -617,8 +621,8 @@ public static int Execute(List args) var where = (! string.IsNullOrEmpty(param.pipe)) ? "on pipe " + param.pipe : "on port " + param.port; Console.WriteLine("Starting the AsyncBaseServer " + where + " with processor TPrototypeProcessorFactory prototype factory " + - (param.buffering == Buffering.BufferedTransport ? " with buffered transport" : "") + - (param.buffering == Buffering.FramedTransport ? " with framed transport" : "") + + (param.buffering == BufferChoice.Buffered ? " with buffered transport" : "") + + (param.buffering == BufferChoice.Framed ? " with framed transport" : "") + (param.transport == TransportChoice.TlsSocket ? " with encryption" : "") + (param.protocol == ProtocolChoice.Compact ? " with compact protocol" : "") + (param.protocol == ProtocolChoice.Json ? " with json protocol" : "") + diff --git a/tutorial/netstd/Client/Client.csproj b/tutorial/netstd/Client/Client.csproj index 70eae15847b..a1470a9d374 100644 --- a/tutorial/netstd/Client/Client.csproj +++ b/tutorial/netstd/Client/Client.csproj @@ -29,6 +29,10 @@ false + + + + diff --git a/tutorial/netstd/Client/Program.cs b/tutorial/netstd/Client/Program.cs index 4b68cee4aed..f9509fa2d9a 100644 --- a/tutorial/netstd/Client/Program.cs +++ b/tutorial/netstd/Client/Program.cs @@ -32,6 +32,7 @@ using tutorial; using shared; using Microsoft.Extensions.DependencyInjection; +using System.Diagnostics; namespace Client { @@ -47,17 +48,20 @@ private static void DisplayHelp() Client.exe -help will diplay help information - Client.exe -tr: -pr: -mc: + Client.exe -tr: -bf: -pr: -mc: will run client with specified arguments (tcp transport and binary protocol by default) and with 1 client Options: -tr (transport): tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) - tcpbuffered - buffered transport over tcp will be used (host - ""localhost"", port - 9090) namedpipe - namedpipe transport will be used (pipe address - "".test"") http - http transport will be used (address - ""http://localhost:9090"") tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) - framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -bf (buffering): + none - (default) no buffering will be used + buffered - buffered transport will be used + framed - framed transport will be used -pr (protocol): binary - (default) binary protocol will be used @@ -139,29 +143,57 @@ private static async Task RunAsync(string[] args, CancellationToken cancellation private static TTransport GetTransport(string[] args) { - var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; + TTransport transport = new TSocketTransport(IPAddress.Loopback, 9090); - Transport selectedTransport; - if (Enum.TryParse(transport, true, out selectedTransport)) + // construct endpoint transport + var transportArg = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; + if (Enum.TryParse(transportArg, true, out Transport selectedTransport)) { switch (selectedTransport) { case Transport.Tcp: - return new TSocketTransport(IPAddress.Loopback, 9090); + transport = new TSocketTransport(IPAddress.Loopback, 9090); + break; + case Transport.NamedPipe: - return new TNamedPipeTransport(".test"); + transport = new TNamedPipeTransport(".test"); + break; + case Transport.Http: - return new THttpTransport(new Uri("http://localhost:9090"), null); - case Transport.TcpBuffered: - return new TBufferedTransport(new TSocketTransport(IPAddress.Loopback, 9090)); + transport = new THttpTransport(new Uri("http://localhost:9090"), null); + break; + case Transport.TcpTls: - return new TTlsSocketTransport(IPAddress.Loopback, 9090, GetCertificate(), CertValidator, LocalCertificateSelectionCallback); - case Transport.Framed: - return new TFramedTransport(new TSocketTransport(IPAddress.Loopback, 9090)); + transport = new TTlsSocketTransport(IPAddress.Loopback, 9090, GetCertificate(), CertValidator, LocalCertificateSelectionCallback); + break; + + default: + Debug.Assert(false, "unhandled case"); + break; } } - return new TSocketTransport(IPAddress.Loopback, 9090); + // optionally add layered transport(s) + var bufferingArg = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(':')?[1]; + if (Enum.TryParse(bufferingArg, out var selectedBuffering)) + { + switch (selectedBuffering) + { + case Buffering.Buffered: + transport = new TBufferedTransport(transport); + break; + + case Buffering.Framed: + transport = new TFramedTransport(transport); + break; + + default: // layered transport(s) are optional + Debug.Assert(selectedBuffering == Buffering.None, "unhandled case"); + break; + } + } + + return transport; } private static int GetNumberOfClients(string[] args) @@ -231,6 +263,9 @@ private static Tuple GetProtocol(string[] args, TTransport case Protocol.Multiplexed: // it returns BinaryProtocol to avoid making wrapped protocol as public in TProtocolDecorator (in RunClientAsync it will be wrapped into Multiplexed protocol) return new Tuple(selectedProtocol, new TBinaryProtocol(transport)); + default: + Debug.Assert(false, "unhandled case"); + break; } } @@ -363,5 +398,12 @@ private enum Protocol Json, Multiplexed } + + private enum Buffering + { + None, + Buffered, + Framed + } } } diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs index c5e26d12d08..25e7daeedaa 100644 --- a/tutorial/netstd/Server/Program.cs +++ b/tutorial/netstd/Server/Program.cs @@ -36,6 +36,7 @@ using tutorial; using shared; using Thrift.Processor; +using System.Diagnostics; namespace Server { @@ -85,17 +86,20 @@ private static void DisplayHelp() Server.exe -help will diplay help information - Server.exe -tr: -pr: - will run server with specified arguments (tcp transport and binary protocol by default) + Server.exe -tr: -bf: -pr: + will run server with specified arguments (tcp transport, no buffering, and binary protocol by default) Options: -tr (transport): tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) - tcpbuffered - tcp buffered transport will be used (host - ""localhost"", port - 9090) namedpipe - namedpipe transport will be used (pipe address - "".test"") http - http transport will be used (http address - ""localhost:9090"") tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) - framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -bf (buffering): + none - (default) no buffering will be used + buffered - buffered transport will be used + framed - framed transport will be used -pr (protocol): binary - (default) binary protocol will be used @@ -111,6 +115,7 @@ will run server with specified arguments (tcp transport and binary protocol by d private static async Task RunAsync(string[] args, CancellationToken cancellationToken) { var selectedTransport = GetTransport(args); + var selectedBuffering = GetBuffering(args); var selectedProtocol = GetProtocol(args); if (selectedTransport == Transport.Http) @@ -119,7 +124,7 @@ private static async Task RunAsync(string[] args, CancellationToken cancellation } else { - await RunSelectedConfigurationAsync(selectedTransport, selectedProtocol, cancellationToken); + await RunSelectedConfigurationAsync(selectedTransport, selectedBuffering, selectedProtocol, cancellationToken); } } @@ -132,6 +137,15 @@ private static Protocol GetProtocol(string[] args) return selectedProtocol; } + private static Buffering GetBuffering(string[] args) + { + var buffering = args.FirstOrDefault(x => x.StartsWith("-bf"))?.Split(":")?[1]; + + Enum.TryParse(buffering, out var selectedBuffering); + + return selectedBuffering; + } + private static Transport GetTransport(string[] args) { var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; @@ -141,10 +155,9 @@ private static Transport GetTransport(string[] args) return selectedTransport; } - private static async Task RunSelectedConfigurationAsync(Transport transport, Protocol protocol, CancellationToken cancellationToken) + private static async Task RunSelectedConfigurationAsync(Transport transport, Buffering buffering, Protocol protocol, CancellationToken cancellationToken) { var handler = new CalculatorAsyncHandler(); - ITAsyncProcessor processor = null; TServerTransport serverTransport = null; switch (transport) @@ -152,23 +165,36 @@ private static async Task RunSelectedConfigurationAsync(Transport transport, Pro case Transport.Tcp: serverTransport = new TServerSocketTransport(9090); break; - case Transport.TcpBuffered: - serverTransport = new TServerSocketTransport(port: 9090, clientTimeout: 10000, buffering: Buffering.BufferedTransport); - break; case Transport.NamedPipe: serverTransport = new TNamedPipeServerTransport(".test"); break; case Transport.TcpTls: - serverTransport = new TTlsServerSocketTransport(9090, GetCertificate(), Buffering.None, ClientCertValidator, LocalCertificateSelectionCallback); - break; - case Transport.Framed: - serverTransport = new TServerFramedTransport(9090); + serverTransport = new TTlsServerSocketTransport(9090, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback); break; } - TProtocolFactory inputProtocolFactory; - TProtocolFactory outputProtocolFactory; + TTransportFactory inputTransportFactory = null; + TTransportFactory outputTransportFactory = null; + switch (buffering) + { + case Buffering.Buffered: + inputTransportFactory = new TBufferedTransport.Factory(); + outputTransportFactory = new TBufferedTransport.Factory(); + break; + case Buffering.Framed: + inputTransportFactory = new TFramedTransport.Factory(); + outputTransportFactory = new TFramedTransport.Factory(); + break; + + default: // layered transport(s) are optional + Debug.Assert(buffering == Buffering.None, "unhandled case"); + break; + } + + TProtocolFactory inputProtocolFactory = null; + TProtocolFactory outputProtocolFactory = null; + ITAsyncProcessor processor = null; switch (protocol) { case Protocol.Binary: @@ -210,15 +236,25 @@ private static async Task RunSelectedConfigurationAsync(Transport transport, Pro throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null); } + try { Logger.LogInformation( $"Selected TAsyncServer with {serverTransport} transport, {processor} processor and {inputProtocolFactory} protocol factories"); - var fabric = ServiceCollection.BuildServiceProvider().GetService(); - var server = new TSimpleAsyncServer(processor, serverTransport, inputProtocolFactory, outputProtocolFactory, fabric); + var loggerFactory = ServiceCollection.BuildServiceProvider().GetService(); + + var server = new TSimpleAsyncServer( + itProcessorFactory: new TSingletonProcessorFactory(processor), + serverTransport: serverTransport, + inputTransportFactory: inputTransportFactory, + outputTransportFactory: outputTransportFactory, + inputProtocolFactory: inputProtocolFactory, + outputProtocolFactory: outputProtocolFactory, + logger: loggerFactory.CreateLogger()); Logger.LogInformation("Starting the server..."); + await server.ServeAsync(cancellationToken); } catch (Exception x) @@ -266,11 +302,16 @@ private static bool ClientCertValidator(object sender, X509Certificate certifica private enum Transport { Tcp, - TcpBuffered, NamedPipe, Http, TcpTls, - Framed + } + + private enum Buffering + { + None, + Buffered, + Framed, } private enum Protocol From 0bc4712929b42d22424c31b11406d7afef950661 Mon Sep 17 00:00:00 2001 From: Kyle Smith Date: Wed, 27 Mar 2019 11:41:34 -0400 Subject: [PATCH 263/756] THRIFT-4840: Updated the README for the netstd tutorial Client: netstd Patch: Kyle Smith This closes #1772 --- tutorial/netstd/README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tutorial/netstd/README.md b/tutorial/netstd/README.md index 8c8317a6581..b1dea4ecbd5 100644 --- a/tutorial/netstd/README.md +++ b/tutorial/netstd/README.md @@ -43,11 +43,14 @@ Options: -tr (transport): tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) - tcpbuffered - tcp buffered transport will be used (host - ""localhost"", port - 9090) namedpipe - namedpipe transport will be used (pipe address - "".test"") http - http transport will be used (http address - ""localhost:9090"") tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) - framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -bf (buffering): + none - (default) no transport factory will be used + buffered - buffered transport factory will be used + framed - framed transport factory will be used (this must match the client) -pr (protocol): binary - (default) binary protocol will be used @@ -79,11 +82,14 @@ Options: -tr (transport): tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) - tcpbuffered - buffered transport over tcp will be used (host - ""localhost"", port - 9090) namedpipe - namedpipe transport will be used (pipe address - "".test"") http - http transport will be used (address - ""http://localhost:9090"") tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) - framed - tcp framed transport will be used (host - ""localhost"", port - 9090) + + -bf (buffering): + none - (default) no transport factory will be used + buffered - buffered transport factory will be used + framed - framed transport factory will be used (this must match the client) -pr (protocol): binary - (default) binary protocol will be used From c9b1e29bc9e0702d7441383358d565e1e76ccea7 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 4 Apr 2019 00:00:38 +0200 Subject: [PATCH 264/756] THRIFT-4843 http:// and https:// schemes are switched in test client Client: Delphi Patch: Jens Geyer --- lib/delphi/test/TestClient.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas index 0fa43b0be66..7b603a3445b 100644 --- a/lib/delphi/test/TestClient.pas +++ b/lib/delphi/test/TestClient.pas @@ -1339,8 +1339,8 @@ procedure TClientThread.InitializeProtocolTransportStack; trns_Http: begin Console.WriteLine('Using HTTPClient'); if FSetup.useSSL - then sUrl := 'http://' - else sUrl := 'https://'; + then sUrl := 'https://' + else sUrl := 'http://'; sUrl := sUrl + FSetup.host; case FSetup.port of 80 : if FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port); From 0223091b7049cbbddea675931771219de929fd59 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 3 Apr 2019 01:12:51 +0200 Subject: [PATCH 265/756] THRIFT-4841 THTTPTransport relies on activeX component Client: Delphi Patch: Jens Geyer This closes #1778 --- CHANGES.md | 9 +- lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas | 255 ++++++ lib/delphi/src/Thrift.Transport.WinHTTP.pas | 335 ++++++++ lib/delphi/src/Thrift.Transport.pas | 210 +---- lib/delphi/src/Thrift.WinHTTP.pas | 805 ++++++++++++++++++ lib/delphi/test/TestClient.pas | 70 +- lib/delphi/test/TestConstants.pas | 5 +- lib/delphi/test/TestServer.pas | 8 +- lib/delphi/test/client.dpr | 3 + .../multiplexed/Multiplex.Test.Client.dpr | 1 + .../multiplexed/Multiplex.Test.Server.dpr | 1 + lib/delphi/test/serializer/TestSerializer.dpr | 1 + lib/delphi/test/server.dpr | 1 + lib/delphi/test/skip/skiptest_version1.dpr | 1 + lib/delphi/test/skip/skiptest_version2.dpr | 1 + .../test/typeregistry/TestTypeRegistry.dpr | 1 + tutorial/delphi/DelphiClient/DelphiClient.dpr | 3 + .../delphi/DelphiClient/DelphiClient.dproj | 3 + tutorial/delphi/DelphiServer/DelphiServer.dpr | 1 + .../delphi/DelphiServer/DelphiServer.dproj | 1 + 20 files changed, 1473 insertions(+), 242 deletions(-) create mode 100644 lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas create mode 100644 lib/delphi/src/Thrift.Transport.WinHTTP.pas create mode 100644 lib/delphi/src/Thrift.WinHTTP.pas diff --git a/CHANGES.md b/CHANGES.md index 1ca18e85d5e..41434e936c4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,14 +6,12 @@ ### Deprecated Languages +- [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - CSharp and Netcore targets are deprecated and will be removed with the next release - use NetStd instead. + ### Removed Languages - [THRIFT-4719](https://issues.apache.org/jira/browse/THRIFT-4719) - Cocoa language was removed - use swift instead. -### Deprecated Languages - -- [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - CSharp and Netcore targets are deprecated and will be removed with the next release - use NetStd instead. - ### Breaking Changes - [THRIFT-4743](https://issues.apache.org/jira/browse/THRIFT-4743) - compiler: removed the plug-in mechanism @@ -22,12 +20,13 @@ - [THRIFT-4732](https://issues.apache.org/jira/browse/THRIFT-4732) - cpp: CMake build changed to use BUILD_SHARED_LIBS - [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735) - cpp: Removed Qt4 support - [THRIFT-4740](https://issues.apache.org/jira/browse/THRIFT-4740) - cpp: Use std::chrono::duration for timeouts -- [THRIFT-4672](https://issues.apache.org/jira/browse/THRIFT-4672) - cpp: TTransport::getOrigin() is now const +- [THRIFT-4762](https://issues.apache.org/jira/browse/THRIFT-4762) - cpp: TTransport::getOrigin() is now const - [THRIFT-4702](https://issues.apache.org/jira/browse/THRIFT-4702) - java: class org.apache.thrift.AutoExpandingBuffer is no longer public - [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - java: changes to UTF-8 handling require JDK 1.7 at a minimum - [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - java: class org.apache.thrift.ShortStack is no longer public - [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - java: change return type signature of 'process' methods - [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - js: now uses node-int64 for 64 bit integer constants +- [THRIFT-4841](https://issues.apache.org/jira/browse/THRIFT-4841) - delphi: old THTTPTransport is now TMsxmlHTTPTransport ### Known Issues (Blocker or Critical) diff --git a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas new file mode 100644 index 00000000000..cdfb541887d --- /dev/null +++ b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas @@ -0,0 +1,255 @@ +(* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *) +unit Thrift.Transport.MsxmlHTTP; + +{$I Thrift.Defines.inc} +{$SCOPEDENUMS ON} + +interface + +uses + Classes, + SysUtils, + Math, + Generics.Collections, + {$IFDEF OLD_UNIT_NAMES} + ActiveX, msxml, + {$ELSE} + Winapi.ActiveX, Winapi.msxml, + {$ENDIF} + Thrift.Collections, + Thrift.Transport, + Thrift.Exception, + Thrift.Utils, + Thrift.Stream; + +type + TMsxmlHTTPClientImpl = class( TTransportImpl, IHTTPClient) + private + FUri : string; + FInputStream : IThriftStream; + FOutputStream : IThriftStream; + FDnsResolveTimeout : Integer; + FConnectionTimeout : Integer; + FSendTimeout : Integer; + FReadTimeout : Integer; + FCustomHeaders : IThriftDictionary; + + function CreateRequest: IXMLHTTPRequest; + protected + function GetIsOpen: Boolean; override; + procedure Open(); override; + procedure Close(); override; + function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; + procedure Write( const pBuf : Pointer; off, len : Integer); override; + procedure Flush; override; + + procedure SetDnsResolveTimeout(const Value: Integer); + function GetDnsResolveTimeout: Integer; + procedure SetConnectionTimeout(const Value: Integer); + function GetConnectionTimeout: Integer; + procedure SetSendTimeout(const Value: Integer); + function GetSendTimeout: Integer; + procedure SetReadTimeout(const Value: Integer); + function GetReadTimeout: Integer; + + function GetCustomHeaders: IThriftDictionary; + procedure SendRequest; + property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout; + property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout; + property SendTimeout: Integer read GetSendTimeout write SetSendTimeout; + property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout; + property CustomHeaders: IThriftDictionary read GetCustomHeaders; + public + constructor Create( const AUri: string); + destructor Destroy; override; + end; + + +implementation + + +{ TMsxmlHTTPClientImpl } + +constructor TMsxmlHTTPClientImpl.Create(const AUri: string); +begin + inherited Create; + FUri := AUri; + + // defaults according to MSDN + FDnsResolveTimeout := 0; // no timeout + FConnectionTimeout := 60 * 1000; + FSendTimeout := 30 * 1000; + FReadTimeout := 30 * 1000; + + FCustomHeaders := TThriftDictionaryImpl.Create; + FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True); +end; + +function TMsxmlHTTPClientImpl.CreateRequest: IXMLHTTPRequest; +var + pair : TPair; + srvHttp : IServerXMLHTTPRequest; +begin + {$IF CompilerVersion >= 21.0} + Result := CoServerXMLHTTP.Create; + {$ELSE} + Result := CoXMLHTTPRequest.Create; + {$IFEND} + + // setting a timeout value to 0 (zero) means "no timeout" for that setting + if Supports( result, IServerXMLHTTPRequest, srvHttp) + then srvHttp.setTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout); + + Result.open('POST', FUri, False, '', ''); + Result.setRequestHeader( 'Content-Type', 'application/x-thrift'); + Result.setRequestHeader( 'Accept', 'application/x-thrift'); + Result.setRequestHeader( 'User-Agent', 'Delphi/IHTTPClient'); + + for pair in FCustomHeaders do begin + Result.setRequestHeader( pair.Key, pair.Value ); + end; +end; + +destructor TMsxmlHTTPClientImpl.Destroy; +begin + Close; + inherited; +end; + +function TMsxmlHTTPClientImpl.GetDnsResolveTimeout: Integer; +begin + Result := FDnsResolveTimeout; +end; + +procedure TMsxmlHTTPClientImpl.SetDnsResolveTimeout(const Value: Integer); +begin + FDnsResolveTimeout := Value; +end; + +function TMsxmlHTTPClientImpl.GetConnectionTimeout: Integer; +begin + Result := FConnectionTimeout; +end; + +procedure TMsxmlHTTPClientImpl.SetConnectionTimeout(const Value: Integer); +begin + FConnectionTimeout := Value; +end; + +function TMsxmlHTTPClientImpl.GetSendTimeout: Integer; +begin + Result := FSendTimeout; +end; + +procedure TMsxmlHTTPClientImpl.SetSendTimeout(const Value: Integer); +begin + FSendTimeout := Value; +end; + +function TMsxmlHTTPClientImpl.GetReadTimeout: Integer; +begin + Result := FReadTimeout; +end; + +procedure TMsxmlHTTPClientImpl.SetReadTimeout(const Value: Integer); +begin + FReadTimeout := Value; +end; + +function TMsxmlHTTPClientImpl.GetCustomHeaders: IThriftDictionary; +begin + Result := FCustomHeaders; +end; + +function TMsxmlHTTPClientImpl.GetIsOpen: Boolean; +begin + Result := True; +end; + +procedure TMsxmlHTTPClientImpl.Open; +begin + FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True); +end; + +procedure TMsxmlHTTPClientImpl.Close; +begin + FInputStream := nil; + FOutputStream := nil; +end; + +procedure TMsxmlHTTPClientImpl.Flush; +begin + try + SendRequest; + finally + FOutputStream := nil; + FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True); + ASSERT( FOutputStream <> nil); + end; +end; + +function TMsxmlHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; +begin + if FInputStream = nil then begin + raise TTransportExceptionNotOpen.Create('No request has been sent'); + end; + + try + Result := FInputStream.Read( pBuf, buflen, off, len) + except + on E: Exception + do raise TTransportExceptionUnknown.Create(E.Message); + end; +end; + +procedure TMsxmlHTTPClientImpl.SendRequest; +var + xmlhttp : IXMLHTTPRequest; + ms : TMemoryStream; + a : TBytes; + len : Integer; +begin + xmlhttp := CreateRequest; + + ms := TMemoryStream.Create; + try + a := FOutputStream.ToArray; + len := Length(a); + if len > 0 then begin + ms.WriteBuffer( Pointer(@a[0])^, len); + end; + ms.Position := 0; + xmlhttp.send( IUnknown( TStreamAdapter.Create( ms, soReference ))); + FInputStream := nil; + FInputStream := TThriftStreamAdapterCOM.Create( IUnknown( xmlhttp.responseStream) as IStream); + finally + ms.Free; + end; +end; + +procedure TMsxmlHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer); +begin + FOutputStream.Write( pBuf, off, len); +end; + + + +end. + diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas new file mode 100644 index 00000000000..aac2aeaf298 --- /dev/null +++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas @@ -0,0 +1,335 @@ +(* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *) +unit Thrift.Transport.WinHTTP; + +{$I Thrift.Defines.inc} +{$SCOPEDENUMS ON} + +interface + +uses + Classes, + SysUtils, + Math, + Generics.Collections, + Thrift.Collections, + Thrift.Transport, + Thrift.Exception, + Thrift.Utils, + Thrift.WinHTTP, + Thrift.Stream; + +type + TWinHTTPClientImpl = class( TTransportImpl, IHTTPClient) + private + FUri : string; + FInputStream : IThriftStream; + FOutputMemoryStream : TMemoryStream; + FDnsResolveTimeout : Integer; + FConnectionTimeout : Integer; + FSendTimeout : Integer; + FReadTimeout : Integer; + FCustomHeaders : IThriftDictionary; + + function CreateRequest: IWinHTTPRequest; + + private type + THTTPResponseStream = class( TThriftStreamImpl) + private + FRequest : IWinHTTPRequest; + protected + procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; + function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; + procedure Open; override; + procedure Close; override; + procedure Flush; override; + function IsOpen: Boolean; override; + function ToArray: TBytes; override; + public + constructor Create( const aRequest : IWinHTTPRequest); + destructor Destroy; override; + end; + + protected + function GetIsOpen: Boolean; override; + procedure Open(); override; + procedure Close(); override; + function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; + procedure Write( const pBuf : Pointer; off, len : Integer); override; + procedure Flush; override; + + procedure SetDnsResolveTimeout(const Value: Integer); + function GetDnsResolveTimeout: Integer; + procedure SetConnectionTimeout(const Value: Integer); + function GetConnectionTimeout: Integer; + procedure SetSendTimeout(const Value: Integer); + function GetSendTimeout: Integer; + procedure SetReadTimeout(const Value: Integer); + function GetReadTimeout: Integer; + + function GetCustomHeaders: IThriftDictionary; + procedure SendRequest; + property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout; + property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout; + property SendTimeout: Integer read GetSendTimeout write SetSendTimeout; + property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout; + property CustomHeaders: IThriftDictionary read GetCustomHeaders; + public + constructor Create( const AUri: string); + destructor Destroy; override; + end; + +implementation + + +{ TWinHTTPClientImpl } + +constructor TWinHTTPClientImpl.Create(const AUri: string); +begin + inherited Create; + FUri := AUri; + + // defaults according to MSDN + FDnsResolveTimeout := 0; // no timeout + FConnectionTimeout := 60 * 1000; + FSendTimeout := 30 * 1000; + FReadTimeout := 30 * 1000; + + FCustomHeaders := TThriftDictionaryImpl.Create; + FOutputMemoryStream := TMemoryStream.Create; +end; + +destructor TWinHTTPClientImpl.Destroy; +begin + Close; + FreeAndNil( FOutputMemoryStream); + inherited; +end; + +function TWinHTTPClientImpl.CreateRequest: IWinHTTPRequest; +var + pair : TPair; + session : IWinHTTPSession; + connect : IWinHTTPConnection; + url : IWinHTTPUrl; + sPath : string; +begin + url := TWinHTTPUrlImpl.Create( FUri); + + session := TWinHTTPSessionImpl.Create('Apache Thrift Delphi Client'); + connect := session.Connect( url.HostName, url.Port); + + sPath := url.UrlPath + url.ExtraInfo; + result := connect.OpenRequest( (url.Scheme = 'https'), 'POST', sPath, 'application/x-thrift'); + + // setting a timeout value to 0 (zero) means "no timeout" for that setting + result.SetTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout); + + result.AddRequestHeader( 'Content-Type: application/x-thrift', WINHTTP_ADDREQ_FLAG_ADD); + + for pair in FCustomHeaders do begin + Result.AddRequestHeader( pair.Key +': '+ pair.Value, WINHTTP_ADDREQ_FLAG_ADD); + end; +end; + +function TWinHTTPClientImpl.GetDnsResolveTimeout: Integer; +begin + Result := FDnsResolveTimeout; +end; + +procedure TWinHTTPClientImpl.SetDnsResolveTimeout(const Value: Integer); +begin + FDnsResolveTimeout := Value; +end; + +function TWinHTTPClientImpl.GetConnectionTimeout: Integer; +begin + Result := FConnectionTimeout; +end; + +procedure TWinHTTPClientImpl.SetConnectionTimeout(const Value: Integer); +begin + FConnectionTimeout := Value; +end; + +function TWinHTTPClientImpl.GetSendTimeout: Integer; +begin + Result := FSendTimeout; +end; + +procedure TWinHTTPClientImpl.SetSendTimeout(const Value: Integer); +begin + FSendTimeout := Value; +end; + +function TWinHTTPClientImpl.GetReadTimeout: Integer; +begin + Result := FReadTimeout; +end; + +procedure TWinHTTPClientImpl.SetReadTimeout(const Value: Integer); +begin + FReadTimeout := Value; +end; + +function TWinHTTPClientImpl.GetCustomHeaders: IThriftDictionary; +begin + Result := FCustomHeaders; +end; + +function TWinHTTPClientImpl.GetIsOpen: Boolean; +begin + Result := True; +end; + +procedure TWinHTTPClientImpl.Open; +begin + FreeAndNil( FOutputMemoryStream); + FOutputMemoryStream := TMemoryStream.Create; +end; + +procedure TWinHTTPClientImpl.Close; +begin + FInputStream := nil; + FreeAndNil( FOutputMemoryStream); +end; + +procedure TWinHTTPClientImpl.Flush; +begin + try + SendRequest; + finally + FreeAndNil( FOutputMemoryStream); + FOutputMemoryStream := TMemoryStream.Create; + ASSERT( FOutputMemoryStream <> nil); + end; +end; + +function TWinHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; +begin + if FInputStream = nil then begin + raise TTransportExceptionNotOpen.Create('No request has been sent'); + end; + + try + Result := FInputStream.Read( pBuf, buflen, off, len) + except + on E: Exception + do raise TTransportExceptionUnknown.Create(E.Message); + end; +end; + +procedure TWinHTTPClientImpl.SendRequest; +var + http : IWinHTTPRequest; + pData : PByte; + len : Integer; +begin + http := CreateRequest; + + pData := FOutputMemoryStream.Memory; + len := FOutputMemoryStream.Size; + + // send all data immediately, since we have it in memory + if not http.SendRequest( pData, len, 0) + then raise TTransportExceptionUnknown.Create('send request error'); + + // end request and start receiving + if not http.FlushAndReceiveResponse + then raise TTransportExceptionInterrupted.Create('flush/receive error'); + + FInputStream := THTTPResponseStream.Create(http); +end; + +procedure TWinHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer); +var pTmp : PByte; +begin + pTmp := pBuf; + Inc(pTmp,off); + FOutputMemoryStream.Write( pTmp^, len); +end; + + +{ TWinHTTPClientImpl.THTTPResponseStream } + +constructor TWinHTTPClientImpl.THTTPResponseStream.Create( const aRequest : IWinHTTPRequest); +begin + inherited Create; + FRequest := aRequest; +end; + +destructor TWinHTTPClientImpl.THTTPResponseStream.Destroy; +begin + try + Close; + finally + inherited Destroy; + end; +end; + +procedure TWinHTTPClientImpl.THTTPResponseStream.Close; +begin + FRequest := nil; +end; + +procedure TWinHTTPClientImpl.THTTPResponseStream.Flush; +begin + raise ENotImplemented(ClassName+'.Flush'); +end; + +function TWinHTTPClientImpl.THTTPResponseStream.IsOpen: Boolean; +begin + Result := FRequest <> nil; +end; + +procedure TWinHTTPClientImpl.THTTPResponseStream.Open; +begin + // nothing to do +end; + +procedure TWinHTTPClientImpl.THTTPResponseStream.Write(const pBuf : Pointer; offset, count: Integer); +begin + inherited; // check pointers + raise ENotImplemented(ClassName+'.Write'); +end; + +function TWinHTTPClientImpl.THTTPResponseStream.Read(const pBuf : Pointer; const buflen : Integer; offset, count: Integer): Integer; +var pTmp : PByte; +begin + inherited; // check pointers + + if count >= buflen-offset + then count := buflen-offset; + + if count > 0 then begin + pTmp := pBuf; + Inc( pTmp, offset); + Result := FRequest.ReadData( pTmp, count); + ASSERT( Result >= 0); + end + else Result := 0; +end; + +function TWinHTTPClientImpl.THTTPResponseStream.ToArray: TBytes; +begin + raise ENotImplemented(ClassName+'.ToArray'); +end; + + +end. diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index dad9ab7f305..1f8fdb0b239 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -29,9 +29,9 @@ interface Math, Generics.Collections, {$IFDEF OLD_UNIT_NAMES} - ActiveX, msxml, WinSock, Sockets, + WinSock, Sockets, {$ELSE} - Winapi.ActiveX, Winapi.msxml, Winapi.WinSock, + Winapi.WinSock, {$IFDEF OLD_SOCKETS} Web.Win.Sockets, {$ELSE} @@ -41,6 +41,7 @@ interface Thrift.Collections, Thrift.Exception, Thrift.Utils, + Thrift.WinHTTP, Thrift.Stream; type @@ -137,47 +138,6 @@ TTransportExceptionInterrupted = class (TTransportExceptionSpecialized); property CustomHeaders: IThriftDictionary read GetCustomHeaders; end; - THTTPClientImpl = class( TTransportImpl, IHTTPClient) - private - FUri : string; - FInputStream : IThriftStream; - FOutputStream : IThriftStream; - FDnsResolveTimeout : Integer; - FConnectionTimeout : Integer; - FSendTimeout : Integer; - FReadTimeout : Integer; - FCustomHeaders : IThriftDictionary; - - function CreateRequest: IXMLHTTPRequest; - protected - function GetIsOpen: Boolean; override; - procedure Open(); override; - procedure Close(); override; - function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; - procedure Write( const pBuf : Pointer; off, len : Integer); override; - procedure Flush; override; - - procedure SetDnsResolveTimeout(const Value: Integer); - function GetDnsResolveTimeout: Integer; - procedure SetConnectionTimeout(const Value: Integer); - function GetConnectionTimeout: Integer; - procedure SetSendTimeout(const Value: Integer); - function GetSendTimeout: Integer; - procedure SetReadTimeout(const Value: Integer); - function GetReadTimeout: Integer; - - function GetCustomHeaders: IThriftDictionary; - procedure SendRequest; - property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout; - property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout; - property SendTimeout: Integer read GetSendTimeout write SetSendTimeout; - property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout; - property CustomHeaders: IThriftDictionary read GetCustomHeaders; - public - constructor Create( const AUri: string); - destructor Destroy; override; - end; - IServerTransport = interface ['{C43B87ED-69EA-47C4-B77C-15E288252900}'] procedure Listen; @@ -472,170 +432,6 @@ procedure TTransportImpl.Write( const pBuf : Pointer; len : Integer); Self.Write( pBuf, 0, len); end; -{ THTTPClientImpl } - -constructor THTTPClientImpl.Create(const AUri: string); -begin - inherited Create; - FUri := AUri; - - // defaults according to MSDN - FDnsResolveTimeout := 0; // no timeout - FConnectionTimeout := 60 * 1000; - FSendTimeout := 30 * 1000; - FReadTimeout := 30 * 1000; - - FCustomHeaders := TThriftDictionaryImpl.Create; - FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True); -end; - -function THTTPClientImpl.CreateRequest: IXMLHTTPRequest; -var - pair : TPair; - srvHttp : IServerXMLHTTPRequest; -begin - {$IF CompilerVersion >= 21.0} - Result := CoServerXMLHTTP.Create; - {$ELSE} - Result := CoXMLHTTPRequest.Create; - {$IFEND} - - // setting a timeout value to 0 (zero) means "no timeout" for that setting - if Supports( result, IServerXMLHTTPRequest, srvHttp) - then srvHttp.setTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout); - - Result.open('POST', FUri, False, '', ''); - Result.setRequestHeader( 'Content-Type', 'application/x-thrift'); - Result.setRequestHeader( 'Accept', 'application/x-thrift'); - Result.setRequestHeader( 'User-Agent', 'Delphi/IHTTPClient'); - - for pair in FCustomHeaders do begin - Result.setRequestHeader( pair.Key, pair.Value ); - end; -end; - -destructor THTTPClientImpl.Destroy; -begin - Close; - inherited; -end; - -function THTTPClientImpl.GetDnsResolveTimeout: Integer; -begin - Result := FDnsResolveTimeout; -end; - -procedure THTTPClientImpl.SetDnsResolveTimeout(const Value: Integer); -begin - FDnsResolveTimeout := Value; -end; - -function THTTPClientImpl.GetConnectionTimeout: Integer; -begin - Result := FConnectionTimeout; -end; - -procedure THTTPClientImpl.SetConnectionTimeout(const Value: Integer); -begin - FConnectionTimeout := Value; -end; - -function THTTPClientImpl.GetSendTimeout: Integer; -begin - Result := FSendTimeout; -end; - -procedure THTTPClientImpl.SetSendTimeout(const Value: Integer); -begin - FSendTimeout := Value; -end; - -function THTTPClientImpl.GetReadTimeout: Integer; -begin - Result := FReadTimeout; -end; - -procedure THTTPClientImpl.SetReadTimeout(const Value: Integer); -begin - FReadTimeout := Value; -end; - -function THTTPClientImpl.GetCustomHeaders: IThriftDictionary; -begin - Result := FCustomHeaders; -end; - -function THTTPClientImpl.GetIsOpen: Boolean; -begin - Result := True; -end; - -procedure THTTPClientImpl.Open; -begin - FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True); -end; - -procedure THTTPClientImpl.Close; -begin - FInputStream := nil; - FOutputStream := nil; -end; - -procedure THTTPClientImpl.Flush; -begin - try - SendRequest; - finally - FOutputStream := nil; - FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True); - ASSERT( FOutputStream <> nil); - end; -end; - -function THTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; -begin - if FInputStream = nil then begin - raise TTransportExceptionNotOpen.Create('No request has been sent'); - end; - - try - Result := FInputStream.Read( pBuf, buflen, off, len) - except - on E: Exception - do raise TTransportExceptionUnknown.Create(E.Message); - end; -end; - -procedure THTTPClientImpl.SendRequest; -var - xmlhttp : IXMLHTTPRequest; - ms : TMemoryStream; - a : TBytes; - len : Integer; -begin - xmlhttp := CreateRequest; - - ms := TMemoryStream.Create; - try - a := FOutputStream.ToArray; - len := Length(a); - if len > 0 then begin - ms.WriteBuffer( Pointer(@a[0])^, len); - end; - ms.Position := 0; - xmlhttp.send( IUnknown( TStreamAdapter.Create( ms, soReference ))); - FInputStream := nil; - FInputStream := TThriftStreamAdapterCOM.Create( IUnknown( xmlhttp.responseStream) as IStream); - finally - ms.Free; - end; -end; - -procedure THTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer); -begin - FOutputStream.Write( pBuf, off, len); -end; - { TTransportException } function TTransportException.GetType: TExceptionType; diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas new file mode 100644 index 00000000000..0d824b6184f --- /dev/null +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -0,0 +1,805 @@ +(* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *) +unit Thrift.WinHTTP; + +{$I Thrift.Defines.inc} +{$SCOPEDENUMS ON} + +// packing according to winhttp.h +{$IFDEF Win64} {$ALIGN 8} {$ELSE} {$ALIGN 4} {$ENDIF} + +interface + +uses + Windows, + Classes, + SysUtils, + Math, + Generics.Collections; + + +type + HINTERNET = type Pointer; + INTERNET_PORT = type WORD; + INTERNET_SCHEME = type Integer; + LPLPCWSTR = ^LPCWSTR; + + LPURL_COMPONENTS = ^URL_COMPONENTS; + URL_COMPONENTS = record + dwStructSize : DWORD; // set to SizeOf(URL_COMPONENTS) + lpszScheme : LPWSTR; // scheme name + dwSchemeLength : DWORD; + nScheme : INTERNET_SCHEME; // enumerated scheme type + lpszHostName : LPWSTR; // host name + dwHostNameLength : DWORD; + nPort : INTERNET_PORT; // port number + lpszUserName : LPWSTR; // user name + dwUserNameLength : DWORD; + lpszPassword : LPWSTR; // password + dwPasswordLength : DWORD; + lpszUrlPath : LPWSTR; // URL-path + dwUrlPathLength : DWORD; + lpszExtraInfo : LPWSTR; // extra information + dwExtraInfoLength : DWORD; + end; + + URL_COMPONENTSW = URL_COMPONENTS; + LPURL_COMPONENTSW = LPURL_COMPONENTS; + + +function WinHttpCloseHandle( aHandle : HINTERNET) : BOOL; stdcall; + +function WinHttpOpen( const pszAgentW : LPCWSTR; + const dwAccessType : DWORD; + const pszProxyW : LPCWSTR; + const pszProxyBypassW : LPCWSTR; + const dwFlags : DWORD + ) : HINTERNET; stdcall; + +function WinHttpConnect( const hSession : HINTERNET; + const pswzServerName : LPCWSTR; + const nServerPort : INTERNET_PORT; + const dwReserved : DWORD + ) : HINTERNET; stdcall; + +function WinHttpOpenRequest( const hConnect : HINTERNET; + const pwszVerb, pwszObjectName, pwszVersion, pwszReferrer : LPCWSTR; + const ppwszAcceptTypes : LPLPCWSTR; + const dwFlags : DWORD + ) : HINTERNET; stdcall; + +function WinHttpSetTimeouts( const hRequestOrSession : HINTERNET; + const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32 + ) : BOOL; stdcall; + +function WinHttpAddRequestHeaders( const hRequest : HINTERNET; + const pwszHeaders : LPCWSTR; + const dwHeadersLengthInChars : DWORD; + const dwModifiers : DWORD + ) : BOOL; stdcall; + +function WinHttpSendRequest( const hRequest : HINTERNET; + const lpszHeaders : LPCWSTR; + const dwHeadersLength : DWORD; + const lpOptional : Pointer; + const dwOptionalLength : DWORD; + const dwTotalLength : DWORD; + const pContext : Pointer + ) : BOOL; stdcall; + +function WinHttpWriteData( const hRequest : HINTERNET; + const pBuf : Pointer; + const dwBytesToWrite : DWORD; + out dwBytesWritten : DWORD + ) : BOOL; stdcall; + +function WinHttpReceiveResponse( const hRequest : HINTERNET; const lpReserved : Pointer) : BOOL; stdcall; + +function WinHttpQueryHeaders( const hRequest : HINTERNET; + const dwInfoLevel : DWORD; + const pwszName : LPCWSTR; + const lpBuffer : Pointer; + var dwBufferLength : DWORD; + var dwIndex : DWORD + ) : BOOL; stdcall; + +function WinHttpQueryDataAvailable( const hRequest : HINTERNET; + var dwNumberOfBytesAvailable : DWORD + ) : BOOL; stdcall; + +function WinHttpReadData( const hRequest : HINTERNET; + const lpBuffer : Pointer; + const dwBytesToRead : DWORD; + out dwBytesRead : DWORD + ) : BOOL; stdcall; + +function WinHttpCrackUrl( const pwszUrl : LPCWSTR; + const dwUrlLength : DWORD; + const dwFlags : DWORD; + var urlComponents : URL_COMPONENTS + ) : BOOL; stdcall; + +function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; + const dwFlags : DWORD; + const pwszUrl : LPCWSTR; + var pdwUrlLength : DWORD + ) : BOOL; stdcall; + + +const + // WinHttpOpen dwAccessType values + WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0; + WINHTTP_ACCESS_TYPE_NO_PROXY = 1; + WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3; + + // flags for WinHttpOpen(): + WINHTTP_FLAG_ASYNC = $10000000; // want async session, requires WinHttpSetStatusCallback() usage + + // ports + INTERNET_DEFAULT_PORT = 0; // use the protocol-specific default (80 or 443) + + // flags for WinHttpOpenRequest(): + WINHTTP_FLAG_SECURE = $00800000; // use SSL if applicable (HTTPS) + WINHTTP_FLAG_ESCAPE_PERCENT = $00000004; // if escaping enabled, escape percent as well + WINHTTP_FLAG_NULL_CODEPAGE = $00000008; // assume all symbols are ASCII, use fast convertion + WINHTTP_FLAG_BYPASS_PROXY_CACHE = $00000100; // add "pragma: no-cache" request header + WINHTTP_FLAG_REFRESH = WINHTTP_FLAG_BYPASS_PROXY_CACHE; + WINHTTP_FLAG_ESCAPE_DISABLE = $00000040; // disable escaping + WINHTTP_FLAG_ESCAPE_DISABLE_QUERY = $00000080; // if escaping enabled escape path part, but do not escape query + + // flags for WinHttpSendRequest(): + WINHTTP_NO_ADDITIONAL_HEADERS = nil; + WINHTTP_NO_REQUEST_DATA = nil; + + // WinHttpAddRequestHeaders() dwModifiers + WINHTTP_ADDREQ_INDEX_MASK = $0000FFFF; + WINHTTP_ADDREQ_FLAGS_MASK = $FFFF0000; + + WINHTTP_ADDREQ_FLAG_ADD_IF_NEW = $10000000; + WINHTTP_ADDREQ_FLAG_ADD = $20000000; + WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA = $40000000; + WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON = $01000000; + WINHTTP_ADDREQ_FLAG_COALESCE = WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA; + WINHTTP_ADDREQ_FLAG_REPLACE = $80000000; + + // URL functions + ICU_NO_ENCODE = $20000000; // Don't convert unsafe characters to escape sequence + ICU_DECODE = $10000000; // Convert %XX escape sequences to characters + ICU_NO_META = $08000000; // Don't convert .. etc. meta path sequences + ICU_ENCODE_SPACES_ONLY = $04000000; // Encode spaces only + ICU_BROWSER_MODE = $02000000; // Special encode/decode rules for browser + ICU_ENCODE_PERCENT = $00001000; // Encode any percent (ASCII25) + + ICU_ESCAPE = $80000000; // (un)escape URL characters + ICU_ESCAPE_AUTHORITY = $00002000; // causes InternetCreateUrlA to escape chars in authority components (user, pwd, host) + ICU_REJECT_USERPWD = $00004000; // rejects usrls whick have username/pwd sections + + INTERNET_SCHEME_HTTP = INTERNET_SCHEME(1); + INTERNET_SCHEME_HTTPS = INTERNET_SCHEME(2); + +const + WINHTTP_ERROR_BASE = 12000; + ERROR_WINHTTP_OUT_OF_HANDLES = WINHTTP_ERROR_BASE + 1; + ERROR_WINHTTP_TIMEOUT = WINHTTP_ERROR_BASE + 2; + ERROR_WINHTTP_INTERNAL_ERROR = WINHTTP_ERROR_BASE + 4; + ERROR_WINHTTP_INVALID_URL = WINHTTP_ERROR_BASE + 5; + ERROR_WINHTTP_UNRECOGNIZED_SCHEME = WINHTTP_ERROR_BASE + 6; + ERROR_WINHTTP_NAME_NOT_RESOLVED = WINHTTP_ERROR_BASE + 7; + ERROR_WINHTTP_INVALID_OPTION = WINHTTP_ERROR_BASE + 9; + ERROR_WINHTTP_OPTION_NOT_SETTABLE = WINHTTP_ERROR_BASE + 11; + ERROR_WINHTTP_SHUTDOWN = WINHTTP_ERROR_BASE + 12; + ERROR_WINHTTP_LOGIN_FAILURE = WINHTTP_ERROR_BASE + 15; + ERROR_WINHTTP_OPERATION_CANCELLED = WINHTTP_ERROR_BASE + 17; + ERROR_WINHTTP_INCORRECT_HANDLE_TYPE = WINHTTP_ERROR_BASE + 18; + ERROR_WINHTTP_INCORRECT_HANDLE_STATE = WINHTTP_ERROR_BASE + 19; + ERROR_WINHTTP_CANNOT_CONNECT = WINHTTP_ERROR_BASE + 29; + ERROR_WINHTTP_CONNECTION_ERROR = WINHTTP_ERROR_BASE + 30; + ERROR_WINHTTP_RESEND_REQUEST = WINHTTP_ERROR_BASE + 32; + ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = WINHTTP_ERROR_BASE + 44; + ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN = WINHTTP_ERROR_BASE + 100; + ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND = WINHTTP_ERROR_BASE + 101; + ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND = WINHTTP_ERROR_BASE + 102; + ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN = WINHTTP_ERROR_BASE + 103; + ERROR_WINHTTP_HEADER_NOT_FOUND = WINHTTP_ERROR_BASE + 150; + ERROR_WINHTTP_INVALID_SERVER_RESPONSE = WINHTTP_ERROR_BASE + 152; + ERROR_WINHTTP_INVALID_HEADER = WINHTTP_ERROR_BASE + 153; + ERROR_WINHTTP_INVALID_QUERY_REQUEST = WINHTTP_ERROR_BASE + 154; + ERROR_WINHTTP_HEADER_ALREADY_EXISTS = WINHTTP_ERROR_BASE + 155; + ERROR_WINHTTP_REDIRECT_FAILED = WINHTTP_ERROR_BASE + 156; + ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR = WINHTTP_ERROR_BASE + 178; + ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT = WINHTTP_ERROR_BASE + 166; + ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = WINHTTP_ERROR_BASE + 167; + ERROR_WINHTTP_NOT_INITIALIZED = WINHTTP_ERROR_BASE + 172; + ERROR_WINHTTP_SECURE_FAILURE = WINHTTP_ERROR_BASE + 175; + + // Certificate security errors. Additional information is provided + // via the WINHTTP_CALLBACK_STATUS_SECURE_FAILURE callback notification. + ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = WINHTTP_ERROR_BASE + 37; + ERROR_WINHTTP_SECURE_CERT_CN_INVALID = WINHTTP_ERROR_BASE + 38; + ERROR_WINHTTP_SECURE_INVALID_CA = WINHTTP_ERROR_BASE + 45; + ERROR_WINHTTP_SECURE_CERT_REV_FAILED = WINHTTP_ERROR_BASE + 57; + ERROR_WINHTTP_SECURE_CHANNEL_ERROR = WINHTTP_ERROR_BASE + 157; + ERROR_WINHTTP_SECURE_INVALID_CERT = WINHTTP_ERROR_BASE + 169; + ERROR_WINHTTP_SECURE_CERT_REVOKED = WINHTTP_ERROR_BASE + 170; + ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE = WINHTTP_ERROR_BASE + 179; + + ERROR_WINHTTP_AUTODETECTION_FAILED = WINHTTP_ERROR_BASE + 180; + ERROR_WINHTTP_HEADER_COUNT_EXCEEDED = WINHTTP_ERROR_BASE + 181; + ERROR_WINHTTP_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 182; + ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 183; + ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW = WINHTTP_ERROR_BASE + 184; + ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = WINHTTP_ERROR_BASE + 185; + ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = WINHTTP_ERROR_BASE + 186; + + +const + WINHTTP_THRIFT_DEFAULTS = WINHTTP_FLAG_NULL_CODEPAGE + or WINHTTP_FLAG_BYPASS_PROXY_CACHE + or WINHTTP_FLAG_ESCAPE_DISABLE; + + +type + IWinHTTPRequest = interface + ['{35C6D9D4-FDCE-42C6-B84C-9294E6FB904C}'] + function Handle : HINTERNET; + function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; + function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; + function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean; + function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD; + function FlushAndReceiveResponse : Boolean; + function ReadData( const dwRead : DWORD) : TBytes; overload; + function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; + end; + + IWinHTTPConnection = interface + ['{1C4F78B5-1525-4788-B638-A0E41BCF4D43}'] + function Handle : HINTERNET; + function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest; + end; + + IWinHTTPSession = interface + ['{B6F8BD98-0605-4A9E-B671-4CB191D74A5E}'] + function Handle : HINTERNET; + function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection; + function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; + end; + + IWinHTTPUrl = interface + ['{78BE977C-4171-4AF5-A250-FD2890205E63}'] + // url parts getter + function GetScheme : UnicodeString; + function GetNumScheme : INTERNET_SCHEME; + function GetHostName : UnicodeString; + function GetPort : INTERNET_PORT; + function GetUserName : UnicodeString; + function GetPassword : UnicodeString; + function GetUrlPath : UnicodeString; + function GetExtraInfo : UnicodeString; + + // url parts setter + procedure SetScheme( const value : UnicodeString); + procedure SetHostName ( const value : UnicodeString); + procedure SetPort( const value : INTERNET_PORT); + procedure SetUserName( const value : UnicodeString); + procedure SetPassword( const value : UnicodeString); + procedure SetUrlPath( const value : UnicodeString); + procedure SetExtraInfo( const value : UnicodeString); + + // url as a whole + function BuildUrl : UnicodeString; + procedure CrackUrl( const value : UnicodeString); + + // url parts + property Scheme : UnicodeString read GetScheme write SetScheme; + property NumScheme : INTERNET_SCHEME read GetNumScheme; // readonly + property HostName : UnicodeString read GetHostName write SetHostName; + property Port : INTERNET_PORT read GetPort write SetPort; + property UserName : UnicodeString read GetUserName write SetUserName; + property Password : UnicodeString read GetPassword write SetPassword; + property UrlPath : UnicodeString read GetUrlPath write SetUrlPath; + property ExtraInfo : UnicodeString read GetExtraInfo write SetExtraInfo; + + // url as a whole + property CompleteURL : UnicodeString read BuildUrl write CrackUrl; + end; + + + + +type + TWinHTTPHandleObjectImpl = class( TInterfacedObject) + strict protected + FHandle : HINTERNET; + function Handle : HINTERNET; + public + constructor Create( const aHandle : HINTERNET); + destructor Destroy; override; + end; + + + TWinHTTPSessionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPSession) + strict protected + + // IWinHTTPSession + function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection; + function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; + + public + constructor Create( const aAgent : UnicodeString; + const aAccessType : DWORD = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; + const aProxy : UnicodeString = ''; + const aProxyBypass : UnicodeString = ''; + const aFlags : DWORD = 0); + destructor Destroy; override; + end; + + + TWinHTTPConnectionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPConnection) + strict protected + FSession : IWinHTTPSession; + + // IWinHTTPConnection + function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest; + + public + constructor Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT); + destructor Destroy; override; + end; + + + TAcceptTypesArray = array of string; + + TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest) + strict protected + FConnection : IWinHTTPConnection; + + // IWinHTTPRequest + function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; + function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; + function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean; + function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD; + function FlushAndReceiveResponse : Boolean; + function ReadData( const dwRead : DWORD) : TBytes; overload; + function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; + + public + constructor Create( const aConnection : IWinHTTPConnection; + const aVerb, aObjName : UnicodeString; + const aVersion : UnicodeString = ''; + const aReferrer : UnicodeString = ''; + const aAcceptTypes : UnicodeString = '*/*'; + const aFlags : DWORD = WINHTTP_THRIFT_DEFAULTS + ); + + destructor Destroy; override; + end; + + + TWinHTTPUrlImpl = class( TInterfacedObject, IWinHTTPUrl) + strict private + FScheme : UnicodeString; + FNumScheme : INTERNET_SCHEME; + FHostName : UnicodeString; + FPort : INTERNET_PORT; + FUserName : UnicodeString; + FPassword : UnicodeString; + FUrlPath : UnicodeString; + FExtraInfo : UnicodeString; + + strict protected + // url parts getter + function GetScheme : UnicodeString; + function GetNumScheme : INTERNET_SCHEME; + function GetHostName : UnicodeString; + function GetPort : INTERNET_PORT; + function GetUserName : UnicodeString; + function GetPassword : UnicodeString; + function GetUrlPath : UnicodeString; + function GetExtraInfo : UnicodeString; + + // url parts setter + procedure SetScheme( const value : UnicodeString); + procedure SetHostName ( const value : UnicodeString); + procedure SetPort( const value : INTERNET_PORT); + procedure SetUserName( const value : UnicodeString); + procedure SetPassword( const value : UnicodeString); + procedure SetUrlPath( const value : UnicodeString); + procedure SetExtraInfo( const value : UnicodeString); + + // url as a whole + function BuildUrl : UnicodeString; + procedure CrackUrl( const value : UnicodeString); + + public + constructor Create( const aUri : UnicodeString); + destructor Destroy; override; + end; + + + EWinHTTPException = class(Exception); + +implementation + +const WINHTTP_DLL = 'WinHTTP.dll'; + +function WinHttpCloseHandle; stdcall; external WINHTTP_DLL; +function WinHttpOpen; stdcall; external WINHTTP_DLL; +function WinHttpConnect; stdcall; external WINHTTP_DLL; +function WinHttpOpenRequest; stdcall; external WINHTTP_DLL; +function WinHttpSendRequest; stdcall; external WINHTTP_DLL; +function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL; +function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL; +function WinHttpWriteData; stdcall; external WINHTTP_DLL; +function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL; +function WinHttpQueryHeaders; stdcall; external WINHTTP_DLL; +function WinHttpQueryDataAvailable; stdcall; external WINHTTP_DLL; +function WinHttpReadData; stdcall; external WINHTTP_DLL; +function WinHttpCrackUrl; stdcall; external WINHTTP_DLL; +function WinHttpCreateUrl; stdcall; external WINHTTP_DLL; + + +{ TWinHTTPHandleObjectImpl } + +constructor TWinHTTPHandleObjectImpl.Create( const aHandle : HINTERNET); +begin + inherited Create; + FHandle := aHandle; + + if FHandle = nil + then raise EWinHTTPException.Create('Invalid handle'); +end; + + +destructor TWinHTTPHandleObjectImpl.Destroy; +begin + try + if Assigned(FHandle) then begin + WinHttpCloseHandle(FHandle); + FHandle := nil; + end; + + finally + inherited Destroy; + end; +end; + + +function TWinHTTPHandleObjectImpl.Handle : HINTERNET; +begin + result := FHandle; +end; + + +{ TWinHTTPSessionImpl } + + +constructor TWinHTTPSessionImpl.Create( const aAgent : UnicodeString; const aAccessType : DWORD; + const aProxy, aProxyBypass : UnicodeString; const aFlags : DWORD); +var handle : HINTERNET; +begin + handle := WinHttpOpen( PWideChar(aAgent), aAccessType, + PWideChar(Pointer(aProxy)), // may be nil + PWideChar(Pointer(aProxyBypass)), // may be nil + aFlags); + inherited Create( handle); +end; + + +destructor TWinHTTPSessionImpl.Destroy; +begin + inherited Destroy; + // add code here +end; + + +function TWinHTTPSessionImpl.Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT) : IWinHTTPConnection; +begin + result := TWinHTTPConnectionImpl.Create( Self, aHostName, aPort); +end; + + +function TWinHTTPSessionImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; +begin + result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout); +end; + + +{ TWinHTTPConnectionImpl } + +constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT); +var handle : HINTERNET; +begin + FSession := aSession; + handle := WinHttpConnect( FSession.Handle, PWideChar(aHostName), aPort, 0); + inherited Create( handle); +end; + + +destructor TWinHTTPConnectionImpl.Destroy; +begin + inherited Destroy; + FSession := nil; +end; + + +function TWinHTTPConnectionImpl.OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest; +var dwFlags : DWORD; +begin + dwFlags := WINHTTP_THRIFT_DEFAULTS; + if secure + then dwFlags := dwFlags or WINHTTP_FLAG_SECURE + else dwFlags := dwFlags and not WINHTTP_FLAG_SECURE; + + result := TWinHTTPRequestImpl.Create( Self, aVerb, aObjName, '', '', aAcceptTypes, dwFlags); +end; + + +{ TWinHTTPRequestImpl } + +constructor TWinHTTPRequestImpl.Create( const aConnection : IWinHTTPConnection; + const aVerb, aObjName, aVersion, aReferrer : UnicodeString; + const aAcceptTypes : UnicodeString; + const aFlags : DWORD + ); +var handle : HINTERNET; + accept : array[0..1] of PWideChar; +begin + FConnection := aConnection; + + accept[0] := PWideChar(aAcceptTypes); + accept[1] := nil; + + handle := WinHttpOpenRequest( FConnection.Handle, + PWideChar(UpperCase(aVerb)), + PWideChar(aObjName), + PWideChar(aVersion), + PWideChar(aReferrer), + @accept, + aFlags); + inherited Create( handle); +end; + + +destructor TWinHTTPRequestImpl.Destroy; +begin + inherited Destroy; + FConnection := nil; +end; + + +function TWinHTTPRequestImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; +begin + result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout); +end; + + +function TWinHTTPRequestImpl.AddRequestHeader( const aHeader : string; const addflag : DWORD) : Boolean; +begin + result := WinHttpAddRequestHeaders( FHandle, PWideChar(aHeader), DWORD(-1), addflag); +end; + + +function TWinHTTPRequestImpl.SendRequest( const pBuf : Pointer; const dwBytes, dwExtra : DWORD) : Boolean; +begin + result := WinHttpSendRequest( FHandle, + WINHTTP_NO_ADDITIONAL_HEADERS, 0, + pBuf, dwBytes, // number of bytes in pBuf + dwBytes + dwExtra, // becomes the Content-Length + nil); // context for async operations +end; + + +function TWinHTTPRequestImpl.WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD; +begin + if not WinHttpWriteData( FHandle, pBuf, dwBytes, result) + then result := 0; +end; + + +function TWinHTTPRequestImpl.FlushAndReceiveResponse : Boolean; +begin + result := WinHttpReceiveResponse( FHandle, nil); +end; + + +function TWinHTTPRequestImpl.ReadData( const dwRead : DWORD) : TBytes; +var dwAvailable, dwReceived : DWORD; +begin + if WinHttpQueryDataAvailable( FHandle, dwAvailable) + then dwAvailable := Min( dwRead, dwAvailable) + else dwAvailable := 0; + + SetLength( result, dwAvailable); + if dwAvailable = 0 then Exit; + + if WinHttpReadData( FHandle, @result[0], Length(result), dwReceived) + then SetLength( result, dwReceived) + else SetLength( result, 0); +end; + + +function TWinHTTPRequestImpl.ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; +var dwAvailable : DWORD; +begin + if WinHttpQueryDataAvailable( FHandle, dwAvailable) + then dwAvailable := Min( dwRead, dwAvailable) + else dwAvailable := 0; + + if (dwAvailable = 0) + or not WinHttpReadData( FHandle, pBuf, dwAvailable, result) + then result := 0; +end; + + +{ TWinHTTPUrlImpl } + +constructor TWinHTTPUrlImpl.Create(const aUri: UnicodeString); +begin + inherited Create; + CrackUrl( aUri) +end; + + +destructor TWinHTTPUrlImpl.Destroy; +begin + inherited Destroy; +end; + + +procedure TWinHTTPUrlImpl.CrackURL( const value : UnicodeString); +const FLAGS = 0; // no special operations, leave components as-is +var components : URL_COMPONENTS; +begin + FillChar(components, SizeOf(components), 0); + components.dwStructSize := SizeOf(components); + + if value <> '' then begin + { For the WinHttpCrackUrl function, [...] if the pointer member is NULL but the + length member is not zero, both the pointer and length members are returned. } + components.dwSchemeLength := DWORD(-1); + components.dwHostNameLength := DWORD(-1); + components.dwUserNameLength := DWORD(-1); + components.dwPasswordLength := DWORD(-1); + components.dwUrlPathLength := DWORD(-1); + components.dwExtraInfoLength := DWORD(-1); + + WinHttpCrackUrl( PWideChar(value), Length(value), FLAGS, components); + end; + + FNumScheme := components.nScheme; + FPort := components.nPort; + SetString( FScheme, components.lpszScheme, components.dwSchemeLength); + SetString( FHostName, components.lpszHostName, components.dwHostNameLength); + SetString( FUserName, components.lpszUserName, components.dwUserNameLength); + SetString( FPassword, components.lpszPassword, components.dwPasswordLength); + SetString( FUrlPath, components.lpszUrlPath, components.dwUrlPathLength); + SetString( FExtraInfo, components.lpszExtraInfo, components.dwExtraInfoLength); +end; + + +function TWinHTTPUrlImpl.BuildUrl : UnicodeString; +const FLAGS = 0; // no special operations, leave components as-is +var components : URL_COMPONENTS; + dwChars : DWORD; +begin + FillChar(components, SizeOf(components), 0); + components.dwStructSize := SizeOf(components); + components.lpszScheme := PWideChar(FScheme); + components.dwSchemeLength := Length(FScheme); + components.lpszHostName := PWideChar(FHostName); + components.dwHostNameLength := Length(FHostName); + components.nPort := FPort; + components.lpszUserName := PWideChar(FUserName); + components.dwUserNameLength := Length(FUserName); + components.lpszPassword := PWideChar(FPassword); + components.dwPasswordLength := Length(FPassword); + components.lpszUrlPath := PWideChar(FUrlPath); + components.dwUrlPathLength := Length(FUrlPath); + components.lpszExtraInfo := PWideChar(FExtraInfo); + components.dwExtraInfoLength := Length(FExtraInfo); + + WinHttpCreateUrl( components, FLAGS, nil, dwChars); + if dwChars = 0 + then result := '' + else begin + SetLength( result, dwChars + 1); + WinHttpCreateUrl( components, FLAGS, @result[1], dwChars); + SetLength( result, dwChars); // cut off terminating #0 + end; +end; + + +function TWinHTTPUrlImpl.GetExtraInfo: UnicodeString; +begin + result := FExtraInfo; +end; + +function TWinHTTPUrlImpl.GetHostName: UnicodeString; +begin + result := FHostName; +end; + +function TWinHTTPUrlImpl.GetNumScheme: INTERNET_SCHEME; +begin + result := FNumScheme; +end; + +function TWinHTTPUrlImpl.GetPassword: UnicodeString; +begin + result := FPassword; +end; + +function TWinHTTPUrlImpl.GetPort: INTERNET_PORT; +begin + result := FPort; +end; + +function TWinHTTPUrlImpl.GetScheme: UnicodeString; +begin + result := FScheme; +end; + +function TWinHTTPUrlImpl.GetUrlPath: UnicodeString; +begin + result := FUrlPath; +end; + +function TWinHTTPUrlImpl.GetUserName: UnicodeString; +begin + result := FUserName; +end; + +procedure TWinHTTPUrlImpl.SetExtraInfo(const value: UnicodeString); +begin + FExtraInfo := value; +end; + +procedure TWinHTTPUrlImpl.SetHostName(const value: UnicodeString); +begin + FHostName := value; +end; + +procedure TWinHTTPUrlImpl.SetPassword(const value: UnicodeString); +begin + FPassword := value; +end; + +procedure TWinHTTPUrlImpl.SetPort(const value: INTERNET_PORT); +begin + FPort := value; +end; + +procedure TWinHTTPUrlImpl.SetScheme(const value: UnicodeString); +begin + FScheme := value; +end; + +procedure TWinHTTPUrlImpl.SetUrlPath(const value: UnicodeString); +begin + FUrlPath := value; +end; + +procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString); +begin + FUserName := value; +end; + + +end. + diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas index 7b603a3445b..55bf92b705f 100644 --- a/lib/delphi/test/TestClient.pas +++ b/lib/delphi/test/TestClient.pas @@ -43,6 +43,8 @@ interface Thrift.Protocol.JSON, Thrift.Protocol, Thrift.Transport.Pipes, + Thrift.Transport.WinHTTP, + Thrift.Transport.MsxmlHTTP, Thrift.Transport, Thrift.Stream, Thrift.Test, @@ -115,6 +117,7 @@ TClientThread = class( TThread ) procedure InitializeProtocolTransportStack; procedure ShutdownProtocolTransportStack; + function InitializeHttpTransport( const aTimeoutSetting : Integer) : IHTTPClient; procedure JSONProtocolReadWriteTest; function PrepareBinaryData( aRandomDist : Boolean; aSize : TTestSize) : TBytes; @@ -188,7 +191,7 @@ class procedure TTestClient.PrintCmdLineHelp; + ' instead of host and port'#10 + ' --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe)'#10 + ' --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles)'#10 - + ' --transport arg (=sockets) Transport: buffered, framed, http, evhttp'#10 + + ' --transport arg (=sockets) Transport: buffered, framed, http, winhttp'#10 + ' --protocol arg (=binary) Protocol: binary, compact, json'#10 + ' --ssl Encrypted Transport using SSL'#10 + ' -n [ --testloops ] arg (=1) Number of Tests'#10 @@ -274,14 +277,15 @@ class function TTestClient.Execute(const args: array of string) : Byte; Console.WriteLine('Using anonymous pipes ('+IntToStr(Integer(setup.hAnonRead))+' and '+IntToStr(Integer(setup.hAnonWrite))+')'); end else if s = '--transport' then begin - // --transport arg (=sockets) Transport: buffered, framed, http, evhttp + // --transport arg (=sockets) Transport: buffered, framed, http, winhttp, evhttp s := args[i]; Inc( i); if s = 'buffered' then Include( setup.layered, trns_Buffered) else if s = 'framed' then Include( setup.layered, trns_Framed) - else if s = 'http' then setup.endpoint := trns_Http - else if s = 'evhttp' then setup.endpoint := trns_EvHttp + else if s = 'http' then setup.endpoint := trns_MsXmlHttp + else if s = 'winhttp' then setup.endpoint := trns_WinHttp + else if s = 'evhttp' then setup.endpoint := trns_EvHttp // recognized, but not supported else InvalidArgs; end else if s = '--protocol' then begin @@ -1315,11 +1319,41 @@ procedure TClientThread.Execute; end; +function TClientThread.InitializeHttpTransport( const aTimeoutSetting : Integer) : IHTTPClient; +var sUrl : string; +begin + ASSERT( FSetup.endpoint in [trns_MsxmlHttp, trns_WinHttp]); + + if FSetup.useSSL + then sUrl := 'https://' + else sUrl := 'http://'; + + sUrl := sUrl + FSetup.host; + + case FSetup.port of + 80 : if FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port); + 443 : if not FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port); + else + if FSetup.port > 0 then sUrl := sUrl + ':'+ IntToStr(FSetup.port); + end; + + Console.WriteLine('Target URL: '+sUrl); + case FSetup.endpoint of + trns_MsxmlHttp : result := TMsxmlHTTPClientImpl.Create( sUrl); + trns_WinHttp : result := TWinHTTPClientImpl.Create( sUrl); + else + raise Exception.Create(ENDPOINT_TRANSPORTS[FSetup.endpoint]+' unhandled case'); + end; + + result.DnsResolveTimeout := aTimeoutSetting; + result.ConnectionTimeout := aTimeoutSetting; + result.SendTimeout := aTimeoutSetting; + result.ReadTimeout := aTimeoutSetting; +end; + + procedure TClientThread.InitializeProtocolTransportStack; -var - streamtrans : IStreamTransport; - http : IHTTPClient; - sUrl : string; +var streamtrans : IStreamTransport; const DEBUG_TIMEOUT = 30 * 1000; RELEASE_TIMEOUT = DEFAULT_THRIFT_TIMEOUT; @@ -1336,24 +1370,10 @@ procedure TClientThread.InitializeProtocolTransportStack; FTransport := streamtrans; end; - trns_Http: begin + trns_MsxmlHttp, + trns_WinHttp: begin Console.WriteLine('Using HTTPClient'); - if FSetup.useSSL - then sUrl := 'https://' - else sUrl := 'http://'; - sUrl := sUrl + FSetup.host; - case FSetup.port of - 80 : if FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port); - 443 : if not FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port); - else - if FSetup.port > 0 then sUrl := sUrl + ':'+ IntToStr(FSetup.port); - end; - http := THTTPClientImpl.Create( sUrl); - http.DnsResolveTimeout := HTTP_TIMEOUTS; - http.ConnectionTimeout := HTTP_TIMEOUTS; - http.SendTimeout := HTTP_TIMEOUTS; - http.ReadTimeout := HTTP_TIMEOUTS; - FTransport := http; + FTransport := InitializeHttpTransport( HTTP_TIMEOUTS); end; trns_EvHttp: begin diff --git a/lib/delphi/test/TestConstants.pas b/lib/delphi/test/TestConstants.pas index 37969dc205a..6bb20e96f3f 100644 --- a/lib/delphi/test/TestConstants.pas +++ b/lib/delphi/test/TestConstants.pas @@ -39,7 +39,8 @@ interface TEndpointTransport = ( trns_Sockets, - trns_Http, + trns_MsxmlHttp, + trns_WinHttp, trns_NamedPipes, trns_AnonPipes, trns_EvHttp // as listed on http://thrift.apache.org/test @@ -63,7 +64,7 @@ interface = ('Buffered', 'Framed'); ENDPOINT_TRANSPORTS : array[TEndpointTransport] of string - = ('Sockets', 'Http', 'Named Pipes','Anon Pipes', 'EvHttp'); + = ('Sockets', 'Http', 'WinHttp', 'Named Pipes','Anon Pipes', 'EvHttp'); // defaults are: read=false, write=true BINARY_STRICT_READ = FALSE; diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas index 69cb17521d2..374472c945e 100644 --- a/lib/delphi/test/TestServer.pas +++ b/lib/delphi/test/TestServer.pas @@ -592,7 +592,8 @@ class procedure TTestServer.Execute( const args: array of string); if s = 'buffered' then Include( layered, trns_Buffered) else if s = 'framed' then Include( layered, trns_Framed) - else if s = 'http' then endpoint := trns_Http + else if s = 'http' then endpoint := trns_MsxmlHttp + else if s = 'winhttp' then endpoint := trns_WinHttp else if s = 'anonpipe' then endpoint := trns_AnonPipes else InvalidArgs; end @@ -650,8 +651,9 @@ class procedure TTestServer.Execute( const args: array of string); servertrans := TServerSocketImpl.Create( Port, 0, (trns_Buffered in layered)); end; - trns_Http : begin - raise Exception.Create(ENDPOINT_TRANSPORTS[endpoint]+' server transport not implemented'); + trns_MsxmlHttp, + trns_WinHttp : begin + raise Exception.Create('HTTP server transport not implemented'); end; trns_NamedPipes : begin diff --git a/lib/delphi/test/client.dpr b/lib/delphi/test/client.dpr index 06dbd3df767..1d1607de7a0 100644 --- a/lib/delphi/test/client.dpr +++ b/lib/delphi/test/client.dpr @@ -31,6 +31,8 @@ uses Thrift.Socket in '..\src\Thrift.Socket.pas', Thrift.Exception in '..\src\Thrift.Exception.pas', Thrift.Transport.Pipes in '..\src\Thrift.Transport.Pipes.pas', + Thrift.Transport.WinHTTP in '..\src\Thrift.Transport.WinHTTP.pas', + Thrift.Transport.MsxmlHTTP in '..\src\Thrift.Transport.MsxmlHTTP.pas', Thrift.Protocol in '..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\src\Thrift.Protocol.JSON.pas', Thrift.Protocol.Compact in '..\src\Thrift.Protocol.Compact.pas', @@ -39,6 +41,7 @@ uses Thrift.Server in '..\src\Thrift.Server.pas', Thrift.Stream in '..\src\Thrift.Stream.pas', Thrift.TypeRegistry in '..\src\Thrift.TypeRegistry.pas', + Thrift.WinHTTP in '..\src\Thrift.WinHTTP.pas', Thrift.Utils in '..\src\Thrift.Utils.pas'; var diff --git a/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr b/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr index 4278d8f0c58..a57e93a2ef8 100644 --- a/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr +++ b/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr @@ -36,6 +36,7 @@ uses Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', + Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas'; var diff --git a/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr b/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr index 120462bf955..81ed3ddc4fc 100644 --- a/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr +++ b/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr @@ -36,6 +36,7 @@ uses Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', + Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas'; diff --git a/lib/delphi/test/serializer/TestSerializer.dpr b/lib/delphi/test/serializer/TestSerializer.dpr index 51e22a4cf90..1f5ae8bbbd5 100644 --- a/lib/delphi/test/serializer/TestSerializer.dpr +++ b/lib/delphi/test/serializer/TestSerializer.dpr @@ -34,6 +34,7 @@ uses Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.Serializer in '..\..\src\Thrift.Serializer.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas', + Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', System_, DebugProtoTest, diff --git a/lib/delphi/test/server.dpr b/lib/delphi/test/server.dpr index b5e48a6b6e6..9731dd4fada 100644 --- a/lib/delphi/test/server.dpr +++ b/lib/delphi/test/server.dpr @@ -40,6 +40,7 @@ uses Thrift.Server in '..\src\Thrift.Server.pas', Thrift.TypeRegistry in '..\src\Thrift.TypeRegistry.pas', Thrift.Utils in '..\src\Thrift.Utils.pas', + Thrift.WinHTTP in '..\src\Thrift.WinHTTP.pas', Thrift.Stream in '..\src\Thrift.Stream.pas'; var diff --git a/lib/delphi/test/skip/skiptest_version1.dpr b/lib/delphi/test/skip/skiptest_version1.dpr index 803d6bd00fd..0bfe96fef04 100644 --- a/lib/delphi/test/skip/skiptest_version1.dpr +++ b/lib/delphi/test/skip/skiptest_version1.dpr @@ -33,6 +33,7 @@ uses Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', + Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas'; diff --git a/lib/delphi/test/skip/skiptest_version2.dpr b/lib/delphi/test/skip/skiptest_version2.dpr index 633b247edf2..7893748a06f 100644 --- a/lib/delphi/test/skip/skiptest_version2.dpr +++ b/lib/delphi/test/skip/skiptest_version2.dpr @@ -33,6 +33,7 @@ uses Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', + Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas'; diff --git a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr b/lib/delphi/test/typeregistry/TestTypeRegistry.dpr index 18a7c7df3e6..fd5e3dd4e03 100644 --- a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr +++ b/lib/delphi/test/typeregistry/TestTypeRegistry.dpr @@ -34,6 +34,7 @@ uses Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.Serializer in '..\..\src\Thrift.Serializer.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas', + Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', DebugProtoTest; diff --git a/tutorial/delphi/DelphiClient/DelphiClient.dpr b/tutorial/delphi/DelphiClient/DelphiClient.dpr index 74d0d45c6a5..4ea9eb3e992 100644 --- a/tutorial/delphi/DelphiClient/DelphiClient.dpr +++ b/tutorial/delphi/DelphiClient/DelphiClient.dpr @@ -32,6 +32,9 @@ uses Thrift.Protocol in '..\..\..\lib\delphi\src\Thrift.Protocol.pas', Thrift.Server in '..\..\..\lib\delphi\src\Thrift.Server.pas', Thrift.Transport in '..\..\..\lib\delphi\src\Thrift.Transport.pas', + Thrift.Transport.WinHTTP in '..\..\..\lib\delphi\src\Thrift.Transport.WinHTTP.pas', + Thrift.Transport.MsxmlHTTP in '..\..\..\lib\delphi\src\Thrift.Transport.MsxmlHTTP.pas', + Thrift.WinHTTP in '..\..\..\lib\delphi\src\Thrift.WinHTTP.pas', Shared in '..\..\gen-delphi\Shared.pas', Tutorial in '..\..\gen-delphi\Tutorial.pas'; diff --git a/tutorial/delphi/DelphiClient/DelphiClient.dproj b/tutorial/delphi/DelphiClient/DelphiClient.dproj index 0680be28d73..7026747d07b 100644 --- a/tutorial/delphi/DelphiClient/DelphiClient.dproj +++ b/tutorial/delphi/DelphiClient/DelphiClient.dproj @@ -58,6 +58,9 @@ + + + diff --git a/tutorial/delphi/DelphiServer/DelphiServer.dpr b/tutorial/delphi/DelphiServer/DelphiServer.dpr index 5f42e7e1089..fc9997a3fb3 100644 --- a/tutorial/delphi/DelphiServer/DelphiServer.dpr +++ b/tutorial/delphi/DelphiServer/DelphiServer.dpr @@ -34,6 +34,7 @@ uses Thrift.Protocol in '..\..\..\lib\delphi\src\Thrift.Protocol.pas', Thrift.Server in '..\..\..\lib\delphi\src\Thrift.Server.pas', Thrift.Transport in '..\..\..\lib\delphi\src\Thrift.Transport.pas', + Thrift.WinHTTP in '..\..\..\lib\delphi\src\Thrift.WinHTTP.pas', Shared in '..\..\gen-delphi\Shared.pas', Tutorial in '..\..\gen-delphi\Tutorial.pas'; diff --git a/tutorial/delphi/DelphiServer/DelphiServer.dproj b/tutorial/delphi/DelphiServer/DelphiServer.dproj index 97d5617a301..ec1da2e693c 100644 --- a/tutorial/delphi/DelphiServer/DelphiServer.dproj +++ b/tutorial/delphi/DelphiServer/DelphiServer.dproj @@ -57,6 +57,7 @@ + From 181d900a396a199083bf9e06da16214b720aacbc Mon Sep 17 00:00:00 2001 From: Danny Browning Date: Mon, 15 Apr 2019 09:50:24 -0600 Subject: [PATCH 266/756] THRIFT 4536: Rust 1.34.0 Update dockerfiles to use rust stable, call out required rust version in breaking changes. --- CHANGES.md | 1 + build/docker/ubuntu-bionic/Dockerfile | 6 ++---- build/docker/ubuntu-xenial/Dockerfile | 6 ++---- lib/rs/README.md | 8 ++++++++ 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 41434e936c4..df731219440 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -27,6 +27,7 @@ - [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - java: change return type signature of 'process' methods - [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - js: now uses node-int64 for 64 bit integer constants - [THRIFT-4841](https://issues.apache.org/jira/browse/THRIFT-4841) - delphi: old THTTPTransport is now TMsxmlHTTPTransport +- [THRIFT-4536](https://issues.apache.org/jira/browse/THRIFT-4536) - rust: convert from try-from crate to rust stable (1.34+), re-export ordered-float ### Known Issues (Blocker or Critical) diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index aae97475f98..c8131bbb2a0 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -256,10 +256,8 @@ RUN apt-get install -y --no-install-recommends \ ruby-dev \ ruby-bundler -RUN apt-get install -y --no-install-recommends \ -`# Rust dependencies` \ - cargo \ - rustc +# Rust dependencies +RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y # Swift on Linux for cross tests RUN cd / && \ diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index e6069f81c55..97aaaea47f5 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -254,10 +254,8 @@ RUN apt-get install -y --no-install-recommends \ ruby-dev \ ruby-bundler -RUN apt-get install -y --no-install-recommends \ -`# Rust dependencies` \ - cargo \ - rustc +# Rust dependencies +RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y # Clean up RUN rm -rf /var/cache/apt/* && \ diff --git a/lib/rs/README.md b/lib/rs/README.md index 7c37a10bc6c..c8d3643edd8 100644 --- a/lib/rs/README.md +++ b/lib/rs/README.md @@ -46,6 +46,14 @@ It does not currently use any Rust 2018 features. Breaking changes are minimized. When they are made they will be outlined below with transition guidelines. +##### Thrift 0.13.0 +* **[THRIFT-4536]** - Use TryFrom from std, required rust 1.34.0 or higher + + Previously TryFrom was from try_from crate, it is now from the std library, + but this functionality is only available in rust 1.34.0. Additionally, + ordered-float is now re-exported under the thrift module to reduce + possible dependency mismatches. + ##### Thrift 0.12.0 * **[THRIFT-4529]** - Rust enum variants are now camel-cased instead of uppercased to conform to Rust naming conventions From 2135a361a5d3767b6d48c70acff4b2b6577e6d9c Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Tue, 16 Apr 2019 16:27:03 +0200 Subject: [PATCH 267/756] THRIFT-4834 CI error at Haskell: Failed to load interface for 'Network' (#1780) --- lib/hs/thrift.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/hs/thrift.cabal b/lib/hs/thrift.cabal index 84a59acade0..0849b802dc4 100644 --- a/lib/hs/thrift.cabal +++ b/lib/hs/thrift.cabal @@ -42,7 +42,7 @@ Library Build-Depends: base >= 4, base < 5, containers, ghc-prim, attoparsec, binary, bytestring >= 0.10, base64-bytestring, hashable, HTTP, text, hspec-core > 2.4.0, unordered-containers >= 0.2.6, vector >= 0.10.12.2, QuickCheck >= 2.8.2, split if flag(network-uri) - build-depends: network-uri >= 2.6, network >= 2.6 + build-depends: network-uri >= 2.6, network >= 2.6 && < 3.0 else build-depends: network < 2.6 Exposed-Modules: From 2ff952b0af4035bcb71d8d73d9eb75df31983544 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 13 Apr 2019 19:46:54 +0200 Subject: [PATCH 268/756] THRIFT-4816 JSONTransports Context.WriteAsync/ReadAsync are badly named Client: netstd Patch: Jens Geyer This closes #1779 --- lib/netstd/Thrift/Protocol/TJSONProtocol.cs | 34 ++++++++++----------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs index 8e40c481b25..12980527b00 100644 --- a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs @@ -102,7 +102,7 @@ protected async Task ReadJsonSyntaxCharAsync(byte[] bytes, CancellationToken can /// private async Task WriteJsonStringAsync(byte[] bytes, CancellationToken cancellationToken) { - await Context.WriteAsync(cancellationToken); + await Context.WriteConditionalDelimiterAsync(cancellationToken); await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); var len = bytes.Length; @@ -150,7 +150,7 @@ private async Task WriteJsonStringAsync(byte[] bytes, CancellationToken cancella /// private async Task WriteJsonIntegerAsync(long num, CancellationToken cancellationToken) { - await Context.WriteAsync(cancellationToken); + await Context.WriteConditionalDelimiterAsync(cancellationToken); var str = num.ToString(); var escapeNum = Context.EscapeNumbers(); @@ -174,7 +174,7 @@ private async Task WriteJsonIntegerAsync(long num, CancellationToken cancellatio /// private async Task WriteJsonDoubleAsync(double num, CancellationToken cancellationToken) { - await Context.WriteAsync(cancellationToken); + await Context.WriteConditionalDelimiterAsync(cancellationToken); var str = num.ToString("G17", CultureInfo.InvariantCulture); var special = false; @@ -214,7 +214,7 @@ private async Task WriteJsonDoubleAsync(double num, CancellationToken cancellati /// private async Task WriteJsonBase64Async(byte[] bytes, CancellationToken cancellationToken) { - await Context.WriteAsync(cancellationToken); + await Context.WriteConditionalDelimiterAsync(cancellationToken); await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); var len = bytes.Length; @@ -241,7 +241,7 @@ private async Task WriteJsonBase64Async(byte[] bytes, CancellationToken cancella private async Task WriteJsonObjectStartAsync(CancellationToken cancellationToken) { - await Context.WriteAsync(cancellationToken); + await Context.WriteConditionalDelimiterAsync(cancellationToken); await Trans.WriteAsync(TJSONProtocolConstants.LeftBrace, cancellationToken); PushContext(new JSONPairContext(this)); } @@ -254,7 +254,7 @@ private async Task WriteJsonObjectEndAsync(CancellationToken cancellationToken) private async Task WriteJsonArrayStartAsync(CancellationToken cancellationToken) { - await Context.WriteAsync(cancellationToken); + await Context.WriteConditionalDelimiterAsync(cancellationToken); await Trans.WriteAsync(TJSONProtocolConstants.LeftBracket, cancellationToken); PushContext(new JSONListContext(this)); } @@ -405,7 +405,7 @@ private async Task ReadJsonStringAsync(bool skipContext, CancellationTok if (!skipContext) { - await Context.ReadAsync(cancellationToken); + await Context.ReadConditionalDelimiterAsync(cancellationToken); } await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); @@ -516,7 +516,7 @@ private async Task ReadJsonNumericCharsAsync(CancellationToken cancellat /// private async Task ReadJsonIntegerAsync(CancellationToken cancellationToken) { - await Context.ReadAsync(cancellationToken); + await Context.ReadConditionalDelimiterAsync(cancellationToken); if (Context.EscapeNumbers()) { await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); @@ -544,7 +544,7 @@ private async Task ReadJsonIntegerAsync(CancellationToken cancellationToke /// private async Task ReadJsonDoubleAsync(CancellationToken cancellationToken) { - await Context.ReadAsync(cancellationToken); + await Context.ReadConditionalDelimiterAsync(cancellationToken); if (await Reader.PeekAsync(cancellationToken) == TJSONProtocolConstants.Quote[0]) { var arr = await ReadJsonStringAsync(true, cancellationToken); @@ -618,7 +618,7 @@ private async Task ReadJsonBase64Async(CancellationToken cancellationTok private async Task ReadJsonObjectStartAsync(CancellationToken cancellationToken) { - await Context.ReadAsync(cancellationToken); + await Context.ReadConditionalDelimiterAsync(cancellationToken); await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBrace, cancellationToken); PushContext(new JSONPairContext(this)); } @@ -631,7 +631,7 @@ private async Task ReadJsonObjectEndAsync(CancellationToken cancellationToken) private async Task ReadJsonArrayStartAsync(CancellationToken cancellationToken) { - await Context.ReadAsync(cancellationToken); + await Context.ReadConditionalDelimiterAsync(cancellationToken); await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBracket, cancellationToken); PushContext(new JSONListContext(this)); } @@ -807,7 +807,7 @@ public JSONBaseContext(TJsonProtocol proto) Proto = proto; } - public virtual async Task WriteAsync(CancellationToken cancellationToken) + public virtual async Task WriteConditionalDelimiterAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -815,7 +815,7 @@ public virtual async Task WriteAsync(CancellationToken cancellationToken) } } - public virtual async Task ReadAsync(CancellationToken cancellationToken) + public virtual async Task ReadConditionalDelimiterAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -842,7 +842,7 @@ public JSONListContext(TJsonProtocol protocol) { } - public override async Task WriteAsync(CancellationToken cancellationToken) + public override async Task WriteConditionalDelimiterAsync(CancellationToken cancellationToken) { if (_first) { @@ -854,7 +854,7 @@ public override async Task WriteAsync(CancellationToken cancellationToken) } } - public override async Task ReadAsync(CancellationToken cancellationToken) + public override async Task ReadConditionalDelimiterAsync(CancellationToken cancellationToken) { if (_first) { @@ -885,7 +885,7 @@ public JSONPairContext(TJsonProtocol proto) { } - public override async Task WriteAsync(CancellationToken cancellationToken) + public override async Task WriteConditionalDelimiterAsync(CancellationToken cancellationToken) { if (_first) { @@ -899,7 +899,7 @@ public override async Task WriteAsync(CancellationToken cancellationToken) } } - public override async Task ReadAsync(CancellationToken cancellationToken) + public override async Task ReadConditionalDelimiterAsync(CancellationToken cancellationToken) { if (_first) { From 8f327f24eeb6ca4c2cdb99a8c5e5a1ce93b29bf6 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 27 Apr 2019 11:20:17 +0200 Subject: [PATCH 269/756] THRIFT-4853 TServerFramedTransport is now obsolete and can be removed Client: netstd Patch: Jens Geyer This closes #1789 --- .../Server/TServerFramedTransport.cs | 150 ------------------ 1 file changed, 150 deletions(-) delete mode 100644 lib/netstd/Thrift/Transport/Server/TServerFramedTransport.cs diff --git a/lib/netstd/Thrift/Transport/Server/TServerFramedTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerFramedTransport.cs deleted file mode 100644 index b3b38025a8c..00000000000 --- a/lib/netstd/Thrift/Transport/Server/TServerFramedTransport.cs +++ /dev/null @@ -1,150 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Transport.Client; - -namespace Thrift.Transport.Server -{ - // ReSharper disable once InconsistentNaming - public class TServerFramedTransport : TServerTransport - { - private readonly int _clientTimeout; - private readonly int _port; - private TcpListener _server; - - public TServerFramedTransport(TcpListener listener) - : this(listener, 0) - { - } - - public TServerFramedTransport(TcpListener listener, int clientTimeout) - { - _server = listener; - _clientTimeout = clientTimeout; - } - - public TServerFramedTransport(int port) - : this(port, 0) - { - } - - public TServerFramedTransport(int port, int clientTimeout) - { - _port = port; - _clientTimeout = clientTimeout; - try - { - // Make server socket - _server = new TcpListener(IPAddress.Any, _port); - _server.Server.NoDelay = true; - } - catch (Exception) - { - _server = null; - throw new TTransportException("Could not create ServerSocket on port " + port + "."); - } - } - - public override void Listen() - { - // Make sure not to block on accept - if (_server != null) - { - try - { - _server.Start(); - } - catch (SocketException sx) - { - throw new TTransportException("Could not accept on listening socket: " + sx.Message); - } - } - } - - public override bool IsClientPending() - { - return _server.Pending(); - } - - protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - if (_server == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); - } - - try - { - TFramedTransport tSocketTransport = null; - var tcpClient = await _server.AcceptTcpClientAsync(); - - try - { - tSocketTransport = new TFramedTransport(new TSocketTransport(tcpClient) - { - Timeout = _clientTimeout - }); - - return tSocketTransport; - } - catch (Exception) - { - if (tSocketTransport != null) - { - tSocketTransport.Dispose(); - } - else // Otherwise, clean it up ourselves. - { - ((IDisposable) tcpClient).Dispose(); - } - - throw; - } - } - catch (Exception ex) - { - throw new TTransportException(ex.ToString()); - } - } - - public override void Close() - { - if (_server != null) - { - try - { - _server.Stop(); - } - catch (Exception ex) - { - throw new TTransportException("WARNING: Could not close server socket: " + ex); - } - _server = null; - } - } - } -} \ No newline at end of file From 366cc3dee0f279b652644ae96b05fabd6fae2e06 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 28 Apr 2019 19:53:32 +0200 Subject: [PATCH 270/756] THRIFT-4854 oneway calls do not work over HTTP Client: netstd Patch: Jens Geyer This closes #1790 --- lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs index b5a500cf76f..056300cfe3d 100644 --- a/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs @@ -100,12 +100,13 @@ public async Task ProcessRequestAsync(HttpContext context, CancellationToken can while (await Processor.ProcessAsync(input, output, cancellationToken)) { + if (!context.Response.HasStarted) // oneway method called + await context.Response.Body.FlushAsync(cancellationToken); } } catch (TTransportException) { - // Client died, just move on - if (!context.Response.HasStarted) + if (!context.Response.HasStarted) // if something goes bust, let the client know context.Response.StatusCode = 500; } finally From cc13de4f87bda658d138b4f9b47f55202be4ac51 Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Wed, 17 Apr 2019 11:00:53 -0400 Subject: [PATCH 271/756] THRIFT-4851: Remove All Calls To printStackTrace Client: Java Patch: Beluga Behr This closes #1783 --- .../org/apache/thrift/server/TNonblockingServer.java | 1 - .../thrift/transport/TNonblockingServerSocket.java | 2 +- .../apache/thrift/transport/TSSLTransportFactory.java | 10 ++++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/java/src/org/apache/thrift/server/TNonblockingServer.java b/lib/java/src/org/apache/thrift/server/TNonblockingServer.java index fe0365a518b..2358c6356d7 100644 --- a/lib/java/src/org/apache/thrift/server/TNonblockingServer.java +++ b/lib/java/src/org/apache/thrift/server/TNonblockingServer.java @@ -239,7 +239,6 @@ private void handleAccept() throws IOException { } 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(); } diff --git a/lib/java/src/org/apache/thrift/transport/TNonblockingServerSocket.java b/lib/java/src/org/apache/thrift/transport/TNonblockingServerSocket.java index ef82ac2c4fb..df37cb06e68 100644 --- a/lib/java/src/org/apache/thrift/transport/TNonblockingServerSocket.java +++ b/lib/java/src/org/apache/thrift/transport/TNonblockingServerSocket.java @@ -103,7 +103,7 @@ public void listen() throws TTransportException { try { serverSocket_.setSoTimeout(0); } catch (SocketException sx) { - sx.printStackTrace(); + LOGGER.error("Socket exception while setting socket timeout", sx); } } } diff --git a/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java b/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java index 2232a315c12..73dfaaf1860 100644 --- a/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java +++ b/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java @@ -37,11 +37,17 @@ import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * A Factory for providing and setting up Client and Server SSL wrapped * TSocket and TServerSocket */ public class TSSLTransportFactory { + + private static final Logger LOGGER = + LoggerFactory.getLogger(TSSLTransportFactory.class); /** * Get a SSL wrapped TServerSocket bound to the specified port. In this @@ -225,14 +231,14 @@ else if (params.isKeyStoreSet) { try { in.close(); } catch (IOException e) { - e.printStackTrace(); + LOGGER.warn("Unable to close stream", e); } } if (is != null) { try { is.close(); } catch (IOException e) { - e.printStackTrace(); + LOGGER.warn("Unable to close stream", e); } } } From 65d5f84507b69118c8c9f664f635652ba00ae346 Mon Sep 17 00:00:00 2001 From: Albert Hives Date: Sat, 20 Apr 2019 07:56:56 -0700 Subject: [PATCH 272/756] renamed TClientTransport.cs file to match its class name TTransport.cs Client: netstd Patch: Albert Hives This closes #1784 --- .../Thrift/Transport/{TClientTransport.cs => TTransport.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/netstd/Thrift/Transport/{TClientTransport.cs => TTransport.cs} (100%) diff --git a/lib/netstd/Thrift/Transport/TClientTransport.cs b/lib/netstd/Thrift/Transport/TTransport.cs similarity index 100% rename from lib/netstd/Thrift/Transport/TClientTransport.cs rename to lib/netstd/Thrift/Transport/TTransport.cs From 8d554f503ee8b10e2a225e4e755158e494d40983 Mon Sep 17 00:00:00 2001 From: Park June Chul Date: Wed, 24 Apr 2019 10:19:01 +0900 Subject: [PATCH 273/756] THRIFT-4859 Enables changing 'UserAgent' Client: C# Patch: Park June Chul This closes #1787 --- lib/csharp/src/Transport/THttpClient.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/csharp/src/Transport/THttpClient.cs b/lib/csharp/src/Transport/THttpClient.cs index 667fc2526c4..986799cd271 100644 --- a/lib/csharp/src/Transport/THttpClient.cs +++ b/lib/csharp/src/Transport/THttpClient.cs @@ -1,4 +1,4 @@ -/** +/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -43,6 +43,7 @@ public class THttpClient : TTransport, IDisposable private int readTimeout = 30000; private IDictionary customHeaders = new Dictionary(); + private string userAgent = "C#/THttpClient"; #if !SILVERLIGHT private IWebProxy proxy = WebRequest.DefaultWebProxy; @@ -52,12 +53,22 @@ public THttpClient(Uri u) : this(u, Enumerable.Empty()) { } + public THttpClient(Uri u, string userAgent) + : this(u, userAgent, Enumerable.Empty()) + { + } public THttpClient(Uri u, IEnumerable certificates) { uri = u; this.certificates = (certificates ?? Enumerable.Empty()).ToArray(); } + public THttpClient(Uri u, string userAgent, IEnumerable certificates) + { + uri = u; + this.userAgent = userAgent; + this.certificates = (certificates ?? Enumerable.Empty()).ToArray(); + } public int ConnectTimeout { @@ -271,7 +282,7 @@ private HttpWebRequest CreateRequest() // Make the request connection.ContentType = "application/x-thrift"; connection.Accept = "application/x-thrift"; - connection.UserAgent = "C#/THttpClient"; + connection.UserAgent = userAgent; connection.Method = "POST"; #if !SILVERLIGHT connection.ProtocolVersion = HttpVersion.Version10; From 27d8387c49a49fcf193893f834e9766ae0b051c1 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 4 May 2019 12:11:52 +0200 Subject: [PATCH 274/756] THRIFT-4860 Allow changing "User-Agent" Client: netstd Patch: Jens Geyer --- .../Thrift/Transport/Client/THttpTransport.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs index 0dd5493efa9..627c93df935 100644 --- a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -41,23 +41,29 @@ public class THttpTransport : TTransport private bool _isDisposed; private MemoryStream _outputStream = new MemoryStream(); - public THttpTransport(Uri u, IDictionary customHeaders = null) - : this(u, Enumerable.Empty(), customHeaders) + public THttpTransport(Uri u, IDictionary customHeaders = null, string userAgent = null) + : this(u, Enumerable.Empty(), customHeaders, userAgent) { } public THttpTransport(Uri u, IEnumerable certificates, - IDictionary customHeaders) + IDictionary customHeaders, string userAgent = null) { _uri = u; _certificates = (certificates ?? Enumerable.Empty()).ToArray(); CustomHeaders = customHeaders; + if (!string.IsNullOrEmpty(userAgent)) + UserAgent = userAgent; + // due to current bug with performance of Dispose in netcore https://github.com/dotnet/corefx/issues/8809 // this can be switched to default way (create client->use->dispose per flush) later _httpClient = CreateClient(); } + // According to RFC 2616 section 3.8, the "User-Agent" header may not carry a version number + public readonly string UserAgent = "Thrift netstd THttpClient"; + public IDictionary CustomHeaders { get; } public int ConnectTimeout @@ -149,7 +155,7 @@ private HttpClient CreateClient() } httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); - httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpTransport", "1.0.0")); + httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd(UserAgent); if (CustomHeaders != null) { @@ -223,4 +229,4 @@ protected override void Dispose(bool disposing) _isDisposed = true; } } -} \ No newline at end of file +} From 9ecdce3fe00931cebda39357b31b655236ab9221 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 3 May 2019 11:24:55 -0400 Subject: [PATCH 275/756] Fix MinGW build issue in AppVeyor --- appveyor.yml | 2 +- build/cmake/BoostMacros.cmake | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 74c92f1fa66..ef729eb2a8a 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -62,7 +62,7 @@ environment: - PROFILE: MINGW PLATFORM: x64 CONFIGURATION: RelWithDebInfo - DISABLED_TESTS: (StressTestNonBlocking) + DISABLED_TESTS: (StalenessCheckTest|StressTestNonBlocking) - PROFILE: CYGWIN PLATFORM: x64 diff --git a/build/cmake/BoostMacros.cmake b/build/cmake/BoostMacros.cmake index 0c7f13dfaf1..61be622eca0 100644 --- a/build/cmake/BoostMacros.cmake +++ b/build/cmake/BoostMacros.cmake @@ -19,14 +19,22 @@ set(BOOST_MINREV 1.53) +# we are not ready for the new style link targets introduced in +# boost 1.70.0 and cmake 3.14.2 which showed up on appveyor in +# mingw builds +set(Boost_NO_BOOST_CMAKE ON) + macro(REQUIRE_BOOST_HEADERS) find_package(Boost ${BOOST_MINREV} QUIET REQUIRED) if (NOT Boost_FOUND) string(CONCAT fatal_message - "Boost 1.53 or later is required to build sources in ${CMAKE_CURRENT_SOURCE_DIR}") + "Boost ${BOOST_MINREV} or later is required to build sources in ${CMAKE_CURRENT_SOURCE_DIR}") message(FATAL_ERROR, ${fatal_message}) endif() - include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") + if (DEFINED Boost_INCLUDE_DIRS) + # pre-boost 1.70.0 aware cmake, otherwise it is using targets + include_directories(SYSTEM "${Boost_INCLUDE_DIRS}") + endif() endmacro() macro(REQUIRE_BOOST_LIBRARIES libs) @@ -34,7 +42,7 @@ macro(REQUIRE_BOOST_LIBRARIES libs) find_package(Boost ${BOOST_MINREV} REQUIRED COMPONENTS ${${libs}}) if (NOT Boost_FOUND) string(CONCAT fatal_message - "Boost 1.53 or later is required to build sources in ${CMAKE_CURRENT_SOURCE_DIR}, " + "Boost ${BOOST_MINREV} or later is required to build sources in ${CMAKE_CURRENT_SOURCE_DIR}, " "or use -DBUILD_TESTING=OFF") message(FATAL_ERROR, ${fatal_message}) endif() From ee8caca54ef51e05c7eee8d67e3c63cd73081e8a Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 4 May 2019 08:20:59 -0400 Subject: [PATCH 276/756] THRIFT-4861: Set minimum boost to 1.56 and stop using deprecated boost predef endian header Client: cpp --- build/cmake/BoostMacros.cmake | 2 +- configure.ac | 2 +- debian/control | 4 ++-- doc/install/README.md | 4 ++-- doc/install/centos.md | 8 ++++---- lib/cpp/src/thrift/protocol/TProtocol.h | 17 ++++++++++------- 6 files changed, 20 insertions(+), 17 deletions(-) diff --git a/build/cmake/BoostMacros.cmake b/build/cmake/BoostMacros.cmake index 61be622eca0..cc50b53db09 100644 --- a/build/cmake/BoostMacros.cmake +++ b/build/cmake/BoostMacros.cmake @@ -17,7 +17,7 @@ # under the License. # -set(BOOST_MINREV 1.53) +set(BOOST_MINREV 1.56) # we are not ready for the new style link targets introduced in # boost 1.70.0 and cmake 3.14.2 which showed up on appveyor in diff --git a/configure.ac b/configure.ac index b09c98361dd..5f25a5cf390 100755 --- a/configure.ac +++ b/configure.ac @@ -158,7 +158,7 @@ AM_CONDITIONAL(WITH_AS3, [test "$have_as3" = "yes"]) AX_THRIFT_LIB(cpp, [C++], yes) have_cpp=no if test "$with_cpp" = "yes"; then - AX_BOOST_BASE([1.53.0]) + AX_BOOST_BASE([1.56.0]) if test "x$succeeded" = "xyes" ; then AC_SUBST([BOOST_LIB_DIR], [$(echo "$BOOST_LDFLAGS" | sed -e 's/^\-L//')]) AC_SUBST([BOOST_CHRONO_LDADD], [$(echo "$BOOST_LIB_DIR/libboost_chrono.a")]) diff --git a/debian/control b/debian/control index 9de66fc272a..414a815fee2 100644 --- a/debian/control +++ b/debian/control @@ -3,11 +3,11 @@ Section: devel Priority: extra Build-Depends: debhelper (>= 9), build-essential, mono-mcs, python-dev, ant, mono-devel, libmono-system-web4.0-cil, erlang-base, ruby-dev | ruby1.9.1-dev, ruby-bundler ,autoconf, automake, - pkg-config, libtool, bison, flex, libboost-dev | libboost1.53-dev | libboost1.63-all-dev, + pkg-config, libtool, bison, flex, libboost-dev | libboost1.56-dev | libboost1.63-all-dev, python-all, python-setuptools, python-all-dev, python-all-dbg, python3-all, python3-setuptools, python3-all-dev, python3-all-dbg, openjdk-8-jdk | openjdk-8-jdk-headless | openjdk-11-jdk | openjdk-11-jdk-headless | default-jdk, - libboost-test-dev | libboost-test1.53-dev | libboost-test1.63-dev, libevent-dev, libssl-dev, perl (>= 5.8.0-7), + libboost-test-dev | libboost-test1.56-dev | libboost-test1.63-dev, libevent-dev, libssl-dev, perl (>= 5.8.0-7), php (>= 5), php-dev (>= 5), libglib2.0-dev, qtchooser, qtbase5-dev-tools Maintainer: Thrift Developer's Homepage: http://thrift.apache.org/ diff --git a/doc/install/README.md b/doc/install/README.md index 22231cd67fe..e48cc4a12c0 100644 --- a/doc/install/README.md +++ b/doc/install/README.md @@ -3,7 +3,7 @@ * A relatively POSIX-compliant *NIX system * Cygwin or MinGW can be used on Windows (but there are better options, see below) * g++ 4.2 -* boost 1.53.0 +* boost 1.56.0 * Runtime libraries for lex and yacc might be needed for the compiler. ## Requirements for building from source @@ -23,7 +23,7 @@ These are only required if you choose to build the libraries for the given language * C++ - * Boost 1.53.0 + * Boost 1.56.0 * libevent (optional, to build the nonblocking server) * zlib (optional) * Java diff --git a/doc/install/centos.md b/doc/install/centos.md index 04932c20a7e..18282a3a189 100644 --- a/doc/install/centos.md +++ b/doc/install/centos.md @@ -54,11 +54,11 @@ If you will be developing Apache Thrift clients/servers in C++ you will also nee sudo yum -y install libevent-devel zlib-devel openssl-devel -### Upgrade Boost >= 1.53 +### Upgrade Boost >= 1.56 - wget http://sourceforge.net/projects/boost/files/boost/1.53.0/boost_1_53_0.tar.gz - tar xvf boost_1_53_0.tar.gz - cd boost_1_53_0 + wget http://sourceforge.net/projects/boost/files/boost/1.56.0/boost_1_56_0.tar.gz + tar xvf boost_1_56_0.tar.gz + cd boost_1_56_0 ./bootstrap.sh sudo ./b2 install diff --git a/lib/cpp/src/thrift/protocol/TProtocol.h b/lib/cpp/src/thrift/protocol/TProtocol.h index 7566a258f41..df9c5c39baf 100644 --- a/lib/cpp/src/thrift/protocol/TProtocol.h +++ b/lib/cpp/src/thrift/protocol/TProtocol.h @@ -88,15 +88,18 @@ static inline To bitwise_cast(From from) { # define __THRIFT_LITTLE_ENDIAN LITTLE_ENDIAN # define __THRIFT_BIG_ENDIAN BIG_ENDIAN # else -# include -# include -# define __THRIFT_BYTE_ORDER BOOST_BYTE_ORDER +# include +# if BOOST_ENDIAN_BIG_BYTE +# define __THRIFT_BYTE_ORDER 4321 +# define __THRIFT_LITTLE_ENDIAN 0 +# define __THRIFT_BIG_ENDIAN __THRIFT_BYTE_ORDER +# elif BOOST_ENDIAN_LITTLE_BYTE +# define __THRIFT_BYTE_ORDER 1234 +# define __THRIFT_LITTLE_ENDIAN __THRIFT_BYTE_ORDER +# define __THRIFT_BIG_ENDIAN 0 +# endif # ifdef BOOST_LITTLE_ENDIAN -# define __THRIFT_LITTLE_ENDIAN __THRIFT_BYTE_ORDER -# define __THRIFT_BIG_ENDIAN 0 # else -# define __THRIFT_LITTLE_ENDIAN 0 -# define __THRIFT_BIG_ENDIAN __THRIFT_BYTE_ORDER # endif # endif #endif From acdd4226c210336e9e15eb812e5932a645fcd5ce Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 4 May 2019 15:56:56 -0400 Subject: [PATCH 277/756] Remove unused THREADMODEL from MSVC appveyor build --- build/appveyor/MSVC-appveyor-build.bat | 3 +-- build/appveyor/cl_setenv.bat | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/build/appveyor/MSVC-appveyor-build.bat b/build/appveyor/MSVC-appveyor-build.bat index 892daa17aeb..3d2bbeed308 100644 --- a/build/appveyor/MSVC-appveyor-build.bat +++ b/build/appveyor/MSVC-appveyor-build.bat @@ -51,8 +51,7 @@ CD "%BUILDDIR%" || EXIT /B -DOPENSSL_USE_STATIC_LIBS=OFF ^ -DZLIB_LIBRARY="%WIN3P%\zlib-inst\lib\zlib%ZLIB_LIB_SUFFIX%.lib" ^ -DZLIB_ROOT="%WIN3P%\zlib-inst" ^ - -DWITH_PYTHON=%WITH_PYTHON% ^ - -DWITH_%THREADMODEL%THREADS=ON || EXIT /B + -DWITH_PYTHON=%WITH_PYTHON% || EXIT /B @ECHO OFF cmake --build . ^ diff --git a/build/appveyor/cl_setenv.bat b/build/appveyor/cl_setenv.bat index da4d4ee4fb3..98931a6031d 100644 --- a/build/appveyor/cl_setenv.bat +++ b/build/appveyor/cl_setenv.bat @@ -52,8 +52,6 @@ IF "%PROFILE:~0,4%" == "MSVC" ( SET OPENSSL_ROOT=C:\OpenSSL-Win%NORM_PLATFORM% SET WIN3P=%APPVEYOR_BUILD_FOLDER%\thirdparty - SET THREADMODEL=STD - IF "%PYTHON_VERSION%" == "" ( SET WITH_PYTHON=OFF ) ELSE ( From 14a9a120a859c2e101bcd5f529693139bf9aef7a Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 9 May 2019 23:29:24 +0200 Subject: [PATCH 278/756] THRIFT-4863 better indication of WinHTTP errors Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.WinHTTP.pas | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index 0d824b6184f..6ad84006656 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -497,6 +497,7 @@ constructor TWinHTTPSessionImpl.Create( const aAgent : UnicodeString; const aAcc PWideChar(Pointer(aProxy)), // may be nil PWideChar(Pointer(aProxyBypass)), // may be nil aFlags); + if handle = nil then RaiseLastOSError; inherited Create( handle); end; @@ -527,6 +528,7 @@ constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; con begin FSession := aSession; handle := WinHttpConnect( FSession.Handle, PWideChar(aHostName), aPort, 0); + if handle = nil then RaiseLastOSError; inherited Create( handle); end; @@ -572,6 +574,7 @@ constructor TWinHTTPRequestImpl.Create( const aConnection : IWinHTTPConnection; PWideChar(aReferrer), @accept, aFlags); + if handle = nil then RaiseLastOSError; inherited Create( handle); end; From 8f7487e1086d8da6baff3376679436e526dd8fd0 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 9 May 2019 22:21:32 +0200 Subject: [PATCH 279/756] THRIFT-4862 better ToString() support for enums and container types Client: Delphi Patch: Jens Geyer This closes #1795 --- .../src/thrift/generate/t_delphi_generator.cc | 8 +- lib/delphi/src/Thrift.Collections.pas | 87 +++++++++++- lib/delphi/src/Thrift.Protocol.pas | 25 +--- lib/delphi/src/Thrift.Utils.pas | 75 +++++++++- lib/delphi/test/TestServer.pas | 129 +++++------------- 5 files changed, 194 insertions(+), 130 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc index 505120e40c2..11501bf523c 100644 --- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc @@ -1743,7 +1743,7 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, if (is_exception && (!is_x_factory)) { out << "TException"; } else { - out << "TInterfacedObject, IBase, " << struct_intf_name; + out << "TInterfacedObject, IBase, ISupportsToString, " << struct_intf_name; } out << ")" << endl; @@ -3949,8 +3949,10 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out, << ".Append('') else " << tmp_sb << ".Append( Self." << prop_name((*f_iter), is_exception) << ".ToString());" << endl; } else if (ttype->is_enum()) { - indent_impl(out) << tmp_sb << ".Append(System.Integer( Self." << prop_name((*f_iter), is_exception) - << "));" << endl; + indent_impl(out) << tmp_sb << ".Append(EnumUtils<" + << type_name(ttype, false, true, is_exception, true) + << ">.ToString( System.Ord( Self." + << prop_name((*f_iter), is_exception) << ")));" << endl; } else { indent_impl(out) << tmp_sb << ".Append( Self." << prop_name((*f_iter), is_exception) << ");" << endl; diff --git a/lib/delphi/src/Thrift.Collections.pas b/lib/delphi/src/Thrift.Collections.pas index b2206cbf0a1..2e137247e92 100644 --- a/lib/delphi/src/Thrift.Collections.pas +++ b/lib/delphi/src/Thrift.Collections.pas @@ -22,7 +22,7 @@ interface uses - Generics.Collections, Generics.Defaults, Thrift.Utils; + SysUtils, Generics.Collections, Generics.Defaults, Thrift.Utils; type @@ -30,11 +30,11 @@ interface TArray = array of T; {$IFEND} - IThriftContainer = interface - ['{93DEF5A0-D162-461A-AB22-5B4EE0734050}'] - function ToString: string; + IThriftContainer = interface( ISupportsToString) + ['{E05C0F9D-A4F5-491D-AADA-C926B4BDB6E4}'] end; + IThriftDictionary = interface(IThriftContainer) ['{25EDD506-F9D1-4008-A40F-5940364B7E46}'] function GetEnumerator: TEnumerator>; @@ -64,7 +64,7 @@ interface property Values: TDictionary.TValueCollection read GetValues; end; - TThriftDictionaryImpl = class( TInterfacedObject, IThriftDictionary) + TThriftDictionaryImpl = class( TInterfacedObject, IThriftDictionary, IThriftContainer, ISupportsToString) private FDictionaly : TDictionary; protected @@ -95,6 +95,7 @@ TThriftDictionaryImpl = class( TInterfacedObject, IThriftDictiona public constructor Create(ACapacity: Integer = 0); destructor Destroy; override; + function ToString : string; override; end; IThriftList = interface(IThriftContainer) @@ -140,7 +141,7 @@ TThriftDictionaryImpl = class( TInterfacedObject, IThriftDictiona property Items[Index: Integer]: T read GetItem write SetItem; default; end; - TThriftListImpl = class( TInterfacedObject, IThriftList) + TThriftListImpl = class( TInterfacedObject, IThriftList, IThriftContainer, ISupportsToString) private FList : TList; protected @@ -186,6 +187,7 @@ TThriftListImpl = class( TInterfacedObject, IThriftList) public constructor Create; destructor Destroy; override; + function ToString : string; override; end; IHashSet = interface(IThriftContainer) @@ -202,7 +204,7 @@ TThriftListImpl = class( TInterfacedObject, IThriftList) function Remove( const item: TValue ): Boolean; end; - THashSetImpl = class( TInterfacedObject, IHashSet) + THashSetImpl = class( TInterfacedObject, IHashSet, IThriftContainer, ISupportsToString) private FDictionary : IThriftDictionary; FIsReadOnly: Boolean; @@ -219,6 +221,7 @@ THashSetImpl = class( TInterfacedObject, IHashSet) function Remove( const item: TValue ): Boolean; public constructor Create; + function ToString : string; override; end; implementation @@ -287,6 +290,28 @@ function THashSetImpl.Remove( const item: TValue): Boolean; end; end; +function THashSetImpl.ToString : string; +var elm : TValue; + sb : TThriftStringBuilder; + first : Boolean; +begin + sb := TThriftStringBuilder.Create('{'); + try + first := TRUE; + for elm in FDictionary.Keys do begin + if first + then first := FALSE + else sb.Append(', '); + + sb.Append( StringUtils.ToString(elm)); + end; + sb.Append('}'); + Result := sb.ToString; + finally + sb.Free; + end; +end; + { TThriftDictionaryImpl } procedure TThriftDictionaryImpl.Add(const Key: TKey; @@ -393,6 +418,32 @@ function TThriftDictionaryImpl.ToArray: TArray {$IFEND} end; +function TThriftDictionaryImpl.ToString : string; +var pair : TPair; + sb : TThriftStringBuilder; + first : Boolean; +begin + sb := TThriftStringBuilder.Create('{'); + try + first := TRUE; + for pair in FDictionaly do begin + if first + then first := FALSE + else sb.Append(', '); + + sb.Append( '('); + sb.Append( StringUtils.ToString(pair.Key)); + sb.Append(' => '); + sb.Append( StringUtils.ToString(pair.Value)); + sb.Append(')'); + end; + sb.Append('}'); + Result := sb.ToString; + finally + sb.Free; + end; +end; + procedure TThriftDictionaryImpl.TrimExcess; begin FDictionaly.TrimExcess; @@ -611,6 +662,28 @@ function TThriftListImpl.ToArray: TArray; {$IFEND} end; +function TThriftListImpl.ToString : string; +var elm : T; + sb : TThriftStringBuilder; + first : Boolean; +begin + sb := TThriftStringBuilder.Create('{'); + try + first := TRUE; + for elm in FList do begin + if first + then first := FALSE + else sb.Append(', '); + + sb.Append( StringUtils.ToString(elm)); + end; + sb.Append('}'); + Result := sb.ToString; + finally + sb.Free; + end; +end; + procedure TThriftListImpl.TrimExcess; begin FList.TrimExcess; diff --git a/lib/delphi/src/Thrift.Protocol.pas b/lib/delphi/src/Thrift.Protocol.pas index 36509ca1882..609dfc60504 100644 --- a/lib/delphi/src/Thrift.Protocol.pas +++ b/lib/delphi/src/Thrift.Protocol.pas @@ -29,6 +29,7 @@ interface Contnrs, Thrift.Exception, Thrift.Stream, + Thrift.Utils, Thrift.Collections, Thrift.Transport; @@ -111,12 +112,6 @@ TThriftSet = record function GetProtocol( const trans: ITransport): IProtocol; end; - TThriftStringBuilder = class( TStringBuilder) - public - function Append(const Value: TBytes): TStringBuilder; overload; - function Append(const Value: IThriftContainer): TStringBuilder; overload; - end; - TProtocolException = class( TException) public const // TODO(jensg): change into enum @@ -292,9 +287,8 @@ TProtocolImpl = class abstract( TInterfacedObject, IProtocol) constructor Create( trans: ITransport ); end; - IBase = interface - ['{08D9BAA8-5EAA-410F-B50B-AC2E6E5E4155}'] - function ToString: string; + IBase = interface( ISupportsToString) + ['{AFF6CECA-5200-4540-950E-9B89E0C1C00C}'] procedure Read( const iprot: IProtocol); procedure Write( const iprot: IProtocol); end; @@ -1034,19 +1028,6 @@ constructor TProtocolExceptionSpecialized.Create(const Msg: string); inherited HiddenCreate(Msg); end; -{ TThriftStringBuilder } - -function TThriftStringBuilder.Append(const Value: TBytes): TStringBuilder; -begin - Result := Append( string( RawByteString(Value)) ); -end; - -function TThriftStringBuilder.Append( - const Value: IThriftContainer): TStringBuilder; -begin - Result := Append( Value.ToString ); -end; - { TBinaryProtocolImpl.TFactory } constructor TBinaryProtocolImpl.TFactory.Create(AStrictRead, AStrictWrite: Boolean); diff --git a/lib/delphi/src/Thrift.Utils.pas b/lib/delphi/src/Thrift.Utils.pas index 7e57863b6fb..46e238cdd42 100644 --- a/lib/delphi/src/Thrift.Utils.pas +++ b/lib/delphi/src/Thrift.Utils.pas @@ -25,12 +25,19 @@ interface uses {$IFDEF OLD_UNIT_NAMES} - Classes, Windows, SysUtils, Character, SyncObjs; + Classes, Windows, SysUtils, Character, SyncObjs, TypInfo, Rtti; {$ELSE} - System.Classes, Winapi.Windows, System.SysUtils, System.Character, System.SyncObjs; + System.Classes, Winapi.Windows, System.SysUtils, System.Character, + System.SyncObjs, System.TypInfo, System.Rtti; {$ENDIF} type + ISupportsToString = interface + ['{AF71C350-E0CD-4E94-B77C-0310DC8227FF}'] + function ToString : string; + end; + + IOverlappedHelper = interface ['{A1832EFA-2E02-4884-8F09-F0A0277157FA}'] function Overlapped : TOverlapped; @@ -55,6 +62,13 @@ TOverlappedHelperImpl = class( TInterfacedObject, IOverlappedHelper) end; + TThriftStringBuilder = class( TStringBuilder) + public + function Append(const Value: TBytes): TStringBuilder; overload; + function Append(const Value: ISupportsToString): TStringBuilder; overload; + end; + + Base64Utils = class sealed public class function Encode( const src : TBytes; srcOff, len : Integer; dst : TBytes; dstOff : Integer) : Integer; static; @@ -68,6 +82,16 @@ CharUtils = class sealed class function IsLowSurrogate( const c : Char) : Boolean; static; inline; end; + EnumUtils = class sealed + public + class function ToString(const value : Integer) : string; reintroduce; static; inline; + end; + + StringUtils = class sealed + public + class function ToString(const value : T) : string; reintroduce; static; inline; + end; + {$IFDEF Win64} function InterlockedExchangeAdd64( var Addend : Int64; Value : Int64) : Int64; @@ -256,4 +280,51 @@ function InterlockedExchangeAdd64( var Addend : Int64; Value : Int64) : Int64; {$ENDIF} +{ EnumUtils } + +class function EnumUtils.ToString(const value : Integer) : string; +var pType : PTypeInfo; +begin + pType := PTypeInfo(TypeInfo(T)); + if Assigned(pType) and (pType^.Kind = tkEnumeration) + then result := GetEnumName(pType,value) + else result := IntToStr(Ord(value)); +end; + + +{ StringUtils } + +class function StringUtils.ToString(const value : T) : string; +var pType : PTypeInfo; + base : ISupportsToString; +begin + pType := PTypeInfo(TypeInfo(T)); + if Assigned(pType) then begin + case pType^.Kind of + tkInterface : begin + if Supports(IInterface(value), ISupportsToString, base) then begin + result := base.toString; + Exit; + end; + end; + end; + end; + + result := TValue.From(value).ToString; +end; + + +{ TThriftStringBuilder } + +function TThriftStringBuilder.Append(const Value: TBytes): TStringBuilder; +begin + Result := Append( string( RawByteString(Value)) ); +end; + +function TThriftStringBuilder.Append( const Value: ISupportsToString): TStringBuilder; +begin + Result := Append( Value.ToString ); +end; + + end. diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas index 374472c945e..4cb00907362 100644 --- a/lib/delphi/test/TestServer.pas +++ b/lib/delphi/test/TestServer.pas @@ -150,7 +150,7 @@ function TTestServer.TTestHandlerImpl.testBinary(const thing: TBytes): TBytes; function TTestServer.TTestHandlerImpl.testEnum(thing: TNumberz): TNumberz; begin - Console.WriteLine('testEnum(' + IntToStr( Integer( thing)) + ')'); + Console.WriteLine('testEnum(' + EnumUtils.ToString(Ord(thing)) + ')'); Result := thing; end; @@ -191,7 +191,10 @@ function TTestServer.TTestHandlerImpl.testInsanity( insane : IThriftDictionary>; begin - Console.WriteLine('testInsanity()'); + Console.Write('testInsanity('); + if argument <> nil then Console.Write(argument.ToString); + Console.WriteLine(')'); + (** * So you think you've got this all worked, out eh? @@ -222,49 +225,20 @@ function TTestServer.TTestHandlerImpl.testInsanity( Result := insane; end; -function TTestServer.TTestHandlerImpl.testList( - const thing: IThriftList): IThriftList; -var - first : Boolean; - elem : Integer; +function TTestServer.TTestHandlerImpl.testList( const thing: IThriftList): IThriftList; begin - Console.Write('testList({'); - first := True; - for elem in thing do - begin - if first then - begin - first := False; - end else - begin - Console.Write(', '); - end; - Console.Write( IntToStr( elem)); - end; - Console.WriteLine('})'); + Console.Write('testList('); + if thing <> nil then Console.Write(thing.ToString); + Console.WriteLine(')'); Result := thing; end; function TTestServer.TTestHandlerImpl.testMap( const thing: IThriftDictionary): IThriftDictionary; -var - first : Boolean; - key : Integer; begin - Console.Write('testMap({'); - first := True; - for key in thing.Keys do - begin - if (first) then - begin - first := false; - end else - begin - Console.Write(', '); - end; - Console.Write(IntToStr(key) + ' => ' + IntToStr( thing[key])); - end; - Console.WriteLine('})'); + Console.Write('testMap('); + if thing <> nil then Console.Write(thing.ToString); + Console.WriteLine(')'); Result := thing; end; @@ -313,12 +287,11 @@ function TTestServer.TTestHandlerImpl.testMultiException( const arg0, arg1: stri x2 : TXception2; begin Console.WriteLine('testMultiException(' + arg0 + ', ' + arg1 + ')'); - if ( arg0 = 'Xception') then - begin + if ( arg0 = 'Xception') then begin raise TXception.Create( 1001, 'This is an Xception'); // test the new rich CTOR - end else - if ( arg0 = 'Xception2') then - begin + end; + + if ( arg0 = 'Xception2') then begin x2 := TXception2.Create; // the old way still works too? x2.ErrorCode := 2002; x2.Struct_thing := TXtructImpl.Create; @@ -332,17 +305,11 @@ function TTestServer.TTestHandlerImpl.testMultiException( const arg0, arg1: stri end; function TTestServer.TTestHandlerImpl.testNest( const thing: IXtruct2): IXtruct2; -var - temp : IXtruct; begin - temp := thing.Struct_thing; - Console.WriteLine('testNest({' + - IntToStr( thing.Byte_thing) + ', {' + - '"' + temp.String_thing + '", ' + - IntToStr( temp.Byte_thing) + ', ' + - IntToStr( temp.I32_thing) + ', ' + - IntToStr( temp.I64_thing) + '}, ' + - IntToStr( temp.I32_thing) + '})'); + Console.Write('testNest('); + if thing <> nil then Console.Write(thing.ToString); + Console.WriteLine(')'); + Result := thing; end; @@ -353,34 +320,18 @@ procedure TTestServer.TTestHandlerImpl.testOneway(secondsToSleep: Integer); Console.WriteLine('testOneway finished'); end; -function TTestServer.TTestHandlerImpl.testSet( - const thing: IHashSet):IHashSet; -var - first : Boolean; - elem : Integer; +function TTestServer.TTestHandlerImpl.testSet( const thing: IHashSet):IHashSet; begin - Console.Write('testSet({'); - first := True; + Console.Write('testSet('); + if thing <> nil then Console.Write(thing.ToString); + Console.WriteLine(')');; - for elem in thing do - begin - if first then - begin - first := False; - end else - begin - Console.Write( ', '); - end; - Console.Write( IntToStr( elem)); - end; - Console.WriteLine('})'); Result := thing; end; procedure TTestServer.TTestHandlerImpl.testStop; begin - if FServer <> nil then - begin + if FServer <> nil then begin FServer.Stop; end; end; @@ -399,24 +350,11 @@ function TTestServer.TTestHandlerImpl.testString( const thing: string): string; function TTestServer.TTestHandlerImpl.testStringMap( const thing: IThriftDictionary): IThriftDictionary; -var - first : Boolean; - key : string; begin - Console.Write('testStringMap({'); - first := True; - for key in thing.Keys do - begin - if (first) then - begin - first := false; - end else - begin - Console.Write(', '); - end; - Console.Write(key + ' => ' + thing[key]); - end; - Console.WriteLine('})'); + Console.Write('testStringMap('); + if thing <> nil then Console.Write(thing.ToString); + Console.WriteLine(')'); + Result := thing; end; @@ -433,11 +371,10 @@ procedure TTestServer.TTestHandlerImpl.TestVoid; function TTestServer.TTestHandlerImpl.testStruct( const thing: IXtruct): IXtruct; begin - Console.WriteLine('testStruct({' + - '"' + thing.String_thing + '", ' + - IntToStr( thing.Byte_thing) + ', ' + - IntToStr( thing.I32_thing) + ', ' + - IntToStr( thing.I64_thing)); + Console.Write('testStruct('); + if thing <> nil then Console.Write(thing.ToString); + Console.WriteLine(')'); + Result := thing; end; From e0e1a088d6857fd5ca9044c0a330fb2ad54020b4 Mon Sep 17 00:00:00 2001 From: "D. Can Celasun" Date: Fri, 10 May 2019 09:18:11 +0200 Subject: [PATCH 280/756] THRIFT-4855: Pin golang/mock to 1.2.0 The latest version (1.3.0) requires us to switch to Go modules for our tests, but that's not trivial given our directory structure. For now, just fix the CI issues by pinning the version. --- test/go/Makefile.am | 3 +-- test/go/genmock.sh | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 test/go/genmock.sh diff --git a/test/go/Makefile.am b/test/go/Makefile.am index 6da83394bea..3cf6a70ee59 100644 --- a/test/go/Makefile.am +++ b/test/go/Makefile.am @@ -58,8 +58,7 @@ check: gopath genmock GOPATH=`pwd` $(GO) test -v common/... genmock: gopath - GOPATH=`pwd` $(GO) install github.com/golang/mock/mockgen - GOPATH=`pwd` bin/mockgen -destination=src/common/mock_handler.go -package=common gen/thrifttest ThriftTest + sh genmock.sh EXTRA_DIST = \ src/bin \ diff --git a/test/go/genmock.sh b/test/go/genmock.sh new file mode 100644 index 00000000000..3ba41b9ed5b --- /dev/null +++ b/test/go/genmock.sh @@ -0,0 +1,15 @@ +#!/bin/sh +set -e + +export GOPATH=`pwd` +export GOBIN=`pwd`/bin +export GO111MODULE=off + +mkdir -p src/github.com/golang/mock +cd src/github.com/golang +curl -fsSL https://github.com/golang/mock/archive/v1.2.0.tar.gz -o mock.tar.gz +tar -xzvf mock.tar.gz -C mock --strip-components=1 +cd mock/mockgen +go install . +cd ../../../../../ +bin/mockgen -destination=src/common/mock_handler.go -package=common gen/thrifttest ThriftTest From 85431d9c6a4695c5fbdeccc34e60de6c6ecf7225 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 10 May 2019 21:17:00 +0200 Subject: [PATCH 281/756] THRIFT-4862 better ToString() support for enums and container types Client: Delphi Patch: Jens Geyer --- compiler/cpp/src/thrift/generate/t_delphi_generator.cc | 2 +- lib/delphi/src/Thrift.Utils.pas | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc index 11501bf523c..4a2ebdaafb5 100644 --- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc @@ -3950,7 +3950,7 @@ void t_delphi_generator::generate_delphi_struct_tostring_impl(ostream& out, << prop_name((*f_iter), is_exception) << ".ToString());" << endl; } else if (ttype->is_enum()) { indent_impl(out) << tmp_sb << ".Append(EnumUtils<" - << type_name(ttype, false, true, is_exception, true) + << type_name(ttype, false, true, false, false) << ">.ToString( System.Ord( Self." << prop_name((*f_iter), is_exception) << ")));" << endl; } else { diff --git a/lib/delphi/src/Thrift.Utils.pas b/lib/delphi/src/Thrift.Utils.pas index 46e238cdd42..11c4f3e71fb 100644 --- a/lib/delphi/src/Thrift.Utils.pas +++ b/lib/delphi/src/Thrift.Utils.pas @@ -295,15 +295,18 @@ class function EnumUtils.ToString(const value : Integer) : string; { StringUtils } class function StringUtils.ToString(const value : T) : string; +type PInterface = ^IInterface; var pType : PTypeInfo; - base : ISupportsToString; + stos : ISupportsToString; + pIntf : PInterface; // Workaround: Rio does not allow the direct typecast begin pType := PTypeInfo(TypeInfo(T)); if Assigned(pType) then begin case pType^.Kind of tkInterface : begin - if Supports(IInterface(value), ISupportsToString, base) then begin - result := base.toString; + pIntf := PInterface(@value); + if Supports( pIntf^, ISupportsToString, stos) then begin + result := stos.toString; Exit; end; end; From 522f873e1ee916d599c61c274e13fa0f31a8b12d Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 10 May 2019 15:17:33 -0400 Subject: [PATCH 282/756] Update and fix js dependencies --- lib/js/package.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/js/package.json b/lib/js/package.json index a10aaf1e6e8..309622dfda8 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -11,21 +11,21 @@ "repository": "https://github.com/apache/thrift", "license": "Apache-2.0", "devDependencies": { - "browserify": "^16.2.3", - "grunt": "^1.0.3", - "grunt-cli": "^1.3.2", - "grunt-contrib-concat": "^1.0.1", - "grunt-contrib-jshint": "^1.0.0", - "grunt-contrib-qunit": "^3.1.0", - "grunt-contrib-uglify": "^1.0.1", - "grunt-jsdoc": "^2.2.1", - "grunt-shell-spawn": "^0.4.0", - "jslint": "^0.12.0", - "node-int64": "^0.4.0" + "browserify": "~16.2", + "grunt": "~1.0", + "grunt-cli": "~1.3", + "grunt-contrib-concat": "~1.0", + "grunt-contrib-jshint": "~2.1", + "grunt-contrib-qunit": "~3.1", + "grunt-contrib-uglify": "~4.0", + "grunt-jsdoc": "~2.3", + "grunt-shell-spawn": "~0.4", + "jslint": "~0.12", + "node-int64": "~0.4.0" }, "dependencies": { - "jsdoc": "^3.5.5", - "json-int64": "^1.0.0", - "nopt": "^4.0.1" + "jsdoc": "~3.5", + "json-int64": "~1.0", + "nopt": "~4.0" } } From a5dbb011fd5682db3406c91d02f17d9d019daa77 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 11 May 2019 15:39:57 +0200 Subject: [PATCH 283/756] THRIFT-4864 CI fails at netstd Client: netstd Patch: Jens Geyer This closes #1798 --- lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs b/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs index a74f42b39c0..970ce7ecec5 100644 --- a/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs +++ b/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs @@ -36,7 +36,7 @@ public class TJSONProtocolTests [TestMethod] public void TJSONProtocol_Can_Create_Instance_Test() { - var httpClientTransport = Substitute.For(new Uri("http://localhost"), null); + var httpClientTransport = Substitute.For(new Uri("http://localhost"), null, null); var result = new TJSONProtocolWrapper(httpClientTransport); From f3d4d51d429015cd14229ae16b242038dffe5fa4 Mon Sep 17 00:00:00 2001 From: Sergey Elin Date: Sat, 11 May 2019 19:33:15 +0300 Subject: [PATCH 284/756] Add missing autogenerated comment to header files Client: erl --- compiler/cpp/src/thrift/generate/t_erl_generator.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/cpp/src/thrift/generate/t_erl_generator.cc b/compiler/cpp/src/thrift/generate/t_erl_generator.cc index d331eccc3fc..910a38a2308 100644 --- a/compiler/cpp/src/thrift/generate/t_erl_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_erl_generator.cc @@ -295,7 +295,8 @@ void t_erl_generator::init_generator() { * Boilerplate at beginning and end of header files */ void t_erl_generator::hrl_header(ostream& out, string name) { - out << "-ifndef(_" << name << "_included)." << endl << "-define(_" << name << "_included, yeah)." + out << erl_autogen_comment() << endl + << "-ifndef(_" << name << "_included)." << endl << "-define(_" << name << "_included, yeah)." << endl; } From ce32ed70124f4213894f2c0cfdb76bf624ce62b6 Mon Sep 17 00:00:00 2001 From: Sergey Elin Date: Sun, 5 May 2019 20:14:43 +0300 Subject: [PATCH 285/756] Report error for abnormal server termination only Client: erl --- lib/erl/src/thrift_socket_server.erl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/erl/src/thrift_socket_server.erl b/lib/erl/src/thrift_socket_server.erl index 4e3c052bffb..432e65b563e 100644 --- a/lib/erl/src/thrift_socket_server.erl +++ b/lib/erl/src/thrift_socket_server.erl @@ -278,9 +278,13 @@ handle_cast(stop, State) -> terminate(Reason, #thrift_socket_server{listen=Listen, port=Port}) -> gen_tcp:close(Listen), - {backtrace, Bt} = erlang:process_info(self(), backtrace), - error_logger:error_report({?MODULE, ?LINE, - {child_error, Reason, Bt}}), + case Reason of + normal -> ok; + shutdown -> ok; + _ -> {backtrace, Bt} = erlang:process_info(self(), backtrace), + error_logger:error_report({?MODULE, ?LINE, + {child_error, Reason, Bt}}) + end, case Port < 1024 of true -> catch fdsrv:stop(), From b808a11559644cc385fe403a06ef8c626149b9b1 Mon Sep 17 00:00:00 2001 From: Aaron Goldman Date: Mon, 22 Apr 2019 13:35:23 -0700 Subject: [PATCH 286/756] Make Field definition follow Literal definition I think this is a violation of your Literal syntax. Could you explain what i'm missing in the language definition? Is this supposed to be a litteral '='? Literal ::= ('"' [^"]* '"') | ("'" [^']* "'") --- doc/specs/idl.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/specs/idl.md b/doc/specs/idl.md index 524f4e72f5a..ac353681951 100644 --- a/doc/specs/idl.md +++ b/doc/specs/idl.md @@ -96,7 +96,7 @@ A service provides the interface for a set of functionality provided by a Thrift ## Field - [16] Field ::= FieldID? FieldReq? FieldType Identifier ('= ConstValue)? XsdFieldOptions ListSeparator? + [16] Field ::= FieldID? FieldReq? FieldType Identifier ('=' ConstValue)? XsdFieldOptions ListSeparator? ### Field ID From 4ffe76351eac93fa2f2632241544e10e80b2b11e Mon Sep 17 00:00:00 2001 From: Sergey Yelin Date: Thu, 18 Apr 2019 17:27:46 +0300 Subject: [PATCH 287/756] THRIFT-4583: Switch to rebar3 Client: erl --- .gitignore | 5 ++++- configure.ac | 2 +- lib/erl/Makefile.am | 10 +++------- lib/erl/rebar.config | 2 ++ lib/erl/rebar.test.config | 5 ----- 5 files changed, 10 insertions(+), 14 deletions(-) delete mode 100644 lib/erl/rebar.test.config diff --git a/.gitignore b/.gitignore index 135b085495c..fb7651e9aee 100644 --- a/.gitignore +++ b/.gitignore @@ -211,15 +211,18 @@ project.lock.json /lib/delphi/**/*.2007 /lib/delphi/**/*.dproj /lib/delphi/**/codegen/*.bat +/lib/erl/_build/ /lib/erl/.eunit /lib/erl/.generated /lib/erl/.rebar/ -/lib/erl/deps/ +/lib/erl/_build/ /lib/erl/ebin +/lib/erl/rebar.lock /lib/erl/src/thrift.app.src /lib/erl/test/*.beam /lib/erl/test/*.hrl /lib/erl/test/Thrift_omit_without.thrift +/lib/erl/rebar.lock /lib/haxe/test/bin /lib/haxe/test/data.tmp /lib/hs/dist diff --git a/configure.ac b/configure.ac index 5f25a5cf390..391cdb33566 100755 --- a/configure.ac +++ b/configure.ac @@ -250,7 +250,7 @@ AX_THRIFT_LIB(erlang, [Erlang], yes) if test "$with_erlang" = "yes"; then AC_ERLANG_PATH_ERL AC_ERLANG_PATH_ERLC - AC_PATH_PROG([REBAR], [rebar]) + AC_PATH_PROG([REBAR], [rebar3]) if test -n "$ERLC" ; then AC_ERLANG_SUBST_LIB_DIR # Install into the detected Erlang directory instead of $libdir/erlang/lib diff --git a/lib/erl/Makefile.am b/lib/erl/Makefile.am index fdfc9eb6b12..d4544a3392a 100644 --- a/lib/erl/Makefile.am +++ b/lib/erl/Makefile.am @@ -49,13 +49,10 @@ $(THRIFT_OMIT_FILE): test/Thrift_omit_with.thrift touch .generated all: .generated - $(REBAR) get-deps $(REBAR) compile check: .generated - $(REBAR) -C rebar.test.config get-deps - $(REBAR) -C rebar.test.config compile - $(REBAR) -C rebar.test.config skip_deps=true eunit + $(REBAR) eunit install: all mkdir -p $(DESTDIR)$(ERLANG_INSTALL_LIB_DIR_thrift) ; \ @@ -73,7 +70,7 @@ clean-local: $(REBAR) clean $(RM) .generated $(RM) -r .rebar/ - $(RM) -r deps/ + $(RM) -r _build/ $(RM) -r test/gen-erl/ $(RM) $(THRIFT_OMIT_FILE) @@ -83,7 +80,7 @@ maintainer-clean-local: dist-hook: $(RM) $(distdir)/.generated $(RM) -r $(distdir)/.rebar/ - $(RM) -r $(distdir)/deps/ + $(RM) -r $(distdir)/_build/ $(RM) -r $(distdir)/ebin/ $(RM) -r $(distdir)/test/gen-erl/ $(RM) $(distdir)/$(THRIFT_OMIT_FILE) @@ -94,7 +91,6 @@ EXTRA_DIST = \ coding_standards.md \ rebar.config \ rebar.config.script \ - rebar.test.config \ test \ README.md diff --git a/lib/erl/rebar.config b/lib/erl/rebar.config index 1ea18a4312f..1b32947a5a3 100644 --- a/lib/erl/rebar.config +++ b/lib/erl/rebar.config @@ -1 +1,3 @@ {erl_opts, [{platform_define, "^R.*", otp16_or_less}, debug_info]}. + +{profiles, [{test, [{deps, [meck]}]}]}. diff --git a/lib/erl/rebar.test.config b/lib/erl/rebar.test.config deleted file mode 100644 index 2ff2afbb119..00000000000 --- a/lib/erl/rebar.test.config +++ /dev/null @@ -1,5 +0,0 @@ -{erl_opts, [{platform_define, "^R.*", otp16_or_less}, debug_info]}. - -{deps, [ - {meck, "", {git, "https://github.com/eproxus/meck.git", {tag, "0.8.9"}}} -]}. From 6ba58e9a662e9c61b63e1bff68b374d6bba848ce Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 13 May 2019 07:21:21 -0400 Subject: [PATCH 288/756] Update README [ci skip] --- README.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d09e6e104d0..2e8a28a9644 100644 --- a/README.md +++ b/README.md @@ -4,22 +4,27 @@ Apache Thrift Introduction ============ -Thrift is a lightweight, language-independent software stack with an -associated code generation mechanism for point-to-point RPC. Thrift provides -clean abstractions for data transport, data serialization, and application -level processing. The code generation system takes a simple definition -language as input and generates code across programming languages that -uses the abstracted stack to build interoperable RPC clients and servers. +Thrift is a lightweight, language-independent software stack for +point-to-point RPC implementation. +Thrift provides clean abstractions and implementations for data transport, +data serialization, and application level processing. The code generation +system takes a simple definition language as input and generates code +across programming languages that uses the abstracted stack to build +interoperable RPC clients and servers. ![Apache Thrift Layered Architecture](doc/images/thrift-layers.png) Thrift makes it easy for programs written in different programming languages to share data and call remote procedures. With support -for [25 programming languages](LANGUAGES.md), chances are Thrift +for [28 programming languages](LANGUAGES.md), chances are Thrift supports the languages that you currently use. Thrift is specifically designed to support non-atomic version changes -across client and server code. +across client and server code. This allows you to upgrade your +server while still being able service older clients; or have newer +clients issue requests to older servers. An excellent community-provided +write-up about thrift and compatibility when versioning an API can be +found in the [Thrift Missing Guide](https://diwakergupta.github.io/thrift-missing-guide/#_versioning_compatibility). For more details on Thrift's design and implementation, see the Thrift whitepaper included in this distribution, or at the README.md file @@ -30,7 +35,8 @@ Status | Branch | Travis | Appveyor | Coverity Scan | codecov.io | Website | | :----- | :----- | :------- | :------------ | :--------- | :------ | -| [`master`](https://github.com/apache/thrift/tree/master) | [![Build Status](https://travis-ci.org/apache/thrift.svg?branch=master)](https://travis-ci.org/apache/thrift) | [![Build status](https://ci.appveyor.com/api/projects/status/github/apache/thrift?branch=master&svg=true)](https://ci.appveyor.com/project/ApacheSoftwareFoundation/thrift/history) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/1345/badge.svg)](https://scan.coverity.com/projects/thrift) | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://thrift.apache.org/) | +| [`master`](https://github.com/apache/thrift/tree/master) | [![Build Status](https://travis-ci.org/apache/thrift.svg?branch=master)](https://travis-ci.org/apache/thrift/branches) | [![Build status](https://ci.appveyor.com/api/projects/status/github/apache/thrift?branch=master&svg=true)](https://ci.appveyor.com/project/ApacheSoftwareFoundation/thrift/history) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/1345/badge.svg)](https://scan.coverity.com/projects/thrift) | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://thrift.apache.org/) | +| [`0.12.0`](https://github.com/apache/thrift/tree/0.12.0) | [![Build Status](https://travis-ci.org/apache/thrift.svg?branch=0.12.0)](https://travis-ci.org/apache/thrift/branches) | | | | | Releases ======== From 6b6a8279aba29a67f005f5e498e88519cdb85049 Mon Sep 17 00:00:00 2001 From: Garret Wilson Date: Fri, 3 May 2019 13:12:16 -0700 Subject: [PATCH 289/756] THRIFT-4857: Made Java TField class hash code consistent with equals. Client: java --- lib/java/src/org/apache/thrift/protocol/TField.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/java/src/org/apache/thrift/protocol/TField.java b/lib/java/src/org/apache/thrift/protocol/TField.java index 31331bba36b..3872b008fb3 100644 --- a/lib/java/src/org/apache/thrift/protocol/TField.java +++ b/lib/java/src/org/apache/thrift/protocol/TField.java @@ -21,7 +21,7 @@ /** * Helper class that encapsulates field metadata. - * + *

Two fields are considered equal if they have the same type and id.

*/ public class TField { public TField() { @@ -47,7 +47,6 @@ 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; } From b261f3c0f114be31ef0f9a103dc4d2baa7c4fc3f Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 13 May 2019 08:04:09 -0400 Subject: [PATCH 290/756] THRIFT-4857: [java] added a unit test for TField --- .../apache/thrift/protocol/TestTField.java | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 lib/java/test/org/apache/thrift/protocol/TestTField.java diff --git a/lib/java/test/org/apache/thrift/protocol/TestTField.java b/lib/java/test/org/apache/thrift/protocol/TestTField.java new file mode 100644 index 00000000000..f72c25972ae --- /dev/null +++ b/lib/java/test/org/apache/thrift/protocol/TestTField.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 org.apache.thrift.protocol; + +import junit.framework.TestCase; +import static org.junit.Assert.assertNotEquals; + +public abstract class TestTField extends TestCase { + + public void testConstructor() { + TField uut = new TField(); + assertEquals("", uut.name); + assertEquals(TType.STOP, uut.type); + assertEquals(0, uut.id); + + uut = new TField("foo", TType.VOID, (short)42); + assertEquals("foo", uut.name); + assertEquals(TType.VOID, uut.type); + assertEquals(42, uut.id); + } + + public void testEquality() { + TField uut1 = new TField(); + TField uut2 = new TField(); + assertEquals(uut1, uut2); + assertEquals(uut1.hashCode(), uut2.hashCode()); + + uut1 = new TField("foo", TType.I32, (short)1); + uut2 = new TField("foo", TType.I32, (short)2); + assertNotEquals(uut1, uut2); + assertNotEquals(uut1.hashCode(), uut2.hashCode()); + + uut1 = new TField("foo", TType.VOID, (short)1); + uut2 = new TField("foo", TType.I32, (short)1); + assertNotEquals(uut1, uut2); + assertNotEquals(uut1.hashCode(), uut2.hashCode()); + + uut1 = new TField("foo", TType.VOID, (short)5); + uut2 = new TField("bar", TType.I32, (short)5); + assertEquals(uut1, uut2); // name field is ignored + assertEquals(uut1.hashCode(), uut2.hashCode()); + } + +} From 79c23377057f5bbb2d52097eb13073db2d69db8c Mon Sep 17 00:00:00 2001 From: Jeremy Mikkola Date: Thu, 4 Apr 2019 18:03:32 -0700 Subject: [PATCH 291/756] THRIFT-4845: Stop ignoring small timeouts Client: php CURLOPT_TIMEOUT requires a long [0], so it seems that small values like 0.2 are being rounded to 0, resulting in a lack of any timeout. This change uses CURLOPT_TIMEOUT_MS, which the PHP documentation says was "added in cURL 7.16.2. Available since PHP 5.2.3." [0] https://curl.haxx.se/libcurl/c/CURLOPT_TIMEOUT.html --- lib/php/lib/Transport/TCurlClient.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/php/lib/Transport/TCurlClient.php b/lib/php/lib/Transport/TCurlClient.php index 482b43b72cd..2060d34e2e0 100644 --- a/lib/php/lib/Transport/TCurlClient.php +++ b/lib/php/lib/Transport/TCurlClient.php @@ -230,7 +230,12 @@ public function flush() curl_setopt(self::$curlHandle, CURLOPT_HTTPHEADER, $headers); if ($this->timeout_ > 0) { - curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT, $this->timeout_); + if ($this->timeout_ < 1.0) { + // Timestamps smaller than 1 second are ignored when CURLOPT_TIMEOUT is used + curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT_MS, 1000 * $this->timeout_); + } else { + curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT, $this->timeout_); + } } curl_setopt(self::$curlHandle, CURLOPT_POSTFIELDS, $this->request_); $this->request_ = ''; From c035eca3c672511779440bd0779ce5bc93d5c327 Mon Sep 17 00:00:00 2001 From: Henrik Tudborg Date: Mon, 18 Apr 2016 20:20:10 +0200 Subject: [PATCH 292/756] hotfix: clear the offline queue when once written --- lib/nodejs/lib/thrift/connection.js | 34 ++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/nodejs/lib/thrift/connection.js b/lib/nodejs/lib/thrift/connection.js index 9e5c063cffd..72ecb69559c 100644 --- a/lib/nodejs/lib/thrift/connection.js +++ b/lib/nodejs/lib/thrift/connection.js @@ -74,10 +74,7 @@ var Connection = exports.Connection = function(stream, options) { this.framePos = 0; this.frame = null; self.initialize_retry_vars(); - - self.offline_queue.forEach(function(data) { - self.connection.write(data); - }); + self.flush_offline_queue(); self.emit("connect"); }); @@ -177,6 +174,18 @@ Connection.prototype.initialize_retry_vars = function () { this.attempts = 0; }; +Connection.prototype.flush_offline_queue = function () { + var self = this; + var offline_queue = this.offline_queue; + + // Reset offline queue + this.offline_queue = []; + // Attempt to write queued items + offline_queue.forEach(function(data) { + self.write(data); + }); +}; + Connection.prototype.write = function(data) { if (!this.connected) { this.offline_queue.push(data); @@ -311,10 +320,7 @@ var StdIOConnection = exports.StdIOConnection = function(command, options) { this.frame = null; this.connected = true; - self.offline_queue.forEach(function(data) { - self.connection.write(data); - }); - + self.flush_offline_queue(); this.connection.addListener("error", function(err) { self.emit("error", err); @@ -359,6 +365,18 @@ StdIOConnection.prototype.end = function() { this.connection.end(); }; +StdIOConnection.prototype.flush_offline_queue = function () { + var self = this; + var offline_queue = this.offline_queue; + + // Reset offline queue + this.offline_queue = []; + // Attempt to write queued items + offline_queue.forEach(function(data) { + self.write(data); + }); +}; + StdIOConnection.prototype.write = function(data) { if (!this.connected) { this.offline_queue.push(data); From 370d7513f074d96007006a82fca4d45e72afe4da Mon Sep 17 00:00:00 2001 From: timestee <19310233+timestee@users.noreply.github.com> Date: Mon, 20 May 2019 19:20:42 +0800 Subject: [PATCH 293/756] spelling mistake, perhaps (#1803) [ci skip --- lib/go/thrift/socket.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/go/thrift/socket.go b/lib/go/thrift/socket.go index 8854279651f..88b98f59164 100644 --- a/lib/go/thrift/socket.go +++ b/lib/go/thrift/socket.go @@ -162,5 +162,5 @@ func (p *TSocket) Interrupt() error { func (p *TSocket) RemainingBytes() (num_bytes uint64) { const maxSize = ^uint64(0) - return maxSize // the thruth is, we just don't know unless framed is used + return maxSize // the truth is, we just don't know unless framed is used } From 5a17b13ebcba71181498ac3ccfa1e8aa04018a72 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 26 May 2019 15:53:37 +0200 Subject: [PATCH 294/756] THRIFT-4879 general performance improvements for netstd library Client: netstd Patch: Jens Geyer This closes #1808 --- .gitignore | 4 + .../src/thrift/generate/t_netstd_generator.cc | 26 +- lib/netstd/Thrift/Collections/THashSet.cs | 31 +- .../Thrift/Processor/ITAsyncProcessor.cs | 2 +- .../Thrift/Processor/TMultiplexedProcessor.cs | 4 +- lib/netstd/Thrift/Protocol/TBinaryProtocol.cs | 201 +++++------ .../Thrift/Protocol/TCompactProtocol.cs | 327 +++++++++--------- lib/netstd/Thrift/Protocol/TJSONProtocol.cs | 44 +-- lib/netstd/Thrift/Protocol/TProtocol.cs | 60 ++-- .../Thrift/Protocol/TProtocolDecorator.cs | 32 +- .../Thrift/Server/TServerEventHandler.cs | 4 +- lib/netstd/Thrift/TApplicationException.cs | 2 +- lib/netstd/Thrift/Thrift.csproj | 1 + .../Thrift/Transport/Client/THttpTransport.cs | 3 +- .../Client/TMemoryBufferTransport.cs | 114 +++++- .../Transport/Client/TNamedPipeTransport.cs | 7 +- .../Transport/Client/TStreamTransport.cs | 5 +- .../Server/TNamedPipeServerTransport.cs | 8 +- .../Server/TServerSocketTransport.cs | 2 +- .../Server/TTlsServerSocketTransport.cs | 2 +- .../Thrift/Transport/TBufferedTransport.cs | 143 ++++---- .../Thrift/Transport/TFramedTransport.cs | 89 ++--- .../Thrift/Transport/TServerTransport.cs | 8 +- lib/netstd/Thrift/Transport/TTransport.cs | 58 ++-- .../Client/Performance/PerformanceTests.cs | 150 ++++++++ .../Client/Performance/TestDataFactory.cs | 154 +++++++++ test/netstd/Client/Program.cs | 5 +- 27 files changed, 928 insertions(+), 558 deletions(-) create mode 100644 test/netstd/Client/Performance/PerformanceTests.cs create mode 100644 test/netstd/Client/Performance/TestDataFactory.cs diff --git a/.gitignore b/.gitignore index fb7651e9aee..3f584e2d325 100644 --- a/.gitignore +++ b/.gitignore @@ -344,6 +344,10 @@ project.lock.json /test/netcore/Thrift /test/netstd/**/bin /test/netstd/**/obj +/test/netstd/*.psess +/test/netstd/*.vspx +/test/netstd/*.vsp +/test/netstd/*.diagsession /test/netstd/Thrift /test/php/php_ext_dir/ /test/rs/Cargo.lock diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index b76a34da7f4..ffe51ab0b24 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -1473,7 +1473,7 @@ void t_netstd_generator::generate_netstd_struct_hashcode(ostream& out, t_struct* out << indent() << "public override int GetHashCode() {" << endl; indent_up(); - out << indent() << "int hashcode = 0;" << endl; + out << indent() << "int hashcode = 157;" << endl; out << indent() << "unchecked {" << endl; indent_up(); @@ -1483,24 +1483,26 @@ void t_netstd_generator::generate_netstd_struct_hashcode(ostream& out, t_struct* for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { t_type* ttype = (*f_iter)->get_type(); - out << indent() << "hashcode = (hashcode * 397) ^ "; - if (field_is_required((*f_iter))) - { - out << "("; - } - else + if (!field_is_required((*f_iter))) { - out << "(!__isset." << normalize_name((*f_iter)->get_name()) << " ? 0 : "; + out << indent() << "if(__isset." << normalize_name((*f_iter)->get_name()) << ")" << endl; + indent_up(); } + out << indent() << "hashcode = (hashcode * 397) + "; if (ttype->is_container()) { - out << "(TCollections.GetHashCode(" << prop_name((*f_iter)) << "))"; + out << "TCollections.GetHashCode(" << prop_name((*f_iter)) << ")"; } else { - out << "(" << prop_name((*f_iter)) << ".GetHashCode())"; + out << prop_name((*f_iter)) << ".GetHashCode()"; + } + out << ";" << endl; + + if (!field_is_required((*f_iter))) + { + indent_down(); } - out << ");" << endl; } indent_down(); @@ -2223,7 +2225,6 @@ void t_netstd_generator::generate_deserialize_container(ostream& out, t_type* tt obj = tmp("_list"); } - out << indent() << prefix << " = new " << type_name(ttype) << "();" << endl; if (ttype->is_map()) { out << indent() << "TMap " << obj << " = await iprot.ReadMapBeginAsync(cancellationToken);" << endl; @@ -2237,6 +2238,7 @@ void t_netstd_generator::generate_deserialize_container(ostream& out, t_type* tt out << indent() << "TList " << obj << " = await iprot.ReadListBeginAsync(cancellationToken);" << endl; } + out << indent() << prefix << " = new " << type_name(ttype) << "(" << obj << ".Count);" << endl; string i = tmp("_i"); out << indent() << "for(int " << i << " = 0; " << i << " < " << obj << ".Count; ++" << i << ")" << endl << indent() << "{" << endl; diff --git a/lib/netstd/Thrift/Collections/THashSet.cs b/lib/netstd/Thrift/Collections/THashSet.cs index 011f0a0d629..ffab5771156 100644 --- a/lib/netstd/Thrift/Collections/THashSet.cs +++ b/lib/netstd/Thrift/Collections/THashSet.cs @@ -23,45 +23,56 @@ namespace Thrift.Collections // ReSharper disable once InconsistentNaming public class THashSet : ICollection { - private readonly HashSet _set = new HashSet(); + private readonly HashSet Items; - public int Count => _set.Count; + public THashSet() + { + Items = new HashSet(); + } + + public THashSet(int capacity) + { + // TODO: uncomment capacity when NET Standard also implements it + Items = new HashSet(/*capacity*/); + } + + public int Count => Items.Count; public bool IsReadOnly => false; public void Add(T item) { - _set.Add(item); + Items.Add(item); } public void Clear() { - _set.Clear(); + Items.Clear(); } public bool Contains(T item) { - return _set.Contains(item); + return Items.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { - _set.CopyTo(array, arrayIndex); + Items.CopyTo(array, arrayIndex); } public IEnumerator GetEnumerator() { - return _set.GetEnumerator(); + return Items.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { - return ((IEnumerable) _set).GetEnumerator(); + return ((IEnumerable) Items).GetEnumerator(); } public bool Remove(T item) { - return _set.Remove(item); + return Items.Remove(item); } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Processor/ITAsyncProcessor.cs b/lib/netstd/Thrift/Processor/ITAsyncProcessor.cs index b8c1bce7213..f5b8d16e359 100644 --- a/lib/netstd/Thrift/Processor/ITAsyncProcessor.cs +++ b/lib/netstd/Thrift/Processor/ITAsyncProcessor.cs @@ -25,4 +25,4 @@ public interface ITAsyncProcessor { Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken = default(CancellationToken)); } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs b/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs index 81274be965e..e5aeaa6c74a 100644 --- a/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs +++ b/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs @@ -129,7 +129,7 @@ public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) _msgBegin = messageBegin; } - public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -140,4 +140,4 @@ public override async Task ReadMessageBeginAsync(CancellationToken can } } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs index 7a0243a95bd..3f30d4aa161 100644 --- a/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs @@ -27,16 +27,19 @@ namespace Thrift.Protocol // ReSharper disable once InconsistentNaming public class TBinaryProtocol : TProtocol { - //TODO: Unit tests - //TODO: Localization - //TODO: pragma - protected const uint VersionMask = 0xffff0000; protected const uint Version1 = 0x80010000; protected bool StrictRead; protected bool StrictWrite; + // minimize memory allocations by means of an preallocated bytes buffer + // The value of 128 is arbitrarily chosen, the required minimum size must be sizeof(long) + private byte[] PreAllocatedBuffer = new byte[128]; + + private static readonly TStruct AnonymousStruct = new TStruct(string.Empty); + private static readonly TField StopField = new TField() { Type = TType.Stop }; + public TBinaryProtocol(TTransport trans) : this(trans, false, true) { @@ -131,12 +134,15 @@ public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancel return; } - await WriteByteAsync((sbyte) map.KeyType, cancellationToken); - await WriteByteAsync((sbyte) map.ValueType, cancellationToken); + PreAllocatedBuffer[0] = (byte)map.KeyType; + PreAllocatedBuffer[1] = (byte)map.ValueType; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken); + await WriteI32Async(map.Count, cancellationToken); } public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + { if (cancellationToken.IsCancellationRequested) { @@ -192,15 +198,6 @@ public override async Task WriteBoolAsync(bool b, CancellationToken cancellation await WriteByteAsync(b ? (sbyte) 1 : (sbyte) 0, cancellationToken); } - protected internal static byte[] CreateWriteByte(sbyte b) - { - var bout = new byte[1]; - - bout[0] = (byte) b; - - return bout; - } - public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -208,20 +205,10 @@ public override async Task WriteByteAsync(sbyte b, CancellationToken cancellatio return; } - var bout = CreateWriteByte(b); - await Trans.WriteAsync(bout, 0, 1, cancellationToken); - } - - protected internal static byte[] CreateWriteI16(short s) - { - var i16Out = new byte[2]; + PreAllocatedBuffer[0] = (byte)b; - i16Out[0] = (byte) (0xff & (s >> 8)); - i16Out[1] = (byte) (0xff & s); - - return i16Out; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } - public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -229,20 +216,10 @@ public override async Task WriteI16Async(short i16, CancellationToken cancellati return; } - var i16Out = CreateWriteI16(i16); - await Trans.WriteAsync(i16Out, 0, 2, cancellationToken); - } - - protected internal static byte[] CreateWriteI32(int i32) - { - var i32Out = new byte[4]; + PreAllocatedBuffer[0] = (byte)(0xff & (i16 >> 8)); + PreAllocatedBuffer[1] = (byte)(0xff & i16); - i32Out[0] = (byte) (0xff & (i32 >> 24)); - i32Out[1] = (byte) (0xff & (i32 >> 16)); - i32Out[2] = (byte) (0xff & (i32 >> 8)); - i32Out[3] = (byte) (0xff & i32); - - return i32Out; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken); } public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) @@ -252,26 +229,15 @@ public override async Task WriteI32Async(int i32, CancellationToken cancellation return; } - var i32Out = CreateWriteI32(i32); - await Trans.WriteAsync(i32Out, 0, 4, cancellationToken); - } + PreAllocatedBuffer[0] = (byte)(0xff & (i32 >> 24)); + PreAllocatedBuffer[1] = (byte)(0xff & (i32 >> 16)); + PreAllocatedBuffer[2] = (byte)(0xff & (i32 >> 8)); + PreAllocatedBuffer[3] = (byte)(0xff & i32); - protected internal static byte[] CreateWriteI64(long i64) - { - var i64Out = new byte[8]; - - i64Out[0] = (byte) (0xff & (i64 >> 56)); - i64Out[1] = (byte) (0xff & (i64 >> 48)); - i64Out[2] = (byte) (0xff & (i64 >> 40)); - i64Out[3] = (byte) (0xff & (i64 >> 32)); - i64Out[4] = (byte) (0xff & (i64 >> 24)); - i64Out[5] = (byte) (0xff & (i64 >> 16)); - i64Out[6] = (byte) (0xff & (i64 >> 8)); - i64Out[7] = (byte) (0xff & i64); - - return i64Out; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 4, cancellationToken); } + public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -279,8 +245,16 @@ public override async Task WriteI64Async(long i64, CancellationToken cancellatio return; } - var i64Out = CreateWriteI64(i64); - await Trans.WriteAsync(i64Out, 0, 8, cancellationToken); + PreAllocatedBuffer[0] = (byte)(0xff & (i64 >> 56)); + PreAllocatedBuffer[1] = (byte)(0xff & (i64 >> 48)); + PreAllocatedBuffer[2] = (byte)(0xff & (i64 >> 40)); + PreAllocatedBuffer[3] = (byte)(0xff & (i64 >> 32)); + PreAllocatedBuffer[4] = (byte)(0xff & (i64 >> 24)); + PreAllocatedBuffer[5] = (byte)(0xff & (i64 >> 16)); + PreAllocatedBuffer[6] = (byte)(0xff & (i64 >> 8)); + PreAllocatedBuffer[7] = (byte)(0xff & i64); + + await Trans.WriteAsync(PreAllocatedBuffer, 0, 8, cancellationToken); } public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) @@ -293,6 +267,7 @@ public override async Task WriteDoubleAsync(double d, CancellationToken cancella await WriteI64Async(BitConverter.DoubleToInt64Bits(d), cancellationToken); } + public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -304,7 +279,7 @@ public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken canc await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); } - public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -332,7 +307,7 @@ public override async Task ReadMessageBeginAsync(CancellationToken can throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in ReadMessageBegin, old client?"); } - message.Name = await ReadStringBodyAsync(size, cancellationToken); + message.Name = (size > 0) ? await ReadStringBodyAsync(size, cancellationToken) : string.Empty; message.Type = (TMessageType) await ReadByteAsync(cancellationToken); message.SeqID = await ReadI32Async(cancellationToken); } @@ -347,15 +322,14 @@ public override async Task ReadMessageEndAsync(CancellationToken cancellationTok } } - public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { await Task.FromCanceled(cancellationToken); } - //TODO: no read from internal transport? - return new TStruct(); + return AnonymousStruct; } public override async Task ReadStructEndAsync(CancellationToken cancellationToken) @@ -366,24 +340,24 @@ public override async Task ReadStructEndAsync(CancellationToken cancellationToke } } - public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return await Task.FromCanceled(cancellationToken); } - var field = new TField - { - Type = (TType) await ReadByteAsync(cancellationToken) - }; - if (field.Type != TType.Stop) + var type = (TType)await ReadByteAsync(cancellationToken); + if (type == TType.Stop) { - field.ID = await ReadI16Async(cancellationToken); + return StopField; } - return field; + return new TField { + Type = type, + ID = await ReadI16Async(cancellationToken) + }; } public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) @@ -394,7 +368,7 @@ public override async Task ReadFieldEndAsync(CancellationToken cancellationToken } } - public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -419,7 +393,7 @@ public override async Task ReadMapEndAsync(CancellationToken cancellationToken) } } - public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -443,7 +417,7 @@ public override async Task ReadListEndAsync(CancellationToken cancellationToken) } } - public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -467,7 +441,7 @@ public override async Task ReadSetEndAsync(CancellationToken cancellationToken) } } - public override async Task ReadBoolAsync(CancellationToken cancellationToken) + public override async ValueTask ReadBoolAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -477,82 +451,78 @@ public override async Task ReadBoolAsync(CancellationToken cancellationTok return await ReadByteAsync(cancellationToken) == 1; } - public override async Task ReadByteAsync(CancellationToken cancellationToken) + public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return await Task.FromCanceled(cancellationToken); } - var bin = new byte[1]; - await Trans.ReadAllAsync(bin, 0, 1, cancellationToken); //TODO: why readall ? - return (sbyte) bin[0]; + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + return (sbyte)PreAllocatedBuffer[0]; } - public override async Task ReadI16Async(CancellationToken cancellationToken) + public override async ValueTask ReadI16Async(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return await Task.FromCanceled(cancellationToken); } - var i16In = new byte[2]; - await Trans.ReadAllAsync(i16In, 0, 2, cancellationToken); - var result = (short) (((i16In[0] & 0xff) << 8) | i16In[1] & 0xff); + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 2, cancellationToken); + var result = (short) (((PreAllocatedBuffer[0] & 0xff) << 8) | PreAllocatedBuffer[1] & 0xff); return result; } - public override async Task ReadI32Async(CancellationToken cancellationToken) + public override async ValueTask ReadI32Async(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return await Task.FromCanceled(cancellationToken); } - var i32In = new byte[4]; - await Trans.ReadAllAsync(i32In, 0, 4, cancellationToken); + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 4, cancellationToken); var result = - ((i32In[0] & 0xff) << 24) | - ((i32In[1] & 0xff) << 16) | - ((i32In[2] & 0xff) << 8) | - i32In[3] & 0xff; + ((PreAllocatedBuffer[0] & 0xff) << 24) | + ((PreAllocatedBuffer[1] & 0xff) << 16) | + ((PreAllocatedBuffer[2] & 0xff) << 8) | + PreAllocatedBuffer[3] & 0xff; return result; } #pragma warning disable 675 - protected internal long CreateReadI64(byte[] buf) + protected internal long ReadI64FromPreAllocatedBuffer() { var result = - ((long) (buf[0] & 0xff) << 56) | - ((long) (buf[1] & 0xff) << 48) | - ((long) (buf[2] & 0xff) << 40) | - ((long) (buf[3] & 0xff) << 32) | - ((long) (buf[4] & 0xff) << 24) | - ((long) (buf[5] & 0xff) << 16) | - ((long) (buf[6] & 0xff) << 8) | - buf[7] & 0xff; + ((long) (PreAllocatedBuffer[0] & 0xff) << 56) | + ((long) (PreAllocatedBuffer[1] & 0xff) << 48) | + ((long) (PreAllocatedBuffer[2] & 0xff) << 40) | + ((long) (PreAllocatedBuffer[3] & 0xff) << 32) | + ((long) (PreAllocatedBuffer[4] & 0xff) << 24) | + ((long) (PreAllocatedBuffer[5] & 0xff) << 16) | + ((long) (PreAllocatedBuffer[6] & 0xff) << 8) | + PreAllocatedBuffer[7] & 0xff; return result; } #pragma warning restore 675 - public override async Task ReadI64Async(CancellationToken cancellationToken) + public override async ValueTask ReadI64Async(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return await Task.FromCanceled(cancellationToken); } - var i64In = new byte[8]; - await Trans.ReadAllAsync(i64In, 0, 8, cancellationToken); - return CreateReadI64(i64In); + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken); + return ReadI64FromPreAllocatedBuffer(); } - public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -563,7 +533,7 @@ public override async Task ReadDoubleAsync(CancellationToken cancellatio return BitConverter.Int64BitsToDouble(d); } - public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -576,13 +546,30 @@ public override async Task ReadBinaryAsync(CancellationToken cancellatio return buf; } - private async Task ReadStringBodyAsync(int size, CancellationToken cancellationToken) + public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return await Task.FromCanceled(cancellationToken); + } + + var size = await ReadI32Async(cancellationToken); + return size > 0 ? await ReadStringBodyAsync(size, cancellationToken) : string.Empty; + } + + private async ValueTask ReadStringBodyAsync(int size, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { await Task.FromCanceled(cancellationToken); } + if (size <= PreAllocatedBuffer.Length) + { + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, size, cancellationToken); + return Encoding.UTF8.GetString(PreAllocatedBuffer, 0, size); + } + var buf = new byte[size]; await Trans.ReadAllAsync(buf, 0, size, cancellationToken); return Encoding.UTF8.GetString(buf, 0, buf.Length); diff --git a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs index e6c5dbd5b89..c26633a14c0 100644 --- a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -37,10 +38,13 @@ public class TCompactProtocol : TProtocol private const byte TypeBits = 0x07; // 0000 0111 private const int TypeShiftAmount = 5; private static readonly TStruct AnonymousStruct = new TStruct(string.Empty); - private static readonly TField Tstop = new TField(string.Empty, TType.Stop, 0); + private static readonly TField StopField = new TField(string.Empty, TType.Stop, 0); + + private const byte NoTypeOverride = 0xFF; // ReSharper disable once InconsistentNaming private static readonly byte[] TTypeToCompactType = new byte[16]; + private static readonly TType[] CompactTypeToTType = new TType[13]; /// /// Used to keep track of the last field for the current and previous structs, so we can do the delta stuff. @@ -59,6 +63,26 @@ public class TCompactProtocol : TProtocol private short _lastFieldId; + // minimize memory allocations by means of an preallocated bytes buffer + // The value of 128 is arbitrarily chosen, the required minimum size must be sizeof(long) + private byte[] PreAllocatedBuffer = new byte[128]; + + private struct VarInt + { + public byte[] bytes; + public int count; + } + + // minimize memory allocations by means of an preallocated VarInt buffer + private VarInt PreAllocatedVarInt = new VarInt() + { + bytes = new byte[10], // see Int64ToVarInt() + count = 0 + }; + + + + public TCompactProtocol(TTransport trans) : base(trans) { @@ -74,6 +98,20 @@ public TCompactProtocol(TTransport trans) TTypeToCompactType[(int) TType.Set] = Types.Set; TTypeToCompactType[(int) TType.Map] = Types.Map; TTypeToCompactType[(int) TType.Struct] = Types.Struct; + + CompactTypeToTType[Types.Stop] = TType.Stop; + CompactTypeToTType[Types.BooleanTrue] = TType.Bool; + CompactTypeToTType[Types.BooleanFalse] = TType.Bool; + CompactTypeToTType[Types.Byte] = TType.Byte; + CompactTypeToTType[Types.I16] = TType.I16; + CompactTypeToTType[Types.I32] = TType.I32; + CompactTypeToTType[Types.I64] = TType.I64; + CompactTypeToTType[Types.Double] = TType.Double; + CompactTypeToTType[Types.Binary] = TType.String; + CompactTypeToTType[Types.List] = TType.List; + CompactTypeToTType[Types.Set] = TType.Set; + CompactTypeToTType[Types.Map] = TType.Map; + CompactTypeToTType[Types.Struct] = TType.Struct; } public void Reset() @@ -84,19 +122,12 @@ public void Reset() public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + PreAllocatedBuffer[0] = ProtocolId; + PreAllocatedBuffer[1] = (byte)((Version & VersionMask) | (((uint)message.Type << TypeShiftAmount) & TypeMask)); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken); - await Trans.WriteAsync(new[] {ProtocolId}, cancellationToken); - await - Trans.WriteAsync( - new[] {(byte) ((Version & VersionMask) | (((uint) message.Type << TypeShiftAmount) & TypeMask))}, - cancellationToken); - - var bufferTuple = CreateWriteVarInt32((uint) message.SeqID); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + Int32ToVarInt((uint) message.SeqID, ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); await WriteStringAsync(message.Name, cancellationToken); } @@ -135,26 +166,31 @@ public override async Task WriteStructEndAsync(CancellationToken cancellationTok _lastFieldId = _lastField.Pop(); } - private async Task WriteFieldBeginInternalAsync(TField field, byte typeOverride, - CancellationToken cancellationToken) + private async Task WriteFieldBeginInternalAsync(TField field, byte fieldType, CancellationToken cancellationToken) { - // if there's a exType override, use that. - var typeToWrite = typeOverride == 0xFF ? GetCompactType(field.Type) : typeOverride; + // if there's a exType override passed in, use that. Otherwise ask GetCompactType(). + if (fieldType == NoTypeOverride) + fieldType = GetCompactType(field.Type); + // check if we can use delta encoding for the field id - if ((field.ID > _lastFieldId) && (field.ID - _lastFieldId <= 15)) - { - var b = (byte) (((field.ID - _lastFieldId) << 4) | typeToWrite); - // Write them together - await Trans.WriteAsync(new[] {b}, cancellationToken); - } - else + if (field.ID > _lastFieldId) { - // Write them separate - await Trans.WriteAsync(new[] {typeToWrite}, cancellationToken); - await WriteI16Async(field.ID, cancellationToken); + var delta = field.ID - _lastFieldId; + if (delta <= 15) + { + // Write them together + PreAllocatedBuffer[0] = (byte)((delta << 4) | fieldType); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + _lastFieldId = field.ID; + return; + } } + // Write them separate + PreAllocatedBuffer[0] = fieldType; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + await WriteI16Async(field.ID, cancellationToken); _lastFieldId = field.ID; } @@ -166,7 +202,7 @@ public override async Task WriteFieldBeginAsync(TField field, CancellationToken } else { - await WriteFieldBeginInternalAsync(field, 0xFF, cancellationToken); + await WriteFieldBeginInternalAsync(field, NoTypeOverride, cancellationToken); } } @@ -185,7 +221,8 @@ public override async Task WriteFieldStopAsync(CancellationToken cancellationTok return; } - await Trans.WriteAsync(new[] {Types.Stop}, cancellationToken); + PreAllocatedBuffer[0] = Types.Stop; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } protected async Task WriteCollectionBeginAsync(TType elemType, int size, CancellationToken cancellationToken) @@ -202,14 +239,16 @@ the wire differ only by the exType indicator. if (size <= 14) { - await Trans.WriteAsync(new[] {(byte) ((size << 4) | GetCompactType(elemType))}, cancellationToken); + PreAllocatedBuffer[0] = (byte)((size << 4) | GetCompactType(elemType)); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } else { - await Trans.WriteAsync(new[] {(byte) (0xf0 | GetCompactType(elemType))}, cancellationToken); + PreAllocatedBuffer[0] = (byte)(0xf0 | GetCompactType(elemType)); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); - var bufferTuple = CreateWriteVarInt32((uint) size); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + Int32ToVarInt((uint) size, ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); } } @@ -261,15 +300,15 @@ public override async Task WriteBoolAsync(bool b, CancellationToken cancellation if (_booleanField != null) { // we haven't written the field header yet - await - WriteFieldBeginInternalAsync(_booleanField.Value, b ? Types.BooleanTrue : Types.BooleanFalse, - cancellationToken); + var type = b ? Types.BooleanTrue : Types.BooleanFalse; + await WriteFieldBeginInternalAsync(_booleanField.Value, type, cancellationToken); _booleanField = null; } else { - // we're not part of a field, so just Write the value. - await Trans.WriteAsync(new[] {b ? Types.BooleanTrue : Types.BooleanFalse}, cancellationToken); + // we're not part of a field, so just write the value. + PreAllocatedBuffer[0] = b ? Types.BooleanTrue : Types.BooleanFalse; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } } @@ -280,7 +319,8 @@ public override async Task WriteByteAsync(sbyte b, CancellationToken cancellatio return; } - await Trans.WriteAsync(new[] {(byte) b}, cancellationToken); + PreAllocatedBuffer[0] = (byte)b; + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) @@ -290,29 +330,27 @@ public override async Task WriteI16Async(short i16, CancellationToken cancellati return; } - var bufferTuple = CreateWriteVarInt32(IntToZigzag(i16)); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + Int32ToVarInt(IntToZigzag(i16), ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); } - protected internal Tuple CreateWriteVarInt32(uint n) + private static void Int32ToVarInt(uint n, ref VarInt varint) { - // Write an i32 as a varint.Results in 1 - 5 bytes on the wire. - var i32Buf = new byte[5]; - var idx = 0; + // Write an i32 as a varint. Results in 1 - 5 bytes on the wire. + varint.count = 0; + Debug.Assert(varint.bytes.Length >= 5); while (true) { if ((n & ~0x7F) == 0) { - i32Buf[idx++] = (byte) n; + varint.bytes[varint.count++] = (byte)n; break; } - i32Buf[idx++] = (byte) ((n & 0x7F) | 0x80); + varint.bytes[varint.count++] = (byte)((n & 0x7F) | 0x80); n >>= 7; } - - return new Tuple(i32Buf, idx); } public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) @@ -322,28 +360,26 @@ public override async Task WriteI32Async(int i32, CancellationToken cancellation return; } - var bufferTuple = CreateWriteVarInt32(IntToZigzag(i32)); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + Int32ToVarInt(IntToZigzag(i32), ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); } - protected internal Tuple CreateWriteVarInt64(ulong n) + static private void Int64ToVarInt(ulong n, ref VarInt varint) { // Write an i64 as a varint. Results in 1-10 bytes on the wire. - var buf = new byte[10]; - var idx = 0; + varint.count = 0; + Debug.Assert(varint.bytes.Length >= 10); while (true) { - if ((n & ~(ulong) 0x7FL) == 0) + if ((n & ~(ulong)0x7FL) == 0) { - buf[idx++] = (byte) n; + varint.bytes[varint.count++] = (byte)n; break; } - buf[idx++] = (byte) ((n & 0x7F) | 0x80); + varint.bytes[varint.count++] = (byte)((n & 0x7F) | 0x80); n >>= 7; } - - return new Tuple(buf, idx); } public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) @@ -353,8 +389,8 @@ public override async Task WriteI64Async(long i64, CancellationToken cancellatio return; } - var bufferTuple = CreateWriteVarInt64(LongToZigzag(i64)); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + Int64ToVarInt(LongToZigzag(i64), ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); } public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) @@ -364,9 +400,8 @@ public override async Task WriteDoubleAsync(double d, CancellationToken cancella return; } - var data = new byte[8]; - FixedLongToBytes(BitConverter.DoubleToInt64Bits(d), data, 0); - await Trans.WriteAsync(data, cancellationToken); + FixedLongToBytes(BitConverter.DoubleToInt64Bits(d), PreAllocatedBuffer, 0); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 8, cancellationToken); } public override async Task WriteStringAsync(string str, CancellationToken cancellationToken) @@ -378,8 +413,8 @@ public override async Task WriteStringAsync(string str, CancellationToken cancel var bytes = Encoding.UTF8.GetBytes(str); - var bufferTuple = CreateWriteVarInt32((uint) bytes.Length); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + Int32ToVarInt((uint) bytes.Length, ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); } @@ -390,8 +425,8 @@ public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken canc return; } - var bufferTuple = CreateWriteVarInt32((uint) bytes.Length); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); + Int32ToVarInt((uint) bytes.Length, ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); } @@ -401,19 +436,19 @@ public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancel { return; } - + if (map.Count == 0) { - await Trans.WriteAsync(new[] {(byte) 0}, cancellationToken); + PreAllocatedBuffer[0] = 0; + await Trans.WriteAsync( PreAllocatedBuffer, 0, 1, cancellationToken); } else { - var bufferTuple = CreateWriteVarInt32((uint) map.Count); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); - await - Trans.WriteAsync( - new[] {(byte) ((GetCompactType(map.KeyType) << 4) | GetCompactType(map.ValueType))}, - cancellationToken); + Int32ToVarInt((uint) map.Count, ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); + + PreAllocatedBuffer[0] = (byte)((GetCompactType(map.KeyType) << 4) | GetCompactType(map.ValueType)); + await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); } } @@ -425,7 +460,7 @@ public override async Task WriteMapEndAsync(CancellationToken cancellationToken) } } - public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -461,7 +496,7 @@ public override async Task ReadMessageEndAsync(CancellationToken cancellationTok } } - public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -492,19 +527,23 @@ this struct from the field stack. _lastFieldId = _lastField.Pop(); } - public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) { // Read a field header off the wire. var type = (byte) await ReadByteAsync(cancellationToken); + // if it's a stop, then we can return immediately, as the struct is over. if (type == Types.Stop) { - return Tstop; + return StopField; } - short fieldId; + // mask off the 4 MSB of the exType header. it could contain a field id delta. var modifier = (short) ((type & 0xf0) >> 4); + var compactType = (byte)(type & 0x0f); + + short fieldId; if (modifier == 0) { fieldId = await ReadI16Async(cancellationToken); @@ -514,11 +553,13 @@ public override async Task ReadFieldBeginAsync(CancellationToken cancell fieldId = (short) (_lastFieldId + modifier); } - var field = new TField(string.Empty, GetTType((byte) (type & 0x0f)), fieldId); + var ttype = GetTType(compactType); + var field = new TField(string.Empty, ttype, fieldId); + // if this happens to be a boolean field, the value is encoded in the exType - if (IsBoolType(type)) + if( ttype == TType.Bool) { - _boolValue = (byte) (type & 0x0f) == Types.BooleanTrue; + _boolValue = (compactType == Types.BooleanTrue); } // push the new field onto the field stack so we can keep the deltas going. @@ -534,7 +575,7 @@ public override async Task ReadFieldEndAsync(CancellationToken cancellationToken } } - public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -560,7 +601,7 @@ public override async Task ReadMapEndAsync(CancellationToken cancellationToken) } } - public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) { /* Read a set header off the wire. If the set size is 0-14, the size will @@ -572,13 +613,8 @@ true size. return new TSet(await ReadListBeginAsync(cancellationToken)); } - public override async Task ReadBoolAsync(CancellationToken cancellationToken) + public override ValueTask ReadBoolAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - /* 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 @@ -589,26 +625,27 @@ public override async Task ReadBoolAsync(CancellationToken cancellationTok { var result = _boolValue.Value; _boolValue = null; - return result; + return new ValueTask(result); } - return await ReadByteAsync(cancellationToken) == Types.BooleanTrue; - } + return InternalCall(); - public override async Task ReadByteAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) + async ValueTask InternalCall() { - return await Task.FromCanceled(cancellationToken); + var data = await ReadByteAsync(cancellationToken); + return (data == Types.BooleanTrue); } + } + + public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) + { // Read a single byte off the wire. Nothing interesting here. - var buf = new byte[1]; - await Trans.ReadAllAsync(buf, 0, 1, cancellationToken); - return (sbyte) buf[0]; + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 1, cancellationToken); + return (sbyte)PreAllocatedBuffer[0]; } - public override async Task ReadI16Async(CancellationToken cancellationToken) + public override async ValueTask ReadI16Async(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -618,7 +655,7 @@ public override async Task ReadI16Async(CancellationToken cancellationTok return (short) ZigzagToInt(await ReadVarInt32Async(cancellationToken)); } - public override async Task ReadI32Async(CancellationToken cancellationToken) + public override async ValueTask ReadI32Async(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -628,7 +665,7 @@ public override async Task ReadI32Async(CancellationToken cancellationToken return ZigzagToInt(await ReadVarInt32Async(cancellationToken)); } - public override async Task ReadI64Async(CancellationToken cancellationToken) + public override async ValueTask ReadI64Async(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -638,60 +675,55 @@ public override async Task ReadI64Async(CancellationToken cancellationToke return ZigzagToLong(await ReadVarInt64Async(cancellationToken)); } - public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return await Task.FromCanceled(cancellationToken); } - var longBits = new byte[8]; - await Trans.ReadAllAsync(longBits, 0, 8, cancellationToken); + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken); - return BitConverter.Int64BitsToDouble(BytesToLong(longBits)); + return BitConverter.Int64BitsToDouble(BytesToLong(PreAllocatedBuffer)); } - public override async Task ReadStringAsync(CancellationToken cancellationToken) + public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - // Reads a byte[] (via ReadBinary), and then UTF-8 decodes it. + // read length var length = (int) await ReadVarInt32Async(cancellationToken); - if (length == 0) { return string.Empty; } + // read and decode data + if (length < PreAllocatedBuffer.Length) + { + await Trans.ReadAllAsync(PreAllocatedBuffer, 0, length, cancellationToken); + return Encoding.UTF8.GetString(PreAllocatedBuffer, 0, length); + } + var buf = new byte[length]; await Trans.ReadAllAsync(buf, 0, length, cancellationToken); - - return Encoding.UTF8.GetString(buf); + return Encoding.UTF8.GetString(buf, 0, length); } - public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - // Read a byte[] from the wire. + // read length var length = (int) await ReadVarInt32Async(cancellationToken); if (length == 0) { return new byte[0]; } + // read data var buf = new byte[length]; await Trans.ReadAllAsync(buf, 0, length, cancellationToken); return buf; } - public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -739,7 +771,7 @@ private static byte GetCompactType(TType ttype) } - private async Task ReadVarInt32Async(CancellationToken cancellationToken) + private async ValueTask ReadVarInt32Async(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -768,7 +800,7 @@ Read an i32 from the wire as a varint. The MSB of each byte is set return result; } - private async Task ReadVarInt64Async(CancellationToken cancellationToken) + private async ValueTask ReadVarInt64Async(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -825,45 +857,10 @@ you just get a messed up int. (bytes[0] & 0xffL); } - private static bool IsBoolType(byte b) - { - var lowerNibble = b & 0x0f; - return (lowerNibble == Types.BooleanTrue) || (lowerNibble == Types.BooleanFalse); - } - private static TType GetTType(byte type) { // Given a TCompactProtocol.Types constant, convert it to its corresponding TType value. - switch ((byte) (type & 0x0f)) - { - case Types.Stop: - return TType.Stop; - case Types.BooleanFalse: - case Types.BooleanTrue: - 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 exType: {(byte) (type & 0x0f)}"); - } + return CompactTypeToTType[type & 0x0f]; } private static ulong LongToZigzag(long n) diff --git a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs index 12980527b00..464bd62ff99 100644 --- a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs @@ -396,7 +396,7 @@ public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken canc /// Read in a JSON string, unescaping as appropriate.. Skip Reading from the /// context if skipContext is true. /// - private async Task ReadJsonStringAsync(bool skipContext, CancellationToken cancellationToken) + private async ValueTask ReadJsonStringAsync(bool skipContext, CancellationToken cancellationToken) { using (var buffer = new MemoryStream()) { @@ -487,7 +487,7 @@ private async Task ReadJsonStringAsync(bool skipContext, CancellationTok /// 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 async Task ReadJsonNumericCharsAsync(CancellationToken cancellationToken) + private async ValueTask ReadJsonNumericCharsAsync(CancellationToken cancellationToken) { var strbld = new StringBuilder(); while (true) @@ -514,7 +514,7 @@ private async Task ReadJsonNumericCharsAsync(CancellationToken cancellat /// /// Read in a JSON number. If the context dictates, Read in enclosing quotes. /// - private async Task ReadJsonIntegerAsync(CancellationToken cancellationToken) + private async ValueTask ReadJsonIntegerAsync(CancellationToken cancellationToken) { await Context.ReadConditionalDelimiterAsync(cancellationToken); if (Context.EscapeNumbers()) @@ -542,7 +542,7 @@ private async Task ReadJsonIntegerAsync(CancellationToken cancellationToke /// 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 async Task ReadJsonDoubleAsync(CancellationToken cancellationToken) + private async ValueTask ReadJsonDoubleAsync(CancellationToken cancellationToken) { await Context.ReadConditionalDelimiterAsync(cancellationToken); if (await Reader.PeekAsync(cancellationToken) == TJSONProtocolConstants.Quote[0]) @@ -578,7 +578,7 @@ private async Task ReadJsonDoubleAsync(CancellationToken cancellationTok /// /// Read in a JSON string containing base-64 encoded data and decode it. /// - private async Task ReadJsonBase64Async(CancellationToken cancellationToken) + private async ValueTask ReadJsonBase64Async(CancellationToken cancellationToken) { var b = await ReadJsonStringAsync(false, cancellationToken); var len = b.Length; @@ -642,7 +642,7 @@ private async Task ReadJsonArrayEndAsync(CancellationToken cancellationToken) PopContext(); } - public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { var message = new TMessage(); await ReadJsonArrayStartAsync(cancellationToken); @@ -663,7 +663,7 @@ public override async Task ReadMessageEndAsync(CancellationToken cancellationTok await ReadJsonArrayEndAsync(cancellationToken); } - public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) { await ReadJsonObjectStartAsync(cancellationToken); return new TStruct(); @@ -674,7 +674,7 @@ public override async Task ReadStructEndAsync(CancellationToken cancellationToke await ReadJsonObjectEndAsync(cancellationToken); } - public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) { var field = new TField(); var ch = await Reader.PeekAsync(cancellationToken); @@ -696,7 +696,7 @@ public override async Task ReadFieldEndAsync(CancellationToken cancellationToken await ReadJsonObjectEndAsync(cancellationToken); } - public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) { var map = new TMap(); await ReadJsonArrayStartAsync(cancellationToken); @@ -713,7 +713,7 @@ public override async Task ReadMapEndAsync(CancellationToken cancellationToken) await ReadJsonArrayEndAsync(cancellationToken); } - public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) { var list = new TList(); await ReadJsonArrayStartAsync(cancellationToken); @@ -727,7 +727,7 @@ public override async Task ReadListEndAsync(CancellationToken cancellationToken) await ReadJsonArrayEndAsync(cancellationToken); } - public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) { var set = new TSet(); await ReadJsonArrayStartAsync(cancellationToken); @@ -741,43 +741,43 @@ public override async Task ReadSetEndAsync(CancellationToken cancellationToken) await ReadJsonArrayEndAsync(cancellationToken); } - public override async Task ReadBoolAsync(CancellationToken cancellationToken) + public override async ValueTask ReadBoolAsync(CancellationToken cancellationToken) { return await ReadJsonIntegerAsync(cancellationToken) != 0; } - public override async Task ReadByteAsync(CancellationToken cancellationToken) + public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) { return (sbyte) await ReadJsonIntegerAsync(cancellationToken); } - public override async Task ReadI16Async(CancellationToken cancellationToken) + public override async ValueTask ReadI16Async(CancellationToken cancellationToken) { return (short) await ReadJsonIntegerAsync(cancellationToken); } - public override async Task ReadI32Async(CancellationToken cancellationToken) + public override async ValueTask ReadI32Async(CancellationToken cancellationToken) { return (int) await ReadJsonIntegerAsync(cancellationToken); } - public override async Task ReadI64Async(CancellationToken cancellationToken) + public override async ValueTask ReadI64Async(CancellationToken cancellationToken) { return await ReadJsonIntegerAsync(cancellationToken); } - public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) { return await ReadJsonDoubleAsync(cancellationToken); } - public override async Task ReadStringAsync(CancellationToken cancellationToken) + public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) { var buf = await ReadJsonStringAsync(false, cancellationToken); return Utf8Encoding.GetString(buf, 0, buf.Length); } - public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) { return await ReadJsonBase64Async(cancellationToken); } @@ -938,7 +938,7 @@ public LookaheadReader(TJsonProtocol proto) /// 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. /// - public async Task ReadAsync(CancellationToken cancellationToken) + public async ValueTask ReadAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -961,7 +961,7 @@ public async Task ReadAsync(CancellationToken cancellationToken) /// Return the next byte to be Read without consuming, filling the data /// buffer if it has not been filled alReady. /// - public async Task PeekAsync(CancellationToken cancellationToken) + public async ValueTask PeekAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -972,8 +972,8 @@ public async Task PeekAsync(CancellationToken cancellationToken) { // find more easy way to avoid exception on reading primitive types await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken); + _hasData = true; } - _hasData = true; return _data[0]; } } diff --git a/lib/netstd/Thrift/Protocol/TProtocol.cs b/lib/netstd/Thrift/Protocol/TProtocol.cs index 1bc91eb9850..75edb11d1f7 100644 --- a/lib/netstd/Thrift/Protocol/TProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TProtocol.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -229,12 +229,12 @@ public virtual async Task WriteBinaryAsync(byte[] bytes) public abstract Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken); - public virtual async Task ReadMessageBeginAsync() + public virtual async ValueTask ReadMessageBeginAsync() { return await ReadMessageBeginAsync(CancellationToken.None); } - public abstract Task ReadMessageBeginAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken); public virtual async Task ReadMessageEndAsync() { @@ -243,12 +243,12 @@ public virtual async Task ReadMessageEndAsync() public abstract Task ReadMessageEndAsync(CancellationToken cancellationToken); - public virtual async Task ReadStructBeginAsync() + public virtual async ValueTask ReadStructBeginAsync() { return await ReadStructBeginAsync(CancellationToken.None); } - public abstract Task ReadStructBeginAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadStructBeginAsync(CancellationToken cancellationToken); public virtual async Task ReadStructEndAsync() { @@ -257,12 +257,12 @@ public virtual async Task ReadStructEndAsync() public abstract Task ReadStructEndAsync(CancellationToken cancellationToken); - public virtual async Task ReadFieldBeginAsync() + public virtual async ValueTask ReadFieldBeginAsync() { return await ReadFieldBeginAsync(CancellationToken.None); } - public abstract Task ReadFieldBeginAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken); public virtual async Task ReadFieldEndAsync() { @@ -271,12 +271,12 @@ public virtual async Task ReadFieldEndAsync() public abstract Task ReadFieldEndAsync(CancellationToken cancellationToken); - public virtual async Task ReadMapBeginAsync() + public virtual async ValueTask ReadMapBeginAsync() { return await ReadMapBeginAsync(CancellationToken.None); } - public abstract Task ReadMapBeginAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadMapBeginAsync(CancellationToken cancellationToken); public virtual async Task ReadMapEndAsync() { @@ -285,12 +285,12 @@ public virtual async Task ReadMapEndAsync() public abstract Task ReadMapEndAsync(CancellationToken cancellationToken); - public virtual async Task ReadListBeginAsync() + public virtual async ValueTask ReadListBeginAsync() { return await ReadListBeginAsync(CancellationToken.None); } - public abstract Task ReadListBeginAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadListBeginAsync(CancellationToken cancellationToken); public virtual async Task ReadListEndAsync() { @@ -299,12 +299,12 @@ public virtual async Task ReadListEndAsync() public abstract Task ReadListEndAsync(CancellationToken cancellationToken); - public virtual async Task ReadSetBeginAsync() + public virtual async ValueTask ReadSetBeginAsync() { return await ReadSetBeginAsync(CancellationToken.None); } - public abstract Task ReadSetBeginAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadSetBeginAsync(CancellationToken cancellationToken); public virtual async Task ReadSetEndAsync() { @@ -313,64 +313,64 @@ public virtual async Task ReadSetEndAsync() public abstract Task ReadSetEndAsync(CancellationToken cancellationToken); - public virtual async Task ReadBoolAsync() + public virtual async ValueTask ReadBoolAsync() { return await ReadBoolAsync(CancellationToken.None); } - public abstract Task ReadBoolAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadBoolAsync(CancellationToken cancellationToken); - public virtual async Task ReadByteAsync() + public virtual async ValueTask ReadByteAsync() { return await ReadByteAsync(CancellationToken.None); } - public abstract Task ReadByteAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadByteAsync(CancellationToken cancellationToken); - public virtual async Task ReadI16Async() + public virtual async ValueTask ReadI16Async() { return await ReadI16Async(CancellationToken.None); } - public abstract Task ReadI16Async(CancellationToken cancellationToken); + public abstract ValueTask ReadI16Async(CancellationToken cancellationToken); - public virtual async Task ReadI32Async() + public virtual async ValueTask ReadI32Async() { return await ReadI32Async(CancellationToken.None); } - public abstract Task ReadI32Async(CancellationToken cancellationToken); + public abstract ValueTask ReadI32Async(CancellationToken cancellationToken); - public virtual async Task ReadI64Async() + public virtual async ValueTask ReadI64Async() { return await ReadI64Async(CancellationToken.None); } - public abstract Task ReadI64Async(CancellationToken cancellationToken); + public abstract ValueTask ReadI64Async(CancellationToken cancellationToken); - public virtual async Task ReadDoubleAsync() + public virtual async ValueTask ReadDoubleAsync() { return await ReadDoubleAsync(CancellationToken.None); } - public abstract Task ReadDoubleAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadDoubleAsync(CancellationToken cancellationToken); - public virtual async Task ReadStringAsync() + public virtual async ValueTask ReadStringAsync() { return await ReadStringAsync(CancellationToken.None); } - public virtual async Task ReadStringAsync(CancellationToken cancellationToken) + public virtual async ValueTask ReadStringAsync(CancellationToken cancellationToken) { var buf = await ReadBinaryAsync(cancellationToken); return Encoding.UTF8.GetString(buf, 0, buf.Length); } - public virtual async Task ReadBinaryAsync() + public virtual async ValueTask ReadBinaryAsync() { return await ReadBinaryAsync(CancellationToken.None); } - public abstract Task ReadBinaryAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadBinaryAsync(CancellationToken cancellationToken); } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs b/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs index c8a433d0b66..845c8274908 100644 --- a/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs +++ b/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -144,7 +144,7 @@ public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken canc await _wrappedProtocol.WriteBinaryAsync(bytes, cancellationToken); } - public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadMessageBeginAsync(cancellationToken); } @@ -154,7 +154,7 @@ public override async Task ReadMessageEndAsync(CancellationToken cancellationTok await _wrappedProtocol.ReadMessageEndAsync(cancellationToken); } - public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadStructBeginAsync(cancellationToken); } @@ -164,7 +164,7 @@ public override async Task ReadStructEndAsync(CancellationToken cancellationToke await _wrappedProtocol.ReadStructEndAsync(cancellationToken); } - public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadFieldBeginAsync(cancellationToken); } @@ -174,7 +174,7 @@ public override async Task ReadFieldEndAsync(CancellationToken cancellationToken await _wrappedProtocol.ReadFieldEndAsync(cancellationToken); } - public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadMapBeginAsync(cancellationToken); } @@ -184,7 +184,7 @@ public override async Task ReadMapEndAsync(CancellationToken cancellationToken) await _wrappedProtocol.ReadMapEndAsync(cancellationToken); } - public override async Task ReadListBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadListBeginAsync(cancellationToken); } @@ -194,7 +194,7 @@ public override async Task ReadListEndAsync(CancellationToken cancellationToken) await _wrappedProtocol.ReadListEndAsync(cancellationToken); } - public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) + public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadSetBeginAsync(cancellationToken); } @@ -204,44 +204,44 @@ public override async Task ReadSetEndAsync(CancellationToken cancellationToken) await _wrappedProtocol.ReadSetEndAsync(cancellationToken); } - public override async Task ReadBoolAsync(CancellationToken cancellationToken) + public override async ValueTask ReadBoolAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadBoolAsync(cancellationToken); } - public override async Task ReadByteAsync(CancellationToken cancellationToken) + public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadByteAsync(cancellationToken); } - public override async Task ReadI16Async(CancellationToken cancellationToken) + public override async ValueTask ReadI16Async(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadI16Async(cancellationToken); } - public override async Task ReadI32Async(CancellationToken cancellationToken) + public override async ValueTask ReadI32Async(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadI32Async(cancellationToken); } - public override async Task ReadI64Async(CancellationToken cancellationToken) + public override async ValueTask ReadI64Async(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadI64Async(cancellationToken); } - public override async Task ReadDoubleAsync(CancellationToken cancellationToken) + public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadDoubleAsync(cancellationToken); } - public override async Task ReadStringAsync(CancellationToken cancellationToken) + public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadStringAsync(cancellationToken); } - public override async Task ReadBinaryAsync(CancellationToken cancellationToken) + public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) { return await _wrappedProtocol.ReadBinaryAsync(cancellationToken); } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Server/TServerEventHandler.cs b/lib/netstd/Thrift/Server/TServerEventHandler.cs index 0c31bf67dea..69314efd624 100644 --- a/lib/netstd/Thrift/Server/TServerEventHandler.cs +++ b/lib/netstd/Thrift/Server/TServerEventHandler.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -51,4 +51,4 @@ Task DeleteContextAsync(object serverContext, TProtocol input, TProtocol output, /// Task ProcessContextAsync(object serverContext, TTransport transport, CancellationToken cancellationToken); } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/TApplicationException.cs b/lib/netstd/Thrift/TApplicationException.cs index 9c86898af6e..67ac2f8c756 100644 --- a/lib/netstd/Thrift/TApplicationException.cs +++ b/lib/netstd/Thrift/TApplicationException.cs @@ -61,7 +61,7 @@ public TApplicationException(ExceptionType type, string message) Type = type; } - public static async Task ReadAsync(TProtocol inputProtocol, CancellationToken cancellationToken) + public static async ValueTask ReadAsync(TProtocol inputProtocol, CancellationToken cancellationToken) { string message = null; var type = ExceptionType.Unknown; diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj index d09380342c4..70d9df344d3 100644 --- a/lib/netstd/Thrift/Thrift.csproj +++ b/lib/netstd/Thrift/Thrift.csproj @@ -49,6 +49,7 @@ +
diff --git a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs index 627c93df935..5d7f1de2899 100644 --- a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs @@ -102,8 +102,7 @@ public override void Close() } } - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) + public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { diff --git a/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs index 75529d167e3..25895c2b7e0 100644 --- a/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs @@ -15,6 +15,8 @@ // specific language governing permissions and limitations // under the License. +using System; +using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -24,17 +26,59 @@ namespace Thrift.Transport.Client // ReSharper disable once InconsistentNaming public class TMemoryBufferTransport : TTransport { - private readonly MemoryStream _byteStream; - private bool _isDisposed; + private bool IsDisposed; + private byte[] Bytes; + private int _bytesUsed; public TMemoryBufferTransport() { - _byteStream = new MemoryStream(); + Bytes = new byte[2048]; // default size + } + + public TMemoryBufferTransport(int initialCapacity) + { + Bytes = new byte[initialCapacity]; // default size } public TMemoryBufferTransport(byte[] buf) { - _byteStream = new MemoryStream(buf); + Bytes = (byte[])buf.Clone(); + _bytesUsed = Bytes.Length; + } + + public int Position { get; set; } + + public int Capacity + { + get + { + Debug.Assert(_bytesUsed <= Bytes.Length); + return Bytes.Length; + } + set + { + Array.Resize(ref Bytes, value); + _bytesUsed = value; + } + } + + public int Length + { + get { + Debug.Assert(_bytesUsed <= Bytes.Length); + return _bytesUsed; + } + set { + if ((Bytes.Length < value) || (Bytes.Length > (10 * value))) + Array.Resize(ref Bytes, Math.Max(2048, (int)(value * 1.25))); + _bytesUsed = value; + } + } + + public void SetLength(int value) + { + Length = value; + Position = Math.Min(Position, value); } public override bool IsOpen => true; @@ -52,20 +96,49 @@ public override void Close() /** do nothing **/ } - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) + public void Seek(int delta, SeekOrigin origin) + { + int newPos; + switch (origin) + { + case SeekOrigin.Begin: + newPos = delta; + break; + case SeekOrigin.Current: + newPos = Position + delta; + break; + case SeekOrigin.End: + newPos = _bytesUsed + delta; + break; + default: + throw new ArgumentException(nameof(origin)); + } + + if ((0 > newPos) || (newPos > _bytesUsed)) + throw new ArgumentException(nameof(origin)); + Position = newPos; + } + + public override ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { - return await _byteStream.ReadAsync(buffer, offset, length, cancellationToken); + var count = Math.Min(Length - Position, length); + Buffer.BlockCopy(Bytes, Position, buffer, offset, count); + Position += count; + return new ValueTask(count); } - public override async Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) + public override Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) { - await _byteStream.WriteAsync(buffer, 0, buffer.Length, cancellationToken); + return WriteAsync(buffer, 0, buffer.Length, cancellationToken); } - public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { - await _byteStream.WriteAsync(buffer, offset, length, cancellationToken); + var free = Length - Position; + Length = Length + count - free; + Buffer.BlockCopy(buffer, offset, Bytes, Position, count); + Position += count; + return Task.CompletedTask; } public override async Task FlushAsync(CancellationToken cancellationToken) @@ -78,20 +151,29 @@ public override async Task FlushAsync(CancellationToken cancellationToken) public byte[] GetBuffer() { - return _byteStream.ToArray(); + var retval = new byte[Length]; + Buffer.BlockCopy(Bytes, 0, retval, 0, Length); + return retval; } + internal bool TryGetBuffer(out ArraySegment bufSegment) + { + bufSegment = new ArraySegment(Bytes, 0, _bytesUsed); + return true; + } + + // IDisposable protected override void Dispose(bool disposing) { - if (!_isDisposed) + if (!IsDisposed) { if (disposing) { - _byteStream?.Dispose(); + // nothing to do } } - _isDisposed = true; + IsDisposed = true; } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs index b78c791400b..2f96a6a484b 100644 --- a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -61,8 +61,7 @@ public override void Close() } } - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) + public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (_client == null) { @@ -95,4 +94,4 @@ protected override void Dispose(bool disposing) _client.Dispose(); } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs b/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs index 9b035339d77..d8574d610c3 100644 --- a/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs @@ -65,8 +65,7 @@ public override void Close() } } - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) + public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (InputStream == null) { @@ -107,4 +106,4 @@ protected override void Dispose(bool disposing) _isDisposed = true; } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs index 8147d67927b..31a052aa24e 100644 --- a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs @@ -210,7 +210,7 @@ private SafePipeHandle CreatePipeNative(string name, int inbuf, int outbuf) #endregion - protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) + protected override async ValueTask AcceptImplementationAsync(CancellationToken cancellationToken) { try { @@ -261,8 +261,7 @@ public override void Close() _stream?.Dispose(); } - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) + public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (_stream == null) { @@ -272,8 +271,7 @@ public override async Task ReadAsync(byte[] buffer, int offset, int length, return await _stream.ReadAsync(buffer, offset, length, cancellationToken); } - public override async Task WriteAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (_stream == null) { diff --git a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs index 0f90841d23f..86d82e3fc73 100644 --- a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs @@ -74,7 +74,7 @@ public override bool IsClientPending() return _server.Pending(); } - protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) + protected override async ValueTask AcceptImplementationAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { diff --git a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs index 5070919fcd4..128680599a6 100644 --- a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs @@ -99,7 +99,7 @@ public override bool IsClientPending() return _server.Pending(); } - protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) + protected override async ValueTask AcceptImplementationAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { diff --git a/lib/netstd/Thrift/Transport/TBufferedTransport.cs b/lib/netstd/Thrift/Transport/TBufferedTransport.cs index c648f5cdb1a..e4fdd3a8dfc 100644 --- a/lib/netstd/Thrift/Transport/TBufferedTransport.cs +++ b/lib/netstd/Thrift/Transport/TBufferedTransport.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -16,6 +16,7 @@ // under the License. using System; +using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -25,11 +26,11 @@ namespace Thrift.Transport // ReSharper disable once InconsistentNaming public class TBufferedTransport : TTransport { - private readonly int _bufSize; - private readonly MemoryStream _inputBuffer = new MemoryStream(0); - private readonly MemoryStream _outputBuffer = new MemoryStream(0); - private readonly TTransport _transport; - private bool _isDisposed; + private readonly int DesiredBufferSize; + private readonly Client.TMemoryBufferTransport ReadBuffer = new Client.TMemoryBufferTransport(1024); + private readonly Client.TMemoryBufferTransport WriteBuffer = new Client.TMemoryBufferTransport(1024); + private readonly TTransport InnerTransport; + private bool IsDisposed; public class Factory : TTransportFactory { @@ -47,8 +48,13 @@ public TBufferedTransport(TTransport transport, int bufSize = 1024) throw new ArgumentOutOfRangeException(nameof(bufSize), "Buffer size must be a positive number."); } - _transport = transport ?? throw new ArgumentNullException(nameof(transport)); - _bufSize = bufSize; + InnerTransport = transport ?? throw new ArgumentNullException(nameof(transport)); + DesiredBufferSize = bufSize; + + if (DesiredBufferSize != ReadBuffer.Capacity) + ReadBuffer.Capacity = DesiredBufferSize; + if (DesiredBufferSize != WriteBuffer.Capacity) + WriteBuffer.Capacity = DesiredBufferSize; } public TTransport UnderlyingTransport @@ -57,32 +63,29 @@ public TTransport UnderlyingTransport { CheckNotDisposed(); - return _transport; + return InnerTransport; } } - public override bool IsOpen => !_isDisposed && _transport.IsOpen; + public override bool IsOpen => !IsDisposed && InnerTransport.IsOpen; public override async Task OpenAsync(CancellationToken cancellationToken) { CheckNotDisposed(); - await _transport.OpenAsync(cancellationToken); + await InnerTransport.OpenAsync(cancellationToken); } public override void Close() { CheckNotDisposed(); - _transport.Close(); + InnerTransport.Close(); } - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) + public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { - //TODO: investigate how it should work correctly CheckNotDisposed(); - ValidateBufferArgs(buffer, offset, length); if (!IsOpen) @@ -90,39 +93,36 @@ public override async Task ReadAsync(byte[] buffer, int offset, int length, throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - if (_inputBuffer.Capacity < _bufSize) + + // do we have something buffered? + var count = ReadBuffer.Length - ReadBuffer.Position; + if (count > 0) { - _inputBuffer.Capacity = _bufSize; + return await ReadBuffer.ReadAsync(buffer, offset, length, cancellationToken); } - var got = await _inputBuffer.ReadAsync(buffer, offset, length, cancellationToken); - if (got > 0) + // does the request even fit into the buffer? + // Note we test for >= instead of > to avoid nonsense buffering + if (length >= ReadBuffer.Capacity) { - return got; + return await InnerTransport.ReadAsync(buffer, offset, length, cancellationToken); } - _inputBuffer.Seek(0, SeekOrigin.Begin); - _inputBuffer.SetLength(_inputBuffer.Capacity); - + // buffer a new chunk of bytes from the underlying transport + ReadBuffer.Length = ReadBuffer.Capacity; ArraySegment bufSegment; - _inputBuffer.TryGetBuffer(out bufSegment); - - // investigate - var filled = await _transport.ReadAsync(bufSegment.Array, 0, (int) _inputBuffer.Length, cancellationToken); - _inputBuffer.SetLength(filled); + ReadBuffer.TryGetBuffer(out bufSegment); + ReadBuffer.Length = await InnerTransport.ReadAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); + ReadBuffer.Position = 0; - if (filled == 0) - { - return 0; - } - - return await ReadAsync(buffer, offset, length, cancellationToken); + // deliver the bytes + return await ReadBuffer.ReadAsync(buffer, offset, length, cancellationToken); } + public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { CheckNotDisposed(); - ValidateBufferArgs(buffer, offset, length); if (!IsOpen) @@ -130,41 +130,26 @@ public override async Task WriteAsync(byte[] buffer, int offset, int length, Can throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - // Relative offset from "off" argument - var writtenCount = 0; - if (_outputBuffer.Length > 0) + // enough space left in buffer? + var free = WriteBuffer.Capacity - WriteBuffer.Length; + if (length > free) { - var capa = (int) (_outputBuffer.Capacity - _outputBuffer.Length); - var writeSize = capa <= length ? capa : length; - await _outputBuffer.WriteAsync(buffer, offset, writeSize, cancellationToken); - - writtenCount += writeSize; - if (writeSize == capa) - { - //ArraySegment bufSegment; - //_outputBuffer.TryGetBuffer(out bufSegment); - var data = _outputBuffer.ToArray(); - //await _transport.WriteAsync(bufSegment.Array, cancellationToken); - await _transport.WriteAsync(data, cancellationToken); - _outputBuffer.SetLength(0); - } + ArraySegment bufSegment; + WriteBuffer.TryGetBuffer(out bufSegment); + await InnerTransport.WriteAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); + WriteBuffer.SetLength(0); } - while (length - writtenCount >= _bufSize) + // do the data even fit into the buffer? + // Note we test for < instead of <= to avoid nonsense buffering + if (length < WriteBuffer.Capacity) { - await _transport.WriteAsync(buffer, offset + writtenCount, _bufSize, cancellationToken); - writtenCount += _bufSize; + await WriteBuffer.WriteAsync(buffer, offset, length, cancellationToken); + return; } - var remain = length - writtenCount; - if (remain > 0) - { - if (_outputBuffer.Capacity < _bufSize) - { - _outputBuffer.Capacity = _bufSize; - } - await _outputBuffer.WriteAsync(buffer, offset + writtenCount, remain, cancellationToken); - } + // write thru + await InnerTransport.WriteAsync(buffer, offset, length, cancellationToken); } public override async Task FlushAsync(CancellationToken cancellationToken) @@ -176,38 +161,38 @@ public override async Task FlushAsync(CancellationToken cancellationToken) throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - if (_outputBuffer.Length > 0) + if (WriteBuffer.Length > 0) { - var data = _outputBuffer.ToArray(); - - await _transport.WriteAsync(data /*bufSegment.Array*/, cancellationToken); - _outputBuffer.SetLength(0); + ArraySegment bufSegment; + WriteBuffer.TryGetBuffer(out bufSegment); + await InnerTransport.WriteAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); + WriteBuffer.SetLength(0); } - await _transport.FlushAsync(cancellationToken); + await InnerTransport.FlushAsync(cancellationToken); } private void CheckNotDisposed() { - if (_isDisposed) + if (IsDisposed) { - throw new ObjectDisposedException(nameof(_transport)); + throw new ObjectDisposedException(nameof(InnerTransport)); } } // IDisposable protected override void Dispose(bool disposing) { - if (!_isDisposed) + if (!IsDisposed) { if (disposing) { - _inputBuffer?.Dispose(); - _outputBuffer?.Dispose(); - _transport?.Dispose(); + ReadBuffer?.Dispose(); + WriteBuffer?.Dispose(); + InnerTransport?.Dispose(); } } - _isDisposed = true; + IsDisposed = true; } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Transport/TFramedTransport.cs b/lib/netstd/Thrift/Transport/TFramedTransport.cs index fe7793ec76b..de6df723886 100644 --- a/lib/netstd/Thrift/Transport/TFramedTransport.cs +++ b/lib/netstd/Thrift/Transport/TFramedTransport.cs @@ -26,12 +26,12 @@ namespace Thrift.Transport public class TFramedTransport : TTransport { private const int HeaderSize = 4; - private readonly byte[] _headerBuf = new byte[HeaderSize]; - private readonly MemoryStream _readBuffer = new MemoryStream(1024); - private readonly TTransport _transport; - private readonly MemoryStream _writeBuffer = new MemoryStream(1024); + private readonly byte[] HeaderBuf = new byte[HeaderSize]; + private readonly Client.TMemoryBufferTransport ReadBuffer = new Client.TMemoryBufferTransport(); + private readonly Client.TMemoryBufferTransport WriteBuffer = new Client.TMemoryBufferTransport(); + private readonly TTransport InnerTransport; - private bool _isDisposed; + private bool IsDisposed; public class Factory : TTransportFactory { @@ -43,32 +43,30 @@ public override TTransport GetTransport(TTransport trans) public TFramedTransport(TTransport transport) { - _transport = transport ?? throw new ArgumentNullException(nameof(transport)); + InnerTransport = transport ?? throw new ArgumentNullException(nameof(transport)); InitWriteBuffer(); } - public override bool IsOpen => !_isDisposed && _transport.IsOpen; + public override bool IsOpen => !IsDisposed && InnerTransport.IsOpen; public override async Task OpenAsync(CancellationToken cancellationToken) { CheckNotDisposed(); - await _transport.OpenAsync(cancellationToken); + await InnerTransport.OpenAsync(cancellationToken); } public override void Close() { CheckNotDisposed(); - _transport.Close(); + InnerTransport.Close(); } - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) + public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { CheckNotDisposed(); - ValidateBufferArgs(buffer, offset, length); if (!IsOpen) @@ -76,39 +74,31 @@ public override async Task ReadAsync(byte[] buffer, int offset, int length, throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - var got = await _readBuffer.ReadAsync(buffer, offset, length, cancellationToken); - if (got > 0) + // Read another frame of data if we run out of bytes + if (ReadBuffer.Position >= ReadBuffer.Length) { - return got; + await ReadFrameAsync(cancellationToken); } - // Read another frame of data - await ReadFrameAsync(cancellationToken); - - return await _readBuffer.ReadAsync(buffer, offset, length, cancellationToken); + return await ReadBuffer.ReadAsync(buffer, offset, length, cancellationToken); } - private async Task ReadFrameAsync(CancellationToken cancellationToken) + private async ValueTask ReadFrameAsync(CancellationToken cancellationToken) { - await _transport.ReadAllAsync(_headerBuf, 0, HeaderSize, cancellationToken); + await InnerTransport.ReadAllAsync(HeaderBuf, 0, HeaderSize, cancellationToken); + var size = DecodeFrameSize(HeaderBuf); - var size = DecodeFrameSize(_headerBuf); - - _readBuffer.SetLength(size); - _readBuffer.Seek(0, SeekOrigin.Begin); + ReadBuffer.SetLength(size); + ReadBuffer.Seek(0, SeekOrigin.Begin); ArraySegment bufSegment; - _readBuffer.TryGetBuffer(out bufSegment); - - var buff = bufSegment.Array; - - await _transport.ReadAllAsync(buff, 0, size, cancellationToken); + ReadBuffer.TryGetBuffer(out bufSegment); + await InnerTransport.ReadAllAsync(bufSegment.Array, 0, size, cancellationToken); } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { CheckNotDisposed(); - ValidateBufferArgs(buffer, offset, length); if (!IsOpen) @@ -116,12 +106,12 @@ public override async Task WriteAsync(byte[] buffer, int offset, int length, Can throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - if (_writeBuffer.Length + length > int.MaxValue) + if (WriteBuffer.Length > (int.MaxValue - length)) { await FlushAsync(cancellationToken); } - await _writeBuffer.WriteAsync(buffer, offset, length, cancellationToken); + await WriteBuffer.WriteAsync(buffer, offset, length, cancellationToken); } public override async Task FlushAsync(CancellationToken cancellationToken) @@ -133,34 +123,31 @@ public override async Task FlushAsync(CancellationToken cancellationToken) throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - //ArraySegment bufSegment; - //_writeBuffer.TryGetBuffer(out bufSegment); - //var buf = bufSegment.Array; - var buf = _writeBuffer.ToArray(); + ArraySegment bufSegment; + WriteBuffer.TryGetBuffer(out bufSegment); - //var len = (int)_writeBuffer.Length; - var dataLen = (int) _writeBuffer.Length - HeaderSize; + int dataLen = bufSegment.Count - HeaderSize; if (dataLen < 0) { throw new InvalidOperationException(); // logic error actually } // Inject message header into the reserved buffer space - EncodeFrameSize(dataLen, buf); + EncodeFrameSize(dataLen, bufSegment.Array); // Send the entire message at once - await _transport.WriteAsync(buf, cancellationToken); + await InnerTransport.WriteAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); InitWriteBuffer(); - await _transport.FlushAsync(cancellationToken); + await InnerTransport.FlushAsync(cancellationToken); } private void InitWriteBuffer() { // Reserve space for message header to be put right before sending it out - _writeBuffer.SetLength(HeaderSize); - _writeBuffer.Seek(0, SeekOrigin.End); + WriteBuffer.SetLength(HeaderSize); + WriteBuffer.Seek(0, SeekOrigin.End); } private static void EncodeFrameSize(int frameSize, byte[] buf) @@ -183,25 +170,25 @@ private static int DecodeFrameSize(byte[] buf) private void CheckNotDisposed() { - if (_isDisposed) + if (IsDisposed) { - throw new ObjectDisposedException("TFramedTransport"); + throw new ObjectDisposedException(this.GetType().Name); } } // IDisposable protected override void Dispose(bool disposing) { - if (!_isDisposed) + if (!IsDisposed) { if (disposing) { - _readBuffer?.Dispose(); - _writeBuffer?.Dispose(); - _transport?.Dispose(); + ReadBuffer?.Dispose(); + WriteBuffer?.Dispose(); + InnerTransport?.Dispose(); } } - _isDisposed = true; + IsDisposed = true; } } } diff --git a/lib/netstd/Thrift/Transport/TServerTransport.cs b/lib/netstd/Thrift/Transport/TServerTransport.cs index e25c0c5e9b4..74c54cd0e66 100644 --- a/lib/netstd/Thrift/Transport/TServerTransport.cs +++ b/lib/netstd/Thrift/Transport/TServerTransport.cs @@ -27,19 +27,19 @@ public abstract class TServerTransport public abstract void Close(); public abstract bool IsClientPending(); - protected virtual async Task AcceptImplementationAsync() + protected virtual async ValueTask AcceptImplementationAsync() { return await AcceptImplementationAsync(CancellationToken.None); } - protected abstract Task AcceptImplementationAsync(CancellationToken cancellationToken); + protected abstract ValueTask AcceptImplementationAsync(CancellationToken cancellationToken); - public async Task AcceptAsync() + public async ValueTask AcceptAsync() { return await AcceptAsync(CancellationToken.None); } - public async Task AcceptAsync(CancellationToken cancellationToken) + public async ValueTask AcceptAsync(CancellationToken cancellationToken) { var transport = await AcceptImplementationAsync(cancellationToken); diff --git a/lib/netstd/Thrift/Transport/TTransport.cs b/lib/netstd/Thrift/Transport/TTransport.cs index d5c8186f7b2..fd802eca886 100644 --- a/lib/netstd/Thrift/Transport/TTransport.cs +++ b/lib/netstd/Thrift/Transport/TTransport.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -16,6 +16,7 @@ // under the License. using System; +using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -37,7 +38,7 @@ public void Dispose() GC.SuppressFinalize(this); } - public async Task PeekAsync(CancellationToken cancellationToken) + public async ValueTask PeekAsync(CancellationToken cancellationToken) { //If we already have a byte read but not consumed, do nothing. if (_hasPeekByte) @@ -85,69 +86,80 @@ protected static void ValidateBufferArgs(byte[] buffer, int offset, int length) throw new ArgumentNullException(nameof(buffer)); } +#if DEBUG // let it fail with OutOfRange in RELEASE mode if (offset < 0) { - throw new ArgumentOutOfRangeException(nameof(offset), "Buffer offset is smaller than zero."); + throw new ArgumentOutOfRangeException(nameof(offset), "Buffer offset must be >= 0"); } if (length < 0) { - throw new ArgumentOutOfRangeException(nameof(length), "Buffer length is smaller than zero."); + throw new ArgumentOutOfRangeException(nameof(length), "Buffer length must be >= 0"); } if (offset + length > buffer.Length) { - throw new ArgumentOutOfRangeException(nameof(buffer), "Not enough data."); + throw new ArgumentOutOfRangeException(nameof(buffer), "Not enough data"); } +#endif } - public virtual async Task ReadAsync(byte[] buffer, int offset, int length) + public virtual async ValueTask ReadAsync(byte[] buffer, int offset, int length) { return await ReadAsync(buffer, offset, length, CancellationToken.None); } - public abstract Task ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); + public abstract ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); - public virtual async Task ReadAllAsync(byte[] buffer, int offset, int length) + public virtual async ValueTask ReadAllAsync(byte[] buffer, int offset, int length) { return await ReadAllAsync(buffer, offset, length, CancellationToken.None); } - public virtual async Task ReadAllAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) + public virtual async ValueTask ReadAllAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { ValidateBufferArgs(buffer, offset, length); if (cancellationToken.IsCancellationRequested) - { return await Task.FromCanceled(cancellationToken); - } - var retrieved = 0; + if (length <= 0) + return 0; - //If we previously peeked a byte, we need to use that first. + // If we previously peeked a byte, we need to use that first. + var totalBytes = 0; if (_hasPeekByte) { - buffer[offset + retrieved++] = _peekBuffer[0]; + buffer[offset++] = _peekBuffer[0]; _hasPeekByte = false; + if (1 == length) + { + Debug.Assert(totalBytes == 1); // what else? + return 1; // we're done + } + ++totalBytes; } - while (retrieved < length) + var remaining = length - totalBytes; + Debug.Assert(remaining > 0); // any other possible cases should have been handled already + while (true) { - if (cancellationToken.IsCancellationRequested) + var numBytes = await ReadAsync(buffer, offset, remaining, cancellationToken); + totalBytes += numBytes; + if (totalBytes >= length) { - return await Task.FromCanceled(cancellationToken); + return totalBytes; // we're done } - var returnedCount = await ReadAsync(buffer, offset + retrieved, length - retrieved, cancellationToken); - if (returnedCount <= 0) + if (numBytes <= 0) { throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "Cannot read, Remote side has closed"); } - retrieved += returnedCount; + + remaining -= numBytes; + offset += numBytes; } - return retrieved; } public virtual async Task WriteAsync(byte[] buffer) @@ -176,4 +188,4 @@ public virtual async Task FlushAsync() protected abstract void Dispose(bool disposing); } -} \ No newline at end of file +} diff --git a/test/netstd/Client/Performance/PerformanceTests.cs b/test/netstd/Client/Performance/PerformanceTests.cs new file mode 100644 index 00000000000..041d12eaea9 --- /dev/null +++ b/test/netstd/Client/Performance/PerformanceTests.cs @@ -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. + +using System; +using System.Collections.Generic; +using System.Text; +using ThriftTest; +using Thrift.Collections; +using Thrift.Protocol; +using System.Threading; +using Thrift.Transport.Client; +using System.Threading.Tasks; +using System.Diagnostics; +using Thrift.Transport; + +namespace Client.Tests +{ + public class PerformanceTests + { + private CancellationTokenSource Cancel; + private CrazyNesting Testdata; + private TMemoryBufferTransport MemBuffer; + private TTransport Transport; + private LayeredChoice Layered; + + internal static int Execute() + { + var instance = new PerformanceTests(); + instance.ProtocolPeformanceTestAsync().Wait(); + + // debug only + if (Debugger.IsAttached) + { + Console.Write("Hit ENTER ..."); + Console.ReadKey(); + } + + return 0; + } + + private async Task ProtocolPeformanceTestAsync() + { + Console.WriteLine("Setting up for ProtocolPeformanceTestAsync ..."); + Cancel = new CancellationTokenSource(); + Testdata = TestDataFactory.CreateCrazyNesting(); + + foreach (var layered in Enum.GetValues(typeof(LayeredChoice))) + { + Layered = (LayeredChoice)layered; + + await RunTestAsync(async (bool b) => { return await GenericProtocolFactory(b); }); + await RunTestAsync(async (bool b) => { return await GenericProtocolFactory(b); }); + //await RunTestAsync(async (bool b) => { return await GenericProtocolFactory(b); }); + } + } + + private Task GenericProtocolFactory(bool forWrite) + where T : TProtocol + { + var oldTrans = Transport; + try + { + // read happens after write here, so let's take over the written bytes + if (forWrite) + MemBuffer = new TMemoryBufferTransport(); + else + MemBuffer = new TMemoryBufferTransport(MemBuffer.GetBuffer()); + + // layered transports anyone? + switch (Layered) + { + case LayeredChoice.None: + Transport = MemBuffer; + break; + case LayeredChoice.Framed: + Transport = new TFramedTransport(MemBuffer); + break; + case LayeredChoice.Buffered: + Transport = new TBufferedTransport(MemBuffer); + break; + default: + Debug.Assert(false); + break; + } + + if (!Transport.IsOpen) + Transport.OpenAsync().Wait(); + + var instance = (T)Activator.CreateInstance(typeof(T), Transport); + return Task.FromResult(instance); + } + finally + { + if (oldTrans is IDisposable) + (oldTrans as IDisposable).Dispose(); + } + } + + private string GetProtocolTransportName(TProtocol proto) + { + var name = Transport.GetType().Name; + if (name.Equals(MemBuffer.GetType().Name)) + name = string.Empty; + else + name = " + " + name; + + name = proto.GetType().Name + name; + return name; + } + + + private async Task RunTestAsync(Func> factory) + { + var stop = new Stopwatch(); + + var proto = await factory(true); + stop.Start(); + await Testdata.WriteAsync(proto, Cancel.Token); + await Transport.FlushAsync(Cancel.Token); + stop.Stop(); + Console.WriteLine("RunTestAsync({0}): write = {1} msec", + GetProtocolTransportName(proto), + stop.ElapsedMilliseconds); + + var restored = new CrazyNesting(); + proto = await factory(false); + stop.Start(); + await restored.ReadAsync(proto, Cancel.Token); + stop.Stop(); + Console.WriteLine("RunTestAsync({0}): read = {1} msec", + GetProtocolTransportName(proto), + stop.ElapsedMilliseconds); + } + + } +} diff --git a/test/netstd/Client/Performance/TestDataFactory.cs b/test/netstd/Client/Performance/TestDataFactory.cs new file mode 100644 index 00000000000..98962857cb5 --- /dev/null +++ b/test/netstd/Client/Performance/TestDataFactory.cs @@ -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. + +using System; +using System.Collections.Generic; +using System.Text; +using ThriftTest; +using Thrift.Collections; + +namespace Client.Tests +{ + + static class TestDataFactory + { + public static CrazyNesting CreateCrazyNesting(int count = 10) + { + if (count <= 0) + return null; + + return new CrazyNesting() + { + Binary_field = CreateBytesArray(count), + List_field = CreateListField(count), + Set_field = CreateSetField(count), + String_field = string.Format("data level {0}", count) + }; + } + + private static THashSet CreateSetField(int count) + { + var retval = new THashSet(); + for (var i = 0; i < count; ++i) + retval.Add(CreateInsanity(count)); + return retval; + } + + private static Insanity CreateInsanity(int count) + { + return new Insanity() + { + UserMap = CreateUserMap(count), + Xtructs = CreateXtructs(count) + }; + } + + private static List CreateXtructs(int count) + { + var retval = new List(); + for (var i = 0; i < count; ++i) + retval.Add(CreateXtruct(count)); + return retval; + } + + private static Xtruct CreateXtruct(int count) + { + return new Xtruct() + { + Byte_thing = (sbyte)(count % 128), + I32_thing = count, + I64_thing = count, + String_thing = string.Format("data level {0}", count) + }; + } + + private static Dictionary CreateUserMap(int count) + { + var retval = new Dictionary(); + retval.Add(Numberz.ONE, count); + retval.Add(Numberz.TWO, count); + retval.Add(Numberz.THREE, count); + retval.Add(Numberz.FIVE, count); + retval.Add(Numberz.SIX, count); + retval.Add(Numberz.EIGHT, count); + return retval; + } + + private static List, Dictionary>>>>> CreateListField(int count) + { + var retval = new List, Dictionary>>>>>(); + for (var i = 0; i < count; ++i) + retval.Add(CreateListFieldData(count)); + return retval; + } + + private static Dictionary, Dictionary>>>> CreateListFieldData(int count) + { + var retval = new Dictionary, Dictionary>>>>(); + for (var i = 0; i < count; ++i) + retval.Add( CreateIntHashSet(count), CreateListFieldDataDict(count)); + return retval; + } + + private static THashSet CreateIntHashSet(int count) + { + var retval = new THashSet(); + for (var i = 0; i < count; ++i) + retval.Add(i); + return retval; + } + + private static Dictionary>>> CreateListFieldDataDict(int count) + { + var retval = new Dictionary>>>(); + for (var i = 0; i < count; ++i) + retval.Add(i, CreateListFieldDataDictValue(count)); + return retval; + } + + private static THashSet>> CreateListFieldDataDictValue(int count) + { + var retval = new THashSet>>(); + for (var i = 0; i < count; ++i) + retval.Add( CreateListFieldDataDictValueList(count)); + return retval; + } + + private static List> CreateListFieldDataDictValueList(int count) + { + var retval = new List>(); + for (var i = 0; i < count; ++i) + retval.Add(CreateListFieldDataDictValueListDict(count)); + return retval; + } + + private static Dictionary CreateListFieldDataDictValueListDict(int count) + { + var retval = new Dictionary(); + retval.Add(CreateInsanity(count), string.Format("data level {0}", count)); + return retval; + } + + private static byte[] CreateBytesArray(int count) + { + var retval = new byte[count]; + for (var i = 0; i < count; ++i) + retval[i] = (byte)(i % 0xFF); + return retval; + } + } +} diff --git a/test/netstd/Client/Program.cs b/test/netstd/Client/Program.cs index 8d973c4804a..62933e62e6f 100644 --- a/test/netstd/Client/Program.cs +++ b/test/netstd/Client/Program.cs @@ -48,6 +48,8 @@ public static int Main(string[] args) { case "client": return TestClient.Execute(subArgs); + case "performance": + return Tests.PerformanceTests.Execute(); case "--help": PrintHelp(); return 0; @@ -61,7 +63,8 @@ public static int Main(string[] args) private static void PrintHelp() { Console.WriteLine("Usage:"); - Console.WriteLine(" Client client [options]'"); + Console.WriteLine(" Client client [options]"); + Console.WriteLine(" Client performance"); Console.WriteLine(" Client --help"); Console.WriteLine(""); From 936944384fc925af696a1e3cec8dad33f94c7cb3 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 5 Jun 2019 22:02:55 +0200 Subject: [PATCH 295/756] THRIFT-4879 general performance improvements for netstd library Client: netstd Patch: Jens Geyer Removing obsolete (and finally incorrect) assertion. --- lib/netstd/Thrift/Transport/TTransport.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/netstd/Thrift/Transport/TTransport.cs b/lib/netstd/Thrift/Transport/TTransport.cs index fd802eca886..7998012025e 100644 --- a/lib/netstd/Thrift/Transport/TTransport.cs +++ b/lib/netstd/Thrift/Transport/TTransport.cs @@ -134,7 +134,6 @@ public virtual async ValueTask ReadAllAsync(byte[] buffer, int offset, int _hasPeekByte = false; if (1 == length) { - Debug.Assert(totalBytes == 1); // what else? return 1; // we're done } ++totalBytes; From 47f6317336b2d8fbd1249a1a49aa561ee052719f Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 6 Jun 2019 22:42:58 +0200 Subject: [PATCH 296/756] THRIFT-4881 Allow TLS1.1 and TLS1.2 even when not configured as systemwide default Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas | 13 ++ lib/delphi/src/Thrift.Transport.WinHTTP.pas | 42 +++++ lib/delphi/src/Thrift.Transport.pas | 14 +- lib/delphi/src/Thrift.WinHTTP.pas | 177 +++++++++++++++++- lib/delphi/test/TestClient.pas | 7 +- 5 files changed, 249 insertions(+), 4 deletions(-) diff --git a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas index cdfb541887d..620bebadb2c 100644 --- a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas @@ -68,9 +68,12 @@ TMsxmlHTTPClientImpl = class( TTransportImpl, IHTTPClient) function GetSendTimeout: Integer; procedure SetReadTimeout(const Value: Integer); function GetReadTimeout: Integer; + function GetSecureProtocols : TSecureProtocols; + procedure SetSecureProtocols( const value : TSecureProtocols); function GetCustomHeaders: IThriftDictionary; procedure SendRequest; + property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout; property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout; property SendTimeout: Integer read GetSendTimeout write SetSendTimeout; @@ -173,6 +176,16 @@ procedure TMsxmlHTTPClientImpl.SetReadTimeout(const Value: Integer); FReadTimeout := Value; end; +function TMsxmlHTTPClientImpl.GetSecureProtocols : TSecureProtocols; +begin + Result := []; +end; + +procedure TMsxmlHTTPClientImpl.SetSecureProtocols( const value : TSecureProtocols); +begin + raise TTransportExceptionBadArgs.Create('SetSecureProtocols: Not supported with '+ClassName); +end; + function TMsxmlHTTPClientImpl.GetCustomHeaders: IThriftDictionary; begin Result := FCustomHeaders; diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas index aac2aeaf298..8b4a7bc8362 100644 --- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas @@ -46,8 +46,10 @@ TWinHTTPClientImpl = class( TTransportImpl, IHTTPClient) FSendTimeout : Integer; FReadTimeout : Integer; FCustomHeaders : IThriftDictionary; + FSecureProtocols : TSecureProtocols; function CreateRequest: IWinHTTPRequest; + function SecureProtocolsAsWinHTTPFlags : Cardinal; private type THTTPResponseStream = class( TThriftStreamImpl) @@ -82,9 +84,12 @@ THTTPResponseStream = class( TThriftStreamImpl) function GetSendTimeout: Integer; procedure SetReadTimeout(const Value: Integer); function GetReadTimeout: Integer; + function GetSecureProtocols : TSecureProtocols; + procedure SetSecureProtocols( const value : TSecureProtocols); function GetCustomHeaders: IThriftDictionary; procedure SendRequest; + property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout; property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout; property SendTimeout: Integer read GetSendTimeout write SetSendTimeout; @@ -111,6 +116,8 @@ constructor TWinHTTPClientImpl.Create(const AUri: string); FSendTimeout := 30 * 1000; FReadTimeout := 30 * 1000; + FSecureProtocols := DEFAULT_THRIFT_SECUREPROTOCOLS; + FCustomHeaders := TThriftDictionaryImpl.Create; FOutputMemoryStream := TMemoryStream.Create; end; @@ -133,6 +140,8 @@ function TWinHTTPClientImpl.CreateRequest: IWinHTTPRequest; url := TWinHTTPUrlImpl.Create( FUri); session := TWinHTTPSessionImpl.Create('Apache Thrift Delphi Client'); + session.EnableSecureProtocols( SecureProtocolsAsWinHTTPFlags); + connect := session.Connect( url.HostName, url.Port); sPath := url.UrlPath + url.ExtraInfo; @@ -148,6 +157,29 @@ function TWinHTTPClientImpl.CreateRequest: IWinHTTPRequest; end; end; + +function TWinHTTPClientImpl.SecureProtocolsAsWinHTTPFlags : Cardinal; +const + PROTOCOL_MAPPING : array[TSecureProtocol] of Cardinal = ( + WINHTTP_FLAG_SECURE_PROTOCOL_SSL2, + WINHTTP_FLAG_SECURE_PROTOCOL_SSL3, + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1, + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1, + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 + ); +var + prot : TSecureProtocol; + protos : TSecureProtocols; +begin + result := 0; + protos := GetSecureProtocols; + for prot := Low(TSecureProtocol) to High(TSecureProtocol) do begin + if prot in protos + then result := result or PROTOCOL_MAPPING[prot]; + end; +end; + + function TWinHTTPClientImpl.GetDnsResolveTimeout: Integer; begin Result := FDnsResolveTimeout; @@ -188,6 +220,16 @@ procedure TWinHTTPClientImpl.SetReadTimeout(const Value: Integer); FReadTimeout := Value; end; +function TWinHTTPClientImpl.GetSecureProtocols : TSecureProtocols; +begin + Result := FSecureProtocols; +end; + +procedure TWinHTTPClientImpl.SetSecureProtocols( const value : TSecureProtocols); +begin + FSecureProtocols := Value; +end; + function TWinHTTPClientImpl.GetCustomHeaders: IThriftDictionary; begin Result := FCustomHeaders; diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index 1f8fdb0b239..c2071df89da 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -118,8 +118,15 @@ TTransportExceptionEndOfFile = class (TTransportExceptionSpecialized); TTransportExceptionBadArgs = class (TTransportExceptionSpecialized); TTransportExceptionInterrupted = class (TTransportExceptionSpecialized); + TSecureProtocol = ( + SSL_2, SSL_3, TLS_1, // outdated, for compatibilty only + TLS_1_1, TLS_1_2 // secure (as of today) + ); + + TSecureProtocols = set of TSecureProtocol; + IHTTPClient = interface( ITransport ) - ['{BA142D12-8AE6-4B50-9E33-6B7843B21D73}'] + ['{7BF615DD-8680-4004-A5B2-88947BA3BA3D}'] procedure SetDnsResolveTimeout(const Value: Integer); function GetDnsResolveTimeout: Integer; procedure SetConnectionTimeout(const Value: Integer); @@ -130,12 +137,15 @@ TTransportExceptionInterrupted = class (TTransportExceptionSpecialized); function GetReadTimeout: Integer; function GetCustomHeaders: IThriftDictionary; procedure SendRequest; + function GetSecureProtocols : TSecureProtocols; + procedure SetSecureProtocols( const value : TSecureProtocols); property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout; property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout; property SendTimeout: Integer read GetSendTimeout write SetSendTimeout; property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout; property CustomHeaders: IThriftDictionary read GetCustomHeaders; + property SecureProtocols : TSecureProtocols read GetSecureProtocols write SetSecureProtocols; end; IServerTransport = interface @@ -373,6 +383,8 @@ procedure TFramedTransportImpl_Initialize; const DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms + DEFAULT_THRIFT_SECUREPROTOCOLS = [ TSecureProtocol.TLS_1_1, TSecureProtocol.TLS_1_2]; + implementation diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index 6ad84006656..4b98f69f2aa 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -84,6 +84,16 @@ function WinHttpOpenRequest( const hConnect : HINTERNET; const dwFlags : DWORD ) : HINTERNET; stdcall; +function WinHttpQueryOption( const hInternet : HINTERNET; + const dwOption : DWORD; + const pBuffer : Pointer; + var dwBufferLength : DWORD) : BOOL; stdcall; + +function WinHttpSetOption( const hInternet : HINTERNET; + const dwOption : DWORD; + const pBuffer : Pointer; + const dwBufferLength : DWORD) : BOOL; stdcall; + function WinHttpSetTimeouts( const hRequestOrSession : HINTERNET; const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32 ) : BOOL; stdcall; @@ -193,6 +203,157 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; INTERNET_SCHEME_HTTP = INTERNET_SCHEME(1); INTERNET_SCHEME_HTTPS = INTERNET_SCHEME(2); + WINHTTP_NO_CLIENT_CERT_CONTEXT = nil; + + // options manifests for WinHttp{Query|Set}Option + WINHTTP_OPTION_CALLBACK = 1; + WINHTTP_OPTION_RESOLVE_TIMEOUT = 2; + WINHTTP_OPTION_CONNECT_TIMEOUT = 3; + WINHTTP_OPTION_CONNECT_RETRIES = 4; + WINHTTP_OPTION_SEND_TIMEOUT = 5; + WINHTTP_OPTION_RECEIVE_TIMEOUT = 6; + WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT = 7; + WINHTTP_OPTION_HANDLE_TYPE = 9; + WINHTTP_OPTION_READ_BUFFER_SIZE = 12; + WINHTTP_OPTION_WRITE_BUFFER_SIZE = 13; + WINHTTP_OPTION_PARENT_HANDLE = 21; + WINHTTP_OPTION_EXTENDED_ERROR = 24; + WINHTTP_OPTION_SECURITY_FLAGS = 31; + WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT = 32; + WINHTTP_OPTION_URL = 34; + WINHTTP_OPTION_SECURITY_KEY_BITNESS = 36; + WINHTTP_OPTION_PROXY = 38; + WINHTTP_OPTION_USER_AGENT = 41; + WINHTTP_OPTION_CONTEXT_VALUE = 45; + WINHTTP_OPTION_CLIENT_CERT_CONTEXT = 47; + WINHTTP_OPTION_REQUEST_PRIORITY = 58; + WINHTTP_OPTION_HTTP_VERSION = 59; + WINHTTP_OPTION_DISABLE_FEATURE = 63; + WINHTTP_OPTION_CODEPAGE = 68; + WINHTTP_OPTION_MAX_CONNS_PER_SERVER = 73; + WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER = 74; + WINHTTP_OPTION_AUTOLOGON_POLICY = 77; + WINHTTP_OPTION_SERVER_CERT_CONTEXT = 78; + WINHTTP_OPTION_ENABLE_FEATURE = 79; + WINHTTP_OPTION_WORKER_THREAD_COUNT = 80; + WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT = 81; + WINHTTP_OPTION_PASSPORT_COBRANDING_URL = 82; + WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH = 83; + WINHTTP_OPTION_SECURE_PROTOCOLS = 84; + WINHTTP_OPTION_ENABLETRACING = 85; + WINHTTP_OPTION_PASSPORT_SIGN_OUT = 86; + WINHTTP_OPTION_PASSPORT_RETURN_URL = 87; + WINHTTP_OPTION_REDIRECT_POLICY = 88; + WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS = 89; + WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE = 90; + WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE = 91; + WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE = 92; + WINHTTP_OPTION_CONNECTION_INFO = 93; + WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST = 94; + WINHTTP_OPTION_SPN = 96; + WINHTTP_OPTION_GLOBAL_PROXY_CREDS = 97; + WINHTTP_OPTION_GLOBAL_SERVER_CREDS = 98; + WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT = 99; + WINHTTP_OPTION_REJECT_USERPWD_IN_URL = 100; + WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS = 101; + WINHTTP_OPTION_RECEIVE_PROXY_CONNECT_RESPONSE = 103; + WINHTTP_OPTION_IS_PROXY_CONNECT_RESPONSE = 104; + WINHTTP_OPTION_SERVER_SPN_USED = 106; + WINHTTP_OPTION_PROXY_SPN_USED = 107; + WINHTTP_OPTION_SERVER_CBT = 108; + // + WINHTTP_FIRST_OPTION = WINHTTP_OPTION_CALLBACK; + WINHTTP_LAST_OPTION = WINHTTP_OPTION_SERVER_CBT; + + WINHTTP_OPTION_USERNAME = $1000; + WINHTTP_OPTION_PASSWORD = $1001; + WINHTTP_OPTION_PROXY_USERNAME = $1002; + WINHTTP_OPTION_PROXY_PASSWORD = $1003; + + // manifest value for WINHTTP_OPTION_MAX_CONNS_PER_SERVER and WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER + WINHTTP_CONNS_PER_SERVER_UNLIMITED = $FFFFFFFF; + + // values for WINHTTP_OPTION_AUTOLOGON_POLICY + WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM = 0; + WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW = 1; + WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH = 2; + + WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT = WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM; + + // values for WINHTTP_OPTION_REDIRECT_POLICY + WINHTTP_OPTION_REDIRECT_POLICY_NEVER = 0; + WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP = 1; + WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS = 2; + + WINHTTP_OPTION_REDIRECT_POLICY_LAST = WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS; + WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP; + + WINHTTP_DISABLE_PASSPORT_AUTH = $00000000; + WINHTTP_ENABLE_PASSPORT_AUTH = $10000000; + WINHTTP_DISABLE_PASSPORT_KEYRING = $20000000; + WINHTTP_ENABLE_PASSPORT_KEYRING = $40000000; + + // values for WINHTTP_OPTION_DISABLE_FEATURE + WINHTTP_DISABLE_COOKIES = $00000001; + WINHTTP_DISABLE_REDIRECTS = $00000002; + WINHTTP_DISABLE_AUTHENTICATION = $00000004; + WINHTTP_DISABLE_KEEP_ALIVE = $00000008; + + // values for WINHTTP_OPTION_ENABLE_FEATURE + WINHTTP_ENABLE_SSL_REVOCATION = $00000001; + WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION = $00000002; + + // values for WINHTTP_OPTION_SPN + WINHTTP_DISABLE_SPN_SERVER_PORT = $00000000; + WINHTTP_ENABLE_SPN_SERVER_PORT = $00000001; + WINHTTP_OPTION_SPN_MASK = WINHTTP_ENABLE_SPN_SERVER_PORT; + + // winhttp handle types + WINHTTP_HANDLE_TYPE_SESSION = 1; + WINHTTP_HANDLE_TYPE_CONNECT = 2; + WINHTTP_HANDLE_TYPE_REQUEST = 3; + + // values for auth schemes + WINHTTP_AUTH_SCHEME_BASIC = $00000001; + WINHTTP_AUTH_SCHEME_NTLM = $00000002; + WINHTTP_AUTH_SCHEME_PASSPORT = $00000004; + WINHTTP_AUTH_SCHEME_DIGEST = $00000008; + WINHTTP_AUTH_SCHEME_NEGOTIATE = $00000010; + + // WinHttp supported Authentication Targets + WINHTTP_AUTH_TARGET_SERVER = $00000000; + WINHTTP_AUTH_TARGET_PROXY = $00000001; + + // values for WINHTTP_OPTION_SECURITY_FLAGS + + // query only + SECURITY_FLAG_SECURE = $00000001; // can query only + SECURITY_FLAG_STRENGTH_WEAK = $10000000; + SECURITY_FLAG_STRENGTH_MEDIUM = $40000000; + SECURITY_FLAG_STRENGTH_STRONG = $20000000; + + // Secure connection error status flags + WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED = $00000001; + WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT = $00000002; + WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED = $00000004; + WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA = $00000008; + WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID = $00000010; + WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID = $00000020; + WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE = $00000040; + WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR = $80000000; + + WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 = $00000008; + WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 = $00000020; + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = $00000080; + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = $00000200; + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = $00000800; + + // Note: SECURE_PROTOCOL_ALL does not include TLS1.1 and higher! + WINHTTP_FLAG_SECURE_PROTOCOL_ALL = WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 + or WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 + or WINHTTP_FLAG_SECURE_PROTOCOL_TLS1; + + const WINHTTP_ERROR_BASE = 12000; ERROR_WINHTTP_OUT_OF_HANDLES = WINHTTP_ERROR_BASE + 1; @@ -254,6 +415,7 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; or WINHTTP_FLAG_ESCAPE_DISABLE; + type IWinHTTPRequest = interface ['{35C6D9D4-FDCE-42C6-B84C-9294E6FB904C}'] @@ -274,10 +436,11 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; end; IWinHTTPSession = interface - ['{B6F8BD98-0605-4A9E-B671-4CB191D74A5E}'] + ['{261ADCB7-5465-4407-8840-468C17F009F0}'] function Handle : HINTERNET; function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection; function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; + function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean; end; IWinHTTPUrl = interface @@ -339,7 +502,7 @@ TWinHTTPSessionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPSession) // IWinHTTPSession function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection; function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; - + function EnableSecureProtocols( const aFlagSet : DWORD) : Boolean; public constructor Create( const aAgent : UnicodeString; const aAccessType : DWORD = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; @@ -444,6 +607,8 @@ function WinHttpConnect; stdcall; external WINHTTP_DLL; function WinHttpOpenRequest; stdcall; external WINHTTP_DLL; function WinHttpSendRequest; stdcall; external WINHTTP_DLL; function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL; +function WinHttpQueryOption; stdcall; external WINHTTP_DLL; +function WinHttpSetOption; stdcall; external WINHTTP_DLL; function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL; function WinHttpWriteData; stdcall; external WINHTTP_DLL; function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL; @@ -521,6 +686,14 @@ function TWinHTTPSessionImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout end; +function TWinHTTPSessionImpl.EnableSecureProtocols( const aFlagSet : DWORD) : Boolean; +var dwSize : DWORD; +begin + dwSize := SizeOf(aFlagSet); + result := WinHttpSetOption( Handle, WINHTTP_OPTION_SECURE_PROTOCOLS, @aFlagset, dwSize); +end; + + { TWinHTTPConnectionImpl } constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT); diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas index 55bf92b705f..ebda7c6d4cd 100644 --- a/lib/delphi/test/TestClient.pas +++ b/lib/delphi/test/TestClient.pas @@ -29,6 +29,8 @@ {$DEFINE SupportsAsync} {$ifend} +{$WARN SYMBOL_PLATFORM OFF} // Win32Check + interface uses @@ -1354,6 +1356,7 @@ function TClientThread.InitializeHttpTransport( const aTimeoutSetting : Integer) procedure TClientThread.InitializeProtocolTransportStack; var streamtrans : IStreamTransport; + canSSL : Boolean; const DEBUG_TIMEOUT = 30 * 1000; RELEASE_TIMEOUT = DEFAULT_THRIFT_TIMEOUT; @@ -1363,6 +1366,7 @@ procedure TClientThread.InitializeProtocolTransportStack; // needed for HTTP clients as they utilize the MSXML COM components OleCheck( CoInitialize( nil)); + canSSL := FALSE; case FSetup.endpoint of trns_Sockets: begin Console.WriteLine('Using sockets ('+FSetup.host+' port '+IntToStr(FSetup.port)+')'); @@ -1374,6 +1378,7 @@ procedure TClientThread.InitializeProtocolTransportStack; trns_WinHttp: begin Console.WriteLine('Using HTTPClient'); FTransport := InitializeHttpTransport( HTTP_TIMEOUTS); + canSSL := TRUE; end; trns_EvHttp: begin @@ -1403,7 +1408,7 @@ procedure TClientThread.InitializeProtocolTransportStack; FTransport := TBufferedTransportImpl.Create( streamtrans, 32); // small buffer to test read() end; - if FSetup.useSSL then begin + if FSetup.useSSL and not canSSL then begin raise Exception.Create('SSL/TLS not implemented'); end; From 83ff75377706eee2033f8de0208be2a61de5fbc6 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 6 Jun 2019 22:46:03 +0200 Subject: [PATCH 297/756] THRIFT-4882 Autodetect proxy settings with WinHTTP Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas | 4 +- lib/delphi/src/Thrift.Transport.WinHTTP.pas | 15 +- lib/delphi/src/Thrift.Utils.pas | 3 + lib/delphi/src/Thrift.WinHTTP.pas | 219 +++++++++++++++++- lib/delphi/test/TestClient.pas | 26 ++- 5 files changed, 253 insertions(+), 14 deletions(-) diff --git a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas index 620bebadb2c..c666e7fedc9 100644 --- a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas @@ -121,8 +121,8 @@ function TMsxmlHTTPClientImpl.CreateRequest: IXMLHTTPRequest; then srvHttp.setTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout); Result.open('POST', FUri, False, '', ''); - Result.setRequestHeader( 'Content-Type', 'application/x-thrift'); - Result.setRequestHeader( 'Accept', 'application/x-thrift'); + Result.setRequestHeader( 'Content-Type', THRIFT_MIMETYPE); + Result.setRequestHeader( 'Accept', THRIFT_MIMETYPE); Result.setRequestHeader( 'User-Agent', 'Delphi/IHTTPClient'); for pair in FCustomHeaders do begin diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas index 8b4a7bc8362..48b74a6648f 100644 --- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas @@ -139,22 +139,25 @@ function TWinHTTPClientImpl.CreateRequest: IWinHTTPRequest; begin url := TWinHTTPUrlImpl.Create( FUri); - session := TWinHTTPSessionImpl.Create('Apache Thrift Delphi Client'); + session := TWinHTTPSessionImpl.Create('Apache Thrift Delphi WinHTTP'); session.EnableSecureProtocols( SecureProtocolsAsWinHTTPFlags); connect := session.Connect( url.HostName, url.Port); sPath := url.UrlPath + url.ExtraInfo; - result := connect.OpenRequest( (url.Scheme = 'https'), 'POST', sPath, 'application/x-thrift'); + result := connect.OpenRequest( (url.Scheme = 'https'), 'POST', sPath, THRIFT_MIMETYPE); // setting a timeout value to 0 (zero) means "no timeout" for that setting result.SetTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout); - result.AddRequestHeader( 'Content-Type: application/x-thrift', WINHTTP_ADDREQ_FLAG_ADD); - + // headers + result.AddRequestHeader( 'Content-Type: '+THRIFT_MIMETYPE, WINHTTP_ADDREQ_FLAG_ADD); for pair in FCustomHeaders do begin Result.AddRequestHeader( pair.Key +': '+ pair.Value, WINHTTP_ADDREQ_FLAG_ADD); end; + + // AutoProxy support + result.TryAutoProxy( FUri); end; @@ -290,11 +293,11 @@ procedure TWinHTTPClientImpl.SendRequest; // send all data immediately, since we have it in memory if not http.SendRequest( pData, len, 0) - then raise TTransportExceptionUnknown.Create('send request error'); + then raise TTransportExceptionUnknown.Create('send request error '+IntToStr(GetLastError)); // end request and start receiving if not http.FlushAndReceiveResponse - then raise TTransportExceptionInterrupted.Create('flush/receive error'); + then raise TTransportExceptionInterrupted.Create('flush/receive error '+IntToStr(GetLastError)); FInputStream := THTTPResponseStream.Create(http); end; diff --git a/lib/delphi/src/Thrift.Utils.pas b/lib/delphi/src/Thrift.Utils.pas index 11c4f3e71fb..ede26564615 100644 --- a/lib/delphi/src/Thrift.Utils.pas +++ b/lib/delphi/src/Thrift.Utils.pas @@ -93,6 +93,9 @@ StringUtils = class sealed end; +const + THRIFT_MIMETYPE = 'application/x-thrift'; + {$IFDEF Win64} function InterlockedExchangeAdd64( var Addend : Int64; Value : Int64) : Int64; {$ENDIF} diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index 4b98f69f2aa..b26f6ba2a66 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -63,6 +63,40 @@ URL_COMPONENTS = record LPURL_COMPONENTSW = LPURL_COMPONENTS; + // When retrieving proxy data, an application must free the lpszProxy and + // lpszProxyBypass strings contained in this structure (if they are non-NULL) + // using the GlobalFree function. + LPWINHTTP_PROXY_INFO = ^WINHTTP_PROXY_INFO; + WINHTTP_PROXY_INFO = record + dwAccessType : DWORD; // see WINHTTP_ACCESS_* types below + lpszProxy : LPWSTR; // proxy server list + lpszProxyBypass : LPWSTR; // proxy bypass list + end; + + LPWINHTTP_PROXY_INFOW = ^WINHTTP_PROXY_INFOW; + WINHTTP_PROXY_INFOW = WINHTTP_PROXY_INFO; + + + WINHTTP_AUTOPROXY_OPTIONS = record + dwFlags : DWORD; + dwAutoDetectFlags : DWORD; + lpszAutoConfigUrl : LPCWSTR; + lpvReserved : LPVOID; + dwReserved : DWORD; + fAutoLogonIfChallenged : BOOL; + end; + + + WINHTTP_CURRENT_USER_IE_PROXY_CONFIG = record + fAutoDetect : BOOL; + lpszAutoConfigUrl : LPWSTR; + lpszProxy : LPWSTR; + lpszProxyBypass : LPWSTR; + end; + + + + function WinHttpCloseHandle( aHandle : HINTERNET) : BOOL; stdcall; function WinHttpOpen( const pszAgentW : LPCWSTR; @@ -104,6 +138,16 @@ function WinHttpAddRequestHeaders( const hRequest : HINTERNET; const dwModifiers : DWORD ) : BOOL; stdcall; +function WinHttpGetProxyForUrl( const hSession : HINTERNET; + const lpcwszUrl : LPCWSTR; + const options : WINHTTP_AUTOPROXY_OPTIONS; + const info : WINHTTP_PROXY_INFO + ) : BOOL; stdcall; + +function WinHttpGetIEProxyConfigForCurrentUser( var config : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG + ) : BOOL; stdcall; + + function WinHttpSendRequest( const hRequest : HINTERNET; const lpszHeaders : LPCWSTR; const dwHeadersLength : DWORD; @@ -353,6 +397,17 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; or WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 or WINHTTP_FLAG_SECURE_PROTOCOL_TLS1; + // AutoProxy + WINHTTP_AUTOPROXY_AUTO_DETECT = $00000001; + WINHTTP_AUTOPROXY_CONFIG_URL = $00000002; + WINHTTP_AUTOPROXY_HOST_KEEPCASE = $00000004; + WINHTTP_AUTOPROXY_HOST_LOWERCASE = $00000008; + WINHTTP_AUTOPROXY_RUN_INPROCESS = $00010000; + WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = $00020000; + + // Flags for dwAutoDetectFlags + WINHTTP_AUTO_DETECT_TYPE_DHCP = $00000001; + WINHTTP_AUTO_DETECT_TYPE_DNS_A = $00000002; const WINHTTP_ERROR_BASE = 12000; @@ -417,11 +472,16 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; type + IWinHTTPSession = interface; + IWinHTTPConnection = interface; + IWinHTTPRequest = interface - ['{35C6D9D4-FDCE-42C6-B84C-9294E6FB904C}'] + ['{0B7D095E-BB3D-4444-8686-5536E7D6437B}'] function Handle : HINTERNET; + function Connection : IWinHTTPConnection; function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; + procedure TryAutoProxy( const aUrl : string); function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean; function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD; function FlushAndReceiveResponse : Boolean; @@ -430,8 +490,9 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; end; IWinHTTPConnection = interface - ['{1C4F78B5-1525-4788-B638-A0E41BCF4D43}'] + ['{ED5BCA49-84D6-4CFE-BF18-3238B1FF2AFB}'] function Handle : HINTERNET; + function Session : IWinHTTPSession; function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest; end; @@ -519,6 +580,7 @@ TWinHTTPConnectionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPConnection) // IWinHTTPConnection function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest; + function Session : IWinHTTPSession; public constructor Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT); @@ -533,8 +595,10 @@ TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest) FConnection : IWinHTTPConnection; // IWinHTTPRequest + function Connection : IWinHTTPConnection; function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; + procedure TryAutoProxy( const aUrl : string); function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean; function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD; function FlushAndReceiveResponse : Boolean; @@ -595,6 +659,18 @@ TWinHTTPUrlImpl = class( TInterfacedObject, IWinHTTPUrl) end; + WINHTTP_PROXY_INFO_Helper = record helper for WINHTTP_PROXY_INFO + procedure Initialize; + procedure FreeAllocatedResources; + end; + + + WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper = record helper for WINHTTP_CURRENT_USER_IE_PROXY_CONFIG + procedure Initialize; + procedure FreeAllocatedResources; + end; + + EWinHTTPException = class(Exception); implementation @@ -610,6 +686,8 @@ function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL; function WinHttpQueryOption; stdcall; external WINHTTP_DLL; function WinHttpSetOption; stdcall; external WINHTTP_DLL; function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL; +function WinHttpGetProxyForUrl; stdcall; external WINHTTP_DLL; +function WinHttpGetIEProxyConfigForCurrentUser; stdcall; external WINHTTP_DLL; function WinHttpWriteData; stdcall; external WINHTTP_DLL; function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL; function WinHttpQueryHeaders; stdcall; external WINHTTP_DLL; @@ -619,6 +697,51 @@ function WinHttpCrackUrl; stdcall; external WINHTTP_DLL; function WinHttpCreateUrl; stdcall; external WINHTTP_DLL; +{ misc. record helper } + + +procedure GlobalFreeAndNil( var p : LPWSTR); +begin + if p <> nil then begin + GlobalFree( HGLOBAL( p)); + p := nil; + end; +end; + + +procedure WINHTTP_PROXY_INFO_Helper.Initialize; +begin + FillChar( Self, SizeOf(Self), 0); +end; + + +procedure WINHTTP_PROXY_INFO_Helper.FreeAllocatedResources; +// The caller must free the lpszProxy and lpszProxyBypass strings +// if they are non-NULL. Use GlobalFree to free the strings. +begin + GlobalFreeAndNil( lpszProxy); + GlobalFreeAndNil( lpszProxyBypass); + Initialize; +end; + + +procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.Initialize; +begin + FillChar( Self, SizeOf(Self), 0); +end; + + +procedure WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper.FreeAllocatedResources; +// The caller must free the lpszProxy, lpszProxyBypass and lpszAutoConfigUrl strings +// if they are non-NULL. Use GlobalFree to free the strings. +begin + GlobalFreeAndNil( lpszProxy); + GlobalFreeAndNil( lpszProxyBypass); + GlobalFreeAndNil( lpszAutoConfigUrl); + Initialize; +end; + + { TWinHTTPHandleObjectImpl } constructor TWinHTTPHandleObjectImpl.Create( const aHandle : HINTERNET); @@ -713,6 +836,12 @@ destructor TWinHTTPConnectionImpl.Destroy; end; +function TWinHTTPConnectionImpl.Session : IWinHTTPSession; +begin + result := FSession; +end; + + function TWinHTTPConnectionImpl.OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest; var dwFlags : DWORD; begin @@ -759,6 +888,12 @@ destructor TWinHTTPRequestImpl.Destroy; end; +function TWinHTTPRequestImpl.Connection : IWinHTTPConnection; +begin + result := FConnection; +end; + + function TWinHTTPRequestImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; begin result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout); @@ -771,6 +906,85 @@ function TWinHTTPRequestImpl.AddRequestHeader( const aHeader : string; const add end; +procedure TWinHTTPRequestImpl.TryAutoProxy( const aUrl : string); +// From MSDN: +// AutoProxy support is not fully integrated into the HTTP stack in WinHTTP. +// Before sending a request, the application must call WinHttpGetProxyForUrl +// to obtain the name of a proxy server and then call WinHttpSetOption using +// WINHTTP_OPTION_PROXY to set the proxy configuration on the WinHTTP request +// handle created by WinHttpOpenRequest. +// See https://docs.microsoft.com/en-us/windows/desktop/winhttp/winhttp-autoproxy-api +var + options : WINHTTP_AUTOPROXY_OPTIONS; + proxy : WINHTTP_PROXY_INFO; + ieProxy : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG; + dwSize : DWORD; +begin + // try AutoProxy via PAC first + proxy.Initialize; + try + FillChar( options, SizeOf(options), 0); + options.dwFlags := WINHTTP_AUTOPROXY_AUTO_DETECT; + options.dwAutoDetectFlags := WINHTTP_AUTO_DETECT_TYPE_DHCP or WINHTTP_AUTO_DETECT_TYPE_DNS_A; + options.fAutoLogonIfChallenged := TRUE; + if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin + dwSize := SizeOf(proxy); + WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize); + Exit; + end; + + finally + proxy.FreeAllocatedResources; + end; + + // Use IE settings as a fallback, useful in client (i.e. non-server) environments + ieProxy.Initialize; + try + if WinHttpGetIEProxyConfigForCurrentUser( ieProxy) + then begin + + // lpszAutoConfigUrl = "Use automatic proxy configuration" + if ieProxy.lpszAutoConfigUrl <> nil then begin + options.lpszAutoConfigUrl := ieProxy.lpszAutoConfigUrl; + options.dwFlags := options.dwFlags or WINHTTP_AUTOPROXY_CONFIG_URL; + + proxy.Initialize; + try + if WinHttpGetProxyForUrl( FConnection.Session.Handle, PChar(aUrl), options, proxy) then begin + dwSize := SizeOf(proxy); + WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize); + Exit; + end; + finally + proxy.FreeAllocatedResources; + end; + end; + + // lpszProxy = "use a proxy server" + if ieProxy.lpszProxy <> nil then begin + proxy.Initialize; + try + proxy.dwAccessType := WINHTTP_ACCESS_TYPE_NAMED_PROXY; + proxy.lpszProxy := ieProxy.lpszProxy; + proxy.lpszProxyBypass := ieProxy.lpszProxyBypass; + dwSize := SizeOf(proxy); + WinHttpSetOption( Handle, WINHTTP_OPTION_PROXY, @proxy, dwSize); + Exit; + finally + proxy.Initialize; // not FreeAllocatedResources, we only hold pointer copies! + end; + end; + + end; + + finally + ieProxy.FreeAllocatedResources; + end; +end; + + + + function TWinHTTPRequestImpl.SendRequest( const pBuf : Pointer; const dwBytes, dwExtra : DWORD) : Boolean; begin result := WinHttpSendRequest( FHandle, @@ -979,3 +1193,4 @@ procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString); end. + diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas index ebda7c6d4cd..677d416b59b 100644 --- a/lib/delphi/test/TestClient.pas +++ b/lib/delphi/test/TestClient.pas @@ -50,6 +50,7 @@ interface Thrift.Transport, Thrift.Stream, Thrift.Test, + Thrift.WinHTTP, Thrift.Utils, Thrift.Collections; @@ -1322,7 +1323,9 @@ procedure TClientThread.Execute; function TClientThread.InitializeHttpTransport( const aTimeoutSetting : Integer) : IHTTPClient; -var sUrl : string; +var sUrl : string; + comps : URL_COMPONENTS; + dwChars : DWORD; begin ASSERT( FSetup.endpoint in [trns_MsxmlHttp, trns_WinHttp]); @@ -1332,12 +1335,27 @@ function TClientThread.InitializeHttpTransport( const aTimeoutSetting : Integer) sUrl := sUrl + FSetup.host; + // add the port number if necessary and at the right place + FillChar( comps, SizeOf(comps), 0); + comps.dwStructSize := SizeOf(comps); + comps.dwSchemeLength := MAXINT; + comps.dwHostNameLength := MAXINT; + comps.dwUserNameLength := MAXINT; + comps.dwPasswordLength := MAXINT; + comps.dwUrlPathLength := MAXINT; + comps.dwExtraInfoLength := MAXINT; + Win32Check( WinHttpCrackUrl( PChar(sUrl), Length(sUrl), 0, comps)); case FSetup.port of - 80 : if FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port); - 443 : if not FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port); + 80 : if FSetup.useSSL then comps.nPort := FSetup.port; + 443 : if not FSetup.useSSL then comps.nPort := FSetup.port; else - if FSetup.port > 0 then sUrl := sUrl + ':'+ IntToStr(FSetup.port); + if FSetup.port > 0 then comps.nPort := FSetup.port; end; + dwChars := Length(sUrl) + 64; + SetLength( sUrl, dwChars); + Win32Check( WinHttpCreateUrl( comps, 0, @sUrl[1], dwChars)); + SetLength( sUrl, dwChars); + Console.WriteLine('Target URL: '+sUrl); case FSetup.endpoint of From b342bd9a614b792a566291350c89aec4e50dbd2c Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Mon, 3 Jun 2019 20:27:00 +0200 Subject: [PATCH 298/756] THRIFT-4884 Add serialisation performance test for Delphi Client: Delphi Patch: Jens Geyer --- lib/delphi/test/Performance/DataFactory.pas | 176 ++++++++++++++++++++ lib/delphi/test/Performance/PerfTests.pas | 173 +++++++++++++++++++ lib/delphi/test/TestClient.pas | 6 + lib/delphi/test/TestConstants.pas | 3 +- lib/delphi/test/client.dpr | 2 + 5 files changed, 359 insertions(+), 1 deletion(-) create mode 100644 lib/delphi/test/Performance/DataFactory.pas create mode 100644 lib/delphi/test/Performance/PerfTests.pas diff --git a/lib/delphi/test/Performance/DataFactory.pas b/lib/delphi/test/Performance/DataFactory.pas new file mode 100644 index 00000000000..e131822a3a6 --- /dev/null +++ b/lib/delphi/test/Performance/DataFactory.pas @@ -0,0 +1,176 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +unit DataFactory; + +interface + +uses + SysUtils, + Thrift.Collections, + Thrift.Test; + +type + TestDataFactory = class + strict protected + class function CreateSetField(const count : Integer) : IHashSet< IInsanity>; static; + class function CreateInsanity(const count : Integer) : IInsanity; static; + class function CreateBytesArray(const count : Integer) : TBytes; static; + class function CreateXtructs(const count : Integer) : IThriftList< IXtruct>; static; + class function CreateXtruct(const count : Integer) : IXtruct; static; + class function CreateListField(const count : Integer) : IThriftList< IThriftDictionary< IHashSet< Integer>, IThriftDictionary< Integer, IHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>>; static; + class function CreateUserMap(const count : Integer) : IThriftDictionary< TNumberz, Int64>; static; + class function CreateListFieldData(const count : Integer) : IThriftDictionary< IHashSet< Integer>, IThriftDictionary< Integer, IHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>; static; + class function CreateIntHashSet(const count : Integer) : IHashSet< Integer>; static; + class function CreateListFieldDataDict(const count : Integer) : IThriftDictionary< Integer, IHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>; static; + class function CreateListFieldDataDictValue(const count : Integer) : IHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>; static; + class function CreateListFieldDataDictValueList(const count : Integer) : IThriftList< IThriftDictionary< IInsanity, string>>; static; + class function CreateListFieldDataDictValueListDict(const count : Integer) : IThriftDictionary< IInsanity, string>; static; + public + class function CreateCrazyNesting(const count : Integer = 10) : ICrazyNesting; static; + end; + +implementation + + +class function TestDataFactory.CreateCrazyNesting(const count : Integer = 10) : ICrazyNesting; +begin + if (count <= 0) + then Exit(nil); + + result := TCrazyNestingImpl.Create; + result.Binary_field := CreateBytesArray(count); + result.List_field := CreateListField(count); + result.Set_field := CreateSetField(count); + result.String_field := Format('data level %d', [count]); +end; + +class function TestDataFactory.CreateSetField(const count : Integer) : IHashSet< IInsanity>; +var i : Integer; +begin + result := THashSetImpl< IInsanity>.Create; + for i := 0 to count-1 do begin + result.Add(CreateInsanity(count)); + end; +end; + +class function TestDataFactory.CreateInsanity(const count : Integer) : IInsanity; +begin + result := TInsanityImpl.Create; + result.UserMap := CreateUserMap(count); + result.Xtructs := CreateXtructs(count); +end; + +class function TestDataFactory.CreateXtructs(const count : Integer) : IThriftList< IXtruct>; +var i : Integer; +begin + result := TThriftListImpl< IXtruct>.Create; + for i := 0 to count-1 do begin + result.Add(CreateXtruct(count)); + end; +end; + +class function TestDataFactory.CreateXtruct(const count : Integer) : IXtruct; +begin + result := TXtructImpl.Create; + result.Byte_thing := SmallInt(count mod 128); + result.I32_thing := count; + result.I64_thing := count; + result.String_thing := Format('data level %d', [count]); +end; + +class function TestDataFactory.CreateUserMap(const count : Integer) : IThriftDictionary< TNumberz, Int64>; +begin + result := TThriftDictionaryImpl< TNumberz, Int64>.Create; + result.Add(TNumberz.ONE, count); + result.Add(TNumberz.TWO, count); + result.Add(TNumberz.THREE, count); + result.Add(TNumberz.FIVE, count); + result.Add(TNumberz.SIX, count); + result.Add(TNumberz.EIGHT, count); +end; + +class function TestDataFactory.CreateListField(const count : Integer) : IThriftList< IThriftDictionary< IHashSet< Integer>, IThriftDictionary< Integer, IHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>>; +var i : Integer; +begin + result := TThriftListImpl< IThriftDictionary< IHashSet< Integer>, IThriftDictionary< Integer, IHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>>.Create; + for i := 0 to count-1 do begin + result.Add(CreateListFieldData(count)); + end; +end; + +class function TestDataFactory.CreateListFieldData(const count : Integer) : IThriftDictionary< IHashSet< Integer>, IThriftDictionary< Integer, IHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>; +var i : Integer; +begin + result := TThriftDictionaryImpl< IHashSet< Integer>, IThriftDictionary< Integer, IHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>>.Create; + for i := 0 to count-1 do begin + result.Add( CreateIntHashSet(count), CreateListFieldDataDict(count)); + end; +end; + +class function TestDataFactory.CreateIntHashSet(const count : Integer) : IHashSet< Integer>; +var i : Integer; +begin + result := THashSetImpl< Integer>.Create; + for i := 0 to count-1 do begin + result.Add(i); + end; +end; + +class function TestDataFactory.CreateListFieldDataDict(const count : Integer) : IThriftDictionary< Integer, IHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>; +var i : Integer; +begin + result := TThriftDictionaryImpl< Integer, IHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>>.Create; + for i := 0 to count-1 do begin + result.Add(i, CreateListFieldDataDictValue(count)); + end; +end; + +class function TestDataFactory.CreateListFieldDataDictValue(const count : Integer) : IHashSet< IThriftList< IThriftDictionary< IInsanity, string>>>; +var i : Integer; +begin + result := THashSetImpl< IThriftList< IThriftDictionary< IInsanity, string>>>.Create; + for i := 0 to count-1 do begin + result.Add( CreateListFieldDataDictValueList(count)); + end; +end; + +class function TestDataFactory.CreateListFieldDataDictValueList(const count : Integer) : IThriftList< IThriftDictionary< IInsanity, string>>; +var i : Integer; +begin + result := TThriftListImpl< IThriftDictionary< IInsanity, string>>.Create; + for i := 0 to count-1 do begin + result.Add(CreateListFieldDataDictValueListDict(count)); + end; +end; + +class function TestDataFactory.CreateListFieldDataDictValueListDict(const count : Integer) : IThriftDictionary< IInsanity, string>; +begin + result := TThriftDictionaryImpl< IInsanity, string>.Create; + result.Add(CreateInsanity(count), Format('data level %d', [count])); +end; + +class function TestDataFactory.CreateBytesArray(const count : Integer) : TBytes; +var i : Integer; +begin + SetLength( result, count); + for i := 0 to count-1 do begin + result[i] := i mod $FF; + end; +end; + +end. + diff --git a/lib/delphi/test/Performance/PerfTests.pas b/lib/delphi/test/Performance/PerfTests.pas new file mode 100644 index 00000000000..2c820b1f3e9 --- /dev/null +++ b/lib/delphi/test/Performance/PerfTests.pas @@ -0,0 +1,173 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +unit PerfTests; + +interface + +uses + Windows, Classes, SysUtils, + Thrift.Collections, + Thrift.Test, + Thrift.Protocol, + Thrift.Protocol.JSON, + Thrift.Protocol.Compact, + Thrift.Transport, + Thrift.Stream, + ConsoleHelper, + TestConstants, + DataFactory; + +type + TPerformanceTests = class + strict private + Testdata : ICrazyNesting; + MemBuffer : TMemoryStream; + Transport : ITransport; + + procedure ProtocolPeformanceTest; + procedure RunTest( const ptyp : TKnownProtocol; const layered : TLayeredTransport); + function GenericProtocolFactory(const ptyp : TKnownProtocol; const layered : TLayeredTransport; const forWrite : Boolean) : IProtocol; + function GetProtocolTransportName(const ptyp : TKnownProtocol; const layered : TLayeredTransport) : string; + public + class function Execute : Integer; + end; + + +implementation + + +// not available in all versions, so make sure we have this one imported +function IsDebuggerPresent: BOOL; stdcall; external KERNEL32 name 'IsDebuggerPresent'; + + +class function TPerformanceTests.Execute : Integer; +var instance : TPerformanceTests; +begin + instance := TPerformanceTests.Create; + instance.ProtocolPeformanceTest; + + // debug only + if IsDebuggerPresent then begin + Console.Write('Hit ENTER ...'); + ReadLn; + end; + + result := 0; +end; + + +procedure TPerformanceTests.ProtocolPeformanceTest; +var layered : TLayeredTransport; +begin + Console.WriteLine('Setting up for ProtocolPeformanceTest ...'); + Testdata := TestDataFactory.CreateCrazyNesting(); + + for layered := Low(TLayeredTransport) to High(TLayeredTransport) do begin + RunTest( TKnownProtocol.prot_Binary, layered); + RunTest( TKnownProtocol.prot_Compact, layered); + RunTest( TKnownProtocol.prot_JSON, layered); + end; +end; + + +procedure TPerformanceTests.RunTest( const ptyp : TKnownProtocol; const layered : TLayeredTransport); +var freq, start, stop : Int64; + proto : IProtocol; + restored : ICrazyNesting; +begin + QueryPerformanceFrequency( freq); + + proto := GenericProtocolFactory( ptyp, layered, TRUE); + QueryPerformanceCounter( start); + Testdata.Write(proto); + Transport.Flush; + QueryPerformanceCounter( stop); + Console.WriteLine( Format('RunTest(%s): write = %d msec', [ + GetProtocolTransportName(ptyp,layered), + Round(1000.0*(stop-start)/freq) + ])); + + restored := TCrazyNestingImpl.Create; + proto := GenericProtocolFactory( ptyp, layered, FALSE); + QueryPerformanceCounter( start); + restored.Read(proto); + QueryPerformanceCounter( stop); + Console.WriteLine( Format('RunTest(%s): read = %d msec', [ + GetProtocolTransportName(ptyp,layered), + Round(1000.0*(stop-start)/freq) + ])); +end; + + +function TPerformanceTests.GenericProtocolFactory(const ptyp : TKnownProtocol; const layered : TLayeredTransport; const forWrite : Boolean) : IProtocol; +var newBuf : TMemoryStream; + stream : IThriftStream; + trans : IStreamTransport; +const COPY_ENTIRE_STREAM = 0; +begin + // read happens after write here, so let's take over the written bytes + newBuf := TMemoryStream.Create; + if not forWrite then newBuf.CopyFrom( MemBuffer, COPY_ENTIRE_STREAM); + MemBuffer := newBuf; + MemBuffer.Position := 0; + + // layered transports anyone? + stream := TThriftStreamAdapterDelphi.Create( newBuf, TRUE); + if forWrite + then trans := TStreamTransportImpl.Create( nil, stream) + else trans := TStreamTransportImpl.Create( stream, nil); + case layered of + trns_Framed : Transport := TFramedTransportImpl.Create( trans); + trns_Buffered : Transport := TBufferedTransportImpl.Create( trans); + else + Transport := trans; + end; + + if not Transport.IsOpen + then Transport.Open; + + case ptyp of + prot_Binary : result := TBinaryProtocolImpl.Create(trans); + prot_Compact : result := TCompactProtocolImpl.Create(trans); + prot_JSON : result := TJSONProtocolImpl.Create(trans); + else + ASSERT(FALSE); + end; +end; + + +function TPerformanceTests.GetProtocolTransportName(const ptyp : TKnownProtocol; const layered : TLayeredTransport) : string; +begin + case layered of + trns_Framed : result := ' + framed'; + trns_Buffered : result := ' + buffered'; + else + result := ''; + end; + + case ptyp of + prot_Binary : result := 'binary' + result; + prot_Compact : result := 'compact' + result; + prot_JSON : result := 'JSON' + result; + else + ASSERT(FALSE); + end; +end; + + +end. + diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas index 677d416b59b..c2660a26dc2 100644 --- a/lib/delphi/test/TestClient.pas +++ b/lib/delphi/test/TestClient.pas @@ -40,6 +40,7 @@ interface Generics.Collections, TestConstants, ConsoleHelper, + PerfTests, Thrift, Thrift.Protocol.Compact, Thrift.Protocol.JSON, @@ -199,6 +200,7 @@ class procedure TTestClient.PrintCmdLineHelp; + ' --ssl Encrypted Transport using SSL'#10 + ' -n [ --testloops ] arg (=1) Number of Tests'#10 + ' -t [ --threads ] arg (=1) Number of Test threads'#10 + + ' --performance Run the built-in performance test (no other arguments)'#10 ; begin Writeln( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + HELPTEXT); @@ -321,6 +323,10 @@ class function TTestClient.Execute(const args: array of string) : Byte; if FNumThread <= 0 then InvalidArgs; end + else if (s = '--performance') then begin + result := TPerformanceTests.Execute; + Exit; + end else begin InvalidArgs; end; diff --git a/lib/delphi/test/TestConstants.pas b/lib/delphi/test/TestConstants.pas index 6bb20e96f3f..ae3b3e8a355 100644 --- a/lib/delphi/test/TestConstants.pas +++ b/lib/delphi/test/TestConstants.pas @@ -47,6 +47,7 @@ interface ); TLayeredTransport = ( + trns_None, trns_Buffered, trns_Framed ); @@ -61,7 +62,7 @@ interface = ('Binary', 'JSON', 'Compact'); LAYERED_TRANSPORTS : array[TLayeredTransport] of string - = ('Buffered', 'Framed'); + = ('None', 'Buffered', 'Framed'); ENDPOINT_TRANSPORTS : array[TEndpointTransport] of string = ('Sockets', 'Http', 'WinHttp', 'Named Pipes','Anon Pipes', 'EvHttp'); diff --git a/lib/delphi/test/client.dpr b/lib/delphi/test/client.dpr index 1d1607de7a0..83727f61951 100644 --- a/lib/delphi/test/client.dpr +++ b/lib/delphi/test/client.dpr @@ -24,6 +24,8 @@ program client; uses SysUtils, + DataFactory in 'Performance\DataFactory.pas', + PerfTests in 'Performance\PerfTests.pas', TestClient in 'TestClient.pas', Thrift.Test, // in 'gen-delphi\Thrift.Test.pas', Thrift in '..\src\Thrift.pas', From 19fdca82c2e61bd42f92a502a91a07b9dc74b5d2 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 12 Jun 2019 22:09:05 +0200 Subject: [PATCH 299/756] THRIFT-4886 More detailed error information for WinHTTP transport Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.Transport.WinHTTP.pas | 49 ++++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas index 48b74a6648f..d7eefa86298 100644 --- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas @@ -51,7 +51,10 @@ TWinHTTPClientImpl = class( TTransportImpl, IHTTPClient) function CreateRequest: IWinHTTPRequest; function SecureProtocolsAsWinHTTPFlags : Cardinal; - private type + private + type + TErrorInfo = ( SplitUrl, WinHTTPSession, WinHTTPConnection, WinHTTPRequest, RequestSetup, AutoProxy ); + THTTPResponseStream = class( TThriftStreamImpl) private FRequest : IWinHTTPRequest; @@ -131,33 +134,45 @@ destructor TWinHTTPClientImpl.Destroy; function TWinHTTPClientImpl.CreateRequest: IWinHTTPRequest; var - pair : TPair; + pair : TPair; session : IWinHTTPSession; connect : IWinHTTPConnection; url : IWinHTTPUrl; sPath : string; + info : TErrorInfo; begin - url := TWinHTTPUrlImpl.Create( FUri); + info := TErrorInfo.SplitUrl; + try + url := TWinHTTPUrlImpl.Create( FUri); - session := TWinHTTPSessionImpl.Create('Apache Thrift Delphi WinHTTP'); - session.EnableSecureProtocols( SecureProtocolsAsWinHTTPFlags); + info := TErrorInfo.WinHTTPSession; + session := TWinHTTPSessionImpl.Create('Apache Thrift Delphi WinHTTP'); + session.EnableSecureProtocols( SecureProtocolsAsWinHTTPFlags); - connect := session.Connect( url.HostName, url.Port); + info := TErrorInfo.WinHTTPConnection; + connect := session.Connect( url.HostName, url.Port); - sPath := url.UrlPath + url.ExtraInfo; - result := connect.OpenRequest( (url.Scheme = 'https'), 'POST', sPath, THRIFT_MIMETYPE); + info := TErrorInfo.WinHTTPRequest; + sPath := url.UrlPath + url.ExtraInfo; + result := connect.OpenRequest( (url.Scheme = 'https'), 'POST', sPath, THRIFT_MIMETYPE); - // setting a timeout value to 0 (zero) means "no timeout" for that setting - result.SetTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout); + // setting a timeout value to 0 (zero) means "no timeout" for that setting + info := TErrorInfo.RequestSetup; + result.SetTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout); - // headers - result.AddRequestHeader( 'Content-Type: '+THRIFT_MIMETYPE, WINHTTP_ADDREQ_FLAG_ADD); - for pair in FCustomHeaders do begin - Result.AddRequestHeader( pair.Key +': '+ pair.Value, WINHTTP_ADDREQ_FLAG_ADD); - end; + // headers + result.AddRequestHeader( 'Content-Type: '+THRIFT_MIMETYPE, WINHTTP_ADDREQ_FLAG_ADD); + for pair in FCustomHeaders do begin + Result.AddRequestHeader( pair.Key +': '+ pair.Value, WINHTTP_ADDREQ_FLAG_ADD); + end; - // AutoProxy support - result.TryAutoProxy( FUri); + // AutoProxy support + info := TErrorInfo.AutoProxy; + result.TryAutoProxy( FUri); + except + on e:TException do raise; + on e:Exception do raise TTransportExceptionUnknown.Create( e.Message+' (at '+EnumUtils.ToString(Ord(info))+')'); + end; end; From 5eef01f231b1e7b33d1ebfb65aeb136f851b350b Mon Sep 17 00:00:00 2001 From: John Boiles Date: Thu, 13 Jun 2019 10:49:45 -0700 Subject: [PATCH 300/756] THRIFT-4868: Fix Go compilation for optional sets with default values (#1802) Client: go --- compiler/cpp/src/thrift/generate/t_go_generator.cc | 8 ++++++-- test/ThriftTest.thrift | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index 66bb65301f3..c8187d8ad37 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -3237,8 +3237,12 @@ void t_go_generator::generate_serialize_container(ostream& out, t_set* tset = (t_set*)ttype; out << indent() << "for i := 0; i with_default = [ "test" ] +} From 823474ec89355f72d3f0720ae5dacc2036d41c03 Mon Sep 17 00:00:00 2001 From: Kyle Smith Date: Mon, 3 Jun 2019 13:31:15 +0200 Subject: [PATCH 301/756] THRIFT-4848: Add ability to set Content-Type,Accept headers in HTTP client Client: netstd Patch: Kyle Smith This closes #1801 --- .../Thrift/Transport/Client/THttpTransport.cs | 89 ++++++++----------- 1 file changed, 38 insertions(+), 51 deletions(-) diff --git a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs index 5d7f1de2899..982e91e81e0 100644 --- a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs @@ -33,45 +33,39 @@ public class THttpTransport : TTransport private readonly X509Certificate[] _certificates; private readonly Uri _uri; - // Timeouts in milliseconds - private int _connectTimeout = 30000; + private int _connectTimeout = 30000; // Timeouts in milliseconds private HttpClient _httpClient; private Stream _inputStream; - - private bool _isDisposed; private MemoryStream _outputStream = new MemoryStream(); + private bool _isDisposed; - public THttpTransport(Uri u, IDictionary customHeaders = null, string userAgent = null) - : this(u, Enumerable.Empty(), customHeaders, userAgent) + public THttpTransport(Uri uri, IDictionary customRequestHeaders = null, string userAgent = null) + : this(uri, Enumerable.Empty(), customRequestHeaders, userAgent) { } - public THttpTransport(Uri u, IEnumerable certificates, - IDictionary customHeaders, string userAgent = null) + public THttpTransport(Uri uri, IEnumerable certificates, + IDictionary customRequestHeaders, string userAgent = null) { - _uri = u; + _uri = uri; _certificates = (certificates ?? Enumerable.Empty()).ToArray(); - CustomHeaders = customHeaders; if (!string.IsNullOrEmpty(userAgent)) UserAgent = userAgent; // due to current bug with performance of Dispose in netcore https://github.com/dotnet/corefx/issues/8809 // this can be switched to default way (create client->use->dispose per flush) later - _httpClient = CreateClient(); + _httpClient = CreateClient(customRequestHeaders); } // According to RFC 2616 section 3.8, the "User-Agent" header may not carry a version number public readonly string UserAgent = "Thrift netstd THttpClient"; - public IDictionary CustomHeaders { get; } + public override bool IsOpen => true; - public int ConnectTimeout - { - set { _connectTimeout = value; } - } + public HttpRequestHeaders RequestHeaders => _httpClient.DefaultRequestHeaders; - public override bool IsOpen => true; + public MediaTypeHeaderValue ContentType { get; set; } public override async Task OpenAsync(CancellationToken cancellationToken) { @@ -141,7 +135,7 @@ public override async Task WriteAsync(byte[] buffer, int offset, int length, Can await _outputStream.WriteAsync(buffer, offset, length, cancellationToken); } - private HttpClient CreateClient() + private HttpClient CreateClient(IDictionary customRequestHeaders) { var handler = new HttpClientHandler(); handler.ClientCertificates.AddRange(_certificates); @@ -155,10 +149,10 @@ private HttpClient CreateClient() httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd(UserAgent); - - if (CustomHeaders != null) + + if (customRequestHeaders != null) { - foreach (var item in CustomHeaders) + foreach (var item in customRequestHeaders) { httpClient.DefaultRequestHeaders.Add(item.Key, item.Value); } @@ -171,41 +165,34 @@ public override async Task FlushAsync(CancellationToken cancellationToken) { try { - try - { - if (_outputStream.CanSeek) - { - _outputStream.Seek(0, SeekOrigin.Begin); - } + _outputStream.Seek(0, SeekOrigin.Begin); - using (var outStream = new StreamContent(_outputStream)) - { - var msg = await _httpClient.PostAsync(_uri, outStream, cancellationToken); - - msg.EnsureSuccessStatusCode(); + using (var contentStream = new StreamContent(_outputStream)) + { + contentStream.Headers.ContentType = ContentType ?? new MediaTypeHeaderValue(@"application/x-thrift"); - if (_inputStream != null) - { - _inputStream.Dispose(); - _inputStream = null; - } + var response = (await _httpClient.PostAsync(_uri, contentStream, cancellationToken)).EnsureSuccessStatusCode(); - _inputStream = await msg.Content.ReadAsStreamAsync(); - if (_inputStream.CanSeek) - { - _inputStream.Seek(0, SeekOrigin.Begin); - } + _inputStream?.Dispose(); + _inputStream = await response.Content.ReadAsStreamAsync(); + if (_inputStream.CanSeek) + { + _inputStream.Seek(0, SeekOrigin.Begin); } } - catch (IOException iox) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString()); - } - catch (HttpRequestException wx) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, - "Couldn't connect to server: " + wx); - } + } + catch (IOException iox) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString()); + } + catch (HttpRequestException wx) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, + "Couldn't connect to server: " + wx); + } + catch (Exception ex) + { + throw new TTransportException(TTransportException.ExceptionType.Unknown, ex.Message); } finally { From 4d46c1124450eeb77d2a6adc7ea5fab304bfeb4a Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Fri, 7 Jun 2019 20:47:18 +0800 Subject: [PATCH 302/756] THRIFT-4612: THeader support in go library Client: go Implement THeaderTransport and THeaderProtocol, with support of: * clients: - headers - framedBinary - unframedBinary - framedCompact - unframedCompact * transforms: - none - zlib * info types: - key_value * wrapped protocols: - TBinary - TCompact The support list is in general on par of the THeader implementation in the python library. The cross-test passes, except ones related to cpp/nodejs http transport, which were also failing for non-theader protocols. This change also fixes two bugs: 1. A small issue in test/go/src/bin/testserver/main.go 2. A bug in TFrameTransport go implementation --- lib/go/thrift/application_exception.go | 6 + lib/go/thrift/framed_transport.go | 16 +- lib/go/thrift/header_protocol.go | 300 +++++++++++ lib/go/thrift/header_protocol_test.go | 28 + lib/go/thrift/header_transport.go | 692 +++++++++++++++++++++++++ lib/go/thrift/header_transport_test.go | 108 ++++ lib/go/thrift/simple_server.go | 22 +- test/go/src/bin/testserver/main.go | 4 +- test/go/src/common/client.go | 2 + test/go/src/common/server.go | 2 + test/known_failures_Linux.json | 8 + test/tests.json | 3 +- 12 files changed, 1182 insertions(+), 9 deletions(-) create mode 100644 lib/go/thrift/header_protocol.go create mode 100644 lib/go/thrift/header_protocol_test.go create mode 100644 lib/go/thrift/header_transport.go create mode 100644 lib/go/thrift/header_transport_test.go diff --git a/lib/go/thrift/application_exception.go b/lib/go/thrift/application_exception.go index b9d7eedcdd7..0023c57cf1e 100644 --- a/lib/go/thrift/application_exception.go +++ b/lib/go/thrift/application_exception.go @@ -28,6 +28,9 @@ const ( MISSING_RESULT = 5 INTERNAL_ERROR = 6 PROTOCOL_ERROR = 7 + INVALID_TRANSFORM = 8 + INVALID_PROTOCOL = 9 + UNSUPPORTED_CLIENT_TYPE = 10 ) var defaultApplicationExceptionMessage = map[int32]string{ @@ -39,6 +42,9 @@ var defaultApplicationExceptionMessage = map[int32]string{ MISSING_RESULT: "missing result", INTERNAL_ERROR: "unknown internal error", PROTOCOL_ERROR: "unknown protocol error", + INVALID_TRANSFORM: "Invalid transform", + INVALID_PROTOCOL: "Invalid protocol", + UNSUPPORTED_CLIENT_TYPE: "Unsupported client type", } // Application level Thrift exception diff --git a/lib/go/thrift/framed_transport.go b/lib/go/thrift/framed_transport.go index 81fa65aaae5..34275b5f4d8 100644 --- a/lib/go/thrift/framed_transport.go +++ b/lib/go/thrift/framed_transport.go @@ -93,7 +93,21 @@ func (p *TFramedTransport) Read(buf []byte) (l int, err error) { l, err = p.Read(tmp) copy(buf, tmp) if err == nil { - err = NewTTransportExceptionFromError(fmt.Errorf("Not enough frame size %d to read %d bytes", frameSize, len(buf))) + // Note: It's important to only return an error when l + // is zero. + // In io.Reader.Read interface, it's perfectly fine to + // return partial data and nil error, which means + // "This is all the data we have right now without + // blocking. If you need the full data, call Read again + // or use io.ReadFull instead". + // Returning partial data with an error actually means + // there's no more data after the partial data just + // returned, which is not true in this case + // (it might be that the other end just haven't written + // them yet). + if l == 0 { + err = NewTTransportExceptionFromError(fmt.Errorf("Not enough frame size %d to read %d bytes", frameSize, len(buf))) + } return } } diff --git a/lib/go/thrift/header_protocol.go b/lib/go/thrift/header_protocol.go new file mode 100644 index 00000000000..0cf48f720b7 --- /dev/null +++ b/lib/go/thrift/header_protocol.go @@ -0,0 +1,300 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "context" +) + +// THeaderProtocol is a thrift protocol that implements THeader: +// https://github.com/apache/thrift/blob/master/doc/specs/HeaderFormat.md +// +// It supports either binary or compact protocol as the wrapped protocol. +// +// Most of the THeader handlings are happening inside THeaderTransport. +type THeaderProtocol struct { + transport *THeaderTransport + + // Will be initialized on first read/write. + protocol TProtocol +} + +// NewTHeaderProtocol creates a new THeaderProtocol from the underlying +// transport. The passed in transport will be wrapped with THeaderTransport. +// +// Note that THeaderTransport handles frame and zlib by itself, +// so the underlying transport should be a raw socket transports (TSocket or TSSLSocket), +// instead of rich transports like TZlibTransport or TFramedTransport. +func NewTHeaderProtocol(trans TTransport) *THeaderProtocol { + t := NewTHeaderTransport(trans) + p, _ := THeaderProtocolDefault.GetProtocol(t) + return &THeaderProtocol{ + transport: t, + protocol: p, + } +} + +type tHeaderProtocolFactory struct{} + +func (tHeaderProtocolFactory) GetProtocol(trans TTransport) TProtocol { + return NewTHeaderProtocol(trans) +} + +// NewTHeaderProtocolFactory creates a factory for THeader. +// +// It's a wrapper for NewTHeaderProtocol +func NewTHeaderProtocolFactory() TProtocolFactory { + return tHeaderProtocolFactory{} +} + +// Transport returns the underlying transport. +// +// It's guaranteed to be of type *THeaderTransport. +func (p *THeaderProtocol) Transport() TTransport { + return p.transport +} + +// GetReadHeaders returns the THeaderMap read from transport. +func (p *THeaderProtocol) GetReadHeaders() THeaderMap { + return p.transport.GetReadHeaders() +} + +// SetWriteHeader sets a header for write. +func (p *THeaderProtocol) SetWriteHeader(key, value string) { + p.transport.SetWriteHeader(key, value) +} + +// ClearWriteHeaders clears all write headers previously set. +func (p *THeaderProtocol) ClearWriteHeaders() { + p.transport.ClearWriteHeaders() +} + +// AddTransform add a transform for writing. +func (p *THeaderProtocol) AddTransform(transform THeaderTransformID) error { + return p.transport.AddTransform(transform) +} + +func (p *THeaderProtocol) Flush(ctx context.Context) error { + return p.transport.Flush(ctx) +} + +func (p *THeaderProtocol) WriteMessageBegin(name string, typeID TMessageType, seqID int32) error { + newProto, err := p.transport.Protocol().GetProtocol(p.transport) + if err != nil { + return err + } + p.protocol = newProto + p.transport.SequenceID = seqID + return p.protocol.WriteMessageBegin(name, typeID, seqID) +} + +func (p *THeaderProtocol) WriteMessageEnd() error { + if err := p.protocol.WriteMessageEnd(); err != nil { + return err + } + return p.transport.Flush(context.Background()) +} + +func (p *THeaderProtocol) WriteStructBegin(name string) error { + return p.protocol.WriteStructBegin(name) +} + +func (p *THeaderProtocol) WriteStructEnd() error { + return p.protocol.WriteStructEnd() +} + +func (p *THeaderProtocol) WriteFieldBegin(name string, typeID TType, id int16) error { + return p.protocol.WriteFieldBegin(name, typeID, id) +} + +func (p *THeaderProtocol) WriteFieldEnd() error { + return p.protocol.WriteFieldEnd() +} + +func (p *THeaderProtocol) WriteFieldStop() error { + return p.protocol.WriteFieldStop() +} + +func (p *THeaderProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { + return p.protocol.WriteMapBegin(keyType, valueType, size) +} + +func (p *THeaderProtocol) WriteMapEnd() error { + return p.protocol.WriteMapEnd() +} + +func (p *THeaderProtocol) WriteListBegin(elemType TType, size int) error { + return p.protocol.WriteListBegin(elemType, size) +} + +func (p *THeaderProtocol) WriteListEnd() error { + return p.protocol.WriteListEnd() +} + +func (p *THeaderProtocol) WriteSetBegin(elemType TType, size int) error { + return p.protocol.WriteSetBegin(elemType, size) +} + +func (p *THeaderProtocol) WriteSetEnd() error { + return p.protocol.WriteSetEnd() +} + +func (p *THeaderProtocol) WriteBool(value bool) error { + return p.protocol.WriteBool(value) +} + +func (p *THeaderProtocol) WriteByte(value int8) error { + return p.protocol.WriteByte(value) +} + +func (p *THeaderProtocol) WriteI16(value int16) error { + return p.protocol.WriteI16(value) +} + +func (p *THeaderProtocol) WriteI32(value int32) error { + return p.protocol.WriteI32(value) +} + +func (p *THeaderProtocol) WriteI64(value int64) error { + return p.protocol.WriteI64(value) +} + +func (p *THeaderProtocol) WriteDouble(value float64) error { + return p.protocol.WriteDouble(value) +} + +func (p *THeaderProtocol) WriteString(value string) error { + return p.protocol.WriteString(value) +} + +func (p *THeaderProtocol) WriteBinary(value []byte) error { + return p.protocol.WriteBinary(value) +} + +func (p *THeaderProtocol) ReadMessageBegin() (name string, typeID TMessageType, seqID int32, err error) { + if err = p.transport.ReadFrame(); err != nil { + return + } + + var newProto TProtocol + newProto, err = p.transport.Protocol().GetProtocol(p.transport) + if err != nil { + tAppExc, ok := err.(TApplicationException) + if !ok { + return + } + if e := p.protocol.WriteMessageBegin("", EXCEPTION, seqID); e != nil { + return + } + if e := tAppExc.Write(p.protocol); e != nil { + return + } + if e := p.protocol.WriteMessageEnd(); e != nil { + return + } + if e := p.transport.Flush(context.Background()); e != nil { + return + } + return + } + p.protocol = newProto + + return p.protocol.ReadMessageBegin() +} + +func (p *THeaderProtocol) ReadMessageEnd() error { + return p.protocol.ReadMessageEnd() +} + +func (p *THeaderProtocol) ReadStructBegin() (name string, err error) { + return p.protocol.ReadStructBegin() +} + +func (p *THeaderProtocol) ReadStructEnd() error { + return p.protocol.ReadStructEnd() +} + +func (p *THeaderProtocol) ReadFieldBegin() (name string, typeID TType, id int16, err error) { + return p.protocol.ReadFieldBegin() +} + +func (p *THeaderProtocol) ReadFieldEnd() error { + return p.protocol.ReadFieldEnd() +} + +func (p *THeaderProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err error) { + return p.protocol.ReadMapBegin() +} + +func (p *THeaderProtocol) ReadMapEnd() error { + return p.protocol.ReadMapEnd() +} + +func (p *THeaderProtocol) ReadListBegin() (elemType TType, size int, err error) { + return p.protocol.ReadListBegin() +} + +func (p *THeaderProtocol) ReadListEnd() error { + return p.protocol.ReadListEnd() +} + +func (p *THeaderProtocol) ReadSetBegin() (elemType TType, size int, err error) { + return p.protocol.ReadSetBegin() +} + +func (p *THeaderProtocol) ReadSetEnd() error { + return p.protocol.ReadSetEnd() +} + +func (p *THeaderProtocol) ReadBool() (value bool, err error) { + return p.protocol.ReadBool() +} + +func (p *THeaderProtocol) ReadByte() (value int8, err error) { + return p.protocol.ReadByte() +} + +func (p *THeaderProtocol) ReadI16() (value int16, err error) { + return p.protocol.ReadI16() +} + +func (p *THeaderProtocol) ReadI32() (value int32, err error) { + return p.protocol.ReadI32() +} + +func (p *THeaderProtocol) ReadI64() (value int64, err error) { + return p.protocol.ReadI64() +} + +func (p *THeaderProtocol) ReadDouble() (value float64, err error) { + return p.protocol.ReadDouble() +} + +func (p *THeaderProtocol) ReadString() (value string, err error) { + return p.protocol.ReadString() +} + +func (p *THeaderProtocol) ReadBinary() (value []byte, err error) { + return p.protocol.ReadBinary() +} + +func (p *THeaderProtocol) Skip(fieldType TType) error { + return p.protocol.Skip(fieldType) +} diff --git a/lib/go/thrift/header_protocol_test.go b/lib/go/thrift/header_protocol_test.go new file mode 100644 index 00000000000..9b6019bcfd6 --- /dev/null +++ b/lib/go/thrift/header_protocol_test.go @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "testing" +) + +func TestReadWriteHeaderProtocol(t *testing.T) { + ReadWriteProtocolTest(t, NewTHeaderProtocolFactory()) +} diff --git a/lib/go/thrift/header_transport.go b/lib/go/thrift/header_transport.go new file mode 100644 index 00000000000..3e684600f50 --- /dev/null +++ b/lib/go/thrift/header_transport.go @@ -0,0 +1,692 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "bufio" + "bytes" + "compress/zlib" + "context" + "encoding/binary" + "errors" + "fmt" + "io" + "io/ioutil" +) + +// Size in bytes for 32-bit ints. +const size32 = 4 + +type headerMeta struct { + MagicFlags uint32 + SequenceID int32 + HeaderLength uint16 +} + +const headerMetaSize = 10 + +type clientType int + +const ( + clientUnknown clientType = iota + clientHeaders + clientFramedBinary + clientUnframedBinary + clientFramedCompact + clientUnframedCompact +) + +// Constants defined in THeader format: +// https://github.com/apache/thrift/blob/master/doc/specs/HeaderFormat.md +const ( + THeaderHeaderMagic uint32 = 0x0fff0000 + THeaderHeaderMask uint32 = 0xffff0000 + THeaderFlagsMask uint32 = 0x0000ffff + THeaderMaxFrameSize uint32 = 0x3fffffff +) + +// THeaderMap is the type of the header map in THeader transport. +type THeaderMap map[string]string + +// THeaderProtocolID is the wrapped protocol id used in THeader. +type THeaderProtocolID int32 + +// Supported THeaderProtocolID values. +const ( + THeaderProtocolBinary THeaderProtocolID = 0x00 + THeaderProtocolCompact THeaderProtocolID = 0x02 + THeaderProtocolDefault = THeaderProtocolBinary +) + +// GetProtocol gets the corresponding TProtocol from the wrapped protocol id. +func (id THeaderProtocolID) GetProtocol(trans TTransport) (TProtocol, error) { + switch id { + default: + return nil, NewTApplicationException( + INVALID_PROTOCOL, + fmt.Sprintf("THeader protocol id %d not supported", id), + ) + case THeaderProtocolBinary: + return NewTBinaryProtocolFactoryDefault().GetProtocol(trans), nil + case THeaderProtocolCompact: + return NewTCompactProtocol(trans), nil + } +} + +// THeaderTransformID defines the numeric id of the transform used. +type THeaderTransformID int32 + +// THeaderTransformID values +const ( + TransformNone THeaderTransformID = iota // 0, no special handling + TransformZlib // 1, zlib + // Rest of the values are not currently supported, namely HMAC and Snappy. +) + +var supportedTransformIDs = map[THeaderTransformID]bool{ + TransformNone: true, + TransformZlib: true, +} + +// TransformReader is an io.ReadCloser that handles transforms reading. +type TransformReader struct { + io.Reader + + closers []io.Closer +} + +var _ io.ReadCloser = (*TransformReader)(nil) + +// NewTransformReaderWithCapacity initializes a TransformReader with expected +// closers capacity. +// +// If you don't know the closers capacity beforehand, just use +// +// &TransformReader{Reader: baseReader} +// +// instead would be sufficient. +func NewTransformReaderWithCapacity(baseReader io.Reader, capacity int) *TransformReader { + return &TransformReader{ + Reader: baseReader, + closers: make([]io.Closer, 0, capacity), + } +} + +// Close calls the underlying closers in appropriate order, +// stops at and returns the first error encountered. +func (tr *TransformReader) Close() error { + // Call closers in reversed order + for i := len(tr.closers) - 1; i >= 0; i-- { + if err := tr.closers[i].Close(); err != nil { + return err + } + } + return nil +} + +// AddTransform adds a transform. +func (tr *TransformReader) AddTransform(id THeaderTransformID) error { + switch id { + default: + return NewTApplicationException( + INVALID_TRANSFORM, + fmt.Sprintf("THeaderTransformID %d not supported", id), + ) + case TransformNone: + // no-op + case TransformZlib: + readCloser, err := zlib.NewReader(tr.Reader) + if err != nil { + return err + } + tr.Reader = readCloser + tr.closers = append(tr.closers, readCloser) + } + return nil +} + +// TransformWriter is an io.WriteCloser that handles transforms writing. +type TransformWriter struct { + io.Writer + + closers []io.Closer +} + +var _ io.WriteCloser = (*TransformWriter)(nil) + +// NewTransformWriter creates a new TransformWriter with base writer and transforms. +func NewTransformWriter(baseWriter io.Writer, transforms []THeaderTransformID) (io.WriteCloser, error) { + writer := &TransformWriter{ + Writer: baseWriter, + closers: make([]io.Closer, 0, len(transforms)), + } + for _, id := range transforms { + if err := writer.AddTransform(id); err != nil { + return nil, err + } + } + return writer, nil +} + +// Close calls the underlying closers in appropriate order, +// stops at and returns the first error encountered. +func (tw *TransformWriter) Close() error { + // Call closers in reversed order + for i := len(tw.closers) - 1; i >= 0; i-- { + if err := tw.closers[i].Close(); err != nil { + return err + } + } + return nil +} + +// AddTransform adds a transform. +func (tw *TransformWriter) AddTransform(id THeaderTransformID) error { + switch id { + default: + return NewTApplicationException( + INVALID_TRANSFORM, + fmt.Sprintf("THeaderTransformID %d not supported", id), + ) + case TransformNone: + // no-op + case TransformZlib: + writeCloser := zlib.NewWriter(tw.Writer) + tw.Writer = writeCloser + tw.closers = append(tw.closers, writeCloser) + } + return nil +} + +// THeaderInfoType is the type id of the info headers. +type THeaderInfoType int32 + +// Supported THeaderInfoType values. +const ( + _ THeaderInfoType = iota // Skip 0 + InfoKeyValue // 1 + // Rest of the info types are not supported. +) + +// THeaderTransport is a Transport mode that implements THeader. +// +// Note that THeaderTransport handles frame and zlib by itself, +// so the underlying transport should be a raw socket transports (TSocket or TSSLSocket), +// instead of rich transports like TZlibTransport or TFramedTransport. +type THeaderTransport struct { + SequenceID int32 + Flags uint32 + + transport TTransport + + // THeaderMap for read and write + readHeaders THeaderMap + writeHeaders THeaderMap + + // Reading related variables. + reader *bufio.Reader + // When frame is detected, we read the frame fully into frameBuffer. + frameBuffer bytes.Buffer + // When it's non-nil, Read should read from frameReader instead of + // reader, and EOF error indicates end of frame instead of end of all + // transport. + frameReader io.ReadCloser + + // Writing related variables + writeBuffer bytes.Buffer + writeTransforms []THeaderTransformID + + clientType clientType + protocolID THeaderProtocolID + + // buffer is used in the following scenarios to avoid repetitive + // allocations, while 4 is big enough for all those scenarios: + // + // * header padding (max size 4) + // * write the frame size (size 4) + buffer [4]byte +} + +var _ TTransport = (*THeaderTransport)(nil) + +// NewTHeaderTransport creates THeaderTransport from the underlying transport. +// +// Please note that THeaderTransport handles framing and zlib by itself, +// so the underlying transport should be the raw socket transports (TSocket or TSSLSocket), +// instead of rich transports like TZlibTransport or TFramedTransport. +func NewTHeaderTransport(trans TTransport) *THeaderTransport { + return &THeaderTransport{ + transport: trans, + reader: bufio.NewReader(trans), + writeHeaders: make(THeaderMap), + protocolID: THeaderProtocolDefault, + } +} + +// Open calls the underlying transport's Open function. +func (t *THeaderTransport) Open() error { + return t.transport.Open() +} + +// IsOpen calls the underlying transport's IsOpen function. +func (t *THeaderTransport) IsOpen() bool { + return t.transport.IsOpen() +} + +// ReadFrame tries to read the frame header, guess the client type, and handle +// unframed clients. +func (t *THeaderTransport) ReadFrame() error { + if !t.needReadFrame() { + // No need to read frame, skipping. + return nil + } + // Peek and handle the first 32 bits. + // They could either be the length field of a framed message, + // or the first bytes of an unframed message. + buf, err := t.reader.Peek(size32) + if err != nil { + return err + } + frameSize := binary.BigEndian.Uint32(buf) + if frameSize&VERSION_MASK == VERSION_1 { + t.clientType = clientUnframedBinary + return nil + } + if buf[0] == COMPACT_PROTOCOL_ID && buf[1]&COMPACT_VERSION_MASK == COMPACT_VERSION { + t.clientType = clientUnframedCompact + return nil + } + + // At this point it should be a framed message, + // sanity check on frameSize then discard the peeked part. + if frameSize > THeaderMaxFrameSize { + return NewTProtocolExceptionWithType( + SIZE_LIMIT, + errors.New("frame too large"), + ) + } + t.reader.Discard(size32) + + // Read the frame fully into frameBuffer. + _, err = io.Copy( + &t.frameBuffer, + io.LimitReader(t.reader, int64(frameSize)), + ) + if err != nil { + return err + } + t.frameReader = ioutil.NopCloser(&t.frameBuffer) + + // Peek and handle the next 32 bits. + buf = t.frameBuffer.Bytes()[:size32] + version := binary.BigEndian.Uint32(buf) + if version&THeaderHeaderMask == THeaderHeaderMagic { + t.clientType = clientHeaders + return t.parseHeaders(frameSize) + } + if version&VERSION_MASK == VERSION_1 { + t.clientType = clientFramedBinary + return nil + } + if buf[0] == COMPACT_PROTOCOL_ID && buf[1]&COMPACT_VERSION_MASK == COMPACT_VERSION { + t.clientType = clientFramedCompact + return nil + } + if err := t.endOfFrame(); err != nil { + return err + } + return NewTProtocolExceptionWithType( + NOT_IMPLEMENTED, + errors.New("unsupported client transport type"), + ) +} + +// endOfFrame does end of frame handling. +// +// It closes frameReader, and also resets frame related states. +func (t *THeaderTransport) endOfFrame() error { + defer func() { + t.frameBuffer.Reset() + t.frameReader = nil + }() + return t.frameReader.Close() +} + +func (t *THeaderTransport) parseHeaders(frameSize uint32) error { + if t.clientType != clientHeaders { + return nil + } + + var err error + var meta headerMeta + if err = binary.Read(&t.frameBuffer, binary.BigEndian, &meta); err != nil { + return err + } + frameSize -= headerMetaSize + t.Flags = meta.MagicFlags & THeaderFlagsMask + t.SequenceID = meta.SequenceID + headerLength := int64(meta.HeaderLength) * 4 + if int64(frameSize) < headerLength { + return NewTProtocolExceptionWithType( + SIZE_LIMIT, + errors.New("header size is larger than the whole frame"), + ) + } + headerBuf := NewTMemoryBuffer() + _, err = io.Copy(headerBuf, io.LimitReader(&t.frameBuffer, headerLength)) + if err != nil { + return err + } + hp := NewTCompactProtocol(headerBuf) + + // At this point the header is already read into headerBuf, + // and t.frameBuffer starts from the actual payload. + protoID, err := hp.readVarint32() + if err != nil { + return err + } + t.protocolID = THeaderProtocolID(protoID) + var transformCount int32 + transformCount, err = hp.readVarint32() + if err != nil { + return err + } + if transformCount > 0 { + reader := NewTransformReaderWithCapacity( + &t.frameBuffer, + int(transformCount), + ) + t.frameReader = reader + transformIDs := make([]THeaderTransformID, transformCount) + for i := 0; i < int(transformCount); i++ { + id, err := hp.readVarint32() + if err != nil { + return err + } + transformIDs[i] = THeaderTransformID(id) + } + // The transform IDs on the wire was added based on the order of + // writing, so on the reading side we need to reverse the order. + for i := transformCount - 1; i >= 0; i-- { + id := transformIDs[i] + if err := reader.AddTransform(id); err != nil { + return err + } + } + } + + // The info part does not use the transforms yet, so it's + // important to continue using headerBuf. + headers := make(THeaderMap) + for { + infoType, err := hp.readVarint32() + if err == io.EOF { + break + } + if err != nil { + return err + } + if THeaderInfoType(infoType) == InfoKeyValue { + count, err := hp.readVarint32() + if err != nil { + return err + } + for i := 0; i < int(count); i++ { + key, err := hp.ReadString() + if err != nil { + return err + } + value, err := hp.ReadString() + if err != nil { + return err + } + headers[key] = value + } + } else { + // Skip reading info section on the first + // unsupported info type. + break + } + } + t.readHeaders = headers + + return nil +} + +func (t *THeaderTransport) needReadFrame() bool { + if t.clientType == clientUnknown { + // This is a new connection that's never read before. + return true + } + if t.isFramed() && t.frameReader == nil { + // We just finished the last frame. + return true + } + return false +} + +func (t *THeaderTransport) Read(p []byte) (read int, err error) { + err = t.ReadFrame() + if err != nil { + return + } + if t.frameReader != nil { + read, err = t.frameReader.Read(p) + if err == io.EOF { + err = t.endOfFrame() + if err != nil { + return + } + if read < len(p) { + var nextRead int + nextRead, err = t.Read(p[read:]) + read += nextRead + } + } + return + } + return t.reader.Read(p) +} + +// Write writes data to the write buffer. +// +// You need to call Flush to actually write them to the transport. +func (t *THeaderTransport) Write(p []byte) (int, error) { + return t.writeBuffer.Write(p) +} + +// Flush writes the appropriate header and the write buffer to the underlying transport. +func (t *THeaderTransport) Flush(ctx context.Context) error { + if t.writeBuffer.Len() == 0 { + return nil + } + + defer t.writeBuffer.Reset() + + switch t.clientType { + default: + fallthrough + case clientUnknown: + t.clientType = clientHeaders + fallthrough + case clientHeaders: + headers := NewTMemoryBuffer() + hp := NewTCompactProtocol(headers) + if _, err := hp.writeVarint32(int32(t.protocolID)); err != nil { + return NewTTransportExceptionFromError(err) + } + if _, err := hp.writeVarint32(int32(len(t.writeTransforms))); err != nil { + return NewTTransportExceptionFromError(err) + } + for _, transform := range t.writeTransforms { + if _, err := hp.writeVarint32(int32(transform)); err != nil { + return NewTTransportExceptionFromError(err) + } + } + if len(t.writeHeaders) > 0 { + if _, err := hp.writeVarint32(int32(InfoKeyValue)); err != nil { + return NewTTransportExceptionFromError(err) + } + if _, err := hp.writeVarint32(int32(len(t.writeHeaders))); err != nil { + return NewTTransportExceptionFromError(err) + } + for key, value := range t.writeHeaders { + if err := hp.WriteString(key); err != nil { + return NewTTransportExceptionFromError(err) + } + if err := hp.WriteString(value); err != nil { + return NewTTransportExceptionFromError(err) + } + } + } + padding := 4 - headers.Len()%4 + if padding < 4 { + buf := t.buffer[:padding] + for i := range buf { + buf[i] = 0 + } + if _, err := headers.Write(buf); err != nil { + return NewTTransportExceptionFromError(err) + } + } + + var payload bytes.Buffer + meta := headerMeta{ + MagicFlags: THeaderHeaderMagic + t.Flags&THeaderFlagsMask, + SequenceID: t.SequenceID, + HeaderLength: uint16(headers.Len() / 4), + } + if err := binary.Write(&payload, binary.BigEndian, meta); err != nil { + return NewTTransportExceptionFromError(err) + } + if _, err := io.Copy(&payload, headers); err != nil { + return NewTTransportExceptionFromError(err) + } + + writer, err := NewTransformWriter(&payload, t.writeTransforms) + if err != nil { + return NewTTransportExceptionFromError(err) + } + if _, err := io.Copy(writer, &t.writeBuffer); err != nil { + return NewTTransportExceptionFromError(err) + } + if err := writer.Close(); err != nil { + return NewTTransportExceptionFromError(err) + } + + // First write frame length + buf := t.buffer[:size32] + binary.BigEndian.PutUint32(buf, uint32(payload.Len())) + if _, err := t.transport.Write(buf); err != nil { + return NewTTransportExceptionFromError(err) + } + // Then write the payload + if _, err := io.Copy(t.transport, &payload); err != nil { + return NewTTransportExceptionFromError(err) + } + + case clientFramedBinary, clientFramedCompact: + buf := t.buffer[:size32] + binary.BigEndian.PutUint32(buf, uint32(t.writeBuffer.Len())) + if _, err := t.transport.Write(buf); err != nil { + return NewTTransportExceptionFromError(err) + } + fallthrough + case clientUnframedBinary, clientUnframedCompact: + if _, err := io.Copy(t.transport, &t.writeBuffer); err != nil { + return NewTTransportExceptionFromError(err) + } + } + + select { + default: + case <-ctx.Done(): + return NewTTransportExceptionFromError(ctx.Err()) + } + + return t.transport.Flush(ctx) +} + +// Close closes the transport, along with its underlying transport. +func (t *THeaderTransport) Close() error { + if err := t.Flush(context.Background()); err != nil { + return err + } + return t.transport.Close() +} + +// RemainingBytes calls underlying transport's RemainingBytes. +// +// Even in framed cases, because of all the possible compression transforms +// involved, the remaining frame size is likely to be different from the actual +// remaining readable bytes, so we don't bother to keep tracking the remaining +// frame size by ourselves and just use the underlying transport's +// RemainingBytes directly. +func (t *THeaderTransport) RemainingBytes() uint64 { + return t.transport.RemainingBytes() +} + +// GetReadHeaders returns the THeaderMap read from transport. +func (t *THeaderTransport) GetReadHeaders() THeaderMap { + return t.readHeaders +} + +// SetWriteHeader sets a header for write. +func (t *THeaderTransport) SetWriteHeader(key, value string) { + t.writeHeaders[key] = value +} + +// ClearWriteHeaders clears all write headers previously set. +func (t *THeaderTransport) ClearWriteHeaders() { + t.writeHeaders = make(THeaderMap) +} + +// AddTransform add a transform for writing. +func (t *THeaderTransport) AddTransform(transform THeaderTransformID) error { + if !supportedTransformIDs[transform] { + return NewTProtocolExceptionWithType( + NOT_IMPLEMENTED, + fmt.Errorf("THeaderTransformID %d not supported", transform), + ) + } + t.writeTransforms = append(t.writeTransforms, transform) + return nil +} + +// Protocol returns the wrapped protocol id used in this THeaderTransport. +func (t *THeaderTransport) Protocol() THeaderProtocolID { + switch t.clientType { + default: + return t.protocolID + case clientFramedBinary, clientUnframedBinary: + return THeaderProtocolBinary + case clientFramedCompact, clientUnframedCompact: + return THeaderProtocolCompact + } +} + +func (t *THeaderTransport) isFramed() bool { + switch t.clientType { + default: + return false + case clientHeaders, clientFramedBinary, clientFramedCompact: + return true + } +} diff --git a/lib/go/thrift/header_transport_test.go b/lib/go/thrift/header_transport_test.go new file mode 100644 index 00000000000..94af010ec65 --- /dev/null +++ b/lib/go/thrift/header_transport_test.go @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "context" + "io/ioutil" + "testing" +) + +func TestTHeaderHeadersReadWrite(t *testing.T) { + trans := NewTMemoryBuffer() + reader := NewTHeaderTransport(trans) + writer := NewTHeaderTransport(trans) + + const key1 = "key1" + const value1 = "value1" + const key2 = "key2" + const value2 = "value2" + const payload1 = "hello, world1\n" + const payload2 = "hello, world2\n" + + // Write + if err := writer.AddTransform(TransformZlib); err != nil { + t.Fatalf( + "writer.AddTransform(TransformZlib) returned error: %v", + err, + ) + } + // Use double zlib to make sure that we close them in the right order. + if err := writer.AddTransform(TransformZlib); err != nil { + t.Fatalf( + "writer.AddTransform(TransformZlib) returned error: %v", + err, + ) + } + if err := writer.AddTransform(TransformNone); err != nil { + t.Fatalf( + "writer.AddTransform(TransformNone) returned error: %v", + err, + ) + } + writer.SetWriteHeader(key1, value1) + writer.SetWriteHeader(key2, value2) + if _, err := writer.Write([]byte(payload1)); err != nil { + t.Errorf("writer.Write returned error: %v", err) + } + if err := writer.Flush(context.Background()); err != nil { + t.Errorf("writer.Flush returned error: %v", err) + } + if _, err := writer.Write([]byte(payload2)); err != nil { + t.Errorf("writer.Write returned error: %v", err) + } + if err := writer.Flush(context.Background()); err != nil { + t.Errorf("writer.Flush returned error: %v", err) + } + + // Read + read, err := ioutil.ReadAll(reader) + if err != nil { + t.Errorf("Read returned error: %v", err) + } + if string(read) != payload1+payload2 { + t.Errorf( + "Read content expected %q, got %q", + payload1+payload2, + read, + ) + } + if prot := reader.Protocol(); prot != THeaderProtocolBinary { + t.Errorf( + "reader.Protocol() expected %d, got %d", + THeaderProtocolBinary, + prot, + ) + } + if reader.clientType != clientHeaders { + t.Errorf( + "reader.clientType expected %d, got %d", + clientHeaders, + reader.clientType, + ) + } + headers := reader.GetReadHeaders() + if len(headers) != 2 || headers[key1] != value1 || headers[key2] != value2 { + t.Errorf( + "reader.GetReadHeaders() expected size 2, actual content: %+v", + headers, + ) + } +} diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go index 60358025160..7db36c211eb 100644 --- a/lib/go/thrift/simple_server.go +++ b/lib/go/thrift/simple_server.go @@ -187,12 +187,24 @@ func (p *TSimpleServer) processRequests(client TTransport) error { if err != nil { return err } - outputTransport, err := p.outputTransportFactory.GetTransport(client) - if err != nil { - return err - } inputProtocol := p.inputProtocolFactory.GetProtocol(inputTransport) - outputProtocol := p.outputProtocolFactory.GetProtocol(outputTransport) + var outputTransport TTransport + var outputProtocol TProtocol + + // for THeaderProtocol, we must use the same protocol instance for + // input and output so that the response is in the same dialect that + // the server detected the request was in. + if _, ok := inputProtocol.(*THeaderProtocol); ok { + outputProtocol = inputProtocol + } else { + oTrans, err := p.outputTransportFactory.GetTransport(client) + if err != nil { + return err + } + outputTransport = oTrans + outputProtocol = p.outputProtocolFactory.GetProtocol(outputTransport) + } + defer func() { if e := recover(); e != nil { log.Printf("panic in processor: %s: %s", e, debug.Stack()) diff --git a/test/go/src/bin/testserver/main.go b/test/go/src/bin/testserver/main.go index ca2d967b623..6fc1185a239 100644 --- a/test/go/src/bin/testserver/main.go +++ b/test/go/src/bin/testserver/main.go @@ -32,7 +32,7 @@ var host = flag.String("host", "localhost", "Host to connect") var port = flag.Int64("port", 9090, "Port number to connect") var domain_socket = flag.String("domain-socket", "", "Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port") var transport = flag.String("transport", "buffered", "Transport: buffered, framed, http, zlib") -var protocol = flag.String("protocol", "binary", "Protocol: binary, compact, json") +var protocol = flag.String("protocol", "binary", "Protocol: binary, compact, json, header") var ssl = flag.Bool("ssl", false, "Encrypted Transport using SSL") var zlib = flag.Bool("zlib", false, "Wrapped Transport using Zlib") var certPath = flag.String("certPath", "keys", "Directory that contains SSL certificates") @@ -43,7 +43,7 @@ func main() { processor, serverTransport, transportFactory, protocolFactory, err := common.GetServerParams(*host, *port, *domain_socket, *transport, *protocol, *ssl, *certPath, common.PrintingHandler) if err != nil { - log.Fatalf("Unable to process server params: ", err) + log.Fatalf("Unable to process server params: %v", err) } if *transport == "http" { diff --git a/test/go/src/common/client.go b/test/go/src/common/client.go index 236ce43eaf6..ed820aeafd4 100644 --- a/test/go/src/common/client.go +++ b/test/go/src/common/client.go @@ -55,6 +55,8 @@ func StartClient( protocolFactory = thrift.NewTJSONProtocolFactory() case "binary": protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() + case "header": + protocolFactory = thrift.NewTHeaderProtocolFactory() default: return nil, nil, fmt.Errorf("Invalid protocol specified %s", protocol) } diff --git a/test/go/src/common/server.go b/test/go/src/common/server.go index 5ac44000298..c6674ae7597 100644 --- a/test/go/src/common/server.go +++ b/test/go/src/common/server.go @@ -60,6 +60,8 @@ func GetServerParams( protocolFactory = thrift.NewTJSONProtocolFactory() case "binary": protocolFactory = thrift.NewTBinaryProtocolFactoryDefault() + case "header": + protocolFactory = thrift.NewTHeaderProtocolFactory() default: return nil, nil, nil, nil, fmt.Errorf("Invalid protocol specified %s", protocol) } diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index 6c61d5a0785..9f97754d24f 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -31,12 +31,16 @@ "cpp-go_binary_http-ip-ssl", "cpp-go_compact_http-ip", "cpp-go_compact_http-ip-ssl", + "cpp-go_header_http-ip", + "cpp-go_header_http-ip-ssl", "cpp-go_json_http-ip", "cpp-go_json_http-ip-ssl", "cpp-go_multi-binary_http-ip", "cpp-go_multi-binary_http-ip-ssl", "cpp-go_multic-compact_http-ip", "cpp-go_multic-compact_http-ip-ssl", + "cpp-go_multih-header_http-ip", + "cpp-go_multih-header_http-ip-ssl", "cpp-go_multij-json_http-ip", "cpp-go_multij-json_http-ip-ssl", "cpp-java_binary_http-ip", @@ -304,6 +308,8 @@ "go-cpp_binary_http-ip-ssl", "go-cpp_compact_http-ip", "go-cpp_compact_http-ip-ssl", + "go-cpp_header_http-ip", + "go-cpp_header_http-ip-ssl", "go-cpp_json_http-ip", "go-cpp_json_http-ip-ssl", "go-d_binary_http-ip", @@ -357,6 +363,8 @@ "nodejs-go_binary_http-ip-ssl", "nodejs-go_compact_http-ip", "nodejs-go_compact_http-ip-ssl", + "nodejs-go_header_http-ip", + "nodejs-go_header_http-ip-ssl", "nodejs-go_json_http-ip", "nodejs-go_json_http-ip-ssl", "nodejs-hs_binary_http-ip", diff --git a/test/tests.json b/test/tests.json index a4680d15008..851244ec612 100644 --- a/test/tests.json +++ b/test/tests.json @@ -115,7 +115,8 @@ "protocols": [ "binary", "compact", - "json" + "json", + "header" ], "workdir": "go/bin" }, From 433a649a36ce9c78793128391e8466e9e96a9482 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 19 Jun 2019 23:14:08 +0200 Subject: [PATCH 303/756] THRIFT-4886 More detailed error information for WinHTTP transport Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.Transport.WinHTTP.pas | 22 +++++--- lib/delphi/src/Thrift.WinHTTP.pas | 59 +++++++++++++++++++-- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas index d7eefa86298..540865f6922 100644 --- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas @@ -297,9 +297,11 @@ function TWinHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; procedure TWinHTTPClientImpl.SendRequest; var - http : IWinHTTPRequest; + http : IWinHTTPRequest; pData : PByte; - len : Integer; + len : Integer; + error : Cardinal; + sMsg : string; begin http := CreateRequest; @@ -307,12 +309,20 @@ procedure TWinHTTPClientImpl.SendRequest; len := FOutputMemoryStream.Size; // send all data immediately, since we have it in memory - if not http.SendRequest( pData, len, 0) - then raise TTransportExceptionUnknown.Create('send request error '+IntToStr(GetLastError)); + if not http.SendRequest( pData, len, 0) then begin + error := Cardinal( GetLastError); + sMsg := 'WinHTTP send error '+IntToStr(Int64(error))+' '+WinHttpSysErrorMessage(error); + raise TTransportExceptionUnknown.Create(sMsg); + end; // end request and start receiving - if not http.FlushAndReceiveResponse - then raise TTransportExceptionInterrupted.Create('flush/receive error '+IntToStr(GetLastError)); + if not http.FlushAndReceiveResponse then begin + error := Cardinal( GetLastError); + sMsg := 'WinHTTP recv error '+IntToStr(Int64(error))+' '+WinHttpSysErrorMessage(error); + if error = ERROR_WINHTTP_TIMEOUT + then raise TTransportExceptionTimedOut.Create( sMsg) + else raise TTransportExceptionInterrupted.Create( sMsg); + end; FInputStream := THTTPResponseStream.Create(http); end; diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index b26f6ba2a66..8179fae7b60 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -463,6 +463,8 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = WINHTTP_ERROR_BASE + 185; ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = WINHTTP_ERROR_BASE + 186; + WINHTTP_ERROR_LAST = WINHTTP_ERROR_BASE + 186; + const WINHTTP_THRIFT_DEFAULTS = WINHTTP_FLAG_NULL_CODEPAGE @@ -673,6 +675,12 @@ WINHTTP_CURRENT_USER_IE_PROXY_CONFIG_Helper = record helper for WINHTTP_CURREN EWinHTTPException = class(Exception); +{ helper functions } + +function WinHttpSysErrorMessage( const error : Cardinal): string; +procedure RaiseLastWinHttpError; + + implementation const WINHTTP_DLL = 'WinHTTP.dll'; @@ -697,6 +705,48 @@ function WinHttpCrackUrl; stdcall; external WINHTTP_DLL; function WinHttpCreateUrl; stdcall; external WINHTTP_DLL; +{ helper functions } + +function WinHttpSysErrorMessage( const error : Cardinal): string; +const FLAGS = FORMAT_MESSAGE_ALLOCATE_BUFFER + or FORMAT_MESSAGE_IGNORE_INSERTS + or FORMAT_MESSAGE_FROM_SYSTEM + or FORMAT_MESSAGE_FROM_HMODULE; +var pBuffer : PChar; + nChars : Cardinal; +begin + if (error < WINHTTP_ERROR_BASE) + or (error > WINHTTP_ERROR_LAST) + then Exit( SysUtils.SysErrorMessage( error)); + + pBuffer := nil; + try + nChars := FormatMessage( FLAGS, + Pointer( GetModuleHandle( WINHTTP_DLL)), + error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language + @pBuffer, 0, + nil); + SetString( result, pBuffer, nChars); + finally + LocalFree( Cardinal( pBuffer)); + end; +end; + + +procedure RaiseLastWinHttpError; +var error : Cardinal; + sMsg : string; +begin + error := Cardinal( GetLastError); + if error <> NOERROR then begin + sMSg := IntToStr(Integer(error))+' '+WinHttpSysErrorMessage(error); + raise EWinHTTPException.Create( sMsg); + end; +end; + + + { misc. record helper } @@ -785,7 +835,7 @@ constructor TWinHTTPSessionImpl.Create( const aAgent : UnicodeString; const aAcc PWideChar(Pointer(aProxy)), // may be nil PWideChar(Pointer(aProxyBypass)), // may be nil aFlags); - if handle = nil then RaiseLastOSError; + if handle = nil then RaiseLastWinHttpError; inherited Create( handle); end; @@ -824,7 +874,7 @@ constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; con begin FSession := aSession; handle := WinHttpConnect( FSession.Handle, PWideChar(aHostName), aPort, 0); - if handle = nil then RaiseLastOSError; + if handle = nil then RaiseLastWinHttpError; inherited Create( handle); end; @@ -876,7 +926,7 @@ constructor TWinHTTPRequestImpl.Create( const aConnection : IWinHTTPConnection; PWideChar(aReferrer), @accept, aFlags); - if handle = nil then RaiseLastOSError; + if handle = nil then RaiseLastWinHttpError; inherited Create( handle); end; @@ -1191,6 +1241,9 @@ procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString); end; +initialization + OutputDebugString( PChar( SysErrorMessage( 12002))); + end. From 96c6113dda9869b7e2d4318bc0bce4f12f3ca3d2 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 14 Jun 2019 22:39:56 +0200 Subject: [PATCH 304/756] THRIFT-4891 Align HTTP test client with all other variants Client: netstd Patch: Jens Geyer This closes #1816 --- test/netstd/Client/TestClient.cs | 87 +++++++++++++++++--------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/test/netstd/Client/TestClient.cs b/test/netstd/Client/TestClient.cs index ddc36acc5a4..6be10234e87 100644 --- a/test/netstd/Client/TestClient.cs +++ b/test/netstd/Client/TestClient.cs @@ -55,6 +55,7 @@ internal enum TransportChoice { Socket, TlsSocket, + Http, NamedPipe } @@ -79,6 +80,7 @@ internal void Parse( List args) if (args[i] == "-u") { url = args[++i]; + transport = TransportChoice.Http; } else if (args[i] == "-n") { @@ -151,6 +153,9 @@ internal void Parse( List args) case TransportChoice.TlsSocket: Console.WriteLine("Using encrypted transport"); break; + case TransportChoice.Http: + Console.WriteLine("Using HTTP transport"); + break; case TransportChoice.NamedPipe: Console.WriteLine("Using named pipes transport"); break; @@ -223,55 +228,55 @@ private static X509Certificate2 GetClientCert() public TTransport CreateTransport() { - if (url == null) + // endpoint transport + TTransport trans = null; + + switch(transport) { - // endpoint transport - TTransport trans = null; + case TransportChoice.Http: + Debug.Assert(url != null); + trans = new THttpTransport(new Uri(url), null); + break; - switch(transport) - { - case TransportChoice.NamedPipe: - Debug.Assert(pipe != null); - trans = new TNamedPipeTransport(pipe); - break; - - case TransportChoice.TlsSocket: - var cert = GetClientCert(); - if (cert == null || !cert.HasPrivateKey) - { - throw new InvalidOperationException("Certificate doesn't contain private key"); - } + case TransportChoice.NamedPipe: + Debug.Assert(pipe != null); + trans = new TNamedPipeTransport(pipe); + break; + + case TransportChoice.TlsSocket: + var cert = GetClientCert(); + if (cert == null || !cert.HasPrivateKey) + { + throw new InvalidOperationException("Certificate doesn't contain private key"); + } - trans = new TTlsSocketTransport(host, port, 0, cert, - (sender, certificate, chain, errors) => true, - null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); - break; - - case TransportChoice.Socket: - default: - trans = new TSocketTransport(host, port); - break; - } + trans = new TTlsSocketTransport(host, port, 0, cert, + (sender, certificate, chain, errors) => true, + null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); + break; + case TransportChoice.Socket: + default: + trans = new TSocketTransport(host, port); + break; + } - // layered transport - switch(layered) - { - case LayeredChoice.Buffered: - trans = new TBufferedTransport(trans); - break; - case LayeredChoice.Framed: - trans = new TFramedTransport(trans); - break; - default: - Debug.Assert(layered == LayeredChoice.None); - break; - } - return trans; + // layered transport + switch(layered) + { + case LayeredChoice.Buffered: + trans = new TBufferedTransport(trans); + break; + case LayeredChoice.Framed: + trans = new TFramedTransport(trans); + break; + default: + Debug.Assert(layered == LayeredChoice.None); + break; } - return new THttpTransport(new Uri(url), null); + return trans; } public TProtocol CreateProtocol(TTransport transport) From 3f0d4447919a7b358e60b09ab919bbe52758cc98 Mon Sep 17 00:00:00 2001 From: Mustafa Senol Cosar Date: Fri, 1 Mar 2019 18:57:09 +0300 Subject: [PATCH 305/756] Implement episodic compilation for js code generation --- compiler/cpp/Makefile.am | 2 +- .../cpp/src/thrift/generate/t_js_generator.cc | 186 +++++++++++++++--- compiler/cpp/src/thrift/main.cc | 3 + compiler/cpp/src/thrift/parse/t_program.h | 11 +- lib/nodejs/Makefile.am | 2 + .../episodic-code-generation-test/client.js | 77 ++++++++ .../episodic_compilation.package.json | 3 + .../episodic-code-generation-test/server.js | 50 +++++ lib/nodejs/test/testAll.sh | 68 ++++++- test/Service.thrift | 24 +++ test/Types.thrift | 23 +++ 11 files changed, 411 insertions(+), 38 deletions(-) create mode 100644 lib/nodejs/test/episodic-code-generation-test/client.js create mode 100644 lib/nodejs/test/episodic-code-generation-test/episodic_compilation.package.json create mode 100644 lib/nodejs/test/episodic-code-generation-test/server.js create mode 100644 test/Service.thrift create mode 100644 test/Types.thrift diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am index 16d4d3ac8af..9a3aeda5600 100644 --- a/compiler/cpp/Makefile.am +++ b/compiler/cpp/Makefile.am @@ -65,7 +65,7 @@ thrift_SOURCES = src/thrift/audit/t_audit.cpp \ src/thrift/parse/t_type.h \ src/thrift/parse/t_typedef.cc \ src/thrift/parse/t_typedef.h \ - src/thrift/platform.h + src/thrift/platform.h # Specific client generator source thrift_SOURCES += src/thrift/generate/t_as3_generator.cc \ diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc index af402a439de..88758b2a00a 100644 --- a/compiler/cpp/src/thrift/generate/t_js_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -38,9 +39,11 @@ using std::ostream; using std::ostringstream; using std::string; using std::stringstream; +using std::unordered_map; using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes +static const string episode_file_name = "thrift.js.episode"; // largest consecutive integer representable by a double (2 ^ 53 - 1) static const int64_t max_safe_integer = 0x1fffffffffffff; // smallest consecutive number representable by a double (-2 ^ 53 + 1) @@ -65,6 +68,7 @@ class t_js_generator : public t_oop_generator { gen_jquery_ = false; gen_ts_ = false; gen_es6_ = false; + gen_episode_file_ = false; bool with_ns_ = false; @@ -79,22 +83,26 @@ class t_js_generator : public t_oop_generator { with_ns_ = true; } else if( iter->first.compare("es6") == 0) { gen_es6_ = true; + } else if( iter->first.compare("imports") == 0) { + parse_imports(program, iter->second); + } else if (iter->first.compare("thrift_package_output_directory") == 0) { + parse_thrift_package_output_directory(iter->second); } else { - throw "unknown option js:" + iter->first; + throw std::invalid_argument("unknown option js:" + iter->first); } } if (gen_es6_ && gen_jquery_) { - throw "Invalid switch: [-gen js:es6,jquery] options not compatible"; + throw std::invalid_argument("invalid switch: [-gen js:es6,jquery] options not compatible"); } if (gen_node_ && gen_jquery_) { - throw "Invalid switch: [-gen js:node,jquery] options not compatible, try: [-gen js:node -gen " - "js:jquery]"; + throw std::invalid_argument("invalid switch: [-gen js:node,jquery] options not compatible, try: [-gen js:node -gen " + "js:jquery]"); } if (!gen_node_ && with_ns_) { - throw "Invalid switch: [-gen js:with_ns] is only valid when using node.js"; + throw std::invalid_argument("invalid switch: [-gen js:with_ns] is only valid when using node.js"); } // Depending on the processing flags, we will update these to be ES6 compatible @@ -207,6 +215,7 @@ class t_js_generator : public t_oop_generator { std::string ts_service_includes(); std::string render_includes(); std::string render_ts_includes(); + std::string get_import_path(t_program* program); std::string declare_field(t_field* tfield, bool init = false, bool obj = false); std::string function_signature(t_function* tfunction, std::string prefix = "", @@ -215,6 +224,13 @@ class t_js_generator : public t_oop_generator { std::string type_to_enum(t_type* ttype); std::string make_valid_nodeJs_identifier(std::string const& name); + /** + * Helper parser functions + */ + + void parse_imports(t_program* program, const std::string& imports_string); + void parse_thrift_package_output_directory(const std::string& thrift_package_output_directory); + std::string autogen_comment() override { return std::string("//\n") + "// Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" + "//\n" + "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" @@ -353,6 +369,11 @@ class t_js_generator : public t_oop_generator { */ bool gen_es6_; + /** + * True if we will generate an episode file. + */ + bool gen_episode_file_; + /** * The name of the defined module(s), for TypeScript Definition Files. */ @@ -363,6 +384,21 @@ class t_js_generator : public t_oop_generator { */ bool no_ns_; + /** + * The node modules to use when importing the previously generated files. + */ + vector imports; + + /** + * Cache for imported modules. + */ + unordered_map module_name_2_import_path; + + /** + * The prefix to use when generating the episode file. + */ + string thrift_package_output_directory_; + /** * The variable decorator for "const" variables. Will default to "var" if in an incompatible language. */ @@ -381,6 +417,7 @@ class t_js_generator : public t_oop_generator { /** * File streams */ + ofstream_with_content_based_conditional_update f_episode_; ofstream_with_content_based_conditional_update f_types_; ofstream_with_content_based_conditional_update f_service_; ofstream_with_content_based_conditional_update f_types_ts_; @@ -397,14 +434,23 @@ void t_js_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); - string outdir = get_out_dir(); + const auto outdir = get_out_dir(); // Make output file(s) - string f_types_name = outdir + program_->get_name() + "_types.js"; + if (gen_episode_file_) { + const auto f_episode_file_path = outdir + episode_file_name; + f_episode_.open(f_episode_file_path); + } + + const auto f_types_name = outdir + program_->get_name() + "_types.js"; f_types_.open(f_types_name.c_str()); + if (gen_episode_file_) { + const auto types_module = program_->get_name() + "_types"; + f_episode_ << types_module << ":" << thrift_package_output_directory_ << "/" << types_module << endl; + } if (gen_ts_) { - string f_types_ts_name = outdir + program_->get_name() + "_types.d.ts"; + const auto f_types_ts_name = outdir + program_->get_name() + "_types.d.ts"; f_types_ts_.open(f_types_ts_name.c_str()); } @@ -500,8 +546,7 @@ string t_js_generator::render_includes() { if (gen_node_) { const vector& includes = program_->get_includes(); for (auto include : includes) { - result += js_const_type_ + make_valid_nodeJs_identifier(include->get_name()) + "_ttypes = require('./" + include->get_name() - + "_types');\n"; + result += js_const_type_ + make_valid_nodeJs_identifier(include->get_name()) + "_ttypes = require('" + get_import_path(include) + "');\n"; } if (includes.size() > 0) { result += "\n"; @@ -522,8 +567,7 @@ string t_js_generator::render_ts_includes() { } const vector& includes = program_->get_includes(); for (auto include : includes) { - result += "import " + make_valid_nodeJs_identifier(include->get_name()) + "_ttypes = require('./" + include->get_name() - + "_types');\n"; + result += "import " + make_valid_nodeJs_identifier(include->get_name()) + "_ttypes = require('" + get_import_path(include) + "');\n"; } if (includes.size() > 0) { result += "\n"; @@ -532,6 +576,21 @@ string t_js_generator::render_ts_includes() { return result; } +string t_js_generator::get_import_path(t_program* program) { + const string import_file_name(program->get_name() + "_types"); + if (program->get_recursive()) { + return "./" + import_file_name; + } + + const string import_file_name_with_extension = import_file_name + ".js"; + + auto module_name_and_import_path_iterator = module_name_2_import_path.find(import_file_name); + if (module_name_and_import_path_iterator != module_name_2_import_path.end()) { + return module_name_and_import_path_iterator->second; + } + return "./" + import_file_name; +} + /** * Close up (or down) some filez. */ @@ -546,6 +605,9 @@ void t_js_generator::close_generator() { } f_types_ts_.close(); } + if (gen_episode_file_){ + f_episode_.close(); + } } /** @@ -657,7 +719,7 @@ string t_js_generator::render_const_value(t_type* type, t_const_value* value) { } break; default: - throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); + throw std::runtime_error("compiler error: no const of base type " + t_base_type::t_base_name(tbase)); } } else if (type->is_enum()) { out << value->get_integer(); @@ -676,7 +738,7 @@ string t_js_generator::render_const_value(t_type* type, t_const_value* value) { } } if (field_type == NULL) { - throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); + throw std::runtime_error("type error: " + type->get_name() + " has no field " + v_iter->first->get_string()); } if (v_iter != val.begin()) out << ","; @@ -698,7 +760,7 @@ string t_js_generator::render_const_value(t_type* type, t_const_value* value) { for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { if (v_iter != val.begin()) out << "," << endl; - + if (ktype->is_base_type() && ((t_base_type*)get_true_type(ktype))->get_base() == t_base_type::TYPE_I64){ out << indent() << "\"" << v_iter->first->get_integer() << "\""; } else { @@ -846,7 +908,6 @@ void t_js_generator::generate_js_struct_definition(ostream& out, f_types_ts_ << ts_indent() << (*m_iter)->get_name() << ": " << ts_get_type((*m_iter)->get_type()) << ";" << endl; } - } } @@ -1124,6 +1185,9 @@ void t_js_generator::generate_js_struct_writer(ostream& out, t_struct* tstruct) void t_js_generator::generate_service(t_service* tservice) { string f_service_name = get_out_dir() + service_name_ + ".js"; f_service_.open(f_service_name.c_str()); + if (gen_episode_file_) { + f_episode_ << service_name_ << ":" << thrift_package_output_directory_ << "/" << service_name_ << endl; + } if (gen_ts_) { string f_service_ts_name = get_out_dir() + service_name_ + ".d.ts"; @@ -2136,7 +2200,7 @@ void t_js_generator::generate_deserialize_field(ostream& out, t_type* type = get_true_type(tfield->get_type()); if (type->is_void()) { - throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); + throw std::runtime_error("CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name()); } string name = prefix + tfield->get_name(); @@ -2152,7 +2216,7 @@ void t_js_generator::generate_deserialize_field(ostream& out, t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: - throw "compiler error: cannot serialize void field in a struct: " + name; + throw std::runtime_error("compiler error: cannot serialize void field in a struct: " + name); break; case t_base_type::TYPE_STRING: out << (type->is_binary() ? "readBinary()" : "readString()"); @@ -2176,7 +2240,7 @@ void t_js_generator::generate_deserialize_field(ostream& out, out << "readDouble()"; break; default: - throw "compiler error: no JS name for base type " + t_base_type::t_base_name(tbase); + throw std::runtime_error("compiler error: no JS name for base type " + t_base_type::t_base_name(tbase)); } } else if (type->is_enum()) { out << "readI32()"; @@ -2317,7 +2381,7 @@ void t_js_generator::generate_serialize_field(ostream& out, t_field* tfield, str // Do nothing for void types if (type->is_void()) { - throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); + throw std::runtime_error("CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name()); } if (type->is_struct() || type->is_xception()) { @@ -2338,7 +2402,7 @@ void t_js_generator::generate_serialize_field(ostream& out, t_field* tfield, str t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: - throw "compiler error: cannot serialize void field in a struct: " + name; + throw std::runtime_error("compiler error: cannot serialize void field in a struct: " + name); break; case t_base_type::TYPE_STRING: out << (type->is_binary() ? "writeBinary(" : "writeString(") << name << ")"; @@ -2362,7 +2426,7 @@ void t_js_generator::generate_serialize_field(ostream& out, t_field* tfield, str out << "writeDouble(" << name << ")"; break; default: - throw "compiler error: no JS name for base type " + t_base_type::t_base_name(tbase); + throw std::runtime_error("compiler error: no JS name for base type " + t_base_type::t_base_name(tbase)); } } else if (type->is_enum()) { out << "writeI32(" << name << ")"; @@ -2510,7 +2574,7 @@ string t_js_generator::declare_field(t_field* tfield, bool init, bool obj) { result += " = null"; break; default: - throw "compiler error: no JS initializer for base type " + t_base_type::t_base_name(tbase); + throw std::runtime_error("compiler error: no JS initializer for base type " + t_base_type::t_base_name(tbase)); } } else if (type->is_enum()) { result += " = null"; @@ -2589,7 +2653,7 @@ string t_js_generator::type_to_enum(t_type* type) { t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); switch (tbase) { case t_base_type::TYPE_VOID: - throw "NO T_VOID CONSTRUCT"; + throw std::runtime_error("NO T_VOID CONSTRUCT"); case t_base_type::TYPE_STRING: return "Thrift.Type.STRING"; case t_base_type::TYPE_BOOL: @@ -2617,7 +2681,7 @@ string t_js_generator::type_to_enum(t_type* type) { return "Thrift.Type.LIST"; } - throw "INVALID TYPE IN type_to_enum: " + type->get_name(); + throw std::runtime_error("INVALID TYPE IN type_to_enum: " + type->get_name()); } /** @@ -2785,10 +2849,80 @@ std::string t_js_generator::make_valid_nodeJs_identifier(std::string const& name return str; } +void t_js_generator::parse_imports(t_program* program, const std::string& imports_string) { + if (program->get_recursive()) { + throw std::invalid_argument("[-gen js:imports=] option is not usable in recursive code generation mode"); + } + std::stringstream sstream(imports_string); + std::string import; + while (std::getline(sstream, import, ':')) { + imports.emplace_back(import); + } + if (imports.empty()) { + throw std::invalid_argument("invalid usage: [-gen js:imports=] requires at least one path " + "(multiple paths are separated by ':')"); + } + for (auto& import : imports) { + // Strip trailing '/' + if (!import.empty() && import[import.size() - 1] == '/') { + import = import.substr(0, import.size() - 1); + } + if (import.empty()) { + throw std::invalid_argument("empty paths are not allowed in imports"); + } + std::ifstream episode_file; + string line; + const auto episode_file_path = import + "/" + episode_file_name; + episode_file.open(episode_file_path); + if (!episode_file) { + throw std::runtime_error("failed to open the file '" + episode_file_path + "'"); + } + while (std::getline(episode_file, line)) { + const auto separator_position = line.find(':'); + if (separator_position == string::npos) { + // could not find the separator in the line + throw std::runtime_error("the episode file '" + episode_file_path + "' is malformed, the line '" + line + + "' does not have a key:value separator ':'"); + } + const auto module_name = line.substr(0, separator_position); + const auto import_path = line.substr(separator_position + 1); + if (module_name.empty()) { + throw std::runtime_error("the episode file '" + episode_file_path + "' is malformed, the module name is empty"); + } + if (import_path.empty()) { + throw std::runtime_error("the episode file '" + episode_file_path + "' is malformed, the import path is empty"); + } + const auto module_import_path = import.substr(import.find_last_of('/') + 1) + "/" + import_path; + const auto result = module_name_2_import_path.emplace(module_name, module_import_path); + if (!result.second) { + throw std::runtime_error("multiple providers of import path found for " + module_name + + "\n\t" + module_import_path + "\n\t" + result.first->second); + } + } + } +} +void t_js_generator::parse_thrift_package_output_directory(const std::string& thrift_package_output_directory) { + thrift_package_output_directory_ = thrift_package_output_directory; + // Strip trailing '/' + if (!thrift_package_output_directory_.empty() && thrift_package_output_directory_[thrift_package_output_directory_.size() - 1] == '/') { + thrift_package_output_directory_ = thrift_package_output_directory_.substr(0, thrift_package_output_directory_.size() - 1); + } + // Check that the thrift_package_output_directory is not empty after stripping + if (thrift_package_output_directory_.empty()) { + throw std::invalid_argument("the thrift_package_output_directory argument must not be empty"); + } else { + gen_episode_file_ = true; + } +} + THRIFT_REGISTER_GENERATOR(js, "Javascript", " jquery: Generate jQuery compatible code.\n" " node: Generate node.js compatible code.\n" " ts: Generate TypeScript definition files.\n" " with_ns: Create global namespace objects when using node.js\n" - " es6: Create ES6 code with Promises\n") + " es6: Create ES6 code with Promises\n" + " thrift_package_output_directory=:\n" + " Generate episode file and use the as prefix\n" + " imports=:\n" + " ':' separated list of paths of modules that has episode files in their root\n") diff --git a/compiler/cpp/src/thrift/main.cc b/compiler/cpp/src/thrift/main.cc index 5b69dc502ee..03e0d6f4842 100644 --- a/compiler/cpp/src/thrift/main.cc +++ b/compiler/cpp/src/thrift/main.cc @@ -982,6 +982,7 @@ void parse(t_program* program, t_program* parent_program) { void generate(t_program* program, const vector& generator_strings) { // Oooohh, recursive code generation, hot!! if (gen_recurse) { + program->set_recursive(true); const vector& includes = program->get_includes(); for (auto include : includes) { // Propagate output path from parent to child programs @@ -1017,6 +1018,8 @@ void generate(t_program* program, const vector& generator_strings) { failure("Error: %s\n", s.c_str()); } catch (const char* exc) { failure("Error: %s\n", exc); + } catch (const std::invalid_argument& invalid_argument_exception) { + failure("Error: %s\n", invalid_argument_exception.what()); } } diff --git a/compiler/cpp/src/thrift/parse/t_program.h b/compiler/cpp/src/thrift/parse/t_program.h index 13cb26e5fa2..140dc35d917 100644 --- a/compiler/cpp/src/thrift/parse/t_program.h +++ b/compiler/cpp/src/thrift/parse/t_program.h @@ -58,9 +58,9 @@ class t_program : public t_doc { public: t_program(std::string path, std::string name) - : path_(path), name_(name), out_path_("./"), out_path_is_absolute_(false), scope_(new t_scope) {} + : path_(path), name_(name), out_path_("./"), out_path_is_absolute_(false), scope_(new t_scope), recursive_(false) {} - t_program(std::string path) : path_(path), out_path_("./"), out_path_is_absolute_(false) { + t_program(std::string path) : path_(path), out_path_("./"), out_path_is_absolute_(false), recursive_(false) { name_ = program_name(path); scope_ = new t_scope(); } @@ -355,6 +355,10 @@ class t_program : public t_doc { const std::vector& get_c_includes() const { return c_includes_; } + void set_recursive(const bool recursive) { recursive_ = recursive; } + + bool get_recursive() const { return recursive_; } + private: // File path std::string path_; @@ -400,6 +404,9 @@ class t_program : public t_doc { // C extra includes std::vector c_includes_; + + // Recursive code generation + bool recursive_; }; #endif diff --git a/lib/nodejs/Makefile.am b/lib/nodejs/Makefile.am index 091f768b90a..71068b58f18 100755 --- a/lib/nodejs/Makefile.am +++ b/lib/nodejs/Makefile.am @@ -34,6 +34,8 @@ check: deps clean-local: $(RM) -r test/gen-* $(RM) -r $(top_srcdir)/node_modules + $(RM) -r test/episodic-code-generation-test/gen* + $(RM) -r test/episodic-code-generation-test/node_modules EXTRA_DIST = \ examples \ diff --git a/lib/nodejs/test/episodic-code-generation-test/client.js b/lib/nodejs/test/episodic-code-generation-test/client.js new file mode 100644 index 00000000000..55dc70269ca --- /dev/null +++ b/lib/nodejs/test/episodic-code-generation-test/client.js @@ -0,0 +1,77 @@ +#!/usr/bin/env node + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const assert = require("assert"); +const test = require("tape"); +const thrift = require("thrift"); +const program = require("commander"); + +program + .option("--host ", "Set the thrift server host to connect", "localhost") + .option("--port ", "Set the thrift server port number to connect", 9090) + .parse(process.argv); + +const Service = require("./gen-2/second-episode/gen-nodejs/Service"); +const Types = require("types-package/first-episode/Types_types"); + +const host = program.host; +const port = program.port; + +const options = { + transport: thrift.TBufferedTransport, + protocol: thrift.TJSONProtocol +}; + +const connection = thrift.createConnection(host, port, options); +const testDriver = function(client, callback) { + test("NodeJS episodic compilation client-server test", function(assert) { + const type1Object = new Types.Type1(); + type1Object.number = 42; + type1Object.message = "The answer"; + client.testEpisode(type1Object, function(err, response) { + assert.error(err, "no callback error"); + assert.equal(response.number, type1Object.number + 1); + assert.equal( + response.message, + type1Object.message + " [Hello from the server]" + ); + assert.end(); + callback("Server successfully tested"); + }); + }); +}; + +connection.on("error", function(err) { + assert(false, err); +}); + +const client = thrift.createClient(Service, connection); + +runTests(); + +function runTests() { + testDriver(client, function(status) { + console.log(status); + connection.destroy(); + }); +} + +exports.expressoTest = function() {}; diff --git a/lib/nodejs/test/episodic-code-generation-test/episodic_compilation.package.json b/lib/nodejs/test/episodic-code-generation-test/episodic_compilation.package.json new file mode 100644 index 00000000000..7a78b4beb85 --- /dev/null +++ b/lib/nodejs/test/episodic-code-generation-test/episodic_compilation.package.json @@ -0,0 +1,3 @@ +{ + "name": "types-package" +} diff --git a/lib/nodejs/test/episodic-code-generation-test/server.js b/lib/nodejs/test/episodic-code-generation-test/server.js new file mode 100644 index 00000000000..2917b681c84 --- /dev/null +++ b/lib/nodejs/test/episodic-code-generation-test/server.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * 'License'); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +const thrift = require("../../lib/thrift"); +const program = require("commander"); + +program + .option("--port ", "Set the thrift server port", 9090) + .parse(process.argv); + +const Service = require("./gen-2/second-episode/gen-nodejs/Service"); +const Types = require("types-package/first-episode/Types_types"); + +const port = program.port; + +const options = { + transport: thrift.TBufferedTransport, + protocol: thrift.TJSONProtocol +}; + +const ServiceHandler = { + testEpisode: function(receivedType1Object) { + const type1Object = new Types.Type1(); + type1Object.number = receivedType1Object.number + 1; + type1Object.message = + receivedType1Object.message + " [Hello from the server]"; + return type1Object; + } +}; + +const server = thrift.createServer(Service, ServiceHandler, options); +server.listen(port); diff --git a/lib/nodejs/test/testAll.sh b/lib/nodejs/test/testAll.sh index e98b198be25..3ae88b369f6 100755 --- a/lib/nodejs/test/testAll.sh +++ b/lib/nodejs/test/testAll.sh @@ -23,6 +23,12 @@ fi DIR="$( cd "$( dirname "$0" )" && pwd )" +EPISODIC_DIR=${DIR}/episodic-code-generation-test + +THRIFT_FILES_DIR=${DIR}/../../../test + +THRIFT_COMPILER=${DIR}/../../../compiler/cpp/thrift + ISTANBUL="$DIR/../../../node_modules/istanbul/lib/cli.js" REPORT_PREFIX="${DIR}/../coverage/report" @@ -54,26 +60,68 @@ testServer() return $RET } +testEpisodicCompilation() +{ + RET=0 + if [ -n "${COVER}" ]; then + ${ISTANBUL} cover ${EPISODIC_DIR}/server.js --dir ${REPORT_PREFIX}${COUNT} --handle-sigint & + COUNT=$((COUNT+1)) + else + node ${EPISODIC_DIR}/server.js & + fi + SERVERPID=$! + sleep 0.1 + if [ -n "${COVER}" ]; then + ${ISTANBUL} cover ${EPISODIC_DIR}/client.js --dir ${REPORT_PREFIX}${COUNT} || RET=1 + COUNT=$((COUNT+1)) + else + node ${EPISODIC_DIR}/client.js || RET=1 + fi + kill -2 $SERVERPID || RET=1 + wait $SERVERPID + return $RET +} + TESTOK=0 -#generating thrift code +# generating Thrift code -${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node ${DIR}/../../../test/ThriftTest.thrift -${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node ${DIR}/../../../test/JsDeepConstructorTest.thrift -${DIR}/../../../compiler/cpp/thrift -o ${DIR} --gen js:node ${DIR}/../../../test/Int64Test.thrift +${THRIFT_COMPILER} -o ${DIR} --gen js:node ${THRIFT_FILES_DIR}/ThriftTest.thrift +${THRIFT_COMPILER} -o ${DIR} --gen js:node ${THRIFT_FILES_DIR}/JsDeepConstructorTest.thrift +${THRIFT_COMPILER} -o ${DIR} --gen js:node ${THRIFT_FILES_DIR}/Int64Test.thrift mkdir ${DIR}/gen-nodejs-es6 -${DIR}/../../../compiler/cpp/thrift -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${DIR}/../../../test/ThriftTest.thrift -${DIR}/../../../compiler/cpp/thrift -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${DIR}/../../../test/JsDeepConstructorTest.thrift -${DIR}/../../../compiler/cpp/thrift -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${DIR}/../../../test/Int64Test.thrift +${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/ThriftTest.thrift +${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/JsDeepConstructorTest.thrift +${THRIFT_COMPILER} -out ${DIR}/gen-nodejs-es6 --gen js:node,es6 ${THRIFT_FILES_DIR}/Int64Test.thrift + +# generate episodic compilation test code +TYPES_PACKAGE=${EPISODIC_DIR}/node_modules/types-package + +# generate the first episode +mkdir --parents ${EPISODIC_DIR}/gen-1/first-episode +${THRIFT_COMPILER} -o ${EPISODIC_DIR}/gen-1/first-episode --gen js:node,thrift_package_output_directory=first-episode ${THRIFT_FILES_DIR}/Types.thrift + +# create a "package" from the first episode and "install" it, the episode file must be at the module root +mkdir --parents ${TYPES_PACKAGE}/first-episode +cp --force ${EPISODIC_DIR}/episodic_compilation.package.json ${TYPES_PACKAGE}/package.json +cp --force ${EPISODIC_DIR}/gen-1/first-episode/gen-nodejs/Types_types.js ${TYPES_PACKAGE}/first-episode/ +cp --force ${EPISODIC_DIR}/gen-1/first-episode/gen-nodejs/thrift.js.episode ${TYPES_PACKAGE} + +# generate the second episode +mkdir --parents ${EPISODIC_DIR}/gen-2/second-episode +${THRIFT_COMPILER} -o ${EPISODIC_DIR}/gen-2/second-episode --gen js:node,imports=${TYPES_PACKAGE} ${THRIFT_FILES_DIR}/Service.thrift +if [ -f ${EPISODIC_DIR}/gen-2/second-episode/Types_types.js ]; then + TESTOK=1 +fi -#unit tests +# unit tests node ${DIR}/binary.test.js || TESTOK=1 node ${DIR}/int64.test.js || TESTOK=1 node ${DIR}/deep-constructor.test.js || TESTOK=1 -#integration tests +# integration tests for type in tcp multiplex websocket http do @@ -91,6 +139,8 @@ do done done +# episodic compilation test +testEpisodicCompilation if [ -n "${COVER}" ]; then ${ISTANBUL} report --dir "${DIR}/../coverage" --include "${DIR}/../coverage/report*/coverage.json" lcov cobertura html diff --git a/test/Service.thrift b/test/Service.thrift new file mode 100644 index 00000000000..6f4c9c7a3d7 --- /dev/null +++ b/test/Service.thrift @@ -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. + */ + +include "Types.thrift" + +service Service { + Types.Type1 testEpisode(1:Types.Type1 arg) +} diff --git a/test/Types.thrift b/test/Types.thrift new file mode 100644 index 00000000000..11069d998a7 --- /dev/null +++ b/test/Types.thrift @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +struct Type1 { + 1: i32 number, + 2: string message, +} \ No newline at end of file From 29ecfaba536984e0a41fb1f1bcb1520640dd5471 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 14 Jun 2019 13:01:31 +0000 Subject: [PATCH 306/756] CPP generator test, catching exceptions by ref instead. --- lib/cpp/test/processor/EventLog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cpp/test/processor/EventLog.cpp b/lib/cpp/test/processor/EventLog.cpp index c8e0d9b0247..c75955d277e 100644 --- a/lib/cpp/test/processor/EventLog.cpp +++ b/lib/cpp/test/processor/EventLog.cpp @@ -98,7 +98,7 @@ Event EventLog::waitForEvent(int64_t timeout) { while (events_.empty()) { monitor_.wait(timeout); } - } catch (TimedOutException ex) { + } catch (const TimedOutException &) { return Event(ET_LOG_END, 0, 0, ""); } @@ -119,7 +119,7 @@ Event EventLog::waitForConnEvent(uint32_t connId, int64_t timeout) { while (it == events_.end()) { monitor_.wait(timeout); } - } catch (TimedOutException ex) { + } catch (const TimedOutException &) { return Event(ET_LOG_END, 0, 0, ""); } From a85d532bb397ecfab59afa079da1fe776548af08 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 17 Jun 2019 04:06:41 -0400 Subject: [PATCH 307/756] Fix mingw appveyor build issue [skip travis] --- build/appveyor/MING-appveyor-install.bat | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/build/appveyor/MING-appveyor-install.bat b/build/appveyor/MING-appveyor-install.bat index 1069b058b4b..4b5d730fb28 100644 --- a/build/appveyor/MING-appveyor-install.bat +++ b/build/appveyor/MING-appveyor-install.bat @@ -36,10 +36,16 @@ SET PACKAGES=^ ::mingw-w64-%MINGWPLAT%-qt5 : WAY too large (1GB download!) - tested in cygwin builds anyway +:: the following uninstall and system upgrade was causing issues; appveyor's is relatively new :: Remove old packages that no longer exist to avoid an error -%BASH% -lc "pacman --noconfirm --remove libcatgets catgets || true" || EXIT /B +:: %BASH% -lc "pacman --noconfirm --remove libcatgets catgets || true" || EXIT /B + +:: Remove incompatible packages 8.2.0-3 and 7.3.0-2 (mingw packaging bugs if you ask me!) +:: %BASH% -lc "pacman --noconfirm --remove mingw-w64-x86_64-gcc-ada mingw-w64-x86_64-gcc-objc || true" || EXIT /B +:: %BASH% -lc "pacman --noconfirm --remove mingw-w64-x86_64-gcc-ada mingw-w64-x86_64-gcc-objc || true" || EXIT /B :: Upgrade things -%BASH% -lc "pacman --noconfirm -Syu %IGNORE%" || EXIT /B -%BASH% -lc "pacman --noconfirm -Su %IGNORE%" || EXIT /B -%BASH% -lc "pacman --noconfirm %PACKAGES%" || EXIT /B \ No newline at end of file +:: %BASH% -lc "pacman --noconfirm -Syu %IGNORE%" || EXIT /B +:: %BASH% -lc "pacman --noconfirm -Su %IGNORE%" || EXIT /B +:: +%BASH% -lc "pacman --noconfirm %PACKAGES%" || EXIT /B From 95870f06cdee04b9ec8a263f8c71597a3b95678a Mon Sep 17 00:00:00 2001 From: antbofh Date: Fri, 21 Jun 2019 22:33:55 +0300 Subject: [PATCH 308/756] THRIFT-4892: fixed data type conflict with simultaneous usage of bytes and str (#1804) --- lib/py/src/transport/TTransport.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/py/src/transport/TTransport.py b/lib/py/src/transport/TTransport.py index d13060f810f..8573ba7b943 100644 --- a/lib/py/src/transport/TTransport.py +++ b/lib/py/src/transport/TTransport.py @@ -376,7 +376,7 @@ def open(self): if not self.transport.isOpen(): self.transport.open() - self.send_sasl_msg(self.START, self.sasl.mechanism) + self.send_sasl_msg(self.START, bytes(self.sasl.mechanism, 'ascii')) self.send_sasl_msg(self.OK, self.sasl.process()) while True: @@ -417,7 +417,7 @@ def write(self, data): def flush(self): data = self.__wbuf.getvalue() encoded = self.sasl.wrap(data) - self.transport.write(''.join((pack("!i", len(encoded)), encoded))) + self.transport.write(pack("!i", len(encoded)) + encoded) self.transport.flush() self.__wbuf = BufferIO() From 19505c3de3f235b71da46b971c3ce38d59db1f22 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 22 Jun 2019 00:59:54 +0200 Subject: [PATCH 309/756] THRIFT-4894 Enable automatic content encoding handling for gzip,deflate in the WinHTTP client Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.Transport.WinHTTP.pas | 3 +++ lib/delphi/src/Thrift.WinHTTP.pas | 28 +++++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas index 540865f6922..262e38fb129 100644 --- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas @@ -166,6 +166,9 @@ function TWinHTTPClientImpl.CreateRequest: IWinHTTPRequest; Result.AddRequestHeader( pair.Key +': '+ pair.Value, WINHTTP_ADDREQ_FLAG_ADD); end; + // enable automatic gzip,deflate decompression + result.EnableAutomaticContentDecompression(TRUE); + // AutoProxy support info := TErrorInfo.AutoProxy; result.TryAutoProxy( FUri); diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index 8179fae7b60..8d677dd3e01 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -305,9 +305,11 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; WINHTTP_OPTION_SERVER_SPN_USED = 106; WINHTTP_OPTION_PROXY_SPN_USED = 107; WINHTTP_OPTION_SERVER_CBT = 108; + // options for newer WinHTTP versions + WINHTTP_OPTION_DECOMPRESSION = 118; // WINHTTP_FIRST_OPTION = WINHTTP_OPTION_CALLBACK; - WINHTTP_LAST_OPTION = WINHTTP_OPTION_SERVER_CBT; + //WINHTTP_LAST_OPTION = WINHTTP_OPTION_SERVER_CBT; WINHTTP_OPTION_USERNAME = $1000; WINHTTP_OPTION_PASSWORD = $1001; @@ -368,6 +370,12 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; WINHTTP_AUTH_TARGET_SERVER = $00000000; WINHTTP_AUTH_TARGET_PROXY = $00000001; + // options for WINHTTP_OPTION_DECOMPRESSION + WINHTTP_DECOMPRESSION_FLAG_GZIP = $00000001; + WINHTTP_DECOMPRESSION_FLAG_DEFLATE = $00000002; + WINHTTP_DECOMPRESSION_FLAG_ALL = WINHTTP_DECOMPRESSION_FLAG_GZIP + or WINHTTP_DECOMPRESSION_FLAG_DEFLATE; + // values for WINHTTP_OPTION_SECURITY_FLAGS // query only @@ -478,12 +486,13 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; IWinHTTPConnection = interface; IWinHTTPRequest = interface - ['{0B7D095E-BB3D-4444-8686-5536E7D6437B}'] + ['{F65952F2-2F3B-47DC-B524-F1694E6D2AD7}'] function Handle : HINTERNET; function Connection : IWinHTTPConnection; function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; procedure TryAutoProxy( const aUrl : string); + procedure EnableAutomaticContentDecompression( const aEnable : Boolean); function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean; function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD; function FlushAndReceiveResponse : Boolean; @@ -601,6 +610,7 @@ TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest) function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean; procedure TryAutoProxy( const aUrl : string); + procedure EnableAutomaticContentDecompression( const aEnable : Boolean); function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean; function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD; function FlushAndReceiveResponse : Boolean; @@ -1033,6 +1043,20 @@ procedure TWinHTTPRequestImpl.TryAutoProxy( const aUrl : string); end; +procedure TWinHTTPRequestImpl.EnableAutomaticContentDecompression( const aEnable : Boolean); +// Enable automatic gzip,deflate decompression on systems that support this option +// From the docs: WinHTTP will automatically set an appropriate Accept-Encoding header, +// overriding any value supplied by the caller -> we don't have to do this +// Available on Win 8.1 or higher +var value : DWORD; +begin + if aEnable + then value := WINHTTP_DECOMPRESSION_FLAG_ALL + else value := 0; + + // ignore returned value, the option is not supported with older WinHTTP versions + WinHttpSetOption( Handle, WINHTTP_OPTION_DECOMPRESSION, @value, SizeOf(DWORD)); +end; function TWinHTTPRequestImpl.SendRequest( const pBuf : Pointer; const dwBytes, dwExtra : DWORD) : Boolean; From 1e808af7b319802527517a7161d4e3edbde6f5b3 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 22 Jun 2019 00:24:07 +0200 Subject: [PATCH 310/756] THRIFT-4893 Enable automatic content encoding handling for gzip,deflate in the HTTP client Client: netstd Patch: Jens Geyer This closes #1818 --- lib/netstd/Thrift/Transport/Client/THttpTransport.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs index 982e91e81e0..21cc409626b 100644 --- a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs @@ -139,6 +139,7 @@ private HttpClient CreateClient(IDictionary customRequestHeaders { var handler = new HttpClientHandler(); handler.ClientCertificates.AddRange(_certificates); + handler.AutomaticDecompression = System.Net.DecompressionMethods.Deflate | System.Net.DecompressionMethods.GZip; var httpClient = new HttpClient(handler); @@ -149,7 +150,10 @@ private HttpClient CreateClient(IDictionary customRequestHeaders httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd(UserAgent); - + + httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate")); + httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip")); + if (customRequestHeaders != null) { foreach (var item in customRequestHeaders) From 99ae730c5dac4c7a16e1d706ee56ca3e132fce29 Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Fri, 21 Jun 2019 23:05:40 -0700 Subject: [PATCH 311/756] Fix environment spelling --- test/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/README.md b/test/README.md index 0682f5d9835..19cc2a1a700 100755 --- a/test/README.md +++ b/test/README.md @@ -166,7 +166,7 @@ failing tests: #define TEST_STRUCTS 2 // 0000 0010 #define TEST_CONTAINERS 4 // 0000 0100 #define TEST_EXCEPTIONS 8 // 0000 1000 - #define TEST_UNKNOWN 64 // 0100 0000 (Failed to prepare environemt etc.) + #define TEST_UNKNOWN 64 // 0100 0000 (Failed to prepare environment etc.) #define TEST_TIMEOUT 128 // 1000 0000 #define TEST_NOTUSED 48 // 0011 0000 (reserved bits) From d886ab291dbde2cac695b3586d41f278e4ffadfc Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sun, 23 Jun 2019 08:40:36 -0400 Subject: [PATCH 312/756] Add a PR checklist item for skipping CI [skip ci] --- .github/pull_request_template.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index edd7befe83e..04188b02ddf 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,12 +1,13 @@ - + - [ ] Did you create an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) ticket? (not required for trivial changes) - [ ] Does your pull request title follow the pattern "THRIFT-NNNN: describe my issue"? (not required for trivial changes) -- [ ] Did you squash your changes to a single commit? -- [ ] Did you do your best to avoid breaking changes? If one was needed, did you label the Jira ticket with "Breaking-Change" +- [ ] Did you squash your changes to a single commit? (not required, but preferred) +- [ ] Did you do your best to avoid breaking changes? If one was needed, did you label the Jira ticket with "Breaking-Change"? +- [ ] If your change does not involve any code, add ` [skip ci]` at the end of your pull request to free up build resources. 0.6.0 YesYes 2.48.22.56.0 -YesYesYesYes +YesYesYesYesYes Yes YesYesYes Yes From 62238d1a6c2746d9afa3900bf83d50896e5fed20 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 26 Jun 2019 20:51:26 +0200 Subject: [PATCH 314/756] THRIFT-4886 More detailed error information for WinHTTP transport Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.WinHTTP.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index 8d677dd3e01..854d7c08016 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -739,7 +739,7 @@ function WinHttpSysErrorMessage( const error : Cardinal): string; nil); SetString( result, pBuffer, nChars); finally - LocalFree( Cardinal( pBuffer)); + LocalFree( NativeUInt( pBuffer)); end; end; From c5068e297ccb32d3776673c752977714baf45391 Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Wed, 26 Jun 2019 22:11:01 -0700 Subject: [PATCH 315/756] Fix some typos in ThriftTest.thrift [ci skip] --- test/ThriftTest.thrift | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift index 99a15ff99f5..cf28b2adf13 100644 --- a/test/ThriftTest.thrift +++ b/test/ThriftTest.thrift @@ -212,7 +212,7 @@ service ThriftTest Xtruct2 testNest(1: Xtruct2 thing), /** - * Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs + * Prints 'testMap("{%s")' where thing has been formatted into a string of 'key => value' pairs * separated by commas and new lines * @param map thing - the map to print * @return map - returns the map 'thing' @@ -220,7 +220,7 @@ service ThriftTest map testMap(1: map thing), /** - * Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs + * Prints 'testStringMap("{%s}")' where thing has been formatted into a string of 'key => value' pairs * separated by commas and new lines * @param map thing - the map to print * @return map - returns the map 'thing' @@ -228,7 +228,7 @@ service ThriftTest map testStringMap(1: map thing), /** - * Prints 'testSet("{%s}")' where thing has been formatted into a string of values + * Prints 'testSet("{%s}")' where thing has been formatted into a string of values * separated by commas and new lines * @param set thing - the set to print * @return set - returns the set 'thing' @@ -236,7 +236,7 @@ service ThriftTest set testSet(1: set thing), /** - * Prints 'testList("{%s}")' where thing has been formatted into a string of values + * Prints 'testList("{%s}")' where thing has been formatted into a string of values * separated by commas and new lines * @param list thing - the list to print * @return list - returns the list 'thing' @@ -244,7 +244,7 @@ service ThriftTest list testList(1: list thing), /** - * Prints 'testEnum("%d")' where thing has been formatted into it's numeric value + * Prints 'testEnum("%d")' where thing has been formatted into its numeric value * @param Numberz thing - the Numberz to print * @return Numberz - returns the Numberz 'thing' */ @@ -266,9 +266,9 @@ service ThriftTest map> testMapMap(1: i32 hello), /** - * So you think you've got this all worked, out eh? + * So you think you've got this all worked out, eh? * - * Creates a the returned map with these values and prints it out: + * Creates a map with these values and prints it out: * { 1 => { 2 => argument, * 3 => argument, * }, @@ -295,16 +295,16 @@ service ThriftTest * Print 'testException(%s)' with arg as '%s' * @param string arg - a string indication what type of exception to throw * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg - * elsen if arg == "TException" throw TException + * else if arg == "TException" throw TException * else do not throw anything */ void testException(1: string arg) throws(1: Xception err1), /** * Print 'testMultiException(%s, %s)' with arg0 as '%s' and arg1 as '%s' - * @param string arg - a string indication what type of exception to throw + * @param string arg - a string indicating what type of exception to throw * if arg0 == "Xception" throw Xception with errorCode = 1001 and message = "This is an Xception" - * elsen if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and struct_thing.string_thing = "This is an Xception2" + * else if arg0 == "Xception2" throw Xception2 with errorCode = 2002 and struct_thing.string_thing = "This is an Xception2" * else do not throw anything * @return Xtruct - an Xtruct with string_thing = arg1 */ From bd1a273ab7979824952bab906b8e260f81b2bd15 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 26 Jun 2019 22:52:44 +0200 Subject: [PATCH 316/756] THRIFT-4898 Pipe write operations across a network are limited to 65,535 bytes per write. Client: netstd Patch: Jens Geyer This closes #1823 --- lib/delphi/test/TestClient.pas | 10 +- lib/delphi/test/TestServer.pas | 2 +- .../Transport/Client/TNamedPipeTransport.cs | 35 ++++-- .../Server/TNamedPipeServerTransport.cs | 28 +++-- test/netstd/Client/TestClient.cs | 112 +++++++++++------- test/netstd/Server/TestServer.cs | 3 +- 6 files changed, 119 insertions(+), 71 deletions(-) diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas index c2660a26dc2..e59c327208b 100644 --- a/lib/delphi/test/TestClient.pas +++ b/lib/delphi/test/TestClient.pas @@ -92,7 +92,8 @@ TClientThread = class( TThread ) Empty, // Edge case: the zero-length empty binary Normal, // Fairly small array of usual size (256 bytes) ByteArrayTest, // THRIFT-4454 Large writes/reads may cause range check errors in debug mode - PipeWriteLimit // THRIFT-4372 Pipe write operations across a network are limited to 65,535 bytes per write. + PipeWriteLimit, // THRIFT-4372 Pipe write operations across a network are limited to 65,535 bytes per write. + TwentyMB // that's quite a bit of data ); private @@ -537,12 +538,12 @@ procedure TClientThread.ClientTest; // random binary small for testsize := Low(TTestSize) to High(TTestSize) do begin binOut := PrepareBinaryData( TRUE, testsize); - Console.WriteLine('testBinary('+BytesToHex(binOut)+')'); + Console.WriteLine('testBinary('+IntToStr(Length(binOut))+' bytes)'); try binIn := client.testBinary(binOut); - Expect( Length(binOut) = Length(binIn), 'testBinary(): length '+IntToStr(Length(binOut))+' = '+IntToStr(Length(binIn))); + Expect( Length(binOut) = Length(binIn), 'testBinary('+IntToStr(Length(binOut))+' bytes): '+IntToStr(Length(binIn))+' bytes received'); i32 := Min( Length(binOut), Length(binIn)); - Expect( CompareMem( binOut, binIn, i32), 'testBinary('+BytesToHex(binOut)+') = '+BytesToHex(binIn)); + Expect( CompareMem( binOut, binIn, i32), 'testBinary('+IntToStr(Length(binOut))+' bytes): validating received data'); except on e:TApplicationException do Console.WriteLine('testBinary(): '+e.Message); on e:Exception do Expect( FALSE, 'testBinary(): Unexpected exception "'+e.ClassName+'": '+e.Message); @@ -1023,6 +1024,7 @@ function TClientThread.PrepareBinaryData( aRandomDist : Boolean; aSize : TTestSi Normal : SetLength( result, $100); ByteArrayTest : SetLength( result, SizeOf(TByteArray) + 128); PipeWriteLimit : SetLength( result, 65535 + 128); + TwentyMB : SetLength( result, 20 * 1024 * 1024); else raise EArgumentException.Create('aSize'); end; diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas index 4cb00907362..2a80d52a737 100644 --- a/lib/delphi/test/TestServer.pas +++ b/lib/delphi/test/TestServer.pas @@ -144,7 +144,7 @@ function TTestServer.TTestHandlerImpl.testDouble( const thing: Double): Double; function TTestServer.TTestHandlerImpl.testBinary(const thing: TBytes): TBytes; begin - Console.WriteLine('testBinary("' + BytesToHex( thing ) + '")'); + Console.WriteLine('testBinary('+IntToStr(Length(thing)) + ' bytes)'); Result := thing; end; diff --git a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs index 2f96a6a484b..7dfe0131ed0 100644 --- a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. +using System; using System.IO.Pipes; using System.Threading; using System.Threading.Tasks; @@ -24,7 +25,7 @@ namespace Thrift.Transport.Client // ReSharper disable once InconsistentNaming public class TNamedPipeTransport : TTransport { - private NamedPipeClientStream _client; + private NamedPipeClientStream PipeStream; private int ConnectTimeout; public TNamedPipeTransport(string pipe, int timeout = Timeout.Infinite) @@ -37,10 +38,10 @@ public TNamedPipeTransport(string server, string pipe, int timeout = Timeout.Inf var serverName = string.IsNullOrWhiteSpace(server) ? server : "."; ConnectTimeout = (timeout > 0) ? timeout : Timeout.Infinite; - _client = new NamedPipeClientStream(serverName, pipe, PipeDirection.InOut, PipeOptions.None); + PipeStream = new NamedPipeClientStream(serverName, pipe, PipeDirection.InOut, PipeOptions.None); } - public override bool IsOpen => _client != null && _client.IsConnected; + public override bool IsOpen => PipeStream != null && PipeStream.IsConnected; public override async Task OpenAsync(CancellationToken cancellationToken) { @@ -49,36 +50,46 @@ public override async Task OpenAsync(CancellationToken cancellationToken) throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen); } - await _client.ConnectAsync( ConnectTimeout, cancellationToken); + await PipeStream.ConnectAsync( ConnectTimeout, cancellationToken); } public override void Close() { - if (_client != null) + if (PipeStream != null) { - _client.Dispose(); - _client = null; + PipeStream.Dispose(); + PipeStream = null; } } public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { - if (_client == null) + if (PipeStream == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - return await _client.ReadAsync(buffer, offset, length, cancellationToken); + return await PipeStream.ReadAsync(buffer, offset, length, cancellationToken); } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { - if (_client == null) + if (PipeStream == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - await _client.WriteAsync(buffer, offset, length, cancellationToken); + // if necessary, send the data in chunks + // there's a system limit around 0x10000 bytes that we hit otherwise + // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section." + var nBytes = Math.Min(15 * 4096, length); // 16 would exceed the limit + while (nBytes > 0) + { + await PipeStream.WriteAsync(buffer, offset, nBytes, cancellationToken); + offset += nBytes; + length -= nBytes; + nBytes = Math.Min(nBytes, length); + } } public override async Task FlushAsync(CancellationToken cancellationToken) @@ -91,7 +102,7 @@ public override async Task FlushAsync(CancellationToken cancellationToken) protected override void Dispose(bool disposing) { - _client.Dispose(); + PipeStream.Dispose(); } } } diff --git a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs index 31a052aa24e..77b82514316 100644 --- a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs @@ -239,14 +239,14 @@ protected override async ValueTask AcceptImplementationAsync(Cancell private class ServerTransport : TTransport { - private readonly NamedPipeServerStream _stream; + private readonly NamedPipeServerStream PipeStream; public ServerTransport(NamedPipeServerStream stream) { - _stream = stream; + PipeStream = stream; } - public override bool IsOpen => _stream != null && _stream.IsConnected; + public override bool IsOpen => PipeStream != null && PipeStream.IsConnected; public override async Task OpenAsync(CancellationToken cancellationToken) { @@ -258,27 +258,37 @@ public override async Task OpenAsync(CancellationToken cancellationToken) public override void Close() { - _stream?.Dispose(); + PipeStream?.Dispose(); } public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { - if (_stream == null) + if (PipeStream == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - return await _stream.ReadAsync(buffer, offset, length, cancellationToken); + return await PipeStream.ReadAsync(buffer, offset, length, cancellationToken); } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { - if (_stream == null) + if (PipeStream == null) { throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - await _stream.WriteAsync(buffer, offset, length, cancellationToken); + // if necessary, send the data in chunks + // there's a system limit around 0x10000 bytes that we hit otherwise + // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section." + var nBytes = Math.Min(15 * 4096, length); // 16 would exceed the limit + while (nBytes > 0) + { + await PipeStream.WriteAsync(buffer, offset, nBytes, cancellationToken); + offset += nBytes; + length -= nBytes; + nBytes = Math.Min(nBytes, length); + } } public override async Task FlushAsync(CancellationToken cancellationToken) @@ -291,7 +301,7 @@ public override async Task FlushAsync(CancellationToken cancellationToken) protected override void Dispose(bool disposing) { - _stream?.Dispose(); + PipeStream?.Dispose(); } } } diff --git a/test/netstd/Client/TestClient.cs b/test/netstd/Client/TestClient.cs index 6be10234e87..0f58f95ed8e 100644 --- a/test/netstd/Client/TestClient.cs +++ b/test/netstd/Client/TestClient.cs @@ -73,7 +73,7 @@ private class TestParams public ProtocolChoice protocol = ProtocolChoice.Binary; public TransportChoice transport = TransportChoice.Socket; - internal void Parse( List args) + internal void Parse(List args) { for (var i = 0; i < args.Count; ++i) { @@ -220,18 +220,18 @@ private static X509Certificate2 GetClientCert() { throw new FileNotFoundException($"Cannot find file: {clientCertName}"); } - + var cert = new X509Certificate2(existingPath, "thrift"); return cert; } - + public TTransport CreateTransport() { // endpoint transport TTransport trans = null; - switch(transport) + switch (transport) { case TransportChoice.Http: Debug.Assert(url != null); @@ -249,8 +249,8 @@ public TTransport CreateTransport() { throw new InvalidOperationException("Certificate doesn't contain private key"); } - - trans = new TTlsSocketTransport(host, port, 0, cert, + + trans = new TTlsSocketTransport(host, port, 0, cert, (sender, certificate, chain, errors) => true, null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); break; @@ -263,7 +263,7 @@ public TTransport CreateTransport() // layered transport - switch(layered) + switch (layered) { case LayeredChoice.Buffered: trans = new TBufferedTransport(trans); @@ -436,15 +436,46 @@ public static string BytesToHex(byte[] data) return BitConverter.ToString(data).Replace("-", string.Empty); } - public static byte[] PrepareTestData(bool randomDist) + + public enum BinaryTestSize + { + Empty, // Edge case: the zero-length empty binary + Normal, // Fairly small array of usual size (256 bytes) + Large, // Large writes/reads may cause range check errors + PipeWriteLimit, // Windows Limit: Pipe write operations across a network are limited to 65,535 bytes per write. + TwentyMB // that's quite a bit of data + }; + + public static byte[] PrepareTestData(bool randomDist, BinaryTestSize testcase) { - var retval = new byte[0x100]; - var initLen = Math.Min(0x100, retval.Length); + int amount = -1; + switch (testcase) + { + case BinaryTestSize.Empty: + amount = 0; + break; + case BinaryTestSize.Normal: + amount = 0x100; + break; + case BinaryTestSize.Large: + amount = 0x8000 + 128; + break; + case BinaryTestSize.PipeWriteLimit: + amount = 0xFFFF + 128; + break; + case BinaryTestSize.TwentyMB: + amount = 20 * 1024 * 1024; + break; + default: + throw new ArgumentException(nameof(testcase)); + } + + var retval = new byte[amount]; // linear distribution, unless random is requested if (!randomDist) { - for (var i = 0; i < initLen; ++i) + for (var i = 0; i < retval.Length; ++i) { retval[i] = (byte)i; } @@ -452,22 +483,10 @@ public static byte[] PrepareTestData(bool randomDist) } // random distribution - for (var i = 0; i < initLen; ++i) - { - retval[i] = (byte)0; - } var rnd = new Random(); - for (var i = 1; i < initLen; ++i) + for (var i = 1; i < retval.Length; ++i) { - while (true) - { - var nextPos = rnd.Next() % initLen; - if (retval[nextPos] == 0) - { - retval[nextPos] = (byte)i; - break; - } - } + retval[i] = (byte)rnd.Next(0x100); } return retval; } @@ -557,32 +576,39 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) returnCode |= ErrorBaseTypes; } - var binOut = PrepareTestData(true); - Console.Write("testBinary(" + BytesToHex(binOut) + ")"); - try + // testBinary() + foreach(BinaryTestSize binTestCase in Enum.GetValues(typeof(BinaryTestSize))) { - var binIn = await client.testBinaryAsync(binOut, MakeTimeoutToken()); - Console.WriteLine(" = " + BytesToHex(binIn)); - if (binIn.Length != binOut.Length) + var binOut = PrepareTestData(true, binTestCase); + + Console.Write("testBinary({0} bytes)", binOut.Length); + try { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - for (var ofs = 0; ofs < Math.Min(binIn.Length, binOut.Length); ++ofs) - if (binIn[ofs] != binOut[ofs]) + var binIn = await client.testBinaryAsync(binOut, MakeTimeoutToken()); + Console.WriteLine(" = {0} bytes", binIn.Length); + if (binIn.Length != binOut.Length) { Console.WriteLine("*** FAILED ***"); returnCode |= ErrorBaseTypes; } - } - catch (Thrift.TApplicationException ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + for (var ofs = 0; ofs < Math.Min(binIn.Length, binOut.Length); ++ofs) + { + if (binIn[ofs] != binOut[ofs]) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + } + } + } + catch (Thrift.TApplicationException ex) + { + Console.WriteLine("*** FAILED ***"); + returnCode |= ErrorBaseTypes; + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + } } - // binary equals? + // CrazyNesting Console.WriteLine("Test CrazyNesting"); var one = new CrazyNesting(); var two = new CrazyNesting(); diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs index 82b36ebadf7..25c2afc1f6d 100644 --- a/test/netstd/Server/TestServer.cs +++ b/test/netstd/Server/TestServer.cs @@ -246,8 +246,7 @@ public Task testDoubleAsync(double thing, CancellationToken cancellation public Task testBinaryAsync(byte[] thing, CancellationToken cancellationToken) { - var hex = BitConverter.ToString(thing).Replace("-", string.Empty); - logger.Invoke("testBinary({0:X})", hex); + logger.Invoke("testBinary({0} bytes)", thing.Length); return Task.FromResult(thing); } From d9019fc5a4a2cec110a9acd9f36a45ee34e3b7f2 Mon Sep 17 00:00:00 2001 From: John Boiles Date: Fri, 28 Jun 2019 23:07:10 -0700 Subject: [PATCH 317/756] THRIFT-4797: Fix import collisions in Go Client: go This closes #1811. --- .../cpp/src/thrift/generate/t_go_generator.cc | 184 ++++++++++-------- .../test/ConflictNamespaceServiceTest.thrift | 25 +++ lib/go/test/ConflictNamespaceTestA.thrift | 23 +++ lib/go/test/ConflictNamespaceTestB.thrift | 23 +++ lib/go/test/ConflictNamespaceTestC.thrift | 23 +++ lib/go/test/ConflictNamespaceTestD.thrift | 23 +++ .../ConflictNamespaceTestSuperThing.thrift | 29 +++ lib/go/test/Makefile.am | 26 ++- 8 files changed, 271 insertions(+), 85 deletions(-) create mode 100644 lib/go/test/ConflictNamespaceServiceTest.thrift create mode 100644 lib/go/test/ConflictNamespaceTestA.thrift create mode 100644 lib/go/test/ConflictNamespaceTestB.thrift create mode 100644 lib/go/test/ConflictNamespaceTestC.thrift create mode 100644 lib/go/test/ConflictNamespaceTestD.thrift create mode 100644 lib/go/test/ConflictNamespaceTestSuperThing.thrift diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index c8187d8ad37..33b7547b4c5 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -249,6 +250,8 @@ class t_go_generator : public t_generator { std::string go_imports_end(); std::string render_includes(bool consts); std::string render_included_programs(string& unused_protection); + std::string render_program_import(const t_program* program, string& unused_protection); + std::string render_system_packages(std::vector &system_packages); std::string render_import_protection(); std::string render_fastbinary_includes(); std::string declare_argument(t_field* tfield); @@ -298,6 +301,8 @@ class t_go_generator : public t_generator { std::string package_name_; std::string package_dir_; + std::unordered_map package_identifiers_; + std::set package_identifiers_set_; std::string read_method_name_; std::string write_method_name_; @@ -763,33 +768,81 @@ void t_go_generator::init_generator() { f_unused_prot_.close(); } - -string t_go_generator::render_included_programs(string& unused_protection) { +string t_go_generator::render_included_programs(string& unused_prot) { const vector& includes = program_->get_includes(); string result = ""; - - unused_protection = ""; - string local_namespace = program_->get_namespace("go"); for (auto include : includes) { if (!local_namespace.empty() && local_namespace == include->get_namespace("go")) { continue; } - string go_module = get_real_go_module(include); - size_t found = 0; - for (size_t j = 0; j < go_module.size(); j++) { - // Import statement uses slashes ('/') in namespace - if (go_module[j] == '.') { - go_module[j] = '/'; - found = j + 1; - } + result += render_program_import(include, unused_prot); + } + return result; +} + +string t_go_generator::render_program_import(const t_program* program, string& unused_protection) { + string result = ""; + + string go_module = get_real_go_module(program); + string go_path = go_module; + size_t found = 0; + for (size_t j = 0; j < go_module.size(); j++) { + // Import statement uses slashes ('/') in namespace + if (go_module[j] == '.') { + go_path[j] = '/'; + found = j + 1; } + } - result += "\t\"" + gen_package_prefix_ + go_module + "\"\n"; - unused_protection += "var _ = " + go_module.substr(found) + ".GoUnusedProtection__\n"; + auto it = package_identifiers_.find(go_module); + auto last_component = go_module.substr(found); + if (it == package_identifiers_.end()) { + auto value = last_component; + // This final path component has already been used, let's construct a more unique alias + if (package_identifiers_set_.find(value) != package_identifiers_set_.end()) { + // TODO: This would produce more readable code if it appended trailing go_module + // path components to generate a more readable name unique identifier (e.g. use + // packageacommon as the alias for packagea/common instead of common=). But just + // appending an integer is much simpler code + value = tmp(value); + } + package_identifiers_set_.insert(value); + it = package_identifiers_.emplace(go_module, std::move(value)).first; + } + auto const& package_identifier = it->second; + result += "\t"; + // if the package_identifier is different than final path component we need an alias + if (last_component.compare(package_identifier) != 0) { + result += package_identifier + " "; } + string s; + + for (auto const& e : package_identifiers_set_) + { + s += e; + s += ','; + } + + s.pop_back(); + + result += "\"" + gen_package_prefix_ + go_path + "\"\n"; + unused_protection += "var _ = " + package_identifier + ".GoUnusedProtection__\n"; + return result; +} + +string t_go_generator::render_system_packages(std::vector& system_packages) { + string result = ""; + for (vector::iterator iter = system_packages.begin(); iter != system_packages.end(); ++iter) { + string package = *iter; + result += "\t\""+ package +"\"\n"; + + // Reserve these package names in case the collide with imported Thrift packages + package_identifiers_set_.insert(package); + package_identifiers_.emplace(package, package); + } return result; } @@ -801,32 +854,14 @@ string t_go_generator::render_includes(bool consts) { const vector& includes = program_->get_includes(); string result = ""; string unused_prot = ""; - - string local_namespace = program_->get_namespace("go"); - for (auto include : includes) { - if (!local_namespace.empty() && local_namespace == include->get_namespace("go")) { - continue; - } - - string go_module = get_real_go_module(include); - size_t found = 0; - for (size_t j = 0; j < go_module.size(); j++) { - // Import statement uses slashes ('/') in namespace - if (go_module[j] == '.') { - go_module[j] = '/'; - found = j + 1; - } - } - - result += "\t\"" + gen_package_prefix_ + go_module + "\"\n"; - unused_prot += "var _ = " + go_module.substr(found) + ".GoUnusedProtection__\n"; - } + result += go_imports_begin(consts); + result += render_included_programs(unused_prot); if (includes.size() > 0) { result += "\n"; } - return go_imports_begin(consts) + result + go_imports_end() + unused_prot; + return result + go_imports_end() + unused_prot; } string t_go_generator::render_import_protection() { @@ -862,22 +897,18 @@ string t_go_generator::go_package() { * If consts include the additional imports. */ string t_go_generator::go_imports_begin(bool consts) { - string extra; - + std::vector system_packages; + system_packages.push_back("bytes"); + system_packages.push_back("context"); + system_packages.push_back("reflect"); // If not writing constants, and there are enums, need extra imports. if (!consts && get_program()->get_enums().size() > 0) { - extra += - "\t\"database/sql/driver\"\n" - "\t\"errors\"\n"; + system_packages.push_back("database/sql/driver"); + system_packages.push_back("errors"); } - return string( - "import (\n" - "\t\"bytes\"\n" - "\t\"context\"\n" - "\t\"reflect\"\n" - + extra + - "\t\"fmt\"\n" - "\t\"" + gen_thrift_import_ + "\"\n"); + system_packages.push_back("fmt"); + system_packages.push_back(gen_thrift_import_); + return "import(\n" + render_system_packages(system_packages); } /** @@ -2113,35 +2144,27 @@ void t_go_generator::generate_service_remote(t_service* tservice) { + underscore(service_name_) + "-remote.go"; ofstream_with_content_based_conditional_update f_remote; f_remote.open(f_remote_name.c_str()); - string service_module = get_real_go_module(program_); - string::size_type loc; - - while ((loc = service_module.find(".")) != string::npos) { - service_module.replace(loc, 1, 1, '/'); - } - if (!gen_package_prefix_.empty()) { - service_module = gen_package_prefix_ + service_module; - } string unused_protection; - string ctxPackage = "context"; + std::vector system_packages; + system_packages.push_back("context"); + system_packages.push_back("flag"); + system_packages.push_back("fmt"); + system_packages.push_back("math"); + system_packages.push_back("net"); + system_packages.push_back("net/url"); + system_packages.push_back("os"); + system_packages.push_back("strconv"); + system_packages.push_back("strings"); f_remote << go_autogen_comment(); f_remote << indent() << "package main" << endl << endl; f_remote << indent() << "import (" << endl; - f_remote << indent() << " \"" << ctxPackage << "\"" << endl; - f_remote << indent() << " \"flag\"" << endl; - f_remote << indent() << " \"fmt\"" << endl; - f_remote << indent() << " \"math\"" << endl; - f_remote << indent() << " \"net\"" << endl; - f_remote << indent() << " \"net/url\"" << endl; - f_remote << indent() << " \"os\"" << endl; - f_remote << indent() << " \"strconv\"" << endl; - f_remote << indent() << " \"strings\"" << endl; - f_remote << indent() << " \"" + gen_thrift_import_ + "\"" << endl; + f_remote << render_system_packages(system_packages); + f_remote << indent() << "\t\"" + gen_thrift_import_ + "\"" << endl; f_remote << indent() << render_included_programs(unused_protection); - f_remote << indent() << " \"" << service_module << "\"" << endl; + f_remote << render_program_import(program_, unused_protection); f_remote << indent() << ")" << endl; f_remote << indent() << endl; f_remote << indent() << unused_protection; // filled in render_included_programs() @@ -2153,6 +2176,8 @@ void t_go_generator::generate_service_remote(t_service* tservice) { f_remote << indent() << " flag.PrintDefaults()" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"\\nFunctions:\")" << endl; + string package_name_aliased = package_identifiers_[get_real_go_module(program_)]; + for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { f_remote << " fmt.Fprintln(os.Stderr, \" " << (*f_iter)->get_returntype()->get_name() << " " << (*f_iter)->get_name() << "("; @@ -2299,7 +2324,7 @@ void t_go_generator::generate_service_remote(t_service* tservice) { f_remote << indent() << "}" << endl; f_remote << indent() << "iprot := protocolFactory.GetProtocol(trans)" << endl; f_remote << indent() << "oprot := protocolFactory.GetProtocol(trans)" << endl; - f_remote << indent() << "client := " << package_name_ << ".New" << publicize(service_name_) + f_remote << indent() << "client := " << package_name_aliased << ".New" << publicize(service_name_) << "Client(thrift.NewTStandardClient(iprot, oprot))" << endl; f_remote << indent() << "if err := trans.Open(); err != nil {" << endl; f_remote << indent() << " fmt.Fprintln(os.Stderr, \"Error opening socket to \", " @@ -2336,7 +2361,7 @@ void t_go_generator::generate_service_remote(t_service* tservice) { f_remote << indent() << " Usage()" << endl; f_remote << indent() << " return" << endl; f_remote << indent() << "}" << endl; - f_remote << indent() << "argvalue" << i << " := " << package_name_ << "." + f_remote << indent() << "argvalue" << i << " := " << package_name_aliased << "." << publicize(the_type->get_name()) << "(tmp" << i << ")" << endl; } else if (the_type2->is_base_type()) { t_base_type::t_base e = ((t_base_type*)the_type2)->get_base(); @@ -2424,7 +2449,7 @@ void t_go_generator::generate_service_remote(t_service* tservice) { std::string tstruct_name(publicize(the_type->get_name())); std::string tstruct_module( module_name(the_type)); if(tstruct_module.empty()) { - tstruct_module = package_name_; + tstruct_module = package_name_aliased; } f_remote << indent() << arg << " := flag.Arg(" << flagArg << ")" << endl; @@ -2468,7 +2493,7 @@ void t_go_generator::generate_service_remote(t_service* tservice) { f_remote << indent() << factory << " := thrift.NewTJSONProtocolFactory()" << endl; f_remote << indent() << jsProt << " := " << factory << ".GetProtocol(" << mbTrans << ")" << endl; - f_remote << indent() << "containerStruct" << i << " := " << package_name_ << ".New" + f_remote << indent() << "containerStruct" << i << " := " << package_name_aliased << ".New" << argumentsName << "()" << endl; f_remote << indent() << err2 << " := containerStruct" << i << ".ReadField" << (i + 1) << "(" << jsProt << ")" << endl; @@ -2483,9 +2508,9 @@ void t_go_generator::generate_service_remote(t_service* tservice) { } if (the_type->is_typedef()) { - std::string typedef_module( module_name(the_type)); + std::string typedef_module(module_name(the_type)); if(typedef_module.empty()) { - typedef_module = package_name_; + typedef_module = package_name_aliased; } f_remote << indent() << "value" << i << " := " << typedef_module << "." << publicize(the_type->get_name()) << "(argvalue" << i << ")" << endl; @@ -3504,12 +3529,7 @@ string t_go_generator::module_name(t_type* ttype) { program_->get_namespace("go").empty() || program->get_namespace("go") != program_->get_namespace("go")) { string module(get_real_go_module(program)); - // for namespaced includes, only keep part after dot. - size_t dot = module.rfind('.'); - if (dot != string::npos) { - module = module.substr(dot + 1); - } - return module; + return package_identifiers_[module]; } } diff --git a/lib/go/test/ConflictNamespaceServiceTest.thrift b/lib/go/test/ConflictNamespaceServiceTest.thrift new file mode 100644 index 00000000000..aade3d7d6ed --- /dev/null +++ b/lib/go/test/ConflictNamespaceServiceTest.thrift @@ -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. +# +namespace go conflict.context + +include "ConflictNamespaceTestD.thrift" + +service ConflictService { + ConflictNamespaceTestD.ThingD thingFunc() +} diff --git a/lib/go/test/ConflictNamespaceTestA.thrift b/lib/go/test/ConflictNamespaceTestA.thrift new file mode 100644 index 00000000000..2749da90b7e --- /dev/null +++ b/lib/go/test/ConflictNamespaceTestA.thrift @@ -0,0 +1,23 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +namespace go conflicta.common + +struct ThingA { + 1: bool value +} diff --git a/lib/go/test/ConflictNamespaceTestB.thrift b/lib/go/test/ConflictNamespaceTestB.thrift new file mode 100644 index 00000000000..b1940ff9f60 --- /dev/null +++ b/lib/go/test/ConflictNamespaceTestB.thrift @@ -0,0 +1,23 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +namespace go conflictb.common + +struct ThingB { + 1: bool value +} diff --git a/lib/go/test/ConflictNamespaceTestC.thrift b/lib/go/test/ConflictNamespaceTestC.thrift new file mode 100644 index 00000000000..7d5ee258260 --- /dev/null +++ b/lib/go/test/ConflictNamespaceTestC.thrift @@ -0,0 +1,23 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +namespace go common + +struct ThingC { + 1: bool value +} diff --git a/lib/go/test/ConflictNamespaceTestD.thrift b/lib/go/test/ConflictNamespaceTestD.thrift new file mode 100644 index 00000000000..8fe7f5e013d --- /dev/null +++ b/lib/go/test/ConflictNamespaceTestD.thrift @@ -0,0 +1,23 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +namespace go conflictd.context + +struct ThingD { + 1: bool value +} diff --git a/lib/go/test/ConflictNamespaceTestSuperThing.thrift b/lib/go/test/ConflictNamespaceTestSuperThing.thrift new file mode 100644 index 00000000000..2348a621f80 --- /dev/null +++ b/lib/go/test/ConflictNamespaceTestSuperThing.thrift @@ -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. +# +include "ConflictNamespaceTestA.thrift" +include "ConflictNamespaceTestB.thrift" +include "ConflictNamespaceTestC.thrift" +include "ConflictNamespaceTestD.thrift" + +struct SuperThing { + 1: ConflictNamespaceTestA.ThingA thing_a + 2: ConflictNamespaceTestB.ThingB thing_b + 3: ConflictNamespaceTestC.ThingC thing_c + 4: ConflictNamespaceTestD.ThingD thing_d +} diff --git a/lib/go/test/Makefile.am b/lib/go/test/Makefile.am index 78d468129c2..244ddff1fd6 100644 --- a/lib/go/test/Makefile.am +++ b/lib/go/test/Makefile.am @@ -39,7 +39,13 @@ gopath: $(THRIFT) $(THRIFTTEST) \ InitialismsTest.thrift \ DontExportRWTest.thrift \ dontexportrwtest/compile_test.go \ - IgnoreInitialismsTest.thrift + IgnoreInitialismsTest.thrift \ + ConflictNamespaceTestA.thrift \ + ConflictNamespaceTestB.thrift \ + ConflictNamespaceTestC.thrift \ + ConflictNamespaceTestD.thrift \ + ConflictNamespaceTestSuperThing.thrift \ + ConflictNamespaceServiceTest.thrift mkdir -p gopath/src grep -v list.*map.*list.*map $(THRIFTTEST) | grep -v 'set' > ThriftTest.thrift $(THRIFT) $(THRIFTARGS) -r IncludesTest.thrift @@ -59,6 +65,12 @@ gopath: $(THRIFT) $(THRIFTTEST) \ $(THRIFT) $(THRIFTARGS) InitialismsTest.thrift $(THRIFT) $(THRIFTARGS),read_write_private DontExportRWTest.thrift $(THRIFT) $(THRIFTARGS),ignore_initialisms IgnoreInitialismsTest.thrift + $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestA.thrift + $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestB.thrift + $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestC.thrift + $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestD.thrift + $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestSuperThing.thrift + $(THRIFT) $(THRIFTARGS) ConflictNamespaceServiceTest.thrift GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock || true sed -i 's/\"context\"/\"golang.org\/x\/net\/context\"/g' gopath/src/github.com/golang/mock/gomock/controller.go || true GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock @@ -79,7 +91,9 @@ check: gopath initialismstest \ dontexportrwtest \ ignoreinitialismstest \ - unionbinarytest + unionbinarytest \ + conflictnamespacetestsuperthing \ + conflict/context/conflict_service-remote GOPATH=`pwd`/gopath $(GO) test thrift tests dontexportrwtest clean-local: @@ -108,4 +122,10 @@ EXTRA_DIST = \ NamesTest.thrift \ InitialismsTest.thrift \ DontExportRWTest.thrift \ - IgnoreInitialismsTest.thrift + IgnoreInitialismsTest.thrift \ + ConflictNamespaceTestA.thrift \ + ConflictNamespaceTestB.thrift \ + ConflictNamespaceTestC.thrift \ + ConflictNamespaceTestD.thrift \ + ConflictNamespaceTestSuperThing.thrift + ConflictNamespaceServiceTest.thrift From 0124c4d66b4e550c1c56c45e994f842b0638d8a2 Mon Sep 17 00:00:00 2001 From: jose andres Date: Tue, 14 May 2019 15:13:17 +0200 Subject: [PATCH 318/756] minor change upgrade to thrift 0.12.0 [THRIFT-4529] - Rust enum variants are now camel-cased instead of uppercased to conform to Rust naming conventions --- tutorial/rs/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tutorial/rs/README.md b/tutorial/rs/README.md index 384e9f8bb30..a686b9b19f8 100644 --- a/tutorial/rs/README.md +++ b/tutorial/rs/README.md @@ -84,14 +84,14 @@ fn run() -> thrift::Result<()> { // two-way with some return let res = client.calculate( 72, - Work::new(7, 8, Operation::MULTIPLY, None) + Work::new(7, 8, Operation::Multiply, None) )?; println!("multiplied 7 and 8, got {}", res); // two-way and returns a Thrift-defined exception let res = client.calculate( 77, - Work::new(2, 0, Operation::DIVIDE, None) + Work::new(2, 0, Operation::Divide, None) ); match res { Ok(v) => panic!("shouldn't have succeeded with result {}", v), From 5338d99176756eefc21fe5c3f2eed3fab99ef715 Mon Sep 17 00:00:00 2001 From: jose andres Date: Tue, 14 May 2019 15:38:21 +0200 Subject: [PATCH 319/756] bug fixed Use TTcpChannel instead of TTcpTransport --- tutorial/rs/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tutorial/rs/README.md b/tutorial/rs/README.md index a686b9b19f8..8ad39adb759 100644 --- a/tutorial/rs/README.md +++ b/tutorial/rs/README.md @@ -35,12 +35,13 @@ extern crate thrift; extern crate try_from; // generated Rust module -use tutorial; +mod tutorial; use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol}; use thrift::protocol::{TInputProtocol, TOutputProtocol}; use thrift::transport::{TFramedReadTransport, TFramedWriteTransport}; use thrift::transport::{TIoChannel, TTcpChannel}; + use tutorial::{CalculatorSyncClient, TCalculatorSyncClient}; use tutorial::{Operation, Work}; @@ -60,7 +61,7 @@ fn run() -> thrift::Result<()> { // println!("connect to server on 127.0.0.1:9090"); - let mut c = TTcpTransport::new(); + let mut c = TTcpChannel::new(); c.open("127.0.0.1:9090")?; let (i_chan, o_chan) = c.split()?; @@ -72,7 +73,7 @@ fn run() -> thrift::Result<()> { TFramedWriteTransport::new(o_chan) ); - let client = CalculatorSyncClient::new(i_prot, o_prot); + let mut client = CalculatorSyncClient::new(i_prot, o_prot); // // alright! - let's make some calls From c2c1e1d709e65d37359cefeb5dc068913f83021b Mon Sep 17 00:00:00 2001 From: Allen George Date: Mon, 1 Jul 2019 07:46:04 -0400 Subject: [PATCH 320/756] Change docker builds to include specific version of Rust (1.35.0) --- LANGUAGES.md | 2 +- build/docker/README.md | 2 +- build/docker/ubuntu-bionic/Dockerfile | 2 +- build/docker/ubuntu-xenial/Dockerfile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LANGUAGES.md b/LANGUAGES.md index 370dc3c6724..5391fe19f39 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -336,7 +336,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Rust 0.11.0 Yes -1.17.01.30.0 +1.35.01.30.0 YesYes Yes YesYesYes diff --git a/build/docker/README.md b/build/docker/README.md index b65f74be5c5..ce79985a3ac 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -192,6 +192,6 @@ Last updated: October 1, 2017 | python | 2.7.12 | 2.7.15rc1 | | | python3 | 3.5.2 | 3.6.7 | | | ruby | 2.3.1p112 | 2.5.1p57 | | -| rust | 1.30.0 | 1.30.0 | | +| rust | 1.35.0 | 1.35.0 | | | smalltalk | | | Not in CI | | swift | | 4.2.1 | | diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index c8131bbb2a0..b508b1e8deb 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -257,7 +257,7 @@ RUN apt-get install -y --no-install-recommends \ ruby-bundler # Rust dependencies -RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y +RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.35.0 -y # Swift on Linux for cross tests RUN cd / && \ diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index 97aaaea47f5..119d4cdf57d 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -255,7 +255,7 @@ RUN apt-get install -y --no-install-recommends \ ruby-bundler # Rust dependencies -RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain stable -y +RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.35.0 -y # Clean up RUN rm -rf /var/cache/apt/* && \ From a304b7c3a00a3c7a8547d3f66bbe6d128f344415 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 30 Jun 2019 15:32:00 +0200 Subject: [PATCH 321/756] THRIFT-4769 Change NuGet package to use netstd artifact Patch: Jens Geyer This closes #1825 Although netcore is superseded by netstd and thus omitted from the package, it still contains "regular" C# binaries. These are deprecated and will be removed with the next regular release after 0.13 --- ApacheThrift.nuspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ApacheThrift.nuspec b/ApacheThrift.nuspec index 8ed92361fc0..7bbfb0dc951 100644 --- a/ApacheThrift.nuspec +++ b/ApacheThrift.nuspec @@ -17,7 +17,7 @@ 1. Open Thrift.sln in lib\csharp\src and build the release version of the "Thrift" and "Thrift.45" projects. - 2. Open Thrift.sln in lib\netcore and build the release version of + 2. Open Thrift.sln in lib\netstd and build the release version of the "Thrift" project. 3. nuget setApiKey 3. nuget pack ApacheThrift.nuspec -Symbols -SymbolPackageFormat snupkg @@ -37,7 +37,7 @@ Apache Thrift .NET Library Contains runtime libraries from lib/csharp for net35 and net45 frameworks, - and from lib/netcore for netstandard2.0 framework development. + and from lib/netstd for netstandard2.0 framework development. Apache Thrift RPC @@ -45,6 +45,6 @@ - +
\ No newline at end of file From 3711d9081095551c04980d328a2e4729d9730219 Mon Sep 17 00:00:00 2001 From: "James Z.M. Gao" Date: Wed, 26 Jun 2019 09:59:55 +0200 Subject: [PATCH 322/756] THRIFT-4897 generate test resource for thrift-maven-plugin Client: Java Patch: James Z.M. Gao This closes #1822 generate SharedIdl.jar for passing the test case for thrift-maven-plugin use antrun plugin to generate test jar --- contrib/thrift-maven-plugin/pom.xml | 21 +++++++++++++++++++ .../thrift/maven/TestAbstractThriftMojo.java | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/contrib/thrift-maven-plugin/pom.xml b/contrib/thrift-maven-plugin/pom.xml index b65f6aa8618..4179b1d914c 100644 --- a/contrib/thrift-maven-plugin/pom.xml +++ b/contrib/thrift-maven-plugin/pom.xml @@ -33,6 +33,7 @@ org.apache.maven.plugins maven-compiler-plugin + 3.8.1 1.8 1.8 @@ -48,6 +49,25 @@ + + org.apache.maven.plugins + maven-antrun-plugin + 1.8 + + + generate-jar-for-test + generate-test-resources + + + + + + + run + + + +
@@ -88,5 +108,6 @@ ${basedir}/../.. ${thrift.root}/compiler/cpp/thrift ${thrift.root}/test + UTF-8 diff --git a/contrib/thrift-maven-plugin/src/test/java/org/apache/thrift/maven/TestAbstractThriftMojo.java b/contrib/thrift-maven-plugin/src/test/java/org/apache/thrift/maven/TestAbstractThriftMojo.java index c1176712d19..7c90a990e39 100644 --- a/contrib/thrift-maven-plugin/src/test/java/org/apache/thrift/maven/TestAbstractThriftMojo.java +++ b/contrib/thrift-maven-plugin/src/test/java/org/apache/thrift/maven/TestAbstractThriftMojo.java @@ -59,7 +59,7 @@ public void testMakeThriftPathFromJars() throws Throwable { // used by other tests. It's used here to represent a dependency of the project maven is building, // one that is contributing .thrift IDL files as well as any other artifacts. final Iterable classpathElementFiles = Lists.newArrayList( - new File("src/test/resources/dependency-jar-test/SharedIdl.jar") + new File("target/SharedIdl.jar") ); final Set thriftDirectories = mojo.makeThriftPathFromJars(temporaryThriftFileDirectory, classpathElementFiles); @@ -70,7 +70,7 @@ public void testMakeThriftPathFromJars() throws Throwable { // means it points to the directory containing the "idl" hierarchy rather than to the idl directory // itself. final Set expected = Sets.newHashSet( - new File(testRootDir, "src/test/resources/dependency-jar-test/SharedIdl.jar") + new File(testRootDir, "target/SharedIdl.jar") ); assertEquals("makeThriftPathFromJars should return thrift IDL base path from within JAR", expected, thriftDirectories); From a392566e9b31edfb3f3da9bb09dc193215c285c2 Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Mon, 1 Jul 2019 11:07:45 -0700 Subject: [PATCH 323/756] THRIFT-4896 - prevent cpp and c_glib include directories from leaking into other targets (#1821) - enable the automake `nostdinc` option - fix up include paths --- compiler/cpp/Makefile.am | 2 +- compiler/cpp/src/Makefile.am | 2 +- compiler/cpp/test/Makefile.am | 2 +- configure.ac | 2 +- lib/c_glib/Makefile.am | 4 ++-- lib/c_glib/test/Makefile.am | 4 ++-- lib/cpp/Makefile.am | 2 +- lib/cpp/test/Makefile.am | 4 ++-- lib/lua/Makefile.am | 2 +- test/c_glib/Makefile.am | 4 ++-- test/cpp/Makefile.am | 4 ++-- tutorial/c_glib/Makefile.am | 4 ++-- tutorial/cpp/Makefile.am | 2 +- 13 files changed, 19 insertions(+), 19 deletions(-) diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am index 9a3aeda5600..91801c6ab6f 100644 --- a/compiler/cpp/Makefile.am +++ b/compiler/cpp/Makefile.am @@ -21,7 +21,7 @@ # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. -AUTOMAKE_OPTIONS = subdir-objects +AUTOMAKE_OPTIONS = subdir-objects nostdinc SUBDIRS = src . if WITH_TESTS diff --git a/compiler/cpp/src/Makefile.am b/compiler/cpp/src/Makefile.am index b3139e21db6..0297708e1e5 100644 --- a/compiler/cpp/src/Makefile.am +++ b/compiler/cpp/src/Makefile.am @@ -21,7 +21,7 @@ # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. -AUTOMAKE_OPTIONS = subdir-objects +AUTOMAKE_OPTIONS = subdir-objects nostdinc AM_YFLAGS = -d diff --git a/compiler/cpp/test/Makefile.am b/compiler/cpp/test/Makefile.am index 96258342407..801f9d85ef2 100644 --- a/compiler/cpp/test/Makefile.am +++ b/compiler/cpp/test/Makefile.am @@ -21,7 +21,7 @@ # Please see doc/old-thrift-license.txt in the Thrift distribution for # details. -AUTOMAKE_OPTIONS = subdir-objects serial-tests +AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc AM_CPPFLAGS = $(BOOST_CPPFLAGS) -I$(top_srcdir)/compiler/cpp/src AM_LDFLAGS = $(BOOST_LDFLAGS) diff --git a/configure.ac b/configure.ac index 391cdb33566..58f9319314a 100755 --- a/configure.ac +++ b/configure.ac @@ -776,7 +776,7 @@ AC_SUBST(GCOV_LDFLAGS) AC_CONFIG_HEADERS(config.h:config.hin) AC_CONFIG_HEADERS(lib/cpp/src/thrift/config.h:config.hin) AC_CONFIG_HEADERS(lib/c_glib/src/thrift/config.h:config.hin) -# gruard against pre defined config.h +# guard against pre defined config.h AH_TOP([ #ifndef CONFIG_H #define CONFIG_H diff --git a/lib/c_glib/Makefile.am b/lib/c_glib/Makefile.am index 49b5b238cd9..fd7f93d768c 100755 --- a/lib/c_glib/Makefile.am +++ b/lib/c_glib/Makefile.am @@ -16,7 +16,7 @@ # specific language governing permissions and limitations # under the License. # -AUTOMAKE_OPTIONS = serial-tests +AUTOMAKE_OPTIONS = serial-tests nostdinc SUBDIRS = . test pkgconfigdir = $(libdir)/pkgconfig @@ -59,7 +59,7 @@ libthrift_c_glib_la_SOURCES = src/thrift/c_glib/thrift.c \ src/thrift/c_glib/server/thrift_server.c \ src/thrift/c_glib/server/thrift_simple_server.c -libthrift_c_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) +libthrift_c_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) -I$(top_builddir)/lib/c_glib/src/thrift libthrift_c_glib_la_LDFLAGS = $(AM_LDFLAGS) $(GLIB_LIBS) $(GOBJECT_LIBS) $(OPENSSL_LDFLAGS) $(OPENSSL_LIBS) include_thriftdir = $(includedir)/thrift/c_glib diff --git a/lib/c_glib/test/Makefile.am b/lib/c_glib/test/Makefile.am index 5e9d2ea415f..c99e0da8374 100755 --- a/lib/c_glib/test/Makefile.am +++ b/lib/c_glib/test/Makefile.am @@ -16,7 +16,7 @@ # specific language governing permissions and limitations # under the License. # -AUTOMAKE_OPTIONS = subdir-objects serial-tests +AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc SUBDIRS = @@ -36,7 +36,7 @@ BUILT_SOURCES = \ gen-c_glib/t_test_thrift_test.h \ gen-c_glib/t_test_thrift_test_types.h -AM_CPPFLAGS = -I../src -I./gen-c_glib +AM_CPPFLAGS = -I../src -I./gen-c_glib -I$(top_builddir)/lib/c_glib/src/thrift AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) \ @GCOV_CFLAGS@ AM_CXXFLAGS = $(AM_CFLAGS) diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index 114ff176798..9b5fb4c1262 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -17,7 +17,7 @@ # under the License. # -AUTOMAKE_OPTIONS = subdir-objects +AUTOMAKE_OPTIONS = subdir-objects nostdinc moc__%.cpp: %.h $(QT5_MOC) $(QT5_CFLAGS) $< -o $@ diff --git a/lib/cpp/test/Makefile.am b/lib/cpp/test/Makefile.am index 5bb9eb76029..2a0b9e69336 100755 --- a/lib/cpp/test/Makefile.am +++ b/lib/cpp/test/Makefile.am @@ -16,7 +16,7 @@ # specific language governing permissions and limitations # under the License. # -AUTOMAKE_OPTIONS = subdir-objects serial-tests +AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc BUILT_SOURCES = gen-cpp/AnnotationTest_types.h \ gen-cpp/DebugProtoTest_types.h \ @@ -408,7 +408,7 @@ gen-cpp/OneWayService.cpp gen-cpp/OneWayTest_constants.cpp gen-cpp/OneWayTest_ty gen-cpp/ChildService.cpp gen-cpp/ChildService.h gen-cpp/ParentService.cpp gen-cpp/ParentService.h gen-cpp/proc_types.cpp gen-cpp/proc_types.h: processor/proc.thrift $(THRIFT) --gen cpp:templates,cob_style $< -AM_CPPFLAGS = $(BOOST_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I. +AM_CPPFLAGS = $(BOOST_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -I$(top_srcdir)/lib/cpp/src/thrift -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I. AM_LDFLAGS = $(BOOST_LDFLAGS) AM_CXXFLAGS = -Wall -Wextra -pedantic diff --git a/lib/lua/Makefile.am b/lib/lua/Makefile.am index 5b0f17a3573..3b272f56cbe 100644 --- a/lib/lua/Makefile.am +++ b/lib/lua/Makefile.am @@ -17,7 +17,7 @@ # under the License. # -AUTOMAKE_OPTIONS = subdir-objects +AUTOMAKE_OPTIONS = subdir-objects nostdinc SUBDIRS = . diff --git a/test/c_glib/Makefile.am b/test/c_glib/Makefile.am index 01ab2caf094..98a3734985d 100755 --- a/test/c_glib/Makefile.am +++ b/test/c_glib/Makefile.am @@ -16,7 +16,7 @@ # specific language governing permissions and limitations # under the License. # -AUTOMAKE_OPTIONS = subdir-objects serial-tests +AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc noinst_LTLIBRARIES = libtestcglib.la nodist_libtestcglib_la_SOURCES = \ @@ -61,7 +61,7 @@ gen-c_glib/t_test_second_service.c gen-c_glib/t_test_second_service.h gen-c_gl AM_CFLAGS = -g -Wall -Wextra $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) AM_CXXFLAGS = $(AM_CFLAGS) -AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib +AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib -I$(top_builddir)/lib/c_glib/src/thrift AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) @GCOV_LDFLAGS@ clean-local: diff --git a/test/cpp/Makefile.am b/test/cpp/Makefile.am index ebe715eefa0..76ae82bfbf9 100755 --- a/test/cpp/Makefile.am +++ b/test/cpp/Makefile.am @@ -16,7 +16,7 @@ # specific language governing permissions and limitations # under the License. # -AUTOMAKE_OPTIONS = subdir-objects serial-tests +AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc BUILT_SOURCES = gen-cpp/ThriftTest.cpp \ gen-cpp/ThriftTest_types.cpp \ @@ -108,7 +108,7 @@ gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants gen-cpp/StressTest_types.cpp gen-cpp/StressTest_constants.cpp gen-cpp/Service.cpp: $(top_srcdir)/test/StressTest.thrift $(THRIFT) $(THRIFT) --gen cpp $< -AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp +AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp -I. AM_CXXFLAGS = -Wall -Wextra -pedantic -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) $(ZLIB_LIBS) diff --git a/tutorial/c_glib/Makefile.am b/tutorial/c_glib/Makefile.am index 4dbe655ef4c..f37649495f4 100755 --- a/tutorial/c_glib/Makefile.am +++ b/tutorial/c_glib/Makefile.am @@ -16,7 +16,7 @@ # specific language governing permissions and limitations # under the License. # -AUTOMAKE_OPTIONS = subdir-objects serial-tests +AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc BUILT_SOURCES = \ gen-c_glib/calculator.h \ @@ -24,7 +24,7 @@ BUILT_SOURCES = \ gen-c_glib/shared_types.h \ gen-c_glib/tutorial_types.h -AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) @GCOV_CFLAGS@ +AM_CFLAGS = -g -Wall -Wextra -pedantic $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(OPENSSL_INCLUDES) @GCOV_CFLAGS@ -I$(top_builddir)/lib/c_glib/src/thrift AM_CPPFLAGS = -I$(top_srcdir)/lib/c_glib/src -Igen-c_glib AM_LDFLAGS = $(GLIB_LIBS) $(GOBJECT_LIBS) $(OPENSSL_LDFLAGS) $(OPENSSL_LIBS) @GCOV_LDFLAGS@ diff --git a/tutorial/cpp/Makefile.am b/tutorial/cpp/Makefile.am index 49cf3be9758..95497d5f338 100755 --- a/tutorial/cpp/Makefile.am +++ b/tutorial/cpp/Makefile.am @@ -16,7 +16,7 @@ # specific language governing permissions and limitations # under the License. # -AUTOMAKE_OPTIONS = subdir-objects serial-tests +AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc BUILT_SOURCES = gen-cpp/shared_types.cpp \ gen-cpp/tutorial_types.cpp From 35cda2fa85ae9c94fc1296e2abcaa2ef733b7352 Mon Sep 17 00:00:00 2001 From: Phil Price Date: Sun, 23 Jun 2019 11:56:28 -0700 Subject: [PATCH 324/756] Fix typescript generation for multi include cases - Ensure imports are generated for includes in *_types.d.ts files - Ensure generated type names for struct fields and function arguments are prefixed with import name if the type is not defined within the same program. --- .../cpp/src/thrift/generate/t_js_generator.cc | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc index 88758b2a00a..dfc398695f6 100644 --- a/compiler/cpp/src/thrift/generate/t_js_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc @@ -394,6 +394,11 @@ class t_js_generator : public t_oop_generator { */ unordered_map module_name_2_import_path; + /** + * Cache for TypeScript includes to generated import name. + */ + unordered_map include_2_import_name; + /** * The prefix to use when generating the episode file. */ @@ -464,7 +469,7 @@ void t_js_generator::init_generator() { f_types_ << js_includes() << endl << render_includes() << endl; if (gen_ts_) { - f_types_ts_ << autogen_comment() << ts_includes() << endl; + f_types_ts_ << autogen_comment() << ts_includes() << endl << render_ts_includes() << endl; } if (gen_node_) { @@ -567,7 +572,9 @@ string t_js_generator::render_ts_includes() { } const vector& includes = program_->get_includes(); for (auto include : includes) { - result += "import " + make_valid_nodeJs_identifier(include->get_name()) + "_ttypes = require('" + get_import_path(include) + "');\n"; + string include_name = make_valid_nodeJs_identifier(include->get_name()) + "_ttypes"; + include_2_import_name.insert({include, include_name}); + result += "import " + include_name + " = require('" + get_import_path(include) + "');\n"; } if (includes.size() > 0) { result += "\n"; @@ -2719,9 +2726,22 @@ string t_js_generator::ts_get_type(t_type* type) { } } else if (type->is_enum() || type->is_struct() || type->is_xception()) { std::string type_name; + if (type->get_program()) { type_name = js_namespace(type->get_program()); + + // If the type is not defined within the current program, we need to prefix it with the same name as + // the generated "import" statement for the types containing program + if(type->get_program() != program_) { + auto prefix = include_2_import_name.find(type->get_program()); + + if(prefix != include_2_import_name.end()) { + type_name.append(prefix->second); + type_name.append("."); + } + } } + type_name.append(type->get_name()); ts_type = type_name; } else if (type->is_list() || type->is_set()) { From 6c847d2d028c155534aee006a77a5dca783233c4 Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Mon, 1 Jul 2019 17:11:56 -0700 Subject: [PATCH 325/756] THRIFT-4878 - [c_glib] add unix domain socket support to ThriftSocket (#1807) --- .../c_glib/transport/thrift_server_socket.c | 90 +++++++++++++++---- .../c_glib/transport/thrift_server_socket.h | 1 + .../thrift/c_glib/transport/thrift_socket.c | 55 +++++++++++- .../thrift/c_glib/transport/thrift_socket.h | 1 + test/c_glib/src/test_client.c | 43 ++++++--- test/c_glib/src/test_server.c | 33 +++++-- test/tests.json | 3 +- 7 files changed, 187 insertions(+), 39 deletions(-) diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c index 6ea897c9110..1646374b8e4 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -36,6 +37,7 @@ enum _ThriftServerSocketProperties { PROP_0, PROP_THRIFT_SERVER_SOCKET_PORT, + PROP_THRIFT_SERVER_SOCKET_PATH, PROP_THRIFT_SERVER_SOCKET_BACKLOG }; @@ -48,17 +50,12 @@ gboolean thrift_server_socket_listen (ThriftServerTransport *transport, GError **error) { int enabled = 1; /* for setsockopt() */ - struct sockaddr_in pin; ThriftServerSocket *tsocket = THRIFT_SERVER_SOCKET (transport); - /* create a address structure */ - memset (&pin, 0, sizeof(pin)); - pin.sin_family = AF_INET; - pin.sin_addr.s_addr = INADDR_ANY; - pin.sin_port = htons(tsocket->port); + const int socket_domain = tsocket->path ? PF_UNIX : AF_INET; /* create a socket */ - if ((tsocket->sd = socket (AF_INET, SOCK_STREAM, 0)) == -1) + if ((tsocket->sd = socket (socket_domain, SOCK_STREAM, 0)) == -1) { g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, THRIFT_SERVER_SOCKET_ERROR_SOCKET, @@ -76,22 +73,60 @@ thrift_server_socket_listen (ThriftServerTransport *transport, GError **error) } /* bind to the socket */ - if (bind(tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) + if (tsocket->path) { - g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, - THRIFT_SERVER_SOCKET_ERROR_BIND, - "failed to bind to port %d - %s", - tsocket->port, strerror(errno)); - return FALSE; + /* create a socket structure */ + struct sockaddr_un pin; + memset (&pin, 0, sizeof(pin)); + pin.sun_family = AF_UNIX; + memcpy(pin.sun_path, tsocket->path, strlen(tsocket->path) + 1); + + if (bind(tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_BIND, + "failed to bind to path %s", + tsocket->path, strerror(errno)); + return FALSE; + } + } + else + { + /* create a address structure */ + struct sockaddr_in pin; + memset (&pin, 0, sizeof(pin)); + pin.sin_family = AF_INET; + pin.sin_addr.s_addr = INADDR_ANY; + pin.sin_port = htons(tsocket->port); + + if (bind(tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_BIND, + "failed to bind to port %d - %s", + tsocket->port, strerror(errno)); + return FALSE; + } } if (listen(tsocket->sd, tsocket->backlog) == -1) { - g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, - THRIFT_SERVER_SOCKET_ERROR_LISTEN, - "failed to listen to port %d - %s", - tsocket->port, strerror(errno)); - return FALSE; + if (tsocket->path) + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_BIND, + "failed to bind to path %s", + tsocket->path, strerror(errno)); + return FALSE; + } + else + { + g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, + THRIFT_SERVER_SOCKET_ERROR_LISTEN, + "failed to listen to port %d - %s", + tsocket->port, strerror(errno)); + return FALSE; + } } return TRUE; @@ -178,6 +213,9 @@ thrift_server_socket_get_property (GObject *object, guint property_id, case PROP_THRIFT_SERVER_SOCKET_PORT: g_value_set_uint (value, socket->port); break; + case PROP_THRIFT_SERVER_SOCKET_PATH: + g_value_set_string (value, socket->path); + break; case PROP_THRIFT_SERVER_SOCKET_BACKLOG: g_value_set_uint (value, socket->backlog); break; @@ -199,6 +237,12 @@ thrift_server_socket_set_property (GObject *object, guint property_id, case PROP_THRIFT_SERVER_SOCKET_PORT: socket->port = g_value_get_uint (value); break; + case PROP_THRIFT_SERVER_SOCKET_PATH: + if (socket->path) { + g_free(socket->path); + } + socket->path = g_strdup (g_value_get_string (value)); + break; case PROP_THRIFT_SERVER_SOCKET_BACKLOG: socket->backlog = g_value_get_uint (value); break; @@ -232,6 +276,16 @@ thrift_server_socket_class_init (ThriftServerSocketClass *cls) PROP_THRIFT_SERVER_SOCKET_PORT, param_spec); + param_spec = g_param_spec_string ("path", + "path (construct)", + "Set the path to listen to", + NULL, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, + PROP_THRIFT_SERVER_SOCKET_PATH, + param_spec); + param_spec = g_param_spec_uint ("backlog", "backlog (construct)", "Set the accept backlog", diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.h b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.h index fd04954015c..7710d5161f9 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.h +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.h @@ -50,6 +50,7 @@ struct _ThriftServerSocket /* private */ guint port; + gchar *path; gshort backlog; int sd; guint8 *buf; diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c index 560c24e28ab..b7b41391075 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -34,7 +35,8 @@ enum _ThriftSocketProperties { PROP_0, PROP_THRIFT_SOCKET_HOSTNAME, - PROP_THRIFT_SOCKET_PORT + PROP_THRIFT_SOCKET_PORT, + PROP_THRIFT_SOCKET_PATH }; G_DEFINE_TYPE(ThriftSocket, thrift_socket, THRIFT_TYPE_TRANSPORT) @@ -128,6 +130,35 @@ thrift_socket_open (ThriftTransport *transport, GError **error) ThriftSocket *tsocket = THRIFT_SOCKET (transport); g_return_val_if_fail (tsocket->sd == THRIFT_INVALID_SOCKET, FALSE); + + if (tsocket->path) { + /* create a socket structure */ + struct sockaddr_un pin; + memset (&pin, 0, sizeof(pin)); + pin.sun_family = AF_UNIX; + memcpy(pin.sun_path, tsocket->path, strlen(tsocket->path) + 1); + + /* create the socket */ + if ((tsocket->sd = socket (PF_UNIX, SOCK_STREAM, 0)) == -1) + { + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_SOCKET, + "failed to create socket for path %s: - %s", + tsocket->path, + strerror(errno)); + return FALSE; + } + + /* open a connection */ + if (connect (tsocket->sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) + { + thrift_socket_close(tsocket, NULL); + g_set_error (error, THRIFT_TRANSPORT_ERROR, THRIFT_TRANSPORT_ERROR_CONNECT, + "failed to connect to path %s: - %s", + tsocket->path, strerror(errno)); + return FALSE; + } + return TRUE; + } /* lookup the destination host */ #if defined(HAVE_GETHOSTBYNAME_R) @@ -278,6 +309,10 @@ thrift_socket_finalize (GObject *object) g_free (socket->hostname); } socket->hostname = NULL; + if (socket->path != NULL) + { + g_free (socket->path); + } if (socket->sd != THRIFT_INVALID_SOCKET) { @@ -303,6 +338,9 @@ thrift_socket_get_property (GObject *object, guint property_id, case PROP_THRIFT_SOCKET_PORT: g_value_set_uint (value, socket->port); break; + case PROP_THRIFT_SOCKET_PATH: + g_value_set_string (value, socket->path); + break; } } @@ -326,6 +364,12 @@ thrift_socket_set_property (GObject *object, guint property_id, case PROP_THRIFT_SOCKET_PORT: socket->port = g_value_get_uint (value); break; + case PROP_THRIFT_SOCKET_PATH: + if (socket->path) { + g_free(socket->path); + } + socket->path = g_strdup (g_value_get_string (value)); + break; } } @@ -361,6 +405,15 @@ thrift_socket_class_init (ThriftSocketClass *cls) g_object_class_install_property (gobject_class, PROP_THRIFT_SOCKET_PORT, param_spec); + param_spec = g_param_spec_string ("path", + "path (construct)", + "Set the path of the remote host", + NULL, /* default value */ + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_THRIFT_SOCKET_PATH, + param_spec); + gobject_class->finalize = thrift_socket_finalize; ttc->is_open = thrift_socket_is_open; ttc->peek = thrift_socket_peek; diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.h b/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.h index 2f6f67db2f6..c91f52f186b 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.h +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_socket.h @@ -51,6 +51,7 @@ struct _ThriftSocket /* private */ gchar *hostname; guint port; + gchar *path; int sd; }; diff --git a/test/c_glib/src/test_client.c b/test/c_glib/src/test_client.c index ef24ab76c6e..7126a86d8a6 100644 --- a/test/c_glib/src/test_client.c +++ b/test/c_glib/src/test_client.c @@ -113,6 +113,7 @@ main (int argc, char **argv) { static gchar * host = NULL; static gint port = 9090; + static gchar * path = NULL; static gboolean ssl = FALSE; static gchar * transport_option = NULL; static gchar * protocol_option = NULL; @@ -124,6 +125,8 @@ main (int argc, char **argv) "Host to connect (=localhost)", NULL }, { "port", 'p', 0, G_OPTION_ARG_INT, &port, "Port number to connect (=9090)", NULL }, + { "domain-socket", 0, 0, G_OPTION_ARG_STRING, &path, + "Unix socket domain path to connect", NULL }, { "ssl", 's', 0, G_OPTION_ARG_NONE, &ssl, "Enable SSL", NULL }, { "transport", 't', 0, G_OPTION_ARG_STRING, &transport_option, @@ -227,12 +230,20 @@ main (int argc, char **argv) if (!options_valid) return 254; - printf ("Connecting (%s/%s) to: %s/%s:%d\n", - transport_name, - protocol_name, - socket_name, - host, - port); + if (path) { + printf ("Connecting (%s/%s) to: %s/%s\n", + transport_name, + protocol_name, + socket_name, + path); + } else { + printf ("Connecting (%s/%s) to: %s/%s:%d\n", + transport_name, + protocol_name, + socket_name, + host, + port); + } /* Install our SIGPIPE handler, which outputs an error message to standard error before exiting so testers can know what @@ -247,10 +258,16 @@ main (int argc, char **argv) } /* Establish all our connection objects */ - socket = g_object_new (socket_type, - "hostname", host, - "port", port, - NULL); + if (path) { + socket = g_object_new (socket_type, + "path", path, + NULL); + } else { + socket = g_object_new (socket_type, + "hostname", host, + "port", port, + NULL); + } if (ssl && !thrift_ssl_load_cert_from_file(THRIFT_SSL_SOCKET(socket), "../keys/CA.pem")) { fprintf(stderr, "Unable to load validation certificate ../keys/CA.pem - did you run in the test/c_glib directory?\n"); @@ -336,7 +353,11 @@ main (int argc, char **argv) gboolean first; gint32 i, j; - printf ("Test #%d, connect %s:%d\n", test_num + 1, host, port); + if (path) { + printf ("Test #%d, connect %s\n", test_num + 1, path); + } else { + printf ("Test #%d, connect %s:%d\n", test_num + 1, host, port); + } gettimeofday (&time_start, NULL); /* These test routines have been ported from the C++ test diff --git a/test/c_glib/src/test_server.c b/test/c_glib/src/test_server.c index 2d716ec2e6f..0819b8ca54c 100644 --- a/test/c_glib/src/test_server.c +++ b/test/c_glib/src/test_server.c @@ -69,6 +69,7 @@ int main (int argc, char **argv) { static gint port = 9090; + static gchar *path_option = NULL; static gchar *server_type_option = NULL; static gchar *transport_option = NULL; static gchar *protocol_option = NULL; @@ -79,6 +80,8 @@ main (int argc, char **argv) GOptionEntry option_entries[] = { { "port", 0, 0, G_OPTION_ARG_INT, &port, "Port number to connect (=9090)", NULL }, + { "domain-socket", 0, 0, G_OPTION_ARG_STRING, &path_option, + "Unix socket domain path to connect", NULL }, { "server-type", 0, 0, G_OPTION_ARG_STRING, &server_type_option, "Type of server: simple (=simple)", NULL }, { "transport", 0, 0, G_OPTION_ARG_STRING, &transport_option, @@ -218,9 +221,15 @@ main (int argc, char **argv) "handler", handler, NULL); } - server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, - "port", port, - NULL); + if (path_option) { + server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "path", path_option, + NULL); + } else { + server_transport = g_object_new (THRIFT_TYPE_SERVER_SOCKET, + "port", port, + NULL); + } transport_factory = g_object_new (transport_factory_type, NULL); @@ -250,11 +259,19 @@ main (int argc, char **argv) sigint_action.sa_flags = SA_RESETHAND; sigaction (SIGINT, &sigint_action, NULL); - printf ("Starting \"%s\" server (%s/%s) listen on: %d\n", - server_name, - transport_name, - protocol_name, - port); + if (path_option) { + printf ("Starting \"%s\" server (%s/%s) listen on: %s\n", + server_name, + transport_name, + protocol_name, + path_option); + } else { + printf ("Starting \"%s\" server (%s/%s) listen on: %d\n", + server_name, + transport_name, + protocol_name, + port); + } fflush (stdout); /* Serve clients until SIGINT is received (Ctrl-C is pressed) */ diff --git a/test/tests.json b/test/tests.json index 851244ec612..6a416399538 100644 --- a/test/tests.json +++ b/test/tests.json @@ -32,7 +32,8 @@ "framed" ], "sockets": [ - "ip" + "ip", + "domain" ], "protocols": [ "binary", From 9b49c96a6a064c40779966960ad1c98d90d6011c Mon Sep 17 00:00:00 2001 From: Gonzalo Aguilar Delgado Date: Tue, 2 Jul 2019 02:13:09 +0200 Subject: [PATCH 326/756] THRIFT-4842 - Fix memory leak on set property c_glib (#1773) --- .../src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c b/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c index 352e3016c82..5084ead4731 100644 --- a/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c +++ b/lib/c_glib/src/thrift/c_glib/protocol/thrift_multiplexed_protocol.c @@ -76,6 +76,7 @@ thrift_multiplexed_protocol_set_property (GObject *object, switch (property_id) { case PROP_THRIFT_MULTIPLEXED_PROTOCOL_SERVICE_NAME: + g_free(self->service_name); self->service_name = g_value_dup_string (value); break; From 6a61dfabbf6ae2fa9fbbc3996590ebdbe38e569f Mon Sep 17 00:00:00 2001 From: soroshsabz Date: Tue, 2 Jul 2019 04:43:54 +0430 Subject: [PATCH 327/756] THRIFT-4830: Add to_string helper function for cpp generator (#1765) --- .../src/thrift/generate/t_cpp_generator.cc | 44 +++++++++++++++++++ lib/cpp/test/EnumTest.cpp | 22 +++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc index dca3167df2d..d66b6e6e16b 100644 --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc @@ -114,6 +114,8 @@ class t_cpp_generator : public t_oop_generator { void generate_enum(t_enum* tenum) override; void generate_enum_ostream_operator_decl(std::ostream& out, t_enum* tenum); void generate_enum_ostream_operator(std::ostream& out, t_enum* tenum); + void generate_enum_to_string_helper_function_decl(std::ostream& out, t_enum* tenum); + void generate_enum_to_string_helper_function(std::ostream& out, t_enum* tenum); void generate_forward_declaration(t_struct* tstruct) override; void generate_struct(t_struct* tstruct) override { generate_cpp_struct(tstruct, false); } void generate_xception(t_struct* txception) override { generate_cpp_struct(txception, true); } @@ -584,6 +586,9 @@ void t_cpp_generator::generate_enum(t_enum* tenum) { generate_enum_ostream_operator_decl(f_types_, tenum); generate_enum_ostream_operator(f_types_impl_, tenum); + + generate_enum_to_string_helper_function_decl(f_types_, tenum); + generate_enum_to_string_helper_function(f_types_impl_, tenum); } void t_cpp_generator::generate_enum_ostream_operator_decl(std::ostream& out, t_enum* tenum) { @@ -631,6 +636,45 @@ void t_cpp_generator::generate_enum_ostream_operator(std::ostream& out, t_enum* } } +void t_cpp_generator::generate_enum_to_string_helper_function_decl(std::ostream& out, t_enum* tenum) { + out << "std::string to_string(const "; + if (gen_pure_enums_) { + out << tenum->get_name(); + } else { + out << tenum->get_name() << "::type&"; + } + out << " val);" << endl; + out << endl; +} + +void t_cpp_generator::generate_enum_to_string_helper_function(std::ostream& out, t_enum* tenum) { + if (!has_custom_ostream(tenum)) { + out << "std::string to_string(const "; + if (gen_pure_enums_) { + out << tenum->get_name(); + } else { + out << tenum->get_name() << "::type&"; + } + out << " val) " ; + scope_up(out); + + out << indent() << "std::map::const_iterator it = _" + << tenum->get_name() << "_VALUES_TO_NAMES.find(val);" << endl; + out << indent() << "if (it != _" << tenum->get_name() << "_VALUES_TO_NAMES.end()) {" << endl; + indent_up(); + out << indent() << "return std::string(it->second);" << endl; + indent_down(); + out << indent() << "} else {" << endl; + indent_up(); + out << indent() << "return std::to_string(static_cast(val));" << endl; + indent_down(); + out << indent() << "}" << endl; + + scope_down(out); + out << endl; + } +} + /** * Generates a class that holds all the constants. */ diff --git a/lib/cpp/test/EnumTest.cpp b/lib/cpp/test/EnumTest.cpp index 6487906324e..388abb7e9ef 100644 --- a/lib/cpp/test/EnumTest.cpp +++ b/lib/cpp/test/EnumTest.cpp @@ -26,6 +26,13 @@ std::ostream& operator <<(std::ostream& os, const MyEnumWithCustomOstream::type& return os; } +std::string to_string(const MyEnumWithCustomOstream::type& val) +{ + std::ostringstream os; + os << val; + return os.str(); +} + BOOST_AUTO_TEST_SUITE(EnumTest) BOOST_AUTO_TEST_CASE(test_enum_value) { @@ -66,7 +73,6 @@ std::string EnumToString(_T e) return ss.str(); } - BOOST_AUTO_TEST_CASE(test_enum_ostream) { BOOST_CHECK_EQUAL(EnumToString(MyEnum1::ME1_0), "ME1_0"); @@ -75,10 +81,22 @@ BOOST_AUTO_TEST_CASE(test_enum_ostream) BOOST_CHECK_EQUAL(EnumToString(MyEnumWithCustomOstream::CustoM2), "{2:CUSTOM!}"); // some invalid or unknown value - auto uut = (MyEnum5::type)44; + auto uut = static_cast(44); BOOST_CHECK_EQUAL(EnumToString(uut), "44"); } +BOOST_AUTO_TEST_CASE(test_enum_to_string) +{ + BOOST_CHECK_EQUAL(::to_string(MyEnum1::ME1_0), "ME1_0"); + BOOST_CHECK_EQUAL(::to_string(MyEnum5::e2), "e2"); + BOOST_CHECK_EQUAL(::to_string(MyEnum3::ME3_N1), "ME3_N1"); + BOOST_CHECK_EQUAL(::to_string(MyEnumWithCustomOstream::CustoM2), "{2:CUSTOM!}"); + + // some invalid or unknown value + auto uut = static_cast(44); + BOOST_CHECK_EQUAL(::to_string(uut), "44"); +} + BOOST_AUTO_TEST_CASE(test_enum_constant) { MyStruct ms; From 1a2dee60b4384de2f6190caa85cf3e2a497c31b9 Mon Sep 17 00:00:00 2001 From: Shaoyu Zhang Date: Sat, 23 Mar 2019 13:47:15 +0800 Subject: [PATCH 328/756] Use THRIFT_WRITE instead of ::write in TFileTransport.cpp --- lib/cpp/src/thrift/transport/TFileTransport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cpp/src/thrift/transport/TFileTransport.cpp b/lib/cpp/src/thrift/transport/TFileTransport.cpp index 53e5136c053..eaf2bc365fb 100644 --- a/lib/cpp/src/thrift/transport/TFileTransport.cpp +++ b/lib/cpp/src/thrift/transport/TFileTransport.cpp @@ -427,7 +427,7 @@ void TFileTransport::writerThread() { auto* zeros = new uint8_t[padding]; memset(zeros, '\0', padding); boost::scoped_array array(zeros); - if (-1 == ::write(fd_, zeros, padding)) { + if (-1 == ::THRIFT_WRITE(fd_, zeros, padding)) { int errno_copy = THRIFT_ERRNO; GlobalOutput.perror("TFileTransport: writerThread() error while padding zeros ", errno_copy); From 93ff9b00531682ece08a1a43883e55fd2aa83a15 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Fri, 21 Jun 2019 17:50:34 -0400 Subject: [PATCH 329/756] Update language levels, fix erlang and rust in CI - Include rebar3 in docker image so erlang builds in CI - Include the correct path in docker image so rust builds in CI - Updated common lisp (sbcl) to 1.5.3 in docker image - Updated dlang to 2.087.0 in docker image - Updated dart to 2.0.0 in xenial docker image - Updated dart to 2.4.0 in bionic docker image - Updated erlang to 22.0 in docker image - Updated openjdk to 11.0.3 in docker image - Updated node.js to 10.16 in docker image - Updated rust to 1.34.0 in xenial docker image - Updated rust to 1.35.0 in bionic docker image THRIFT-4905: Disable hanging experimental dlang async ssl test --- .gitignore | 3 +- LANGUAGES.md | 22 +- build/docker/README.md | 32 +- build/docker/ubuntu-bionic/Dockerfile | 40 +- build/docker/ubuntu-xenial/Dockerfile | 40 +- lib/d/README.md | 19 +- lib/d/test/Makefile.am | 19 +- lib/d/test/async_test.d | 8 +- lib/d/test/async_test_runner.sh | 7 +- lib/d/test/openssl.test.cnf | 14 - lib/d/test/thrift_test_server.d | 5 +- lib/js/package-lock.json | 861 +++----------------------- lib/rs/Cargo.toml | 6 +- lib/rs/src/errors.rs | 3 - lib/rs/src/protocol/stored.rs | 1 - lib/rs/src/server/mod.rs | 1 - lib/rs/src/server/threaded.rs | 1 - lib/rs/test/Cargo.toml | 4 +- test/features/tls.sh | 7 +- test/rs/Cargo.toml | 8 +- test/tests.json | 12 +- tutorial/rs/Cargo.toml | 6 +- 22 files changed, 178 insertions(+), 941 deletions(-) delete mode 100644 lib/d/test/openssl.test.cnf diff --git a/.gitignore b/.gitignore index 3f584e2d325..54fb986bca9 100644 --- a/.gitignore +++ b/.gitignore @@ -222,7 +222,6 @@ project.lock.json /lib/erl/test/*.beam /lib/erl/test/*.hrl /lib/erl/test/Thrift_omit_without.thrift -/lib/erl/rebar.lock /lib/haxe/test/bin /lib/haxe/test/data.tmp /lib/hs/dist @@ -323,6 +322,8 @@ project.lock.json /test/erl/.generated /test/erl/.rebar /test/erl/ebin +/test/erl/_build/ +/test/erl/rebar.lock /test/go/bin/ /test/go/ThriftTest.thrift /test/go/gopath diff --git a/LANGUAGES.md b/LANGUAGES.md index 5391fe19f39..59d5e53c2e4 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -72,7 +72,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr C (glib) 0.6.0 YesYes -2.48.22.56.0 +2.48.22.56.4 YesYesYesYesYes Yes YesYesYes @@ -105,7 +105,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Common LISP 0.12.0 Yes -SBCL 1.4.x +SBCL 1.4.xSBCL 1.5.3 YesYes Yes YesYesYes @@ -116,7 +116,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Dlang 0.9.0 Yes -2.075.12.083.2 +2.075.12.087.0 YesYesYesYesYes YesYesYes YesYesYes @@ -127,7 +127,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Dart 0.10.0 Yes -1.24.32.x +2.0.02.4.0 Yes YesYes YesYesYesYes @@ -171,7 +171,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Erlang 0.3.0 Yes -18.320.0.4 +18.322.0 YesYesYesYes YesYes YesYesYesYes @@ -182,7 +182,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Go 0.7.0 Yes -1.7.61.11.4 +1.10.81.12.6 YesYesYes YesYesYes YesYesYesYes @@ -215,7 +215,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Java (SE) 0.2.0 YesYes -1.8.0_1511.8.0_191 +1.8.0_15111.0.3 YesYesYesYes YesYesYes YesYesYesYes @@ -259,7 +259,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr node.js 0.6.0 Yes -6.x8.x +6.x10.x YesYesYes YesYesYes YesYesYesYes @@ -303,7 +303,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr PHP 0.2.0 Yes -7.0.227.2.10 +7.0.227.2.19 YesYesYes YesYes YesYesYesYes @@ -314,7 +314,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Python 0.2.0 YesYes -2.7.12, 3.5.22.7.15rc1, 3.6.7 +2.7.12, 3.5.22.7.15, 3.6.8 YesYes YesYesYes YesYesYesYes @@ -336,7 +336,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Rust 0.11.0 Yes -1.35.01.30.0 +1.35.01.35.0 YesYes Yes YesYesYes diff --git a/build/docker/README.md b/build/docker/README.md index ce79985a3ac..7bbf001734f 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -167,31 +167,31 @@ Last updated: October 1, 2017 | Language | ubuntu-xenial | ubuntu-bionic | Notes | | :-------- | :------------ | :------------ | :---- | -| as of | Mar 06, 2018 | Jan 21, 2019 | | +| as of | Mar 06, 2018 | Jul 1, 2019 | | | as3 | | 4.6.0 | | -| C++ gcc | 5.4.0 | 7.3.0 | | +| C++ gcc | 5.4.0 | 7.4.0 | | | C++ clang | 3.8 | 6.0 | | | C# (mono) | 4.2.1.0 | 4.6.2.7 | | -| c_glib | 2.48.2 | 2.56.0 | | -| cl (sbcl) | | 1.4.15 | | -| d | 2.075.1 | 2.083.1 | | -| dart | 1.24.3 | 2.1.0 | | +| c_glib | 2.48.2 | 2.56.4 | | +| cl (sbcl) | | 1.5.3 | | +| d | 2.075.1 | 2.087.0 | | +| dart | 2.0.0 | 2.4.0 | | | delphi | | | Not in CI | -| dotnet | 2.1.503 | 2.2.103 | | -| erlang | 18.3 | 20.2.2 | | -| go | 1.7.6 | 1.11.4 | | +| dotnet | 2.1.503 | 2.2.300 | | +| erlang | 18.3 | 22.0 | | +| go | 1.10.8 | 1.12.6 | | | haskell | 7.10.3 | 8.0.2 | | | haxe | 3.2.1 | 3.4.4 | THRIFT-4352: avoid 3.4.2 | -| java | 1.8.0_191 | 1.8.0_191 | | +| java | 1.8.0_191 | 11.0.3 | | | js | | | Unsure how to look for version info? | -| lua | 5.2.4 | 5.2.4 | Lua 5.3: see THRIFT-4386 | -| nodejs | 6.16.0 | 8.15.0 | | +| lua | | 5.2.4 | Lua 5.3: see THRIFT-4386 | +| nodejs | 6.16.0 | 10.16.0 | | | ocaml | | 4.05.0 | THRIFT-4517: ocaml 4.02.3 on xenial appears broken | | perl | 5.22.1 | 5.26.1 | | -| php | 7.0.32 | 7.2.10 | | -| python | 2.7.12 | 2.7.15rc1 | | -| python3 | 3.5.2 | 3.6.7 | | +| php | 7.0.32 | 7.2.19 | | +| python | 2.7.12 | 2.7.15 | | +| python3 | 3.5.2 | 3.6.8 | | | ruby | 2.3.1p112 | 2.5.1p57 | | -| rust | 1.35.0 | 1.35.0 | | +| rust | 1.34.0 | 1.35.0 | | | smalltalk | | | Not in CI | | swift | | 4.2.1 | | diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index b508b1e8deb..2c0609e23cc 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -12,13 +12,7 @@ # # Apache Thrift Docker build environment for Ubuntu Bionic -# Using all stock Ubuntu Bionic packaging except for: -# - cl: want latest -# - d: dmd does not come with Ubuntu -# - dart: does not come with Ubuntu - we use 2.x here -# - dotnet: does not come with Ubuntu -# - go: want latest -# - nodejs: want v8, bionic comes with v6 +# with some updated packages. # FROM buildpack-deps:bionic-scm @@ -38,10 +32,6 @@ RUN apt-get update && \ software-properties-common \ wget -# csharp (mono) - if we ever want a later version -# RUN echo "deb http://download.mono-project.com/repo/debian xenial main" | tee /etc/apt/sources.list.d/mono.list && \ -# apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A6A19B38D3D831EF - # Dart RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ @@ -53,9 +43,13 @@ RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /et chown root:root /etc/apt/trusted.gpg.d/microsoft.gpg && \ chown root:root /etc/apt/sources.list.d/microsoft-prod.list +# erlang +RUN wget -O- https://packages.erlang-solutions.com/ubuntu/erlang_solutions.asc | apt-key add - && \ + echo "deb https://packages.erlang-solutions.com/ubuntu bionic contrib" | tee /etc/apt/sources.list.d/erlang.list + # node.js RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ - echo "deb https://deb.nodesource.com/node_8.x bionic main" | tee /etc/apt/sources.list.d/nodesource.list + echo "deb https://deb.nodesource.com/node_10.x bionic main" | tee /etc/apt/sources.list.d/nodesource.list ### install general dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -99,7 +93,7 @@ RUN apt-get install -y --no-install-recommends \ `# csharp (mono) dependencies` \ mono-devel -ENV SBCL_VERSION 1.4.15 +ENV SBCL_VERSION 1.5.3 RUN \ `# Common Lisp (sbcl) dependencies` \ curl --version && \ @@ -111,8 +105,8 @@ RUN \ cd .. && \ rm -rf sbcl* -ENV D_VERSION 2.083.1 -ENV DMD_DEB dmd_2.083.1-0_amd64.deb +ENV D_VERSION 2.087.0 +ENV DMD_DEB dmd_2.087.0-0_amd64.deb RUN \ `# D dependencies` \ wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \ @@ -128,7 +122,7 @@ RUN \ mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf deimos-openssl-1.1.0h -ENV DART_VERSION 2.1.0-1 +ENV DART_VERSION 2.4.0-1 RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart=$DART_VERSION @@ -140,20 +134,19 @@ RUN apt-get install -y --no-install-recommends \ RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ - erlang-base \ - erlang-eunit \ - erlang-dev \ - erlang-tools \ - rebar + erlang && \ + wget https://s3.amazonaws.com/rebar3/rebar3 -O /usr/bin/rebar3 && \ + chmod 755 /usr/bin/rebar3 && \ + rebar3 --version RUN apt-get install -y --no-install-recommends \ `# GlibC dependencies` \ libglib2.0-dev # golang -ENV GOLANG_VERSION 1.12.1 +ENV GOLANG_VERSION 1.12.6 ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz -ENV GOLANG_DOWNLOAD_SHA256 2a3fdabf665496a0db5f41ec6af7a9b15a49fbe71a85a50ca38b1f13a103aeec +ENV GOLANG_DOWNLOAD_SHA256 dbcf71a3c1ea53b8d54ef1b48c85a39a6c9a935d01fc8291ff2b92028e59913c RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ @@ -258,6 +251,7 @@ RUN apt-get install -y --no-install-recommends \ # Rust dependencies RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.35.0 -y +ENV PATH /root/.cargo/bin:$PATH # Swift on Linux for cross tests RUN cd / && \ diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index 119d4cdf57d..8dc6497dce9 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -14,7 +14,7 @@ # Apache Thrift Docker build environment for Ubuntu Xenial # Using all stock Ubuntu Xenial packaging except for: # - d: does not come with Ubuntu so we're installing 2.075.1 for coverage -# - dart: does not come with Ubuntu so we're installing 1.24.3 for coverage +# - dart: does not come with Ubuntu so we're installing 2.0.0-1 for coverage # - dotnet: does not come with Ubuntu # - go: Xenial comes with 1.6, but we need 1.10 or later # - nodejs: Xenial comes with 4.2.6 which exits LTS April 2018, so we're installing 6.x @@ -35,29 +35,29 @@ RUN apt-get update && \ apt-utils \ curl \ software-properties-common \ - wget + wget && \ # csharp (mono) -# RUN echo "deb http://download.mono-project.com/repo/debian xenial main" | tee /etc/apt/sources.list.d/mono.list && \ -# apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A6A19B38D3D831EF +# echo "deb http://download.mono-project.com/repo/debian xenial main" | tee /etc/apt/sources.list.d/mono.list && \ +# apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A6A19B38D3D831EF && \ # D -RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EBCF975E5BA24D5E && \ + apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EBCF975E5BA24D5E && \ wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list && \ - wget -qO - https://dlang.org/d-keyring.gpg | apt-key add - + wget -qO - https://dlang.org/d-keyring.gpg | apt-key add - && \ # Dart -RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ + curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ - /etc/apt/sources.list.d/dart_stable.list + /etc/apt/sources.list.d/dart_stable.list && \ # dotnet (core) -RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ + curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-xenial-prod xenial main" > \ - /etc/apt/sources.list.d/dotnetdev.list + /etc/apt/sources.list.d/dotnetdev.list && \ # node.js -RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ + curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ echo "deb https://deb.nodesource.com/node_6.x xenial main" | tee /etc/apt/sources.list.d/nodesource.list ### install general dependencies @@ -119,7 +119,7 @@ RUN curl -sSL https://github.com/D-Programming-Deimos/openssl/archive/v1.1.6+1.0 mv openssl-1.1.6-1.0.1g/C/* /usr/include/dmd/druntime/import/C/ && \ rm -rf openssl-1.1.6-1.0.1g -ENV DART_VERSION 1.24.3-1 +ENV DART_VERSION 2.0.0-1 RUN apt-get install -y --no-install-recommends \ `# Dart dependencies` \ dart=$DART_VERSION @@ -151,7 +151,7 @@ RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ ln -s /usr/local/go/bin/go /usr/local/bin && \ rm golang.tar.gz -# due to a bug in cabal in xenial (cabal-install package) we pull in another: +# cabal 1.22 in xenial is too old so we grab a pre-built 1.24 binary RUN apt-get install -y --no-install-recommends \ `# Haskell dependencies` \ ghc && \ @@ -160,7 +160,8 @@ RUN apt-get install -y --no-install-recommends \ tar xzf cabal-install-1.24.0.2-x86_64-unknown-linux.tar.gz && \ find dist-newstyle/ -type f -name cabal -exec mv {} /usr/bin \; && \ rm -rf /tmp/cabal* && \ - cabal --version + cabal --version && \ + cabal update RUN apt-get install -y --no-install-recommends \ `# Haxe dependencies` \ @@ -179,10 +180,11 @@ RUN apt-get install -y --no-install-recommends \ openjdk-8-jdk \ maven -RUN apt-get install -y --no-install-recommends \ -`# Lua dependencies` \ - lua5.2 \ - lua5.2-dev +# disabled: same as ubuntu-bionic jobs +# RUN apt-get install -y --no-install-recommends \ +# `# Lua dependencies` \ +# lua5.2 \ +# lua5.2-dev # https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212 # lua5.3 does not install alternatives so stick with 5.2 here @@ -255,7 +257,7 @@ RUN apt-get install -y --no-install-recommends \ ruby-bundler # Rust dependencies -RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.35.0 -y +RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.34.0 -y # Clean up RUN rm -rf /var/cache/apt/* && \ diff --git a/lib/d/README.md b/lib/d/README.md index 5d37e4fe7b8..9b188abf512 100644 --- a/lib/d/README.md +++ b/lib/d/README.md @@ -42,17 +42,8 @@ directory (PowerShell syntax): dmd -ofunittest -unittest -w $(dir -r -filter '*.d' -name) -If you want to run the test clients/servers in OpenSSL -mode, you have to provide »server-private-key.pem« and -»server-certificate.pem« files in the directory the server -executable resides in, and a »trusted-ca-certificate.pem« -file for the client. The easiest way is to generate a new -self signed certificate using the provided config file -(openssl.test.cnf): - -openssl req -new -x509 -nodes -config openssl.test.cnf \ - -out server-certificate.pem -cat server-certificate.pem > trusted-ca-certificate.pem - -This steps are also performed automatically by the -Autotools build system if the files are not present. +Async and SSL +------------- +Using SSL with async is experimental (always has been) and +the unit test "async_test --ssl" hangs. Use at your own +risk. diff --git a/lib/d/test/Makefile.am b/lib/d/test/Makefile.am index 3b6a6f14a50..5ec8255bb25 100755 --- a/lib/d/test/Makefile.am +++ b/lib/d/test/Makefile.am @@ -19,9 +19,6 @@ AUTOMAKE_OPTIONS = serial-tests -BUILT_SOURCES = trusted-ca-certificate.pem server-certificate.pem - - # Thrift compiler rules debug_proto_gen = $(addprefix gen-d/, DebugProtoTest_types.d) @@ -99,17 +96,6 @@ thrift_test_server: %: %.d thrift_test_common.d test_utils.d $(thrift_test_gen) $(DMD) $(d_test_flags) -of$@ $^ -# Certificate generation targets (for the SSL tests). -# Currently, we just assume that the "openssl" tool is on the path, could be -# replaced by a more elaborate mechanism. - -server-certificate.pem: openssl.test.cnf - openssl req -new -x509 -nodes -config openssl.test.cnf \ - -out server-certificate.pem - -trusted-ca-certificate.pem: server-certificate.pem - cat server-certificate.pem > $@ - check-local: $(targets) clean-local: @@ -118,9 +104,8 @@ clean-local: # Tests ran as part of make check. -async_test_runner.sh: async_test trusted-ca-certificate.pem server-certificate.pem -thrift_test_runner.sh: thrift_test_client thrift_test_server \ - trusted-ca-certificate.pem server-certificate.pem +async_test_runner.sh: async_test +thrift_test_runner.sh: thrift_test_client thrift_test_server TESTS = $(ran_tests) diff --git a/lib/d/test/async_test.d b/lib/d/test/async_test.d index fb765ad6e8e..51529ba867e 100644 --- a/lib/d/test/async_test.d +++ b/lib/d/test/async_test.d @@ -104,18 +104,18 @@ void main(string[] args) { if (ssl) { auto clientSSLContext = new TSSLContext(); with (clientSSLContext) { - ciphers = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"; authenticate = true; - loadTrustedCertificates("./trusted-ca-certificate.pem"); + ciphers = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"; + loadTrustedCertificates("../../../test/keys/CA.pem"); } clientTransportFactory = new TAsyncSSLSocketFactory(clientSSLContext); serverSSLContext = new TSSLContext(); with (serverSSLContext) { serverSide = true; - loadCertificate("./server-certificate.pem"); - loadPrivateKey("./server-private-key.pem"); ciphers = "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"; + loadCertificate("../../../test/keys/server.crt"); + loadPrivateKey("../../../test/keys/server.key"); } } else { clientTransportFactory = new TBufferedTransportFactory; diff --git a/lib/d/test/async_test_runner.sh b/lib/d/test/async_test_runner.sh index 7d507ee929b..d56654f5091 100755 --- a/lib/d/test/async_test_runner.sh +++ b/lib/d/test/async_test_runner.sh @@ -24,5 +24,8 @@ CUR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Runs the async test in both SSL and non-SSL mode. ${CUR}/async_test > /dev/null || exit 1 echo "Non-SSL tests done." -${CUR}/async_test --ssl > /dev/null || exit 1 -echo "SSL tests done." + +# THRIFT-4905: disabled the following test as it deadlocks / hangs +# ${CUR}/async_test --ssl > /dev/null || exit 1 +# echo "SSL tests done." +echo "THRIFT-4905: SSL tests are disabled. Fix them." diff --git a/lib/d/test/openssl.test.cnf b/lib/d/test/openssl.test.cnf deleted file mode 100644 index 2ada30b7c79..00000000000 --- a/lib/d/test/openssl.test.cnf +++ /dev/null @@ -1,14 +0,0 @@ -[ req ] -default_bits = 2048 -default_keyfile = server-private-key.pem -distinguished_name = req_distinguished_name -x509_extensions = v3_ca -prompt = no - -[ req_distinguished_name ] -CN = localhost - -[ v3_ca ] -# Add ::1 to the list of allowed IPs so we can use ::1 to explicitly connect -# to localhost via IPv6. -subjectAltName = IP:::1 diff --git a/lib/d/test/thrift_test_server.d b/lib/d/test/thrift_test_server.d index b582253c77a..ce820d69905 100644 --- a/lib/d/test/thrift_test_server.d +++ b/lib/d/test/thrift_test_server.d @@ -20,7 +20,7 @@ module thrift_test_server; import core.stdc.errno : errno; -import core.stdc.signal : signal, sigfn_t, SIGINT, SIG_DFL, SIG_ERR; +import core.stdc.signal : signal, SIGINT, SIG_DFL, SIG_ERR; import core.thread : dur, Thread; import std.algorithm; import std.exception : enforce; @@ -314,8 +314,7 @@ void main(string[] args) { processor, serverSocket, transportFactory, protocolFactory); // Set up SIGINT signal handling - sigfn_t oldHandler = signal(SIGINT, &handleSignal); - enforce(oldHandler != SIG_ERR, + enforce(signal(SIGINT, &handleSignal) != SIG_ERR, "Could not replace the SIGINT signal handler: errno {0}".format(errno())); // Set up a server cancellation trigger diff --git a/lib/js/package-lock.json b/lib/js/package-lock.json index 9110814c9a6..00bf05c9223 100644 --- a/lib/js/package-lock.json +++ b/lib/js/package-lock.json @@ -58,41 +58,6 @@ "es6-promisify": "^5.0.0" } }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "optional": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -185,16 +150,6 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", @@ -232,12 +187,6 @@ } } }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", @@ -256,33 +205,12 @@ "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", "dev": true }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true, - "optional": true - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true, - "optional": true - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true, - "optional": true - }, "babylon": { "version": "7.0.0-beta.19", "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", @@ -355,16 +283,6 @@ "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", "dev": true }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, "bluebird": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", @@ -628,15 +546,6 @@ "parse-asn1": "^5.0.0" } }, - "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "dev": true, - "requires": { - "pako": "~0.2.0" - } - }, "buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", @@ -716,13 +625,6 @@ "map-obj": "^1.0.0" } }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true, - "optional": true - }, "catharsis": { "version": "0.8.9", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", @@ -731,16 +633,6 @@ "underscore-contrib": "~0.3.0" } }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -796,9 +688,9 @@ }, "dependencies": { "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -811,24 +703,6 @@ } } }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true, - "optional": true - }, "coffeescript": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz", @@ -878,14 +752,11 @@ "source-map": "~0.5.3" } }, - "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true }, "component-emitter": { "version": "1.2.1", @@ -1048,23 +919,6 @@ "array-find-index": "^1.0.1" } }, - "cycle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=", - "dev": true, - "optional": true - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -1149,12 +1003,6 @@ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", "dev": true }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, "deps-sort": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", @@ -1214,25 +1062,19 @@ } }, "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", "dev": true, "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" + "domelementtype": "^1.3.0", + "entities": "^1.1.1" }, "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", - "dev": true - }, "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true } } @@ -1244,9 +1086,9 @@ "dev": true }, "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, "domhandler": { @@ -1268,6 +1110,12 @@ "domelementtype": "1" } }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -1303,17 +1151,6 @@ } } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "optional": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", @@ -1546,33 +1383,6 @@ "yauzl": "2.4.1" } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", - "dev": true, - "optional": true - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true, - "optional": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true, - "optional": true - }, "fd-slicer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", @@ -1683,25 +1493,6 @@ "for-in": "^1.0.1" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "optional": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "optional": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -1711,30 +1502,6 @@ "map-cache": "^0.2.2" } }, - "fs-extra": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", - "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" - }, - "dependencies": { - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.9" - } - } - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1771,16 +1538,6 @@ "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", @@ -1923,40 +1680,26 @@ } }, "grunt-contrib-jshint": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-1.1.0.tgz", - "integrity": "sha1-Np2QmyWTxA6L55lAshNAhQx5Oaw=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-jshint/-/grunt-contrib-jshint-2.1.0.tgz", + "integrity": "sha512-65S2/C/6RfjY/umTxfwXXn+wVvaYmykHkHSsW6Q6rhkbv3oudTEgqnFFZvWzWCoHUb+3GMZLbP3oSrNyvshmIQ==", "dev": true, "requires": { - "chalk": "^1.1.1", + "chalk": "^2.4.2", "hooker": "^0.2.3", - "jshint": "~2.9.4" + "jshint": "~2.10.2" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true } } }, @@ -1980,43 +1723,15 @@ } }, "grunt-contrib-uglify": { - "version": "1.0.2", - "resolved": "http://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-1.0.2.tgz", - "integrity": "sha1-rmekb5FT7dTLEYE6Vetpxw19svs=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-4.0.1.tgz", + "integrity": "sha512-dwf8/+4uW1+7pH72WButOEnzErPGmtUvc8p08B0eQS/6ON0WdeQu0+WFeafaPTbbY1GqtS25lsHWaDeiTQNWPg==", "dev": true, "requires": { - "chalk": "^1.0.0", - "lodash": "^4.0.1", - "maxmin": "^1.1.0", - "uglify-js": "~2.6.2", + "chalk": "^2.4.1", + "maxmin": "^2.1.0", + "uglify-js": "^3.5.0", "uri-path": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } } }, "grunt-jsdoc": { @@ -2091,31 +1806,12 @@ } }, "gzip-size": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz", - "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=", - "dev": true, - "requires": { - "browserify-zlib": "^0.1.4", - "concat-stream": "^1.4.1" - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true, - "optional": true - }, - "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", + "integrity": "sha1-VGGI6b3DN/Zzdy+BZgRks4nc5SA=", "dev": true, - "optional": true, "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" + "duplexer": "^0.1.1" } }, "has": { @@ -2194,17 +1890,6 @@ "minimalistic-assert": "^1.0.1" } }, - "hasha": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", - "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", - "dev": true, - "optional": true, - "requires": { - "is-stream": "^1.0.1", - "pinkie-promise": "^2.0.0" - } - }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -2256,18 +1941,6 @@ "readable-stream": "1.1" } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -2538,20 +2211,6 @@ "is-unc-path": "^1.0.0" } }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true, - "optional": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true, - "optional": true - }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -2591,12 +2250,6 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, "js-yaml": { "version": "3.5.5", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz", @@ -2615,12 +2268,6 @@ "xmlcreate": "^1.0.1" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, "jsdoc": { "version": "3.5.5", "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", @@ -2641,22 +2288,19 @@ } }, "jshint": { - "version": "2.9.6", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.6.tgz", - "integrity": "sha512-KO9SIAKTlJQOM4lE64GQUtGBRpTOuvbrRrSZw3AhUxMNG266nX9hK2cKA4SBhXOj0irJGyNyGSLT62HGOVDEOA==", + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.10.2.tgz", + "integrity": "sha512-e7KZgCSXMJxznE/4WULzybCMNXNAd/bf5TSrvVEq78Q/K8ZwFpmBqQeDtNiHc3l49nV4E/+YeHU/JZjSUIrLAA==", "dev": true, "requires": { "cli": "~1.0.0", "console-browserify": "1.1.x", "exit": "0.1.x", "htmlparser2": "3.8.x", - "lodash": "~4.17.10", + "lodash": "~4.17.11", "minimatch": "~3.0.2", - "phantom": "~4.0.1", - "phantomjs-prebuilt": "~2.1.7", "shelljs": "0.3.x", - "strip-json-comments": "1.0.x", - "unicode-5.2.0": "^0.7.5" + "strip-json-comments": "1.0.x" }, "dependencies": { "strip-json-comments": { @@ -2733,20 +2377,6 @@ "node-int64": "0.4.0" } }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true, - "optional": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true, - "optional": true - }, "json-stable-stringify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", @@ -2756,23 +2386,6 @@ "jsonify": "~0.0.0" } }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true, - "optional": true - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", @@ -2785,26 +2398,6 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "kew": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", - "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", - "dev": true, - "optional": true - }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", @@ -2838,12 +2431,6 @@ } } }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, "liftoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", @@ -2899,12 +2486,6 @@ "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", "dev": true }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -2951,15 +2532,15 @@ "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==" }, "maxmin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz", - "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", + "integrity": "sha1-TTsiCQPZXu5+t6x/qGTnLcCaMWY=", "dev": true, "requires": { "chalk": "^1.0.0", "figures": "^1.0.1", - "gzip-size": "^1.0.0", - "pretty-bytes": "^1.0.0" + "gzip-size": "^3.0.0", + "pretty-bytes": "^3.0.0" }, "dependencies": { "ansi-styles": { @@ -2970,7 +2551,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -3063,21 +2644,6 @@ "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", "dev": true }, - "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", - "dev": true - }, - "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", - "dev": true, - "requires": { - "mime-db": "~1.37.0" - } - }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -3254,13 +2820,6 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "optional": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3387,12 +2946,6 @@ "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", "dev": true }, - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", - "dev": true - }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", @@ -3531,43 +3084,6 @@ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", "dev": true }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true, - "optional": true - }, - "phantom": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/phantom/-/phantom-4.0.12.tgz", - "integrity": "sha512-Tz82XhtPmwCk1FFPmecy7yRGZG2btpzY2KI9fcoPT7zT9det0CcMyfBFPp1S8DqzsnQnm8ZYEfdy528mwVtksA==", - "dev": true, - "optional": true, - "requires": { - "phantomjs-prebuilt": "^2.1.16", - "split": "^1.0.1", - "winston": "^2.4.0" - } - }, - "phantomjs-prebuilt": { - "version": "2.1.16", - "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.16.tgz", - "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", - "dev": true, - "optional": true, - "requires": { - "es6-promise": "^4.0.3", - "extract-zip": "^1.6.5", - "fs-extra": "^1.0.0", - "hasha": "^2.2.0", - "kew": "^0.7.0", - "progress": "^1.1.8", - "request": "^2.81.0", - "request-progress": "^2.0.1", - "which": "^1.2.10" - } - }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -3596,13 +3112,12 @@ "dev": true }, "pretty-bytes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", - "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz", + "integrity": "sha1-J9AAjXeAY6C0gRuzXHnxvV1fvM8=", "dev": true, "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.1.0" + "number-is-nan": "^1.0.0" } }, "process": { @@ -3617,26 +3132,12 @@ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, - "progress": { - "version": "1.1.8", - "resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true, - "optional": true - }, "proxy-from-env": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=", "dev": true }, - "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", - "dev": true, - "optional": true - }, "public-encrypt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", @@ -3696,13 +3197,6 @@ } } }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true, - "optional": true - }, "querystring": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", @@ -3792,7 +3286,7 @@ }, "readable-stream": { "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { @@ -3860,45 +3354,6 @@ "is-finite": "^1.0.0" } }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "request-progress": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", - "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", - "dev": true, - "optional": true, - "requires": { - "throttleit": "^1.0.0" - } - }, "requizzle": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", @@ -3942,15 +3397,6 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "^0.1.1" - } - }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -4249,16 +3695,6 @@ "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", "dev": true }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "optional": true, - "requires": { - "through": "2" - } - }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -4274,31 +3710,6 @@ "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=", "dev": true }, - "sshpk": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", - "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", - "dev": true, - "optional": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "optional": true - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -4545,13 +3956,6 @@ "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=" }, - "throttleit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", - "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", - "dev": true, - "optional": true - }, "through": { "version": "2.3.8", "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -4651,17 +4055,6 @@ "repeat-string": "^1.6.1" } }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "optional": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } - }, "trim-newlines": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", @@ -4674,22 +4067,6 @@ "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", "dev": true }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -4697,31 +4074,23 @@ "dev": true }, "uglify-js": { - "version": "2.6.4", - "resolved": "http://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz", - "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", + "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", "dev": true, "requires": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" + "commander": "~2.20.0", + "source-map": "~0.6.1" }, "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "http://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true - }, "umd": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", @@ -4776,12 +4145,6 @@ "util-deprecate": "^1.0.2" } }, - "unicode-5.2.0": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/unicode-5.2.0/-/unicode-5.2.0-0.7.5.tgz", - "integrity": "sha512-KVGLW1Bri30x00yv4HNM8kBxoqFXr0Sbo55735nvrlsx4PYBZol3UtoWgO492fSwmsetzPEZzy73rbU8OGXJcA==", - "dev": true - }, "union-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", @@ -4908,13 +4271,6 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true, - "optional": true - }, "v8flags": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", @@ -4934,18 +4290,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "vm-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", @@ -4961,49 +4305,6 @@ "isexe": "^2.0.0" } }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "winston": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.4.tgz", - "integrity": "sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q==", - "dev": true, - "optional": true, - "requires": { - "async": "~1.0.0", - "colors": "1.0.x", - "cycle": "1.0.x", - "eyes": "0.1.x", - "isstream": "0.1.x", - "stack-trace": "0.0.x" - }, - "dependencies": { - "async": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/async/-/async-1.0.0.tgz", - "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=", - "dev": true, - "optional": true - }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", - "dev": true, - "optional": true - } - } - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -5030,26 +4331,6 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, - "yargs": { - "version": "3.10.0", - "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - } - } - }, "yauzl": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml index bad2a3872f8..69da0f39957 100644 --- a/lib/rs/Cargo.toml +++ b/lib/rs/Cargo.toml @@ -11,8 +11,8 @@ exclude = ["Makefile*", "test/**", "*.iml"] keywords = ["thrift"] [dependencies] -ordered-float = "0.5" -byteorder = "1" -integer-encoding = "1" +ordered-float = "1.0" +byteorder = "1.3" +integer-encoding = "1.0" log = "0.4" threadpool = "1.7" diff --git a/lib/rs/src/errors.rs b/lib/rs/src/errors.rs index 6fb1aee565f..13be1ee06d3 100644 --- a/lib/rs/src/errors.rs +++ b/lib/rs/src/errors.rs @@ -58,7 +58,6 @@ use protocol::{TFieldIdentifier, TInputProtocol, TOutputProtocol, TStructIdentif /// Create a `TransportError`. /// /// ``` -/// use thrift; /// use thrift::{TransportError, TransportErrorKind}; /// /// // explicit @@ -104,7 +103,6 @@ use protocol::{TFieldIdentifier, TInputProtocol, TOutputProtocol, TStructIdentif /// Create an error from a string. /// /// ``` -/// use thrift; /// use thrift::{ApplicationError, ApplicationErrorKind}; /// /// // we just use `From::from` to convert a `String` into a `thrift::Error` @@ -134,7 +132,6 @@ use protocol::{TFieldIdentifier, TInputProtocol, TOutputProtocol, TStructIdentif /// ``` /// /// ``` -/// use std::convert::From; /// use std::error::Error; /// use std::fmt; /// use std::fmt::{Display, Formatter}; diff --git a/lib/rs/src/protocol/stored.rs b/lib/rs/src/protocol/stored.rs index 8c559788777..4fe465fc6fa 100644 --- a/lib/rs/src/protocol/stored.rs +++ b/lib/rs/src/protocol/stored.rs @@ -42,7 +42,6 @@ use ProtocolErrorKind; /// Create and use a `TStoredInputProtocol`. /// /// ```no_run -/// use thrift; /// use thrift::protocol::{TInputProtocol, TMessageIdentifier, TMessageType, TOutputProtocol}; /// use thrift::protocol::{TBinaryInputProtocol, TBinaryOutputProtocol, TStoredInputProtocol}; /// use thrift::server::TProcessor; diff --git a/lib/rs/src/server/mod.rs b/lib/rs/src/server/mod.rs index 70b381ac928..3d42891044c 100644 --- a/lib/rs/src/server/mod.rs +++ b/lib/rs/src/server/mod.rs @@ -39,7 +39,6 @@ pub use self::threaded::TServer; /// a Thrift service `SimpleService`. /// /// ```no_run -/// use thrift; /// use thrift::protocol::{TInputProtocol, TOutputProtocol}; /// use thrift::server::TProcessor; /// diff --git a/lib/rs/src/server/threaded.rs b/lib/rs/src/server/threaded.rs index 8139a4e2789..e15a25ab668 100644 --- a/lib/rs/src/server/threaded.rs +++ b/lib/rs/src/server/threaded.rs @@ -43,7 +43,6 @@ use super::TProcessor; /// service code. /// /// ```no_run -/// use thrift; /// use thrift::protocol::{TInputProtocolFactory, TOutputProtocolFactory}; /// use thrift::protocol::{TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory}; /// use thrift::protocol::{TInputProtocol, TOutputProtocol}; diff --git a/lib/rs/test/Cargo.toml b/lib/rs/test/Cargo.toml index 50dec1972c2..dc4ffe32b78 100644 --- a/lib/rs/test/Cargo.toml +++ b/lib/rs/test/Cargo.toml @@ -7,8 +7,8 @@ publish = false [dependencies] clap = "<2.28.0" -ordered-float = "0.3.0" -try_from = "0.2.0" +ordered-float = "1.0" +try_from = "0.3" [dependencies.thrift] path = "../" diff --git a/test/features/tls.sh b/test/features/tls.sh index dada6ab95d6..6fd90a5fcde 100755 --- a/test/features/tls.sh +++ b/test/features/tls.sh @@ -32,6 +32,7 @@ declare -A EXPECT_NEGOTIATE EXPECT_NEGOTIATE[tls1]=1 EXPECT_NEGOTIATE[tls1_1]=1 EXPECT_NEGOTIATE[tls1_2]=1 +EXPECT_NEGOTIATE[tls1_3]=1 failures=0 @@ -62,10 +63,10 @@ function tls tls -if [[ $failures -eq 3 ]]; then - echo "[fail] At least one of TLSv1.0, TLSv1.1, or TLSv1.2 needs to work, but does not" +if [[ $failures -eq 4 ]]; then + echo "[fail] At least one of TLSv1.0, TLSv1.1, TLSv1.2, or TLSv1.3 needs to work, but does not" exit $failures fi -echo "[pass] At least one of TLSv1.0, TLSv1.1, or TLSv1.2 worked" +echo "[pass] At least one of TLSv1.0, TLSv1.1, TLSv1.2, or TLSv1.3 worked" exit 0 diff --git a/test/rs/Cargo.toml b/test/rs/Cargo.toml index 9b35e3c4102..c1058f91f1b 100644 --- a/test/rs/Cargo.toml +++ b/test/rs/Cargo.toml @@ -6,11 +6,11 @@ authors = ["Apache Thrift Developers "] publish = false [dependencies] -clap = "<2.28.0" +clap = "2.33" env_logger = "0.4.0" -log = "0.3.7" -ordered-float = "0.3.0" -try_from = "0.2.0" +log = "0.4" +ordered-float = "1.0" +try_from = "0.3" [dependencies.thrift] path = "../../lib/rs" diff --git a/test/tests.json b/test/tests.json index 6a416399538..78d4c0e9b52 100644 --- a/test/tests.json +++ b/test/tests.json @@ -584,9 +584,9 @@ ], "command": [ "dart", - "--checked", + "--enable-asserts", "test_client/bin/main.dart", - "--verbose" + "--verbose" ] }, "workdir": "dart" @@ -612,9 +612,9 @@ "true", "-noshell", "-pa", - "../../lib/erl/ebin/", + "../../lib/erl/_build/default/lib/thrift/ebin/", "-pa", - "./ebin", + "./_build/default/lib/thrift_test/ebin", "-s", "test_client", "-s", @@ -630,9 +630,9 @@ "true", "-noshell", "-pa", - "../../lib/erl/ebin/", + "../../lib/erl/_build/default/lib/thrift/ebin/", "-pa", - "./ebin", + "./_build/default/lib/thrift_test/ebin", "-s", "test_thrift_server", "-extra" diff --git a/tutorial/rs/Cargo.toml b/tutorial/rs/Cargo.toml index 210a0daf9ff..60f02d73c22 100644 --- a/tutorial/rs/Cargo.toml +++ b/tutorial/rs/Cargo.toml @@ -7,9 +7,9 @@ exclude = ["Makefile*", "shared.rs", "tutorial.rs"] publish = false [dependencies] -clap = "<2.28.0" -ordered-float = "0.3.0" -try_from = "0.2.0" +clap = "2.33" +ordered-float = "1.0" +try_from = "0.3" [dependencies.thrift] path = "../../lib/rs" From 3131fe975ce2efd2887e41f86e73f7205a02a2a4 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 2 Jul 2019 14:21:05 -0400 Subject: [PATCH 330/756] THRIFT-4904: Fix python unit test errors and exception escapes Due to the way SSL layers on top of sockets, it was possible to complete a connection and then have the server close it. This would happen if the client is not checking certificates but the server is. The TSSLSocket unit test was enhanced to do a read and a write as well as just connecting to ensure a more complete test. The TSocket read() and write() calls were leaking OSError, socker.error, and ssl.Error exceptions. These cases are now wrapped into a TTransportException of the appropriate type, and the original exception is added as an argument named inner. --- lib/py/src/transport/TSSLSocket.py | 6 +++--- lib/py/src/transport/TSocket.py | 27 ++++++++++++++++----------- lib/py/src/transport/TTransport.py | 3 ++- lib/py/test/test_sslsocket.py | 10 ++++++++-- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/lib/py/src/transport/TSSLSocket.py b/lib/py/src/transport/TSSLSocket.py index 066d8da5e98..5b3ae599194 100644 --- a/lib/py/src/transport/TSSLSocket.py +++ b/lib/py/src/transport/TSSLSocket.py @@ -291,11 +291,11 @@ def _do_open(self, family, socktype): plain_sock = socket.socket(family, socktype) try: return self._wrap_socket(plain_sock) - except Exception: + except Exception as ex: plain_sock.close() msg = 'failed to initialize SSL' logger.exception(msg) - raise TTransportException(TTransportException.NOT_OPEN, msg) + raise TTransportException(type=TTransportException.NOT_OPEN, message=msg, inner=ex) def open(self): super(TSSLSocket, self).open() @@ -307,7 +307,7 @@ def open(self): except TTransportException: raise except Exception as ex: - raise TTransportException(TTransportException.UNKNOWN, str(ex)) + raise TTransportException(message=str(ex), inner=ex) class TSSLServerSocket(TSocket.TServerSocket, TSSLBase): diff --git a/lib/py/src/transport/TSocket.py b/lib/py/src/transport/TSocket.py index c8be25a4c2b..df25d42db5b 100644 --- a/lib/py/src/transport/TSocket.py +++ b/lib/py/src/transport/TSocket.py @@ -94,13 +94,13 @@ def _address(self): def open(self): if self.handle: - raise TTransportException(TTransportException.ALREADY_OPEN) + raise TTransportException(type=TTransportException.ALREADY_OPEN, message="already open") try: addrs = self._resolveAddr() - except socket.gaierror: + except socket.gaierror as gai: msg = 'failed to resolve sockaddr for ' + str(self._address) logger.exception(msg) - raise TTransportException(TTransportException.NOT_OPEN, msg) + raise TTransportException(type=TTransportException.NOT_OPEN, message=msg, inner=gai) for family, socktype, _, _, sockaddr in addrs: handle = self._do_open(family, socktype) @@ -119,7 +119,7 @@ def open(self): msg = 'Could not connect to any of %s' % list(map(lambda a: a[4], addrs)) logger.error(msg) - raise TTransportException(TTransportException.NOT_OPEN, msg) + raise TTransportException(type=TTransportException.NOT_OPEN, message=msg) def read(self, sz): try: @@ -134,8 +134,10 @@ def read(self, sz): self.close() # Trigger the check to raise the END_OF_FILE exception below. buff = '' + elif e.args[0] == errno.ETIMEDOUT: + raise TTransportException(type=TTransportException.TIMED_OUT, message="read timeout", inner=e) else: - raise + raise TTransportException(message="unexpected exception", inner=e) if len(buff) == 0: raise TTransportException(type=TTransportException.END_OF_FILE, message='TSocket read 0 bytes') @@ -148,12 +150,15 @@ def write(self, buff): sent = 0 have = len(buff) while sent < have: - plus = self.handle.send(buff) - if plus == 0: - raise TTransportException(type=TTransportException.END_OF_FILE, - message='TSocket sent 0 bytes') - sent += plus - buff = buff[plus:] + try: + plus = self.handle.send(buff) + if plus == 0: + raise TTransportException(type=TTransportException.END_OF_FILE, + message='TSocket sent 0 bytes') + sent += plus + buff = buff[plus:] + except socket.error as e: + raise TTransportException(message="unexpected exception", inner=e) def flush(self): pass diff --git a/lib/py/src/transport/TTransport.py b/lib/py/src/transport/TTransport.py index 8573ba7b943..9dbe95df498 100644 --- a/lib/py/src/transport/TTransport.py +++ b/lib/py/src/transport/TTransport.py @@ -34,9 +34,10 @@ class TTransportException(TException): SIZE_LIMIT = 6 INVALID_CLIENT_TYPE = 7 - def __init__(self, type=UNKNOWN, message=None): + def __init__(self, type=UNKNOWN, message=None, inner=None): TException.__init__(self, message) self.type = type + self.inner = inner class TTransportBase(object): diff --git a/lib/py/test/test_sslsocket.py b/lib/py/test/test_sslsocket.py index 598c174dcfe..f4c87f195ab 100644 --- a/lib/py/test/test_sslsocket.py +++ b/lib/py/test/test_sslsocket.py @@ -75,6 +75,9 @@ def run(self): try: self._client = self._server.accept() + if self._client: + self._client.read(5) # hello + self._client.write(b"there") except Exception: logging.exception('error on server side (%s):' % self.name) if not self._expect_failure: @@ -141,7 +144,8 @@ def _assert_connection_failure(self, server, path=None, **client_args): client.setTimeout(20) with self._assert_raises(TTransportException): client.open() - self.assertTrue(acc.client is None) + client.write(b"hello") + client.read(5) # b"there" finally: logging.disable(logging.NOTSET) @@ -153,8 +157,10 @@ def _assert_raises(self, exc): def _assert_connection_success(self, server, path=None, **client_args): with self._connectable_client(server, path=path, **client_args) as (acc, client): - client.open() try: + client.open() + client.write(b"hello") + self.assertEqual(client.read(5), b"there") self.assertTrue(acc.client is not None) finally: client.close() From 08fea1640e3585b74bbbd9ec53db798df7fe1656 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Sat, 6 Jul 2019 06:20:32 -0400 Subject: [PATCH 331/756] Mark some csharp-erl, erl-csharp ssl tests as known issues. The latest ssl (9.3) in erl does not support TLSv1.0 or TLSv1.1 by default and cross tests are failing. Since csharp was deprecated in favor of netstd, ignoring it. --- test/known_failures_Linux.json | 38 ++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index 9f97754d24f..dd6195a3715 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -67,6 +67,9 @@ "cpp-nodejs_compact_http-domain", "cpp-nodejs_compact_http-ip", "cpp-nodejs_compact_http-ip-ssl", + "cpp-nodejs_header_http-domain", + "cpp-nodejs_header_http-ip", + "cpp-nodejs_header_http-ip-ssl", "cpp-nodejs_json_http-domain", "cpp-nodejs_json_http-ip", "cpp-nodejs_json_http-ip-ssl", @@ -76,15 +79,12 @@ "cpp-nodejs_multic-compact_http-domain", "cpp-nodejs_multic-compact_http-ip", "cpp-nodejs_multic-compact_http-ip-ssl", + "cpp-nodejs_multih-header_http-domain", + "cpp-nodejs_multih-header_http-ip", + "cpp-nodejs_multih-header_http-ip-ssl", "cpp-nodejs_multij-json_http-domain", "cpp-nodejs_multij-json_http-ip", "cpp-nodejs_multij-json_http-ip-ssl", - "cpp-nodejs_multih-header_http-ip", - "cpp-nodejs_multih-header_http-ip-ssl", - "cpp-nodejs_multih-header_http-domain", - "cpp-nodejs_header_http-ip", - "cpp-nodejs_header_http-ip-ssl", - "cpp-nodejs_header_http-domain", "cpp-py3_binary-accel_http-ip", "cpp-py3_binary-accel_http-ip-ssl", "cpp-py3_binary_http-ip", @@ -159,6 +159,10 @@ "cpp-rs_multi_framed-ip", "cpp-rs_multic_buffered-ip", "cpp-rs_multic_framed-ip", + "csharp-erl_binary_buffered-ip-ssl", + "csharp-erl_binary_framed-ip-ssl", + "csharp-erl_compact_buffered-ip-ssl", + "csharp-erl_compact_framed-ip-ssl", "csharp-rb_binary-accel_buffered-ip-ssl", "csharp-rb_binary-accel_framed-ip-ssl", "csharp-rb_binary_buffered-ip-ssl", @@ -288,7 +292,11 @@ "erl-cpp_binary_buffered-ip", "erl-cpp_compact_buffered-ip", "erl-csharp_binary_buffered-ip", + "erl-csharp_binary_buffered-ip-ssl", + "erl-csharp_binary_framed-ip-ssl", "erl-csharp_compact_buffered-ip", + "erl-csharp_compact_buffered-ip-ssl", + "erl-csharp_compact_framed-ip-ssl", "erl-nodejs_binary_buffered-ip", "erl-nodejs_compact_buffered-ip", "erl-nodets_binary_buffered-ip", @@ -343,13 +351,13 @@ "nodejs-cpp_compact_http-domain", "nodejs-cpp_compact_http-ip", "nodejs-cpp_compact_http-ip-ssl", + "nodejs-cpp_header_http-domain", + "nodejs-cpp_header_http-ip", + "nodejs-cpp_header_http-ip-ssl", "nodejs-cpp_json_buffered-ip-ssl", "nodejs-cpp_json_http-domain", "nodejs-cpp_json_http-ip", "nodejs-cpp_json_http-ip-ssl", - "nodejs-cpp_header_http-ip", - "nodejs-cpp_header_http-ip-ssl", - "nodejs-cpp_header_http-domain", "nodejs-d_binary_http-ip", "nodejs-d_binary_http-ip-ssl", "nodejs-d_compact_http-ip", @@ -369,8 +377,8 @@ "nodejs-go_json_http-ip-ssl", "nodejs-hs_binary_http-ip", "nodejs-hs_compact_http-ip", - "nodejs-hs_json_http-ip", "nodejs-hs_header_http-ip", + "nodejs-hs_json_http-ip", "nodejs-java_binary_http-ip", "nodejs-java_binary_http-ip-ssl", "nodejs-java_compact_http-ip", @@ -389,12 +397,10 @@ "nodejs-py3_compact-accelc_http-ip-ssl", "nodejs-py3_compact_http-ip", "nodejs-py3_compact_http-ip-ssl", - "nodejs-py3_json_http-ip", - "nodejs-py3_json_http-ip-ssl", "nodejs-py3_header_http-ip", "nodejs-py3_header_http-ip-ssl", - "nodejs-py_header_http-ip", - "nodejs-py_header_http-ip-ssl", + "nodejs-py3_json_http-ip", + "nodejs-py3_json_http-ip-ssl", "nodejs-py_binary-accel_http-ip", "nodejs-py_binary-accel_http-ip-ssl", "nodejs-py_binary_http-ip", @@ -403,6 +409,8 @@ "nodejs-py_compact-accelc_http-ip-ssl", "nodejs-py_compact_http-ip", "nodejs-py_compact_http-ip-ssl", + "nodejs-py_header_http-ip", + "nodejs-py_header_http-ip-ssl", "nodejs-py_json_http-ip", "nodejs-py_json_http-ip-ssl", "perl-rs_multi_buffered-ip", @@ -607,4 +615,4 @@ "rb-cpp_json_framed-domain", "rb-cpp_json_framed-ip", "rb-cpp_json_framed-ip-ssl" -] +] \ No newline at end of file From f9435643d758f9b08937399abe7f721ec7d65fcf Mon Sep 17 00:00:00 2001 From: Matt Kantor Date: Thu, 4 Jul 2019 11:55:26 -0700 Subject: [PATCH 332/756] Fix a typo in README.md. The crate is named `ordered-float`, not `ordered_float`. --- tutorial/rs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tutorial/rs/README.md b/tutorial/rs/README.md index 8ad39adb759..166854beaff 100644 --- a/tutorial/rs/README.md +++ b/tutorial/rs/README.md @@ -8,7 +8,7 @@ ```toml thrift = "x.y.z" # x.y.z is the version of the thrift compiler -ordered_float = "0.3.0" +ordered-float = "0.3.0" try_from = "0.2.0" ``` From 08a6eb6e1f21aa15682e414e124d7ee1a51a39c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20C=C5=93ur?= Date: Mon, 8 Jul 2019 18:42:09 +0800 Subject: [PATCH 333/756] THRIFT-4902: Swift 4 and 5 compatibility (#1827) --- .travis.yml | 23 +++++++++++++++- Thrift.podspec | 13 +++++---- lib/swift/Sources/TBinaryProtocol.swift | 30 ++++++++++----------- lib/swift/Sources/TCompactProtocol.swift | 10 +++---- lib/swift/Sources/TFramedTransport.swift | 8 +++--- lib/swift/Sources/TMap.swift | 8 ++---- lib/swift/Sources/TProtocol.swift | 13 +++++---- lib/swift/Sources/TSSLSocketTransport.swift | 15 ++++++++--- lib/swift/Sources/TSet.swift | 2 +- lib/swift/Sources/TSocketServer.swift | 1 - lib/swift/Sources/TSocketTransport.swift | 16 +++++++---- lib/swift/Sources/TStreamTransport.swift | 15 ++++++++--- lib/swift/Sources/TStruct.swift | 8 +++--- 13 files changed, 96 insertions(+), 66 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4a399a60e82..400cfa146e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -148,7 +148,28 @@ jobs: env: - JOB="Coverity Scan" - SCRIPT="covscan.sh" - + + # ------------------------- phase: swift ------------------------ + # We lint the podspec + - os: osx + osx_image: xcode10.1 + language: swift + script: + - gem update cocoapods + - pod lib lint --allow-warnings --swift-version=3 + env: + - JOB="pod lib lint" + + - os: osx + osx_image: xcode10.2 + language: swift + script: + - gem update cocoapods + - pod lib lint --allow-warnings --swift-version=4.0 + - pod lib lint --allow-warnings --swift-version=4.2 + - pod lib lint --allow-warnings --swift-version=5.0 + env: + - JOB="pod lib lint" ### ------------------------- phase: osx -------------------------- # disabled due to the time delays it imposes on build jobs diff --git a/Thrift.podspec b/Thrift.podspec index cb1c9b2922a..4c8fa68aced 100644 --- a/Thrift.podspec +++ b/Thrift.podspec @@ -1,16 +1,15 @@ Pod::Spec.new do |s| - s.name = "Thrift-swift3" - s.version = "0.13.0" + s.name = 'Thrift' + s.version = '0.13.0' s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC." s.description = <<-DESC The Apache Thrift scalable cross-language software framework for networked services development combines a software stack with a code generation engine to build services that work efficiently and seamlessly between many programming languages. DESC - s.homepage = "http://thrift.apache.org" + s.homepage = 'https://thrift.apache.org' s.license = { :type => 'Apache License, Version 2.0', :url => 'https://www.apache.org/licenses/LICENSE-2.0' } - s.author = { "Apache Thrift Developers" => "dev@thrift.apache.org" } + s.author = { 'Apache Thrift Developers' => 'dev@thrift.apache.org' } s.ios.deployment_target = '9.0' s.osx.deployment_target = '10.10' - s.requires_arc = true - s.source = { :git => "https://github.com/apache/thrift.git", :tag => "v0.13.0" } - s.source_files = "lib/swift/Sources/*.swift" + s.source = { :git => 'https://github.com/apache/thrift.git', :tag => 'v0.13.0' } + s.source_files = 'lib/swift/Sources/*.swift' end diff --git a/lib/swift/Sources/TBinaryProtocol.swift b/lib/swift/Sources/TBinaryProtocol.swift index a97249abc9e..85acce0455f 100644 --- a/lib/swift/Sources/TBinaryProtocol.swift +++ b/lib/swift/Sources/TBinaryProtocol.swift @@ -325,7 +325,7 @@ public class TBinaryProtocol: TProtocol { } public func write(_ value: UInt8) throws { - let buff = Data(bytes: [value]) + let buff = Data([value]) try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) { try self.transport.write(data: buff) @@ -334,8 +334,8 @@ public class TBinaryProtocol: TProtocol { public func write(_ value: Int16) throws { var buff = Data() - buff.append(Data(bytes: [UInt8(0xff & (value >> 8))])) - buff.append(Data(bytes: [UInt8(0xff & (value))])) + buff.append(Data([UInt8(0xff & (value >> 8))])) + buff.append(Data([UInt8(0xff & (value))])) try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) { try self.transport.write(data: buff) } @@ -343,10 +343,10 @@ public class TBinaryProtocol: TProtocol { public func write(_ value: Int32) throws { var buff = Data() - buff.append(Data(bytes: [UInt8(0xff & (value >> 24))])) - buff.append(Data(bytes: [UInt8(0xff & (value >> 16))])) - buff.append(Data(bytes: [UInt8(0xff & (value >> 8))])) - buff.append(Data(bytes: [UInt8(0xff & (value))])) + buff.append(Data([UInt8(0xff & (value >> 24))])) + buff.append(Data([UInt8(0xff & (value >> 16))])) + buff.append(Data([UInt8(0xff & (value >> 8))])) + buff.append(Data([UInt8(0xff & (value))])) try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) { try self.transport.write(data: buff) @@ -355,14 +355,14 @@ public class TBinaryProtocol: TProtocol { public func write(_ value: Int64) throws { var buff = Data() - buff.append(Data(bytes: [UInt8(0xff & (value >> 56))])) - buff.append(Data(bytes: [UInt8(0xff & (value >> 48))])) - buff.append(Data(bytes: [UInt8(0xff & (value >> 40))])) - buff.append(Data(bytes: [UInt8(0xff & (value >> 32))])) - buff.append(Data(bytes: [UInt8(0xff & (value >> 24))])) - buff.append(Data(bytes: [UInt8(0xff & (value >> 16))])) - buff.append(Data(bytes: [UInt8(0xff & (value >> 8))])) - buff.append(Data(bytes: [UInt8(0xff & (value))])) + buff.append(Data([UInt8(0xff & (value >> 56))])) + buff.append(Data([UInt8(0xff & (value >> 48))])) + buff.append(Data([UInt8(0xff & (value >> 40))])) + buff.append(Data([UInt8(0xff & (value >> 32))])) + buff.append(Data([UInt8(0xff & (value >> 24))])) + buff.append(Data([UInt8(0xff & (value >> 16))])) + buff.append(Data([UInt8(0xff & (value >> 8))])) + buff.append(Data([UInt8(0xff & (value))])) try ProtocolTransportTry(error: TProtocolError(message: "Transport write failed")) { try self.transport.write(data: buff) diff --git a/lib/swift/Sources/TCompactProtocol.swift b/lib/swift/Sources/TCompactProtocol.swift index 59773c34af3..5b302d38f8d 100644 --- a/lib/swift/Sources/TCompactProtocol.swift +++ b/lib/swift/Sources/TCompactProtocol.swift @@ -67,7 +67,7 @@ public class TCompactProtocol: TProtocol { /// Mark: - TCompactProtocol helpers func writebyteDirect(_ byte: UInt8) throws { - let byte = Data(bytes: [byte]) + let byte = Data([byte]) try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) { try self.transport.write(data: byte) } @@ -90,7 +90,7 @@ public class TCompactProtocol: TProtocol { } try ProtocolTransportTry(error: TProtocolError(message: "Transport Write Failed")) { - try self.transport.write(data: Data(bytes: i32buf[0..> UInt8(TCType.typeShiftAmount)) & TCType.typeBits @@ -485,7 +482,6 @@ public class TCompactProtocol: TProtocol { } lastFieldId = UInt8(fieldID) - } public func writeFieldStop() throws { diff --git a/lib/swift/Sources/TFramedTransport.swift b/lib/swift/Sources/TFramedTransport.swift index ca385d6d3ce..59855eb9cb7 100644 --- a/lib/swift/Sources/TFramedTransport.swift +++ b/lib/swift/Sources/TFramedTransport.swift @@ -92,10 +92,10 @@ public class TFramedTransport: TTransport { private func encodeFrameSize(size: UInt32) -> Data { var data = Data() - data.append(Data(bytes: [UInt8(0xff & (size >> 24))])) - data.append(Data(bytes: [UInt8(0xff & (size >> 16))])) - data.append(Data(bytes: [UInt8(0xff & (size >> 8))])) - data.append(Data(bytes: [UInt8(0xff & (size))])) + data.append(Data([UInt8(0xff & (size >> 24))])) + data.append(Data([UInt8(0xff & (size >> 16))])) + data.append(Data([UInt8(0xff & (size >> 8))])) + data.append(Data([UInt8(0xff & (size))])) return data } diff --git a/lib/swift/Sources/TMap.swift b/lib/swift/Sources/TMap.swift index 89803773949..dcf1481c6a4 100644 --- a/lib/swift/Sources/TMap.swift +++ b/lib/swift/Sources/TMap.swift @@ -21,7 +21,7 @@ public struct TMap: Colle public typealias Storage = Dictionary public typealias Element = Storage.Element public typealias Index = Storage.Index - public typealias IndexDistance = Storage.IndexDistance + public typealias IndexDistance = Int public typealias Indices = Storage.Indices public typealias SubSequence = Storage.SubSequence internal var storage = Storage() @@ -33,11 +33,7 @@ public struct TMap: Colle } public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? { - return updateValue(value, forKey: key) - } - - public mutating func removeAtIndex(_ index: DictionaryIndex) -> (Key, Value) { - return removeAtIndex(index) + return storage.updateValue(value, forKey: key) } public mutating func removeValueForKey(_ key: Key) -> Value? { diff --git a/lib/swift/Sources/TProtocol.swift b/lib/swift/Sources/TProtocol.swift index b111e71bbbf..b4e5dbe73b3 100644 --- a/lib/swift/Sources/TProtocol.swift +++ b/lib/swift/Sources/TProtocol.swift @@ -18,7 +18,6 @@ */ import Foundation -// public enum TMessageType: Int32 { case call = 1 @@ -99,19 +98,19 @@ public protocol TProtocol { } public extension TProtocol { - public func writeFieldValue(_ value: TSerializable, name: String, type: TType, id: Int32) throws { + func writeFieldValue(_ value: TSerializable, name: String, type: TType, id: Int32) throws { try writeFieldBegin(name: name, type: type, fieldID: id) try value.write(to: self) try writeFieldEnd() } - public func validateValue(_ value: Any?, named name: String) throws { + func validateValue(_ value: Any?, named name: String) throws { if value == nil { throw TProtocolError(error: .unknown, message: "Missing required value for field: \(name)") } } - public func readResultMessageBegin() throws { + func readResultMessageBegin() throws { let (_, type, _) = try readMessageBegin(); if type == .exception { let x = try readException() @@ -120,17 +119,17 @@ public extension TProtocol { return } - public func readException() throws -> TApplicationError { + func readException() throws -> TApplicationError { return try TApplicationError.read(from: self) } - public func writeException(messageName name: String, sequenceID: Int32, ex: TApplicationError) throws { + func writeException(messageName name: String, sequenceID: Int32, ex: TApplicationError) throws { try writeMessageBegin(name: name, type: .exception, sequenceID: sequenceID) try ex.write(to: self) try writeMessageEnd() } - public func skip(type: TType) throws { + func skip(type: TType) throws { switch type { case .bool: _ = try read() as Bool case .i8: _ = try read() as UInt8 diff --git a/lib/swift/Sources/TSSLSocketTransport.swift b/lib/swift/Sources/TSSLSocketTransport.swift index c2b590266a8..d350f821ee7 100644 --- a/lib/swift/Sources/TSSLSocketTransport.swift +++ b/lib/swift/Sources/TSSLSocketTransport.swift @@ -20,6 +20,13 @@ import Foundation import CoreFoundation +#if !swift(>=4.2) +// Swift 3/4 compatibility +fileprivate extension RunLoopMode { + static let `default` = defaultRunLoopMode +} +#endif + #if os(Linux) public class TSSLSocketTransport { init(hostname: String, port: UInt16) { @@ -98,18 +105,18 @@ public class TSSLSocketTransport: TStreamTransport { CFReadStreamSetProperty(readStream?.takeRetainedValue(), .SSLSettings, - settings as CFTypeRef!) + settings as CFTypeRef) CFWriteStreamSetProperty(writeStream?.takeRetainedValue(), .SSLSettings, - settings as CFTypeRef!) + settings as CFTypeRef) inputStream = readStream!.takeRetainedValue() - inputStream?.schedule(in: .current, forMode: .defaultRunLoopMode) + inputStream?.schedule(in: .current, forMode: .default) inputStream?.open() outputStream = writeStream!.takeRetainedValue() - outputStream?.schedule(in: .current, forMode: .defaultRunLoopMode) + outputStream?.schedule(in: .current, forMode: .default) outputStream?.open() readStream?.release() diff --git a/lib/swift/Sources/TSet.swift b/lib/swift/Sources/TSet.swift index 1ecd170a571..6891c11e6de 100644 --- a/lib/swift/Sources/TSet.swift +++ b/lib/swift/Sources/TSet.swift @@ -32,7 +32,7 @@ public struct TSet : SetAlgebra, Hashable, C public typealias Indices = Storage.Indices public typealias Index = Storage.Index - public typealias IndexDistance = Storage.IndexDistance + public typealias IndexDistance = Int public typealias SubSequence = Storage.SubSequence diff --git a/lib/swift/Sources/TSocketServer.swift b/lib/swift/Sources/TSocketServer.swift index 0224e67b5e9..7367c7edcbe 100644 --- a/lib/swift/Sources/TSocketServer.swift +++ b/lib/swift/Sources/TSocketServer.swift @@ -105,7 +105,6 @@ class TSocketServer=4.2) +// Swift 3/4 compatibility +fileprivate extension RunLoopMode { + static let `default` = defaultRunLoopMode +} +#endif + private struct Sys { #if os(Linux) static let read = Glibc.read @@ -72,7 +79,7 @@ public class TCFSocketTransport: TStreamTransport { var readStream: Unmanaged? var writeStream: Unmanaged? CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, - hostname as CFString!, + hostname as CFString, UInt32(port), &readStream, &writeStream) @@ -88,11 +95,11 @@ public class TCFSocketTransport: TStreamTransport { } inputStream = readStream as InputStream - inputStream.schedule(in: .current, forMode: .defaultRunLoopMode) + inputStream.schedule(in: .current, forMode: .default) inputStream.open() outputStream = writeStream as OutputStream - outputStream.schedule(in: .current, forMode: .defaultRunLoopMode) + outputStream.schedule(in: .current, forMode: .default) outputStream.open() } else { @@ -140,7 +147,6 @@ public class TSocketTransport : TTransport { } - #if os(Linux) let sock = socket(AF_INET, Int32(SOCK_STREAM.rawValue), 0) var addr = sockaddr_in(sin_family: sa_family_t(AF_INET), @@ -184,7 +190,7 @@ public class TSocketTransport : TTransport { var buff = Array.init(repeating: 0, count: size) let readBytes = Sys.read(socketDescriptor, &buff, size) - return Data(bytes: buff[0..=4.2) +// Swift 3/4 compatibility +fileprivate extension RunLoopMode { + static let `default` = defaultRunLoopMode +} +#endif + #if os(Linux) /// Currently unavailable in Linux /// Remove comments and build to fix @@ -64,7 +71,7 @@ import CoreFoundation if bytesRead <= 0 { throw TTransportError(error: .notOpen) } - read.append(Data(bytes: buffer)) + read.append(Data(buffer)) } return read } @@ -85,7 +92,7 @@ import CoreFoundation break } - read.append(Data(bytes: buffer)) + read.append(Data(buffer)) } return read } @@ -124,7 +131,7 @@ import CoreFoundation input?.delegate = nil input?.close() - input?.remove(from: .current, forMode: .defaultRunLoopMode) + input?.remove(from: .current, forMode: .default) input = nil } @@ -135,7 +142,7 @@ import CoreFoundation } output?.delegate = nil output?.close() - output?.remove(from: .current, forMode: .defaultRunLoopMode) + output?.remove(from: .current, forMode: .default) output = nil } } diff --git a/lib/swift/Sources/TStruct.swift b/lib/swift/Sources/TStruct.swift index f172a32d125..38e51e7026c 100644 --- a/lib/swift/Sources/TStruct.swift +++ b/lib/swift/Sources/TStruct.swift @@ -29,10 +29,10 @@ public protocol TStruct : TSerializable { } public extension TStruct { - public static var fieldIds: [String: (id: Int32, type: TType)] { return [:] } - public static var thriftType: TType { return .struct } + static var fieldIds: [String: (id: Int32, type: TType)] { return [:] } + static var thriftType: TType { return .struct } - public func write(to proto: TProtocol) throws { + func write(to proto: TProtocol) throws { // Write struct name first try proto.writeStructBegin(name: Self.structName) @@ -45,7 +45,7 @@ public extension TStruct { try proto.writeStructEnd() } - public var hashValue: Int { + var hashValue: Int { let prime = 31 var result = 1 self.forEach { _, value, _ in From c35ed736d26a1dfd8965ae197a67904ed9b4fba3 Mon Sep 17 00:00:00 2001 From: Mithun RK Date: Mon, 11 Mar 2019 14:14:05 -0700 Subject: [PATCH 334/756] THRIFT-4805: Suppress excessive logging of SASL TTransportExceptions in case of END_OF_FILE Two fixes here: 1. Additional logic to properly catch and handle TTransportException. Currently, T(SASL)TransportException gets caught and handled in the wrong catch-block. 2. The fix for THRIFT-3769 mutes _all_ TTransportExceptions in TThreadPoolServer. This might mute legitimate failures. The intent of THRIFT-3769 (and THRIFT-2268) was to mute the noise caused by TTransportException.END_OF_FILE. This commit lets legitimate failures to be bubbled upwards. --- CHANGES.md | 1 + lib/java/README.md | 5 ++- .../thrift/server/TThreadPoolServer.java | 36 ++++++++++------ .../thrift/transport/TSaslTransport.java | 17 +++++--- .../transport/TSaslTransportException.java | 43 ------------------- 5 files changed, 40 insertions(+), 62 deletions(-) delete mode 100644 lib/java/src/org/apache/thrift/transport/TSaslTransportException.java diff --git a/CHANGES.md b/CHANGES.md index df731219440..9f2d1e436b0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -25,6 +25,7 @@ - [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - java: changes to UTF-8 handling require JDK 1.7 at a minimum - [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - java: class org.apache.thrift.ShortStack is no longer public - [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - java: change return type signature of 'process' methods +- [THRIFT-4805](https://issues.apache.org/jira/browse/THRIFT-4805) - java: Suppress excessive logging of SASL TTransportExceptions in case of END_OF_FILE - [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - js: now uses node-int64 for 64 bit integer constants - [THRIFT-4841](https://issues.apache.org/jira/browse/THRIFT-4841) - delphi: old THTTPTransport is now TMsxmlHTTPTransport - [THRIFT-4536](https://issues.apache.org/jira/browse/THRIFT-4536) - rust: convert from try-from crate to rust stable (1.34+), re-export ordered-float diff --git a/lib/java/README.md b/lib/java/README.md index 7dca456204f..78e6445a6da 100644 --- a/lib/java/README.md +++ b/lib/java/README.md @@ -170,9 +170,12 @@ http://gradle.org/ ## 1.0 -The signature of the 'process' method in TAsyncProcessor and TProcessor has +* The signature of the 'process' method in TAsyncProcessor and TProcessor has changed to remove a boolean return type and to instead rely on Exceptions. +* Per THRIFT-4805, TSaslTransportException has been removed. The same condition +is now covered by TTansportException, where `TTransportException.getType() == END_OF_FILE`. + ## 0.12.0 The access modifier of the AutoExpandingBuffer class has been changed from diff --git a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java index db1ecb9dab6..87e873381d2 100644 --- a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java +++ b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java @@ -19,6 +19,8 @@ package org.apache.thrift.server; +import java.util.Arrays; +import java.util.List; import java.util.Random; import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; @@ -29,14 +31,12 @@ import org.apache.thrift.TException; import org.apache.thrift.TProcessor; import org.apache.thrift.protocol.TProtocol; -import org.apache.thrift.transport.TSaslTransportException; import org.apache.thrift.transport.TServerTransport; import org.apache.thrift.transport.TTransport; import org.apache.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 @@ -312,21 +312,13 @@ public void run() { } processor.process(inputProtocol, outputProtocol); } - } catch (TException tx) { - LOGGER.error("Thrift error occurred during processing of message.", tx); } catch (Exception x) { // We'll usually receive RuntimeException types here // Need to unwrap to ascertain real causing exception before we choose to ignore - Throwable realCause = x.getCause(); // Ignore err-logging all transport-level/type exceptions - if ((realCause != null && realCause instanceof TTransportException) - || (x instanceof TTransportException)) { - LOGGER.debug( - "Received TTransportException during processing of message. Ignoring.", - x); - } else { + if (!isIgnorableException(x)) { // Log the exception at error level and continue - LOGGER.error("Error occurred during processing of message.", x); + LOGGER.error((x instanceof TException? "Thrift " : "") + "Error occurred during processing of message.", x); } } finally { if (eventHandler != null) { @@ -343,5 +335,25 @@ public void run() { } } } + + private boolean isIgnorableException(Exception x) { + TTransportException tTransportException = null; + + if (x instanceof TTransportException) { + tTransportException = (TTransportException)x; + } + else if (x.getCause() instanceof TTransportException) { + tTransportException = (TTransportException)x.getCause(); + } + + if (tTransportException != null) { + switch(tTransportException.getType()) { + case TTransportException.END_OF_FILE: + case TTransportException.TIMED_OUT: + return true; + } + } + return false; + } } } diff --git a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java index c8584259184..4a453b68f97 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java @@ -310,14 +310,11 @@ public void open() throws TTransportException { 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 there is no-data or no-sasl header in the stream, + // log the failure, and clean up the underlying transport. 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 during negotiation", e); + LOGGER.debug("No data or no sasl data in the stream during negotiation"); } throw e; } @@ -427,6 +424,14 @@ public int read(byte[] buf, int off, int len) throws TTransportException { readFrame(); } catch (SaslException e) { throw new TTransportException(e); + } catch (TTransportException transportException) { + // If there is no-data or no-sasl header in the stream, log the failure, and rethrow. + if (transportException.getType() == TTransportException.END_OF_FILE) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("No data or no sasl data in the stream during negotiation"); + } + } + throw transportException; } return readBuffer.read(buf, off, len); diff --git a/lib/java/src/org/apache/thrift/transport/TSaslTransportException.java b/lib/java/src/org/apache/thrift/transport/TSaslTransportException.java deleted file mode 100644 index 90189f4a75b..00000000000 --- a/lib/java/src/org/apache/thrift/transport/TSaslTransportException.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 org.apache.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); - } -} From 178891f7d62adc98d1d1e661a0c26dd6a67ee50b Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 8 Jul 2019 06:49:15 -0400 Subject: [PATCH 335/756] THRIFT-4805: Fixed readme files --- CHANGES.md | 2 +- lib/java/README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9f2d1e436b0..9d13d9501c6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -25,7 +25,7 @@ - [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - java: changes to UTF-8 handling require JDK 1.7 at a minimum - [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - java: class org.apache.thrift.ShortStack is no longer public - [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - java: change return type signature of 'process' methods -- [THRIFT-4805](https://issues.apache.org/jira/browse/THRIFT-4805) - java: Suppress excessive logging of SASL TTransportExceptions in case of END_OF_FILE +- [THRIFT-4805](https://issues.apache.org/jira/browse/THRIFT-4805) - java: replaced TSaslTransportException with TTransportException - [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - js: now uses node-int64 for 64 bit integer constants - [THRIFT-4841](https://issues.apache.org/jira/browse/THRIFT-4841) - delphi: old THTTPTransport is now TMsxmlHTTPTransport - [THRIFT-4536](https://issues.apache.org/jira/browse/THRIFT-4536) - rust: convert from try-from crate to rust stable (1.34+), re-export ordered-float diff --git a/lib/java/README.md b/lib/java/README.md index 78e6445a6da..c8ec1c37c62 100644 --- a/lib/java/README.md +++ b/lib/java/README.md @@ -168,10 +168,10 @@ http://gradle.org/ # Breaking Changes -## 1.0 +## 0.13.0 * The signature of the 'process' method in TAsyncProcessor and TProcessor has -changed to remove a boolean return type and to instead rely on Exceptions. +changed to remove the boolean return type and instead rely on Exceptions. * Per THRIFT-4805, TSaslTransportException has been removed. The same condition is now covered by TTansportException, where `TTransportException.getType() == END_OF_FILE`. From 234e80e1b9acb1bc778c7adfaa6cb695d922d5f0 Mon Sep 17 00:00:00 2001 From: fmalaguti Date: Thu, 4 Apr 2019 15:05:26 +0200 Subject: [PATCH 336/756] THRIFT-4844: createConnection ignores connect_timeout option --- lib/nodejs/lib/thrift/connection.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/nodejs/lib/thrift/connection.js b/lib/nodejs/lib/thrift/connection.js index 72ecb69559c..25e34ed4240 100644 --- a/lib/nodejs/lib/thrift/connection.js +++ b/lib/nodejs/lib/thrift/connection.js @@ -256,7 +256,11 @@ Connection.prototype.connection_gone = function () { }; exports.createConnection = function(host, port, options) { - var stream = net.createConnection(port, host); + var stream = net.createConnection( { + port: port, + host: host, + timeout: options.connect_timeout || options.timeout || 0 + }); var connection = new Connection(stream, options); connection.host = host; connection.port = port; From 286eee16b147a302ddc7b10740c5e5401ebbec17 Mon Sep 17 00:00:00 2001 From: Beluga Behr Date: Wed, 17 Apr 2019 09:33:58 -0400 Subject: [PATCH 337/756] THRIFT-4849: Do not Ignore InterruptedException --- lib/java/src/org/apache/thrift/server/TNonblockingServer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/java/src/org/apache/thrift/server/TNonblockingServer.java b/lib/java/src/org/apache/thrift/server/TNonblockingServer.java index 2358c6356d7..79610b0f70d 100644 --- a/lib/java/src/org/apache/thrift/server/TNonblockingServer.java +++ b/lib/java/src/org/apache/thrift/server/TNonblockingServer.java @@ -86,8 +86,8 @@ protected void joinSelector() { 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. + LOGGER.debug("Interrupted while waiting for accept thread", e); + Thread.currentThread().interrupt(); } } From 49aab657b95e0b0955cb487fefb794ae2f83fd98 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Thu, 11 Jul 2019 06:55:28 -0400 Subject: [PATCH 338/756] Update the versioning description [ci skip] --- doc/ReleaseManagement.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/ReleaseManagement.md b/doc/ReleaseManagement.md index ce0744b3a3b..362fd831511 100644 --- a/doc/ReleaseManagement.md +++ b/doc/ReleaseManagement.md @@ -8,12 +8,13 @@ It is important to note here that Apache Thrift is designed for version interope ### Versioning -Apache Thrift and the vast majority of package management systems out there conform to the [SemVer 2.0](https://semver.org/spec/v2.0.0.html) version numbering specification. +Apache Thrift and the vast majority of package management systems out there conform to the [SemVer 2.0](https://semver.org/spec/v2.0.0.html) version numbering specification. Apache Thrift uses the following versioning rules: -In terms of releases, the important version numbers for Apache Thrift are the major and minor. The patch number is used in the following cases: +- *major* is currently always zero; +- *minor* is increased for each release cycle; +- *patch* is increased for patch builds between release cycles to address critical defect, security, or packaging issues -1. There were language-specific critical defects or packaging issues. -1. There was something horribly and fundamentally wrong with a x.x.0 release. +Further, if there are only packaging changes for a single third-party distribution point to correct an issue, the major.minor.patch may remain the same while adding a suffix compatible with that distribution point, for example "0.12.0.1" for nuget, or "0.12.0-1" for maven. #### External Package Patches From f34b50fdc582d8e625f5d6fe01d7f85ead5cc903 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Mon, 15 Jul 2019 07:04:28 -0400 Subject: [PATCH 339/756] Add a coverity scan utility build script [ci skip] --- build/docker/scripts/coverity.sh | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 build/docker/scripts/coverity.sh diff --git a/build/docker/scripts/coverity.sh b/build/docker/scripts/coverity.sh new file mode 100755 index 00000000000..ecc7a282e75 --- /dev/null +++ b/build/docker/scripts/coverity.sh @@ -0,0 +1,40 @@ +#! /bin/bash +# +# This script allows you to run coverity on the project and submit the +# results. Do this inside the docker build container. Only works if +# you are a coverity scan thrift project admin with access to the +# necessary security token. +# +# Environment Variables +# +# COVERITY_SCAN_NOTIFICATION_EMAIL - email address to notify +# COVERITY_SCAN_TOKEN - the Coverity Scan token (should be secure) +# VERSION - the version to report we scanned + +set -ex + +wget -nv https://entrust.com/root-certificates/entrust_l1k.cer -O /tmp/scanca.cer + +pushd /tmp +if [[ "$1" != "--skipdownload" ]]; then + rm -rf coverity_tool.tgz cov-analysis* + wget -nv -O coverity_tool.tgz https://scan.coverity.com/download/cxx/linux64 --post-data "project=thrift&token=$COVERITY_SCAN_TOKEN" + tar xzf coverity_tool.tgz +fi +COVBIN=$(echo $(pwd)/cov-analysis*/bin) +export PATH=$COVBIN:$PATH +popd + +./bootstrap.sh +./configure $* +rm -rf cov-int/ +cov-build --dir cov-int make check -j3 +tail -50 cov-int/build-log.txt +tar cJf cov-int.tar.xz cov-int/ +curl --cacert /tmp/scanca.cer \ + --form token="$COVERITY_SCAN_TOKEN" \ + --form email="$COVERITY_SCAN_NOTIFICATION_EMAIL" \ + --form file=@cov-int.tar.xz \ + --form version="$VERSION" \ + --form description="thrift master" \ + https://scan.coverity.com/builds?project=thrift From 4c847372eb9af8ec0b21ace31840eaabfdf32660 Mon Sep 17 00:00:00 2001 From: guozhu cheng Date: Mon, 15 Jul 2019 19:46:25 +0800 Subject: [PATCH 340/756] THRIFT-4908: remove reader&writer in Golang's TBinaryProtocol Client: go This closes #1831. --- lib/go/thrift/binary_protocol.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/go/thrift/binary_protocol.go b/lib/go/thrift/binary_protocol.go index 1f90bf4351f..93ae898cf5e 100644 --- a/lib/go/thrift/binary_protocol.go +++ b/lib/go/thrift/binary_protocol.go @@ -32,8 +32,6 @@ import ( type TBinaryProtocol struct { trans TRichTransport origTransport TTransport - reader io.Reader - writer io.Writer strictRead bool strictWrite bool buffer [64]byte @@ -55,8 +53,6 @@ func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProt } else { p.trans = NewTRichTransport(t) } - p.reader = p.trans - p.writer = p.trans return p } @@ -192,21 +188,21 @@ func (p *TBinaryProtocol) WriteByte(value int8) error { func (p *TBinaryProtocol) WriteI16(value int16) error { v := p.buffer[0:2] binary.BigEndian.PutUint16(v, uint16(value)) - _, e := p.writer.Write(v) + _, e := p.trans.Write(v) return NewTProtocolException(e) } func (p *TBinaryProtocol) WriteI32(value int32) error { v := p.buffer[0:4] binary.BigEndian.PutUint32(v, uint32(value)) - _, e := p.writer.Write(v) + _, e := p.trans.Write(v) return NewTProtocolException(e) } func (p *TBinaryProtocol) WriteI64(value int64) error { v := p.buffer[0:8] binary.BigEndian.PutUint64(v, uint64(value)) - _, err := p.writer.Write(v) + _, err := p.trans.Write(v) return NewTProtocolException(err) } @@ -228,7 +224,7 @@ func (p *TBinaryProtocol) WriteBinary(value []byte) error { if e != nil { return e } - _, err := p.writer.Write(value) + _, err := p.trans.Write(value) return NewTProtocolException(err) } @@ -468,7 +464,7 @@ func (p *TBinaryProtocol) Transport() TTransport { } func (p *TBinaryProtocol) readAll(buf []byte) error { - _, err := io.ReadFull(p.reader, buf) + _, err := io.ReadFull(p.trans, buf) return NewTProtocolException(err) } From 90a044659878f3581aba922dbde1ed4bd7918678 Mon Sep 17 00:00:00 2001 From: "James E. King III" Date: Tue, 23 Jul 2019 22:50:28 -0400 Subject: [PATCH 341/756] Added an Ubuntu Disco 19.04 dockerfile for testing [ci skip] --- build/docker/ubuntu-disco/Dockerfile | 285 +++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 build/docker/ubuntu-disco/Dockerfile diff --git a/build/docker/ubuntu-disco/Dockerfile b/build/docker/ubuntu-disco/Dockerfile new file mode 100644 index 00000000000..b017c4e2164 --- /dev/null +++ b/build/docker/ubuntu-disco/Dockerfile @@ -0,0 +1,285 @@ +# 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. + +# +# Apache Thrift Docker build environment for Ubuntu Disco +# with some updated packages. +# + +FROM buildpack-deps:disco-scm +MAINTAINER Apache Thrift +ENV DEBIAN_FRONTEND noninteractive + +### Add apt repos + +RUN apt-get update && \ + apt-get dist-upgrade -y && \ + apt-get install -y --no-install-recommends \ + apt \ + apt-transport-https \ + apt-utils \ + curl \ + dirmngr \ + software-properties-common \ + wget + +# Dart +RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ + curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ + /etc/apt/sources.list.d/dart_stable.list + +# dotnet (netcore) +RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /etc/apt/trusted.gpg.d/microsoft.gpg && \ + wget -q -O /etc/apt/sources.list.d/microsoft-prod.list https://packages.microsoft.com/config/ubuntu/18.04/prod.list && \ + chown root:root /etc/apt/trusted.gpg.d/microsoft.gpg && \ + chown root:root /etc/apt/sources.list.d/microsoft-prod.list + +# erlang +RUN wget -O- https://packages.erlang-solutions.com/ubuntu/erlang_solutions.asc | apt-key add - && \ + echo "deb https://packages.erlang-solutions.com/ubuntu disco contrib" | tee /etc/apt/sources.list.d/erlang.list + +# node.js +RUN curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ + echo "deb https://deb.nodesource.com/node_10.x disco main" | tee /etc/apt/sources.list.d/nodesource.list + +### install general dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ +`# General dependencies` \ + bash-completion \ + bison \ + build-essential \ + clang \ + cmake \ + debhelper \ + flex \ + gdb \ + libasound2 \ + libatk-bridge2.0-0 \ + libgtk-3-0 \ + llvm \ + ninja-build \ + pkg-config \ + unzip \ + valgrind \ + vim +ENV PATH /usr/lib/llvm-6.0/bin:$PATH + +# lib/as3 (ActionScript) +RUN mkdir -p /usr/local/adobe/flex/4.6 && \ + cd /usr/local/adobe/flex/4.6 && \ + wget -q "http://download.macromedia.com/pub/flex/sdk/flex_sdk_4.6.zip" && \ + unzip flex_sdk_4.6.zip +ENV FLEX_HOME /usr/local/adobe/flex/4.6 + +RUN apt-get install -y --no-install-recommends \ +`# C++ dependencies` \ + libboost-all-dev \ + libevent-dev \ + libssl-dev \ + qt5-default \ + qtbase5-dev \ + qtbase5-dev-tools + +RUN apt-get install -y --no-install-recommends \ +`# csharp (mono) dependencies` \ + mono-devel + +ENV SBCL_VERSION 1.5.3 +RUN \ +`# Common Lisp (sbcl) dependencies` \ + curl --version && \ + curl -o sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 -J -L https://sourceforge.net/projects/sbcl/files/sbcl/${SBCL_VERSION}/sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2/download?use_mirror=managedway# && \ + tar xjf sbcl-${SBCL_VERSION}-x86-64-linux-binary.tar.bz2 && \ + cd sbcl-${SBCL_VERSION}-x86-64-linux && \ + ./install.sh && \ + sbcl --version && \ + cd .. && \ + rm -rf sbcl* + +ENV D_VERSION 2.087.0 +ENV DMD_DEB dmd_2.087.0-0_amd64.deb +RUN \ +`# D dependencies` \ + wget -q http://downloads.dlang.org/releases/2.x/${D_VERSION}/${DMD_DEB} && \ + dpkg --install ${DMD_DEB} && \ + rm -f ${DMD_DEB} && \ + mkdir -p /usr/include/dmd/druntime/import/deimos /usr/include/dmd/druntime/import/C && \ + git clone -b 'v2.0.2+2.0.16' https://github.com/D-Programming-Deimos/libevent.git deimos-libevent-2.0 && \ + mv deimos-libevent-2.0/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ + mv deimos-libevent-2.0/C/* /usr/include/dmd/druntime/import/C/ && \ + rm -rf deimos-libevent-2.0 && \ + git clone -b 'v2.0.0+1.1.0h' https://github.com/D-Programming-Deimos/openssl.git deimos-openssl-1.1.0h && \ + mv deimos-openssl-1.1.0h/deimos/* /usr/include/dmd/druntime/import/deimos/ && \ + mv deimos-openssl-1.1.0h/C/* /usr/include/dmd/druntime/import/C/ && \ + rm -rf deimos-openssl-1.1.0h + +ENV DART_VERSION 2.4.0-1 +RUN apt-get install -y --no-install-recommends \ + `# Dart dependencies` \ + dart=$DART_VERSION +ENV PATH /usr/lib/dart/bin:$PATH + +RUN apt-get install -y --no-install-recommends \ +`# dotnet core dependencies` \ + dotnet-sdk-2.2 + +RUN apt-get install -y --no-install-recommends \ +`# Erlang dependencies` \ + erlang && \ + wget https://s3.amazonaws.com/rebar3/rebar3 -O /usr/bin/rebar3 && \ + chmod 755 /usr/bin/rebar3 && \ + rebar3 --version + +RUN apt-get install -y --no-install-recommends \ +`# GlibC dependencies` \ + libglib2.0-dev + +# golang +ENV GOLANG_VERSION 1.12.6 +ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz +ENV GOLANG_DOWNLOAD_SHA256 dbcf71a3c1ea53b8d54ef1b48c85a39a6c9a935d01fc8291ff2b92028e59913c +RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ + echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ + tar -C /usr/local -xzf golang.tar.gz && \ + ln -s /usr/local/go/bin/go /usr/local/bin && \ + rm golang.tar.gz + +RUN apt-get install -y --no-install-recommends \ +`# Haskell dependencies` \ + ghc \ + cabal-install + +RUN apt-get install -y --no-install-recommends \ +`# Haxe dependencies` \ + haxe \ + neko \ + neko-dev && \ + haxelib setup --always /usr/share/haxe/lib && \ + haxelib install --always hxcpp 2>&1 > /dev/null + +RUN apt-get install -y --no-install-recommends \ +`# Java dependencies` \ + ant \ + ant-optional \ + maven \ + openjdk-11-jdk-headless + +RUN apt-get install -y --no-install-recommends \ +`# Lua dependencies` \ + lua5.2 \ + lua5.2-dev +# https://bugs.launchpad.net/ubuntu/+source/lua5.3/+bug/1707212 +# lua5.3 does not install alternatives! +# need to update our luasocket code, lua doesn't have luaL_openlib any more + +RUN apt-get install -y --no-install-recommends \ +`# Node.js dependencies` \ + nodejs + +# Test dependencies for running puppeteer +RUN apt-get install -y --no-install-recommends \ +`# JS dependencies` \ + libxss1 + +# does not work on disco? +# RUN apt-get install -y --no-install-recommends \ +# `# OCaml dependencies` \ +# ocaml \ +# opam && \ +# opam init --yes && \ +# opam install --yes oasis + +RUN apt-get install -y --no-install-recommends \ +`# Perl dependencies` \ + libbit-vector-perl \ + libclass-accessor-class-perl \ + libcrypt-ssleay-perl \ + libio-socket-ssl-perl \ + libnet-ssleay-perl + +RUN apt-get install -y --no-install-recommends \ +`# Php dependencies` \ + php \ + php-cli \ + php-dev \ + php-json \ + php-pear \ + re2c \ + composer + +RUN apt-get install -y --no-install-recommends \ +`# Python dependencies` \ + python-all \ + python-all-dbg \ + python-all-dev \ + python-ipaddress \ + python-pip \ + python-setuptools \ + python-six \ + python-tornado \ + python-twisted \ + python-wheel \ + python-zope.interface && \ + pip install --upgrade backports.ssl_match_hostname + +RUN apt-get install -y --no-install-recommends \ +`# Python3 dependencies` \ + python3-all \ + python3-all-dbg \ + python3-all-dev \ + python3-pip \ + python3-setuptools \ + python3-six \ + python3-tornado \ + python3-twisted \ + python3-wheel \ + python3-zope.interface + +RUN apt-get install -y --no-install-recommends \ +`# Ruby dependencies` \ + ruby \ + ruby-dev \ + ruby-bundler + +# Rust dependencies +RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.35.0 -y +ENV PATH /root/.cargo/bin:$PATH + +# Swift on Linux for cross tests +# does not work on disco +# RUN cd / && \ +# wget --quiet https://swift.org/builds/swift-4.2.1-release/ubuntu1804/swift-4.2.1-RELEASE/swift-4.2.1-RELEASE-ubuntu18.04.tar.gz && \ +# tar xf swift-4.2.1-RELEASE-ubuntu18.04.tar.gz --strip-components=1 && \ +# rm swift-4.2.1-RELEASE-ubuntu18.04.tar.gz && \ +# swift --version + +# cppcheck-1.82 has a nasty cpp parser bug, so we're using something newer +# don't need this on disco, nobody uses it +# RUN apt-get install -y --no-install-recommends \ +# `# Static Code Analysis dependencies` \ +# cppcheck \ +# sloccount && \ +# pip install flake8 && \ +# wget -q "https://launchpad.net/ubuntu/+source/cppcheck/1.83-2/+build/14874703/+files/cppcheck_1.83-2_amd64.deb" && \ +# dpkg -i cppcheck_1.83-2_amd64.deb && \ +# rm cppcheck_1.83-2_amd64.deb + +# Clean up +RUN rm -rf /var/cache/apt/* && \ + rm -rf /var/lib/apt/lists/* && \ + rm -rf /tmp/* && \ + rm -rf /var/tmp/* + +ENV THRIFT_ROOT /thrift +RUN mkdir -p $THRIFT_ROOT/src +COPY Dockerfile $THRIFT_ROOT/ +WORKDIR $THRIFT_ROOT/src From ebb6b2ed68a4e0a986ce3a7797fb4ae054aa23ac Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Wed, 24 Jul 2019 08:42:06 -0700 Subject: [PATCH 342/756] THRIFT-4612: Add THeaderTransportFactory to go library Client: go This was supposed to be in 4d46c11, but was forgotten. Closes #1832. --- lib/go/thrift/header_transport.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/go/thrift/header_transport.go b/lib/go/thrift/header_transport.go index 3e684600f50..4302635d9e5 100644 --- a/lib/go/thrift/header_transport.go +++ b/lib/go/thrift/header_transport.go @@ -690,3 +690,29 @@ func (t *THeaderTransport) isFramed() bool { return true } } + +// THeaderTransportFactory is a TTransportFactory implementation to create +// THeaderTransport. +type THeaderTransportFactory struct { + // The underlying factory, could be nil. + Factory TTransportFactory +} + +// NewTHeaderTransportFactory creates a new *THeaderTransportFactory. +func NewTHeaderTransportFactory(factory TTransportFactory) TTransportFactory { + return &THeaderTransportFactory{ + Factory: factory, + } +} + +// GetTransport implements TTransportFactory. +func (f *THeaderTransportFactory) GetTransport(trans TTransport) (TTransport, error) { + if f.Factory != nil { + t, err := f.Factory.GetTransport(trans) + if err != nil { + return nil, err + } + return NewTHeaderTransport(t), nil + } + return NewTHeaderTransport(trans), nil +} From bb311a772e0a6fc142387abc3489a103662ea187 Mon Sep 17 00:00:00 2001 From: Craig Wickesser Date: Fri, 19 Jul 2019 10:21:51 -0400 Subject: [PATCH 343/756] Add pointer helpers for missing types --- lib/go/thrift/pointerize.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/go/thrift/pointerize.go b/lib/go/thrift/pointerize.go index 8d6b2c2159d..fb564ea8193 100644 --- a/lib/go/thrift/pointerize.go +++ b/lib/go/thrift/pointerize.go @@ -41,6 +41,8 @@ package thrift func Float32Ptr(v float32) *float32 { return &v } func Float64Ptr(v float64) *float64 { return &v } func IntPtr(v int) *int { return &v } +func Int8Ptr(v int8) *int8 { return &v } +func Int16Ptr(v int16) *int16 { return &v } func Int32Ptr(v int32) *int32 { return &v } func Int64Ptr(v int64) *int64 { return &v } func StringPtr(v string) *string { return &v } From 6ae2b189efbe83caa11d341e69359159a773525e Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Mon, 5 Aug 2019 04:59:08 -0700 Subject: [PATCH 344/756] THRIFT-4612: Avoid double wrapping THeaderTransport Client: go Previously the library didn't check against double wrapping, so when NewTSimpleServerN was used with both THeaderTransportFactory and THeaderProtocolFactory, inside THeaderProtocolFactory the transport was double wrapped with THeaderTransport. Worse, the transport still appeared to work, because THeaderTransport is backwards compatible with TBinaryProtocol and TCompactProtocol so the outer layer of THeaderTransport wrapper (the one directly accessible from the protocol) would assume the client doesn't support THeader and fallback. So when double wrapping happened, it appeared like everything was fine, except you couldn't get the headers from the protocol (because they were in the inner THeaderTransport, not the outer one that's directly accessible from the protocol), making it very hard to debug. This commit adds protection against such double wrapping. This closes #1839. --- lib/go/thrift/header_transport.go | 5 +++++ lib/go/thrift/header_transport_test.go | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/go/thrift/header_transport.go b/lib/go/thrift/header_transport.go index 4302635d9e5..5343ccb46bc 100644 --- a/lib/go/thrift/header_transport.go +++ b/lib/go/thrift/header_transport.go @@ -271,7 +271,12 @@ var _ TTransport = (*THeaderTransport)(nil) // Please note that THeaderTransport handles framing and zlib by itself, // so the underlying transport should be the raw socket transports (TSocket or TSSLSocket), // instead of rich transports like TZlibTransport or TFramedTransport. +// +// If trans is already a *THeaderTransport, it will be returned as is. func NewTHeaderTransport(trans TTransport) *THeaderTransport { + if ht, ok := trans.(*THeaderTransport); ok { + return ht + } return &THeaderTransport{ transport: trans, reader: bufio.NewReader(trans), diff --git a/lib/go/thrift/header_transport_test.go b/lib/go/thrift/header_transport_test.go index 94af010ec65..7462dd54757 100644 --- a/lib/go/thrift/header_transport_test.go +++ b/lib/go/thrift/header_transport_test.go @@ -106,3 +106,13 @@ func TestTHeaderHeadersReadWrite(t *testing.T) { ) } } + +func TestTHeaderTransportNoDoubleWrapping(t *testing.T) { + trans := NewTMemoryBuffer() + orig := NewTHeaderTransport(trans) + wrapped := NewTHeaderTransport(orig) + + if wrapped != orig { + t.Errorf("NewTHeaderTransport double wrapped THeaderTransport") + } +} From b1002a71fb3838039d3442420c604999551311e9 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Mon, 5 Aug 2019 13:03:02 -0700 Subject: [PATCH 345/756] THRIFT-4914: Add THeader to context for server reads Client: go This is the first part of THRIFT-4914, which handles the server reading part in the requests (client -> server direction). In TSimpleServer, when the protocol is THeaderProtocol automatically add all present headers into the context object before passing it to processor, so the processor code can access headers from the context directly by using the new helper functions added in header_context.go. This closes #1840. --- lib/go/thrift/header_context.go | 81 +++++++++++++++++++++ lib/go/thrift/header_context_test.go | 97 ++++++++++++++++++++++++++ lib/go/thrift/header_protocol.go | 5 ++ lib/go/thrift/header_transport_test.go | 12 ++++ lib/go/thrift/simple_server.go | 19 ++++- 5 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 lib/go/thrift/header_context.go create mode 100644 lib/go/thrift/header_context_test.go diff --git a/lib/go/thrift/header_context.go b/lib/go/thrift/header_context.go new file mode 100644 index 00000000000..5d9104b3acf --- /dev/null +++ b/lib/go/thrift/header_context.go @@ -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 thrift + +import ( + "context" +) + +// See https://godoc.org/context#WithValue on why do we need the unexported typedefs. +type ( + headerKey string + headerKeyList int +) + +// Values for headerKeyList. +const ( + headerKeyListRead headerKeyList = iota +) + +// SetHeader sets a header in the context. +func SetHeader(ctx context.Context, key, value string) context.Context { + return context.WithValue( + ctx, + headerKey(key), + value, + ) +} + +// GetHeader returns a value of the given header from the context. +func GetHeader(ctx context.Context, key string) (value string, ok bool) { + if v := ctx.Value(headerKey(key)); v != nil { + value, ok = v.(string) + } + return +} + +// SetReadHeaderList sets the key list of read THeaders in the context. +func SetReadHeaderList(ctx context.Context, keys []string) context.Context { + return context.WithValue( + ctx, + headerKeyListRead, + keys, + ) +} + +// GetReadHeaderList returns the key list of read THeaders from the context. +func GetReadHeaderList(ctx context.Context) []string { + if v := ctx.Value(headerKeyListRead); v != nil { + if value, ok := v.([]string); ok { + return value + } + } + return nil +} + +// AddReadTHeaderToContext adds the whole THeader headers into context. +func AddReadTHeaderToContext(ctx context.Context, headers THeaderMap) context.Context { + keys := make([]string, 0, len(headers)) + for key, value := range headers { + ctx = SetHeader(ctx, key, value) + keys = append(keys, key) + } + return SetReadHeaderList(ctx, keys) +} diff --git a/lib/go/thrift/header_context_test.go b/lib/go/thrift/header_context_test.go new file mode 100644 index 00000000000..33ac4ecd24d --- /dev/null +++ b/lib/go/thrift/header_context_test.go @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "context" + "reflect" + "testing" +) + +func TestSetGetHeader(t *testing.T) { + const ( + key = "foo" + value = "bar" + ) + ctx := context.Background() + + ctx = SetHeader(ctx, key, value) + + checkGet := func(t *testing.T, ctx context.Context) { + t.Helper() + got, ok := GetHeader(ctx, key) + if !ok { + t.Fatalf("Cannot get header %q back after setting it.", key) + } + if got != value { + t.Fatalf("Header value expected %q, got %q instead", value, got) + } + } + + checkGet(t, ctx) + + t.Run( + "NoConflicts", + func(t *testing.T) { + type otherType string + const otherValue = "bar2" + + ctx = context.WithValue(ctx, otherType(key), otherValue) + checkGet(t, ctx) + }, + ) + + t.Run( + "GetHeaderOnNonExistKey", + func(t *testing.T) { + const otherKey = "foo2" + + if _, ok := GetHeader(ctx, otherKey); ok { + t.Errorf("GetHeader returned ok on non-existing key %q", otherKey) + } + }, + ) +} + +func TestKeyList(t *testing.T) { + headers := THeaderMap{ + "key1": "value1", + "key2": "value2", + } + ctx := context.Background() + + ctx = AddReadTHeaderToContext(ctx, headers) + + got := make(THeaderMap) + keys := GetReadHeaderList(ctx) + t.Logf("keys: %+v", keys) + for _, key := range keys { + value, ok := GetHeader(ctx, key) + if ok { + got[key] = value + } else { + t.Errorf("Cannot get key %q from context", key) + } + } + + if !reflect.DeepEqual(headers, got) { + t.Errorf("Expected header map %+v, got %+v", headers, got) + } +} diff --git a/lib/go/thrift/header_protocol.go b/lib/go/thrift/header_protocol.go index 0cf48f720b7..46205b28ba6 100644 --- a/lib/go/thrift/header_protocol.go +++ b/lib/go/thrift/header_protocol.go @@ -188,6 +188,11 @@ func (p *THeaderProtocol) WriteBinary(value []byte) error { return p.protocol.WriteBinary(value) } +// ReadFrame calls underlying THeaderTransport's ReadFrame function. +func (p *THeaderProtocol) ReadFrame() error { + return p.transport.ReadFrame() +} + func (p *THeaderProtocol) ReadMessageBegin() (name string, typeID TMessageType, seqID int32, err error) { if err = p.transport.ReadFrame(); err != nil { return diff --git a/lib/go/thrift/header_transport_test.go b/lib/go/thrift/header_transport_test.go index 7462dd54757..e30476802f0 100644 --- a/lib/go/thrift/header_transport_test.go +++ b/lib/go/thrift/header_transport_test.go @@ -21,6 +21,7 @@ package thrift import ( "context" + "io" "io/ioutil" "testing" ) @@ -73,10 +74,21 @@ func TestTHeaderHeadersReadWrite(t *testing.T) { } // Read + + // Make sure multiple calls to ReadFrame is fine. + if err := reader.ReadFrame(); err != nil { + t.Errorf("reader.ReadFrame returned error: %v", err) + } + if err := reader.ReadFrame(); err != nil { + t.Errorf("reader.ReadFrame returned error: %v", err) + } read, err := ioutil.ReadAll(reader) if err != nil { t.Errorf("Read returned error: %v", err) } + if err := reader.ReadFrame(); err != nil && err != io.EOF { + t.Errorf("reader.ReadFrame returned error: %v", err) + } if string(read) != payload1+payload2 { t.Errorf( "Read content expected %q, got %q", diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go index 7db36c211eb..9155cfbfcbb 100644 --- a/lib/go/thrift/simple_server.go +++ b/lib/go/thrift/simple_server.go @@ -194,7 +194,8 @@ func (p *TSimpleServer) processRequests(client TTransport) error { // for THeaderProtocol, we must use the same protocol instance for // input and output so that the response is in the same dialect that // the server detected the request was in. - if _, ok := inputProtocol.(*THeaderProtocol); ok { + headerProtocol, ok := inputProtocol.(*THeaderProtocol) + if ok { outputProtocol = inputProtocol } else { oTrans, err := p.outputTransportFactory.GetTransport(client) @@ -222,7 +223,21 @@ func (p *TSimpleServer) processRequests(client TTransport) error { return nil } - ok, err := processor.Process(defaultCtx, inputProtocol, outputProtocol) + ctx := defaultCtx + if headerProtocol != nil { + // We need to call ReadFrame here, otherwise we won't + // get any headers on the AddReadTHeaderToContext call. + // + // ReadFrame is safe to be called multiple times so it + // won't break when it's called again later when we + // actually start to read the message. + if err := headerProtocol.ReadFrame(); err != nil { + return err + } + ctx = AddReadTHeaderToContext(defaultCtx, headerProtocol.GetReadHeaders()) + } + + ok, err := processor.Process(ctx, inputProtocol, outputProtocol) if err, ok := err.(TTransportException); ok && err.TypeId() == END_OF_FILE { return nil } else if err != nil { From 3e95c533be4489ff2cb82118e886ed93225d30fc Mon Sep 17 00:00:00 2001 From: Robert Schadek Date: Wed, 7 Aug 2019 09:04:46 +0100 Subject: [PATCH 346/756] THRIFT-4918: Avoid dlang name conflicts Client: dlang Currently Thrift generates members that are invalid for D because they are D reserved words. This change fixes the problem by appending a '_' to such names. This closes #1842. --- .../cpp/src/thrift/generate/t_d_generator.cc | 76 +++++++++++++------ 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_d_generator.cc b/compiler/cpp/src/thrift/generate/t_d_generator.cc index 56519e410f3..b8442041c98 100644 --- a/compiler/cpp/src/thrift/generate/t_d_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_d_generator.cc @@ -71,6 +71,14 @@ class t_d_generator : public t_oop_generator { } protected: + + // D reserved words are suffixed with an underscore + static string suffix_if_reserved(const string& name) { + const bool isIn = std::binary_search(std::begin(d_reserved_words), std::end(d_reserved_words), name); + string ret = isIn ? name + "_" : name; + return ret; + } + void init_generator() override { // Make output directory MKDIR(get_out_dir().c_str()); @@ -132,7 +140,7 @@ class t_d_generator : public t_oop_generator { vector::iterator c_iter; for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { this->emit_doc(*c_iter, f_consts); - string name = (*c_iter)->get_name(); + string name = suffix_if_reserved((*c_iter)->get_name()); t_type* type = (*c_iter)->get_type(); indent(f_consts) << "immutable(" << render_type_name(type) << ") " << name << ";" << endl; } @@ -148,7 +156,7 @@ class t_d_generator : public t_oop_generator { f_consts << endl; } t_type* type = (*c_iter)->get_type(); - indent(f_consts) << (*c_iter)->get_name() << " = "; + indent(f_consts) << suffix_if_reserved((*c_iter)->get_name()) << " = "; if (!is_immutable_type(type)) { f_consts << "cast(immutable(" << render_type_name(type) << ")) "; } @@ -169,7 +177,7 @@ class t_d_generator : public t_oop_generator { vector constants = tenum->get_constants(); this->emit_doc(tenum, f_types_); - string enum_name = tenum->get_name(); + string enum_name = suffix_if_reserved(tenum->get_name()); f_types_ << indent() << "enum " << enum_name << " {" << endl; indent_up(); @@ -177,7 +185,7 @@ class t_d_generator : public t_oop_generator { vector::const_iterator c_iter; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { this->emit_doc(*c_iter, f_types_); - indent(f_types_) << (*c_iter)->get_name(); + indent(f_types_) << suffix_if_reserved((*c_iter)->get_name()); f_types_ << " = " << (*c_iter)->get_value() << ","; } @@ -197,30 +205,30 @@ class t_d_generator : public t_oop_generator { } void generate_service(t_service* tservice) override { - string svc_name = tservice->get_name(); + string svc_name = suffix_if_reserved(tservice->get_name()); // Service implementation file includes string f_servicename = package_dir_ + svc_name + ".d"; ofstream_with_content_based_conditional_update f_service; f_service.open(f_servicename.c_str()); - f_service << autogen_comment() << "module " << render_package(*program_) << svc_name << ";" + f_service << autogen_comment() << "module " << suffix_if_reserved(render_package(*program_)) << svc_name << ";" << endl << endl; print_default_imports(f_service); - f_service << "import " << render_package(*get_program()) << program_name_ << "_types;" << endl; + f_service << "import " << suffix_if_reserved(render_package(*get_program())) << program_name_ << "_types;" << endl; t_service* extends_service = tservice->get_extends(); if (extends_service != NULL) { - f_service << "import " << render_package(*(extends_service->get_program())) - << extends_service->get_name() << ";" << endl; + f_service << "import " << suffix_if_reserved(render_package(*(extends_service->get_program()))) + << suffix_if_reserved(extends_service->get_name()) << ";" << endl; } f_service << endl; string extends = ""; if (tservice->get_extends() != NULL) { - extends = " : " + render_type_name(tservice->get_extends()); + extends = " : " + suffix_if_reserved(render_type_name(tservice->get_extends())); } this->emit_doc(tservice, f_service); @@ -274,7 +282,7 @@ class t_d_generator : public t_oop_generator { meta << ","; } - meta << endl << indent() << "TMethodMeta(`" << (*fn_iter)->get_name() << "`, " << endl; + meta << endl << indent() << "TMethodMeta(`" << suffix_if_reserved((*fn_iter)->get_name()) << "`, " << endl; indent_up(); indent(meta) << "["; @@ -288,7 +296,7 @@ class t_d_generator : public t_oop_generator { meta << ", "; } - meta << "TParamMeta(`" << (*p_iter)->get_name() << "`, " << (*p_iter)->get_key(); + meta << "TParamMeta(`" << suffix_if_reserved((*p_iter)->get_name()) << "`, " << (*p_iter)->get_key(); t_const_value* cv = (*p_iter)->get_value(); if (cv != NULL) { @@ -312,8 +320,8 @@ class t_d_generator : public t_oop_generator { meta << ", "; } - meta << "TExceptionMeta(`" << (*ex_iter)->get_name() << "`, " << (*ex_iter)->get_key() - << ", `" << (*ex_iter)->get_type()->get_name() << "`)"; + meta << "TExceptionMeta(`" << suffix_if_reserved((*ex_iter)->get_name()) << "`, " + << (*ex_iter)->get_key() << ", `" << (*ex_iter)->get_type()->get_name() << "`)"; } meta << "]"; @@ -364,7 +372,7 @@ class t_d_generator : public t_oop_generator { * Writes a server skeleton for the passed service to out. */ void print_server_skeleton(ostream& out, t_service* tservice) { - string svc_name = tservice->get_name(); + string svc_name = suffix_if_reserved(tservice->get_name()); out << "/*" << endl << " * This auto-generated skeleton file illustrates how to build a server. If you" << endl @@ -393,7 +401,7 @@ class t_d_generator : public t_oop_generator { indent_up(); out << indent() << "// Your implementation goes here." << endl << indent() << "writeln(\"" - << (*f_iter)->get_name() << " called\");" << endl; + << suffix_if_reserved((*f_iter)->get_name()) << " called\");" << endl; t_type* rt = (*f_iter)->get_returntype(); if (!rt->is_void()) { @@ -428,16 +436,16 @@ class t_d_generator : public t_oop_generator { const vector& members = tstruct->get_members(); if (is_exception) { - indent(out) << "class " << tstruct->get_name() << " : TException {" << endl; + indent(out) << "class " << suffix_if_reserved(tstruct->get_name()) << " : TException {" << endl; } else { - indent(out) << "struct " << tstruct->get_name() << " {" << endl; + indent(out) << "struct " << suffix_if_reserved(tstruct->get_name()) << " {" << endl; } indent_up(); // Declare all fields. vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - indent(out) << render_type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name() << ";" + indent(out) << render_type_name((*m_iter)->get_type()) << " " << suffix_if_reserved((*m_iter)->get_name()) << ";" << endl; } @@ -462,7 +470,7 @@ class t_d_generator : public t_oop_generator { } out << endl; - indent(out) << "TFieldMeta(`" << (*m_iter)->get_name() << "`, " << (*m_iter)->get_key(); + indent(out) << "TFieldMeta(`" << suffix_if_reserved((*m_iter)->get_name()) << "`, " << (*m_iter)->get_key(); t_const_value* cv = (*m_iter)->get_value(); t_field::e_req req = (*m_iter)->get_req(); @@ -488,7 +496,7 @@ class t_d_generator : public t_oop_generator { * method. */ void print_function_signature(ostream& out, t_function* fn) { - out << render_type_name(fn->get_returntype()) << " " << fn->get_name() << "("; + out << render_type_name(fn->get_returntype()) << " " << suffix_if_reserved(fn->get_name()) << "("; const vector& fields = fn->get_arglist()->get_members(); vector::const_iterator f_iter; @@ -499,7 +507,7 @@ class t_d_generator : public t_oop_generator { } else { out << ", "; } - out << render_type_name((*f_iter)->get_type(), true) << " " << (*f_iter)->get_name(); + out << render_type_name((*f_iter)->get_type(), true) << " " << suffix_if_reserved((*f_iter)->get_name()); } out << ")"; @@ -737,6 +745,30 @@ class t_d_generator : public t_oop_generator { ofstream_with_content_based_conditional_update f_header_; string package_dir_; + + protected: + static vector d_reserved_words; + +}; + +vector t_d_generator::d_reserved_words = { + // The keywords are extracted from https://dlang.org/spec/lex.html + // and sorted for use with std::binary_search + "__FILE_FULL_PATH__", "__FILE__", "__FUNCTION__", "__LINE__", "__MODULE__", + "__PRETTY_FUNCTION__", "__gshared", "__parameters", "__traits", "__vector", + "abstract", "alias", "align", "asm", "assert", "auto", "body", "bool", + "break", "byte", "case", "cast", "catch", "cdouble", "cent", "cfloat", + "char", "class", "const", "continue", "creal", "dchar", "debug", "default", + "delegate", "delete", "deprecated", "do", "double", "else", "enum", + "export", "extern", "false", "final", "finally", "float", "for", "foreach", + "foreach_reverse", "function", "goto", "idouble", "if", "ifloat", "immutable", + "import", "in", "inout", "int", "interface", "invariant", "ireal", "is", + "lazy", "long", "macro ", "mixin", "module", "new", "nothrow", "null", "out", + "override", "package", "pragma", "private", "protected", "public", "pure", + "real", "ref", "return", "scope", "shared", "short", "static", "struct", + "super", "switch", "synchronized", "template", "this", "throw", "true", "try", + "typeid", "typeof", "ubyte", "ucent", "uint", "ulong", "union", "unittest", + "ushort", "version", "void", "wchar", "while", "with" }; THRIFT_REGISTER_GENERATOR(d, "D", "") From 74d6d9d3d6400d1672f48b4acf5bc7d1260ad96d Mon Sep 17 00:00:00 2001 From: Laeeth Isharc Date: Mon, 5 Aug 2019 13:23:29 +0100 Subject: [PATCH 347/756] Initialisation of immutable data in static constructors has been deprecated. They now need to be initialised in shared static constructors. This change brings the generator for D up to date with the latest version of the compiler, but it should continue to work with older versions. --- compiler/cpp/src/thrift/generate/t_d_generator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/cpp/src/thrift/generate/t_d_generator.cc b/compiler/cpp/src/thrift/generate/t_d_generator.cc index b8442041c98..65f4b445ea5 100644 --- a/compiler/cpp/src/thrift/generate/t_d_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_d_generator.cc @@ -145,7 +145,7 @@ class t_d_generator : public t_oop_generator { indent(f_consts) << "immutable(" << render_type_name(type) << ") " << name << ";" << endl; } - f_consts << endl << "static this() {" << endl; + f_consts << endl << "shared static this() {" << endl; indent_up(); bool first = true; From 26ef904600edc810f6514605c0611b7442a4c64e Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Mon, 19 Aug 2019 00:18:22 -0700 Subject: [PATCH 348/756] THRIFT-4914: Send context THeaders for client writes Client: go This is the second part of THRIFT-4914, which handles the client writing part in the requests (client -> server direction). In TStandardClient, when the context has write headers set, and the protocol is THeaderProtocol, automatically extract all headers from the context object and set to THeaderProtocol to send over the wire. Client code can set headers into the context object by using the helper functions in header_context.go. Note that we have separated keys for read and write header key list, so that for code that's both a server and a client (example: a server that calls other upstream thrift servers), they don't automatically forward all headers to their upstream servers, and need to explicitly set which headers to forward. In order to make auto forwarding easier, also add SetForwardHeaders function to TSimpleServer, which will help the users to auto forward selected headers. This closes #1845. --- lib/go/thrift/client.go | 10 +++++++++ lib/go/thrift/header_context.go | 20 +++++++++++++++++ lib/go/thrift/header_context_test.go | 33 +++++++++++++++++++++++++++- lib/go/thrift/simple_server.go | 24 ++++++++++++++++++++ 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/lib/go/thrift/client.go b/lib/go/thrift/client.go index 28791ccd0c0..b073a952d92 100644 --- a/lib/go/thrift/client.go +++ b/lib/go/thrift/client.go @@ -24,6 +24,16 @@ func NewTStandardClient(inputProtocol, outputProtocol TProtocol) *TStandardClien } func (p *TStandardClient) Send(ctx context.Context, oprot TProtocol, seqId int32, method string, args TStruct) error { + // Set headers from context object on THeaderProtocol + if headerProt, ok := oprot.(*THeaderProtocol); ok { + headerProt.ClearWriteHeaders() + for _, key := range GetWriteHeaderList(ctx) { + if value, ok := GetHeader(ctx, key); ok { + headerProt.SetWriteHeader(key, value) + } + } + } + if err := oprot.WriteMessageBegin(method, CALL, seqId); err != nil { return err } diff --git a/lib/go/thrift/header_context.go b/lib/go/thrift/header_context.go index 5d9104b3acf..21e880d66c2 100644 --- a/lib/go/thrift/header_context.go +++ b/lib/go/thrift/header_context.go @@ -32,6 +32,7 @@ type ( // Values for headerKeyList. const ( headerKeyListRead headerKeyList = iota + headerKeyListWrite ) // SetHeader sets a header in the context. @@ -70,6 +71,25 @@ func GetReadHeaderList(ctx context.Context) []string { return nil } +// SetWriteHeaderList sets the key list of THeaders to write in the context. +func SetWriteHeaderList(ctx context.Context, keys []string) context.Context { + return context.WithValue( + ctx, + headerKeyListWrite, + keys, + ) +} + +// GetWriteHeaderList returns the key list of THeaders to write from the context. +func GetWriteHeaderList(ctx context.Context) []string { + if v := ctx.Value(headerKeyListWrite); v != nil { + if value, ok := v.([]string); ok { + return value + } + } + return nil +} + // AddReadTHeaderToContext adds the whole THeader headers into context. func AddReadTHeaderToContext(ctx context.Context, headers THeaderMap) context.Context { keys := make([]string, 0, len(headers)) diff --git a/lib/go/thrift/header_context_test.go b/lib/go/thrift/header_context_test.go index 33ac4ecd24d..a1ea2d0930b 100644 --- a/lib/go/thrift/header_context_test.go +++ b/lib/go/thrift/header_context_test.go @@ -70,7 +70,7 @@ func TestSetGetHeader(t *testing.T) { ) } -func TestKeyList(t *testing.T) { +func TestReadKeyList(t *testing.T) { headers := THeaderMap{ "key1": "value1", "key2": "value2", @@ -94,4 +94,35 @@ func TestKeyList(t *testing.T) { if !reflect.DeepEqual(headers, got) { t.Errorf("Expected header map %+v, got %+v", headers, got) } + + writtenKeys := GetWriteHeaderList(ctx) + if len(writtenKeys) > 0 { + t.Errorf( + "Expected empty GetWriteHeaderList() result, got %+v", + writtenKeys, + ) + } +} + +func TestWriteKeyList(t *testing.T) { + keys := []string{ + "key1", + "key2", + } + ctx := context.Background() + + ctx = SetWriteHeaderList(ctx, keys) + got := GetWriteHeaderList(ctx) + + if !reflect.DeepEqual(keys, got) { + t.Errorf("Expected header keys %+v, got %+v", keys, got) + } + + readKeys := GetReadHeaderList(ctx) + if len(readKeys) > 0 { + t.Errorf( + "Expected empty GetReadHeaderList() result, got %+v", + readKeys, + ) + } } diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go index 9155cfbfcbb..f8efbed914d 100644 --- a/lib/go/thrift/simple_server.go +++ b/lib/go/thrift/simple_server.go @@ -42,6 +42,9 @@ type TSimpleServer struct { outputTransportFactory TTransportFactory inputProtocolFactory TProtocolFactory outputProtocolFactory TProtocolFactory + + // Headers to auto forward in THeaderProtocol + forwardHeaders []string } func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer { @@ -125,6 +128,26 @@ func (p *TSimpleServer) Listen() error { return p.serverTransport.Listen() } +// SetForwardHeaders sets the list of header keys that will be auto forwarded +// while using THeaderProtocol. +// +// "forward" means that when the server is also a client to other upstream +// thrift servers, the context object user gets in the processor functions will +// have both read and write headers set, with write headers being forwarded. +// Users can always override the write headers by calling SetWriteHeaderList +// before calling thrift client functions. +func (p *TSimpleServer) SetForwardHeaders(headers []string) { + size := len(headers) + if size == 0 { + p.forwardHeaders = nil + return + } + + keys := make([]string, size) + copy(keys, headers) + p.forwardHeaders = keys +} + func (p *TSimpleServer) innerAccept() (int32, error) { client, err := p.serverTransport.Accept() p.mu.Lock() @@ -235,6 +258,7 @@ func (p *TSimpleServer) processRequests(client TTransport) error { return err } ctx = AddReadTHeaderToContext(defaultCtx, headerProtocol.GetReadHeaders()) + ctx = SetWriteHeaderList(ctx, p.forwardHeaders) } ok, err := processor.Process(ctx, inputProtocol, outputProtocol) From 8c7ab5f7c26a2e5d0300818d749912e562a334c4 Mon Sep 17 00:00:00 2001 From: Issacpeng Date: Tue, 20 Aug 2019 16:01:58 +0800 Subject: [PATCH 349/756] THRIFT-4933 Java build mode is incorrect in doc/install --- doc/install/README.md | 2 +- doc/install/debian.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/install/README.md b/doc/install/README.md index e48cc4a12c0..071a5d64d59 100644 --- a/doc/install/README.md +++ b/doc/install/README.md @@ -28,7 +28,7 @@ These are only required if you choose to build the libraries for the given langu * zlib (optional) * Java * Java 1.8 - * Apache Ant + * Gradle * C#: Mono 1.2.4 (and pkg-config to detect it) or Visual Studio 2005+ * Python 2.6 (including header files for extension modules) * PHP 5.0 (optionally including header files for extension modules) diff --git a/doc/install/debian.md b/doc/install/debian.md index 84f696ea2ff..2ccc37da7d3 100644 --- a/doc/install/debian.md +++ b/doc/install/debian.md @@ -18,7 +18,7 @@ Debian 7/Ubuntu 12 users need to manually install a more recent version of autom If you would like to build Apache Thrift libraries for other programming languages you may need to install additional packages. The following languages require the specified additional packages: * Java - * packages: ant + * packages: gradle * You will also need Java JDK v1.8 or higher. Type **javac** to see a list of available packages, pick the one you prefer and **apt-get install** it (e.g. default-jdk). * Ruby * ruby-full ruby-dev ruby-rspec rake rubygems bundler From 9cf37be1f1c86626ddadb277ff6cb17b2fb27da0 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Mon, 19 Aug 2019 23:41:49 +0200 Subject: [PATCH 350/756] THRIFT-4919 THttpTransport.cs (netstd) and THttpClientTransport (netcore) have bad timeout code Patch: Jens Geyer This closes #1847 --- lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs | 3 ++- lib/netstd/Thrift/Transport/Client/THttpTransport.cs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs index 949bee7ef88..8bce9e4a019 100644 --- a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs +++ b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs @@ -63,6 +63,7 @@ public THttpClientTransport(Uri u, IEnumerable certificates, public int ConnectTimeout { set { _connectTimeout = value; } + get { return _connectTimeout; } } public override bool IsOpen => true; @@ -145,7 +146,7 @@ private HttpClient CreateClient() if (_connectTimeout > 0) { - httpClient.Timeout = TimeSpan.FromSeconds(_connectTimeout); + httpClient.Timeout = TimeSpan.FromMilliseconds(_connectTimeout); } httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); diff --git a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs index 21cc409626b..c84df83ae89 100644 --- a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs @@ -145,7 +145,7 @@ private HttpClient CreateClient(IDictionary customRequestHeaders if (_connectTimeout > 0) { - httpClient.Timeout = TimeSpan.FromSeconds(_connectTimeout); + httpClient.Timeout = TimeSpan.FromMilliseconds(_connectTimeout); } httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); From 2ff4b13df4fcadf5fba48f23550b09c13390c164 Mon Sep 17 00:00:00 2001 From: pengzhouhu Date: Thu, 22 Aug 2019 15:47:37 +0800 Subject: [PATCH 351/756] THRIFT-4936 add depth limit type exception description Client: C++ Patch: pengzhouhu This closes #1852 --- lib/cpp/src/thrift/protocol/TProtocolException.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/cpp/src/thrift/protocol/TProtocolException.h b/lib/cpp/src/thrift/protocol/TProtocolException.h index 3d44365b91c..4ace9046e6a 100644 --- a/lib/cpp/src/thrift/protocol/TProtocolException.h +++ b/lib/cpp/src/thrift/protocol/TProtocolException.h @@ -84,6 +84,8 @@ class TProtocolException : public apache::thrift::TException { return "TProtocolException: Invalid version"; case NOT_IMPLEMENTED: return "TProtocolException: Not implemented"; + case DEPTH_LIMIT: + return "TProtocolException: Exceeded depth limit"; default: return "TProtocolException: (Invalid exception type)"; } From 44fcfabc37e98badfe03e1349c728842d3fdf321 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 23 Aug 2019 08:59:39 +0200 Subject: [PATCH 352/756] Pull-Request template not clear enough at step 2 --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 04188b02ddf..08051ac0224 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,7 +4,7 @@ - [ ] Did you create an [Apache Jira](https://issues.apache.org/jira/projects/THRIFT/issues/) ticket? (not required for trivial changes) -- [ ] Does your pull request title follow the pattern "THRIFT-NNNN: describe my issue"? (not required for trivial changes) +- [ ] If a ticket exists: Does your pull request title follow the pattern "THRIFT-NNNN: describe my issue"? - [ ] Did you squash your changes to a single commit? (not required, but preferred) - [ ] Did you do your best to avoid breaking changes? If one was needed, did you label the Jira ticket with "Breaking-Change"? - [ ] If your change does not involve any code, add ` [skip ci]` at the end of your pull request to free up build resources. From 81f5e10ec420ae01675b61f212939a93128438f0 Mon Sep 17 00:00:00 2001 From: Issacpeng Date: Fri, 16 Aug 2019 16:09:46 +0800 Subject: [PATCH 353/756] THRIFT-4865:Replace expired Charsets with StandardCharsets Client: Java Patch: Issacpeng This closes #1846 --- .../apache/thrift/transport/TestTByteBuffer.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/java/test/org/apache/thrift/transport/TestTByteBuffer.java b/lib/java/test/org/apache/thrift/transport/TestTByteBuffer.java index a73075b58cd..bdc0a848af2 100644 --- a/lib/java/test/org/apache/thrift/transport/TestTByteBuffer.java +++ b/lib/java/test/org/apache/thrift/transport/TestTByteBuffer.java @@ -1,7 +1,7 @@ package org.apache.thrift.transport; import junit.framework.TestCase; -import org.apache.commons.codec.Charsets; +import java.nio.charset.StandardCharsets; import org.apache.thrift.TException; import java.nio.ByteBuffer; @@ -9,25 +9,25 @@ public class TestTByteBuffer extends TestCase { public void testReadWrite() throws Exception { final TByteBuffer byteBuffer = new TByteBuffer(ByteBuffer.allocate(16)); - byteBuffer.write("Hello World".getBytes(Charsets.UTF_8)); - assertEquals("Hello World", new String(byteBuffer.flip().toByteArray(), Charsets.UTF_8)); + byteBuffer.write("Hello World".getBytes(StandardCharsets.UTF_8)); + assertEquals("Hello World", new String(byteBuffer.flip().toByteArray(), StandardCharsets.UTF_8)); } public void testReuseReadWrite() throws Exception { final TByteBuffer byteBuffer = new TByteBuffer(ByteBuffer.allocate(16)); - byteBuffer.write("Hello World".getBytes(Charsets.UTF_8)); - assertEquals("Hello World", new String(byteBuffer.flip().toByteArray(), Charsets.UTF_8)); + byteBuffer.write("Hello World".getBytes(StandardCharsets.UTF_8)); + assertEquals("Hello World", new String(byteBuffer.flip().toByteArray(), StandardCharsets.UTF_8)); byteBuffer.clear(); - byteBuffer.write("Goodbye Horses".getBytes(Charsets.UTF_8)); - assertEquals("Goodbye Horses", new String(byteBuffer.flip().toByteArray(), Charsets.UTF_8)); + byteBuffer.write("Goodbye Horses".getBytes(StandardCharsets.UTF_8)); + assertEquals("Goodbye Horses", new String(byteBuffer.flip().toByteArray(), StandardCharsets.UTF_8)); } public void testOverflow() throws Exception { final TByteBuffer byteBuffer = new TByteBuffer(ByteBuffer.allocate(4)); try { - byteBuffer.write("Hello World".getBytes(Charsets.UTF_8)); + byteBuffer.write("Hello World".getBytes(StandardCharsets.UTF_8)); fail("Expected write operation to fail with TTransportException"); } catch (TTransportException e) { assertEquals("Not enough room in output buffer", e.getMessage()); From 693e19cf485cf22d32466d3478aaecbfb07010be Mon Sep 17 00:00:00 2001 From: Alex-Rud Date: Tue, 30 Jul 2019 14:51:56 +0300 Subject: [PATCH 354/756] THRIFT-4939 TThriftListImpl.Sort() does not use comparer Client: Delphi Patch: Alex-Rud --- lib/delphi/src/Thrift.Collections.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/delphi/src/Thrift.Collections.pas b/lib/delphi/src/Thrift.Collections.pas index 2e137247e92..3b56fe20564 100644 --- a/lib/delphi/src/Thrift.Collections.pas +++ b/lib/delphi/src/Thrift.Collections.pas @@ -639,7 +639,7 @@ procedure TThriftListImpl.Sort; procedure TThriftListImpl.Sort(const AComparer: IComparer); begin - FList.Sort; + FList.Sort(AComparer); end; function TThriftListImpl.ToArray: TArray; From a4fc3d42e9a9ab54f8e1341a60e98d9be1eabc55 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 24 Aug 2019 23:10:32 +0200 Subject: [PATCH 355/756] THRIFT-4907 strong named assemblies wanted Client: netstd Patch: Jens Geyer This closes #1854 --- lib/csharp/src/Thrift.45.csproj | 9 +++++++++ lib/csharp/src/Thrift.csproj | 11 ++++++++++- lib/csharp/src/thrift.snk | Bin 0 -> 596 bytes lib/netcore/Thrift/Thrift.csproj | 2 ++ lib/netcore/Thrift/thrift.snk | Bin 0 -> 596 bytes lib/netstd/Thrift/Thrift.csproj | 3 +++ lib/netstd/Thrift/thrift.snk | Bin 0 -> 596 bytes 7 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 lib/csharp/src/thrift.snk create mode 100644 lib/netcore/Thrift/thrift.snk create mode 100644 lib/netstd/Thrift/thrift.snk diff --git a/lib/csharp/src/Thrift.45.csproj b/lib/csharp/src/Thrift.45.csproj index 4e28b25110e..146e7f8ed13 100644 --- a/lib/csharp/src/Thrift.45.csproj +++ b/lib/csharp/src/Thrift.45.csproj @@ -46,6 +46,12 @@ prompt 4 + + true + + + thrift.snk + @@ -118,6 +124,9 @@ + + + 0.7.0 Yes -1.10.81.12.6 +1.10.81.13.1 YesYesYes YesYesYes YesYesYesYes diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index 2c0609e23cc..5f9833f12c2 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -144,9 +144,9 @@ RUN apt-get install -y --no-install-recommends \ libglib2.0-dev # golang -ENV GOLANG_VERSION 1.12.6 +ENV GOLANG_VERSION 1.13.1 ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz -ENV GOLANG_DOWNLOAD_SHA256 dbcf71a3c1ea53b8d54ef1b48c85a39a6c9a935d01fc8291ff2b92028e59913c +ENV GOLANG_DOWNLOAD_SHA256 94f874037b82ea5353f4061e543681a0e79657f787437974214629af8407d124 RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ From 224b43ec7e916d2d588ad356762553fe2181aea5 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 9 Oct 2019 00:03:11 +0200 Subject: [PATCH 384/756] THRIFT-4874: Thrift 0.12.0 Source Distribution (.tar.gz) Contains Hardlinks - Extract Fails Client: Build system Patch: Jens Geyer This closes #1894 The patch contains a modified version of tar.m4. The --hard-dereference option prevents from a situation, where symlinks (used in the compiler/src subtree) get converted into hard links. --- aclocal/tar.m4 | 132 ++++++++++++++++++++++++++++++++++++ lib/perl/build-cpan-dist.sh | 2 +- lib/php/Makefile.am | 1 - 3 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 aclocal/tar.m4 diff --git a/aclocal/tar.m4 b/aclocal/tar.m4 new file mode 100644 index 00000000000..4e16b6b2c9a --- /dev/null +++ b/aclocal/tar.m4 @@ -0,0 +1,132 @@ +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004-2018 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +# +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' + +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --hard-dereference --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --hard-dereference --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf --hard-dereference - "$$tardir"' + am__tar_='tar chf --hard-dereference - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done + rm -rf conftest.dir + + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR diff --git a/lib/perl/build-cpan-dist.sh b/lib/perl/build-cpan-dist.sh index ac0ff0bc0b3..c92fd76b58b 100755 --- a/lib/perl/build-cpan-dist.sh +++ b/lib/perl/build-cpan-dist.sh @@ -52,5 +52,5 @@ cp -pr ../gen-perl . cp -pr ../gen-perl2 . perl ../tools/FixupDist.pl cd .. -tar cvzf $DISTFILE $DISTDIR +tar cvzf --hard-dereference $DISTFILE $DISTDIR rm -r $DISTDIR diff --git a/lib/php/Makefile.am b/lib/php/Makefile.am index 7fdebe102ad..ce353f0e6b3 100755 --- a/lib/php/Makefile.am +++ b/lib/php/Makefile.am @@ -140,7 +140,6 @@ EXTRA_DIST = \ src/ext/thrift_protocol/config.w32 \ src/ext/thrift_protocol/php_thrift_protocol.cpp \ src/ext/thrift_protocol/php_thrift_protocol.h \ - src/ext/thrift_protocol/run-tests.php \ src/Thrift.php \ src/TStringUtils.php \ coding_standards.md \ From 85d8162dcbfd17db3bb8232a2dbb870dd9908cc4 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 10 Oct 2019 01:33:30 +0200 Subject: [PATCH 385/756] Revert "THRIFT-4951: Remove senum from tests" This reverts commit df8ef4b489e2b84ac6dbbf895be32d6fb2415c81. The contributor confuses "deprecated" with "unsupported". Unless the feature as a whole is also removed, so essentially nothing is left to be tested. Regardless whether a particular feature is deprecated or not, removing a working test for it is NOT helpful. The only "achievement" of such efforts would be that the test coverage goes down, which is clearly not in our intention and only opens room for bugs and issues. --- test/AnnotationTest.thrift | 8 ++++++++ test/SmallTest.thrift | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/test/AnnotationTest.thrift b/test/AnnotationTest.thrift index 6238395d480..7e24e1ccbe7 100644 --- a/test/AnnotationTest.thrift +++ b/test/AnnotationTest.thrift @@ -49,6 +49,14 @@ enum weekdays { SATURDAY ( weekend = "yes" ) } (foo.bar="baz") +/* Note that annotations on senum values are not supported. */ +senum seasons { + "Spring", + "Summer", + "Fall", + "Winter" +} ( foo = "bar" ) + struct ostr_default { 1: i32 bar; } diff --git a/test/SmallTest.thrift b/test/SmallTest.thrift index 891bd6a0c67..d0821c7ffb0 100644 --- a/test/SmallTest.thrift +++ b/test/SmallTest.thrift @@ -24,6 +24,12 @@ struct Goodbyez { 1: i32 val = 325; } +senum Thinger { + "ASDFKJ", + "r32)*F#@", + "ASDFLJASDF" +} + struct BoolPasser { 1: bool value = 1 } @@ -47,6 +53,7 @@ exception Goodbye { } service SmallService { + Thinger testThinger(1:Thinger bootz), Hello testMe(1:i32 hello=64, 2: Hello wonk) throws (1: Goodbye g), void testVoid() throws (1: Goodbye g), i32 testI32(1:i32 boo) From ab89b8b40ee593e344dafb6192fd6ef3b1357c8b Mon Sep 17 00:00:00 2001 From: wineandcheeze Date: Thu, 10 Oct 2019 13:50:50 +0200 Subject: [PATCH 386/756] THRIFT-2530: Fix TIOStreamTransport#isOpen isOpen should return false when close is called. Client: java This closes #1878. --- CHANGES.md | 1 + .../src/org/apache/thrift/transport/TIOStreamTransport.java | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9d13d9501c6..35e8ccba084 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,7 @@ - [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - java: class org.apache.thrift.ShortStack is no longer public - [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - java: change return type signature of 'process' methods - [THRIFT-4805](https://issues.apache.org/jira/browse/THRIFT-4805) - java: replaced TSaslTransportException with TTransportException +- [THRIFT-2530](https://issues.apache.org/jira/browse/THRIFT-2530) - java: TIOStreamTransport's "isOpen" now returns false after "close" is called - [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - js: now uses node-int64 for 64 bit integer constants - [THRIFT-4841](https://issues.apache.org/jira/browse/THRIFT-4841) - delphi: old THTTPTransport is now TMsxmlHTTPTransport - [THRIFT-4536](https://issues.apache.org/jira/browse/THRIFT-4536) - rust: convert from try-from crate to rust stable (1.34+), re-export ordered-float diff --git a/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java b/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java index 93b051f3193..2d31f392f43 100644 --- a/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java @@ -79,13 +79,11 @@ public TIOStreamTransport(InputStream is, OutputStream os) { } /** - * The streams must already be open at construction time, so this should - * always return true. * - * @return true + * @return false after close is called. */ public boolean isOpen() { - return true; + return inputStream_ != null && outputStream_ != null; } /** From a899fe84123b6511d8076645048f70592dfcac96 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 10 Oct 2019 23:17:04 +0200 Subject: [PATCH 387/756] THRIFT-4973 Add deprecation messages for csharp and netcore Client: csharp, netcore Patch: Jens Geyer This closes #1895 --- compiler/cpp/src/thrift/generate/t_csharp_generator.cc | 2 ++ compiler/cpp/src/thrift/generate/t_netcore_generator.cc | 2 ++ compiler/cpp/src/thrift/parse/t_program.h | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc index e4d99b2cc1a..a6ece8083a8 100644 --- a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc @@ -87,6 +87,8 @@ class t_csharp_generator : public t_oop_generator { } } + pwarning(1, "The 'csharp' target is deprecated. Consider using 'netstd' instead.\n"); + out_dir_base_ = "gen-csharp"; } void init_generator() override; diff --git a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc b/compiler/cpp/src/thrift/generate/t_netcore_generator.cc index 1a5c3842f2d..ed6a365ac15 100644 --- a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netcore_generator.cc @@ -91,6 +91,8 @@ t_netcore_generator::t_netcore_generator(t_program* program, const map Date: Fri, 11 Oct 2019 00:42:29 +0200 Subject: [PATCH 388/756] Version 0.13.0 --- CHANGES.md | 271 +++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 6 ++ doap.rdf | 5 + 3 files changed, 282 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 35e8ccba084..72c7eb8faa3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,8 @@ ### New Languages +- (none) + ### Deprecated Languages - [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - CSharp and Netcore targets are deprecated and will be removed with the next release - use NetStd instead. @@ -33,6 +35,275 @@ ### Known Issues (Blocker or Critical) +- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++: library don't work with HTTP (csharp server, cpp client; need cross test enhancement) + +### As3 + +- [THRIFT-4784](https://issues.apache.org/jira/browse/THRIFT-4784) - Thrift should throw when skipping over unexpected data + +### Build Process + +- [THRIFT-2333](https://issues.apache.org/jira/browse/THRIFT-2333) - RPMBUILD: Abort build if user did not disable ruby but ruby build will fail later on +- [THRIFT-4689](https://issues.apache.org/jira/browse/THRIFT-4689) - Pull changes from 0.12.0 release branch into master +- [THRIFT-4690](https://issues.apache.org/jira/browse/THRIFT-4690) - Update dlang deimos for OpenSSL 1.1 (use 1.1.0h tagged release instead of master) +- [THRIFT-4694](https://issues.apache.org/jira/browse/THRIFT-4694) - Upgrade Java to Java 1.8 +- [THRIFT-4716](https://issues.apache.org/jira/browse/THRIFT-4716) - Create a version alignment tool to make releases easier +- [THRIFT-4760](https://issues.apache.org/jira/browse/THRIFT-4760) - Install pkgconfig when using cmake +- [THRIFT-4769](https://issues.apache.org/jira/browse/THRIFT-4769) - Change NuGet package to use netstd artifact +- [THRIFT-4811](https://issues.apache.org/jira/browse/THRIFT-4811) - Add cmake config module +- [THRIFT-4855](https://issues.apache.org/jira/browse/THRIFT-4855) - go CI fails with "cannot find package "golang.org/x/tools/go/packages" in any of ..." +- [THRIFT-4864](https://issues.apache.org/jira/browse/THRIFT-4864) - CI fails at netstd +- [THRIFT-4874](https://issues.apache.org/jira/browse/THRIFT-4874) - Thrift 0.12.0 Source Distribution (.tar.gz) Contains Hardlinks - Extract Fails +- [THRIFT-4896](https://issues.apache.org/jira/browse/THRIFT-4896) - cpp and c_glib include paths are added to source files when building +- [THRIFT-4966](https://issues.apache.org/jira/browse/THRIFT-4966) - Git ignore files generated by the build + +### C glib + +- [THRIFT-4842](https://issues.apache.org/jira/browse/THRIFT-4842) - Multiplexed protocol has a memory leak in set c_glib +- [THRIFT-4878](https://issues.apache.org/jira/browse/THRIFT-4878) - c_glib ThriftSocket support for unix domain sockets +- [THRIFT-4950](https://issues.apache.org/jira/browse/THRIFT-4950) - fix bind print error and Macro call errors thrift_server_socket + +### C# + +- [THRIFT-3587](https://issues.apache.org/jira/browse/THRIFT-3587) - C# TTLSSocket does not use timeout for opening the socket +- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types +- [THRIFT-4684](https://issues.apache.org/jira/browse/THRIFT-4684) - Missing namespace and un-used private fields in WCF fault classes when enable WCF in C# code generation +- [THRIFT-4715](https://issues.apache.org/jira/browse/THRIFT-4715) - C# union "data" should be strongly-typed +- [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - Consolidate C# and netcore into new netstd language target (and finally deprecate both C# and netcore bindings) +- [THRIFT-4741](https://issues.apache.org/jira/browse/THRIFT-4741) - Missing "inner" argument from one CTOR +- [THRIFT-4769](https://issues.apache.org/jira/browse/THRIFT-4769) - Change NuGet package to use netstd artifact +- [THRIFT-4859](https://issues.apache.org/jira/browse/THRIFT-4859) - Enables changing 'UserAgent' +- [THRIFT-4907](https://issues.apache.org/jira/browse/THRIFT-4907) - strong named assemblies wanted + +### C++ + +- [THRIFT-4384](https://issues.apache.org/jira/browse/THRIFT-4384) - Using a concurrent client with cpp async is not safe. +- [THRIFT-4441](https://issues.apache.org/jira/browse/THRIFT-4441) - C++: support building lib without Boost +- [THRIFT-4487](https://issues.apache.org/jira/browse/THRIFT-4487) - gettimeofday: windows implementation not quoting source, applying license to foreign code +- [THRIFT-4593](https://issues.apache.org/jira/browse/THRIFT-4593) - Unit Tests failing on Alpine Linux due to non-portable mutex initializers +- [THRIFT-4678](https://issues.apache.org/jira/browse/THRIFT-4678) - add noexcept cpp generator option +- [THRIFT-4720](https://issues.apache.org/jira/browse/THRIFT-4720) - Drop support for C++03/C++98 and begin refactoring +- [THRIFT-4730](https://issues.apache.org/jira/browse/THRIFT-4730) - Remove pthread and boost::thread library support and use std::thread for C++11 +- [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735) - Remove C++ Qt4 support (leave Qt5) - Qt4 LTS ended in 2014 +- [THRIFT-4739](https://issues.apache.org/jira/browse/THRIFT-4739) - Good old concurrency_test failing on windows builds again with some regularity +- [THRIFT-4740](https://issues.apache.org/jira/browse/THRIFT-4740) - Use std::chrono for timeout and remove old structures. +- [THRIFT-4762](https://issues.apache.org/jira/browse/THRIFT-4762) - C++: Applied some C++11 refactorings to the runtime library and compiler +- [THRIFT-4776](https://issues.apache.org/jira/browse/THRIFT-4776) - Modernize c++11 code by clang-tidy +- [THRIFT-4830](https://issues.apache.org/jira/browse/THRIFT-4830) - Add to_string function for enum in C++ file generate +- [THRIFT-4861](https://issues.apache.org/jira/browse/THRIFT-4861) - Fix use of deprecated boost endian header; move to minimum boost 1.56.0 +- [THRIFT-4936](https://issues.apache.org/jira/browse/THRIFT-4936) - add depth limit type exception description +- [THRIFT-4962](https://issues.apache.org/jira/browse/THRIFT-4962) - Deadlock in TimerManager::stop + +### cocoa + +- [THRIFT-4719](https://issues.apache.org/jira/browse/THRIFT-4719) - Remove cocoa language support + +## Compiler (General) + +- [THRIFT-4743](https://issues.apache.org/jira/browse/THRIFT-4743) - Remove the compiler plug-in mode + +### contributed + +- [THRIFT-4897](https://issues.apache.org/jira/browse/THRIFT-4897) - UT of thrift-maven-plugin failed + +## D language + +- [THRIFT-4690](https://issues.apache.org/jira/browse/THRIFT-4690) - Update dlang deimos for OpenSSL 1.1 (use 1.1.0h tagged release instead of master) +- [THRIFT-4724](https://issues.apache.org/jira/browse/THRIFT-4724) - dlang dub.json dependency for openssl is too restrictive +- [THRIFT-4918](https://issues.apache.org/jira/browse/THRIFT-4918) - dlang name conflict + +### dart + +- [THRIFT-4654](https://issues.apache.org/jira/browse/THRIFT-4654) - Thrift Dart port is not compatible with Dart 2 + +### Delphi + +- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types +- [THRIFT-4841](https://issues.apache.org/jira/browse/THRIFT-4841) - THTTPTransport relies on activeX component +- [THRIFT-4843](https://issues.apache.org/jira/browse/THRIFT-4843) - http:// and https:// schemes are switched in test client +- [THRIFT-4862](https://issues.apache.org/jira/browse/THRIFT-4862) - better ToString() support for enums and container types +- [THRIFT-4863](https://issues.apache.org/jira/browse/THRIFT-4863) - better indication of WinHTTP errors +- [THRIFT-4881](https://issues.apache.org/jira/browse/THRIFT-4881) - Allow TLS1.1 and TLS1.2 over WinHTTP even when not configured as systemwide default +- [THRIFT-4882](https://issues.apache.org/jira/browse/THRIFT-4882) - Autodetect proxy settings with WinHTTP +- [THRIFT-4884](https://issues.apache.org/jira/browse/THRIFT-4884) - Add serialisation performance test for Delphi +- [THRIFT-4886](https://issues.apache.org/jira/browse/THRIFT-4886) - More detailed error information for WinHTTP transport +- [THRIFT-4894](https://issues.apache.org/jira/browse/THRIFT-4894) - Enable automatic content encoding handling for gzip,deflate in the WinHTTP client +- [THRIFT-4939](https://issues.apache.org/jira/browse/THRIFT-4939) - TThriftListImpl.Sort() does not use comparer +- [THRIFT-4944](https://issues.apache.org/jira/browse/THRIFT-4944) - Field IDs > 255 fail with compact protocol + +### Documentation + +- [THRIFT-4697](https://issues.apache.org/jira/browse/THRIFT-4697) - Create updated release procedures +- [THRIFT-4808](https://issues.apache.org/jira/browse/THRIFT-4808) - Update LANGUAGES.md on master to reflect master +- [THRIFT-4933](https://issues.apache.org/jira/browse/THRIFT-4933) - Incorrect description in the 0.12.0 version of the documentation + +### Erlang + +- [THRIFT-4583](https://issues.apache.org/jira/browse/THRIFT-4583) - Support rebar3 for erlang builds +- [THRIFT-4744](https://issues.apache.org/jira/browse/THRIFT-4744) - Erlang help intendation not aligned + +### Go + +- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types +- [THRIFT-4612](https://issues.apache.org/jira/browse/THRIFT-4612) - Add THeader for Go +- [THRIFT-4747](https://issues.apache.org/jira/browse/THRIFT-4747) - The 'omitempty' tag should not be appended to optional fields that have a default value +- [THRIFT-4797](https://issues.apache.org/jira/browse/THRIFT-4797) - Generated Go code produces name collisions on imports +- [THRIFT-4908](https://issues.apache.org/jira/browse/THRIFT-4908) - reader&writer in golang's TBinaryProtocol is not necessary and misleading + +### haskell + +- [THRIFT-4834](https://issues.apache.org/jira/browse/THRIFT-4834) - CI error at Haskell: Failed to load interface for `Network' +- [THRIFT-4955](https://issues.apache.org/jira/browse/THRIFT-4955) - Haskell test broken due to extension to CompactProtoTestStruct +- [THRIFT-4956](https://issues.apache.org/jira/browse/THRIFT-4956) - DebugProtoTest_Main.hs: Invalid ThriftType 128 + +### haxe + +- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types +- [THRIFT-4812](https://issues.apache.org/jira/browse/THRIFT-4812) - haxelib readme still points to old ASF git repo + +### HTML + +- [THRIFT-4763](https://issues.apache.org/jira/browse/THRIFT-4763) - HTML compiler produces invalid HTML document + +### Java + +- [THRIFT-2530](https://issues.apache.org/jira/browse/THRIFT-2530) - TIOStreamTransport's isOpen() always be true even if close() was called. +- [THRIFT-4368](https://issues.apache.org/jira/browse/THRIFT-4368) - Guaranteed NPE in TBaseAsyncProcessor.java +- [THRIFT-4469](https://issues.apache.org/jira/browse/THRIFT-4469) - isServing is not thread safe +- [THRIFT-4481](https://issues.apache.org/jira/browse/THRIFT-4481) - TBinaryProtocol.writeMessageEnd isn't throwable exception +- [THRIFT-4695](https://issues.apache.org/jira/browse/THRIFT-4695) - Pre-Size Java Collections in Union +- [THRIFT-4696](https://issues.apache.org/jira/browse/THRIFT-4696) - NonBlocking Server: Use case-switch Statement Instead of if-else Clauses +- [THRIFT-4702](https://issues.apache.org/jira/browse/THRIFT-4702) - Improve AutoExpandingBuffer +- [THRIFT-4704](https://issues.apache.org/jira/browse/THRIFT-4704) - Streamline TDeserializer Implementation +- [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - Use StandardCharset UTF-8 +- [THRIFT-4711](https://issues.apache.org/jira/browse/THRIFT-4711) - Improve Immutable None Type Instantiation +- [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - Improve Performance of ShortStack +- [THRIFT-4713](https://issues.apache.org/jira/browse/THRIFT-4713) - Review of TBaseHelper.java +- [THRIFT-4714](https://issues.apache.org/jira/browse/THRIFT-4714) - Java TFramedTransport calls write twice for each flush +- [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - Change Return Type Signature of Process Methods +- [THRIFT-4726](https://issues.apache.org/jira/browse/THRIFT-4726) - Remove SLF4J Logging Guards +- [THRIFT-4748](https://issues.apache.org/jira/browse/THRIFT-4748) - Add Jitpack support +- [THRIFT-4766](https://issues.apache.org/jira/browse/THRIFT-4766) - JDK9+ fails on missing annotations +- [THRIFT-4773](https://issues.apache.org/jira/browse/THRIFT-4773) - TSaslTransport should relay underlying TTransportException to TSaslTransportException +- [THRIFT-4805](https://issues.apache.org/jira/browse/THRIFT-4805) - Suppress excessive logging of SASL TTransportExceptions in case of END_OF_FILE +- [THRIFT-4849](https://issues.apache.org/jira/browse/THRIFT-4849) - Do not Ignore InterruptedException +- [THRIFT-4851](https://issues.apache.org/jira/browse/THRIFT-4851) - Remove All Calls To printStackTrace +- [THRIFT-4857](https://issues.apache.org/jira/browse/THRIFT-4857) - Java field hash code implementation inconsistent with equals. +- [THRIFT-4858](https://issues.apache.org/jira/browse/THRIFT-4858) - Java TThreadPoolServer: confusing error message on closed socket +- [THRIFT-4865](https://issues.apache.org/jira/browse/THRIFT-4865) - warning: [deprecation] UTF_8 in Charsets has been deprecated +- [THRIFT-4899](https://issues.apache.org/jira/browse/THRIFT-4899) - Generated TypeScript declarations incorrectly references types when there is more than 1 include +- [THRIFT-4945](https://issues.apache.org/jira/browse/THRIFT-4945) - Log output mode is not standardized +- [THRIFT-4957](https://issues.apache.org/jira/browse/THRIFT-4957) - testSanePartsOfCompactProtoTestStruct FAILED + +### JavaScript + +- [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - JS code generators not handling int64 type properly for constants and for TypeScript type mappings +- [THRIFT-4728](https://issues.apache.org/jira/browse/THRIFT-4728) - Cleanup for the double rendering test in JS +- [THRIFT-4737](https://issues.apache.org/jira/browse/THRIFT-4737) - thrift.js does not use customHeaders in jqRequest +- [THRIFT-4745](https://issues.apache.org/jira/browse/THRIFT-4745) - warning C4305: 'initializing' : truncation from '"__int64' to 'long' +- [THRIFT-4757](https://issues.apache.org/jira/browse/THRIFT-4757) - grunt-shell-spawn drags in sync-exec which has a security notice + +### netcore + +- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types +- [THRIFT-4722](https://issues.apache.org/jira/browse/THRIFT-4722) - Netcore union "data" should be strongly-typed +- [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - Consolidate C# and netcore into new netstd language target (and finally deprecate both C# and netcore bindings) +- [THRIFT-4742](https://issues.apache.org/jira/browse/THRIFT-4742) - Typo "cannot read from null input stream" on write +- [THRIFT-4769](https://issues.apache.org/jira/browse/THRIFT-4769) - Change NuGet package to use netstd artifact +- [THRIFT-4919](https://issues.apache.org/jira/browse/THRIFT-4919) - THttpTransport.cs (netstd) and THttpClientTransport (netcore) have bad timeout code + +### netstd + +- [THRIFT-4768](https://issues.apache.org/jira/browse/THRIFT-4768) - Remove "nullable" option from the code base (netstd ONLY) +- [THRIFT-4772](https://issues.apache.org/jira/browse/THRIFT-4772) - fully enable server-side usage of framed/buffered transports +- [THRIFT-4813](https://issues.apache.org/jira/browse/THRIFT-4813) - NamedPipes may not work in all cases +- [THRIFT-4816](https://issues.apache.org/jira/browse/THRIFT-4816) - JSONTransports Context.WriteAsync/ReadAsync are badly named +- [THRIFT-4817](https://issues.apache.org/jira/browse/THRIFT-4817) - Add string CTOR to TTlsSocketTransport +- [THRIFT-4818](https://issues.apache.org/jira/browse/THRIFT-4818) - Test client should use cancellation token +- [THRIFT-4821](https://issues.apache.org/jira/browse/THRIFT-4821) - Normalize TServerSocketTransport constructors in netstd +- [THRIFT-4822](https://issues.apache.org/jira/browse/THRIFT-4822) - Refactor bool CTOR flags into enum type +- [THRIFT-4824](https://issues.apache.org/jira/browse/THRIFT-4824) - Logger deprecation warnings in tutorial +- [THRIFT-4825](https://issues.apache.org/jira/browse/THRIFT-4825) - Align TTlsServerSocketTransport constructors with TServerSocketTransport - Breaking Change +- [THRIFT-4829](https://issues.apache.org/jira/browse/THRIFT-4829) - HTTP server transport lacks TransportFactory arguments +- [THRIFT-4831](https://issues.apache.org/jira/browse/THRIFT-4831) - interface ITProtocolFactory should be class TProtocolFactory again +- [THRIFT-4832](https://issues.apache.org/jira/browse/THRIFT-4832) - superfluous backing field causes CS0169 "field never used" +- [THRIFT-4839](https://issues.apache.org/jira/browse/THRIFT-4839) - Remove embedded buffering/framed options from TCP transports +- [THRIFT-4840](https://issues.apache.org/jira/browse/THRIFT-4840) - Update the README in the netstd tutorial to include references to the new buffering arguments +- [THRIFT-4848](https://issues.apache.org/jira/browse/THRIFT-4848) - Add ability to set Content-Type,Accept headers in HTTP client +- [THRIFT-4853](https://issues.apache.org/jira/browse/THRIFT-4853) - TServerFramedTransport is now obsolete and can be removed +- [THRIFT-4854](https://issues.apache.org/jira/browse/THRIFT-4854) - oneway calls do not work over HTTP +- [THRIFT-4860](https://issues.apache.org/jira/browse/THRIFT-4860) - Allow changing "User-Agent" +- [THRIFT-4879](https://issues.apache.org/jira/browse/THRIFT-4879) - general performance improvements for netstd library +- [THRIFT-4891](https://issues.apache.org/jira/browse/THRIFT-4891) - Align HTTP test client with all other variants +- [THRIFT-4893](https://issues.apache.org/jira/browse/THRIFT-4893) - Enable automatic content encoding handling for gzip,deflate in the HTTP client +- [THRIFT-4898](https://issues.apache.org/jira/browse/THRIFT-4898) - Pipe write operations across a network are limited to 65,535 bytes per write. +- [THRIFT-4919](https://issues.apache.org/jira/browse/THRIFT-4919) - THttpTransport.cs (netstd) and THttpClientTransport (netcore) have bad timeout code + +### node.js + +- [THRIFT-3060](https://issues.apache.org/jira/browse/THRIFT-3060) - Node.js client retry logic doesn't flush offline queue on reconnect +- [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - JS code generators not handling int64 type properly for constants and for TypeScript type mappings +- [THRIFT-4738](https://issues.apache.org/jira/browse/THRIFT-4738) - Generated typescript type definition files are incorrect +- [THRIFT-4771](https://issues.apache.org/jira/browse/THRIFT-4771) - THeader for node.js +- [THRIFT-4809](https://issues.apache.org/jira/browse/THRIFT-4809) - Javascript episodic code generation +- [THRIFT-4844](https://issues.apache.org/jira/browse/THRIFT-4844) - createConnection ignores connect_timeout option + +### perl + +- [THRIFT-4691](https://issues.apache.org/jira/browse/THRIFT-4691) - The perl CPAN module contains no tests + +### PHP + +- [THRIFT-4751](https://issues.apache.org/jira/browse/THRIFT-4751) - Missing imports in TProtocol (phpdoc related only) +- [THRIFT-4794](https://issues.apache.org/jira/browse/THRIFT-4794) - Finish adding json protocol to the php cross test +- [THRIFT-4807](https://issues.apache.org/jira/browse/THRIFT-4807) - PHP extension segfaults if reference is used in input +- [THRIFT-4845](https://issues.apache.org/jira/browse/THRIFT-4845) - PHP's TCurlClient ignores timeout values smaller that 1 second + +### python + +- [THRIFT-1549](https://issues.apache.org/jira/browse/THRIFT-1549) - Python TSSLSocket: Shutdown cleanly +- [THRIFT-4733](https://issues.apache.org/jira/browse/THRIFT-4733) - Address already in use with python unit test +- [THRIFT-4767](https://issues.apache.org/jira/browse/THRIFT-4767) - support tcp keepalive in python +- [THRIFT-4778](https://issues.apache.org/jira/browse/THRIFT-4778) - Python protocol factories do not derive from TProtocolFactory +- [THRIFT-4779](https://issues.apache.org/jira/browse/THRIFT-4779) - Python, Java TMultiplexedProcessor do not raise TProtocolException +- [THRIFT-4780](https://issues.apache.org/jira/browse/THRIFT-4780) - TMultiplexedProcessor is not fully tested or implemented in Python +- [THRIFT-4783](https://issues.apache.org/jira/browse/THRIFT-4783) - Thrift should throw when skipping over unexpected data +- [THRIFT-4798](https://issues.apache.org/jira/browse/THRIFT-4798) - Fix python THttpServer to honor correct oneway reply semantics +- [THRIFT-4892](https://issues.apache.org/jira/browse/THRIFT-4892) - SASL data type exception for PLAIN +- [THRIFT-4920](https://issues.apache.org/jira/browse/THRIFT-4920) - Binary constants emit non-binary Python literals + +### ruby + +- [THRIFT-4721](https://issues.apache.org/jira/browse/THRIFT-4721) - Installing the ruby gem on systems without make fails in the build_ext task. +- [THRIFT-4971](https://issues.apache.org/jira/browse/THRIFT-4971) - Fix lib/rb/spec/union_spec.rb so that CI succeeds + +### rust + +- [THRIFT-4953](https://issues.apache.org/jira/browse/THRIFT-4953) - Unspecified Field Identifier Creates Non Compiling Rust Code +- [THRIFT-4960](https://issues.apache.org/jira/browse/THRIFT-4960) - Bare Trait Warnings + +### Swift + +- [THRIFT-4902](https://issues.apache.org/jira/browse/THRIFT-4902) - Swift compatibility with Swift 4.2, 5.0 and 5.1 + +### Test suite + +- [THRIFT-4301](https://issues.apache.org/jira/browse/THRIFT-4301) - configuring --without-python and --without-py3 still invokes py3 tests in make cross +- [THRIFT-4405](https://issues.apache.org/jira/browse/THRIFT-4405) - Incorrect handling of sequence numbers that wrap to negative +- [THRIFT-4794](https://issues.apache.org/jira/browse/THRIFT-4794) - Finish adding json protocol to the php cross test +- [THRIFT-4969](https://issues.apache.org/jira/browse/THRIFT-4969) - PHP test doesn't check the code generation with php:classmap + +### Tutorial + +- [THRIFT-4426](https://issues.apache.org/jira/browse/THRIFT-4426) - repository should not include symbolic links +- [THRIFT-4965](https://issues.apache.org/jira/browse/THRIFT-4965) - Perl tutorial server doesn't work due to the lack of use statement +- [THRIFT-4967](https://issues.apache.org/jira/browse/THRIFT-4967) - Node.js tutorial server fails if the zip function invoked +- [THRIFT-4968](https://issues.apache.org/jira/browse/THRIFT-4968) - Makefile.am in the Ruby tutorial refers to Python directory +- [THRIFT-4970](https://issues.apache.org/jira/browse/THRIFT-4970) - PHP tutorial doesn't work with Thrift v0.12.0+ + +### Typescript + +- [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - JS code generators not handling int64 type properly for constants and for TypeScript type mappings ## 0.12.0 diff --git a/debian/changelog b/debian/changelog index 69b5f208383..f91921a5592 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +thrift (0.13.0) stable; urgency=low + + * update to 0.13.0 + + -- Apache Thrift Developers Wed, 11 Nov 2019 12:00:00 -0500 + thrift (0.12.0) stable; urgency=low * update to 0.12.0 diff --git a/doap.rdf b/doap.rdf index 50b3491d658..77b9113247a 100755 --- a/doap.rdf +++ b/doap.rdf @@ -57,6 +57,11 @@ + + Apache Thrift + 2019-10-11 + 0.13.0 + Apache Thrift 2018-12-28 From 0f14e2f3f65ddab76bfae28b3343ba12157d93f5 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Tue, 15 Oct 2019 11:25:10 +0200 Subject: [PATCH 389/756] THRIFT-4977: Allow loading OpenSSL certificates from memory Client: cpp This closes #1860. --- lib/cpp/src/thrift/transport/TSSLSocket.cpp | 77 ++++++ lib/cpp/src/thrift/transport/TSSLSocket.h | 3 + lib/cpp/test/CMakeLists.txt | 11 + lib/cpp/test/Makefile.am | 12 + lib/cpp/test/SecurityFromBufferTest.cpp | 253 ++++++++++++++++++++ 5 files changed, 356 insertions(+) create mode 100644 lib/cpp/test/SecurityFromBufferTest.cpp diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.cpp b/lib/cpp/src/thrift/transport/TSSLSocket.cpp index b413002f1f0..64f08ddf19a 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.cpp +++ b/lib/cpp/src/thrift/transport/TSSLSocket.cpp @@ -957,6 +957,28 @@ void TSSLSocketFactory::loadCertificate(const char* path, const char* format) { } } +void TSSLSocketFactory::loadCertificateFromBuffer(const char* aCertificate, const char* format) { + if (aCertificate == nullptr || format == nullptr) { + throw TTransportException(TTransportException::BAD_ARGS, + "loadCertificate: either or is NULL"); + } + if (strcmp(format, "PEM") == 0) { + BIO* mem = BIO_new(BIO_s_mem()); + BIO_puts(mem, aCertificate); + X509* cert = PEM_read_bio_X509(mem, NULL, 0, NULL); + BIO_free(mem); + + if (SSL_CTX_use_certificate(ctx_->get(), cert) == 0) { + int errno_copy = THRIFT_GET_SOCKET_ERROR; + string errors; + buildErrors(errors, errno_copy); + throw TSSLException("SSL_CTX_use_certificate: " + errors); + } + } else { + throw TSSLException("Unsupported certificate format: " + string(format)); + } +} + void TSSLSocketFactory::loadPrivateKey(const char* path, const char* format) { if (path == nullptr || format == nullptr) { throw TTransportException(TTransportException::BAD_ARGS, @@ -972,6 +994,28 @@ void TSSLSocketFactory::loadPrivateKey(const char* path, const char* format) { } } +void TSSLSocketFactory::loadPrivateKeyFromBuffer(const char* aPrivateKey, const char* format) { + if (aPrivateKey == nullptr || format == nullptr) { + throw TTransportException(TTransportException::BAD_ARGS, + "loadPrivateKey: either or is NULL"); + } + if (strcmp(format, "PEM") == 0) { + BIO* mem = BIO_new(BIO_s_mem()); + BIO_puts(mem, aPrivateKey); + EVP_PKEY* cert = PEM_read_bio_PrivateKey(mem, nullptr, nullptr, nullptr); + + BIO_free(mem); + if (SSL_CTX_use_PrivateKey(ctx_->get(), cert) == 0) { + int errno_copy = THRIFT_GET_SOCKET_ERROR; + string errors; + buildErrors(errors, errno_copy); + throw TSSLException("SSL_CTX_use_PrivateKey: " + errors); + } + } else { + throw TSSLException("Unsupported certificate format: " + string(format)); + } +} + void TSSLSocketFactory::loadTrustedCertificates(const char* path, const char* capath) { if (path == nullptr) { throw TTransportException(TTransportException::BAD_ARGS, @@ -985,6 +1029,39 @@ void TSSLSocketFactory::loadTrustedCertificates(const char* path, const char* ca } } +void TSSLSocketFactory::loadTrustedCertificatesFromBuffer(const char* aCertificate, const char* aChain) { + if (aCertificate == nullptr) { + throw TTransportException(TTransportException::BAD_ARGS, + "loadTrustedCertificates: aCertificate is empty"); + } + X509_STORE* vX509Store = SSL_CTX_get_cert_store(ctx_->get()); + BIO* mem = BIO_new(BIO_s_mem()); + BIO_puts(mem, aCertificate); + X509* cert = PEM_read_bio_X509(mem, NULL, 0, NULL); + BIO_free(mem); + + if (X509_STORE_add_cert(vX509Store, cert) == 0) { + int errno_copy = THRIFT_GET_SOCKET_ERROR; + string errors; + buildErrors(errors, errno_copy); + throw TSSLException("X509_STORE_add_cert: " + errors); + } + + if (aChain) { + mem = BIO_new(BIO_s_mem()); + BIO_puts(mem, aChain); + cert = PEM_read_bio_X509(mem, NULL, 0, NULL); + BIO_free(mem); + + if (SSL_CTX_add_extra_chain_cert(ctx_->get(), cert) == 0) { + int errno_copy = THRIFT_GET_SOCKET_ERROR; + string errors; + buildErrors(errors, errno_copy); + throw TSSLException("X509_STORE_add_cert: " + errors); + } + } +} + void TSSLSocketFactory::randomize() { RAND_poll(); } diff --git a/lib/cpp/src/thrift/transport/TSSLSocket.h b/lib/cpp/src/thrift/transport/TSSLSocket.h index 87a9601476b..a78112c89c1 100644 --- a/lib/cpp/src/thrift/transport/TSSLSocket.h +++ b/lib/cpp/src/thrift/transport/TSSLSocket.h @@ -261,6 +261,7 @@ class TSSLSocketFactory { * @param format Certificate file format */ virtual void loadCertificate(const char* path, const char* format = "PEM"); + virtual void loadCertificateFromBuffer(const char* aCertificate, const char* format = "PEM"); /** * Load private key. * @@ -268,12 +269,14 @@ class TSSLSocketFactory { * @param format Private key file format */ virtual void loadPrivateKey(const char* path, const char* format = "PEM"); + virtual void loadPrivateKeyFromBuffer(const char* aPrivateKey, const char* format = "PEM"); /** * Load trusted certificates from specified file. * * @param path Path to trusted certificate file */ virtual void loadTrustedCertificates(const char* path, const char* capath = nullptr); + virtual void loadTrustedCertificatesFromBuffer(const char* aCertificate, const char* aChain = nullptr); /** * Default randomize method. */ diff --git a/lib/cpp/test/CMakeLists.txt b/lib/cpp/test/CMakeLists.txt index ef08dbce225..fba15f6c07f 100644 --- a/lib/cpp/test/CMakeLists.txt +++ b/lib/cpp/test/CMakeLists.txt @@ -334,6 +334,17 @@ target_link_libraries(SecurityTest -lrt) endif () add_test(NAME SecurityTest COMMAND SecurityTest -- "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys") +add_executable(SecurityFromBufferTest SecurityFromBufferTest.cpp) +target_link_libraries(SecurityFromBufferTest + testgencpp + ${Boost_LIBRARIES} +) +LINK_AGAINST_THRIFT_LIBRARY(SecurityFromBufferTest thrift) +if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW) +target_link_libraries(SecurityFromBufferTest -lrt) +endif () +add_test(NAME SecurityFromBufferTest COMMAND SecurityFromBufferTest -- "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys") + endif() if(WITH_QT5) diff --git a/lib/cpp/test/Makefile.am b/lib/cpp/test/Makefile.am index 2a0b9e69336..8399d9eb5b0 100755 --- a/lib/cpp/test/Makefile.am +++ b/lib/cpp/test/Makefile.am @@ -99,6 +99,7 @@ check_PROGRAMS = \ TInterruptTest \ TServerIntegrationTest \ SecurityTest \ + SecurityFromBufferTest \ ZlibTest \ TFileTransportTest \ link_test \ @@ -174,6 +175,17 @@ SecurityTest_LDADD = \ $(BOOST_SYSTEM_LDADD) \ $(BOOST_THREAD_LDADD) +SecurityFromBufferTest_SOURCES = \ + SecurityFromBufferTest.cpp + +SecurityFromBufferTest_LDADD = \ + libtestgencpp.la \ + libprocessortest.la \ + $(BOOST_TEST_LDADD) \ + $(BOOST_FILESYSTEM_LDADD) \ + $(BOOST_SYSTEM_LDADD) \ + $(BOOST_THREAD_LDADD) + TransportTest_SOURCES = \ TransportTest.cpp diff --git a/lib/cpp/test/SecurityFromBufferTest.cpp b/lib/cpp/test/SecurityFromBufferTest.cpp new file mode 100644 index 00000000000..72a4c2a28f0 --- /dev/null +++ b/lib/cpp/test/SecurityFromBufferTest.cpp @@ -0,0 +1,253 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#define BOOST_TEST_MODULE SecurityFromBufferTest +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __linux__ +#include +#endif + +using apache::thrift::transport::TServerTransport; +using apache::thrift::transport::TSSLServerSocket; +using apache::thrift::transport::TSSLSocket; +using apache::thrift::transport::TSSLSocketFactory; +using apache::thrift::transport::TTransport; +using apache::thrift::transport::TTransportException; +using apache::thrift::transport::TTransportFactory; + +using std::bind; +using std::shared_ptr; + +boost::filesystem::path keyDir; +boost::filesystem::path certFile(const std::string& filename) { + return keyDir / filename; +} +std::string certString(const std::string& filename) { + std::ifstream ifs(certFile(filename).string()); + if(!ifs.is_open() || !ifs.good()) { + throw(std::runtime_error("Failed to open key file " + filename + " for reading")); + } + std::stringstream buffer; + buffer << ifs.rdbuf(); + return buffer.str(); +} +boost::mutex gMutex; + +struct GlobalFixture { + GlobalFixture() { + using namespace boost::unit_test::framework; + for (int i = 0; i < master_test_suite().argc; ++i) { + BOOST_TEST_MESSAGE(boost::format("argv[%1%] = \"%2%\"") % i % master_test_suite().argv[i]); + } + +#ifdef __linux__ + // OpenSSL calls send() without MSG_NOSIGPIPE so writing to a socket that has + // disconnected can cause a SIGPIPE signal... + signal(SIGPIPE, SIG_IGN); +#endif + + TSSLSocketFactory::setManualOpenSSLInitialization(true); + apache::thrift::transport::initializeOpenSSL(); + + keyDir = boost::filesystem::current_path().parent_path().parent_path().parent_path() / "test" / "keys"; + if (!boost::filesystem::exists(certFile("server.crt"))) { + keyDir = boost::filesystem::path(master_test_suite().argv[master_test_suite().argc - 1]); + if (!boost::filesystem::exists(certFile("server.crt"))) { + throw std::invalid_argument("The last argument to this test must be the directory containing the test certificate(s)."); + } + } + } + + virtual ~GlobalFixture() { + apache::thrift::transport::cleanupOpenSSL(); +#ifdef __linux__ + signal(SIGPIPE, SIG_DFL); +#endif + } +}; + +#if (BOOST_VERSION >= 105900) +BOOST_GLOBAL_FIXTURE(GlobalFixture); +#else +BOOST_GLOBAL_FIXTURE(GlobalFixture) +#endif + +struct SecurityFromBufferFixture { + void server(apache::thrift::transport::SSLProtocol protocol) { + try { + boost::mutex::scoped_lock lock(mMutex); + + shared_ptr pServerSocketFactory; + shared_ptr pServerSocket; + + pServerSocketFactory.reset(new TSSLSocketFactory(static_cast(protocol))); + pServerSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"); + pServerSocketFactory->loadCertificateFromBuffer(certString("server.crt").c_str()); + pServerSocketFactory->loadPrivateKeyFromBuffer(certString("server.key").c_str()); + pServerSocketFactory->server(true); + pServerSocket.reset(new TSSLServerSocket("localhost", 0, pServerSocketFactory)); + shared_ptr connectedClient; + + try { + pServerSocket->listen(); + mPort = pServerSocket->getPort(); + mCVar.notify_one(); + lock.unlock(); + + connectedClient = pServerSocket->accept(); + uint8_t buf[2]; + buf[0] = 'O'; + buf[1] = 'K'; + connectedClient->write(&buf[0], 2); + connectedClient->flush(); + } + + catch (apache::thrift::transport::TTransportException& ex) { + boost::mutex::scoped_lock lock(gMutex); + BOOST_TEST_MESSAGE(boost::format("SRV %1% Exception: %2%") % boost::this_thread::get_id() % ex.what()); + } + + if (connectedClient) { + connectedClient->close(); + connectedClient.reset(); + } + + pServerSocket->close(); + pServerSocket.reset(); + } catch (std::exception& ex) { + BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what()); + } + } + + void client(apache::thrift::transport::SSLProtocol protocol) { + try { + shared_ptr pClientSocketFactory; + shared_ptr pClientSocket; + + try { + pClientSocketFactory.reset(new TSSLSocketFactory(static_cast(protocol))); + pClientSocketFactory->authenticate(true); + pClientSocketFactory->loadCertificateFromBuffer(certString("client.crt").c_str()); + pClientSocketFactory->loadPrivateKeyFromBuffer(certString("client.key").c_str()); + pClientSocketFactory->loadTrustedCertificatesFromBuffer(certString("CA.pem").c_str()); + pClientSocket = pClientSocketFactory->createSocket("localhost", mPort); + pClientSocket->open(); + + uint8_t buf[3]; + buf[0] = 0; + buf[1] = 0; + BOOST_CHECK_EQUAL(2, pClientSocket->read(&buf[0], 2)); + BOOST_CHECK_EQUAL(0, memcmp(&buf[0], "OK", 2)); + mConnected = true; + } catch (apache::thrift::transport::TTransportException& ex) { + boost::mutex::scoped_lock lock(gMutex); + BOOST_TEST_MESSAGE(boost::format("CLI %1% Exception: %2%") % boost::this_thread::get_id() % ex.what()); + } + + if (pClientSocket) { + pClientSocket->close(); + pClientSocket.reset(); + } + } catch (std::exception& ex) { + BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what()); + } + } + + static const char* protocol2str(size_t protocol) { + static const char* strings[apache::thrift::transport::LATEST + 1] + = {"SSLTLS", "SSLv2", "SSLv3", "TLSv1_0", "TLSv1_1", "TLSv1_2"}; + return strings[protocol]; + } + + boost::mutex mMutex; + boost::condition_variable mCVar; + int mPort; + bool mConnected; +}; + +BOOST_FIXTURE_TEST_SUITE(BOOST_TEST_MODULE, SecurityFromBufferFixture) + +BOOST_AUTO_TEST_CASE(ssl_security_matrix) { + try { + // matrix of connection success between client and server with different SSLProtocol selections + static_assert(apache::thrift::transport::LATEST == 5, "Mismatch in assumed number of ssl protocols"); + bool matrix[apache::thrift::transport::LATEST + 1][apache::thrift::transport::LATEST + 1] = + { + // server = SSLTLS SSLv2 SSLv3 TLSv1_0 TLSv1_1 TLSv1_2 + // client + /* SSLTLS */ { true, false, false, true, true, true }, + /* SSLv2 */ { false, false, false, false, false, false }, + /* SSLv3 */ { false, false, true, false, false, false }, + /* TLSv1_0 */ { true, false, false, true, false, false }, + /* TLSv1_1 */ { true, false, false, false, true, false }, + /* TLSv1_2 */ { true, false, false, false, false, true } + }; + + for (size_t si = 0; si <= apache::thrift::transport::LATEST; ++si) { + for (size_t ci = 0; ci <= apache::thrift::transport::LATEST; ++ci) { + if (si == 1 || ci == 1) { + // Skip all SSLv2 cases - protocol not supported + continue; + } + +#ifdef OPENSSL_NO_SSL3 + if (si == 2 || ci == 2) { + // Skip all SSLv3 cases - protocol not supported + continue; + } +#endif + + boost::mutex::scoped_lock lock(mMutex); + + BOOST_TEST_MESSAGE(boost::format("TEST: Server = %1%, Client = %2%") % protocol2str(si) + % protocol2str(ci)); + + mConnected = false; + // thread_group manages the thread lifetime - ignore the return value of create_thread + boost::thread_group threads; + (void)threads.create_thread(bind(&SecurityFromBufferFixture::server, this, + static_cast(si))); + mCVar.wait(lock); // wait for listen() to succeed + lock.unlock(); + (void)threads.create_thread(bind(&SecurityFromBufferFixture::client, this, + static_cast(ci))); + threads.join_all(); + + BOOST_CHECK_MESSAGE(mConnected == matrix[ci][si], + boost::format(" Server = %1%, Client = %2% expected mConnected == %3% but was %4%") + % protocol2str(si) % protocol2str(ci) % matrix[ci][si] % mConnected); + } + } + } catch (std::exception& ex) { + BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what()); + } +} + +BOOST_AUTO_TEST_SUITE_END() From 7cb8473bcd019deed508942cd628b606a544852e Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 16 Oct 2019 22:57:19 +0200 Subject: [PATCH 390/756] Updated ReleaseManagement.md [ci skip] --- doc/ReleaseManagement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ReleaseManagement.md b/doc/ReleaseManagement.md index 362fd831511..ee744aeb46b 100644 --- a/doc/ReleaseManagement.md +++ b/doc/ReleaseManagement.md @@ -331,7 +331,7 @@ Voting on the development mailing list provides additional benefits (wisdom from ~/thrift$ git push --tags ``` - **NOTE:** If you get the error "gpg failed to sign the data" when tagging, try this fix: "export GPG_TTY=$(tty)" + **NOTE:** If you get the error "gpg failed to sign the data" when tagging, try this fix: ```export GPG_TTY=$(tty)```. Alternatively, it may be necessary to specify the ```-u ``` as an additional argument. 1. Create a new release from the [GitHub Tags Page](https://github.com/apache/thrift/tags). Attach the statically built Windows thrift compiler as a binary here. From a3fa0d928f7647aa6007e16ac81d76a3b5183d2c Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 11 Oct 2019 00:42:29 +0200 Subject: [PATCH 391/756] Version 0.13.0 --- CHANGES.md | 271 +++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 6 ++ doap.rdf | 5 + 3 files changed, 282 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 35e8ccba084..72c7eb8faa3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,8 @@ ### New Languages +- (none) + ### Deprecated Languages - [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - CSharp and Netcore targets are deprecated and will be removed with the next release - use NetStd instead. @@ -33,6 +35,275 @@ ### Known Issues (Blocker or Critical) +- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++: library don't work with HTTP (csharp server, cpp client; need cross test enhancement) + +### As3 + +- [THRIFT-4784](https://issues.apache.org/jira/browse/THRIFT-4784) - Thrift should throw when skipping over unexpected data + +### Build Process + +- [THRIFT-2333](https://issues.apache.org/jira/browse/THRIFT-2333) - RPMBUILD: Abort build if user did not disable ruby but ruby build will fail later on +- [THRIFT-4689](https://issues.apache.org/jira/browse/THRIFT-4689) - Pull changes from 0.12.0 release branch into master +- [THRIFT-4690](https://issues.apache.org/jira/browse/THRIFT-4690) - Update dlang deimos for OpenSSL 1.1 (use 1.1.0h tagged release instead of master) +- [THRIFT-4694](https://issues.apache.org/jira/browse/THRIFT-4694) - Upgrade Java to Java 1.8 +- [THRIFT-4716](https://issues.apache.org/jira/browse/THRIFT-4716) - Create a version alignment tool to make releases easier +- [THRIFT-4760](https://issues.apache.org/jira/browse/THRIFT-4760) - Install pkgconfig when using cmake +- [THRIFT-4769](https://issues.apache.org/jira/browse/THRIFT-4769) - Change NuGet package to use netstd artifact +- [THRIFT-4811](https://issues.apache.org/jira/browse/THRIFT-4811) - Add cmake config module +- [THRIFT-4855](https://issues.apache.org/jira/browse/THRIFT-4855) - go CI fails with "cannot find package "golang.org/x/tools/go/packages" in any of ..." +- [THRIFT-4864](https://issues.apache.org/jira/browse/THRIFT-4864) - CI fails at netstd +- [THRIFT-4874](https://issues.apache.org/jira/browse/THRIFT-4874) - Thrift 0.12.0 Source Distribution (.tar.gz) Contains Hardlinks - Extract Fails +- [THRIFT-4896](https://issues.apache.org/jira/browse/THRIFT-4896) - cpp and c_glib include paths are added to source files when building +- [THRIFT-4966](https://issues.apache.org/jira/browse/THRIFT-4966) - Git ignore files generated by the build + +### C glib + +- [THRIFT-4842](https://issues.apache.org/jira/browse/THRIFT-4842) - Multiplexed protocol has a memory leak in set c_glib +- [THRIFT-4878](https://issues.apache.org/jira/browse/THRIFT-4878) - c_glib ThriftSocket support for unix domain sockets +- [THRIFT-4950](https://issues.apache.org/jira/browse/THRIFT-4950) - fix bind print error and Macro call errors thrift_server_socket + +### C# + +- [THRIFT-3587](https://issues.apache.org/jira/browse/THRIFT-3587) - C# TTLSSocket does not use timeout for opening the socket +- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types +- [THRIFT-4684](https://issues.apache.org/jira/browse/THRIFT-4684) - Missing namespace and un-used private fields in WCF fault classes when enable WCF in C# code generation +- [THRIFT-4715](https://issues.apache.org/jira/browse/THRIFT-4715) - C# union "data" should be strongly-typed +- [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - Consolidate C# and netcore into new netstd language target (and finally deprecate both C# and netcore bindings) +- [THRIFT-4741](https://issues.apache.org/jira/browse/THRIFT-4741) - Missing "inner" argument from one CTOR +- [THRIFT-4769](https://issues.apache.org/jira/browse/THRIFT-4769) - Change NuGet package to use netstd artifact +- [THRIFT-4859](https://issues.apache.org/jira/browse/THRIFT-4859) - Enables changing 'UserAgent' +- [THRIFT-4907](https://issues.apache.org/jira/browse/THRIFT-4907) - strong named assemblies wanted + +### C++ + +- [THRIFT-4384](https://issues.apache.org/jira/browse/THRIFT-4384) - Using a concurrent client with cpp async is not safe. +- [THRIFT-4441](https://issues.apache.org/jira/browse/THRIFT-4441) - C++: support building lib without Boost +- [THRIFT-4487](https://issues.apache.org/jira/browse/THRIFT-4487) - gettimeofday: windows implementation not quoting source, applying license to foreign code +- [THRIFT-4593](https://issues.apache.org/jira/browse/THRIFT-4593) - Unit Tests failing on Alpine Linux due to non-portable mutex initializers +- [THRIFT-4678](https://issues.apache.org/jira/browse/THRIFT-4678) - add noexcept cpp generator option +- [THRIFT-4720](https://issues.apache.org/jira/browse/THRIFT-4720) - Drop support for C++03/C++98 and begin refactoring +- [THRIFT-4730](https://issues.apache.org/jira/browse/THRIFT-4730) - Remove pthread and boost::thread library support and use std::thread for C++11 +- [THRIFT-4735](https://issues.apache.org/jira/browse/THRIFT-4735) - Remove C++ Qt4 support (leave Qt5) - Qt4 LTS ended in 2014 +- [THRIFT-4739](https://issues.apache.org/jira/browse/THRIFT-4739) - Good old concurrency_test failing on windows builds again with some regularity +- [THRIFT-4740](https://issues.apache.org/jira/browse/THRIFT-4740) - Use std::chrono for timeout and remove old structures. +- [THRIFT-4762](https://issues.apache.org/jira/browse/THRIFT-4762) - C++: Applied some C++11 refactorings to the runtime library and compiler +- [THRIFT-4776](https://issues.apache.org/jira/browse/THRIFT-4776) - Modernize c++11 code by clang-tidy +- [THRIFT-4830](https://issues.apache.org/jira/browse/THRIFT-4830) - Add to_string function for enum in C++ file generate +- [THRIFT-4861](https://issues.apache.org/jira/browse/THRIFT-4861) - Fix use of deprecated boost endian header; move to minimum boost 1.56.0 +- [THRIFT-4936](https://issues.apache.org/jira/browse/THRIFT-4936) - add depth limit type exception description +- [THRIFT-4962](https://issues.apache.org/jira/browse/THRIFT-4962) - Deadlock in TimerManager::stop + +### cocoa + +- [THRIFT-4719](https://issues.apache.org/jira/browse/THRIFT-4719) - Remove cocoa language support + +## Compiler (General) + +- [THRIFT-4743](https://issues.apache.org/jira/browse/THRIFT-4743) - Remove the compiler plug-in mode + +### contributed + +- [THRIFT-4897](https://issues.apache.org/jira/browse/THRIFT-4897) - UT of thrift-maven-plugin failed + +## D language + +- [THRIFT-4690](https://issues.apache.org/jira/browse/THRIFT-4690) - Update dlang deimos for OpenSSL 1.1 (use 1.1.0h tagged release instead of master) +- [THRIFT-4724](https://issues.apache.org/jira/browse/THRIFT-4724) - dlang dub.json dependency for openssl is too restrictive +- [THRIFT-4918](https://issues.apache.org/jira/browse/THRIFT-4918) - dlang name conflict + +### dart + +- [THRIFT-4654](https://issues.apache.org/jira/browse/THRIFT-4654) - Thrift Dart port is not compatible with Dart 2 + +### Delphi + +- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types +- [THRIFT-4841](https://issues.apache.org/jira/browse/THRIFT-4841) - THTTPTransport relies on activeX component +- [THRIFT-4843](https://issues.apache.org/jira/browse/THRIFT-4843) - http:// and https:// schemes are switched in test client +- [THRIFT-4862](https://issues.apache.org/jira/browse/THRIFT-4862) - better ToString() support for enums and container types +- [THRIFT-4863](https://issues.apache.org/jira/browse/THRIFT-4863) - better indication of WinHTTP errors +- [THRIFT-4881](https://issues.apache.org/jira/browse/THRIFT-4881) - Allow TLS1.1 and TLS1.2 over WinHTTP even when not configured as systemwide default +- [THRIFT-4882](https://issues.apache.org/jira/browse/THRIFT-4882) - Autodetect proxy settings with WinHTTP +- [THRIFT-4884](https://issues.apache.org/jira/browse/THRIFT-4884) - Add serialisation performance test for Delphi +- [THRIFT-4886](https://issues.apache.org/jira/browse/THRIFT-4886) - More detailed error information for WinHTTP transport +- [THRIFT-4894](https://issues.apache.org/jira/browse/THRIFT-4894) - Enable automatic content encoding handling for gzip,deflate in the WinHTTP client +- [THRIFT-4939](https://issues.apache.org/jira/browse/THRIFT-4939) - TThriftListImpl.Sort() does not use comparer +- [THRIFT-4944](https://issues.apache.org/jira/browse/THRIFT-4944) - Field IDs > 255 fail with compact protocol + +### Documentation + +- [THRIFT-4697](https://issues.apache.org/jira/browse/THRIFT-4697) - Create updated release procedures +- [THRIFT-4808](https://issues.apache.org/jira/browse/THRIFT-4808) - Update LANGUAGES.md on master to reflect master +- [THRIFT-4933](https://issues.apache.org/jira/browse/THRIFT-4933) - Incorrect description in the 0.12.0 version of the documentation + +### Erlang + +- [THRIFT-4583](https://issues.apache.org/jira/browse/THRIFT-4583) - Support rebar3 for erlang builds +- [THRIFT-4744](https://issues.apache.org/jira/browse/THRIFT-4744) - Erlang help intendation not aligned + +### Go + +- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types +- [THRIFT-4612](https://issues.apache.org/jira/browse/THRIFT-4612) - Add THeader for Go +- [THRIFT-4747](https://issues.apache.org/jira/browse/THRIFT-4747) - The 'omitempty' tag should not be appended to optional fields that have a default value +- [THRIFT-4797](https://issues.apache.org/jira/browse/THRIFT-4797) - Generated Go code produces name collisions on imports +- [THRIFT-4908](https://issues.apache.org/jira/browse/THRIFT-4908) - reader&writer in golang's TBinaryProtocol is not necessary and misleading + +### haskell + +- [THRIFT-4834](https://issues.apache.org/jira/browse/THRIFT-4834) - CI error at Haskell: Failed to load interface for `Network' +- [THRIFT-4955](https://issues.apache.org/jira/browse/THRIFT-4955) - Haskell test broken due to extension to CompactProtoTestStruct +- [THRIFT-4956](https://issues.apache.org/jira/browse/THRIFT-4956) - DebugProtoTest_Main.hs: Invalid ThriftType 128 + +### haxe + +- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types +- [THRIFT-4812](https://issues.apache.org/jira/browse/THRIFT-4812) - haxelib readme still points to old ASF git repo + +### HTML + +- [THRIFT-4763](https://issues.apache.org/jira/browse/THRIFT-4763) - HTML compiler produces invalid HTML document + +### Java + +- [THRIFT-2530](https://issues.apache.org/jira/browse/THRIFT-2530) - TIOStreamTransport's isOpen() always be true even if close() was called. +- [THRIFT-4368](https://issues.apache.org/jira/browse/THRIFT-4368) - Guaranteed NPE in TBaseAsyncProcessor.java +- [THRIFT-4469](https://issues.apache.org/jira/browse/THRIFT-4469) - isServing is not thread safe +- [THRIFT-4481](https://issues.apache.org/jira/browse/THRIFT-4481) - TBinaryProtocol.writeMessageEnd isn't throwable exception +- [THRIFT-4695](https://issues.apache.org/jira/browse/THRIFT-4695) - Pre-Size Java Collections in Union +- [THRIFT-4696](https://issues.apache.org/jira/browse/THRIFT-4696) - NonBlocking Server: Use case-switch Statement Instead of if-else Clauses +- [THRIFT-4702](https://issues.apache.org/jira/browse/THRIFT-4702) - Improve AutoExpandingBuffer +- [THRIFT-4704](https://issues.apache.org/jira/browse/THRIFT-4704) - Streamline TDeserializer Implementation +- [THRIFT-4709](https://issues.apache.org/jira/browse/THRIFT-4709) - Use StandardCharset UTF-8 +- [THRIFT-4711](https://issues.apache.org/jira/browse/THRIFT-4711) - Improve Immutable None Type Instantiation +- [THRIFT-4712](https://issues.apache.org/jira/browse/THRIFT-4712) - Improve Performance of ShortStack +- [THRIFT-4713](https://issues.apache.org/jira/browse/THRIFT-4713) - Review of TBaseHelper.java +- [THRIFT-4714](https://issues.apache.org/jira/browse/THRIFT-4714) - Java TFramedTransport calls write twice for each flush +- [THRIFT-4725](https://issues.apache.org/jira/browse/THRIFT-4725) - Change Return Type Signature of Process Methods +- [THRIFT-4726](https://issues.apache.org/jira/browse/THRIFT-4726) - Remove SLF4J Logging Guards +- [THRIFT-4748](https://issues.apache.org/jira/browse/THRIFT-4748) - Add Jitpack support +- [THRIFT-4766](https://issues.apache.org/jira/browse/THRIFT-4766) - JDK9+ fails on missing annotations +- [THRIFT-4773](https://issues.apache.org/jira/browse/THRIFT-4773) - TSaslTransport should relay underlying TTransportException to TSaslTransportException +- [THRIFT-4805](https://issues.apache.org/jira/browse/THRIFT-4805) - Suppress excessive logging of SASL TTransportExceptions in case of END_OF_FILE +- [THRIFT-4849](https://issues.apache.org/jira/browse/THRIFT-4849) - Do not Ignore InterruptedException +- [THRIFT-4851](https://issues.apache.org/jira/browse/THRIFT-4851) - Remove All Calls To printStackTrace +- [THRIFT-4857](https://issues.apache.org/jira/browse/THRIFT-4857) - Java field hash code implementation inconsistent with equals. +- [THRIFT-4858](https://issues.apache.org/jira/browse/THRIFT-4858) - Java TThreadPoolServer: confusing error message on closed socket +- [THRIFT-4865](https://issues.apache.org/jira/browse/THRIFT-4865) - warning: [deprecation] UTF_8 in Charsets has been deprecated +- [THRIFT-4899](https://issues.apache.org/jira/browse/THRIFT-4899) - Generated TypeScript declarations incorrectly references types when there is more than 1 include +- [THRIFT-4945](https://issues.apache.org/jira/browse/THRIFT-4945) - Log output mode is not standardized +- [THRIFT-4957](https://issues.apache.org/jira/browse/THRIFT-4957) - testSanePartsOfCompactProtoTestStruct FAILED + +### JavaScript + +- [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - JS code generators not handling int64 type properly for constants and for TypeScript type mappings +- [THRIFT-4728](https://issues.apache.org/jira/browse/THRIFT-4728) - Cleanup for the double rendering test in JS +- [THRIFT-4737](https://issues.apache.org/jira/browse/THRIFT-4737) - thrift.js does not use customHeaders in jqRequest +- [THRIFT-4745](https://issues.apache.org/jira/browse/THRIFT-4745) - warning C4305: 'initializing' : truncation from '"__int64' to 'long' +- [THRIFT-4757](https://issues.apache.org/jira/browse/THRIFT-4757) - grunt-shell-spawn drags in sync-exec which has a security notice + +### netcore + +- [THRIFT-4024](https://issues.apache.org/jira/browse/THRIFT-4024) - Skip() should throw on unknown data types +- [THRIFT-4722](https://issues.apache.org/jira/browse/THRIFT-4722) - Netcore union "data" should be strongly-typed +- [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723) - Consolidate C# and netcore into new netstd language target (and finally deprecate both C# and netcore bindings) +- [THRIFT-4742](https://issues.apache.org/jira/browse/THRIFT-4742) - Typo "cannot read from null input stream" on write +- [THRIFT-4769](https://issues.apache.org/jira/browse/THRIFT-4769) - Change NuGet package to use netstd artifact +- [THRIFT-4919](https://issues.apache.org/jira/browse/THRIFT-4919) - THttpTransport.cs (netstd) and THttpClientTransport (netcore) have bad timeout code + +### netstd + +- [THRIFT-4768](https://issues.apache.org/jira/browse/THRIFT-4768) - Remove "nullable" option from the code base (netstd ONLY) +- [THRIFT-4772](https://issues.apache.org/jira/browse/THRIFT-4772) - fully enable server-side usage of framed/buffered transports +- [THRIFT-4813](https://issues.apache.org/jira/browse/THRIFT-4813) - NamedPipes may not work in all cases +- [THRIFT-4816](https://issues.apache.org/jira/browse/THRIFT-4816) - JSONTransports Context.WriteAsync/ReadAsync are badly named +- [THRIFT-4817](https://issues.apache.org/jira/browse/THRIFT-4817) - Add string CTOR to TTlsSocketTransport +- [THRIFT-4818](https://issues.apache.org/jira/browse/THRIFT-4818) - Test client should use cancellation token +- [THRIFT-4821](https://issues.apache.org/jira/browse/THRIFT-4821) - Normalize TServerSocketTransport constructors in netstd +- [THRIFT-4822](https://issues.apache.org/jira/browse/THRIFT-4822) - Refactor bool CTOR flags into enum type +- [THRIFT-4824](https://issues.apache.org/jira/browse/THRIFT-4824) - Logger deprecation warnings in tutorial +- [THRIFT-4825](https://issues.apache.org/jira/browse/THRIFT-4825) - Align TTlsServerSocketTransport constructors with TServerSocketTransport - Breaking Change +- [THRIFT-4829](https://issues.apache.org/jira/browse/THRIFT-4829) - HTTP server transport lacks TransportFactory arguments +- [THRIFT-4831](https://issues.apache.org/jira/browse/THRIFT-4831) - interface ITProtocolFactory should be class TProtocolFactory again +- [THRIFT-4832](https://issues.apache.org/jira/browse/THRIFT-4832) - superfluous backing field causes CS0169 "field never used" +- [THRIFT-4839](https://issues.apache.org/jira/browse/THRIFT-4839) - Remove embedded buffering/framed options from TCP transports +- [THRIFT-4840](https://issues.apache.org/jira/browse/THRIFT-4840) - Update the README in the netstd tutorial to include references to the new buffering arguments +- [THRIFT-4848](https://issues.apache.org/jira/browse/THRIFT-4848) - Add ability to set Content-Type,Accept headers in HTTP client +- [THRIFT-4853](https://issues.apache.org/jira/browse/THRIFT-4853) - TServerFramedTransport is now obsolete and can be removed +- [THRIFT-4854](https://issues.apache.org/jira/browse/THRIFT-4854) - oneway calls do not work over HTTP +- [THRIFT-4860](https://issues.apache.org/jira/browse/THRIFT-4860) - Allow changing "User-Agent" +- [THRIFT-4879](https://issues.apache.org/jira/browse/THRIFT-4879) - general performance improvements for netstd library +- [THRIFT-4891](https://issues.apache.org/jira/browse/THRIFT-4891) - Align HTTP test client with all other variants +- [THRIFT-4893](https://issues.apache.org/jira/browse/THRIFT-4893) - Enable automatic content encoding handling for gzip,deflate in the HTTP client +- [THRIFT-4898](https://issues.apache.org/jira/browse/THRIFT-4898) - Pipe write operations across a network are limited to 65,535 bytes per write. +- [THRIFT-4919](https://issues.apache.org/jira/browse/THRIFT-4919) - THttpTransport.cs (netstd) and THttpClientTransport (netcore) have bad timeout code + +### node.js + +- [THRIFT-3060](https://issues.apache.org/jira/browse/THRIFT-3060) - Node.js client retry logic doesn't flush offline queue on reconnect +- [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - JS code generators not handling int64 type properly for constants and for TypeScript type mappings +- [THRIFT-4738](https://issues.apache.org/jira/browse/THRIFT-4738) - Generated typescript type definition files are incorrect +- [THRIFT-4771](https://issues.apache.org/jira/browse/THRIFT-4771) - THeader for node.js +- [THRIFT-4809](https://issues.apache.org/jira/browse/THRIFT-4809) - Javascript episodic code generation +- [THRIFT-4844](https://issues.apache.org/jira/browse/THRIFT-4844) - createConnection ignores connect_timeout option + +### perl + +- [THRIFT-4691](https://issues.apache.org/jira/browse/THRIFT-4691) - The perl CPAN module contains no tests + +### PHP + +- [THRIFT-4751](https://issues.apache.org/jira/browse/THRIFT-4751) - Missing imports in TProtocol (phpdoc related only) +- [THRIFT-4794](https://issues.apache.org/jira/browse/THRIFT-4794) - Finish adding json protocol to the php cross test +- [THRIFT-4807](https://issues.apache.org/jira/browse/THRIFT-4807) - PHP extension segfaults if reference is used in input +- [THRIFT-4845](https://issues.apache.org/jira/browse/THRIFT-4845) - PHP's TCurlClient ignores timeout values smaller that 1 second + +### python + +- [THRIFT-1549](https://issues.apache.org/jira/browse/THRIFT-1549) - Python TSSLSocket: Shutdown cleanly +- [THRIFT-4733](https://issues.apache.org/jira/browse/THRIFT-4733) - Address already in use with python unit test +- [THRIFT-4767](https://issues.apache.org/jira/browse/THRIFT-4767) - support tcp keepalive in python +- [THRIFT-4778](https://issues.apache.org/jira/browse/THRIFT-4778) - Python protocol factories do not derive from TProtocolFactory +- [THRIFT-4779](https://issues.apache.org/jira/browse/THRIFT-4779) - Python, Java TMultiplexedProcessor do not raise TProtocolException +- [THRIFT-4780](https://issues.apache.org/jira/browse/THRIFT-4780) - TMultiplexedProcessor is not fully tested or implemented in Python +- [THRIFT-4783](https://issues.apache.org/jira/browse/THRIFT-4783) - Thrift should throw when skipping over unexpected data +- [THRIFT-4798](https://issues.apache.org/jira/browse/THRIFT-4798) - Fix python THttpServer to honor correct oneway reply semantics +- [THRIFT-4892](https://issues.apache.org/jira/browse/THRIFT-4892) - SASL data type exception for PLAIN +- [THRIFT-4920](https://issues.apache.org/jira/browse/THRIFT-4920) - Binary constants emit non-binary Python literals + +### ruby + +- [THRIFT-4721](https://issues.apache.org/jira/browse/THRIFT-4721) - Installing the ruby gem on systems without make fails in the build_ext task. +- [THRIFT-4971](https://issues.apache.org/jira/browse/THRIFT-4971) - Fix lib/rb/spec/union_spec.rb so that CI succeeds + +### rust + +- [THRIFT-4953](https://issues.apache.org/jira/browse/THRIFT-4953) - Unspecified Field Identifier Creates Non Compiling Rust Code +- [THRIFT-4960](https://issues.apache.org/jira/browse/THRIFT-4960) - Bare Trait Warnings + +### Swift + +- [THRIFT-4902](https://issues.apache.org/jira/browse/THRIFT-4902) - Swift compatibility with Swift 4.2, 5.0 and 5.1 + +### Test suite + +- [THRIFT-4301](https://issues.apache.org/jira/browse/THRIFT-4301) - configuring --without-python and --without-py3 still invokes py3 tests in make cross +- [THRIFT-4405](https://issues.apache.org/jira/browse/THRIFT-4405) - Incorrect handling of sequence numbers that wrap to negative +- [THRIFT-4794](https://issues.apache.org/jira/browse/THRIFT-4794) - Finish adding json protocol to the php cross test +- [THRIFT-4969](https://issues.apache.org/jira/browse/THRIFT-4969) - PHP test doesn't check the code generation with php:classmap + +### Tutorial + +- [THRIFT-4426](https://issues.apache.org/jira/browse/THRIFT-4426) - repository should not include symbolic links +- [THRIFT-4965](https://issues.apache.org/jira/browse/THRIFT-4965) - Perl tutorial server doesn't work due to the lack of use statement +- [THRIFT-4967](https://issues.apache.org/jira/browse/THRIFT-4967) - Node.js tutorial server fails if the zip function invoked +- [THRIFT-4968](https://issues.apache.org/jira/browse/THRIFT-4968) - Makefile.am in the Ruby tutorial refers to Python directory +- [THRIFT-4970](https://issues.apache.org/jira/browse/THRIFT-4970) - PHP tutorial doesn't work with Thrift v0.12.0+ + +### Typescript + +- [THRIFT-4675](https://issues.apache.org/jira/browse/THRIFT-4675) - JS code generators not handling int64 type properly for constants and for TypeScript type mappings ## 0.12.0 diff --git a/debian/changelog b/debian/changelog index 69b5f208383..f91921a5592 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +thrift (0.13.0) stable; urgency=low + + * update to 0.13.0 + + -- Apache Thrift Developers Wed, 11 Nov 2019 12:00:00 -0500 + thrift (0.12.0) stable; urgency=low * update to 0.12.0 diff --git a/doap.rdf b/doap.rdf index 50b3491d658..77b9113247a 100755 --- a/doap.rdf +++ b/doap.rdf @@ -57,6 +57,11 @@ + + Apache Thrift + 2019-10-11 + 0.13.0 + Apache Thrift 2018-12-28 From e02559fd46b07035a4a41c9d2604765756e3745b Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 17 Oct 2019 00:11:59 +0200 Subject: [PATCH 392/756] bump version This closes #1899 --- ApacheThrift.nuspec | 8 ++++---- CMakeLists.txt | 2 +- appveyor.yml | 2 +- bower.json | 2 +- configure.ac | 2 +- contrib/thrift.spec | 2 +- lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj | 2 +- lib/csharp/src/Thrift.csproj | 2 +- lib/csharp/test/Multiplex/Client/MultiplexClient.csproj | 2 +- .../test/Multiplex/Server/Properties/AssemblyInfo.cs | 4 ++-- lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs | 4 ++-- lib/d/src/thrift/base.d | 2 +- lib/delphi/src/Thrift.pas | 2 +- lib/haxe/haxelib.json | 2 +- lib/hs/thrift.cabal | 2 +- lib/java/gradle.properties | 2 +- lib/js/src/thrift.js | 2 +- lib/lua/Thrift.lua | 2 +- lib/netcore/Thrift/Properties/AssemblyInfo.cs | 4 ++-- .../Thrift/Transports/Client/THttpClientTransport.cs | 2 +- lib/netstd/Thrift/Properties/AssemblyInfo.cs | 4 ++-- lib/rb/thrift.gemspec | 2 +- lib/rs/Cargo.toml | 2 +- lib/st/package.xml | 2 +- lib/ts/package.json | 2 +- package.json | 2 +- test/csharp/Properties/AssemblyInfo.cs | 4 ++-- tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs | 4 ++-- tutorial/dart/console_client/pubspec.yaml | 2 +- tutorial/dart/server/pubspec.yaml | 2 +- tutorial/delphi/DelphiServer/DelphiServer.dproj | 4 ++-- tutorial/hs/ThriftTutorial.cabal | 2 +- tutorial/ocaml/_oasis | 2 +- 33 files changed, 43 insertions(+), 43 deletions(-) diff --git a/ApacheThrift.nuspec b/ApacheThrift.nuspec index 7bbfb0dc951..6dc3225f26d 100644 --- a/ApacheThrift.nuspec +++ b/ApacheThrift.nuspec @@ -21,14 +21,14 @@ the "Thrift" project. 3. nuget setApiKey 3. nuget pack ApacheThrift.nuspec -Symbols -SymbolPackageFormat snupkg - 4. nuget push ApacheThrift.0.13.0.nupkg -Source https://api.nuget.org/v3/index.json + 4. nuget push ApacheThrift.0.14.0.nupkg -Source https://api.nuget.org/v3/index.json --> ApacheThrift - 0.13.0 - Apache Thrift 0.13.0 + 0.14.0 + Apache Thrift 0.14.0 Apache Thrift Developers Apache Software Foundation Apache-2.0 @@ -39,7 +39,7 @@ Contains runtime libraries from lib/csharp for net35 and net45 frameworks, and from lib/netstd for netstandard2.0 framework development. - + Apache Thrift RPC diff --git a/CMakeLists.txt b/CMakeLists.txt index 1880b790ba3..f2e682ac2c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ endif() # PACKAGE_VERSION is used by cpack scripts currently # Both thrift_VERSION and PACKAGE_VERSION should be the same for now -set(thrift_VERSION "0.13.0") +set(thrift_VERSION "0.14.0") set(PACKAGE_VERSION ${thrift_VERSION}) project("thrift" VERSION ${PACKAGE_VERSION}) diff --git a/appveyor.yml b/appveyor.yml index ef729eb2a8a..233a056b903 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -19,7 +19,7 @@ # build Apache Thrift on AppVeyor - https://ci.appveyor.com -version: '0.13.0.{build}' +version: '0.14.0.{build}' shallow_clone: true diff --git a/bower.json b/bower.json index c602af15a3a..68f2c8d2c78 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.13.0", + "version": "0.14.0", "homepage": "https://github.com/apache/thrift.git", "authors": [ "Apache Thrift " diff --git a/configure.ac b/configure.ac index 58f9319314a..27846995ae1 100755 --- a/configure.ac +++ b/configure.ac @@ -20,7 +20,7 @@ AC_PREREQ(2.65) AC_CONFIG_MACRO_DIR([./aclocal]) -AC_INIT([thrift], [0.13.0]) +AC_INIT([thrift], [0.14.0]) AC_CONFIG_AUX_DIR([.]) diff --git a/contrib/thrift.spec b/contrib/thrift.spec index cbb08fba5c0..225a969911b 100644 --- a/contrib/thrift.spec +++ b/contrib/thrift.spec @@ -28,7 +28,7 @@ Name: thrift License: Apache License v2.0 Group: Development Summary: RPC and serialization framework -Version: 0.13.0 +Version: 0.14.0 Release: 0 URL: http://thrift.apache.org Packager: Thrift Developers diff --git a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj index f4a26de45f7..25899705c13 100644 --- a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj +++ b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj @@ -45,7 +45,7 @@ false true 0 - 0.13.0.0 + 0.14.0.0 false false true diff --git a/lib/csharp/src/Thrift.csproj b/lib/csharp/src/Thrift.csproj index da69554d1e9..13054821d7d 100644 --- a/lib/csharp/src/Thrift.csproj +++ b/lib/csharp/src/Thrift.csproj @@ -45,7 +45,7 @@ false true 0 - 0.13.0.0 + 0.14.0.0 false false true diff --git a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj index 09d20f50326..551640ba6ba 100644 --- a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj +++ b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj @@ -46,7 +46,7 @@ false true 0 - 0.13.0.0 + 0.14.0.0 false true diff --git a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs index 2b8a6af2330..50b11af2b23 100644 --- a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.13.0.0")] -[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyVersion("0.14.0.0")] +[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs b/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs index b812aaf1d1a..a87107cb992 100644 --- a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs @@ -49,5 +49,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.13.0.0")] -[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyVersion("0.14.0.0")] +[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/lib/d/src/thrift/base.d b/lib/d/src/thrift/base.d index 150c3da8e74..4a8fbd7599e 100644 --- a/lib/d/src/thrift/base.d +++ b/lib/d/src/thrift/base.d @@ -50,7 +50,7 @@ class TCompoundOperationException : TException { /// The Thrift version string, used for informative purposes. // Note: This is currently hardcoded, but will likely be filled in by the build // system in future versions. -enum VERSION = "0.13.0"; +enum VERSION = "0.14.0"; /** * Functions used for logging inside Thrift. diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index 2ee83441b68..e127380cab5 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -27,7 +27,7 @@ interface Thrift.Protocol; const - Version = '0.13.0'; + Version = '0.14.0'; type TException = Thrift.Exception.TException; // compatibility alias diff --git a/lib/haxe/haxelib.json b/lib/haxe/haxelib.json index b3c15308df3..d0e437ba396 100644 --- a/lib/haxe/haxelib.json +++ b/lib/haxe/haxelib.json @@ -4,7 +4,7 @@ "license": "Apache", "tags": ["thrift", "rpc", "serialization", "cross", "framework"], "description": "Haxe bindings for the Apache Thrift RPC and serialization framework", - "version": "0.13.0", + "version": "0.14.0", "releasenote": "Licensed under Apache License, Version 2.0. The Apache Thrift compiler needs to be installed separately.", "contributors": ["Apache Software Foundation (ASF)"], "dependencies": { }, diff --git a/lib/hs/thrift.cabal b/lib/hs/thrift.cabal index dd30d89f1b3..c60effbe891 100644 --- a/lib/hs/thrift.cabal +++ b/lib/hs/thrift.cabal @@ -18,7 +18,7 @@ -- Name: thrift -Version: 0.13.0 +Version: 0.14.0 Cabal-Version: 1.24 License: Apache Category: Foreign diff --git a/lib/java/gradle.properties b/lib/java/gradle.properties index 0811659106a..c5d2a1b14a3 100644 --- a/lib/java/gradle.properties +++ b/lib/java/gradle.properties @@ -1,7 +1,7 @@ # This file is shared currently between this Gradle build and the # Ant builds for fd303 and JavaScript. Keep the dotted notation for # the properties to minimize the changes in the dependencies. -thrift.version=0.13.0 +thrift.version=0.14.0 thrift.groupid=org.apache.thrift release=false diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 21a3d65fc20..69bcccdd23f 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -46,7 +46,7 @@ var Thrift = { * @const {string} Version * @memberof Thrift */ - Version: '0.13.0', + Version: '0.14.0', /** * Thrift IDL type string to Id mapping. diff --git a/lib/lua/Thrift.lua b/lib/lua/Thrift.lua index a948b3dcb25..4a290de5cb8 100644 --- a/lib/lua/Thrift.lua +++ b/lib/lua/Thrift.lua @@ -48,7 +48,7 @@ function ttable_size(t) return count end -version = '0.13.0' +version = '0.14.0' TType = { STOP = 0, diff --git a/lib/netcore/Thrift/Properties/AssemblyInfo.cs b/lib/netcore/Thrift/Properties/AssemblyInfo.cs index 0f433b6003d..58aa84495d2 100644 --- a/lib/netcore/Thrift/Properties/AssemblyInfo.cs +++ b/lib/netcore/Thrift/Properties/AssemblyInfo.cs @@ -52,5 +52,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.13.0.0")] -[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyVersion("0.14.0.0")] +[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs index 8bce9e4a019..b2ff8040cbf 100644 --- a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs +++ b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs @@ -150,7 +150,7 @@ private HttpClient CreateClient() } httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); - httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "0.13.0")); + httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "0.14.0")); if (CustomHeaders != null) { diff --git a/lib/netstd/Thrift/Properties/AssemblyInfo.cs b/lib/netstd/Thrift/Properties/AssemblyInfo.cs index e3118ab23be..58aa84495d2 100644 --- a/lib/netstd/Thrift/Properties/AssemblyInfo.cs +++ b/lib/netstd/Thrift/Properties/AssemblyInfo.cs @@ -52,5 +52,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.1")] -[assembly: AssemblyFileVersion("1.0.0.1")] \ No newline at end of file +[assembly: AssemblyVersion("0.14.0.0")] +[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/lib/rb/thrift.gemspec b/lib/rb/thrift.gemspec index 869e5d95d88..3ee7e7cbfef 100644 --- a/lib/rb/thrift.gemspec +++ b/lib/rb/thrift.gemspec @@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__) Gem::Specification.new do |s| s.name = 'thrift' - s.version = '0.13.0' + s.version = '0.14.0' s.authors = ['Apache Thrift Developers'] s.email = ['dev@thrift.apache.org'] s.homepage = 'http://thrift.apache.org' diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml index 69da0f39957..0c71bab4195 100644 --- a/lib/rs/Cargo.toml +++ b/lib/rs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "thrift" description = "Rust bindings for the Apache Thrift RPC system" -version = "0.13.0" +version = "0.14.0" license = "Apache-2.0" authors = ["Apache Thrift Developers "] homepage = "http://thrift.apache.org" diff --git a/lib/st/package.xml b/lib/st/package.xml index 21b7adcd2eb..eab405225e2 100644 --- a/lib/st/package.xml +++ b/lib/st/package.xml @@ -17,7 +17,7 @@ specific language governing permissions and limitations under the License. --> - + libthrift-st thrift.st diff --git a/lib/ts/package.json b/lib/ts/package.json index eda1c0aea55..1cd6c710033 100644 --- a/lib/ts/package.json +++ b/lib/ts/package.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.13.0", + "version": "0.14.0", "description": "Thrift is a software framework for scalable cross-language services development.", "author": { "name": "Apache Thrift Developers", diff --git a/package.json b/package.json index 6393ee7128d..c674fef8355 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://github.com/apache/thrift.git" }, - "version": "0.13.0", + "version": "0.14.0", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org", diff --git a/test/csharp/Properties/AssemblyInfo.cs b/test/csharp/Properties/AssemblyInfo.cs index 76c9a80dd43..376ff253ff2 100644 --- a/test/csharp/Properties/AssemblyInfo.cs +++ b/test/csharp/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.13.0.0")] -[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyVersion("0.14.0.0")] +[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs index bae5e70c983..8f5b32a2842 100644 --- a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs +++ b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.13.0.0")] -[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyVersion("0.14.0.0")] +[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/tutorial/dart/console_client/pubspec.yaml b/tutorial/dart/console_client/pubspec.yaml index ca122d2fde4..1068f909cc6 100644 --- a/tutorial/dart/console_client/pubspec.yaml +++ b/tutorial/dart/console_client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_console_client -version: 0.13.0 +version: 0.14.0 description: > A Dart console client to implementation of the Apache Thrift tutorial author: Apache Thrift Developers diff --git a/tutorial/dart/server/pubspec.yaml b/tutorial/dart/server/pubspec.yaml index e09465e704a..bdd74b826f9 100644 --- a/tutorial/dart/server/pubspec.yaml +++ b/tutorial/dart/server/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_server -version: 0.13.0 +version: 0.14.0 description: A Dart server to support the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/tutorial/delphi/DelphiServer/DelphiServer.dproj b/tutorial/delphi/DelphiServer/DelphiServer.dproj index ec1da2e693c..132d1bfb42b 100644 --- a/tutorial/delphi/DelphiServer/DelphiServer.dproj +++ b/tutorial/delphi/DelphiServer/DelphiServer.dproj @@ -97,13 +97,13 @@ Thrift Tutorial - 0.13.0.0 + 0.14.0.0 DelphiServer Copyright © 2012 The Apache Software Foundation DelphiServer.exe Thrift - 0.13.0.0 + 0.14.0.0 diff --git a/tutorial/hs/ThriftTutorial.cabal b/tutorial/hs/ThriftTutorial.cabal index b6a612216e4..acf2130bfd4 100755 --- a/tutorial/hs/ThriftTutorial.cabal +++ b/tutorial/hs/ThriftTutorial.cabal @@ -18,7 +18,7 @@ -- Name: ThriftTutorial -Version: 0.13.0 +Version: 0.14.0 Cabal-Version: >= 1.4 License: OtherLicense Category: Foreign diff --git a/tutorial/ocaml/_oasis b/tutorial/ocaml/_oasis index 4a4f337b3a6..7491436e933 100644 --- a/tutorial/ocaml/_oasis +++ b/tutorial/ocaml/_oasis @@ -1,5 +1,5 @@ Name: tutorial -Version: 0.13.0 +Version: 0.14.0 OASISFormat: 0.3 Synopsis: OCaml Tutorial example Authors: Apache Thrift Developers From dd14e869ce5262307f796fee20baee17eb00a608 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 17 Oct 2019 20:54:34 +0200 Subject: [PATCH 393/756] Fix PHP style errors (by means of phpcbf) --- lib/php/test/Fixtures.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/php/test/Fixtures.php b/lib/php/test/Fixtures.php index fd57d831c5e..996f4af36cd 100644 --- a/lib/php/test/Fixtures.php +++ b/lib/php/test/Fixtures.php @@ -66,32 +66,32 @@ public static function populateTestArgs() self::$testArgs['testStruct'] = new Xtruct( - array( + array( 'string_thing' => 'worked', 'byte_thing' => 0x01, 'i32_thing' => pow(2, 30), 'i64_thing' => self::$testArgs['testI64'] ) - ); + ); self::$testArgs['testNestNested'] = new Xtruct( - array( + array( 'string_thing' => 'worked', 'byte_thing' => 0x01, 'i32_thing' => pow(2, 30), 'i64_thing' => self::$testArgs['testI64'] ) - ); + ); self::$testArgs['testNest'] = new Xtruct2( - array( + array( 'byte_thing' => 0x01, 'struct_thing' => self::$testArgs['testNestNested'], 'i32_thing' => pow(2, 15) ) - ); + ); self::$testArgs['testMap'] = array( @@ -138,23 +138,23 @@ public static function populateTestArgs() $xtruct1 = new Xtruct( - array( + array( 'string_thing' => 'Goodbye4', 'byte_thing' => 4, 'i32_thing' => 4, 'i64_thing' => 4 ) - ); + ); $xtruct2 = new Xtruct( - array( + array( 'string_thing' => 'Hello2', 'byte_thing' => 2, 'i32_thing' => 2, 'i64_thing' => 2 ) - ); + ); $userMap = array( @@ -164,21 +164,21 @@ public static function populateTestArgs() $insanity2 = new Insanity( - array( + array( 'userMap' => $userMap, 'xtructs' => array($xtruct1, $xtruct2) ) - ); + ); $insanity3 = $insanity2; $insanity6 = new Insanity( - array( + array( 'userMap' => null, 'xtructs' => null ) - ); + ); self::$testArgs['testInsanityExpectedResult'] = array( From b75e88a33d67ae05ef9b5fa001d2a63a2effe377 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 17 Oct 2019 21:56:39 +0200 Subject: [PATCH 394/756] FIX netstd assembly version --- build/veralign.sh | 1 + lib/netstd/Thrift/Properties/AssemblyInfo.cs | 5 +++-- lib/netstd/Thrift/Thrift.csproj | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build/veralign.sh b/build/veralign.sh index 56c436a8136..1dd1e6f4a10 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -80,6 +80,7 @@ FILES[lib/netcore/Thrift/Properties/AssemblyInfo.cs]=simpleReplace FILES[lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs]=simpleReplace FILES[lib/netstd/Thrift/Properties/AssemblyInfo.cs]=simpleReplace FILES[lib/netstd/Thrift/Transports/Client/THttpClientTransport.cs]=simpleReplace +FILES[lib/netstd/Thrift/Thrift.csproj]=simpleReplace FILES[lib/ocaml/_oasis]=simpleReplace FILES[lib/perl/lib/Thrift.pm]=simpleReplace FILES[lib/py/setup.py]=simpleReplace diff --git a/lib/netstd/Thrift/Properties/AssemblyInfo.cs b/lib/netstd/Thrift/Properties/AssemblyInfo.cs index e3118ab23be..597290de5a9 100644 --- a/lib/netstd/Thrift/Properties/AssemblyInfo.cs +++ b/lib/netstd/Thrift/Properties/AssemblyInfo.cs @@ -52,5 +52,6 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.1")] -[assembly: AssemblyFileVersion("1.0.0.1")] \ No newline at end of file +[assembly: AssemblyVersion("0.13.0.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] + diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj index 46d530e300b..ceb4409c01e 100644 --- a/lib/netstd/Thrift/Thrift.csproj +++ b/lib/netstd/Thrift/Thrift.csproj @@ -39,6 +39,7 @@ true thrift.snk false + 0.13.0.0 From 5fe31ea7d728a2f0a4de4aae7479d6fe3ec93f5a Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 17 Oct 2019 23:51:36 +0200 Subject: [PATCH 395/756] bump version --- lib/netstd/Thrift/Thrift.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj index ceb4409c01e..5d8a9c3c966 100644 --- a/lib/netstd/Thrift/Thrift.csproj +++ b/lib/netstd/Thrift/Thrift.csproj @@ -39,7 +39,7 @@ true thrift.snk false - 0.13.0.0 + 0.14.0.0 From 58efe895b5878b6cffc1b054b7a9a92fef041647 Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Wed, 9 Oct 2019 22:23:16 +0900 Subject: [PATCH 396/756] THRIFT-4972: Add Makefile.am to the Perl tutorial Client: Perl Patch: Kengo Seki This closes #1893 --- configure.ac | 1 + tutorial/Makefile.am | 5 ++++- tutorial/perl/Makefile.am | 36 ++++++++++++++++++++++++++++++++++++ tutorial/perl/PerlClient.pl | 2 +- tutorial/perl/PerlServer.pl | 3 ++- 5 files changed, 44 insertions(+), 3 deletions(-) create mode 100755 tutorial/perl/Makefile.am diff --git a/configure.ac b/configure.ac index 27846995ae1..adebe9e4874 100755 --- a/configure.ac +++ b/configure.ac @@ -871,6 +871,7 @@ AC_CONFIG_FILES([ tutorial/netstd/Makefile tutorial/nodejs/Makefile tutorial/dart/Makefile + tutorial/perl/Makefile tutorial/py/Makefile tutorial/py.twisted/Makefile tutorial/py.tornado/Makefile diff --git a/tutorial/Makefile.am b/tutorial/Makefile.am index 17a92573b44..9160ad08c5b 100755 --- a/tutorial/Makefile.am +++ b/tutorial/Makefile.am @@ -83,6 +83,10 @@ if WITH_CL SUBDIRS += cl endif +if WITH_PERL +SUBDIRS += perl +endif + # # generate html for ThriftTest.thrift # @@ -104,7 +108,6 @@ EXTRA_DIST = \ erl \ hs \ ocaml \ - perl \ php \ shared.thrift \ tutorial.thrift \ diff --git a/tutorial/perl/Makefile.am b/tutorial/perl/Makefile.am new file mode 100755 index 00000000000..fe77213bbf3 --- /dev/null +++ b/tutorial/perl/Makefile.am @@ -0,0 +1,36 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +gen-perl/tutorial/Calculator.pm gen-perl/shared/SharedService.pm: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen perl -r $< + +all-local: gen-perl/tutorial/Calculator.pm + +tutorialserver: all + ${PERL} PerlServer.pl + +tutorialclient: all + ${PERL} PerlClient.pl + +clean-local: + $(RM) -r gen-* + +EXTRA_DIST = \ + PerlServer.pl \ + PerlClient.pl diff --git a/tutorial/perl/PerlClient.pl b/tutorial/perl/PerlClient.pl index 7c23289ce5a..5f6a3b2d1dc 100644 --- a/tutorial/perl/PerlClient.pl +++ b/tutorial/perl/PerlClient.pl @@ -23,7 +23,7 @@ use warnings; use lib '../../lib/perl/lib'; -use lib '../gen-perl'; +use lib 'gen-perl'; use Thrift; use Thrift::BinaryProtocol; diff --git a/tutorial/perl/PerlServer.pl b/tutorial/perl/PerlServer.pl index ee5d9367404..15129873101 100644 --- a/tutorial/perl/PerlServer.pl +++ b/tutorial/perl/PerlServer.pl @@ -20,7 +20,8 @@ # use strict; -use lib '../gen-perl'; +use lib '../../lib/perl/lib'; +use lib 'gen-perl'; use Thrift::Socket; use Thrift::Server; use Thrift::ServerSocket; From 9f0548e05f1b1383cc122148d60cc40383ce599e Mon Sep 17 00:00:00 2001 From: pengzhouhu Date: Fri, 6 Sep 2019 17:04:24 +0800 Subject: [PATCH 397/756] THRIFT-4952 Modified ssl_read feedback value break all the time error. Client: c_glib Patch: pengzhouhu This closes #1869 --- lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c index df17fa6ee20..a41e9c63af6 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c @@ -291,7 +291,7 @@ thrift_ssl_socket_read (ThriftTransport *transport, gpointer buf, { guint maxRecvRetries_ = 10; ThriftSSLSocket *ssl_socket = THRIFT_SSL_SOCKET (transport); - guint bytes = 0; + gint32 bytes = 0; guint retries = 0; ThriftSocket *socket = THRIFT_SOCKET (transport); g_return_val_if_fail (socket->sd != THRIFT_INVALID_SOCKET && ssl_socket->ssl!=NULL, FALSE); From 538e36c645d6e56748c6af3ef80ef21b26646ed2 Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Fri, 18 Oct 2019 22:09:01 +0900 Subject: [PATCH 398/756] THRIFT-4975: Add Makefile.am to the PHP tutorial Client: php This closes #1900. --- configure.ac | 1 + tutorial/Makefile.am | 5 ++++- tutorial/php/Makefile.am | 36 ++++++++++++++++++++++++++++++++++++ tutorial/php/PhpClient.php | 2 +- tutorial/php/PhpServer.php | 2 +- 5 files changed, 43 insertions(+), 3 deletions(-) create mode 100755 tutorial/php/Makefile.am diff --git a/configure.ac b/configure.ac index adebe9e4874..48923626c0b 100755 --- a/configure.ac +++ b/configure.ac @@ -872,6 +872,7 @@ AC_CONFIG_FILES([ tutorial/nodejs/Makefile tutorial/dart/Makefile tutorial/perl/Makefile + tutorial/php/Makefile tutorial/py/Makefile tutorial/py.twisted/Makefile tutorial/py.tornado/Makefile diff --git a/tutorial/Makefile.am b/tutorial/Makefile.am index 9160ad08c5b..49d18fb2606 100755 --- a/tutorial/Makefile.am +++ b/tutorial/Makefile.am @@ -87,6 +87,10 @@ if WITH_PERL SUBDIRS += perl endif +if WITH_PHP +SUBDIRS += php +endif + # # generate html for ThriftTest.thrift # @@ -108,7 +112,6 @@ EXTRA_DIST = \ erl \ hs \ ocaml \ - php \ shared.thrift \ tutorial.thrift \ README.md diff --git a/tutorial/php/Makefile.am b/tutorial/php/Makefile.am new file mode 100755 index 00000000000..65f48795140 --- /dev/null +++ b/tutorial/php/Makefile.am @@ -0,0 +1,36 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +gen-php/tutorial/Calculator.php gen-php/shared/SharedService.php: $(top_srcdir)/tutorial/tutorial.thrift + $(THRIFT) --gen php:server -r $< + +all-local: gen-php/tutorial/Calculator.php + +tutorialserver: all + ${PYTHON} runserver.py + +tutorialclient: all + ${PHP} PhpClient.php --http + +clean-local: + $(RM) -r gen-* + +EXTRA_DIST = \ + PhpServer.php \ + PhpClient.php diff --git a/tutorial/php/PhpClient.php b/tutorial/php/PhpClient.php index eb2c2e5ee4c..5ac154718b3 100755 --- a/tutorial/php/PhpClient.php +++ b/tutorial/php/PhpClient.php @@ -9,7 +9,7 @@ use Thrift\ClassLoader\ThriftClassLoader; -$GEN_DIR = realpath(dirname(__FILE__).'/..').'/gen-php'; +$GEN_DIR = realpath(dirname(__FILE__)).'/gen-php'; $loader = new ThriftClassLoader(); $loader->registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib'); diff --git a/tutorial/php/PhpServer.php b/tutorial/php/PhpServer.php index 749da3a0b2c..f4b3b319f2a 100755 --- a/tutorial/php/PhpServer.php +++ b/tutorial/php/PhpServer.php @@ -9,7 +9,7 @@ use Thrift\ClassLoader\ThriftClassLoader; -$GEN_DIR = realpath(dirname(__FILE__).'/..').'/gen-php'; +$GEN_DIR = realpath(dirname(__FILE__)).'/gen-php'; $loader = new ThriftClassLoader(); $loader->registerNamespace('Thrift', __DIR__ . '/../../lib/php/lib'); From 76fa8c9a81621aae254e10c19c68b31b41f5b4b7 Mon Sep 17 00:00:00 2001 From: "D. Can Celasun" Date: Fri, 18 Oct 2019 15:15:45 +0100 Subject: [PATCH 399/756] Update Java dependencies Update most dependencies to their latest versions, replace findbugs with spotbugs as the former is dead and was replaced with the latter. Fixes THRIFT-4937. Client: java --- lib/java/build.gradle | 6 ++++++ lib/java/gradle.properties | 8 ++++---- lib/java/gradle/codeQualityChecks.gradle | 13 +++++++++---- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/lib/java/build.gradle b/lib/java/build.gradle index 5f0d2782bee..9184f7b97e3 100644 --- a/lib/java/build.gradle +++ b/lib/java/build.gradle @@ -36,6 +36,12 @@ plugins { id 'maven' id 'signing' id 'com.github.johnrengelman.shadow' version '4.0.4' + id "com.github.spotbugs" version "2.0.0" +} + +ext { + // https://github.com/spotbugs/spotbugs-gradle-plugin/issues/32#issuecomment-409951172 + SpotBugsTask = com.github.spotbugs.SpotBugsTask } description = 'Apache Thrift Java Library' diff --git a/lib/java/gradle.properties b/lib/java/gradle.properties index c5d2a1b14a3..8559464c9da 100644 --- a/lib/java/gradle.properties +++ b/lib/java/gradle.properties @@ -25,10 +25,10 @@ maven-repository-url=https://repository.apache.org/service/local/staging/deploy/ maven-repository-id=apache.releases.https # Dependency versions -httpclient.version=4.5.6 -httpcore.version=4.4.1 -slf4j.version=1.7.25 +httpclient.version=4.5.10 +httpcore.version=4.4.12 +slf4j.version=1.7.28 servlet.version=2.5 junit.version=4.12 -mockito.version=1.9.5 +mockito.version=1.10.19 javax.annotation.version=1.3.2 diff --git a/lib/java/gradle/codeQualityChecks.gradle b/lib/java/gradle/codeQualityChecks.gradle index 1ff1c297dea..b0662875900 100644 --- a/lib/java/gradle/codeQualityChecks.gradle +++ b/lib/java/gradle/codeQualityChecks.gradle @@ -3,18 +3,23 @@ // Configure the Gradle code quality plugins here. // -apply plugin: 'findbugs' +dependencies { + spotbugs configurations.spotbugsPlugins.dependencies + spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.8.0' +} + +apply plugin: 'com.github.spotbugs' -findbugs { +spotbugs{ ignoreFailures = true - toolVersion = '3.0.1' + toolVersion = '3.1.12' sourceSets = [ sourceSets.main ] effort = 'max' reportLevel = 'low' excludeFilter = file('code_quality_tools/findbugs-filter.xml') } -tasks.withType(FindBugs) { +tasks.withType(SpotBugsTask) { reports { text.enabled = false html.enabled = true From 6701dbb8e89f6550c7843e9b75b118998df471c3 Mon Sep 17 00:00:00 2001 From: Qinghui Xu Date: Sun, 13 Oct 2019 22:19:42 +0200 Subject: [PATCH 400/756] THRIFT-4976: Delay 1 second before recompiling Patch: Qinghui Xu This closes #1898 In some environment, the file system only has second accuracy on file modification timestamp, so delay of 0.1 second before recompiling could makes the modification timestamp unchanged. --- compiler/cpp/test/compiler/staleness_check.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/cpp/test/compiler/staleness_check.py b/compiler/cpp/test/compiler/staleness_check.py index 5b11dff9e52..6b67798d6a4 100755 --- a/compiler/cpp/test/compiler/staleness_check.py +++ b/compiler/cpp/test/compiler/staleness_check.py @@ -46,7 +46,7 @@ def test_staleness_check_of_single_thrift_file_without_changed_output(self): first_modification_time = os.path.getmtime(os.path.join(used_file_path)) - time.sleep(0.1) + time.sleep(1.0) subprocess.call(command) @@ -74,7 +74,7 @@ def test_staleness_check_of_single_thrift_file_with_changed_output(self): used_file.write("\n/* This is a comment */\n") used_file.close() - time.sleep(0.1) + time.sleep(1.0) subprocess.call(command) @@ -112,7 +112,7 @@ def test_staleness_check_of_included_file(self): temp_included_file.write("\nconst i32 an_integer = 42\n") temp_included_file.close() - time.sleep(0.1) + time.sleep(1.0) subprocess.call(command) From 616df98f00a594f133466aa7f94930c1bf85b24a Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 19 Oct 2019 22:08:13 +0200 Subject: [PATCH 401/756] fix veralign.sh and bump version (again) --- Thrift.podspec | 4 ++-- build/veralign.sh | 4 +++- doc/specs/idl.md | 2 +- lib/as3/gradle.properties | 2 +- lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs | 4 ++-- lib/csharp/src/Properties/AssemblyInfo.cs | 4 ++-- lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs | 4 ++-- lib/csharp/test/Multiplex/Server/MultiplexServer.csproj | 2 +- lib/dart/pubspec.yaml | 2 +- lib/erl/src/thrift.app.src | 2 +- lib/js/package-lock.json | 2 +- lib/js/package.json | 2 +- lib/ocaml/_oasis | 2 +- lib/perl/lib/Thrift.pm | 2 +- lib/py/setup.py | 2 +- lib/swift/Sources/Thrift.swift | 2 +- lib/swift/Tests/ThriftTests/ThriftTests.swift | 2 +- lib/ts/package-lock.json | 2 +- package-lock.json | 2 +- sonar-project.properties | 6 +++--- test/csharp/ThriftTest.csproj | 2 +- test/dart/test_client/pubspec.yaml | 2 +- test/erl/src/thrift_test.app.src | 2 +- tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs | 4 ++-- tutorial/dart/client/pubspec.yaml | 2 +- tutorial/delphi/DelphiClient/DelphiClient.dproj | 4 ++-- 26 files changed, 36 insertions(+), 34 deletions(-) diff --git a/Thrift.podspec b/Thrift.podspec index 4c8fa68aced..46de2b40547 100644 --- a/Thrift.podspec +++ b/Thrift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'Thrift' - s.version = '0.13.0' + s.version = '0.14.0' s.summary = "Apache Thrift is a lightweight, language-independent software stack with an associated code generation mechanism for RPC." s.description = <<-DESC The Apache Thrift scalable cross-language software framework for networked services development combines a software stack with a code generation engine to build services that work efficiently and seamlessly between many programming languages. @@ -10,6 +10,6 @@ The Apache Thrift scalable cross-language software framework for networked servi s.author = { 'Apache Thrift Developers' => 'dev@thrift.apache.org' } s.ios.deployment_target = '9.0' s.osx.deployment_target = '10.10' - s.source = { :git => 'https://github.com/apache/thrift.git', :tag => 'v0.13.0' } + s.source = { :git => 'https://github.com/apache/thrift.git', :tag => 'v0.14.0' } s.source_files = 'lib/swift/Sources/*.swift' end diff --git a/build/veralign.sh b/build/veralign.sh index 1dd1e6f4a10..ffecb6e30d6 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -74,12 +74,12 @@ FILES[lib/haxe/haxelib.json]=simpleReplace FILES[lib/hs/thrift.cabal]=simpleReplace FILES[lib/java/gradle.properties]=simpleReplace FILES[lib/js/package.json]=jsonReplace +FILES[lib/js/package-lock.json]=jsonReplace FILES[lib/js/src/thrift.js]=simpleReplace FILES[lib/lua/Thrift.lua]=simpleReplace FILES[lib/netcore/Thrift/Properties/AssemblyInfo.cs]=simpleReplace FILES[lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs]=simpleReplace FILES[lib/netstd/Thrift/Properties/AssemblyInfo.cs]=simpleReplace -FILES[lib/netstd/Thrift/Transports/Client/THttpClientTransport.cs]=simpleReplace FILES[lib/netstd/Thrift/Thrift.csproj]=simpleReplace FILES[lib/ocaml/_oasis]=simpleReplace FILES[lib/perl/lib/Thrift.pm]=simpleReplace @@ -90,7 +90,9 @@ FILES[lib/st/package.xml]=simpleReplace FILES[lib/swift/Sources/Thrift.swift]=simpleReplace FILES[lib/swift/Tests/ThriftTests/ThriftTests.swift]=simpleReplace FILES[lib/ts/package.json]=jsonReplace +FILES[lib/ts/package-lock.json]=jsonReplace FILES[package.json]=jsonReplace +FILES[package-lock.json]=jsonReplace FILES[sonar-project.properties]=simpleReplace FILES[test/csharp/Properties/AssemblyInfo.cs]=simpleReplace FILES[test/csharp/ThriftTest.csproj]=simpleReplace diff --git a/doc/specs/idl.md b/doc/specs/idl.md index 9439bee4e20..32763a6b6b8 100644 --- a/doc/specs/idl.md +++ b/doc/specs/idl.md @@ -1,6 +1,6 @@ ## Thrift interface description language -For Thrift version 0.13.0. +For Thrift version 0.14.0. The Thrift interface definition language (IDL) allows for the definition of [Thrift Types](/docs/types). A Thrift IDL file is processed by the Thrift code generator to produce code for the various target languages to support the defined structs and services in the IDL file. diff --git a/lib/as3/gradle.properties b/lib/as3/gradle.properties index 02d5eefad6e..d918a23f542 100644 --- a/lib/as3/gradle.properties +++ b/lib/as3/gradle.properties @@ -1,7 +1,7 @@ # This file is shared currently between this Gradle build and the # Ant builds for fd303 and JavaScript. Keep the dotted notation for # the properties to minimize the changes in the dependencies. -thrift.version=0.13.0 +thrift.version=0.14.0 thrift.groupid=org.apache.thrift release=false sign=false diff --git a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs index 6e99dd9fd5e..f5f00005976 100644 --- a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs +++ b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs @@ -56,5 +56,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.13.0.*")] -[assembly: AssemblyFileVersion("0.13.0.*")] +[assembly: AssemblyVersion("0.14.0.*")] +[assembly: AssemblyFileVersion("0.14.0.*")] diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs index ace031045f7..c8f51b5c076 100644 --- a/lib/csharp/src/Properties/AssemblyInfo.cs +++ b/lib/csharp/src/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("0.13.0.0")] -[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyVersion("0.14.0.0")] +[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs index 0b65c1e5257..ce6692fb0d3 100644 --- a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs +++ b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.13.0.0")] -[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyVersion("0.14.0.0")] +[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj index 23d32536289..771ee1266e0 100644 --- a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj +++ b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj @@ -46,7 +46,7 @@ false true 0 - 0.13.0.0 + 0.14.0.0 false true diff --git a/lib/dart/pubspec.yaml b/lib/dart/pubspec.yaml index f406b9932cf..1999b58247b 100644 --- a/lib/dart/pubspec.yaml +++ b/lib/dart/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: thrift -version: 0.13.0 +version: 0.14.0 description: > A Dart library for Apache Thrift author: Apache Thrift Developers diff --git a/lib/erl/src/thrift.app.src b/lib/erl/src/thrift.app.src index e5e6ed5cf2c..5e8d670f2b6 100644 --- a/lib/erl/src/thrift.app.src +++ b/lib/erl/src/thrift.app.src @@ -22,7 +22,7 @@ {description, "Thrift bindings"}, % The version of the applicaton - {vsn, "0.13.0"}, + {vsn, "0.14.0"}, % All modules used by the application. {modules, [ diff --git a/lib/js/package-lock.json b/lib/js/package-lock.json index 00bf05c9223..dfde697c88d 100644 --- a/lib/js/package-lock.json +++ b/lib/js/package-lock.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.13.0", + "version": "0.14.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/lib/js/package.json b/lib/js/package.json index 309622dfda8..f578e4ba2ee 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.13.0", + "version": "0.14.0", "description": "Thrift is a software framework for scalable cross-language services development.", "author": { "name": "Apache Thrift Developers", diff --git a/lib/ocaml/_oasis b/lib/ocaml/_oasis index 83566aaa9e8..2b6c477b061 100644 --- a/lib/ocaml/_oasis +++ b/lib/ocaml/_oasis @@ -1,5 +1,5 @@ Name: libthrift-ocaml -Version: 0.13.0 +Version: 0.14.0 OASISFormat: 0.3 Synopsis: OCaml bindings for the Apache Thrift RPC system Authors: Apache Thrift Developers diff --git a/lib/perl/lib/Thrift.pm b/lib/perl/lib/Thrift.pm index 01985ea87c1..9a7c6bbf873 100644 --- a/lib/perl/lib/Thrift.pm +++ b/lib/perl/lib/Thrift.pm @@ -31,6 +31,6 @@ use warnings; # package Thrift; -use version 0.77; our $VERSION = version->declare("v0.13.0"); +use version 0.77; our $VERSION = version->declare("v0.14.0"); 1; diff --git a/lib/py/setup.py b/lib/py/setup.py index 2ba26915979..fa81694a517 100644 --- a/lib/py/setup.py +++ b/lib/py/setup.py @@ -90,7 +90,7 @@ def run_setup(with_binary): twisted_deps = ['twisted'] setup(name='thrift', - version='0.13.0', + version='0.14.0', description='Python bindings for the Apache Thrift RPC system', author='Apache Thrift Developers', author_email='dev@thrift.apache.org', diff --git a/lib/swift/Sources/Thrift.swift b/lib/swift/Sources/Thrift.swift index 45c68f2e535..789aae9e7dd 100644 --- a/lib/swift/Sources/Thrift.swift +++ b/lib/swift/Sources/Thrift.swift @@ -1,3 +1,3 @@ class Thrift { - let version = "0.13.0" + let version = "0.14.0" } diff --git a/lib/swift/Tests/ThriftTests/ThriftTests.swift b/lib/swift/Tests/ThriftTests/ThriftTests.swift index ae47f388cbb..37f3cf68927 100644 --- a/lib/swift/Tests/ThriftTests/ThriftTests.swift +++ b/lib/swift/Tests/ThriftTests/ThriftTests.swift @@ -3,7 +3,7 @@ import XCTest class ThriftTests: XCTestCase { func testVersion() { - XCTAssertEqual(Thrift().version, "0.13.0") + XCTAssertEqual(Thrift().version, "0.14.0") } func test_in_addr_extension() { diff --git a/lib/ts/package-lock.json b/lib/ts/package-lock.json index 8d0a7ff2f3c..49de90bf499 100644 --- a/lib/ts/package-lock.json +++ b/lib/ts/package-lock.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.13.0", + "version": "0.14.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package-lock.json b/package-lock.json index 8eb8a212236..e88fb1e1fb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "thrift", - "version": "0.13.0", + "version": "0.14.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/sonar-project.properties b/sonar-project.properties index a238197cb18..fcda4776272 100755 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -16,7 +16,7 @@ development, combines a software stack with a code generation engine to build services that work efficiently and seamlessly between all major languages. # Apache Thrift Version -sonar.projectVersion=0.13.0 +sonar.projectVersion=0.14.0 # use this to set another version string # $ sonar-runner -D sonar.projectVersion=`git rev-parse HEAD` # set projectDate in combination with projectVersion for imports of old releases @@ -54,7 +54,7 @@ module1.sonar.projectName=Apache Thrift - Java Library module1.sonar.projectBaseDir=lib/java module1.sonar.sources=src module1.sonar.tests=test -module1.sonar.binaries=build/libs/libthrift-0.13.0.jar +module1.sonar.binaries=build/libs/libthrift-0.14.0.jar module1.sonar.libraries=build/deps/*.jar module1.sonar.language=java @@ -62,7 +62,7 @@ module2.sonar.projectName=Apache Thrift - Java Tutorial module2.sonar.projectBaseDir=. module2.sonar.sources=tutorial/java/src, tutorial/java/gen-java module2.sonar.binaries=tutorial/java/tutorial.jar -module2.sonar.libraries=lib/java/build/deps/*.jar,lib/java/build/libs/libthrift-0.13.0.jar +module2.sonar.libraries=lib/java/build/deps/*.jar,lib/java/build/libs/libthrift-0.14.0.jar module2.sonar.language=java module3.sonar.projectName=Apache Thrift - JavaScript Library diff --git a/test/csharp/ThriftTest.csproj b/test/csharp/ThriftTest.csproj index effec197940..2ff092673c8 100644 --- a/test/csharp/ThriftTest.csproj +++ b/test/csharp/ThriftTest.csproj @@ -46,7 +46,7 @@ false true 0 - 0.13.0.0 + 0.14.0.0 false true diff --git a/test/dart/test_client/pubspec.yaml b/test/dart/test_client/pubspec.yaml index c86225eeea6..648196214df 100644 --- a/test/dart/test_client/pubspec.yaml +++ b/test/dart/test_client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: thrift_test_client -version: 0.13.0 +version: 0.14.0 description: A client integration test for the Dart Thrift library author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/test/erl/src/thrift_test.app.src b/test/erl/src/thrift_test.app.src index ffbad58835a..b6242b3eef2 100644 --- a/test/erl/src/thrift_test.app.src +++ b/test/erl/src/thrift_test.app.src @@ -22,7 +22,7 @@ {description, "Thrift cross language test"}, % The version of the applicaton - {vsn, "0.13.0"}, + {vsn, "0.14.0"}, % All modules used by the application. {modules, [ diff --git a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs index e3ed39a9c62..0d4f0fbb1b7 100644 --- a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs +++ b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.13.0.0")] -[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyVersion("0.14.0.0")] +[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/tutorial/dart/client/pubspec.yaml b/tutorial/dart/client/pubspec.yaml index 6581b4d2180..35880ed0870 100644 --- a/tutorial/dart/client/pubspec.yaml +++ b/tutorial/dart/client/pubspec.yaml @@ -16,7 +16,7 @@ # under the License. name: tutorial_client -version: 0.13.0 +version: 0.14.0 description: A Dart client implementation of the Apache Thrift tutorial author: Apache Thrift Developers homepage: http://thrift.apache.org diff --git a/tutorial/delphi/DelphiClient/DelphiClient.dproj b/tutorial/delphi/DelphiClient/DelphiClient.dproj index 7026747d07b..f9adf858b23 100644 --- a/tutorial/delphi/DelphiClient/DelphiClient.dproj +++ b/tutorial/delphi/DelphiClient/DelphiClient.dproj @@ -100,13 +100,13 @@ Thrift Tutorial - 0.13.0.0 + 0.14.0.0 DelphiClient Copyright © 2012 The Apache Software Foundation DelphiClient.exe Thrift - 0.13.0.0 + 0.14.0.0 From 7199741f440ef7de15e13755ea2371157c8cd298 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 19 Oct 2019 21:22:59 +0200 Subject: [PATCH 402/756] THRIFT-4938 Issues with version.h treatment Client: Compiler Patch: Jens Geyer This closes #1902 --- build/veralign.sh | 1 + compiler/cpp/CMakeLists.txt | 5 +++-- compiler/cpp/Makefile.am | 5 +++-- compiler/cpp/src/thrift/{version.h.in => version.h} | 2 +- compiler/cpp/tests/CMakeLists.txt | 5 +++-- configure.ac | 1 - 6 files changed, 11 insertions(+), 8 deletions(-) rename compiler/cpp/src/thrift/{version.h.in => version.h} (95%) diff --git a/build/veralign.sh b/build/veralign.sh index ffecb6e30d6..39b67eb5be5 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -54,6 +54,7 @@ FILES[Thrift.podspec]=simpleReplace FILES[appveyor.yml]=simpleReplace FILES[bower.json]=jsonReplace FILES[configure.ac]=configureReplace +FILES[compiler/cpp/src/thrift/version.h]=simpleReplace FILES[contrib/thrift.spec]=simpleReplace FILES[doc/specs/idl.md]=simpleReplace FILES[lib/as3/gradle.properties]=simpleReplace diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt index 17dae4787b4..2bc08cfa624 100644 --- a/compiler/cpp/CMakeLists.txt +++ b/compiler/cpp/CMakeLists.txt @@ -20,7 +20,8 @@ cmake_minimum_required(VERSION 3.3) project("thrift-compiler" VERSION ${PACKAGE_VERSION}) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h) +# version.h now handled via veralign.sh +#configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/thrift/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h) find_package(FLEX REQUIRED) find_package(BISON REQUIRED) @@ -47,7 +48,7 @@ set(compiler_core src/thrift/generate/t_generator.cc src/thrift/parse/t_typedef.cc src/thrift/parse/parse.cc - ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h + src/thrift/version.h ) set(thrift-compiler_SOURCES diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am index 91801c6ab6f..429df648dc7 100644 --- a/compiler/cpp/Makefile.am +++ b/compiler/cpp/Makefile.am @@ -45,6 +45,7 @@ thrift_SOURCES = src/thrift/audit/t_audit.cpp \ src/thrift/logging.h \ src/thrift/main.cc \ src/thrift/main.h \ + src/thrift/version.h \ src/thrift/parse/parse.cc \ src/thrift/parse/t_base_type.h \ src/thrift/parse/t_const.h \ @@ -118,8 +119,8 @@ EXTRA_DIST = \ test \ $(WINDOWS_DIST) -clean-local: - $(RM) version.h +#clean-local: +# $(RM) version.h -- do not delete, we need it src/thrift/main.cc: src/thrift/version.h diff --git a/compiler/cpp/src/thrift/version.h.in b/compiler/cpp/src/thrift/version.h similarity index 95% rename from compiler/cpp/src/thrift/version.h.in rename to compiler/cpp/src/thrift/version.h index aef076f7f0c..3a7250d9d16 100644 --- a/compiler/cpp/src/thrift/version.h.in +++ b/compiler/cpp/src/thrift/version.h @@ -24,6 +24,6 @@ #pragma once #endif // _MSC_VER -#define THRIFT_VERSION "@PACKAGE_VERSION@" +#define THRIFT_VERSION "0.14.0" #endif // _THRIFT_VERSION_H_ diff --git a/compiler/cpp/tests/CMakeLists.txt b/compiler/cpp/tests/CMakeLists.txt index fde9073cad2..91cc35dbff1 100644 --- a/compiler/cpp/tests/CMakeLists.txt +++ b/compiler/cpp/tests/CMakeLists.txt @@ -27,7 +27,8 @@ set(THRIFT_COMPILER_SOURCE_DIR # don't generate ZERO_CHECK set(CMAKE_SUPPRESS_REGENERATION true) -configure_file(${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h) +# version.h now handled via veralign.sh +#configure_file(${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h) if(MSVC) # The winflexbison generator outputs some macros that conflict with the Visual Studio 2010 copy of stdint.h # This might be fixed in later versions of Visual Studio, but an easy solution is to include stdint.h first @@ -77,7 +78,7 @@ set(thrift_compiler_SOURCES ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/generate/t_generator.cc ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/parse/t_typedef.cc ${THRIFT_COMPILER_SOURCE_DIR}/src/thrift/parse/parse.cc - ${CMAKE_CURRENT_BINARY_DIR}/thrift/version.h + ${THRIFT_COMPILER_SOURCE_DIR}/thrift/version.h ) # This macro adds an option THRIFT_COMPILER_${NAME} diff --git a/configure.ac b/configure.ac index 48923626c0b..ad26ef03fe6 100755 --- a/configure.ac +++ b/configure.ac @@ -791,7 +791,6 @@ AC_CONFIG_FILES([ compiler/cpp/Makefile compiler/cpp/src/Makefile compiler/cpp/test/Makefile - compiler/cpp/src/thrift/version.h lib/Makefile lib/as3/Makefile lib/cl/Makefile From 3f3567a1143194712747fff9dd02b2162e2d14dd Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 19 Oct 2019 18:27:35 +0200 Subject: [PATCH 403/756] THRIFT-4981 Remove deprecated netcore bindings from the code base Client: netcore Patch: Jens Geyer This closes #1901 --- Makefile.am | 2 +- build/veralign.sh | 2 - compiler/cpp/CMakeLists.txt | 1 - compiler/cpp/Makefile.am | 2 - compiler/cpp/README.md | 2 +- compiler/cpp/compiler.vcxproj | 1 - compiler/cpp/compiler.vcxproj.filters | 6 - .../thrift/generate/t_netcore_generator.cc | 3133 ----------------- .../src/thrift/generate/t_netcore_generator.h | 160 - compiler/cpp/src/thrift/parse/t_program.h | 6 +- compiler/cpp/tests/CMakeLists.txt | 2 +- compiler/cpp/tests/README.md | 4 +- .../t_netcore_generator_functional_tests.cc | 58 +- ...core_generator_functional_tests_helpers.cc | 48 +- ...tcore_generator_functional_tests_helpers.h | 16 +- .../t_netcore_generator_helpers_tests.cc | 24 +- ..._netcore_generator_initialization_tests.cc | 24 +- configure.ac | 27 +- contrib/fb303/if/fb303.thrift | 2 +- lib/Makefile.am | 1 - lib/cpp/test/OneWayTest.thrift | 1 - lib/netcore/Makefile.am | 58 - lib/netcore/README.md | 29 - .../Tests/Thrift.IntegrationTests/.gitignore | 2 - .../Protocols/ProtocolsOperationsTests.cs | 502 --- .../Thrift.IntegrationTests.csproj | 29 - .../.gitignore | 4 - .../CassandraTest.thrift | 705 ---- .../Properties/AssemblyInfo.cs | 40 - ...rift.PublicInterfaces.Compile.Tests.csproj | 36 - .../Collections/TCollectionsTests.cs | 83 - .../Thrift.Tests/Collections/THashSetTests.cs | 71 - .../Protocols/TJsonProtocolHelperTests.cs | 172 - .../Protocols/TJsonProtocolTests.cs | 67 - .../Tests/Thrift.Tests/Thrift.Tests.csproj | 18 - lib/netcore/Thrift.sln | 85 - .../Thrift/Collections/TCollections.cs | 101 - lib/netcore/Thrift/Collections/THashSet.cs | 67 - lib/netcore/Thrift/ITAsyncProcessor.cs | 29 - lib/netcore/Thrift/ITProcessorFactory.cs | 28 - lib/netcore/Thrift/Properties/AssemblyInfo.cs | 56 - .../Thrift/Protocols/Entities/TField.cs | 37 - .../Thrift/Protocols/Entities/TList.cs | 33 - lib/netcore/Thrift/Protocols/Entities/TMap.cs | 36 - .../Thrift/Protocols/Entities/TMessage.cs | 37 - .../Thrift/Protocols/Entities/TMessageType.cs | 28 - lib/netcore/Thrift/Protocols/Entities/TSet.cs | 38 - .../Thrift/Protocols/Entities/TStruct.cs | 30 - .../Thrift/Protocols/Entities/TType.cs | 37 - .../Thrift/Protocols/ITProtocolFactory.cs | 27 - lib/netcore/Thrift/Protocols/TAbstractBase.cs | 28 - lib/netcore/Thrift/Protocols/TBase.cs | 28 - .../Thrift/Protocols/TBinaryProtocol.cs | 613 ---- .../Thrift/Protocols/TCompactProtocol.cs | 922 ----- lib/netcore/Thrift/Protocols/TJSONProtocol.cs | 981 ------ .../Thrift/Protocols/TMultiplexedProtocol.cs | 91 - lib/netcore/Thrift/Protocols/TProtocol.cs | 376 -- .../Thrift/Protocols/TProtocolDecorator.cs | 247 -- .../Thrift/Protocols/TProtocolException.cs | 59 - .../Protocols/Utilities/TBase64Helper.cs | 101 - .../Protocols/Utilities/TBase64Utils.cs | 101 - .../Utilities/TJsonProtocolConstants.cs | 61 - .../Utilities/TJsonProtocolHelper.cs | 176 - .../Protocols/Utilities/TProtocolUtil.cs | 110 - lib/netcore/Thrift/Server/AsyncBaseServer.cs | 183 - lib/netcore/Thrift/Server/TBaseServer.cs | 79 - .../Thrift/Server/TServerEventHandler.cs | 54 - .../Thrift/SingletonTProcessorFactory.cs | 38 - lib/netcore/Thrift/TApplicationException.cs | 150 - lib/netcore/Thrift/TBaseClient.cs | 91 - lib/netcore/Thrift/TException.cs | 34 - lib/netcore/Thrift/TMultiplexedProcessor.cs | 143 - lib/netcore/Thrift/Thrift.csproj | 33 - .../Client/TBufferedClientTransport.cs | 206 -- .../Client/TFramedClientTransport.cs | 201 -- .../Transports/Client/THttpClientTransport.cs | 227 -- .../Client/TMemoryBufferClientTransport.cs | 97 - .../Client/TNamedPipeClientTransport.cs | 95 - .../Client/TSocketClientTransport.cs | 139 - .../Client/TStreamClientTransport.cs | 110 - .../Client/TTlsSocketClientTransport.cs | 237 -- .../Transports/Server/THttpServerTransport.cs | 98 - .../Server/TNamedPipeServerTransport.cs | 191 - .../Server/TServerFramedTransport.cs | 150 - .../Server/TServerSocketTransport.cs | 174 - .../Server/TTlsServerSocketTransport.cs | 177 - .../Thrift/Transports/TClientTransport.cs | 179 - .../Thrift/Transports/TServerTransport.cs | 54 - .../Thrift/Transports/TTransportException.cs | 58 - .../Thrift/Transports/TTransportFactory.cs | 35 - lib/netcore/Thrift/thrift.snk | Bin 596 -> 0 bytes lib/netcore/build.cmd | 27 - lib/netcore/build.sh | 32 - lib/netcore/runtests.cmd | 28 - lib/netcore/runtests.sh | 26 - lib/netstd/Makefile.am | 2 +- test/Makefile.am | 1 - test/ThriftTest.thrift | 1 - test/netcore/Client/.gitignore | 2 - test/netcore/Client/Client.csproj | 31 - test/netcore/Client/Program.cs | 72 - .../netcore/Client/Properties/AssemblyInfo.cs | 43 - test/netcore/Client/TestClient.cs | 943 ----- test/netcore/Makefile.am | 50 - test/netcore/README.md | 20 - test/netcore/Server/.gitignore | 2 - test/netcore/Server/Program.cs | 72 - .../netcore/Server/Properties/AssemblyInfo.cs | 43 - test/netcore/Server/Server.csproj | 31 - test/netcore/Server/TestServer.cs | 594 ---- test/netcore/ThriftTest.sln | 64 - test/netcore/build.cmd | 25 - test/netcore/build.sh | 26 - tutorial/Makefile.am | 1 - tutorial/netcore/.gitignore | 1 - tutorial/netcore/Client/Client.csproj | 19 - tutorial/netcore/Client/Program.cs | 355 -- .../netcore/Client/Properties/AssemblyInfo.cs | 40 - .../Client/Properties/launchSettings.json | 8 - tutorial/netcore/Client/ThriftTest.pfx | Bin 2661 -> 0 bytes tutorial/netcore/Interfaces/.gitignore | 3 - tutorial/netcore/Interfaces/Interfaces.csproj | 30 - .../Interfaces/Properties/AssemblyInfo.cs | 40 - tutorial/netcore/Makefile.am | 51 - tutorial/netcore/README.md | 278 -- tutorial/netcore/Server/Program.cs | 428 --- .../netcore/Server/Properties/AssemblyInfo.cs | 40 - .../Server/Properties/launchSettings.json | 8 - tutorial/netcore/Server/Server.csproj | 26 - tutorial/netcore/Server/ThriftTest.pfx | Bin 2661 -> 0 bytes tutorial/netcore/Tutorial.sln | 78 - tutorial/netcore/build.cmd | 25 - tutorial/netcore/build.sh | 26 - tutorial/shared.thrift | 1 - tutorial/tutorial.thrift | 1 - 135 files changed, 105 insertions(+), 16623 deletions(-) delete mode 100644 compiler/cpp/src/thrift/generate/t_netcore_generator.cc delete mode 100644 compiler/cpp/src/thrift/generate/t_netcore_generator.h delete mode 100644 lib/netcore/Makefile.am delete mode 100644 lib/netcore/README.md delete mode 100644 lib/netcore/Tests/Thrift.IntegrationTests/.gitignore delete mode 100644 lib/netcore/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs delete mode 100644 lib/netcore/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj delete mode 100644 lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/.gitignore delete mode 100644 lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift delete mode 100644 lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs delete mode 100644 lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj delete mode 100644 lib/netcore/Tests/Thrift.Tests/Collections/TCollectionsTests.cs delete mode 100644 lib/netcore/Tests/Thrift.Tests/Collections/THashSetTests.cs delete mode 100644 lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs delete mode 100644 lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs delete mode 100644 lib/netcore/Tests/Thrift.Tests/Thrift.Tests.csproj delete mode 100644 lib/netcore/Thrift.sln delete mode 100644 lib/netcore/Thrift/Collections/TCollections.cs delete mode 100644 lib/netcore/Thrift/Collections/THashSet.cs delete mode 100644 lib/netcore/Thrift/ITAsyncProcessor.cs delete mode 100644 lib/netcore/Thrift/ITProcessorFactory.cs delete mode 100644 lib/netcore/Thrift/Properties/AssemblyInfo.cs delete mode 100644 lib/netcore/Thrift/Protocols/Entities/TField.cs delete mode 100644 lib/netcore/Thrift/Protocols/Entities/TList.cs delete mode 100644 lib/netcore/Thrift/Protocols/Entities/TMap.cs delete mode 100644 lib/netcore/Thrift/Protocols/Entities/TMessage.cs delete mode 100644 lib/netcore/Thrift/Protocols/Entities/TMessageType.cs delete mode 100644 lib/netcore/Thrift/Protocols/Entities/TSet.cs delete mode 100644 lib/netcore/Thrift/Protocols/Entities/TStruct.cs delete mode 100644 lib/netcore/Thrift/Protocols/Entities/TType.cs delete mode 100644 lib/netcore/Thrift/Protocols/ITProtocolFactory.cs delete mode 100644 lib/netcore/Thrift/Protocols/TAbstractBase.cs delete mode 100644 lib/netcore/Thrift/Protocols/TBase.cs delete mode 100644 lib/netcore/Thrift/Protocols/TBinaryProtocol.cs delete mode 100644 lib/netcore/Thrift/Protocols/TCompactProtocol.cs delete mode 100644 lib/netcore/Thrift/Protocols/TJSONProtocol.cs delete mode 100644 lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs delete mode 100644 lib/netcore/Thrift/Protocols/TProtocol.cs delete mode 100644 lib/netcore/Thrift/Protocols/TProtocolDecorator.cs delete mode 100644 lib/netcore/Thrift/Protocols/TProtocolException.cs delete mode 100644 lib/netcore/Thrift/Protocols/Utilities/TBase64Helper.cs delete mode 100644 lib/netcore/Thrift/Protocols/Utilities/TBase64Utils.cs delete mode 100644 lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs delete mode 100644 lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs delete mode 100644 lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs delete mode 100644 lib/netcore/Thrift/Server/AsyncBaseServer.cs delete mode 100644 lib/netcore/Thrift/Server/TBaseServer.cs delete mode 100644 lib/netcore/Thrift/Server/TServerEventHandler.cs delete mode 100644 lib/netcore/Thrift/SingletonTProcessorFactory.cs delete mode 100644 lib/netcore/Thrift/TApplicationException.cs delete mode 100644 lib/netcore/Thrift/TBaseClient.cs delete mode 100644 lib/netcore/Thrift/TException.cs delete mode 100644 lib/netcore/Thrift/TMultiplexedProcessor.cs delete mode 100644 lib/netcore/Thrift/Thrift.csproj delete mode 100644 lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Client/TMemoryBufferClientTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Client/TNamedPipeClientTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Client/TStreamClientTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Server/TServerFramedTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/TClientTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/TServerTransport.cs delete mode 100644 lib/netcore/Thrift/Transports/TTransportException.cs delete mode 100644 lib/netcore/Thrift/Transports/TTransportFactory.cs delete mode 100644 lib/netcore/Thrift/thrift.snk delete mode 100644 lib/netcore/build.cmd delete mode 100644 lib/netcore/build.sh delete mode 100644 lib/netcore/runtests.cmd delete mode 100644 lib/netcore/runtests.sh delete mode 100644 test/netcore/Client/.gitignore delete mode 100644 test/netcore/Client/Client.csproj delete mode 100644 test/netcore/Client/Program.cs delete mode 100644 test/netcore/Client/Properties/AssemblyInfo.cs delete mode 100644 test/netcore/Client/TestClient.cs delete mode 100644 test/netcore/Makefile.am delete mode 100644 test/netcore/README.md delete mode 100644 test/netcore/Server/.gitignore delete mode 100644 test/netcore/Server/Program.cs delete mode 100644 test/netcore/Server/Properties/AssemblyInfo.cs delete mode 100644 test/netcore/Server/Server.csproj delete mode 100644 test/netcore/Server/TestServer.cs delete mode 100644 test/netcore/ThriftTest.sln delete mode 100644 test/netcore/build.cmd delete mode 100755 test/netcore/build.sh delete mode 100644 tutorial/netcore/.gitignore delete mode 100644 tutorial/netcore/Client/Client.csproj delete mode 100644 tutorial/netcore/Client/Program.cs delete mode 100644 tutorial/netcore/Client/Properties/AssemblyInfo.cs delete mode 100644 tutorial/netcore/Client/Properties/launchSettings.json delete mode 100644 tutorial/netcore/Client/ThriftTest.pfx delete mode 100644 tutorial/netcore/Interfaces/.gitignore delete mode 100644 tutorial/netcore/Interfaces/Interfaces.csproj delete mode 100644 tutorial/netcore/Interfaces/Properties/AssemblyInfo.cs delete mode 100644 tutorial/netcore/Makefile.am delete mode 100644 tutorial/netcore/README.md delete mode 100644 tutorial/netcore/Server/Program.cs delete mode 100644 tutorial/netcore/Server/Properties/AssemblyInfo.cs delete mode 100644 tutorial/netcore/Server/Properties/launchSettings.json delete mode 100644 tutorial/netcore/Server/Server.csproj delete mode 100644 tutorial/netcore/Server/ThriftTest.pfx delete mode 100644 tutorial/netcore/Tutorial.sln delete mode 100644 tutorial/netcore/build.cmd delete mode 100755 tutorial/netcore/build.sh diff --git a/Makefile.am b/Makefile.am index bacd0082a65..5832077fb26 100755 --- a/Makefile.am +++ b/Makefile.am @@ -78,7 +78,7 @@ empty := space := $(empty) $(empty) comma := , -CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_CL@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_CSHARP@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_HASKELL@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_DOTNETCORE@ @MAYBE_NODETS@ +CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_CL@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_CSHARP@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_HASKELL@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_NETSTD@ @MAYBE_NODETS@ CROSS_LANGS_COMMA_SEPARATED = $(subst $(space),$(comma),$(CROSS_LANGS)) if WITH_PY3 diff --git a/build/veralign.sh b/build/veralign.sh index 39b67eb5be5..c15e0010d56 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -78,8 +78,6 @@ FILES[lib/js/package.json]=jsonReplace FILES[lib/js/package-lock.json]=jsonReplace FILES[lib/js/src/thrift.js]=simpleReplace FILES[lib/lua/Thrift.lua]=simpleReplace -FILES[lib/netcore/Thrift/Properties/AssemblyInfo.cs]=simpleReplace -FILES[lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs]=simpleReplace FILES[lib/netstd/Thrift/Properties/AssemblyInfo.cs]=simpleReplace FILES[lib/netstd/Thrift/Thrift.csproj]=simpleReplace FILES[lib/ocaml/_oasis]=simpleReplace diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt index 2bc08cfa624..3c292b47a16 100644 --- a/compiler/cpp/CMakeLists.txt +++ b/compiler/cpp/CMakeLists.txt @@ -91,7 +91,6 @@ THRIFT_ADD_COMPILER(javame "Enable compiler for Java ME" ON) THRIFT_ADD_COMPILER(js "Enable compiler for JavaScript" ON) THRIFT_ADD_COMPILER(json "Enable compiler for JSON" ON) THRIFT_ADD_COMPILER(lua "Enable compiler for Lua" ON) -THRIFT_ADD_COMPILER(netcore "Enable compiler for .NET Core" ON) THRIFT_ADD_COMPILER(netstd "Enable compiler for .NET Standard" ON) THRIFT_ADD_COMPILER(ocaml "Enable compiler for OCaml" ON) THRIFT_ADD_COMPILER(perl "Enable compiler for Perl" ON) diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am index 429df648dc7..d0ac8749660 100644 --- a/compiler/cpp/Makefile.am +++ b/compiler/cpp/Makefile.am @@ -88,8 +88,6 @@ thrift_SOURCES += src/thrift/generate/t_as3_generator.cc \ src/thrift/generate/t_js_generator.cc \ src/thrift/generate/t_json_generator.cc \ src/thrift/generate/t_lua_generator.cc \ - src/thrift/generate/t_netcore_generator.cc \ - src/thrift/generate/t_netcore_generator.h \ src/thrift/generate/t_netstd_generator.cc \ src/thrift/generate/t_netstd_generator.h \ src/thrift/generate/t_ocaml_generator.cc \ diff --git a/compiler/cpp/README.md b/compiler/cpp/README.md index 5c04cd869db..8d6edacb5c1 100644 --- a/compiler/cpp/README.md +++ b/compiler/cpp/README.md @@ -168,7 +168,7 @@ Build the compiler in Visual Studio. ## Using Catch C++ test library -Added generic way to cover code by tests for many languages (you just need to make a correct header file for generator for your language - example in **netcore** implementation) +Added generic way to cover code by tests for many languages (you just need to make a correct header file for generator for your language - example in **netstd** implementation) - pls check **tests** folder diff --git a/compiler/cpp/compiler.vcxproj b/compiler/cpp/compiler.vcxproj index 06c4eb4d8eb..5d073e7381a 100644 --- a/compiler/cpp/compiler.vcxproj +++ b/compiler/cpp/compiler.vcxproj @@ -73,7 +73,6 @@ - diff --git a/compiler/cpp/compiler.vcxproj.filters b/compiler/cpp/compiler.vcxproj.filters index 5a575894fa3..664a9d97570 100644 --- a/compiler/cpp/compiler.vcxproj.filters +++ b/compiler/cpp/compiler.vcxproj.filters @@ -161,15 +161,9 @@ generate - - generate - generate - - generate - generate diff --git a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc b/compiler/cpp/src/thrift/generate/t_netcore_generator.cc deleted file mode 100644 index ed6a365ac15..00000000000 --- a/compiler/cpp/src/thrift/generate/t_netcore_generator.cc +++ /dev/null @@ -1,3133 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "thrift/platform.h" -#include "thrift/generate/t_oop_generator.h" -#include "thrift/generate/t_netcore_generator.h" - -using std::map; -using std::ostream; -using std::ostringstream; -using std::string; -using std::stringstream; -using std::vector; - -//TODO: check for indentation -//TODO: Do we need seqId_ in generation? - -t_netcore_generator::t_netcore_generator(t_program* program, const map& parsed_options, const string& option_string) - : t_oop_generator(program) -{ - (void)option_string; - - nullable_ = false; - hashcode_ = false; - union_ = false; - serialize_ = false; - wcf_ = false; - wcf_namespace_.clear(); - - map::const_iterator iter; - - for (iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) - { - if (iter->first.compare("nullable") == 0) - { - nullable_ = true; - } - else if (iter->first.compare("hashcode") == 0) - { - hashcode_ = true; - } - else if (iter->first.compare("union") == 0) - { - union_ = true; - } - else if (iter->first.compare("serial") == 0) - { - serialize_ = true; - wcf_namespace_ = iter->second; // since there can be only one namespace - } - else if (iter->first.compare("wcf") == 0) - { - wcf_ = true; - wcf_namespace_ = iter->second; - } - else - { - throw "unknown option netcore:" + iter->first; - } - } - - pwarning(1, "The 'netcore' target is deprecated. Consider using 'netstd' instead.\n"); - - out_dir_base_ = "gen-netcore"; -} - -static string correct_function_name_for_async(string const& function_name) -{ - string const async_end = "Async"; - size_t i = function_name.find(async_end); - if (i != string::npos) - { - return function_name + async_end; - } - - return function_name; -} - -/** -* \brief Search and replace "_args" substring in struct name if exist (for C# class naming) -* \param struct_name -* \return Modified struct name ("Struct_args" -> "StructArgs") or original name -*/ -static string check_and_correct_struct_name(const string& struct_name) -{ - string args_end = "_args"; - size_t i = struct_name.find(args_end); - if (i != string::npos) - { - string new_struct_name = struct_name; - new_struct_name.replace(i, args_end.length(), "Args"); - return new_struct_name; - } - - string result_end = "_result"; - size_t j = struct_name.find(result_end); - if (j != string::npos) - { - string new_struct_name = struct_name; - new_struct_name.replace(j, result_end.length(), "Result"); - return new_struct_name; - } - - return struct_name; -} - -static bool field_has_default(t_field* tfield) { return tfield->get_value() != NULL; } - -static bool field_is_required(t_field* tfield) { return tfield->get_req() == t_field::T_REQUIRED; } - -static bool type_can_be_null(t_type* ttype) -{ - while (ttype->is_typedef()) - { - ttype = static_cast(ttype)->get_type(); - } - - return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string(); -} - -bool t_netcore_generator::is_wcf_enabled() const { return wcf_; } - -bool t_netcore_generator::is_nullable_enabled() const { return nullable_; } - -bool t_netcore_generator::is_hashcode_enabled() const { return hashcode_; } - -bool t_netcore_generator::is_serialize_enabled() const { return serialize_; } - -bool t_netcore_generator::is_union_enabled() const { return union_; } - -map t_netcore_generator::get_keywords_list() const -{ - return netcore_keywords; -} - -void t_netcore_generator::init_generator() -{ - MKDIR(get_out_dir().c_str()); - - // for usage of csharp namespaces in thrift files (from files for csharp) - namespace_name_ = program_->get_namespace("netcore"); - if (namespace_name_.empty()) - { - namespace_name_ = program_->get_namespace("netcore"); - } - - string dir = namespace_name_; - string subdir = get_out_dir().c_str(); - string::size_type loc; - - while ((loc = dir.find(".")) != string::npos) - { - subdir = subdir + "/" + dir.substr(0, loc); - MKDIR(subdir.c_str()); - dir = dir.substr(loc + 1); - } - if (dir.size() > 0) - { - subdir = subdir + "/" + dir; - MKDIR(subdir.c_str()); - } - - namespace_dir_ = subdir; - init_keywords(); - - while (!member_mapping_scopes.empty()) - { - cleanup_member_name_mapping(member_mapping_scopes.back().scope_member); - } - - pverbose(".NET Core options:\n"); - pverbose("- nullable ... %s\n", (nullable_ ? "ON" : "off")); - pverbose("- union ...... %s\n", (union_ ? "ON" : "off")); - pverbose("- hashcode ... %s\n", (hashcode_ ? "ON" : "off")); - pverbose("- serialize .. %s\n", (serialize_ ? "ON" : "off")); - pverbose("- wcf ........ %s\n", (wcf_ ? "ON" : "off")); -} - -string t_netcore_generator::normalize_name(string name) -{ - string tmp(name); - transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast(tolower)); - - // un-conflict keywords by prefixing with "@" - if (netcore_keywords.find(tmp) != netcore_keywords.end()) - { - return "@" + name; - } - - // no changes necessary - return name; -} - -void t_netcore_generator::init_keywords() -{ - netcore_keywords.clear(); - - // C# keywords - netcore_keywords["abstract"] = 1; - netcore_keywords["as"] = 1; - netcore_keywords["base"] = 1; - netcore_keywords["bool"] = 1; - netcore_keywords["break"] = 1; - netcore_keywords["byte"] = 1; - netcore_keywords["case"] = 1; - netcore_keywords["catch"] = 1; - netcore_keywords["char"] = 1; - netcore_keywords["checked"] = 1; - netcore_keywords["class"] = 1; - netcore_keywords["const"] = 1; - netcore_keywords["continue"] = 1; - netcore_keywords["decimal"] = 1; - netcore_keywords["default"] = 1; - netcore_keywords["delegate"] = 1; - netcore_keywords["do"] = 1; - netcore_keywords["double"] = 1; - netcore_keywords["else"] = 1; - netcore_keywords["enum"] = 1; - netcore_keywords["event"] = 1; - netcore_keywords["explicit"] = 1; - netcore_keywords["extern"] = 1; - netcore_keywords["false"] = 1; - netcore_keywords["finally"] = 1; - netcore_keywords["fixed"] = 1; - netcore_keywords["float"] = 1; - netcore_keywords["for"] = 1; - netcore_keywords["foreach"] = 1; - netcore_keywords["goto"] = 1; - netcore_keywords["if"] = 1; - netcore_keywords["implicit"] = 1; - netcore_keywords["in"] = 1; - netcore_keywords["int"] = 1; - netcore_keywords["interface"] = 1; - netcore_keywords["internal"] = 1; - netcore_keywords["is"] = 1; - netcore_keywords["lock"] = 1; - netcore_keywords["long"] = 1; - netcore_keywords["namespace"] = 1; - netcore_keywords["new"] = 1; - netcore_keywords["null"] = 1; - netcore_keywords["object"] = 1; - netcore_keywords["operator"] = 1; - netcore_keywords["out"] = 1; - netcore_keywords["override"] = 1; - netcore_keywords["params"] = 1; - netcore_keywords["private"] = 1; - netcore_keywords["protected"] = 1; - netcore_keywords["public"] = 1; - netcore_keywords["readonly"] = 1; - netcore_keywords["ref"] = 1; - netcore_keywords["return"] = 1; - netcore_keywords["sbyte"] = 1; - netcore_keywords["sealed"] = 1; - netcore_keywords["short"] = 1; - netcore_keywords["sizeof"] = 1; - netcore_keywords["stackalloc"] = 1; - netcore_keywords["static"] = 1; - netcore_keywords["string"] = 1; - netcore_keywords["struct"] = 1; - netcore_keywords["switch"] = 1; - netcore_keywords["this"] = 1; - netcore_keywords["throw"] = 1; - netcore_keywords["true"] = 1; - netcore_keywords["try"] = 1; - netcore_keywords["typeof"] = 1; - netcore_keywords["uint"] = 1; - netcore_keywords["ulong"] = 1; - netcore_keywords["unchecked"] = 1; - netcore_keywords["unsafe"] = 1; - netcore_keywords["ushort"] = 1; - netcore_keywords["using"] = 1; - netcore_keywords["virtual"] = 1; - netcore_keywords["void"] = 1; - netcore_keywords["volatile"] = 1; - netcore_keywords["while"] = 1; - - // C# contextual keywords - netcore_keywords["add"] = 1; - netcore_keywords["alias"] = 1; - netcore_keywords["ascending"] = 1; - netcore_keywords["async"] = 1; - netcore_keywords["await"] = 1; - netcore_keywords["descending"] = 1; - netcore_keywords["dynamic"] = 1; - netcore_keywords["from"] = 1; - netcore_keywords["get"] = 1; - netcore_keywords["global"] = 1; - netcore_keywords["group"] = 1; - netcore_keywords["into"] = 1; - netcore_keywords["join"] = 1; - netcore_keywords["let"] = 1; - netcore_keywords["orderby"] = 1; - netcore_keywords["partial"] = 1; - netcore_keywords["remove"] = 1; - netcore_keywords["select"] = 1; - netcore_keywords["set"] = 1; - netcore_keywords["value"] = 1; - netcore_keywords["var"] = 1; - netcore_keywords["where"] = 1; - netcore_keywords["yield"] = 1; - - netcore_keywords["when"] = 1; -} - -void t_netcore_generator::start_netcore_namespace(ostream& out) -{ - if (!namespace_name_.empty()) - { - out << "namespace " << namespace_name_ << endl; - scope_up(out); - } -} - -void t_netcore_generator::end_netcore_namespace(ostream& out) -{ - if (!namespace_name_.empty()) - { - scope_down(out); - } -} - -string t_netcore_generator::netcore_type_usings() const -{ - string namespaces = - "using System;\n" - "using System.Collections;\n" - "using System.Collections.Generic;\n" - "using System.Text;\n" - "using System.IO;\n" - "using System.Threading;\n" - "using System.Threading.Tasks;\n" - "using Thrift;\n" - "using Thrift.Collections;\n"; - - if (wcf_) - { - namespaces += "using System.ServiceModel;\n"; - namespaces += "using System.Runtime.Serialization;\n"; - } - - return namespaces + endl; -} - -string t_netcore_generator::netcore_thrift_usings() const -{ - string namespaces = - "using Thrift.Protocols;\n" - "using Thrift.Protocols.Entities;\n" - "using Thrift.Protocols.Utilities;\n" - "using Thrift.Transports;\n" - "using Thrift.Transports.Client;\n" - "using Thrift.Transports.Server;\n"; - - return namespaces + endl; -} - -void t_netcore_generator::close_generator() -{ -} - -void t_netcore_generator::generate_typedef(t_typedef* ttypedef) -{ - (void)ttypedef; -} - -void t_netcore_generator::generate_enum(t_enum* tenum) -{ - int ic = indent_count(); - string f_enum_name = namespace_dir_ + "/" + tenum->get_name() + ".cs"; - - ofstream_with_content_based_conditional_update f_enum; - f_enum.open(f_enum_name.c_str()); - - generate_enum(f_enum, tenum); - - f_enum.close(); - indent_validate(ic, "generate_enum"); -} - -void t_netcore_generator::generate_enum(ostream& out, t_enum* tenum) -{ - out << autogen_comment() << endl; - - start_netcore_namespace(out); - generate_netcore_doc(out, tenum); - - out << indent() << "public enum " << tenum->get_name() << endl; - scope_up(out); - - vector constants = tenum->get_constants(); - vector::iterator c_iter; - - for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) - { - generate_netcore_doc(out, *c_iter); - int value = (*c_iter)->get_value(); - out << indent() << (*c_iter)->get_name() << " = " << value << "," << endl; - } - - scope_down(out); - end_netcore_namespace(out); -} - -void t_netcore_generator::generate_consts(vector consts) -{ - if (consts.empty()) - { - return; - } - - string f_consts_name = namespace_dir_ + '/' + program_name_ + ".Constants.cs"; - ofstream_with_content_based_conditional_update f_consts; - f_consts.open(f_consts_name.c_str()); - - generate_consts(f_consts, consts); - - f_consts.close(); -} - -void t_netcore_generator::generate_consts(ostream& out, vector consts) -{ - if (consts.empty()) - { - return; - } - - out << autogen_comment() << netcore_type_usings() << endl; - - start_netcore_namespace(out); - - out << indent() << "public static class " << make_valid_csharp_identifier(program_name_) << "Constants" << endl; - - scope_up(out); - - vector::iterator c_iter; - bool need_static_constructor = false; - for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) - { - generate_netcore_doc(out, *c_iter); - if (print_const_value(out, (*c_iter)->get_name(), (*c_iter)->get_type(), (*c_iter)->get_value(), false)) - { - need_static_constructor = true; - } - } - - if (need_static_constructor) - { - print_const_constructor(out, consts); - } - - scope_down(out); - end_netcore_namespace(out); -} - -void t_netcore_generator::print_const_def_value(ostream& out, string name, t_type* type, t_const_value* value) -{ - if (type->is_struct() || type->is_xception()) - { - const vector& fields = static_cast(type)->get_members(); - const map& val = value->get_map(); - vector::const_iterator f_iter; - map::const_iterator v_iter; - prepare_member_name_mapping(static_cast(type)); - - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) - { - t_field* field = NULL; - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - if ((*f_iter)->get_name() == v_iter->first->get_string()) - { - field = *f_iter; - } - } - - if (field == NULL) - { - throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); - } - - t_type* field_type = field->get_type(); - - string val = render_const_value(out, name, field_type, v_iter->second); - out << indent() << name << "." << prop_name(field) << " = " << val << ";" << endl; - } - - cleanup_member_name_mapping(static_cast(type)); - } - else if (type->is_map()) - { - t_type* ktype = static_cast(type)->get_key_type(); - t_type* vtype = static_cast(type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) - { - string key = render_const_value(out, name, ktype, v_iter->first); - string val = render_const_value(out, name, vtype, v_iter->second); - out << indent() << name << "[" << key << "]" << " = " << val << ";" << endl; - } - } - else if (type->is_list() || type->is_set()) - { - t_type* etype; - if (type->is_list()) - { - etype = static_cast(type)->get_elem_type(); - } - else - { - etype = static_cast(type)->get_elem_type(); - } - - const vector& val = value->get_list(); - vector::const_iterator v_iter; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) - { - string val = render_const_value(out, name, etype, *v_iter); - out << indent() << name << ".Add(" << val << ");" << endl; - } - } -} - -void t_netcore_generator::print_const_constructor(ostream& out, vector consts) -{ - out << indent() << "static " << make_valid_csharp_identifier(program_name_).c_str() << "Constants()" << endl; - scope_up(out); - - vector::iterator c_iter; - for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) - { - string name = (*c_iter)->get_name(); - t_type* type = (*c_iter)->get_type(); - t_const_value* value = (*c_iter)->get_value(); - - print_const_def_value(out, name, type, value); - } - scope_down(out); -} - -bool t_netcore_generator::print_const_value(ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval, bool needtype) -{ - out << indent(); - bool need_static_construction = !in_static; - while (type->is_typedef()) - { - type = static_cast(type)->get_type(); - } - - if (!defval || needtype) - { - out << (in_static ? "" : type->is_base_type() ? "public const " : "public static ") << type_name(type) << " "; - } - - if (type->is_base_type()) - { - string v2 = render_const_value(out, name, type, value); - out << normalize_name(name) << " = " << v2 << ";" << endl; - need_static_construction = false; - } - else if (type->is_enum()) - { - out << name << " = " << type_name(type, false, true) << "." << value->get_identifier_name() << ";" << endl; - need_static_construction = false; - } - else if (type->is_struct() || type->is_xception()) - { - out << name << " = new " << type_name(type) << "();" << endl; - } - else if (type->is_map()) - { - out << name << " = new " << type_name(type, true, true) << "();" << endl; - } - else if (type->is_list() || type->is_set()) - { - out << name << " = new " << type_name(type) << "();" << endl; - } - - if (defval && !type->is_base_type() && !type->is_enum()) - { - print_const_def_value(out, name, type, value); - } - - return need_static_construction; -} - -string t_netcore_generator::render_const_value(ostream& out, string name, t_type* type, t_const_value* value) -{ - (void)name; - ostringstream render; - - if (type->is_base_type()) - { - t_base_type::t_base tbase = static_cast(type)->get_base(); - switch (tbase) - { - case t_base_type::TYPE_STRING: - render << '"' << get_escaped_string(value) << '"'; - break; - case t_base_type::TYPE_BOOL: - render << ((value->get_integer() > 0) ? "true" : "false"); - break; - case t_base_type::TYPE_I8: - case t_base_type::TYPE_I16: - case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: - render << value->get_integer(); - break; - case t_base_type::TYPE_DOUBLE: - if (value->get_type() == t_const_value::CV_INTEGER) - { - render << value->get_integer(); - } - else - { - render << value->get_double(); - } - break; - default: - throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); - } - } - else if (type->is_enum()) - { - render << type->get_name() << "." << value->get_identifier_name(); - } - else - { - string t = tmp("tmp"); - print_const_value(out, t, type, value, true, true, true); - render << t; - } - - return render.str(); -} - -void t_netcore_generator::generate_struct(t_struct* tstruct) -{ - if (union_ && tstruct->is_union()) - { - generate_netcore_union(tstruct); - } - else - { - generate_netcore_struct(tstruct, false); - } -} - -void t_netcore_generator::generate_xception(t_struct* txception) -{ - generate_netcore_struct(txception, true); -} - -void t_netcore_generator::generate_netcore_struct(t_struct* tstruct, bool is_exception) -{ - int ic = indent_count(); - - string f_struct_name = namespace_dir_ + "/" + (tstruct->get_name()) + ".cs"; - ofstream_with_content_based_conditional_update f_struct; - - f_struct.open(f_struct_name.c_str()); - - f_struct << autogen_comment() << netcore_type_usings() << netcore_thrift_usings() << endl; - - generate_netcore_struct_definition(f_struct, tstruct, is_exception); - - f_struct.close(); - - indent_validate(ic, "generate_netcore_struct"); -} - -void t_netcore_generator::generate_netcore_struct_definition(ostream& out, t_struct* tstruct, bool is_exception, bool in_class, bool is_result) -{ - if (!in_class) - { - start_netcore_namespace(out); - } - - out << endl; - - generate_netcore_doc(out, tstruct); - prepare_member_name_mapping(tstruct); - - if ((serialize_ || wcf_) && !is_exception) - { - out << indent() << "[DataContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; - } - - bool is_final = tstruct->annotations_.find("final") != tstruct->annotations_.end(); - - string sharp_struct_name = check_and_correct_struct_name(normalize_name(tstruct->get_name())); - - out << indent() << "public " << (is_final ? "sealed " : "") << "partial class " << sharp_struct_name << " : "; - - if (is_exception) - { - out << "TException, "; - } - - out << "TBase" << endl - << indent() << "{" << endl; - indent_up(); - - const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; - - // make private members with public Properties - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) - { - // if the field is requied, then we use auto-properties - if (!field_is_required((*m_iter)) && (!nullable_ || field_has_default((*m_iter)))) - { - out << indent() << "private " << declare_field(*m_iter, false, "_") << endl; - } - } - out << endl; - - bool has_non_required_fields = false; - bool has_non_required_default_value_fields = false; - bool has_required_fields = false; - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) - { - generate_netcore_doc(out, *m_iter); - generate_property(out, *m_iter, true, true); - bool is_required = field_is_required((*m_iter)); - bool has_default = field_has_default((*m_iter)); - if (is_required) - { - has_required_fields = true; - } - else - { - if (has_default) - { - has_non_required_default_value_fields = true; - } - has_non_required_fields = true; - } - } - - bool generate_isset = (nullable_ && has_non_required_default_value_fields) || (!nullable_ && has_non_required_fields); - if (generate_isset) - { - out << endl; - if (serialize_ || wcf_) - { - out << indent() << "[DataMember(Order = 1)]" << endl; - } - out << indent() << "public Isset __isset;" << endl; - if (serialize_ || wcf_) - { - out << indent() << "[DataContract]" << endl; - } - - out << indent() << "public struct Isset" << endl - << indent() << "{" << endl; - indent_up(); - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) - { - bool is_required = field_is_required((*m_iter)); - bool has_default = field_has_default((*m_iter)); - // if it is required, don't need Isset for that variable - // if it is not required, if it has a default value, we need to generate Isset - // if we are not nullable, then we generate Isset - if (!is_required && (!nullable_ || has_default)) - { - if (serialize_ || wcf_) - { - out << indent() << "[DataMember]" << endl; - } - out << indent() << "public bool " << normalize_name((*m_iter)->get_name()) << ";" << endl; - } - } - - indent_down(); - out << indent() << "}" << endl << endl; - - if (generate_isset && (serialize_ || wcf_)) - { - out << indent() << "#region XmlSerializer support" << endl << endl; - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) - { - bool is_required = field_is_required(*m_iter); - bool has_default = field_has_default(*m_iter); - // if it is required, don't need Isset for that variable - // if it is not required, if it has a default value, we need to generate Isset - // if we are not nullable, then we generate Isset - if (!is_required && (!nullable_ || has_default)) - { - out << indent() << "public bool ShouldSerialize" << prop_name(*m_iter) << "()" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "return __isset." << normalize_name((*m_iter)->get_name()) << ";" << endl; - indent_down(); - out << indent() << "}" << endl << endl; - } - } - - out << indent() << "#endregion XmlSerializer support" << endl << endl; - } - } - - // We always want a default, no argument constructor for Reading - out << indent() << "public " << sharp_struct_name << "()" << endl - << indent() << "{" << endl; - indent_up(); - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) - { - t_type* t = (*m_iter)->get_type(); - while (t->is_typedef()) - { - t = static_cast(t)->get_type(); - } - if ((*m_iter)->get_value() != NULL) - { - if (field_is_required((*m_iter))) - { - print_const_value(out, "this." + prop_name(*m_iter), t, (*m_iter)->get_value(), true, true); - } - else - { - print_const_value(out, "this._" + (*m_iter)->get_name(), t, (*m_iter)->get_value(), true, true); - // Optionals with defaults are marked set - out << indent() << "this.__isset." << normalize_name((*m_iter)->get_name()) << " = true;" << endl; - } - } - } - indent_down(); - out << indent() << "}" << endl << endl; - - if (has_required_fields) - { - out << indent() << "public " << sharp_struct_name << "("; - bool first = true; - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) - { - if (field_is_required(*m_iter)) - { - if (first) - { - first = false; - } - else - { - out << ", "; - } - out << type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name(); - } - } - out << ") : this()" << endl - << indent() << "{" << endl; - indent_up(); - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) - { - if (field_is_required(*m_iter)) - { - out << indent() << "this." << prop_name(*m_iter) << " = " << (*m_iter)->get_name() << ";" << endl; - } - } - - indent_down(); - out << indent() << "}" << endl << endl; - } - - generate_netcore_struct_reader(out, tstruct); - if (is_result) - { - generate_netcore_struct_result_writer(out, tstruct); - } - else - { - generate_netcore_struct_writer(out, tstruct); - } - if (hashcode_) - { - generate_netcore_struct_equals(out, tstruct); - generate_netcore_struct_hashcode(out, tstruct); - } - generate_netcore_struct_tostring(out, tstruct); - - indent_down(); - out << indent() << "}" << endl << endl; - - // generate a corresponding WCF fault to wrap the exception - if ((serialize_ || wcf_) && is_exception) - { - generate_netcore_wcffault(out, tstruct); - } - - cleanup_member_name_mapping(tstruct); - if (!in_class) - { - end_netcore_namespace(out); - } -} - -void t_netcore_generator::generate_netcore_wcffault(ostream& out, t_struct* tstruct) -{ - out << endl; - out << indent() << "[DataContract]" << endl; - - bool is_final = tstruct->annotations_.find("final") != tstruct->annotations_.end(); - - out << indent() << "public " << (is_final ? "sealed " : "") << "partial class " << tstruct->get_name() << "Fault" << endl - << indent() << "{" << endl; - indent_up(); - - const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; - - // make private members with public Properties - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) - { - out << indent() << "private " << declare_field(*m_iter, false, "_") << endl; - } - out << endl; - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) - { - generate_property(out, *m_iter, true, false); - } - - indent_down(); - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_netcore_struct_reader(ostream& out, t_struct* tstruct) -{ - out << indent() << "public async Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "iprot.IncrementRecursionDepth();" << endl - << indent() << "try" << endl - << indent() << "{" << endl; - indent_up(); - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - // Required variables aren't in __isset, so we need tmp vars to check them - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - if (field_is_required(*f_iter)) - { - out << indent() << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl; - } - } - - out << indent() << "TField field;" << endl - << indent() << "await iprot.ReadStructBeginAsync(cancellationToken);" << endl - << indent() << "while (true)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "field = await iprot.ReadFieldBeginAsync(cancellationToken);" << endl - << indent() << "if (field.Type == TType.Stop)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "break;" << endl; - indent_down(); - out << indent() << "}" << endl << endl - << indent() << "switch (field.ID)" << endl - << indent() << "{" << endl; - indent_up(); - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - bool is_required = field_is_required(*f_iter); - out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; - indent_up(); - out << indent() << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ")" << endl - << indent() << "{" << endl; - indent_up(); - - generate_deserialize_field(out, *f_iter); - if (is_required) - { - out << indent() << "isset_" << (*f_iter)->get_name() << " = true;" << endl; - } - - indent_down(); - out << indent() << "}" << endl - << indent() << "else" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);" << endl; - indent_down(); - out << indent() << "}" << endl - << indent() << "break;" << endl; - indent_down(); - } - - out << indent() << "default: " << endl; - indent_up(); - out << indent() << "await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);" << endl - << indent() << "break;" << endl; - indent_down(); - indent_down(); - out << indent() << "}" << endl - << endl - << indent() << "await iprot.ReadFieldEndAsync(cancellationToken);" << endl; - indent_down(); - out << indent() << "}" << endl - << endl - << indent() << "await iprot.ReadStructEndAsync(cancellationToken);" << endl; - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - if (field_is_required((*f_iter))) - { - out << indent() << "if (!isset_" << (*f_iter)->get_name() << ")" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl; - indent_down(); - out << indent() << "}" << endl; - } - } - - indent_down(); - out << indent() << "}" << endl; - out << indent() << "finally" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "iprot.DecrementRecursionDepth();" << endl; - indent_down(); - out << indent() << "}" << endl; - indent_down(); - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_netcore_struct_writer(ostream& out, t_struct* tstruct) -{ - out << indent() << "public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl - << indent() << "{" << endl; - indent_up(); - - out << indent() << "oprot.IncrementRecursionDepth();" << endl - << indent() << "try" << endl - << indent() << "{" << endl; - indent_up(); - - string name = tstruct->get_name(); - const vector& fields = tstruct->get_sorted_members(); - vector::const_iterator f_iter; - - out << indent() << "var struc = new TStruct(\"" << name << "\");" << endl - << indent() << "await oprot.WriteStructBeginAsync(struc, cancellationToken);" << endl; - - if (fields.size() > 0) - { - out << indent() << "var field = new TField();" << endl; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - bool is_required = field_is_required(*f_iter); - bool has_default = field_has_default(*f_iter); - if (nullable_ && !has_default && !is_required) - { - out << indent() << "if (" << prop_name(*f_iter) << " != null)" << endl - << indent() << "{" << endl; - indent_up(); - } - else if (!is_required) - { - bool null_allowed = type_can_be_null((*f_iter)->get_type()); - if (null_allowed) - { - out << indent() << "if (" << prop_name(*f_iter) << " != null && __isset." << normalize_name((*f_iter)->get_name()) << ")" << endl - << indent() << "{" << endl; - indent_up(); - } - else - { - out << indent() << "if (__isset." << normalize_name((*f_iter)->get_name()) << ")" << endl - << indent() << "{" << endl; - indent_up(); - } - } - out << indent() << "field.Name = \"" << (*f_iter)->get_name() << "\";" << endl - << indent() << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl - << indent() << "field.ID = " << (*f_iter)->get_key() << ";" << endl - << indent() << "await oprot.WriteFieldBeginAsync(field, cancellationToken);" << endl; - - generate_serialize_field(out, *f_iter); - - out << indent() << "await oprot.WriteFieldEndAsync(cancellationToken);" << endl; - if (!is_required) - { - indent_down(); - out << indent() << "}" << endl; - } - } - } - - out << indent() << "await oprot.WriteFieldStopAsync(cancellationToken);" << endl - << indent() << "await oprot.WriteStructEndAsync(cancellationToken);" << endl; - indent_down(); - out << indent() << "}" << endl - << indent() << "finally" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "oprot.DecrementRecursionDepth();" << endl; - indent_down(); - out << indent() << "}" << endl; - indent_down(); - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_netcore_struct_result_writer(ostream& out, t_struct* tstruct) -{ - out << indent() << "public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl - << indent() << "{" << endl; - indent_up(); - - out << indent() << "oprot.IncrementRecursionDepth();" << endl - << indent() << "try" << endl - << indent() << "{" << endl; - indent_up(); - - string name = tstruct->get_name(); - const vector& fields = tstruct->get_sorted_members(); - vector::const_iterator f_iter; - - out << indent() << "var struc = new TStruct(\"" << name << "\");" << endl - << indent() << "await oprot.WriteStructBeginAsync(struc, cancellationToken);" << endl; - - if (fields.size() > 0) - { - out << indent() << "var field = new TField();" << endl; - bool first = true; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - if (first) - { - first = false; - out << endl << indent() << "if"; - } - else - { - out << indent() << "else if"; - } - - if (nullable_) - { - out << "(this." << prop_name((*f_iter)) << " != null)" << endl - << indent() << "{" << endl; - } - else - { - out << "(this.__isset." << normalize_name((*f_iter)->get_name()) << ")" << endl - << indent() << "{" << endl; - } - indent_up(); - - bool null_allowed = !nullable_ && type_can_be_null((*f_iter)->get_type()); - if (null_allowed) - { - out << indent() << "if (" << prop_name(*f_iter) << " != null)" << endl - << indent() << "{" << endl; - indent_up(); - } - - out << indent() << "field.Name = \"" << prop_name(*f_iter) << "\";" << endl - << indent() << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl - << indent() << "field.ID = " << (*f_iter)->get_key() << ";" << endl - << indent() << "await oprot.WriteFieldBeginAsync(field, cancellationToken);" << endl; - - generate_serialize_field(out, *f_iter); - - out << indent() << "await oprot.WriteFieldEndAsync(cancellationToken);" << endl; - - if (null_allowed) - { - indent_down(); - out << indent() << "}" << endl; - } - - indent_down(); - out << indent() << "}" << endl; - } - } - - out << indent() << "await oprot.WriteFieldStopAsync(cancellationToken);" << endl - << indent() << "await oprot.WriteStructEndAsync(cancellationToken);" << endl; - indent_down(); - out << indent() << "}" << endl - << indent() << "finally" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "oprot.DecrementRecursionDepth();" << endl; - indent_down(); - out << indent() << "}" << endl; - indent_down(); - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_netcore_struct_tostring(ostream& out, t_struct* tstruct) -{ - out << indent() << "public override string ToString()" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "var sb = new StringBuilder(\"" << tstruct->get_name() << "(\");" << endl; - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - bool useFirstFlag = false; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - if (!field_is_required((*f_iter))) - { - out << indent() << "bool __first = true;" << endl; - useFirstFlag = true; - } - break; - } - - bool had_required = false; // set to true after first required field has been processed - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - bool is_required = field_is_required((*f_iter)); - bool has_default = field_has_default((*f_iter)); - if (nullable_ && !has_default && !is_required) - { - out << indent() << "if (" << prop_name((*f_iter)) << " != null)" << endl - << indent() << "{" << endl; - indent_up(); - } - else if (!is_required) - { - bool null_allowed = type_can_be_null((*f_iter)->get_type()); - if (null_allowed) - { - out << indent() << "if (" << prop_name((*f_iter)) << " != null && __isset." << normalize_name((*f_iter)->get_name()) << ")" << endl - << indent() << "{" << endl; - indent_up(); - } - else - { - out << indent() << "if (__isset." << normalize_name((*f_iter)->get_name()) << ")" << endl - << indent() << "{" << endl; - indent_up(); - } - } - - if (useFirstFlag && (!had_required)) - { - out << indent() << "if(!__first) { sb.Append(\", \"); }" << endl; - if (!is_required) - { - out << indent() << "__first = false;" << endl; - } - out << indent() << "sb.Append(\"" << prop_name(*f_iter) << ": \");" << endl; - } - else - { - out << indent() << "sb.Append(\", " << prop_name(*f_iter) << ": \");" << endl; - } - - t_type* ttype = (*f_iter)->get_type(); - if (ttype->is_xception() || ttype->is_struct()) - { - out << indent() << "sb.Append(" << prop_name(*f_iter) << "== null ? \"\" : " << prop_name(*f_iter) << ".ToString());" << endl; - } - else - { - out << indent() << "sb.Append(" << prop_name(*f_iter) << ");" << endl; - } - - if (!is_required) - { - indent_down(); - out << indent() << "}" << endl; - } - else - { - had_required = true; // now __first must be false, so we don't need to check it anymore - } - } - - out << indent() << "sb.Append(\")\");" << endl - << indent() << "return sb.ToString();" << endl; - indent_down(); - out << indent() << "}" << endl; -} - -void t_netcore_generator::generate_netcore_union(t_struct* tunion) -{ - int ic = indent_count(); - - string f_union_name = namespace_dir_ + "/" + (tunion->get_name()) + ".cs"; - ofstream_with_content_based_conditional_update f_union; - - f_union.open(f_union_name.c_str()); - - f_union << autogen_comment() << netcore_type_usings() << netcore_thrift_usings() << endl; - - generate_netcore_union_definition(f_union, tunion); - - f_union.close(); - - indent_validate(ic, "generate_netcore_union."); -} - -void t_netcore_generator::generate_netcore_union_definition(ostream& out, t_struct* tunion) -{ - // Let's define the class first - start_netcore_namespace(out); - - out << indent() << "public abstract partial class " << tunion->get_name() << " : TAbstractBase" << endl - << indent() << "{" << endl; - indent_up(); - - out << indent() << "public abstract Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken);" << endl - << indent() << "public readonly int Isset;" << endl - << indent() << "public abstract object Data { get; }" << endl - << indent() << "protected " << tunion->get_name() << "(int isset)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "Isset = isset;" << endl; - indent_down(); - out << indent() << "}" << endl << endl; - - out << indent() << "public class ___undefined : " << tunion->get_name() << endl - << indent() << "{" << endl; - indent_up(); - - out << indent() << "public override object Data { get { return null; } }" << endl - << indent() << "public ___undefined() : base(0) {}" << endl << endl; - - out << indent() << "public override Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "throw new TProtocolException( TProtocolException.INVALID_DATA, \"Cannot persist an union type which is not set.\");" << endl; - indent_down(); - out << indent() << "}" << endl << endl; - indent_down(); - out << indent() << "}" << endl << endl; - - const vector& fields = tunion->get_members(); - vector::const_iterator f_iter; - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - generate_netcore_union_class(out, tunion, (*f_iter)); - } - - generate_netcore_union_reader(out, tunion); - - indent_down(); - out << indent() << "}" << endl << endl; - - end_netcore_namespace(out); -} - -void t_netcore_generator::generate_netcore_union_class(ostream& out, t_struct* tunion, t_field* tfield) -{ - out << indent() << "public " << type_name(tfield->get_type()) << " As_" << tfield->get_name() << endl; - out << indent() << "{" << endl; - indent_up(); - out << indent() << "get" << endl; - out << indent() << "{" << endl; - indent_up(); - out << indent() << "return (" << tfield->get_key() << " == Isset) ? (" << type_name(tfield->get_type()) << ")Data : default(" << type_name(tfield->get_type()) << ");" << endl; - indent_down(); - out << indent() << "}" << endl; - indent_down(); - out << indent() << "}" << endl - << endl; - - - out << indent() << "public class " << tfield->get_name() << " : " << tunion->get_name() << endl - << indent() << "{" << endl; - indent_up(); - - out << indent() << "private " << type_name(tfield->get_type()) << " _data;" << endl - << indent() << "public override object Data { get { return _data; } }" << endl - << indent() << "public " << tfield->get_name() << "(" << type_name(tfield->get_type()) << " data) : base("<< tfield->get_key() <<")" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "this._data = data;" << endl; - indent_down(); - out << indent() << "}" << endl; - - out << indent() << "public override async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) {" << endl; - indent_up(); - - out << indent() << "oprot.IncrementRecursionDepth();" << endl - << indent() << "try" << endl - << indent() << "{" << endl; - indent_up(); - - out << indent() << "var struc = new TStruct(\"" << tunion->get_name() << "\");" << endl - << indent() << "await oprot.WriteStructBeginAsync(struc, cancellationToken);" << endl; - - out << indent() << "var field = new TField();" << endl - << indent() << "field.Name = \"" << tfield->get_name() << "\";" << endl - << indent() << "field.Type = " << type_to_enum(tfield->get_type()) << ";" << endl - << indent() << "field.ID = " << tfield->get_key() << ";" << endl - << indent() << "await oprot.WriteFieldBeginAsync(field, cancellationToken);" << endl; - - generate_serialize_field(out, tfield, "_data", true, true); - - out << indent() << "await oprot.WriteFieldEndAsync(cancellationToken);" << endl - << indent() << "await oprot.WriteFieldStopAsync(cancellationToken);" << endl - << indent() << "await oprot.WriteStructEndAsync(cancellationToken);" << endl; - indent_down(); - out << indent() << "}" << endl - << indent() << "finally" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "oprot.DecrementRecursionDepth();" << endl; - indent_down(); - out << indent() << "}" << endl; - out << indent() << "}" << endl; - indent_down(); - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_netcore_struct_equals(ostream& out, t_struct* tstruct) -{ - out << indent() << "public override bool Equals(object that)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "var other = that as " << check_and_correct_struct_name(normalize_name(tstruct->get_name())) << ";" << endl - << indent() << "if (other == null) return false;" << endl - << indent() << "if (ReferenceEquals(this, other)) return true;" << endl; - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - bool first = true; - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - if (first) - { - first = false; - out << indent() << "return "; - indent_up(); - } - else - { - out << endl; - out << indent() << "&& "; - } - if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) - { - out << "((__isset." << normalize_name((*f_iter)->get_name()) << " == other.__isset." - << normalize_name((*f_iter)->get_name()) << ") && ((!__isset." - << normalize_name((*f_iter)->get_name()) << ") || ("; - } - t_type* ttype = (*f_iter)->get_type(); - if (ttype->is_container() || ttype->is_binary()) - { - out << "TCollections.Equals("; - } - else - { - out << "System.Object.Equals("; - } - out << prop_name((*f_iter)) << ", other." << prop_name((*f_iter)) << ")"; - if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) - { - out << ")))"; - } - } - if (first) - { - out << indent() << "return true;" << endl; - } - else - { - out << ";" << endl; - indent_down(); - } - - indent_down(); - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_netcore_struct_hashcode(ostream& out, t_struct* tstruct) -{ - out << indent() << "public override int GetHashCode() {" << endl; - indent_up(); - - out << indent() << "int hashcode = 0;" << endl; - out << indent() << "unchecked {" << endl; - indent_up(); - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - t_type* ttype = (*f_iter)->get_type(); - out << indent() << "hashcode = (hashcode * 397) ^ "; - if (field_is_required((*f_iter))) - { - out << "("; - } - else if (nullable_) - { - out << "(" << prop_name((*f_iter)) << " == null ? 0 : "; - } - else - { - out << "(!__isset." << normalize_name((*f_iter)->get_name()) << " ? 0 : "; - } - if (ttype->is_container()) - { - out << "(TCollections.GetHashCode(" << prop_name((*f_iter)) << "))"; - } - else - { - out << "(" << prop_name((*f_iter)) << ".GetHashCode())"; - } - out << ");" << endl; - } - - indent_down(); - out << indent() << "}" << endl; - out << indent() << "return hashcode;" << endl; - - indent_down(); - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_service(t_service* tservice) -{ - int ic = indent_count(); - - string f_service_name = namespace_dir_ + "/" + service_name_ + ".cs"; - ofstream_with_content_based_conditional_update f_service; - f_service.open(f_service_name.c_str()); - - f_service << autogen_comment() << netcore_type_usings() << netcore_thrift_usings() << endl; - - start_netcore_namespace(f_service); - - f_service << indent() << "public partial class " << normalize_name(service_name_) << endl - << indent() << "{" << endl; - indent_up(); - - generate_service_interface(f_service, tservice); - generate_service_client(f_service, tservice); - generate_service_server(f_service, tservice); - generate_service_helpers(f_service, tservice); - - indent_down(); - f_service << indent() << "}" << endl; - - end_netcore_namespace(f_service); - f_service.close(); - - indent_validate(ic, "generate_service."); -} - -void t_netcore_generator::generate_service_interface(ostream& out, t_service* tservice) -{ - string extends = ""; - string extends_iface = ""; - if (tservice->get_extends() != NULL) - { - extends = type_name(tservice->get_extends()); - extends_iface = " : " + extends + ".IAsync"; - } - - //out << endl << endl; - - generate_netcore_doc(out, tservice); - - if (wcf_) - { - out << indent() << "[ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; - } - - out << indent() << "public interface IAsync" << extends_iface << endl - << indent() << "{" << endl; - - indent_up(); - vector functions = tservice->get_functions(); - vector::iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) - { - generate_netcore_doc(out, *f_iter); - - // if we're using WCF, add the corresponding attributes - if (wcf_) - { - out << indent() << "[OperationContract]" << endl; - - const vector& xceptions = (*f_iter)->get_xceptions()->get_members(); - vector::const_iterator x_iter; - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) - { - out << indent() << "[FaultContract(typeof(" + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl; - } - } - - out << indent() << function_signature_async(*f_iter) << ";" << endl << endl; - } - indent_down(); - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_service_helpers(ostream& out, t_service* tservice) -{ - vector functions = tservice->get_functions(); - vector::iterator f_iter; - - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) - { - t_struct* ts = (*f_iter)->get_arglist(); - generate_netcore_struct_definition(out, ts, false, true); - generate_function_helpers(out, *f_iter); - } -} - -void t_netcore_generator::generate_service_client(ostream& out, t_service* tservice) -{ - string extends = ""; - string extends_client = ""; - if (tservice->get_extends() != NULL) - { - extends = type_name(tservice->get_extends()); - extends_client = extends + ".Client, "; - } - else - { - extends_client = "TBaseClient, IDisposable, "; - } - - out << endl; - - generate_netcore_doc(out, tservice); - - out << indent() << "public class Client : " << extends_client << "IAsync" << endl - << indent() << "{" << endl; - indent_up(); - - out << indent() << "public Client(TProtocol protocol) : this(protocol, protocol)" << endl - << indent() << "{" << endl - << indent() << "}" << endl - << endl - << indent() << "public Client(TProtocol inputProtocol, TProtocol outputProtocol) : base(inputProtocol, outputProtocol)" - << indent() << "{" << endl - << indent() << "}" << endl; - - vector functions = tservice->get_functions(); - vector::const_iterator functions_iterator; - - for (functions_iterator = functions.begin(); functions_iterator != functions.end(); ++functions_iterator) - { - string function_name = correct_function_name_for_async((*functions_iterator)->get_name()); - - // async - out << indent() << "public async " << function_signature_async(*functions_iterator, "") << endl - << indent() << "{" << endl; - indent_up(); - - string argsname = (*functions_iterator)->get_name() + "Args"; - - out << indent() << "await OutputProtocol.WriteMessageBeginAsync(new TMessage(\"" << function_name - << "\", " << ((*functions_iterator)->is_oneway() ? "TMessageType.Oneway" : "TMessageType.Call") << ", SeqId), cancellationToken);" << endl - << indent() << endl - << indent() << "var args = new " << argsname << "();" << endl; - - t_struct* arg_struct = (*functions_iterator)->get_arglist(); - prepare_member_name_mapping(arg_struct); - const vector& fields = arg_struct->get_members(); - vector::const_iterator fld_iter; - - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) - { - out << indent() << "args." << prop_name(*fld_iter) << " = " << normalize_name((*fld_iter)->get_name()) << ";" << endl; - } - - out << indent() << endl - << indent() << "await args.WriteAsync(OutputProtocol, cancellationToken);" << endl - << indent() << "await OutputProtocol.WriteMessageEndAsync(cancellationToken);" << endl - << indent() << "await OutputProtocol.Transport.FlushAsync(cancellationToken);" << endl; - - if (!(*functions_iterator)->is_oneway()) - { - string resultname = (*functions_iterator)->get_name() + "Result"; - t_struct noargs(program_); - t_struct* xs = (*functions_iterator)->get_xceptions(); - prepare_member_name_mapping(xs, xs->get_members(), resultname); - - out << indent() << endl - << indent() << "var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);" << endl - << indent() << "if (msg.Type == TMessageType.Exception)" << endl - << indent() << "{" << endl; - indent_up(); - - out << indent() << "var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);" << endl - << indent() << "await InputProtocol.ReadMessageEndAsync(cancellationToken);" << endl - << indent() << "throw x;" << endl; - indent_down(); - - out << indent() << "}" << endl - << endl - << indent() << "var result = new " << resultname << "();" << endl - << indent() << "await result.ReadAsync(InputProtocol, cancellationToken);" << endl - << indent() << "await InputProtocol.ReadMessageEndAsync(cancellationToken);" << endl; - - if (!(*functions_iterator)->get_returntype()->is_void()) - { - if (nullable_) - { - if (type_can_be_null((*functions_iterator)->get_returntype())) - { - out << indent() << "if (result.Success != null)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "return result.Success;" << endl; - indent_down(); - out << indent() << "}" << endl; - } - else - { - out << indent() << "if (result.Success.HasValue)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "return result.Success.Value;" << endl; - indent_down(); - out << indent() << "}" << endl; - } - } - else - { - out << indent() << "if (result.__isset.success)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "return result.Success;" << endl; - indent_down(); - out << indent() << "}" << endl; - } - } - - const vector& xceptions = xs->get_members(); - vector::const_iterator x_iter; - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) - { - if (nullable_) - { - out << indent() << "if (result." << prop_name(*x_iter) << " != null)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "throw result." << prop_name(*x_iter) << ";" << endl; - indent_down(); - out << indent() << "}" << endl; - } - else - { - out << indent() << "if (result.__isset." << normalize_name((*x_iter)->get_name()) << ")" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "throw result." << prop_name(*x_iter) << ";" << endl; - indent_down(); - out << indent() << "}" << endl; - } - } - - if ((*functions_iterator)->get_returntype()->is_void()) - { - out << indent() << "return;" << endl; - } - else - { - out << indent() << "throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, \"" - << function_name << " failed: unknown result\");" << endl; - } - - cleanup_member_name_mapping((*functions_iterator)->get_xceptions()); - indent_down(); - out << indent() << "}" << endl << endl; - } - else - { - indent_down(); - out << indent() << "}" << endl; - } - } - - indent_down(); - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_service_server(ostream& out, t_service* tservice) -{ - vector functions = tservice->get_functions(); - vector::iterator f_iter; - - string extends = ""; - string extends_processor = ""; - if (tservice->get_extends() != NULL) - { - extends = type_name(tservice->get_extends()); - extends_processor = extends + ".AsyncProcessor, "; - } - - out << indent() << "public class AsyncProcessor : " << extends_processor << "ITAsyncProcessor" << endl - << indent() << "{" << endl; - - indent_up(); - - out << indent() << "private IAsync _iAsync;" << endl - << endl - << indent() << "public AsyncProcessor(IAsync iAsync)"; - - if (!extends.empty()) - { - out << " : base(iAsync)"; - } - - out << endl - << indent() << "{" << endl; - indent_up(); - - out << indent() << "if (iAsync == null) throw new ArgumentNullException(nameof(iAsync));" << endl - << endl - << indent() << "_iAsync = iAsync;" << endl; - - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) - { - string function_name = (*f_iter)->get_name(); - out << indent() << "processMap_[\"" << correct_function_name_for_async(function_name) << "\"] = " << function_name << "_ProcessAsync;" << endl; - } - - indent_down(); - out << indent() << "}" << endl - << endl; - - if (extends.empty()) - { - out << indent() << "protected delegate Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken);" << endl; - } - - if (extends.empty()) - { - out << indent() << "protected Dictionary processMap_ = new Dictionary();" << endl; - } - - out << endl; - - if (extends.empty()) - { - out << indent() << "public async Task ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "return await ProcessAsync(iprot, oprot, CancellationToken.None);" << endl; - indent_down(); - out << indent() << "}" << endl << endl; - - out << indent() << "public async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken)" << endl; - } - else - { - out << indent() << "public new async Task ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "return await ProcessAsync(iprot, oprot, CancellationToken.None);" << endl; - indent_down(); - out << indent() << "}" << endl << endl; - - out << indent() << "public new async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken)" << endl; - } - - out << indent() << "{" << endl; - indent_up(); - out << indent() << "try" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "var msg = await iprot.ReadMessageBeginAsync(cancellationToken);" << endl - << endl - << indent() << "ProcessFunction fn;" << endl - << indent() << "processMap_.TryGetValue(msg.Name, out fn);" << endl - << endl - << indent() << "if (fn == null)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "await TProtocolUtil.SkipAsync(iprot, TType.Struct, cancellationToken);" << endl - << indent() << "await iprot.ReadMessageEndAsync(cancellationToken);" << endl - << indent() << "var x = new TApplicationException (TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + msg.Name + \"'\");" << endl - << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID), cancellationToken);" << endl - << indent() << "await x.WriteAsync(oprot, cancellationToken);" << endl - << indent() << "await oprot.WriteMessageEndAsync(cancellationToken);" << endl - << indent() << "await oprot.Transport.FlushAsync(cancellationToken);" << endl - << indent() << "return true;" << endl; - indent_down(); - out << indent() << "}" << endl - << endl - << indent() << "await fn(msg.SeqID, iprot, oprot, cancellationToken);" << endl - << endl; - indent_down(); - out << indent() << "}" << endl; - out << indent() << "catch (IOException)" << endl - << indent() << "{" << endl; - indent_up(); - out << indent() << "return false;" << endl; - indent_down(); - out << indent() << "}" << endl - << endl - << indent() << "return true;" << endl; - indent_down(); - out << indent() << "}" << endl << endl; - - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) - { - generate_process_function_async(out, tservice, *f_iter); - } - - indent_down(); - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_function_helpers(ostream& out, t_function* tfunction) -{ - if (tfunction->is_oneway()) - { - return; - } - - t_struct result(program_, tfunction->get_name() + "_result"); - t_field success(tfunction->get_returntype(), "success", 0); - if (!tfunction->get_returntype()->is_void()) - { - result.append(&success); - } - - t_struct* xs = tfunction->get_xceptions(); - const vector& fields = xs->get_members(); - vector::const_iterator f_iter; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - result.append(*f_iter); - } - - generate_netcore_struct_definition(out, &result, false, true, true); -} - -void t_netcore_generator::generate_process_function_async(ostream& out, t_service* tservice, t_function* tfunction) -{ - (void)tservice; - out << indent() << "public async Task " << tfunction->get_name() - << "_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken)" << endl - << indent() << "{" << endl; - indent_up(); - - string argsname = tfunction->get_name() + "Args"; - string resultname = tfunction->get_name() + "Result"; - - out << indent() << "var args = new " << argsname << "();" << endl - << indent() << "await args.ReadAsync(iprot, cancellationToken);" << endl - << indent() << "await iprot.ReadMessageEndAsync(cancellationToken);" << endl; - - if (!tfunction->is_oneway()) - { - out << indent() << "var result = new " << resultname << "();" << endl; - } - - out << indent() << "try" << endl - << indent() << "{" << endl; - indent_up(); - - t_struct* xs = tfunction->get_xceptions(); - const vector& xceptions = xs->get_members(); - - if (xceptions.size() > 0) - { - out << indent() << "try" << endl - << indent() << "{" << endl; - indent_up(); - } - - t_struct* arg_struct = tfunction->get_arglist(); - const vector& fields = arg_struct->get_members(); - vector::const_iterator f_iter; - - out << indent(); - if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) - { - out << "result.Success = "; - } - - out << "await _iAsync." << normalize_name(tfunction->get_name()) << "Async("; - - bool first = true; - prepare_member_name_mapping(arg_struct); - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - if (first) - { - first = false; - } - else - { - out << ", "; - } - - out << "args." << prop_name(*f_iter); - if (nullable_ && !type_can_be_null((*f_iter)->get_type())) - { - out << ".Value"; - } - } - - cleanup_member_name_mapping(arg_struct); - - if (!first) - { - out << ", "; - } - - out << "cancellationToken);" << endl; - - vector::const_iterator x_iter; - - prepare_member_name_mapping(xs, xs->get_members(), resultname); - if (xceptions.size() > 0) - { - indent_down(); - out << indent() << "}" << endl; - - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) - { - out << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " " << (*x_iter)->get_name() << ")" << endl - << indent() << "{" << endl; - - if (!tfunction->is_oneway()) - { - indent_up(); - out << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name() << ";" << endl; - indent_down(); - } - out << indent() << "}" << endl; - } - } - - if (!tfunction->is_oneway()) - { - out << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\"" - << correct_function_name_for_async(tfunction->get_name()) << "\", TMessageType.Reply, seqid), cancellationToken); " << endl - << indent() << "await result.WriteAsync(oprot, cancellationToken);" << endl; - } - indent_down(); - - cleanup_member_name_mapping(xs); - - out << indent() << "}" << endl - << indent() << "catch (TTransportException)" << endl - << indent() << "{" << endl - << indent() << " throw;" << endl - << indent() << "}" << endl - << indent() << "catch (Exception ex)" << endl - << indent() << "{" << endl; - indent_up(); - - out << indent() << "Console.Error.WriteLine(\"Error occurred in processor:\");" << endl - << indent() << "Console.Error.WriteLine(ex.ToString());" << endl; - - if (tfunction->is_oneway()) - { - indent_down(); - out << indent() << "}" << endl; - } - else - { - out << indent() << "var x = new TApplicationException(TApplicationException.ExceptionType.InternalError,\" Internal error.\");" << endl - << indent() << "await oprot.WriteMessageBeginAsync(new TMessage(\"" << correct_function_name_for_async(tfunction->get_name()) - << "\", TMessageType.Exception, seqid), cancellationToken);" << endl - << indent() << "await x.WriteAsync(oprot, cancellationToken);" << endl; - indent_down(); - - out << indent() << "}" << endl - << indent() << "await oprot.WriteMessageEndAsync(cancellationToken);" << endl - << indent() << "await oprot.Transport.FlushAsync(cancellationToken);" << endl; - } - - indent_down(); - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_netcore_union_reader(ostream& out, t_struct* tunion) -{ - // Thanks to THRIFT-1768, we don't need to check for required fields in the union - const vector& fields = tunion->get_members(); - vector::const_iterator f_iter; - - out << indent() << "public static async Task<" << tunion->get_name() << "> ReadAsync(TProtocol iprot, CancellationToken cancellationToken)" << endl; - scope_up(out); - - out << indent() << "iprot.IncrementRecursionDepth();" << endl; - out << indent() << "try" << endl; - scope_up(out); - - out << indent() << tunion->get_name() << " retval;" << endl; - out << indent() << "await iprot.ReadStructBeginAsync(cancellationToken);" << endl; - out << indent() << "TField field = await iprot.ReadFieldBeginAsync(cancellationToken);" << endl; - // we cannot have the first field be a stop -- we must have a single field defined - out << indent() << "if (field.Type == TType.Stop)" << endl; - scope_up(out); - out << indent() << "await iprot.ReadFieldEndAsync(cancellationToken);" << endl; - out << indent() << "retval = new ___undefined();" << endl; - scope_down(out); - out << indent() << "else" << endl; - scope_up(out); - out << indent() << "switch (field.ID)" << endl; - scope_up(out); - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; - indent_up(); - out << indent() << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; - indent_up(); - - out << indent() << type_name((*f_iter)->get_type()) << " temp;" << endl; - generate_deserialize_field(out, (*f_iter), "temp", true); - out << indent() << "retval = new " << (*f_iter)->get_name() << "(temp);" << endl; - - indent_down(); - out << indent() << "} else { " << endl << indent() << " await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);" - << endl << indent() << " retval = new ___undefined();" << endl << indent() << "}" << endl - << indent() << "break;" << endl; - indent_down(); - } - - out << indent() << "default: " << endl; - indent_up(); - out << indent() << "await TProtocolUtil.SkipAsync(iprot, field.Type, cancellationToken);" << endl << indent() - << "retval = new ___undefined();" << endl; - out << indent() << "break;" << endl; - indent_down(); - - scope_down(out); - - out << indent() << "await iprot.ReadFieldEndAsync(cancellationToken);" << endl; - - out << indent() << "if ((await iprot.ReadFieldBeginAsync(cancellationToken)).Type != TType.Stop)" << endl; - scope_up(out); - out << indent() << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl; - scope_down(out); - - // end of else for TStop - scope_down(out); - out << indent() << "await iprot.ReadStructEndAsync(cancellationToken);" << endl; - out << indent() << "return retval;" << endl; - indent_down(); - - scope_down(out); - out << indent() << "finally" << endl; - scope_up(out); - out << indent() << "iprot.DecrementRecursionDepth();" << endl; - scope_down(out); - - out << indent() << "}" << endl << endl; -} - -void t_netcore_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, bool is_propertyless) -{ - t_type* type = tfield->get_type(); - while (type->is_typedef()) - { - type = static_cast(type)->get_type(); - } - - if (type->is_void()) - { - throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); - } - - string name = prefix + (is_propertyless ? "" : prop_name(tfield)); - - if (type->is_struct() || type->is_xception()) - { - generate_deserialize_struct(out, static_cast(type), name); - } - else if (type->is_container()) - { - generate_deserialize_container(out, type, name); - } - else if (type->is_base_type() || type->is_enum()) - { - out << indent() << name << " = "; - - if (type->is_enum()) - { - out << "(" << type_name(type, false, true) << ")"; - } - - out << "await iprot."; - - if (type->is_base_type()) - { - t_base_type::t_base tbase = static_cast(type)->get_base(); - switch (tbase) - { - case t_base_type::TYPE_VOID: - throw "compiler error: cannot serialize void field in a struct: " + name; - break; - case t_base_type::TYPE_STRING: - if (type->is_binary()) - { - out << "ReadBinaryAsync(cancellationToken);"; - } - else - { - out << "ReadStringAsync(cancellationToken);"; - } - break; - case t_base_type::TYPE_BOOL: - out << "ReadBoolAsync(cancellationToken);"; - break; - case t_base_type::TYPE_I8: - out << "ReadByteAsync(cancellationToken);"; - break; - case t_base_type::TYPE_I16: - out << "ReadI16Async(cancellationToken);"; - break; - case t_base_type::TYPE_I32: - out << "ReadI32Async(cancellationToken);"; - break; - case t_base_type::TYPE_I64: - out << "ReadI64Async(cancellationToken);"; - break; - case t_base_type::TYPE_DOUBLE: - out << "ReadDoubleAsync(cancellationToken);"; - break; - default: - throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase); - } - } - else if (type->is_enum()) - { - out << "ReadI32Async(cancellationToken);"; - } - out << endl; - } - else - { - printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", tfield->get_name().c_str(), type_name(type).c_str()); - } -} - -void t_netcore_generator::generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix) -{ - if (union_ && tstruct->is_union()) - { - out << indent() << prefix << " = await " << type_name(tstruct) << ".ReadAsync(iprot, cancellationToken);" << endl; - } - else - { - out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl - << indent() << "await " << prefix << ".ReadAsync(iprot, cancellationToken);" << endl; - } -} - -void t_netcore_generator::generate_deserialize_container(ostream& out, t_type* ttype, string prefix) -{ - out << indent() << "{" << endl; - indent_up(); - - string obj; - - if (ttype->is_map()) - { - obj = tmp("_map"); - } - else if (ttype->is_set()) - { - obj = tmp("_set"); - } - else if (ttype->is_list()) - { - obj = tmp("_list"); - } - - out << indent() << prefix << " = new " << type_name(ttype, false, true) << "();" << endl; - if (ttype->is_map()) - { - out << indent() << "TMap " << obj << " = await iprot.ReadMapBeginAsync(cancellationToken);" << endl; - } - else if (ttype->is_set()) - { - out << indent() << "TSet " << obj << " = await iprot.ReadSetBeginAsync(cancellationToken);" << endl; - } - else if (ttype->is_list()) - { - out << indent() << "TList " << obj << " = await iprot.ReadListBeginAsync(cancellationToken);" << endl; - } - - string i = tmp("_i"); - out << indent() << "for(int " << i << " = 0; " << i << " < " << obj << ".Count; ++" << i << ")" << endl - << indent() << "{" << endl; - indent_up(); - - if (ttype->is_map()) - { - generate_deserialize_map_element(out, static_cast(ttype), prefix); - } - else if (ttype->is_set()) - { - generate_deserialize_set_element(out, static_cast(ttype), prefix); - } - else if (ttype->is_list()) - { - generate_deserialize_list_element(out, static_cast(ttype), prefix); - } - - indent_down(); - out << indent() << "}" << endl; - - if (ttype->is_map()) - { - out << indent() << "await iprot.ReadMapEndAsync(cancellationToken);" << endl; - } - else if (ttype->is_set()) - { - out << indent() << "await iprot.ReadSetEndAsync(cancellationToken);" << endl; - } - else if (ttype->is_list()) - { - out << indent() << "await iprot.ReadListEndAsync(cancellationToken);" << endl; - } - - indent_down(); - out << indent() << "}" << endl; -} - -void t_netcore_generator::generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix) -{ - string key = tmp("_key"); - string val = tmp("_val"); - - t_field fkey(tmap->get_key_type(), key); - t_field fval(tmap->get_val_type(), val); - - out << indent() << declare_field(&fkey) << endl; - out << indent() << declare_field(&fval) << endl; - - generate_deserialize_field(out, &fkey); - generate_deserialize_field(out, &fval); - - out << indent() << prefix << "[" << key << "] = " << val << ";" << endl; -} - -void t_netcore_generator::generate_deserialize_set_element(ostream& out, t_set* tset, string prefix) -{ - string elem = tmp("_elem"); - t_field felem(tset->get_elem_type(), elem); - - out << indent() << declare_field(&felem) << endl; - - generate_deserialize_field(out, &felem); - - out << indent() << prefix << ".Add(" << elem << ");" << endl; -} - -void t_netcore_generator::generate_deserialize_list_element(ostream& out, t_list* tlist, string prefix) -{ - string elem = tmp("_elem"); - t_field felem(tlist->get_elem_type(), elem); - - out << indent() << declare_field(&felem) << endl; - - generate_deserialize_field(out, &felem); - - out << indent() << prefix << ".Add(" << elem << ");" << endl; -} - -void t_netcore_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix, bool is_element, bool is_propertyless) -{ - t_type* type = tfield->get_type(); - while (type->is_typedef()) - { - type = static_cast(type)->get_type(); - } - - string name = prefix + (is_propertyless ? "" : prop_name(tfield)); - - if (type->is_void()) - { - throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; - } - - if (type->is_struct() || type->is_xception()) - { - generate_serialize_struct(out, static_cast(type), name); - } - else if (type->is_container()) - { - generate_serialize_container(out, type, name); - } - else if (type->is_base_type() || type->is_enum()) - { - out << indent() << "await oprot."; - - string nullable_name = nullable_ && !is_element && !field_is_required(tfield) ? name + ".Value" : name; - - if (type->is_base_type()) - { - t_base_type::t_base tbase = static_cast(type)->get_base(); - switch (tbase) - { - case t_base_type::TYPE_VOID: - throw "compiler error: cannot serialize void field in a struct: " + name; - case t_base_type::TYPE_STRING: - if (type->is_binary()) - { - out << "WriteBinaryAsync("; - } - else - { - out << "WriteStringAsync("; - } - out << name << ", cancellationToken);"; - break; - case t_base_type::TYPE_BOOL: - out << "WriteBoolAsync(" << nullable_name << ", cancellationToken);"; - break; - case t_base_type::TYPE_I8: - out << "WriteByteAsync(" << nullable_name << ", cancellationToken);"; - break; - case t_base_type::TYPE_I16: - out << "WriteI16Async(" << nullable_name << ", cancellationToken);"; - break; - case t_base_type::TYPE_I32: - out << "WriteI32Async(" << nullable_name << ", cancellationToken);"; - break; - case t_base_type::TYPE_I64: - out << "WriteI64Async(" << nullable_name << ", cancellationToken);"; - break; - case t_base_type::TYPE_DOUBLE: - out << "WriteDoubleAsync(" << nullable_name << ", cancellationToken);"; - break; - default: - throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase); - } - } - else if (type->is_enum()) - { - out << "WriteI32Async((int)" << nullable_name << ", cancellationToken);"; - } - out << endl; - } - else - { - printf("DO NOT KNOW HOW TO SERIALIZE '%s%s' TYPE '%s'\n", prefix.c_str(), tfield->get_name().c_str(), type_name(type).c_str()); - } -} - -void t_netcore_generator::generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix) -{ - (void)tstruct; - out << indent() << "await " << prefix << ".WriteAsync(oprot, cancellationToken);" << endl; -} - -void t_netcore_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) -{ - out << indent() << "{" << endl; - indent_up(); - - if (ttype->is_map()) - { - out << indent() << "await oprot.WriteMapBeginAsync(new TMap(" << type_to_enum(static_cast(ttype)->get_key_type()) - << ", " << type_to_enum(static_cast(ttype)->get_val_type()) << ", " << prefix - << ".Count), cancellationToken);" << endl; - } - else if (ttype->is_set()) - { - out << indent() << "await oprot.WriteSetBeginAsync(new TSet(" << type_to_enum(static_cast(ttype)->get_elem_type()) - << ", " << prefix << ".Count), cancellationToken);" << endl; - } - else if (ttype->is_list()) - { - out << indent() << "await oprot.WriteListBeginAsync(new TList(" - << type_to_enum(static_cast(ttype)->get_elem_type()) << ", " << prefix << ".Count), cancellationToken);" - << endl; - } - - string iter = tmp("_iter"); - if (ttype->is_map()) - { - out << indent() << "foreach (" << type_name(static_cast(ttype)->get_key_type()) << " " << iter - << " in " << prefix << ".Keys)"; - } - else if (ttype->is_set()) - { - out << indent() << "foreach (" << type_name(static_cast(ttype)->get_elem_type()) << " " << iter - << " in " << prefix << ")"; - } - else if (ttype->is_list()) - { - out << indent() << "foreach (" << type_name(static_cast(ttype)->get_elem_type()) << " " << iter - << " in " << prefix << ")"; - } - - out << endl; - out << indent() << "{" << endl; - indent_up(); - - if (ttype->is_map()) - { - generate_serialize_map_element(out, static_cast(ttype), iter, prefix); - } - else if (ttype->is_set()) - { - generate_serialize_set_element(out, static_cast(ttype), iter); - } - else if (ttype->is_list()) - { - generate_serialize_list_element(out, static_cast(ttype), iter); - } - - indent_down(); - out << indent() << "}" << endl; - - if (ttype->is_map()) - { - out << indent() << "await oprot.WriteMapEndAsync(cancellationToken);" << endl; - } - else if (ttype->is_set()) - { - out << indent() << "await oprot.WriteSetEndAsync(cancellationToken);" << endl; - } - else if (ttype->is_list()) - { - out << indent() << "await oprot.WriteListEndAsync(cancellationToken);" << endl; - } - - indent_down(); - out << indent() << "}" << endl; -} - -void t_netcore_generator::generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map) -{ - t_field kfield(tmap->get_key_type(), iter); - generate_serialize_field(out, &kfield, "", true); - t_field vfield(tmap->get_val_type(), map + "[" + iter + "]"); - generate_serialize_field(out, &vfield, "", true); -} - -void t_netcore_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) -{ - t_field efield(tset->get_elem_type(), iter); - generate_serialize_field(out, &efield, "", true); -} - -void t_netcore_generator::generate_serialize_list_element(ostream& out, t_list* tlist, string iter) -{ - t_field efield(tlist->get_elem_type(), iter); - generate_serialize_field(out, &efield, "", true); -} - -void t_netcore_generator::generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset) -{ - generate_netcore_property(out, tfield, isPublic, generateIsset, "_"); -} - -void t_netcore_generator::generate_netcore_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset, string fieldPrefix) -{ - if ((serialize_ || wcf_) && isPublic) - { - out << indent() << "[DataMember(Order = 0)]" << endl; - } - bool has_default = field_has_default(tfield); - bool is_required = field_is_required(tfield); - if ((nullable_ && !has_default) || is_required) - { - out << indent() << (isPublic ? "public " : "private ") << type_name(tfield->get_type(), false, false, true, is_required) << " " << prop_name(tfield) << " { get; set; }" << endl; - } - else - { - out << indent() << (isPublic ? "public " : "private ") << type_name(tfield->get_type(), false, false, true) << " " << prop_name(tfield) << endl - << indent() << "{" << endl; - indent_up(); - - out << indent() << "get" << endl - << indent() << "{" << endl; - indent_up(); - - bool use_nullable = false; - if (nullable_) - { - t_type* ttype = tfield->get_type(); - while (ttype->is_typedef()) - { - ttype = static_cast(ttype)->get_type(); - } - if (ttype->is_base_type()) - { - use_nullable = static_cast(ttype)->get_base() != t_base_type::TYPE_STRING; - } - } - - out << indent() << "return " << fieldPrefix + tfield->get_name() << ";" << endl; - indent_down(); - out << indent() << "}" << endl - << indent() << "set" << endl - << indent() << "{" << endl; - indent_up(); - - if (use_nullable) - { - if (generateIsset) - { - out << indent() << "__isset." << normalize_name(tfield->get_name()) << " = value.HasValue;" << endl; - } - out << indent() << "if (value.HasValue) this." << fieldPrefix + tfield->get_name() << " = value.Value;" << endl; - } - else - { - if (generateIsset) - { - out << indent() << "__isset." << normalize_name(tfield->get_name()) << " = true;" << endl; - } - out << indent() << "this." << fieldPrefix + tfield->get_name() << " = value;" << endl; - } - - indent_down(); - out << indent() << "}" << endl; - indent_down(); - out << indent() << "}" << endl; - } - out << endl; -} - -string t_netcore_generator::make_valid_csharp_identifier(string const& fromName) -{ - string str = fromName; - if (str.empty()) - { - return str; - } - - // tests rely on this - assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9')); - - // if the first letter is a number, we add an additional underscore in front of it - char c = str.at(0); - if (('0' <= c) && (c <= '9')) - { - str = "_" + str; - } - - // following chars: letter, number or underscore - for (size_t i = 0; i < str.size(); ++i) - { - c = str.at(i); - if (('A' > c || c > 'Z') && ('a' > c || c > 'z') && ('0' > c || c > '9') && '_' != c) - { - str.replace(i, 1, "_"); - } - } - - return str; -} - -void t_netcore_generator::cleanup_member_name_mapping(void* scope) -{ - if (member_mapping_scopes.empty()) - { - throw "internal error: cleanup_member_name_mapping() no scope active"; - } - - member_mapping_scope& active = member_mapping_scopes.back(); - if (active.scope_member != scope) - { - throw "internal error: cleanup_member_name_mapping() called for wrong struct"; - } - - member_mapping_scopes.pop_back(); -} - -string t_netcore_generator::get_mapped_member_name(string name) -{ - if (!member_mapping_scopes.empty()) - { - member_mapping_scope& active = member_mapping_scopes.back(); - map::iterator iter = active.mapping_table.find(name); - if (active.mapping_table.end() != iter) - { - return iter->second; - } - } - - pverbose("no mapping for member %s\n", name.c_str()); - return name; -} - -void t_netcore_generator::prepare_member_name_mapping(t_struct* tstruct) -{ - prepare_member_name_mapping(tstruct, tstruct->get_members(), tstruct->get_name()); -} - -void t_netcore_generator::prepare_member_name_mapping(void* scope, const vector& members, const string& structname) -{ - // begin new scope - member_mapping_scopes.emplace_back(); - member_mapping_scope& active = member_mapping_scopes.back(); - active.scope_member = scope; - - // current C# generator policy: - // - prop names are always rendered with an Uppercase first letter - // - struct names are used as given - std::set used_member_names; - vector::const_iterator iter; - - // prevent name conflicts with struct (CS0542 error) - used_member_names.insert(structname); - - // prevent name conflicts with known methods (THRIFT-2942) - used_member_names.insert("Read"); - used_member_names.insert("Write"); - - for (iter = members.begin(); iter != members.end(); ++iter) - { - string oldname = (*iter)->get_name(); - string newname = prop_name(*iter, true); - while (true) - { - // new name conflicts with another member - if (used_member_names.find(newname) != used_member_names.end()) - { - pverbose("struct %s: member %s conflicts with another member\n", structname.c_str(), newname.c_str()); - newname += '_'; - continue; - } - - // add always, this helps us to detect edge cases like - // different spellings ("foo" and "Foo") within the same struct - pverbose("struct %s: member mapping %s => %s\n", structname.c_str(), oldname.c_str(), newname.c_str()); - active.mapping_table[oldname] = newname; - used_member_names.insert(newname); - break; - } - } -} - -string t_netcore_generator::prop_name(t_field* tfield, bool suppress_mapping) -{ - string name(tfield->get_name()); - if (suppress_mapping) - { - name[0] = toupper(name[0]); - } - else - { - name = get_mapped_member_name(name); - } - return name; -} - -string t_netcore_generator::type_name(t_type* ttype, bool in_container, bool in_init, bool in_param, bool is_required) -{ - (void)in_init; - - while (ttype->is_typedef()) - { - ttype = static_cast(ttype)->get_type(); - } - - if (ttype->is_base_type()) - { - return base_type_name(static_cast(ttype), in_container, in_param, is_required); - } - - if (ttype->is_map()) - { - t_map* tmap = static_cast(ttype); - return "Dictionary<" + type_name(tmap->get_key_type(), true) + ", " + type_name(tmap->get_val_type(), true) + ">"; - } - - if (ttype->is_set()) - { - t_set* tset = static_cast(ttype); - return "THashSet<" + type_name(tset->get_elem_type(), true) + ">"; - } - - if (ttype->is_list()) - { - t_list* tlist = static_cast(ttype); - return "List<" + type_name(tlist->get_elem_type(), true) + ">"; - } - - t_program* program = ttype->get_program(); - string postfix = (!is_required && nullable_ && in_param && ttype->is_enum()) ? "?" : ""; - if (program != NULL && program != program_) - { - string ns = program->get_namespace("netcore"); - if (!ns.empty()) - { - return ns + "." + normalize_name(ttype->get_name()) + postfix; - } - } - - return normalize_name(ttype->get_name()) + postfix; -} - -string t_netcore_generator::base_type_name(t_base_type* tbase, bool in_container, bool in_param, bool is_required) -{ - (void)in_container; - string postfix = (!is_required && nullable_ && in_param) ? "?" : ""; - switch (tbase->get_base()) - { - case t_base_type::TYPE_VOID: - return "void"; - case t_base_type::TYPE_STRING: - { - if (tbase->is_binary()) - { - return "byte[]"; - } - return "string"; - } - case t_base_type::TYPE_BOOL: - return "bool" + postfix; - case t_base_type::TYPE_I8: - return "sbyte" + postfix; - case t_base_type::TYPE_I16: - return "short" + postfix; - case t_base_type::TYPE_I32: - return "int" + postfix; - case t_base_type::TYPE_I64: - return "long" + postfix; - case t_base_type::TYPE_DOUBLE: - return "double" + postfix; - default: - throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase->get_base()); - } -} - -string t_netcore_generator::declare_field(t_field* tfield, bool init, string prefix) -{ - string result = type_name(tfield->get_type()) + " " + prefix + tfield->get_name(); - if (init) - { - t_type* ttype = tfield->get_type(); - while (ttype->is_typedef()) - { - ttype = static_cast(ttype)->get_type(); - } - if (ttype->is_base_type() && field_has_default(tfield)) - { - std::ofstream dummy; - result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value()); - } - else if (ttype->is_base_type()) - { - t_base_type::t_base tbase = static_cast(ttype)->get_base(); - switch (tbase) - { - case t_base_type::TYPE_VOID: - throw "NO T_VOID CONSTRUCT"; - case t_base_type::TYPE_STRING: - result += " = null"; - break; - case t_base_type::TYPE_BOOL: - result += " = false"; - break; - case t_base_type::TYPE_I8: - case t_base_type::TYPE_I16: - case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: - result += " = 0"; - break; - case t_base_type::TYPE_DOUBLE: - result += " = (double)0"; - break; - } - } - else if (ttype->is_enum()) - { - result += " = (" + type_name(ttype, false, true) + ")0"; - } - else if (ttype->is_container()) - { - result += " = new " + type_name(ttype, false, true) + "()"; - } - else - { - result += " = new " + type_name(ttype, false, true) + "()"; - } - } - return result + ";"; -} - -string t_netcore_generator::function_signature(t_function* tfunction, string prefix) -{ - t_type* ttype = tfunction->get_returntype(); - return type_name(ttype) + " " + normalize_name(prefix + tfunction->get_name()) + "(" + argument_list(tfunction->get_arglist()) + ")"; -} - -string t_netcore_generator::function_signature_async(t_function* tfunction, string prefix) -{ - t_type* ttype = tfunction->get_returntype(); - string task = "Task"; - if (!ttype->is_void()) - { - task += "<" + type_name(ttype) + ">"; - } - - string result = task + " " + normalize_name(prefix + tfunction->get_name()) + "Async("; - string args = argument_list(tfunction->get_arglist()); - result += args; - if (!args.empty()) - { - result += ", "; - } - result += "CancellationToken cancellationToken)"; - - return result; -} - -string t_netcore_generator::argument_list(t_struct* tstruct) -{ - string result = ""; - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - bool first = true; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) - { - if (first) - { - first = false; - } - else - { - result += ", "; - } - result += type_name((*f_iter)->get_type()) + " " + normalize_name((*f_iter)->get_name()); - } - return result; -} - -string t_netcore_generator::type_to_enum(t_type* type) -{ - while (type->is_typedef()) - { - type = static_cast(type)->get_type(); - } - - if (type->is_base_type()) - { - t_base_type::t_base tbase = static_cast(type)->get_base(); - switch (tbase) - { - case t_base_type::TYPE_VOID: - throw "NO T_VOID CONSTRUCT"; - case t_base_type::TYPE_STRING: - return "TType.String"; - case t_base_type::TYPE_BOOL: - return "TType.Bool"; - case t_base_type::TYPE_I8: - return "TType.Byte"; - case t_base_type::TYPE_I16: - return "TType.I16"; - case t_base_type::TYPE_I32: - return "TType.I32"; - case t_base_type::TYPE_I64: - return "TType.I64"; - case t_base_type::TYPE_DOUBLE: - return "TType.Double"; - } - } - else if (type->is_enum()) - { - return "TType.I32"; - } - else if (type->is_struct() || type->is_xception()) - { - return "TType.Struct"; - } - else if (type->is_map()) - { - return "TType.Map"; - } - else if (type->is_set()) - { - return "TType.Set"; - } - else if (type->is_list()) - { - return "TType.List"; - } - - throw "INVALID TYPE IN type_to_enum: " + type->get_name(); -} - -void t_netcore_generator::generate_netcore_docstring_comment(ostream& out, string contents) -{ - docstring_comment(out, "/// " + endl, "/// ", contents, "/// " + endl); -} - -void t_netcore_generator::generate_netcore_doc(ostream& out, t_field* field) -{ - if (field->get_type()->is_enum()) - { - string combined_message = field->get_doc() + endl + "get_type()) + "\"/>"; - generate_netcore_docstring_comment(out, combined_message); - } - else - { - generate_netcore_doc(out, static_cast(field)); - } -} - -void t_netcore_generator::generate_netcore_doc(ostream& out, t_doc* tdoc) -{ - if (tdoc->has_doc()) - { - generate_netcore_docstring_comment(out, tdoc->get_doc()); - } -} - -void t_netcore_generator::generate_netcore_doc(ostream& out, t_function* tfunction) -{ - if (tfunction->has_doc()) - { - stringstream ps; - const vector& fields = tfunction->get_arglist()->get_members(); - vector::const_iterator p_iter; - for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) - { - t_field* p = *p_iter; - ps << endl << "get_name() << "\">"; - if (p->has_doc()) - { - string str = p->get_doc(); - str.erase(remove(str.begin(), str.end(), '\n'), str.end()); - ps << str; - } - ps << ""; - } - - docstring_comment(out, - "", - "/// ", - "" + endl + tfunction->get_doc() + "" + ps.str(), - ""); - } -} - -void t_netcore_generator::docstring_comment(ostream& out, const string& comment_start, const string& line_prefix, const string& contents, const string& comment_end) -{ - if (comment_start != "") - { - out << indent() << comment_start; - } - - stringstream docs(contents, std::ios_base::in); - - while (!(docs.eof() || docs.fail())) - { - char line[1024]; - docs.getline(line, 1024); - - // Just prnt a newline when the line & prefix are empty. - if (strlen(line) == 0 && line_prefix == "" && !docs.eof()) - { - out << endl; - } - else if (strlen(line) > 0 || !docs.eof()) - { // skip the empty last line - out << indent() << line_prefix << line << endl; - } - } - if (comment_end != "") - { - out << indent() << comment_end; - } -} - -string t_netcore_generator::get_enum_class_name(t_type* type) -{ - string package = ""; - t_program* program = type->get_program(); - if (program != NULL && program != program_) - { - package = program->get_namespace("netcore") + "."; - } - return package + type->get_name(); -} - -THRIFT_REGISTER_GENERATOR( - netcore, - "C#", - " wcf: Adds bindings for WCF to generated classes.\n" - " serial: Add serialization support to generated classes.\n" - " nullable: Use nullable types for properties.\n" - " hashcode: Generate a hashcode and equals implementation for classes.\n" - " union: Use new union typing, which includes a static read function for union types.\n" -) diff --git a/compiler/cpp/src/thrift/generate/t_netcore_generator.h b/compiler/cpp/src/thrift/generate/t_netcore_generator.h deleted file mode 100644 index e98980a9eee..00000000000 --- a/compiler/cpp/src/thrift/generate/t_netcore_generator.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "thrift/platform.h" -#include "thrift/generate/t_oop_generator.h" - -using std::map; -using std::ostream; -using std::ostringstream; -using std::string; -using std::stringstream; -using std::vector; - -static const string endl = "\n"; // avoid ostream << std::endl flushes - -class t_netcore_generator : public t_oop_generator -{ - - struct member_mapping_scope - { - public: - member_mapping_scope() : scope_member(0) { } - void* scope_member; - map mapping_table; - }; - -public: - t_netcore_generator(t_program* program, const map& parsed_options, const string& option_string); - - bool is_wcf_enabled() const; - bool is_nullable_enabled() const; - bool is_hashcode_enabled() const; - bool is_serialize_enabled() const; - bool is_union_enabled() const; - map get_keywords_list() const; - - // overrides - void init_generator(); - void close_generator(); - void generate_consts(vector consts); - void generate_consts(ostream& out, vector consts); - void generate_typedef(t_typedef* ttypedef); - void generate_enum(t_enum* tenum); - void generate_enum(ostream& out, t_enum* tenum); - void generate_struct(t_struct* tstruct); - void generate_xception(t_struct* txception); - void generate_service(t_service* tservice); - - void generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset); - void generate_netcore_property(ostream& out, t_field* tfield, bool isPublic, bool includeIsset = true, string fieldPrefix = ""); - bool print_const_value(ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval = false, bool needtype = false); - string render_const_value(ostream& out, string name, t_type* type, t_const_value* value); - void print_const_constructor(ostream& out, vector consts); - void print_const_def_value(ostream& out, string name, t_type* type, t_const_value* value); - void generate_netcore_struct(t_struct* tstruct, bool is_exception); - void generate_netcore_union(t_struct* tunion); - void generate_netcore_struct_definition(ostream& out, t_struct* tstruct, bool is_xception = false, bool in_class = false, bool is_result = false); - void generate_netcore_union_definition(ostream& out, t_struct* tunion); - void generate_netcore_union_class(ostream& out, t_struct* tunion, t_field* tfield); - void generate_netcore_wcffault(ostream& out, t_struct* tstruct); - void generate_netcore_struct_reader(ostream& out, t_struct* tstruct); - void generate_netcore_struct_result_writer(ostream& out, t_struct* tstruct); - void generate_netcore_struct_writer(ostream& out, t_struct* tstruct); - void generate_netcore_struct_tostring(ostream& out, t_struct* tstruct); - void generate_netcore_struct_equals(ostream& out, t_struct* tstruct); - void generate_netcore_struct_hashcode(ostream& out, t_struct* tstruct); - void generate_netcore_union_reader(ostream& out, t_struct* tunion); - void generate_function_helpers(ostream& out, t_function* tfunction); - void generate_service_interface(ostream& out, t_service* tservice); - void generate_service_helpers(ostream& out, t_service* tservice); - void generate_service_client(ostream& out, t_service* tservice); - void generate_service_server(ostream& out, t_service* tservice); - void generate_process_function_async(ostream& out, t_service* tservice, t_function* function); - void generate_deserialize_field(ostream& out, t_field* tfield, string prefix = "", bool is_propertyless = false); - void generate_deserialize_struct(ostream& out, t_struct* tstruct, string prefix = ""); - void generate_deserialize_container(ostream& out, t_type* ttype, string prefix = ""); - void generate_deserialize_set_element(ostream& out, t_set* tset, string prefix = ""); - void generate_deserialize_map_element(ostream& out, t_map* tmap, string prefix = ""); - void generate_deserialize_list_element(ostream& out, t_list* list, string prefix = ""); - void generate_serialize_field(ostream& out, t_field* tfield, string prefix = "", bool is_element = false, bool is_propertyless = false); - void generate_serialize_struct(ostream& out, t_struct* tstruct, string prefix = ""); - void generate_serialize_container(ostream& out, t_type* ttype, string prefix = ""); - void generate_serialize_map_element(ostream& out, t_map* tmap, string iter, string map); - void generate_serialize_set_element(ostream& out, t_set* tmap, string iter); - void generate_serialize_list_element(ostream& out, t_list* tlist, string iter); - void generate_netcore_doc(ostream& out, t_field* field); - void generate_netcore_doc(ostream& out, t_doc* tdoc); - void generate_netcore_doc(ostream& out, t_function* tdoc); - void generate_netcore_docstring_comment(ostream& out, string contents); - void docstring_comment(ostream& out, const string& comment_start, const string& line_prefix, const string& contents, const string& comment_end); - void start_netcore_namespace(ostream& out); - void end_netcore_namespace(ostream& out); - - string netcore_type_usings() const; - string netcore_thrift_usings() const; - - string type_name(t_type* ttype, bool in_countainer = false, bool in_init = false, bool in_param = false, bool is_required = false); - string base_type_name(t_base_type* tbase, bool in_container = false, bool in_param = false, bool is_required = false); - string declare_field(t_field* tfield, bool init = false, string prefix = ""); - string function_signature_async(t_function* tfunction, string prefix = ""); - string function_signature(t_function* tfunction, string prefix = ""); - string argument_list(t_struct* tstruct); - string type_to_enum(t_type* ttype); - string prop_name(t_field* tfield, bool suppress_mapping = false); - string get_enum_class_name(t_type* type); - -private: - string namespace_name_; - string namespace_dir_; - - bool nullable_; - bool union_; - bool hashcode_; - bool serialize_; - bool wcf_; - - string wcf_namespace_; - map netcore_keywords; - vector member_mapping_scopes; - - void init_keywords(); - string normalize_name(string name); - string make_valid_csharp_identifier(string const& fromName); - void prepare_member_name_mapping(t_struct* tstruct); - void prepare_member_name_mapping(void* scope, const vector& members, const string& structname); - void cleanup_member_name_mapping(void* scope); - string get_mapped_member_name(string oldname); -}; diff --git a/compiler/cpp/src/thrift/parse/t_program.h b/compiler/cpp/src/thrift/parse/t_program.h index e0b4b6ecdc4..de68a0c1b93 100644 --- a/compiler/cpp/src/thrift/parse/t_program.h +++ b/compiler/cpp/src/thrift/parse/t_program.h @@ -291,10 +291,14 @@ class t_program : public t_doc { pwarning(1, "Namespace 'smalltalk' is deprecated. Use 'st' instead"); base_language = "st"; } - else if ((base_language == "csharp") || (base_language == "netcore")) { + else if (base_language == "csharp") { pwarning(1, "The '%s' target is deprecated. Consider moving to 'netstd' instead.", base_language.c_str()); // warn only, don't change base_language } + else if (base_language == "netcore") { + pwarning(1, "The '%s' target is no longer available. Use 'netstd' instead.", base_language.c_str()); + // warn only, don't change base_language + } t_generator_registry::gen_map_t my_copy = t_generator_registry::get_generator_map(); diff --git a/compiler/cpp/tests/CMakeLists.txt b/compiler/cpp/tests/CMakeLists.txt index 91cc35dbff1..7798c15f1ce 100644 --- a/compiler/cpp/tests/CMakeLists.txt +++ b/compiler/cpp/tests/CMakeLists.txt @@ -116,7 +116,7 @@ THRIFT_ADD_COMPILER(javame "Enable compiler for Java ME" OFF) THRIFT_ADD_COMPILER(js "Enable compiler for JavaScript" OFF) THRIFT_ADD_COMPILER(json "Enable compiler for JSON" OFF) THRIFT_ADD_COMPILER(lua "Enable compiler for Lua" OFF) -THRIFT_ADD_COMPILER(netcore "Enable compiler for .NET Core" ON) +THRIFT_ADD_COMPILER(netstd "Enable compiler for .NET Standard" ON) THRIFT_ADD_COMPILER(ocaml "Enable compiler for OCaml" OFF) THRIFT_ADD_COMPILER(perl "Enable compiler for Perl" OFF) THRIFT_ADD_COMPILER(php "Enable compiler for PHP" OFF) diff --git a/compiler/cpp/tests/README.md b/compiler/cpp/tests/README.md index 27be491cbcf..91c0625a340 100644 --- a/compiler/cpp/tests/README.md +++ b/compiler/cpp/tests/README.md @@ -16,7 +16,7 @@ ## General information -Added generic way to cover code by tests for many languages (you just need to make a correct header file for generator for your language - example in **netcore** implementation) +Added generic way to cover code by tests for many languages (you just need to make a correct header file for generator for your language - example in **netstd** implementation) At current moment these tests use free Catch library (https://github.com/catchorg/Catch2/tree/Catch1.x) for easy test creation and usage. Decision to use it was because of simplicity, easy usage, one header file to use, stable community and growing interest (https://cpp.libhunt.com/project/googletest-google/vs/catch?rel=cmp-cmp) @@ -29,7 +29,7 @@ Also, maybe, later it will be migrated to Catch2 (https://github.com/philsquared - Set **On** to call of **THRIFT_ADD_COMPILER** for your language ``` cmake -THRIFT_ADD_COMPILER(netcore "Enable compiler for .NET Core" ON) +THRIFT_ADD_COMPILER(netstd "Enable compiler for .NET Standard" ON) ``` - Create folder with name specified in list of languages in **CMakeLists.txt** diff --git a/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests.cc b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests.cc index 0b8c8378e4d..a2f0a502d93 100644 --- a/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests.cc +++ b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests.cc @@ -17,18 +17,18 @@ #include "../catch/catch.hpp" #include -#include -#include "t_netcore_generator_functional_tests_helpers.h" +#include +#include "t_netstd_generator_functional_tests_helpers.h" -TEST_CASE( "t_netcore_generator should generate valid enum", "[functional]" ) +TEST_CASE( "t_netstd_generator should generate valid enum", "[functional]" ) { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); std::pair pair = TestDataGenerator::get_test_enum_data(program); string expected_result = pair.first; @@ -53,15 +53,15 @@ TEST_CASE( "t_netcore_generator should generate valid enum", "[functional]" ) delete program; } -TEST_CASE("t_netcore_generator should generate valid void", "[functional]") +TEST_CASE("t_netstd_generator should generate valid void", "[functional]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); std::pair pair = TestDataGenerator::get_test_void_const_data(gen); string expected_result = pair.first; @@ -86,15 +86,15 @@ TEST_CASE("t_netcore_generator should generate valid void", "[functional]") delete program; } -TEST_CASE("t_netcore_generator should generate valid string with escaping keyword", "[functional]") +TEST_CASE("t_netstd_generator should generate valid string with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_string_const_data(gen); @@ -122,15 +122,15 @@ TEST_CASE("t_netcore_generator should generate valid string with escaping keywor delete program; } -TEST_CASE("t_netcore_generator should generate valid bool with escaping keyword", "[functional]") +TEST_CASE("t_netstd_generator should generate valid bool with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_bool_const_data(gen); @@ -158,15 +158,15 @@ TEST_CASE("t_netcore_generator should generate valid bool with escaping keyword" delete program; } -TEST_CASE("t_netcore_generator should generate valid sbyte (i8) with escaping keyword", "[functional]") +TEST_CASE("t_netstd_generator should generate valid sbyte (i8) with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_i8_const_data(gen); @@ -194,15 +194,15 @@ TEST_CASE("t_netcore_generator should generate valid sbyte (i8) with escaping ke delete program; } -TEST_CASE("t_netcore_generator should generate valid short (i16) with escaping keyword", "[functional]") +TEST_CASE("t_netstd_generator should generate valid short (i16) with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_i16_const_data(gen); @@ -230,15 +230,15 @@ TEST_CASE("t_netcore_generator should generate valid short (i16) with escaping k delete program; } -TEST_CASE("t_netcore_generator should generate valid integer (i32) with escaping keyword", "[functional]") +TEST_CASE("t_netstd_generator should generate valid integer (i32) with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_i32_const_data(gen); @@ -266,15 +266,15 @@ TEST_CASE("t_netcore_generator should generate valid integer (i32) with escaping delete program; } -TEST_CASE("t_netcore_generator should generate valid long (i64) with escaping keyword", "[functional]") +TEST_CASE("t_netstd_generator should generate valid long (i64) with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_i64_const_data(gen); @@ -302,15 +302,15 @@ TEST_CASE("t_netcore_generator should generate valid long (i64) with escaping ke delete program; } -TEST_CASE("t_netcore_generator should generate valid double with escaping keyword", "[functional]") +TEST_CASE("t_netstd_generator should generate valid double with escaping keyword", "[functional]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); std::pair pair = TestDataGenerator::get_test_double_const_data(gen); diff --git a/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.cc b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.cc index 92c170bb947..db4ce78ae1b 100644 --- a/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.cc +++ b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.cc @@ -17,8 +17,8 @@ #include #include "thrift/common.h" -#include -#include "t_netcore_generator_functional_tests_helpers.h" +#include +#include "t_netstd_generator_functional_tests_helpers.h" const string TestDataGenerator::DEFAULT_FILE_HEADER = "/**" "\n" " * Autogenerated by Thrift Compiler ()" "\n" @@ -52,7 +52,7 @@ std::pair TestDataGenerator::get_test_enum_data(t_program* prog return std::pair(expected_result, enum_); } -std::pair TestDataGenerator::get_test_void_const_data(t_netcore_generator* gen) +std::pair TestDataGenerator::get_test_void_const_data(t_netstd_generator* gen) { string expected_result = DEFAULT_FILE_HEADER; @@ -68,11 +68,11 @@ std::pair TestDataGenerator::get_test_void_const_data(t_netcor return std::pair(expected_result, const_); } -std::pair TestDataGenerator::get_test_string_const_data(t_netcore_generator* gen) +std::pair TestDataGenerator::get_test_string_const_data(t_netstd_generator* gen) { - string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() + + string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" - "public static class netcoreConstants\n" + "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" @@ -92,11 +92,11 @@ std::pair TestDataGenerator::get_test_string_const_data(t_netc return std::pair(expected_result, const_); } -std::pair TestDataGenerator::get_test_bool_const_data(t_netcore_generator* gen) +std::pair TestDataGenerator::get_test_bool_const_data(t_netstd_generator* gen) { - string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() + + string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" - "public static class netcoreConstants\n" + "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" @@ -116,11 +116,11 @@ std::pair TestDataGenerator::get_test_bool_const_data(t_netcor return std::pair(expected_result, const_); } -std::pair TestDataGenerator::get_test_i8_const_data(t_netcore_generator* gen) +std::pair TestDataGenerator::get_test_i8_const_data(t_netstd_generator* gen) { - string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() + + string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" - "public static class netcoreConstants\n" + "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" @@ -140,11 +140,11 @@ std::pair TestDataGenerator::get_test_i8_const_data(t_netcore_ return std::pair(expected_result, const_); } -std::pair TestDataGenerator::get_test_i16_const_data(t_netcore_generator* gen) +std::pair TestDataGenerator::get_test_i16_const_data(t_netstd_generator* gen) { - string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() + + string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" - "public static class netcoreConstants\n" + "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" @@ -164,11 +164,11 @@ std::pair TestDataGenerator::get_test_i16_const_data(t_netcore return std::pair(expected_result, const_); } -std::pair TestDataGenerator::get_test_i32_const_data(t_netcore_generator* gen) +std::pair TestDataGenerator::get_test_i32_const_data(t_netstd_generator* gen) { - string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() + + string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" - "public static class netcoreConstants\n" + "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" @@ -188,11 +188,11 @@ std::pair TestDataGenerator::get_test_i32_const_data(t_netcore return std::pair(expected_result, const_); } -std::pair TestDataGenerator::get_test_i64_const_data(t_netcore_generator* gen) +std::pair TestDataGenerator::get_test_i64_const_data(t_netstd_generator* gen) { - string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() + + string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" - "public static class netcoreConstants\n" + "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" @@ -212,11 +212,11 @@ std::pair TestDataGenerator::get_test_i64_const_data(t_netcore return std::pair(expected_result, const_); } -std::pair TestDataGenerator::get_test_double_const_data(t_netcore_generator* gen) +std::pair TestDataGenerator::get_test_double_const_data(t_netstd_generator* gen) { - string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netcore_type_usings() + + string expected_result = DEFAULT_FILE_HEADER + "\n" +gen->netstd_type_usings() + "\n" - "public static class netcoreConstants\n" + "public static class netstdConstants\n" "{\n" " /// \n" " /// TestDoc\n" diff --git a/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.h b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.h index c6eaac22cb8..982919799d7 100644 --- a/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.h +++ b/compiler/cpp/tests/netcore/t_netcore_generator_functional_tests_helpers.h @@ -23,12 +23,12 @@ class TestDataGenerator static const string DEFAULT_FILE_HEADER; static std::pair get_test_enum_data(t_program* program); - static std::pair get_test_void_const_data(t_netcore_generator* gen); - static std::pair get_test_string_const_data(t_netcore_generator* gen); - static std::pair get_test_bool_const_data(t_netcore_generator* gen); - static std::pair get_test_i8_const_data(t_netcore_generator* gen); - static std::pair get_test_i16_const_data(t_netcore_generator* gen); - static std::pair get_test_i32_const_data(t_netcore_generator* gen); - static std::pair get_test_i64_const_data(t_netcore_generator* gen); - static std::pair get_test_double_const_data(t_netcore_generator* gen); + static std::pair get_test_void_const_data(t_netstd_generator* gen); + static std::pair get_test_string_const_data(t_netstd_generator* gen); + static std::pair get_test_bool_const_data(t_netstd_generator* gen); + static std::pair get_test_i8_const_data(t_netstd_generator* gen); + static std::pair get_test_i16_const_data(t_netstd_generator* gen); + static std::pair get_test_i32_const_data(t_netstd_generator* gen); + static std::pair get_test_i64_const_data(t_netstd_generator* gen); + static std::pair get_test_double_const_data(t_netstd_generator* gen); }; diff --git a/compiler/cpp/tests/netcore/t_netcore_generator_helpers_tests.cc b/compiler/cpp/tests/netcore/t_netcore_generator_helpers_tests.cc index 0bcbeed197d..6acedc0f345 100644 --- a/compiler/cpp/tests/netcore/t_netcore_generator_helpers_tests.cc +++ b/compiler/cpp/tests/netcore/t_netcore_generator_helpers_tests.cc @@ -17,14 +17,14 @@ #include "../catch/catch.hpp" #include -#include +#include using std::vector; -TEST_CASE("t_netcore_generator::netcore_type_usings() without option wcf should return valid namespaces", "[helpers]") +TEST_CASE("t_netstd_generator::netstd_type_usings() without option wcf should return valid namespaces", "[helpers]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "union", "union" } }; string option_string = ""; @@ -39,19 +39,19 @@ TEST_CASE("t_netcore_generator::netcore_type_usings() without option wcf should "using Thrift.Collections;\n" + endl; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); REQUIRE_FALSE(gen->is_wcf_enabled()); - REQUIRE(gen->netcore_type_usings() == expected_namespaces); + REQUIRE(gen->netstd_type_usings() == expected_namespaces); delete gen; delete program; } -TEST_CASE("t_netcore_generator::netcore_type_usings() with option wcf should return valid namespaces", "[helpers]") +TEST_CASE("t_netstd_generator::netstd_type_usings() with option wcf should return valid namespaces", "[helpers]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; @@ -68,19 +68,19 @@ TEST_CASE("t_netcore_generator::netcore_type_usings() with option wcf should ret "using System.Runtime.Serialization;\n" + endl; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); REQUIRE(gen->is_wcf_enabled()); - REQUIRE(gen->netcore_type_usings() == expected_namespaces_wcf); + REQUIRE(gen->netstd_type_usings() == expected_namespaces_wcf); delete gen; delete program; } -TEST_CASE("t_netcore_generator should contains latest C# keywords to normalize with @", "[helpers]") +TEST_CASE("t_netstd_generator should contains latest C# keywords to normalize with @", "[helpers]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" } }; string option_string = ""; vector current_keywords = { @@ -190,7 +190,7 @@ TEST_CASE("t_netcore_generator should contains latest C# keywords to normalize w string missed_keywords = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); gen->init_generator(); map generators_keywords = gen->get_keywords_list(); diff --git a/compiler/cpp/tests/netcore/t_netcore_generator_initialization_tests.cc b/compiler/cpp/tests/netcore/t_netcore_generator_initialization_tests.cc index ec17733bd22..530e290ac60 100644 --- a/compiler/cpp/tests/netcore/t_netcore_generator_initialization_tests.cc +++ b/compiler/cpp/tests/netcore/t_netcore_generator_initialization_tests.cc @@ -17,35 +17,35 @@ #include "../catch/catch.hpp" #include -#include +#include -TEST_CASE( "t_netcore_generator should throw error with unknown options", "[initialization]" ) +TEST_CASE( "t_netstd_generator should throw error with unknown options", "[initialization]" ) { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "keys", "keys" } }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = nullptr; + t_netstd_generator* gen = nullptr; - REQUIRE_THROWS(gen = new t_netcore_generator(program, parsed_options, option_string)); + REQUIRE_THROWS(gen = new t_netstd_generator(program, parsed_options, option_string)); delete gen; delete program; } -TEST_CASE("t_netcore_generator should create valid instance with valid options", "[initialization]") +TEST_CASE("t_netstd_generator should create valid instance with valid options", "[initialization]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" }, { "nullable", "nullable"} }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = nullptr; + t_netstd_generator* gen = nullptr; - REQUIRE_NOTHROW(gen = new t_netcore_generator(program, parsed_options, option_string)); + REQUIRE_NOTHROW(gen = new t_netstd_generator(program, parsed_options, option_string)); REQUIRE(gen != nullptr); REQUIRE(gen->is_wcf_enabled()); REQUIRE(gen->is_nullable_enabled()); @@ -57,15 +57,15 @@ TEST_CASE("t_netcore_generator should create valid instance with valid options", delete program; } -TEST_CASE("t_netcore_generator should pass init succesfully", "[initialization]") +TEST_CASE("t_netstd_generator should pass init succesfully", "[initialization]") { string path = "CassandraTest.thrift"; - string name = "netcore"; + string name = "netstd"; map parsed_options = { { "wcf", "wcf" },{ "nullable", "nullable" } }; string option_string = ""; t_program* program = new t_program(path, name); - t_netcore_generator* gen = new t_netcore_generator(program, parsed_options, option_string); + t_netstd_generator* gen = new t_netstd_generator(program, parsed_options, option_string); REQUIRE_NOTHROW(gen->init_generator()); diff --git a/configure.ac b/configure.ac index ad26ef03fe6..d5d7ecbc968 100755 --- a/configure.ac +++ b/configure.ac @@ -127,7 +127,6 @@ if test "$enable_libs" = "no"; then with_ruby="no" with_haskell="no" with_haxe="no" - with_dotnetcore="no" with_netstd="no" with_perl="no" with_php="no" @@ -502,14 +501,14 @@ fi AM_CONDITIONAL(WITH_HAXE, [test "$have_haxe" = "yes"]) -AX_THRIFT_LIB(dotnetcore, [.NET Core], yes) -if test "$with_dotnetcore" = "yes"; then +AX_THRIFT_LIB(netstd, [.NET Core], yes) +if test "$with_netstd" = "yes"; then AC_PATH_PROG([DOTNETCORE], [dotnet]) if [[ -x "$DOTNETCORE" ]] ; then - AX_PROG_DOTNETCORE_VERSION( [2.0.0], have_dotnetcore="yes", have_dotnetcore="no") + AX_PROG_DOTNETCORE_VERSION( [2.0.0], have_netstd="yes", have_netstd="no") fi fi -AM_CONDITIONAL(WITH_DOTNET, [test "$have_dotnetcore" = "yes"]) +AM_CONDITIONAL(WITH_DOTNET, [test "$have_netstd" = "yes"]) AX_THRIFT_LIB(d, [D], yes) @@ -817,7 +816,6 @@ AC_CONFIG_FILES([ lib/js/test/Makefile lib/json/Makefile lib/json/test/Makefile - lib/netcore/Makefile lib/netstd/Makefile lib/nodejs/Makefile lib/nodets/Makefile @@ -846,7 +844,6 @@ AC_CONFIG_FILES([ test/haxe/Makefile test/hs/Makefile test/lua/Makefile - test/netcore/Makefile test/netstd/Makefile test/php/Makefile test/dart/Makefile @@ -866,7 +863,6 @@ AC_CONFIG_FILES([ tutorial/hs/Makefile tutorial/java/Makefile tutorial/js/Makefile - tutorial/netcore/Makefile tutorial/netstd/Makefile tutorial/nodejs/Makefile tutorial/dart/Makefile @@ -919,8 +915,8 @@ if test "$have_rs" = "yes" ; then MAYBE_RS="rs" ; else MAYBE_RS="" ; fi AC_SUBST([MAYBE_RS]) if test "$have_swift" = "yes" ; then MAYBE_SWIFT="swift" ; else MAYBE_SWIFT="" ; fi AC_SUBST([MAYBE_SWIFT]) -if test "$have_dotnetcore" = "yes" ; then MAYBE_DOTNETCORE="netcore" ; else MAYBE_DOTNETCORE="" ; fi -AC_SUBST([MAYBE_DOTNETCORE]) +if test "$have_netstd" = "yes" ; then MAYBE_NETSTD="netstd" ; else MAYBE_NETSTD="" ; fi +AC_SUBST([MAYBE_NETSTD]) if test "$have_cl" = "yes" ; then MAYBE_CL="cl" ; else MAYBE_CL="" ; fi AC_SUBST([MAYBE_CL]) @@ -937,8 +933,7 @@ echo "Building C++ Library ......... : $have_cpp" echo "Building Common Lisp Library.. : $have_cl" echo "Building D Library ........... : $have_d" echo "Building Dart Library ........ : $have_dart" -echo "Building dotnetcore Library .. : $have_dotnetcore" -echo "Building .NET Standard Library : $have_dotnetcore" +echo "Building .NET Standard Library : $have_netstd" echo "Building Erlang Library ...... : $have_erlang" echo "Building Go Library .......... : $have_go" echo "Building Haskell Library ..... : $have_haskell" @@ -1001,13 +996,7 @@ if test "$have_dart" = "yes" ; then echo " Using Pub ................. : $DARTPUB" echo " Using Dart version ........ : $($DART --version 2>&1)" fi -if test "$have_dotnetcore" = "yes" ; then - echo - echo ".NET Core Library:" - echo " Using .NET Core ........... : $DOTNETCORE" - echo " Using .NET Core version ... : $DOTNETCORE_VERSION" -fi -if test "$have_dotnetcore" = "yes" ; then +if test "$have_netstd" = "yes" ; then echo echo ".NET Standard Library:" echo " Using dotnet .............. : $DOTNETCORE" diff --git a/contrib/fb303/if/fb303.thrift b/contrib/fb303/if/fb303.thrift index 89bd6eb7b41..f1ca982b8bc 100644 --- a/contrib/fb303/if/fb303.thrift +++ b/contrib/fb303/if/fb303.thrift @@ -24,7 +24,7 @@ namespace java com.facebook.fb303 namespace cpp facebook.fb303 namespace perl Facebook.FB303 -namespace netcore Facebook.FB303.Test +namespace netstd Facebook.FB303.Test /** * Common status reporting mechanism across all services diff --git a/lib/Makefile.am b/lib/Makefile.am index 73326a56d85..51a2af01df5 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -73,7 +73,6 @@ SUBDIRS += dart endif if WITH_DOTNET -SUBDIRS += netcore SUBDIRS += netstd endif diff --git a/lib/cpp/test/OneWayTest.thrift b/lib/cpp/test/OneWayTest.thrift index 102cf26e5a6..1e9894cd992 100644 --- a/lib/cpp/test/OneWayTest.thrift +++ b/lib/cpp/test/OneWayTest.thrift @@ -36,7 +36,6 @@ namespace php OneWayTest namespace delphi Onewaytest namespace lua OneWayTest namespace xsd test (uri = 'http://thrift.apache.org/ns/OneWayTest') -namespace netcore ThriftAsync.OneWayTest // a minimal Thrift service, for use in OneWayHTTPTtest.cpp service OneWayService { diff --git a/lib/netcore/Makefile.am b/lib/netcore/Makefile.am deleted file mode 100644 index 4e2d6a5972c..00000000000 --- a/lib/netcore/Makefile.am +++ /dev/null @@ -1,58 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -all-local: - $(DOTNETCORE) build - -check-local: - $(DOTNETCORE) test Tests/Thrift.Tests/Thrift.Tests.csproj - $(DOTNETCORE) test Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj - -clean-local: - $(RM) -r Thrift/bin - $(RM) -r Thrift/obj - $(RM) -r Tests/Thrift.Tests/bin - $(RM) -r Tests/Thrift.Tests/obj - $(RM) -r Tests/Thrift.IntegrationTests/bin - $(RM) -r Tests/Thrift.IntegrationTests/obj - $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/bin - $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/obj - -dist-hook: - $(RM) -r $(distdir)/Thrift/bin - $(RM) -r $(distdir)/Thrift/obj - $(RM) -r $(distdir)/Tests/Thrift.Tests/bin - $(RM) -r $(distdir)/Tests/Thrift.Tests/obj - $(RM) -r $(distdir)/Tests/Thrift.IntegrationTests/bin - $(RM) -r $(distdir)/Tests/Thrift.IntegrationTests/obj - $(RM) -r $(distdir)/Tests/Thrift.PublicInterfaces.Compile.Tests/bin - $(RM) -r $(distdir)/Tests/Thrift.PublicInterfaces.Compile.Tests/obj - -DISTCLEANFILES = \ - Makefile.in - -EXTRA_DIST = \ - README.md \ - Tests \ - Thrift \ - Thrift.sln \ - build.cmd \ - build.sh \ - runtests.cmd \ - runtests.sh diff --git a/lib/netcore/README.md b/lib/netcore/README.md deleted file mode 100644 index bcd25b92728..00000000000 --- a/lib/netcore/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Apache Thrift netcore - -Thrift client library ported to Microsoft .Net Core - -# Deprecation notice - -Per [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723), both CSharp and Netcore targets are deprecated -and will be removed with the next release. Migrate to the [NetStd language target](../netstd/README.md) instead. - -# Content -- Tests/Thrift.PublicInterfaces.Compile.Tests - project for checking public interfaces during adding changes to Thrift library -- Thrift - Thrift library - -# Reused components -- .NET Standard 1.6 (SDK 2.0.0) - -# How to build on Windows -- Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable -- Open the Thrift.sln project with Visual Studio and build. -or -- Build with scripts - -# How to build on Unix -- Ensure you have .NET Core 2.0.0 SDK installed or use the Ubuntu Xenial docker image -- Follow common build practice for Thrift: bootstrap, configure, and make - -# Known issues -- In trace logging mode you can see some not important internal exceptions - diff --git a/lib/netcore/Tests/Thrift.IntegrationTests/.gitignore b/lib/netcore/Tests/Thrift.IntegrationTests/.gitignore deleted file mode 100644 index 7254c313a61..00000000000 --- a/lib/netcore/Tests/Thrift.IntegrationTests/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# ignore for autogenerated files -/Apache diff --git a/lib/netcore/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs b/lib/netcore/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs deleted file mode 100644 index bc4afa156c7..00000000000 --- a/lib/netcore/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs +++ /dev/null @@ -1,502 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.IO; -using System.Text; -using System.Threading.Tasks; -using KellermanSoftware.CompareNetObjects; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Thrift.Protocols; -using Thrift.Protocols.Entities; -using Thrift.Transports.Client; - -namespace Thrift.IntegrationTests.Protocols -{ - [TestClass] - public class ProtocolsOperationsTests - { - private readonly CompareLogic _compareLogic = new CompareLogic(); - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol), TMessageType.Call)] - [DataRow(typeof(TBinaryProtocol), TMessageType.Exception)] - [DataRow(typeof(TBinaryProtocol), TMessageType.Oneway)] - [DataRow(typeof(TBinaryProtocol), TMessageType.Reply)] - [DataRow(typeof(TCompactProtocol), TMessageType.Call)] - [DataRow(typeof(TCompactProtocol), TMessageType.Exception)] - [DataRow(typeof(TCompactProtocol), TMessageType.Oneway)] - [DataRow(typeof(TCompactProtocol), TMessageType.Reply)] - [DataRow(typeof(TJsonProtocol), TMessageType.Call)] - [DataRow(typeof(TJsonProtocol), TMessageType.Exception)] - [DataRow(typeof(TJsonProtocol), TMessageType.Oneway)] - [DataRow(typeof(TJsonProtocol), TMessageType.Reply)] - public async Task WriteReadMessage_Test(Type protocolType, TMessageType messageType) - { - var expected = new TMessage(nameof(TMessage), messageType, 1); - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteMessageBeginAsync(expected); - await protocol.WriteMessageEndAsync(); - - stream.Seek(0, SeekOrigin.Begin); - - var actualMessage = await protocol.ReadMessageBeginAsync(); - await protocol.ReadMessageEndAsync(); - - var result = _compareLogic.Compare(expected, actualMessage); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - [ExpectedException(typeof(Exception))] - public async Task WriteReadStruct_Test(Type protocolType) - { - var expected = new TStruct(nameof(TStruct)); - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteStructBeginAsync(expected); - await protocol.WriteStructEndAsync(); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadStructBeginAsync(); - await protocol.ReadStructEndAsync(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - [ExpectedException(typeof(Exception))] - public async Task WriteReadField_Test(Type protocolType) - { - var expected = new TField(nameof(TField), TType.String, 1); - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteFieldBeginAsync(expected); - await protocol.WriteFieldEndAsync(); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadFieldBeginAsync(); - await protocol.ReadFieldEndAsync(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - public async Task WriteReadMap_Test(Type protocolType) - { - var expected = new TMap(TType.String, TType.String, 1); - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteMapBeginAsync(expected); - await protocol.WriteMapEndAsync(); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadMapBeginAsync(); - await protocol.ReadMapEndAsync(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - public async Task WriteReadList_Test(Type protocolType) - { - var expected = new TList(TType.String, 1); - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteListBeginAsync(expected); - await protocol.WriteListEndAsync(); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadListBeginAsync(); - await protocol.ReadListEndAsync(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - public async Task WriteReadSet_Test(Type protocolType) - { - var expected = new TSet(TType.String, 1); - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteSetBeginAsync(expected); - await protocol.WriteSetEndAsync(); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadSetBeginAsync(); - await protocol.ReadSetEndAsync(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - public async Task WriteReadBool_Test(Type protocolType) - { - var expected = true; - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteBoolAsync(expected); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadBoolAsync(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - public async Task WriteReadByte_Test(Type protocolType) - { - var expected = sbyte.MaxValue; - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteByteAsync(expected); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadByteAsync(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - public async Task WriteReadI16_Test(Type protocolType) - { - var expected = short.MaxValue; - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteI16Async(expected); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadI16Async(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - public async Task WriteReadI32_Test(Type protocolType) - { - var expected = int.MaxValue; - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteI32Async(expected); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadI32Async(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - public async Task WriteReadI64_Test(Type protocolType) - { - var expected = long.MaxValue; - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteI64Async(expected); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadI64Async(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - public async Task WriteReadDouble_Test(Type protocolType) - { - var expected = double.MaxValue; - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteDoubleAsync(expected); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadDoubleAsync(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - public async Task WriteReadString_Test(Type protocolType) - { - var expected = nameof(String); - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteStringAsync(expected); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadStringAsync(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - [DataTestMethod] - [DataRow(typeof(TBinaryProtocol))] - [DataRow(typeof(TCompactProtocol))] - [DataRow(typeof(TJsonProtocol))] - public async Task WriteReadBinary_Test(Type protocolType) - { - var expected = Encoding.UTF8.GetBytes(nameof(String)); - - try - { - var tuple = GetProtocolInstance(protocolType); - using (var stream = tuple.Item1) - { - var protocol = tuple.Item2; - - await protocol.WriteBinaryAsync(expected); - - stream?.Seek(0, SeekOrigin.Begin); - - var actual = await protocol.ReadBinaryAsync(); - - var result = _compareLogic.Compare(expected, actual); - Assert.IsTrue(result.AreEqual, result.DifferencesString); - } - } - catch (Exception e) - { - throw new Exception($"Exception during testing of protocol: {protocolType.FullName}", e); - } - } - - private static Tuple GetProtocolInstance(Type protocolType) - { - var memoryStream = new MemoryStream(); - var streamClientTransport = new TStreamClientTransport(memoryStream, memoryStream); - var protocol = (TProtocol) Activator.CreateInstance(protocolType, streamClientTransport); - return new Tuple(memoryStream, protocol); - } - } -} diff --git a/lib/netcore/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj b/lib/netcore/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj deleted file mode 100644 index f25dac536fd..00000000000 --- a/lib/netcore/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj +++ /dev/null @@ -1,29 +0,0 @@ - - - netcoreapp2.0 - Thrift.IntegrationTests - Thrift.IntegrationTests - Exe - false - false - false - false - false - false - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/.gitignore b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/.gitignore deleted file mode 100644 index ae929a32e42..00000000000 --- a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# ignore for autogenerated files -/ThriftTest -/Apache -/Facebook diff --git a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift deleted file mode 100644 index 4b92720c2d4..00000000000 --- a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift +++ /dev/null @@ -1,705 +0,0 @@ -#!/usr/local/bin/thrift --java --php --py -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# *** PLEASE REMEMBER TO EDIT THE VERSION CONSTANT WHEN MAKING CHANGES *** -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -# -# Interface definition for Cassandra Service -# - -namespace netcore Apache.Cassandra.Test - -# Thrift.rb has a bug where top-level modules that include modules -# with the same name are not properly referenced, so we can't do -# Cassandra::Cassandra::Client. -namespace rb CassandraThrift - -# The API version (NOT the product version), composed as a dot delimited -# string with major, minor, and patch level components. -# -# - Major: Incremented for backward incompatible changes. An example would -# be changes to the number or disposition of method arguments. -# - Minor: Incremented for backward compatible changes. An example would -# be the addition of a new (optional) method. -# - Patch: Incremented for bug fixes. The patch level should be increased -# for every edit that doesn't result in a change to major/minor. -# -# See the Semantic Versioning Specification (SemVer) http://semver.org. -const string VERSION = "19.24.0" - - -# -# data structures -# - -/** Basic unit of data within a ColumnFamily. - * @param name, the name by which this column is set and retrieved. Maximum 64KB long. - * @param value. The data associated with the name. Maximum 2GB long, but in practice you should limit it to small numbers of MB (since Thrift must read the full value into memory to operate on it). - * @param timestamp. The timestamp is used for conflict detection/resolution when two columns with same name need to be compared. - * @param ttl. An optional, positive delay (in seconds) after which the column will be automatically deleted. - */ -struct Column { - 1: required binary name, - 2: optional binary value, - 3: optional i64 timestamp, - 4: optional i32 ttl, -} - -/** A named list of columns. - * @param name. see Column.name. - * @param columns. A collection of standard Columns. The columns within a super column are defined in an adhoc manner. - * Columns within a super column do not have to have matching structures (similarly named child columns). - */ -struct SuperColumn { - 1: required binary name, - 2: required list columns, -} - -struct CounterColumn { - 1: required binary name, - 2: required i64 value -} - -struct CounterSuperColumn { - 1: required binary name, - 2: required list columns -} - -/** - Methods for fetching rows/records from Cassandra will return either a single instance of ColumnOrSuperColumn or a list - of ColumnOrSuperColumns (get_slice()). If you're looking up a SuperColumn (or list of SuperColumns) then the resulting - instances of ColumnOrSuperColumn will have the requested SuperColumn in the attribute super_column. For queries resulting - in Columns, those values will be in the attribute column. This change was made between 0.3 and 0.4 to standardize on - single query methods that may return either a SuperColumn or Column. - - If the query was on a counter column family, you will either get a counter_column (instead of a column) or a - counter_super_column (instead of a super_column) - - @param column. The Column returned by get() or get_slice(). - @param super_column. The SuperColumn returned by get() or get_slice(). - @param counter_column. The Counterolumn returned by get() or get_slice(). - @param counter_super_column. The CounterSuperColumn returned by get() or get_slice(). - */ -struct ColumnOrSuperColumn { - 1: optional Column column, - 2: optional SuperColumn super_column, - 3: optional CounterColumn counter_column, - 4: optional CounterSuperColumn counter_super_column -} - - -# -# Exceptions -# (note that internal server errors will raise a TApplicationException, courtesy of Thrift) -# - -/** A specific column was requested that does not exist. */ -exception NotFoundException { -} - -/** Invalid request could mean keyspace or column family does not exist, required parameters are missing, or a parameter is malformed. - why contains an associated error message. -*/ -exception InvalidRequestException { - 1: required string why -} - -/** Not all the replicas required could be created and/or read. */ -exception UnavailableException { -} - -/** RPC timeout was exceeded. either a node failed mid-operation, or load was too high, or the requested op was too large. */ -exception TimedOutException { -} - -/** invalid authentication request (invalid keyspace, user does not exist, or credentials invalid) */ -exception AuthenticationException { - 1: required string why -} - -/** invalid authorization request (user does not have access to keyspace) */ -exception AuthorizationException { - 1: required string why -} - -/** schemas are not in agreement across all nodes */ -exception SchemaDisagreementException { -} - - -# -# service api -# -/** - * The ConsistencyLevel is an enum that controls both read and write - * behavior based on the ReplicationFactor of the keyspace. The - * different consistency levels have different meanings, depending on - * if you're doing a write or read operation. - * - * If W + R > ReplicationFactor, where W is the number of nodes to - * block for on write, and R the number to block for on reads, you - * will have strongly consistent behavior; that is, readers will - * always see the most recent write. Of these, the most interesting is - * to do QUORUM reads and writes, which gives you consistency while - * still allowing availability in the face of node failures up to half - * of . Of course if latency is more important than - * consistency then you can use lower values for either or both. - * - * Some ConsistencyLevels (ONE, TWO, THREE) refer to a specific number - * of replicas rather than a logical concept that adjusts - * automatically with the replication factor. Of these, only ONE is - * commonly used; TWO and (even more rarely) THREE are only useful - * when you care more about guaranteeing a certain level of - * durability, than consistency. - * - * Write consistency levels make the following guarantees before reporting success to the client: - * ANY Ensure that the write has been written once somewhere, including possibly being hinted in a non-target node. - * ONE Ensure that the write has been written to at least 1 node's commit log and memory table - * TWO Ensure that the write has been written to at least 2 node's commit log and memory table - * THREE Ensure that the write has been written to at least 3 node's commit log and memory table - * QUORUM Ensure that the write has been written to / 2 + 1 nodes - * LOCAL_QUORUM Ensure that the write has been written to / 2 + 1 nodes, within the local datacenter (requires NetworkTopologyStrategy) - * EACH_QUORUM Ensure that the write has been written to / 2 + 1 nodes in each datacenter (requires NetworkTopologyStrategy) - * ALL Ensure that the write is written to <ReplicationFactor> nodes before responding to the client. - * - * Read consistency levels make the following guarantees before returning successful results to the client: - * ANY Not supported. You probably want ONE instead. - * ONE Returns the record obtained from a single replica. - * TWO Returns the record with the most recent timestamp once two replicas have replied. - * THREE Returns the record with the most recent timestamp once three replicas have replied. - * QUORUM Returns the record with the most recent timestamp once a majority of replicas have replied. - * LOCAL_QUORUM Returns the record with the most recent timestamp once a majority of replicas within the local datacenter have replied. - * EACH_QUORUM Returns the record with the most recent timestamp once a majority of replicas within each datacenter have replied. - * ALL Returns the record with the most recent timestamp once all replicas have replied (implies no replica may be down).. -*/ -enum ConsistencyLevel { - ONE = 1, - QUORUM = 2, - LOCAL_QUORUM = 3, - EACH_QUORUM = 4, - ALL = 5, - ANY = 6, - TWO = 7, - THREE = 8, -} - -/** - ColumnParent is used when selecting groups of columns from the same ColumnFamily. In directory structure terms, imagine - ColumnParent as ColumnPath + '/../'. - - See also ColumnPath - */ -struct ColumnParent { - 3: required string column_family, - 4: optional binary super_column, -} - -/** The ColumnPath is the path to a single column in Cassandra. It might make sense to think of ColumnPath and - * ColumnParent in terms of a directory structure. - * - * ColumnPath is used to looking up a single column. - * - * @param column_family. The name of the CF of the column being looked up. - * @param super_column. The super column name. - * @param column. The column name. - */ -struct ColumnPath { - 3: required string column_family, - 4: optional binary super_column, - 5: optional binary column, -} - -/** - A slice range is a structure that stores basic range, ordering and limit information for a query that will return - multiple columns. It could be thought of as Cassandra's version of LIMIT and ORDER BY - - @param start. The column name to start the slice with. This attribute is not required, though there is no default value, - and can be safely set to '', i.e., an empty byte array, to start with the first column name. Otherwise, it - must a valid value under the rules of the Comparator defined for the given ColumnFamily. - @param finish. The column name to stop the slice at. This attribute is not required, though there is no default value, - and can be safely set to an empty byte array to not stop until 'count' results are seen. Otherwise, it - must also be a valid value to the ColumnFamily Comparator. - @param reversed. Whether the results should be ordered in reversed order. Similar to ORDER BY blah DESC in SQL. - @param count. How many columns to return. Similar to LIMIT in SQL. May be arbitrarily large, but Thrift will - materialize the whole result into memory before returning it to the client, so be aware that you may - be better served by iterating through slices by passing the last value of one call in as the 'start' - of the next instead of increasing 'count' arbitrarily large. - */ -struct SliceRange { - 1: required binary start, - 2: required binary finish, - 3: required bool reversed=0, - 4: required i32 count=100, -} - -/** - A SlicePredicate is similar to a mathematic predicate (see http://en.wikipedia.org/wiki/Predicate_(mathematical_logic)), - which is described as "a property that the elements of a set have in common." - - SlicePredicate's in Cassandra are described with either a list of column_names or a SliceRange. If column_names is - specified, slice_range is ignored. - - @param column_name. A list of column names to retrieve. This can be used similar to Memcached's "multi-get" feature - to fetch N known column names. For instance, if you know you wish to fetch columns 'Joe', 'Jack', - and 'Jim' you can pass those column names as a list to fetch all three at once. - @param slice_range. A SliceRange describing how to range, order, and/or limit the slice. - */ -struct SlicePredicate { - 1: optional list column_names, - 2: optional SliceRange slice_range, -} - -enum IndexOperator { - EQ, - GTE, - GT, - LTE, - LT -} - -struct IndexExpression { - 1: required binary column_name, - 2: required IndexOperator op, - 3: required binary value, -} - -struct IndexClause { - 1: required list expressions - 2: required binary start_key, - 3: required i32 count=100, -} - -/** -The semantics of start keys and tokens are slightly different. -Keys are start-inclusive; tokens are start-exclusive. Token -ranges may also wrap -- that is, the end token may be less -than the start one. Thus, a range from keyX to keyX is a -one-element range, but a range from tokenY to tokenY is the -full ring. -*/ -struct KeyRange { - 1: optional binary start_key, - 2: optional binary end_key, - 3: optional string start_token, - 4: optional string end_token, - 5: required i32 count=100 -} - -/** - A KeySlice is key followed by the data it maps to. A collection of KeySlice is returned by the get_range_slice operation. - - @param key. a row key - @param columns. List of data represented by the key. Typically, the list is pared down to only the columns specified by - a SlicePredicate. - */ -struct KeySlice { - 1: required binary key, - 2: required list columns, -} - -struct KeyCount { - 1: required binary key, - 2: required i32 count -} - -/** - * Note that the timestamp is only optional in case of counter deletion. - */ -struct Deletion { - 1: optional i64 timestamp, - 2: optional binary super_column, - 3: optional SlicePredicate predicate, -} - -/** - A Mutation is either an insert (represented by filling column_or_supercolumn) or a deletion (represented by filling the deletion attribute). - @param column_or_supercolumn. An insert to a column or supercolumn (possibly counter column or supercolumn) - @param deletion. A deletion of a column or supercolumn -*/ -struct Mutation { - 1: optional ColumnOrSuperColumn column_or_supercolumn, - 2: optional Deletion deletion, -} - -struct EndpointDetails { - 1: string host, - 2: string datacenter, - 3: optional string rack -} - -/** - A TokenRange describes part of the Cassandra ring, it is a mapping from a range to - endpoints responsible for that range. - @param start_token The first token in the range - @param end_token The last token in the range - @param endpoints The endpoints responsible for the range (listed by their configured listen_address) - @param rpc_endpoints The endpoints responsible for the range (listed by their configured rpc_address) -*/ -struct TokenRange { - 1: required string start_token, - 2: required string end_token, - 3: required list endpoints, - 4: optional list rpc_endpoints - 5: optional list endpoint_details, -} - -/** - Authentication requests can contain any data, dependent on the IAuthenticator used -*/ -struct AuthenticationRequest { - 1: required map credentials -} - -enum IndexType { - KEYS, - CUSTOM -} - -/* describes a column in a column family. */ -struct ColumnDef { - 1: required binary name, - 2: required string validation_class, - 3: optional IndexType index_type, - 4: optional string index_name, - 5: optional map index_options -} - - -/* describes a column family. */ -struct CfDef { - 1: required string keyspace, - 2: required string name, - 3: optional string column_type="Standard", - 5: optional string comparator_type="BytesType", - 6: optional string subcomparator_type, - 8: optional string comment, - 12: optional double read_repair_chance=1.0, - 13: optional list column_metadata, - 14: optional i32 gc_grace_seconds, - 15: optional string default_validation_class, - 16: optional i32 id, - 17: optional i32 min_compaction_threshold, - 18: optional i32 max_compaction_threshold, - 24: optional bool replicate_on_write, - 25: optional double merge_shards_chance, - 26: optional string key_validation_class, - 28: optional binary key_alias, - 29: optional string compaction_strategy, - 30: optional map compaction_strategy_options, - 32: optional map compression_options, - 33: optional double bloom_filter_fp_chance, -} - -/* describes a keyspace. */ -struct KsDef { - 1: required string name, - 2: required string strategy_class, - 3: optional map strategy_options, - - /** @deprecated */ - 4: optional i32 replication_factor, - - 5: required list cf_defs, - 6: optional bool durable_writes=1, -} - -/** CQL query compression */ -enum Compression { - GZIP = 1, - NONE = 2 -} - -enum CqlResultType { - ROWS = 1, - VOID = 2, - INT = 3 -} - -/** Row returned from a CQL query */ -struct CqlRow { - 1: required binary key, - 2: required list columns -} - -struct CqlMetadata { - 1: required map name_types, - 2: required map value_types, - 3: required string default_name_type, - 4: required string default_value_type -} - -struct CqlResult { - 1: required CqlResultType type, - 2: optional list rows, - 3: optional i32 num, - 4: optional CqlMetadata schema -} - -struct CqlPreparedResult { - 1: required i32 itemId, - 2: required i32 count -} - - -service Cassandra { - # auth methods - void login(1: required AuthenticationRequest auth_request) throws (1:AuthenticationException authnx, 2:AuthorizationException authzx), - - # set keyspace - void set_keyspace(1: required string keyspace) throws (1:InvalidRequestException ire), - - # retrieval methods - - /** - Get the Column or SuperColumn at the given column_path. If no value is present, NotFoundException is thrown. (This is - the only method that can throw an exception under non-failure conditions.) - */ - ColumnOrSuperColumn get(1:required binary key, - 2:required ColumnPath column_path, - 3:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:NotFoundException nfe, 3:UnavailableException ue, 4:TimedOutException te), - - /** - Get the group of columns contained by column_parent (either a ColumnFamily name or a ColumnFamily/SuperColumn name - pair) specified by the given SlicePredicate. If no matching values are found, an empty list is returned. - */ - list get_slice(1:required binary key, - 2:required ColumnParent column_parent, - 3:required SlicePredicate predicate, - 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), - - /** - returns the number of columns matching predicate for a particular key, - ColumnFamily and optionally SuperColumn. - */ - i32 get_count(1:required binary key, - 2:required ColumnParent column_parent, - 3:required SlicePredicate predicate, - 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), - - /** - Performs a get_slice for column_parent and predicate for the given keys in parallel. - */ - map> multiget_slice(1:required list keys, - 2:required ColumnParent column_parent, - 3:required SlicePredicate predicate, - 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), - - /** - Perform a get_count in parallel on the given list keys. The return value maps keys to the count found. - */ - map multiget_count(1:required list keys, - 2:required ColumnParent column_parent, - 3:required SlicePredicate predicate, - 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), - - /** - returns a subset of columns for a contiguous range of keys. - */ - list get_range_slices(1:required ColumnParent column_parent, - 2:required SlicePredicate predicate, - 3:required KeyRange range, - 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), - - /** Returns the subset of columns specified in SlicePredicate for the rows matching the IndexClause */ - list get_indexed_slices(1:required ColumnParent column_parent, - 2:required IndexClause index_clause, - 3:required SlicePredicate column_predicate, - 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), - - # modification methods - - /** - * Insert a Column at the given column_parent.column_family and optional column_parent.super_column. - */ - void insert(1:required binary key, - 2:required ColumnParent column_parent, - 3:required Column column, - 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), - - /** - * Increment or decrement a counter. - */ - void add(1:required binary key, - 2:required ColumnParent column_parent, - 3:required CounterColumn column, - 4:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), - - /** - Remove data from the row specified by key at the granularity specified by column_path, and the given timestamp. Note - that all the values in column_path besides column_path.column_family are truly optional: you can remove the entire - row by just specifying the ColumnFamily, or you can remove a SuperColumn or a single Column by specifying those levels too. - */ - void remove(1:required binary key, - 2:required ColumnPath column_path, - 3:required i64 timestamp, - 4:ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), - - /** - * Remove a counter at the specified location. - * Note that counters have limited support for deletes: if you remove a counter, you must wait to issue any following update - * until the delete has reached all the nodes and all of them have been fully compacted. - */ - void remove_counter(1:required binary key, - 2:required ColumnPath path, - 3:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), - - - /** - Mutate many columns or super columns for many row keys. See also: Mutation. - - mutation_map maps key to column family to a list of Mutation objects to take place at that scope. - **/ - void batch_mutate(1:required map>> mutation_map, - 2:required ConsistencyLevel consistency_level=ConsistencyLevel.ONE) - throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te), - - /** - Truncate will mark and entire column family as deleted. - From the user's perspective a successful call to truncate will result complete data deletion from cfname. - Internally, however, disk space will not be immediatily released, as with all deletes in cassandra, this one - only marks the data as deleted. - The operation succeeds only if all hosts in the cluster at available and will throw an UnavailableException if - some hosts are down. - */ - void truncate(1:required string cfname) - throws (1: InvalidRequestException ire, 2: UnavailableException ue, 3: TimedOutException te), - - - - // Meta-APIs -- APIs to get information about the node or cluster, - // rather than user data. The nodeprobe program provides usage examples. - - /** - * for each schema version present in the cluster, returns a list of nodes at that version. - * hosts that do not respond will be under the key DatabaseDescriptor.INITIAL_VERSION. - * the cluster is all on the same version if the size of the map is 1. - */ - map> describe_schema_versions() - throws (1: InvalidRequestException ire), - - /** list the defined keyspaces in this cluster */ - list describe_keyspaces() - throws (1:InvalidRequestException ire), - - /** get the cluster name */ - string describe_cluster_name(), - - /** get the thrift api version */ - string describe_version(), - - /** get the token ring: a map of ranges to host addresses, - represented as a set of TokenRange instead of a map from range - to list of endpoints, because you can't use Thrift structs as - map keys: - https://issues.apache.org/jira/browse/THRIFT-162 - - for the same reason, we can't return a set here, even though - order is neither important nor predictable. */ - list describe_ring(1:required string keyspace) - throws (1:InvalidRequestException ire), - - /** returns the partitioner used by this cluster */ - string describe_partitioner(), - - /** returns the snitch used by this cluster */ - string describe_snitch(), - - /** describe specified keyspace */ - KsDef describe_keyspace(1:required string keyspace) - throws (1:NotFoundException nfe, 2:InvalidRequestException ire), - - /** experimental API for hadoop/parallel query support. - may change violently and without warning. - - returns list of token strings such that first subrange is (list[0], list[1]], - next is (list[1], list[2]], etc. */ - list describe_splits(1:required string cfName, - 2:required string start_token, - 3:required string end_token, - 4:required i32 keys_per_split) - throws (1:InvalidRequestException ire), - - /** adds a column family. returns the new schema id. */ - string system_add_column_family(1:required CfDef cf_def) - throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), - - /** drops a column family. returns the new schema id. */ - string system_drop_column_family(1:required string column_family) - throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), - - /** adds a keyspace and any column families that are part of it. returns the new schema id. */ - string system_add_keyspace(1:required KsDef ks_def) - throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), - - /** drops a keyspace and any column families that are part of it. returns the new schema id. */ - string system_drop_keyspace(1:required string keyspace) - throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), - - /** updates properties of a keyspace. returns the new schema id. */ - string system_update_keyspace(1:required KsDef ks_def) - throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), - - /** updates properties of a column family. returns the new schema id. */ - string system_update_column_family(1:required CfDef cf_def) - throws (1:InvalidRequestException ire, 2:SchemaDisagreementException sde), - - /** - * Executes a CQL (Cassandra Query Language) statement and returns a - * CqlResult containing the results. - */ - CqlResult execute_cql_query(1:required binary query, 2:required Compression compression) - throws (1:InvalidRequestException ire, - 2:UnavailableException ue, - 3:TimedOutException te, - 4:SchemaDisagreementException sde) - - - /** - * Prepare a CQL (Cassandra Query Language) statement by compiling and returning - * - the type of CQL statement - * - an id token of the compiled CQL stored on the server side. - * - a count of the discovered bound markers in the statement - */ - CqlPreparedResult prepare_cql_query(1:required binary query, 2:required Compression compression) - throws (1:InvalidRequestException ire) - - - /** - * Executes a prepared CQL (Cassandra Query Language) statement by passing an id token and a list of variables - * to bind and returns a CqlResult containing the results. - */ - CqlResult execute_prepared_cql_query(1:required i32 itemId, 2:required list values) - throws (1:InvalidRequestException ire, - 2:UnavailableException ue, - 3:TimedOutException te, - 4:SchemaDisagreementException sde) - - -} diff --git a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 0bb460ff441..00000000000 --- a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("d0d3706b-fed5-4cf5-b984-04f448de9d7b")] \ No newline at end of file diff --git a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj b/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj deleted file mode 100644 index c4a84a301f0..00000000000 --- a/lib/netcore/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj +++ /dev/null @@ -1,36 +0,0 @@ - - - - netcoreapp2.0 - Thrift.PublicInterfaces.Compile.Tests - Thrift.PublicInterfaces.Compile.Tests - false - false - false - false - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/netcore/Tests/Thrift.Tests/Collections/TCollectionsTests.cs b/lib/netcore/Tests/Thrift.Tests/Collections/TCollectionsTests.cs deleted file mode 100644 index 1be99b48fd6..00000000000 --- a/lib/netcore/Tests/Thrift.Tests/Collections/TCollectionsTests.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.Text; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Thrift.Collections; - -namespace Thrift.Tests.Collections -{ - // ReSharper disable once InconsistentNaming - [TestClass] - public class TCollectionsTests - { - //TODO: Add tests for IEnumerable with objects and primitive values inside - - [TestMethod] - public void TCollection_Equals_Primitive_Test() - { - var collection1 = new List {1,2,3}; - var collection2 = new List {1,2,3}; - - var result = TCollections.Equals(collection1, collection2); - - Assert.IsTrue(result); - } - - [TestMethod] - public void TCollection_Equals_Primitive_Different_Test() - { - var collection1 = new List { 1, 2, 3 }; - var collection2 = new List { 1, 2 }; - - var result = TCollections.Equals(collection1, collection2); - - Assert.IsFalse(result); - } - - [TestMethod] - public void TCollection_Equals_Objects_Test() - { - var collection1 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; - var collection2 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; - - var result = TCollections.Equals(collection1, collection2); - - // references to different collections - Assert.IsFalse(result); - } - - [TestMethod] - public void TCollection_Equals_OneAndTheSameObject_Test() - { - var collection1 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; - var collection2 = collection1; - - var result = TCollections.Equals(collection1, collection2); - - // references to one and the same collection - Assert.IsTrue(result); - } - - private class ExampleClass - { - public int X { get; set; } - } - } -} diff --git a/lib/netcore/Tests/Thrift.Tests/Collections/THashSetTests.cs b/lib/netcore/Tests/Thrift.Tests/Collections/THashSetTests.cs deleted file mode 100644 index 8de573eee8c..00000000000 --- a/lib/netcore/Tests/Thrift.Tests/Collections/THashSetTests.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Thrift.Collections; - -namespace Thrift.Tests.Collections -{ - // ReSharper disable once InconsistentNaming - [TestClass] - public class THashSetTests - { - [TestMethod] - public void THashSet_Equals_Primitive_Test() - { - const int value = 1; - - var hashSet = new THashSet {value}; - - Assert.IsTrue(hashSet.Contains(value)); - - hashSet.Remove(value); - - Assert.IsTrue(hashSet.Count == 0); - - hashSet.Add(value); - - Assert.IsTrue(hashSet.Contains(value)); - - hashSet.Clear(); - - Assert.IsTrue(hashSet.Count == 0); - - var newArr = new int[1]; - hashSet.Add(value); - hashSet.CopyTo(newArr, 0); - - Assert.IsTrue(newArr.Contains(value)); - - var en = hashSet.GetEnumerator(); - en.MoveNext(); - - Assert.IsTrue((int)en.Current == value); - - using (var ien = ((IEnumerable)hashSet).GetEnumerator()) - { - ien.MoveNext(); - - Assert.IsTrue(ien.Current == value); - } - } - } -} diff --git a/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs b/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs deleted file mode 100644 index cdc8317e249..00000000000 --- a/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolHelperTests.cs +++ /dev/null @@ -1,172 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Thrift.Protocols; -using Thrift.Protocols.Entities; -using Thrift.Protocols.Utilities; - -namespace Thrift.Tests.Protocols -{ - [TestClass] - public class TJSONProtocolHelperTests - { - [TestMethod] - public void GetTypeNameForTypeId_Test() - { - // input/output - var sets = new List> - { - new Tuple(TType.Bool, TJSONProtocolConstants.TypeNames.NameBool), - new Tuple(TType.Byte, TJSONProtocolConstants.TypeNames.NameByte), - new Tuple(TType.I16, TJSONProtocolConstants.TypeNames.NameI16), - new Tuple(TType.I32, TJSONProtocolConstants.TypeNames.NameI32), - new Tuple(TType.I64, TJSONProtocolConstants.TypeNames.NameI64), - new Tuple(TType.Double, TJSONProtocolConstants.TypeNames.NameDouble), - new Tuple(TType.String, TJSONProtocolConstants.TypeNames.NameString), - new Tuple(TType.Struct, TJSONProtocolConstants.TypeNames.NameStruct), - new Tuple(TType.Map, TJSONProtocolConstants.TypeNames.NameMap), - new Tuple(TType.Set, TJSONProtocolConstants.TypeNames.NameSet), - new Tuple(TType.List, TJSONProtocolConstants.TypeNames.NameList), - }; - - foreach (var t in sets) - { - Assert.IsTrue(TJSONProtocolHelper.GetTypeNameForTypeId(t.Item1) == t.Item2, $"Wrong mapping of TypeName {t.Item2} to TType: {t.Item1}"); - } - } - - [TestMethod] - [ExpectedException(typeof(TProtocolException))] - public void GetTypeNameForTypeId_TStop_Test() - { - TJSONProtocolHelper.GetTypeNameForTypeId(TType.Stop); - } - - [TestMethod] - [ExpectedException(typeof(TProtocolException))] - public void GetTypeNameForTypeId_NonExistingTType_Test() - { - TJSONProtocolHelper.GetTypeNameForTypeId((TType)100); - } - - [TestMethod] - public void GetTypeIdForTypeName_Test() - { - // input/output - var sets = new List> - { - new Tuple(TType.Bool, TJSONProtocolConstants.TypeNames.NameBool), - new Tuple(TType.Byte, TJSONProtocolConstants.TypeNames.NameByte), - new Tuple(TType.I16, TJSONProtocolConstants.TypeNames.NameI16), - new Tuple(TType.I32, TJSONProtocolConstants.TypeNames.NameI32), - new Tuple(TType.I64, TJSONProtocolConstants.TypeNames.NameI64), - new Tuple(TType.Double, TJSONProtocolConstants.TypeNames.NameDouble), - new Tuple(TType.String, TJSONProtocolConstants.TypeNames.NameString), - new Tuple(TType.Struct, TJSONProtocolConstants.TypeNames.NameStruct), - new Tuple(TType.Map, TJSONProtocolConstants.TypeNames.NameMap), - new Tuple(TType.Set, TJSONProtocolConstants.TypeNames.NameSet), - new Tuple(TType.List, TJSONProtocolConstants.TypeNames.NameList), - }; - - foreach (var t in sets) - { - Assert.IsTrue(TJSONProtocolHelper.GetTypeIdForTypeName(t.Item2) == t.Item1, $"Wrong mapping of TypeName {t.Item2} to TType: {t.Item1}"); - } - } - - [TestMethod] - [ExpectedException(typeof(TProtocolException))] - public void GetTypeIdForTypeName_TStopTypeName_Test() - { - TJSONProtocolHelper.GetTypeIdForTypeName(new []{(byte)TType.Stop, (byte)TType.Stop}); - } - - [TestMethod] - [ExpectedException(typeof(TProtocolException))] - public void GetTypeIdForTypeName_NonExistingTypeName_Test() - { - TJSONProtocolHelper.GetTypeIdForTypeName(new byte[]{100}); - } - - [TestMethod] - [ExpectedException(typeof(TProtocolException))] - public void GetTypeIdForTypeName_EmptyName_Test() - { - TJSONProtocolHelper.GetTypeIdForTypeName(new byte[] {}); - } - - [TestMethod] - public void IsJsonNumeric_Test() - { - // input/output - var correctJsonNumeric = "+-.0123456789Ee"; - var incorrectJsonNumeric = "AaBcDd/*\\"; - - var sets = correctJsonNumeric.Select(ch => new Tuple((byte) ch, true)).ToList(); - sets.AddRange(incorrectJsonNumeric.Select(ch => new Tuple((byte) ch, false))); - - foreach (var t in sets) - { - Assert.IsTrue(TJSONProtocolHelper.IsJsonNumeric(t.Item1) == t.Item2, $"Wrong mapping of Char {t.Item1} to bool: {t.Item2}"); - } - } - - [TestMethod] - public void ToHexVal_Test() - { - // input/output - var chars = "0123456789abcdef"; - var expectedHexValues = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - - var sets = chars.Select((ch, i) => new Tuple(ch, expectedHexValues[i])).ToList(); - - foreach (var t in sets) - { - var actualResult = TJSONProtocolHelper.ToHexVal((byte)t.Item1); - Assert.IsTrue(actualResult == t.Item2, $"Wrong mapping of char byte {t.Item1} to it expected hex value: {t.Item2}. Actual hex value: {actualResult}"); - } - } - - [TestMethod] - [ExpectedException(typeof(TProtocolException))] - public void ToHexVal_WrongInputChar_Test() - { - TJSONProtocolHelper.ToHexVal((byte)'s'); - } - - [TestMethod] - public void ToHexChar_Test() - { - // input/output - var hexValues = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; - var expectedChars = "0123456789abcdef"; - - - var sets = hexValues.Select((hv, i) => new Tuple(hv, expectedChars[i])).ToList(); - - foreach (var t in sets) - { - var actualResult = TJSONProtocolHelper.ToHexChar(t.Item1); - Assert.IsTrue(actualResult == t.Item2, $"Wrong mapping of hex value {t.Item1} to it expected char: {t.Item2}. Actual hex value: {actualResult}"); - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs b/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs deleted file mode 100644 index 523736086e7..00000000000 --- a/lib/netcore/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using NSubstitute; -using Thrift.Protocols; -using Thrift.Protocols.Entities; -using Thrift.Transports; -using Thrift.Transports.Client; - -namespace Thrift.Tests.Protocols -{ - // ReSharper disable once InconsistentNaming - [TestClass] - public class TJSONProtocolTests - { - [TestMethod] - public void TJSONProtocol_Can_Create_Instance_Test() - { - var httpClientTransport = Substitute.For(new Uri("http://localhost"), null); - - var result = new TJSONProtocolWrapper(httpClientTransport); - - Assert.IsNotNull(result); - Assert.IsNotNull(result.WrappedContext); - Assert.IsNotNull(result.WrappedReader); - Assert.IsNotNull(result.Transport); - Assert.IsTrue(result.WrappedRecursionDepth == 0); - Assert.IsTrue(result.WrappedRecursionLimit == TProtocol.DefaultRecursionDepth); - - Assert.IsTrue(result.Transport.Equals(httpClientTransport)); - Assert.IsTrue(result.WrappedContext.GetType().Name.Equals("JSONBaseContext", StringComparison.OrdinalIgnoreCase)); - Assert.IsTrue(result.WrappedReader.GetType().Name.Equals("LookaheadReader", StringComparison.OrdinalIgnoreCase)); - } - - private class TJSONProtocolWrapper : TJsonProtocol - { - public TJSONProtocolWrapper(TClientTransport trans) : base(trans) - { - } - - public object WrappedContext => Context; - public object WrappedReader => Reader; - public int WrappedRecursionDepth => RecursionDepth; - public int WrappedRecursionLimit => RecursionLimit; - } - } -} diff --git a/lib/netcore/Tests/Thrift.Tests/Thrift.Tests.csproj b/lib/netcore/Tests/Thrift.Tests/Thrift.Tests.csproj deleted file mode 100644 index e46f16522f1..00000000000 --- a/lib/netcore/Tests/Thrift.Tests/Thrift.Tests.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - netcoreapp2.0 - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/netcore/Thrift.sln b/lib/netcore/Thrift.sln deleted file mode 100644 index fe30aa5c676..00000000000 --- a/lib/netcore/Thrift.sln +++ /dev/null @@ -1,85 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.12 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "Thrift\Thrift.csproj", "{D85F572F-7D80-40A4-9A9B-2731ED187C24}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.IntegrationTests", "Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj", "{9F9A11BF-3C95-4E80-AFBF-768541996844}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.Tests", "Tests\Thrift.Tests\Thrift.Tests.csproj", "{75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.PublicInterfaces.Compile.Tests", "Tests\Thrift.PublicInterfaces.Compile.Tests\Thrift.PublicInterfaces.Compile.Tests.csproj", "{A429F05B-F511-45EF-AE7B-04E1AE9C9367}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|x64.ActiveCfg = Debug|Any CPU - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|x64.Build.0 = Debug|Any CPU - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|x86.ActiveCfg = Debug|Any CPU - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Debug|x86.Build.0 = Debug|Any CPU - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|Any CPU.Build.0 = Release|Any CPU - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|x64.ActiveCfg = Release|Any CPU - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|x64.Build.0 = Release|Any CPU - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|x86.ActiveCfg = Release|Any CPU - {D85F572F-7D80-40A4-9A9B-2731ED187C24}.Release|x86.Build.0 = Release|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x64.ActiveCfg = Debug|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x64.Build.0 = Debug|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x86.ActiveCfg = Debug|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Debug|x86.Build.0 = Debug|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|Any CPU.Build.0 = Release|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x64.ActiveCfg = Release|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x64.Build.0 = Release|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x86.ActiveCfg = Release|Any CPU - {9F9A11BF-3C95-4E80-AFBF-768541996844}.Release|x86.Build.0 = Release|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x64.ActiveCfg = Debug|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x64.Build.0 = Debug|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x86.ActiveCfg = Debug|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Debug|x86.Build.0 = Debug|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|Any CPU.Build.0 = Release|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x64.ActiveCfg = Release|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x64.Build.0 = Release|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x86.ActiveCfg = Release|Any CPU - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1}.Release|x86.Build.0 = Release|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x64.ActiveCfg = Debug|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x64.Build.0 = Debug|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x86.ActiveCfg = Debug|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Debug|x86.Build.0 = Debug|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|Any CPU.Build.0 = Release|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x64.ActiveCfg = Release|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x64.Build.0 = Release|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x86.ActiveCfg = Release|Any CPU - {A429F05B-F511-45EF-AE7B-04E1AE9C9367}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {9F9A11BF-3C95-4E80-AFBF-768541996844} = {F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE} - {75C2F9DC-3546-4D0A-A2DF-31C93516B6C1} = {F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE} - {A429F05B-F511-45EF-AE7B-04E1AE9C9367} = {F51FC4DA-CAC0-48B1-A069-B1712BCAA5BE} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {FD20BC4A-0109-41D8-8C0C-893E784D7EF9} - EndGlobalSection -EndGlobal diff --git a/lib/netcore/Thrift/Collections/TCollections.cs b/lib/netcore/Thrift/Collections/TCollections.cs deleted file mode 100644 index 147bfc7d31c..00000000000 --- a/lib/netcore/Thrift/Collections/TCollections.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Collections; - -namespace Thrift.Collections -{ - // ReSharper disable once InconsistentNaming - public class TCollections - { - /// - /// This will return true if the two collections are value-wise the same. - /// If the collection contains a collection, the collections will be compared using this method. - /// - public static bool Equals(IEnumerable first, IEnumerable second) - { - if (first == null && second == null) - { - return true; - } - - if (first == null || second == null) - { - return false; - } - - var fiter = first.GetEnumerator(); - var siter = second.GetEnumerator(); - - var fnext = fiter.MoveNext(); - var snext = siter.MoveNext(); - - while (fnext && snext) - { - var fenum = fiter.Current as IEnumerable; - var senum = siter.Current as IEnumerable; - - if (fenum != null && senum != null) - { - if (!Equals(fenum, senum)) - { - return false; - } - } - else if (fenum == null ^ senum == null) - { - return false; - } - else if (!Equals(fiter.Current, siter.Current)) - { - return false; - } - - fnext = fiter.MoveNext(); - snext = siter.MoveNext(); - } - - return fnext == snext; - } - - /// - /// This returns a hashcode based on the value of the enumerable. - /// - public static int GetHashCode(IEnumerable enumerable) - { - if (enumerable == null) - { - return 0; - } - - var hashcode = 0; - - foreach (var obj in enumerable) - { - var enum2 = obj as IEnumerable; - var objHash = enum2 == null ? obj.GetHashCode() : GetHashCode(enum2); - - unchecked - { - hashcode = (hashcode*397) ^ (objHash); - } - } - - return hashcode; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Collections/THashSet.cs b/lib/netcore/Thrift/Collections/THashSet.cs deleted file mode 100644 index 011f0a0d629..00000000000 --- a/lib/netcore/Thrift/Collections/THashSet.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Collections; -using System.Collections.Generic; - -namespace Thrift.Collections -{ - // ReSharper disable once InconsistentNaming - public class THashSet : ICollection - { - private readonly HashSet _set = new HashSet(); - - public int Count => _set.Count; - - public bool IsReadOnly => false; - - public void Add(T item) - { - _set.Add(item); - } - - public void Clear() - { - _set.Clear(); - } - - public bool Contains(T item) - { - return _set.Contains(item); - } - - public void CopyTo(T[] array, int arrayIndex) - { - _set.CopyTo(array, arrayIndex); - } - - public IEnumerator GetEnumerator() - { - return _set.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable) _set).GetEnumerator(); - } - - public bool Remove(T item) - { - return _set.Remove(item); - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/ITAsyncProcessor.cs b/lib/netcore/Thrift/ITAsyncProcessor.cs deleted file mode 100644 index db8e40aefe8..00000000000 --- a/lib/netcore/Thrift/ITAsyncProcessor.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols; - -namespace Thrift -{ - public interface ITAsyncProcessor - { - Task ProcessAsync(TProtocol iprot, TProtocol oprot); - Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken); - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/ITProcessorFactory.cs b/lib/netcore/Thrift/ITProcessorFactory.cs deleted file mode 100644 index 5133e5c4801..00000000000 --- a/lib/netcore/Thrift/ITProcessorFactory.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using Thrift.Server; -using Thrift.Transports; - -namespace Thrift -{ - // ReSharper disable once InconsistentNaming - public interface ITProcessorFactory - { - ITAsyncProcessor GetAsyncProcessor(TClientTransport trans, TBaseServer baseServer = null); - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Properties/AssemblyInfo.cs b/lib/netcore/Thrift/Properties/AssemblyInfo.cs deleted file mode 100644 index 58aa84495d2..00000000000 --- a/lib/netcore/Thrift/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyTitle("Thrift")] -[assembly: AssemblyDescription("C# .NET Core bindings for the Apache Thrift RPC system")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -//@TODO where to put License information? - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a exType in this assembly from -// COM, set the ComVisible attribute to true on that exType. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("df3f8ef0-e0a3-4c86-a65b-8ec84e016b1d")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: - -[assembly: AssemblyVersion("0.14.0.0")] -[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/lib/netcore/Thrift/Protocols/Entities/TField.cs b/lib/netcore/Thrift/Protocols/Entities/TField.cs deleted file mode 100644 index d311535e73c..00000000000 --- a/lib/netcore/Thrift/Protocols/Entities/TField.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -namespace Thrift.Protocols.Entities -{ - // ReSharper disable once InconsistentNaming - public struct TField - { - public TField(string name, TType type, short id) - { - Name = name; - Type = type; - ID = id; - } - - public string Name { get; set; } - - public TType Type { get; set; } - - // ReSharper disable once InconsistentNaming - do not rename - it used for generation - public short ID { get; set; } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Entities/TList.cs b/lib/netcore/Thrift/Protocols/Entities/TList.cs deleted file mode 100644 index ce232207cba..00000000000 --- a/lib/netcore/Thrift/Protocols/Entities/TList.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -namespace Thrift.Protocols.Entities -{ - // ReSharper disable once InconsistentNaming - public struct TList - { - public TList(TType elementType, int count) - { - ElementType = elementType; - Count = count; - } - - public TType ElementType { get; set; } - - public int Count { get; set; } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Entities/TMap.cs b/lib/netcore/Thrift/Protocols/Entities/TMap.cs deleted file mode 100644 index 9195593db27..00000000000 --- a/lib/netcore/Thrift/Protocols/Entities/TMap.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -namespace Thrift.Protocols.Entities -{ - // ReSharper disable once InconsistentNaming - public struct TMap - { - public TMap(TType keyType, TType valueType, int count) - { - KeyType = keyType; - ValueType = valueType; - Count = count; - } - - public TType KeyType { get; set; } - - public TType ValueType { get; set; } - - public int Count { get; set; } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Entities/TMessage.cs b/lib/netcore/Thrift/Protocols/Entities/TMessage.cs deleted file mode 100644 index 17f49298f77..00000000000 --- a/lib/netcore/Thrift/Protocols/Entities/TMessage.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -namespace Thrift.Protocols.Entities -{ - // ReSharper disable once InconsistentNaming - public struct TMessage - { - public TMessage(string name, TMessageType type, int seqid) - { - Name = name; - Type = type; - SeqID = seqid; - } - - public string Name { get; set; } - - public TMessageType Type { get; set; } - - // ReSharper disable once InconsistentNaming - do not rename - it used for generation - public int SeqID { get; set; } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Entities/TMessageType.cs b/lib/netcore/Thrift/Protocols/Entities/TMessageType.cs deleted file mode 100644 index d7b9a227595..00000000000 --- a/lib/netcore/Thrift/Protocols/Entities/TMessageType.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -namespace Thrift.Protocols.Entities -{ - // ReSharper disable once InconsistentNaming - public enum TMessageType - { - Call = 1, - Reply = 2, - Exception = 3, - Oneway = 4 - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Entities/TSet.cs b/lib/netcore/Thrift/Protocols/Entities/TSet.cs deleted file mode 100644 index a583b54a681..00000000000 --- a/lib/netcore/Thrift/Protocols/Entities/TSet.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -namespace Thrift.Protocols.Entities -{ - // ReSharper disable once InconsistentNaming - public struct TSet - { - public TSet(TType elementType, int count) - { - ElementType = elementType; - Count = count; - } - - public TSet(TList list) - : this(list.ElementType, list.Count) - { - } - - public TType ElementType { get; set; } - - public int Count { get; set; } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Entities/TStruct.cs b/lib/netcore/Thrift/Protocols/Entities/TStruct.cs deleted file mode 100644 index a28dcc3d001..00000000000 --- a/lib/netcore/Thrift/Protocols/Entities/TStruct.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -namespace Thrift.Protocols.Entities -{ - // ReSharper disable once InconsistentNaming - public struct TStruct - { - public TStruct(string name) - { - Name = name; - } - - public string Name { get; set; } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Entities/TType.cs b/lib/netcore/Thrift/Protocols/Entities/TType.cs deleted file mode 100644 index ebe781c9547..00000000000 --- a/lib/netcore/Thrift/Protocols/Entities/TType.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -namespace Thrift.Protocols.Entities -{ - // ReSharper disable once InconsistentNaming - public enum TType : byte - { - Stop = 0, - Void = 1, - Bool = 2, - Byte = 3, - Double = 4, - I16 = 6, - I32 = 8, - I64 = 10, - String = 11, - Struct = 12, - Map = 13, - Set = 14, - List = 15 - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/ITProtocolFactory.cs b/lib/netcore/Thrift/Protocols/ITProtocolFactory.cs deleted file mode 100644 index ecc5cc494d4..00000000000 --- a/lib/netcore/Thrift/Protocols/ITProtocolFactory.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using Thrift.Transports; - -namespace Thrift.Protocols -{ - // ReSharper disable once InconsistentNaming - public interface ITProtocolFactory - { - TProtocol GetProtocol(TClientTransport trans); - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/TAbstractBase.cs b/lib/netcore/Thrift/Protocols/TAbstractBase.cs deleted file mode 100644 index 4e18681bfb9..00000000000 --- a/lib/netcore/Thrift/Protocols/TAbstractBase.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Protocols -{ - // ReSharper disable once InconsistentNaming - public interface TAbstractBase - { - Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken); - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/TBase.cs b/lib/netcore/Thrift/Protocols/TBase.cs deleted file mode 100644 index 014e1aee856..00000000000 --- a/lib/netcore/Thrift/Protocols/TBase.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Protocols -{ - // ReSharper disable once InconsistentNaming - public interface TBase : TAbstractBase - { - Task ReadAsync(TProtocol tProtocol, CancellationToken cancellationToken); - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/TBinaryProtocol.cs b/lib/netcore/Thrift/Protocols/TBinaryProtocol.cs deleted file mode 100644 index deec85c4245..00000000000 --- a/lib/netcore/Thrift/Protocols/TBinaryProtocol.cs +++ /dev/null @@ -1,613 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols.Entities; -using Thrift.Transports; - -namespace Thrift.Protocols -{ - // ReSharper disable once InconsistentNaming - public class TBinaryProtocol : TProtocol - { - //TODO: Unit tests - //TODO: Localization - //TODO: pragma - - protected const uint VersionMask = 0xffff0000; - protected const uint Version1 = 0x80010000; - - protected bool StrictRead; - protected bool StrictWrite; - - public TBinaryProtocol(TClientTransport trans) - : this(trans, false, true) - { - } - - public TBinaryProtocol(TClientTransport trans, bool strictRead, bool strictWrite) - : base(trans) - { - StrictRead = strictRead; - StrictWrite = strictWrite; - } - - public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - if (StrictWrite) - { - var version = Version1 | (uint) message.Type; - await WriteI32Async((int) version, cancellationToken); - await WriteStringAsync(message.Name, cancellationToken); - await WriteI32Async(message.SeqID, cancellationToken); - } - else - { - await WriteStringAsync(message.Name, cancellationToken); - await WriteByteAsync((sbyte) message.Type, cancellationToken); - await WriteI32Async(message.SeqID, cancellationToken); - } - } - - public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task WriteStructEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await WriteByteAsync((sbyte) field.Type, cancellationToken); - await WriteI16Async(field.ID, cancellationToken); - } - - public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await WriteByteAsync((sbyte) TType.Stop, cancellationToken); - } - - public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await WriteByteAsync((sbyte) map.KeyType, cancellationToken); - await WriteByteAsync((sbyte) map.ValueType, cancellationToken); - await WriteI32Async(map.Count, cancellationToken); - } - - public override async Task WriteMapEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await WriteByteAsync((sbyte) list.ElementType, cancellationToken); - await WriteI32Async(list.Count, cancellationToken); - } - - public override async Task WriteListEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await WriteByteAsync((sbyte) set.ElementType, cancellationToken); - await WriteI32Async(set.Count, cancellationToken); - } - - public override async Task WriteSetEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await WriteByteAsync(b ? (sbyte) 1 : (sbyte) 0, cancellationToken); - } - - protected internal static byte[] CreateWriteByte(sbyte b) - { - var bout = new byte[1]; - - bout[0] = (byte) b; - - return bout; - } - - public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var bout = CreateWriteByte(b); - await Trans.WriteAsync(bout, 0, 1, cancellationToken); - } - - protected internal static byte[] CreateWriteI16(short s) - { - var i16Out = new byte[2]; - - i16Out[0] = (byte) (0xff & (s >> 8)); - i16Out[1] = (byte) (0xff & s); - - return i16Out; - } - - public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var i16Out = CreateWriteI16(i16); - await Trans.WriteAsync(i16Out, 0, 2, cancellationToken); - } - - protected internal static byte[] CreateWriteI32(int i32) - { - var i32Out = new byte[4]; - - i32Out[0] = (byte) (0xff & (i32 >> 24)); - i32Out[1] = (byte) (0xff & (i32 >> 16)); - i32Out[2] = (byte) (0xff & (i32 >> 8)); - i32Out[3] = (byte) (0xff & i32); - - return i32Out; - } - - public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var i32Out = CreateWriteI32(i32); - await Trans.WriteAsync(i32Out, 0, 4, cancellationToken); - } - - protected internal static byte[] CreateWriteI64(long i64) - { - var i64Out = new byte[8]; - - i64Out[0] = (byte) (0xff & (i64 >> 56)); - i64Out[1] = (byte) (0xff & (i64 >> 48)); - i64Out[2] = (byte) (0xff & (i64 >> 40)); - i64Out[3] = (byte) (0xff & (i64 >> 32)); - i64Out[4] = (byte) (0xff & (i64 >> 24)); - i64Out[5] = (byte) (0xff & (i64 >> 16)); - i64Out[6] = (byte) (0xff & (i64 >> 8)); - i64Out[7] = (byte) (0xff & i64); - - return i64Out; - } - - public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var i64Out = CreateWriteI64(i64); - await Trans.WriteAsync(i64Out, 0, 8, cancellationToken); - } - - public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await WriteI64Async(BitConverter.DoubleToInt64Bits(d), cancellationToken); - } - - public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await WriteI32Async(bytes.Length, cancellationToken); - await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); - } - - public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var message = new TMessage(); - var size = await ReadI32Async(cancellationToken); - if (size < 0) - { - var version = (uint) size & VersionMask; - if (version != Version1) - { - throw new TProtocolException(TProtocolException.BAD_VERSION, - $"Bad version in ReadMessageBegin: {version}"); - } - message.Type = (TMessageType) (size & 0x000000ff); - message.Name = await ReadStringAsync(cancellationToken); - message.SeqID = await ReadI32Async(cancellationToken); - } - else - { - if (StrictRead) - { - throw new TProtocolException(TProtocolException.BAD_VERSION, - "Missing version in ReadMessageBegin, old client?"); - } - message.Name = await ReadStringBodyAsync(size, cancellationToken); - message.Type = (TMessageType) await ReadByteAsync(cancellationToken); - message.SeqID = await ReadI32Async(cancellationToken); - } - return message; - } - - public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - //TODO: no read from internal transport? - return new TStruct(); - } - - public override async Task ReadStructEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var field = new TField - { - Type = (TType) await ReadByteAsync(cancellationToken) - }; - - if (field.Type != TType.Stop) - { - field.ID = await ReadI16Async(cancellationToken); - } - - return field; - } - - public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var map = new TMap - { - KeyType = (TType) await ReadByteAsync(cancellationToken), - ValueType = (TType) await ReadByteAsync(cancellationToken), - Count = await ReadI32Async(cancellationToken) - }; - - return map; - } - - public override async Task ReadMapEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task ReadListBeginAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var list = new TList - { - ElementType = (TType) await ReadByteAsync(cancellationToken), - Count = await ReadI32Async(cancellationToken) - }; - - return list; - } - - public override async Task ReadListEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var set = new TSet - { - ElementType = (TType) await ReadByteAsync(cancellationToken), - Count = await ReadI32Async(cancellationToken) - }; - - return set; - } - - public override async Task ReadSetEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task ReadBoolAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - return await ReadByteAsync(cancellationToken) == 1; - } - - public override async Task ReadByteAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var bin = new byte[1]; - await Trans.ReadAllAsync(bin, 0, 1, cancellationToken); //TODO: why readall ? - return (sbyte) bin[0]; - } - - public override async Task ReadI16Async(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var i16In = new byte[2]; - await Trans.ReadAllAsync(i16In, 0, 2, cancellationToken); - var result = (short) (((i16In[0] & 0xff) << 8) | i16In[1] & 0xff); - return result; - } - - public override async Task ReadI32Async(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var i32In = new byte[4]; - await Trans.ReadAllAsync(i32In, 0, 4, cancellationToken); - - var result = - ((i32In[0] & 0xff) << 24) | - ((i32In[1] & 0xff) << 16) | - ((i32In[2] & 0xff) << 8) | - i32In[3] & 0xff; - - return result; - } - -#pragma warning disable 675 - - protected internal long CreateReadI64(byte[] buf) - { - var result = - ((long) (buf[0] & 0xff) << 56) | - ((long) (buf[1] & 0xff) << 48) | - ((long) (buf[2] & 0xff) << 40) | - ((long) (buf[3] & 0xff) << 32) | - ((long) (buf[4] & 0xff) << 24) | - ((long) (buf[5] & 0xff) << 16) | - ((long) (buf[6] & 0xff) << 8) | - buf[7] & 0xff; - - return result; - } - -#pragma warning restore 675 - - public override async Task ReadI64Async(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var i64In = new byte[8]; - await Trans.ReadAllAsync(i64In, 0, 8, cancellationToken); - return CreateReadI64(i64In); - } - - public override async Task ReadDoubleAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var d = await ReadI64Async(cancellationToken); - return BitConverter.Int64BitsToDouble(d); - } - - public override async Task ReadBinaryAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var size = await ReadI32Async(cancellationToken); - var buf = new byte[size]; - await Trans.ReadAllAsync(buf, 0, size, cancellationToken); - return buf; - } - - private async Task ReadStringBodyAsync(int size, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - var buf = new byte[size]; - await Trans.ReadAllAsync(buf, 0, size, cancellationToken); - return Encoding.UTF8.GetString(buf, 0, buf.Length); - } - - public class Factory : ITProtocolFactory - { - protected bool StrictRead; - protected bool StrictWrite; - - public Factory() - : this(false, true) - { - } - - public Factory(bool strictRead, bool strictWrite) - { - StrictRead = strictRead; - StrictWrite = strictWrite; - } - - public TProtocol GetProtocol(TClientTransport trans) - { - return new TBinaryProtocol(trans, StrictRead, StrictWrite); - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/TCompactProtocol.cs b/lib/netcore/Thrift/Protocols/TCompactProtocol.cs deleted file mode 100644 index cecdf03ccb8..00000000000 --- a/lib/netcore/Thrift/Protocols/TCompactProtocol.cs +++ /dev/null @@ -1,922 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols.Entities; -using Thrift.Transports; - -namespace Thrift.Protocols -{ - //TODO: implementation of TProtocol - - // ReSharper disable once InconsistentNaming - public class TCompactProtocol : TProtocol - { - private const byte ProtocolId = 0x82; - private const byte Version = 1; - private const byte VersionMask = 0x1f; // 0001 1111 - private const byte TypeMask = 0xE0; // 1110 0000 - private const byte TypeBits = 0x07; // 0000 0111 - private const int TypeShiftAmount = 5; - private static readonly TStruct AnonymousStruct = new TStruct(string.Empty); - private static readonly TField Tstop = new TField(string.Empty, TType.Stop, 0); - - // ReSharper disable once InconsistentNaming - private static readonly byte[] TTypeToCompactType = new byte[16]; - - /// - /// Used to keep track of the last field for the current and previous structs, so we can do the delta stuff. - /// - private readonly Stack _lastField = new Stack(15); - - /// - /// If we encounter a boolean field begin, save the TField here so it can have the value incorporated. - /// - private TField? _booleanField; - - /// - /// If we Read a field header, and it's a boolean field, save the boolean value here so that ReadBool can use it. - /// - private bool? _boolValue; - - private short _lastFieldId; - - public TCompactProtocol(TClientTransport trans) - : base(trans) - { - TTypeToCompactType[(int) TType.Stop] = Types.Stop; - TTypeToCompactType[(int) TType.Bool] = Types.BooleanTrue; - TTypeToCompactType[(int) TType.Byte] = Types.Byte; - TTypeToCompactType[(int) TType.I16] = Types.I16; - TTypeToCompactType[(int) TType.I32] = Types.I32; - TTypeToCompactType[(int) TType.I64] = Types.I64; - TTypeToCompactType[(int) TType.Double] = Types.Double; - TTypeToCompactType[(int) TType.String] = Types.Binary; - TTypeToCompactType[(int) TType.List] = Types.List; - TTypeToCompactType[(int) TType.Set] = Types.Set; - TTypeToCompactType[(int) TType.Map] = Types.Map; - TTypeToCompactType[(int) TType.Struct] = Types.Struct; - } - - public void Reset() - { - _lastField.Clear(); - _lastFieldId = 0; - } - - public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await Trans.WriteAsync(new[] {ProtocolId}, cancellationToken); - await - Trans.WriteAsync( - new[] {(byte) ((Version & VersionMask) | (((uint) message.Type << TypeShiftAmount) & TypeMask))}, - cancellationToken); - - var bufferTuple = CreateWriteVarInt32((uint) message.SeqID); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); - - await WriteStringAsync(message.Name, cancellationToken); - } - - public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - /// - /// 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 override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - _lastField.Push(_lastFieldId); - _lastFieldId = 0; - } - - public override async Task WriteStructEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - _lastFieldId = _lastField.Pop(); - } - - private async Task WriteFieldBeginInternalAsync(TField field, byte typeOverride, - CancellationToken cancellationToken) - { - // if there's a exType override, use that. - var typeToWrite = typeOverride == 0xFF ? GetCompactType(field.Type) : typeOverride; - - // check if we can use delta encoding for the field id - if ((field.ID > _lastFieldId) && (field.ID - _lastFieldId <= 15)) - { - var b = (byte) (((field.ID - _lastFieldId) << 4) | typeToWrite); - // Write them together - await Trans.WriteAsync(new[] {b}, cancellationToken); - } - else - { - // Write them separate - await Trans.WriteAsync(new[] {typeToWrite}, cancellationToken); - await WriteI16Async(field.ID, cancellationToken); - } - - _lastFieldId = field.ID; - } - - public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) - { - if (field.Type == TType.Bool) - { - _booleanField = field; - } - else - { - await WriteFieldBeginInternalAsync(field, 0xFF, cancellationToken); - } - } - - public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await Trans.WriteAsync(new[] {Types.Stop}, cancellationToken); - } - - protected async Task WriteCollectionBeginAsync(TType elemType, int size, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - /* - Abstract method for writing the start of lists and sets. List and sets on - the wire differ only by the exType indicator. - */ - - if (size <= 14) - { - await Trans.WriteAsync(new[] {(byte) ((size << 4) | GetCompactType(elemType))}, cancellationToken); - } - else - { - await Trans.WriteAsync(new[] {(byte) (0xf0 | GetCompactType(elemType))}, cancellationToken); - - var bufferTuple = CreateWriteVarInt32((uint) size); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); - } - } - - public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) - { - await WriteCollectionBeginAsync(list.ElementType, list.Count, cancellationToken); - } - - public override async Task WriteListEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await WriteCollectionBeginAsync(set.ElementType, set.Count, cancellationToken); - } - - public override async Task WriteSetEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - /* - 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 exType header is for the value and then Write the field header. - Otherwise, Write a single byte. - */ - - if (_booleanField != null) - { - // we haven't written the field header yet - await - WriteFieldBeginInternalAsync(_booleanField.Value, b ? Types.BooleanTrue : Types.BooleanFalse, - cancellationToken); - _booleanField = null; - } - else - { - // we're not part of a field, so just Write the value. - await Trans.WriteAsync(new[] {b ? Types.BooleanTrue : Types.BooleanFalse}, cancellationToken); - } - } - - public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - await Trans.WriteAsync(new[] {(byte) b}, cancellationToken); - } - - public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var bufferTuple = CreateWriteVarInt32(IntToZigzag(i16)); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); - } - - protected internal Tuple CreateWriteVarInt32(uint n) - { - // Write an i32 as a varint.Results in 1 - 5 bytes on the wire. - var i32Buf = new byte[5]; - var idx = 0; - - while (true) - { - if ((n & ~0x7F) == 0) - { - i32Buf[idx++] = (byte) n; - break; - } - - i32Buf[idx++] = (byte) ((n & 0x7F) | 0x80); - n >>= 7; - } - - return new Tuple(i32Buf, idx); - } - - public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var bufferTuple = CreateWriteVarInt32(IntToZigzag(i32)); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); - } - - protected internal Tuple CreateWriteVarInt64(ulong n) - { - // Write an i64 as a varint. Results in 1-10 bytes on the wire. - var buf = new byte[10]; - var idx = 0; - - while (true) - { - if ((n & ~(ulong) 0x7FL) == 0) - { - buf[idx++] = (byte) n; - break; - } - buf[idx++] = (byte) ((n & 0x7F) | 0x80); - n >>= 7; - } - - return new Tuple(buf, idx); - } - - public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var bufferTuple = CreateWriteVarInt64(LongToZigzag(i64)); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); - } - - public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var data = new byte[8]; - FixedLongToBytes(BitConverter.DoubleToInt64Bits(d), data, 0); - await Trans.WriteAsync(data, cancellationToken); - } - - public override async Task WriteStringAsync(string str, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var bytes = Encoding.UTF8.GetBytes(str); - - var bufferTuple = CreateWriteVarInt32((uint) bytes.Length); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); - await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); - } - - public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - var bufferTuple = CreateWriteVarInt32((uint) bytes.Length); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); - await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); - } - - public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return; - } - - if (map.Count == 0) - { - await Trans.WriteAsync(new[] {(byte) 0}, cancellationToken); - } - else - { - var bufferTuple = CreateWriteVarInt32((uint) map.Count); - await Trans.WriteAsync(bufferTuple.Item1, 0, bufferTuple.Item2, cancellationToken); - await - Trans.WriteAsync( - new[] {(byte) ((GetCompactType(map.KeyType) << 4) | GetCompactType(map.ValueType))}, - cancellationToken); - } - } - - public override async Task WriteMapEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var protocolId = (byte) await ReadByteAsync(cancellationToken); - if (protocolId != ProtocolId) - { - throw new TProtocolException($"Expected protocol id {ProtocolId:X} but got {protocolId:X}"); - } - - var versionAndType = (byte) await ReadByteAsync(cancellationToken); - var version = (byte) (versionAndType & VersionMask); - - if (version != Version) - { - throw new TProtocolException($"Expected version {Version} but got {version}"); - } - - var type = (byte) ((versionAndType >> TypeShiftAmount) & TypeBits); - var seqid = (int) await ReadVarInt32Async(cancellationToken); - var messageName = await ReadStringAsync(cancellationToken); - - return new TMessage(messageName, (TMessageType) type, seqid); - } - - public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - // some magic is here ) - - _lastField.Push(_lastFieldId); - _lastFieldId = 0; - - return AnonymousStruct; - } - - public override async Task ReadStructEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - /* - Doesn't actually consume any wire data, just removes the last field for - this struct from the field stack. - */ - - // consume the last field we Read off the wire. - _lastFieldId = _lastField.Pop(); - } - - public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) - { - // Read a field header off the wire. - var type = (byte) await ReadByteAsync(cancellationToken); - // if it's a stop, then we can return immediately, as the struct is over. - if (type == Types.Stop) - { - return Tstop; - } - - short fieldId; - // mask off the 4 MSB of the exType header. it could contain a field id delta. - var modifier = (short) ((type & 0xf0) >> 4); - if (modifier == 0) - { - fieldId = await ReadI16Async(cancellationToken); - } - else - { - fieldId = (short) (_lastFieldId + modifier); - } - - var field = new TField(string.Empty, GetTType((byte) (type & 0x0f)), fieldId); - // if this happens to be a boolean field, the value is encoded in the exType - if (IsBoolType(type)) - { - _boolValue = (byte) (type & 0x0f) == Types.BooleanTrue; - } - - // push the new field onto the field stack so we can keep the deltas going. - _lastFieldId = field.ID; - return field; - } - - public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - /* - Read a map header off the wire. If the size is zero, skip Reading the key - and value exType. This means that 0-length maps will yield TMaps without the - "correct" types. - */ - - var size = (int) await ReadVarInt32Async(cancellationToken); - var keyAndValueType = size == 0 ? (byte) 0 : (byte) await ReadByteAsync(cancellationToken); - return new TMap(GetTType((byte) (keyAndValueType >> 4)), GetTType((byte) (keyAndValueType & 0xf)), size); - } - - public override async Task ReadMapEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) - { - /* - Read a set header off the wire. If the set size is 0-14, the size will - be packed into the element exType header. If it's a longer set, the 4 MSB - of the element exType header will be 0xF, and a varint will follow with the - true size. - */ - - return new TSet(await ReadListBeginAsync(cancellationToken)); - } - - public override async Task ReadBoolAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - /* - 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. - */ - - if (_boolValue != null) - { - var result = _boolValue.Value; - _boolValue = null; - return result; - } - - return await ReadByteAsync(cancellationToken) == Types.BooleanTrue; - } - - public override async Task ReadByteAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - // Read a single byte off the wire. Nothing interesting here. - var buf = new byte[1]; - await Trans.ReadAllAsync(buf, 0, 1, cancellationToken); - return (sbyte) buf[0]; - } - - public override async Task ReadI16Async(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - return (short) ZigzagToInt(await ReadVarInt32Async(cancellationToken)); - } - - public override async Task ReadI32Async(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - return ZigzagToInt(await ReadVarInt32Async(cancellationToken)); - } - - public override async Task ReadI64Async(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - return ZigzagToLong(await ReadVarInt64Async(cancellationToken)); - } - - public override async Task ReadDoubleAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var longBits = new byte[8]; - await Trans.ReadAllAsync(longBits, 0, 8, cancellationToken); - - return BitConverter.Int64BitsToDouble(BytesToLong(longBits)); - } - - public override async Task ReadStringAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - // Reads a byte[] (via ReadBinary), and then UTF-8 decodes it. - var length = (int) await ReadVarInt32Async(cancellationToken); - - if (length == 0) - { - return string.Empty; - } - - var buf = new byte[length]; - await Trans.ReadAllAsync(buf, 0, length, cancellationToken); - - return Encoding.UTF8.GetString(buf); - } - - public override async Task ReadBinaryAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - // Read a byte[] from the wire. - var length = (int) await ReadVarInt32Async(cancellationToken); - if (length == 0) - { - return new byte[0]; - } - - var buf = new byte[length]; - await Trans.ReadAllAsync(buf, 0, length, cancellationToken); - return buf; - } - - public override async Task ReadListBeginAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - /* - Read a list header off the wire. If the list size is 0-14, the size will - be packed into the element exType header. If it's a longer list, the 4 MSB - of the element exType header will be 0xF, and a varint will follow with the - true size. - */ - - var sizeAndType = (byte) await ReadByteAsync(cancellationToken); - var size = (sizeAndType >> 4) & 0x0f; - if (size == 15) - { - size = (int) await ReadVarInt32Async(cancellationToken); - } - - var type = GetTType(sizeAndType); - return new TList(type, size); - } - - public override async Task ReadListEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task ReadSetEndAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - private static byte GetCompactType(TType ttype) - { - // Given a TType value, find the appropriate TCompactProtocol.Types constant. - return TTypeToCompactType[(int) ttype]; - } - - - private async Task ReadVarInt32Async(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - /* - 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. - */ - - uint result = 0; - var shift = 0; - - while (true) - { - var b = (byte) await ReadByteAsync(cancellationToken); - result |= (uint) (b & 0x7f) << shift; - if ((b & 0x80) != 0x80) - { - break; - } - shift += 7; - } - - return result; - } - - private async Task ReadVarInt64Async(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - /* - 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. - */ - - var shift = 0; - ulong result = 0; - while (true) - { - var b = (byte) await ReadByteAsync(cancellationToken); - result |= (ulong) (b & 0x7f) << shift; - if ((b & 0x80) != 0x80) - { - break; - } - shift += 7; - } - - return result; - } - - private static int ZigzagToInt(uint n) - { - return (int) (n >> 1) ^ -(int) (n & 1); - } - - private static long ZigzagToLong(ulong n) - { - return (long) (n >> 1) ^ -(long) (n & 1); - } - - private static long BytesToLong(byte[] bytes) - { - /* - 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. - */ - - 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); - } - - private static bool IsBoolType(byte b) - { - var lowerNibble = b & 0x0f; - return (lowerNibble == Types.BooleanTrue) || (lowerNibble == Types.BooleanFalse); - } - - private static TType GetTType(byte type) - { - // Given a TCompactProtocol.Types constant, convert it to its corresponding TType value. - switch ((byte) (type & 0x0f)) - { - case Types.Stop: - return TType.Stop; - case Types.BooleanFalse: - case Types.BooleanTrue: - 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 exType: {(byte) (type & 0x0f)}"); - } - } - - private static ulong LongToZigzag(long n) - { - // Convert l into a zigzag long. This allows negative numbers to be represented compactly as a varint - return (ulong) (n << 1) ^ (ulong) (n >> 63); - } - - private static uint IntToZigzag(int n) - { - // Convert n into a zigzag int. This allows negative numbers to be represented compactly as a varint - return (uint) (n << 1) ^ (uint) (n >> 31); - } - - private static void FixedLongToBytes(long n, byte[] buf, int off) - { - // Convert a long into little-endian bytes in buf starting at off and going until off+7. - 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); - } - - public class Factory : ITProtocolFactory - { - public TProtocol GetProtocol(TClientTransport trans) - { - return new TCompactProtocol(trans); - } - } - - /// - /// All of the on-wire exType codes. - /// - private static class Types - { - public const byte Stop = 0x00; - public const byte BooleanTrue = 0x01; - public const byte BooleanFalse = 0x02; - public const byte Byte = 0x03; - public const byte I16 = 0x04; - public const byte I32 = 0x05; - public const byte I64 = 0x06; - public const byte Double = 0x07; - public const byte Binary = 0x08; - public const byte List = 0x09; - public const byte Set = 0x0A; - public const byte Map = 0x0B; - public const byte Struct = 0x0C; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/TJSONProtocol.cs b/lib/netcore/Thrift/Protocols/TJSONProtocol.cs deleted file mode 100644 index 6d33f029e57..00000000000 --- a/lib/netcore/Thrift/Protocols/TJSONProtocol.cs +++ /dev/null @@ -1,981 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols.Entities; -using Thrift.Protocols.Utilities; -using Thrift.Transports; - -namespace Thrift.Protocols -{ - /// - /// 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. - /// Adapted from the Java version. - /// - // ReSharper disable once InconsistentNaming - public class TJsonProtocol : TProtocol - { - private const long Version = 1; - - // Temporary buffer used by several methods - private readonly byte[] _tempBuffer = new byte[4]; - - // Current context that we are in - protected JSONBaseContext Context; - - // Stack of nested contexts that we may be in - protected Stack ContextStack = new Stack(); - - // Reader that manages a 1-byte buffer - protected LookaheadReader Reader; - - // Default encoding - protected Encoding Utf8Encoding = Encoding.UTF8; - - /// - /// TJsonProtocol Constructor - /// - public TJsonProtocol(TClientTransport trans) - : base(trans) - { - Context = new JSONBaseContext(this); - Reader = new LookaheadReader(this); - } - - /// - /// Push a new JSON context onto the stack. - /// - protected void PushContext(JSONBaseContext c) - { - ContextStack.Push(Context); - Context = c; - } - - /// - /// Pop the last JSON context off the stack - /// - protected void PopContext() - { - Context = ContextStack.Pop(); - } - - /// - /// 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 async Task ReadJsonSyntaxCharAsync(byte[] bytes, CancellationToken cancellationToken) - { - var ch = await Reader.ReadAsync(cancellationToken); - if (ch != bytes[0]) - { - throw new TProtocolException(TProtocolException.INVALID_DATA, $"Unexpected character: {(char) ch}"); - } - } - - /// - /// Write the bytes in array buf as a JSON characters, escaping as needed - /// - private async Task WriteJsonStringAsync(byte[] bytes, CancellationToken cancellationToken) - { - await Context.WriteAsync(cancellationToken); - await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); - - var len = bytes.Length; - for (var i = 0; i < len; i++) - { - if ((bytes[i] & 0x00FF) >= 0x30) - { - if (bytes[i] == TJSONProtocolConstants.Backslash[0]) - { - await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); - await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); - } - else - { - await Trans.WriteAsync(bytes.ToArray(), i, 1, cancellationToken); - } - } - else - { - _tempBuffer[0] = TJSONProtocolConstants.JsonCharTable[bytes[i]]; - if (_tempBuffer[0] == 1) - { - await Trans.WriteAsync(bytes, i, 1, cancellationToken); - } - else if (_tempBuffer[0] > 1) - { - await Trans.WriteAsync(TJSONProtocolConstants.Backslash, cancellationToken); - await Trans.WriteAsync(_tempBuffer, 0, 1, cancellationToken); - } - else - { - await Trans.WriteAsync(TJSONProtocolConstants.EscSequences, cancellationToken); - _tempBuffer[0] = TJSONProtocolHelper.ToHexChar((byte) (bytes[i] >> 4)); - _tempBuffer[1] = TJSONProtocolHelper.ToHexChar(bytes[i]); - await Trans.WriteAsync(_tempBuffer, 0, 2, cancellationToken); - } - } - } - await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); - } - - /// - /// 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 async Task WriteJsonIntegerAsync(long num, CancellationToken cancellationToken) - { - await Context.WriteAsync(cancellationToken); - var str = num.ToString(); - - var escapeNum = Context.EscapeNumbers(); - if (escapeNum) - { - await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); - } - - var bytes = Utf8Encoding.GetBytes(str); - await Trans.WriteAsync(bytes, cancellationToken); - - if (escapeNum) - { - await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); - } - } - - /// - /// 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 async Task WriteJsonDoubleAsync(double num, CancellationToken cancellationToken) - { - await Context.WriteAsync(cancellationToken); - var str = num.ToString("G17", CultureInfo.InvariantCulture); - var special = false; - - switch (str[0]) - { - case 'N': // NaN - case 'I': // Infinity - special = true; - break; - case '-': - if (str[1] == 'I') - { - // -Infinity - special = true; - } - break; - } - - var escapeNum = special || Context.EscapeNumbers(); - - if (escapeNum) - { - await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); - } - - await Trans.WriteAsync(Utf8Encoding.GetBytes(str), cancellationToken); - - if (escapeNum) - { - await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); - } - } - - /// - /// Write out contents of byte array b as a JSON string with base-64 encoded - /// data - /// - private async Task WriteJsonBase64Async(byte[] bytes, CancellationToken cancellationToken) - { - await Context.WriteAsync(cancellationToken); - await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); - - var len = bytes.Length; - var off = 0; - - while (len >= 3) - { - // Encode 3 bytes at a time - TBase64Helper.Encode(bytes, off, 3, _tempBuffer, 0); - await Trans.WriteAsync(_tempBuffer, 0, 4, cancellationToken); - off += 3; - len -= 3; - } - - if (len > 0) - { - // Encode remainder - TBase64Helper.Encode(bytes, off, len, _tempBuffer, 0); - await Trans.WriteAsync(_tempBuffer, 0, len + 1, cancellationToken); - } - - await Trans.WriteAsync(TJSONProtocolConstants.Quote, cancellationToken); - } - - private async Task WriteJsonObjectStartAsync(CancellationToken cancellationToken) - { - await Context.WriteAsync(cancellationToken); - await Trans.WriteAsync(TJSONProtocolConstants.LeftBrace, cancellationToken); - PushContext(new JSONPairContext(this)); - } - - private async Task WriteJsonObjectEndAsync(CancellationToken cancellationToken) - { - PopContext(); - await Trans.WriteAsync(TJSONProtocolConstants.RightBrace, cancellationToken); - } - - private async Task WriteJsonArrayStartAsync(CancellationToken cancellationToken) - { - await Context.WriteAsync(cancellationToken); - await Trans.WriteAsync(TJSONProtocolConstants.LeftBracket, cancellationToken); - PushContext(new JSONListContext(this)); - } - - private async Task WriteJsonArrayEndAsync(CancellationToken cancellationToken) - { - PopContext(); - await Trans.WriteAsync(TJSONProtocolConstants.RightBracket, cancellationToken); - } - - public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) - { - await WriteJsonArrayStartAsync(cancellationToken); - await WriteJsonIntegerAsync(Version, cancellationToken); - - var b = Utf8Encoding.GetBytes(message.Name); - await WriteJsonStringAsync(b, cancellationToken); - - await WriteJsonIntegerAsync((long) message.Type, cancellationToken); - await WriteJsonIntegerAsync(message.SeqID, cancellationToken); - } - - public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) - { - await WriteJsonArrayEndAsync(cancellationToken); - } - - public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) - { - await WriteJsonObjectStartAsync(cancellationToken); - } - - public override async Task WriteStructEndAsync(CancellationToken cancellationToken) - { - await WriteJsonObjectEndAsync(cancellationToken); - } - - public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) - { - await WriteJsonIntegerAsync(field.ID, cancellationToken); - await WriteJsonObjectStartAsync(cancellationToken); - await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(field.Type), cancellationToken); - } - - public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) - { - await WriteJsonObjectEndAsync(cancellationToken); - } - - public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) - { - await WriteJsonArrayStartAsync(cancellationToken); - await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.KeyType), cancellationToken); - await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(map.ValueType), cancellationToken); - await WriteJsonIntegerAsync(map.Count, cancellationToken); - await WriteJsonObjectStartAsync(cancellationToken); - } - - public override async Task WriteMapEndAsync(CancellationToken cancellationToken) - { - await WriteJsonObjectEndAsync(cancellationToken); - await WriteJsonArrayEndAsync(cancellationToken); - } - - public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) - { - await WriteJsonArrayStartAsync(cancellationToken); - await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(list.ElementType), cancellationToken); - await WriteJsonIntegerAsync(list.Count, cancellationToken); - } - - public override async Task WriteListEndAsync(CancellationToken cancellationToken) - { - await WriteJsonArrayEndAsync(cancellationToken); - } - - public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) - { - await WriteJsonArrayStartAsync(cancellationToken); - await WriteJsonStringAsync(TJSONProtocolHelper.GetTypeNameForTypeId(set.ElementType), cancellationToken); - await WriteJsonIntegerAsync(set.Count, cancellationToken); - } - - public override async Task WriteSetEndAsync(CancellationToken cancellationToken) - { - await WriteJsonArrayEndAsync(cancellationToken); - } - - public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) - { - await WriteJsonIntegerAsync(b ? 1 : 0, cancellationToken); - } - - public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) - { - await WriteJsonIntegerAsync(b, cancellationToken); - } - - public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) - { - await WriteJsonIntegerAsync(i16, cancellationToken); - } - - public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) - { - await WriteJsonIntegerAsync(i32, cancellationToken); - } - - public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) - { - await WriteJsonIntegerAsync(i64, cancellationToken); - } - - public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) - { - await WriteJsonDoubleAsync(d, cancellationToken); - } - - public override async Task WriteStringAsync(string s, CancellationToken cancellationToken) - { - var b = Utf8Encoding.GetBytes(s); - await WriteJsonStringAsync(b, cancellationToken); - } - - public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) - { - await WriteJsonBase64Async(bytes, cancellationToken); - } - - /// - /// Read in a JSON string, unescaping as appropriate.. Skip Reading from the - /// context if skipContext is true. - /// - private async Task ReadJsonStringAsync(bool skipContext, CancellationToken cancellationToken) - { - using (var buffer = new MemoryStream()) - { - var codeunits = new List(); - - - if (!skipContext) - { - await Context.ReadAsync(cancellationToken); - } - - await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); - - while (true) - { - var ch = await Reader.ReadAsync(cancellationToken); - if (ch == TJSONProtocolConstants.Quote[0]) - { - break; - } - - // escaped? - if (ch != TJSONProtocolConstants.EscSequences[0]) - { - await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken); - continue; - } - - // distinguish between \uXXXX and \? - ch = await Reader.ReadAsync(cancellationToken); - if (ch != TJSONProtocolConstants.EscSequences[1]) // control chars like \n - { - var off = Array.IndexOf(TJSONProtocolConstants.EscapeChars, (char) ch); - if (off == -1) - { - throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected control char"); - } - ch = TJSONProtocolConstants.EscapeCharValues[off]; - await buffer.WriteAsync(new[] {ch}, 0, 1, cancellationToken); - continue; - } - - // it's \uXXXX - await Trans.ReadAllAsync(_tempBuffer, 0, 4, cancellationToken); - - var wch = (short) ((TJSONProtocolHelper.ToHexVal(_tempBuffer[0]) << 12) + - (TJSONProtocolHelper.ToHexVal(_tempBuffer[1]) << 8) + - (TJSONProtocolHelper.ToHexVal(_tempBuffer[2]) << 4) + - TJSONProtocolHelper.ToHexVal(_tempBuffer[3])); - - if (char.IsHighSurrogate((char) wch)) - { - if (codeunits.Count > 0) - { - throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); - } - codeunits.Add((char) wch); - } - else if (char.IsLowSurrogate((char) wch)) - { - if (codeunits.Count == 0) - { - throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected high surrogate char"); - } - - codeunits.Add((char) wch); - var tmp = Utf8Encoding.GetBytes(codeunits.ToArray()); - await buffer.WriteAsync(tmp, 0, tmp.Length, cancellationToken); - codeunits.Clear(); - } - else - { - var tmp = Utf8Encoding.GetBytes(new[] {(char) wch}); - await buffer.WriteAsync(tmp, 0, tmp.Length, cancellationToken); - } - } - - if (codeunits.Count > 0) - { - throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected low surrogate char"); - } - - return buffer.ToArray(); - } - } - - /// - /// 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 async Task ReadJsonNumericCharsAsync(CancellationToken cancellationToken) - { - var strbld = new StringBuilder(); - while (true) - { - //TODO: workaround for primitive types with TJsonProtocol, think - how to rewrite into more easy form without exceptions - try - { - var ch = await Reader.PeekAsync(cancellationToken); - if (!TJSONProtocolHelper.IsJsonNumeric(ch)) - { - break; - } - var c = (char)await Reader.ReadAsync(cancellationToken); - strbld.Append(c); - } - catch (TTransportException) - { - break; - } - } - return strbld.ToString(); - } - - /// - /// Read in a JSON number. If the context dictates, Read in enclosing quotes. - /// - private async Task ReadJsonIntegerAsync(CancellationToken cancellationToken) - { - await Context.ReadAsync(cancellationToken); - if (Context.EscapeNumbers()) - { - await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); - } - - var str = await ReadJsonNumericCharsAsync(cancellationToken); - if (Context.EscapeNumbers()) - { - await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); - } - - try - { - return long.Parse(str); - } - catch (FormatException) - { - 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 async Task ReadJsonDoubleAsync(CancellationToken cancellationToken) - { - await Context.ReadAsync(cancellationToken); - if (await Reader.PeekAsync(cancellationToken) == TJSONProtocolConstants.Quote[0]) - { - var arr = await ReadJsonStringAsync(true, cancellationToken); - var dub = double.Parse(Utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture); - - if (!Context.EscapeNumbers() && !double.IsNaN(dub) && !double.IsInfinity(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; - } - - if (Context.EscapeNumbers()) - { - // This will throw - we should have had a quote if escapeNum == true - await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Quote, cancellationToken); - } - - try - { - return double.Parse(await ReadJsonNumericCharsAsync(cancellationToken), CultureInfo.InvariantCulture); - } - catch (FormatException) - { - 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 async Task ReadJsonBase64Async(CancellationToken cancellationToken) - { - var b = await ReadJsonStringAsync(false, cancellationToken); - var len = b.Length; - var off = 0; - var size = 0; - - // reduce len to ignore fill bytes - while ((len > 0) && (b[len - 1] == '=')) - { - --len; - } - - // read & decode full byte triplets = 4 source bytes - while (len > 4) - { - // Decode 4 bytes at a time - TBase64Helper.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 exType) - if (len > 1) - { - // Decode remainder - TBase64Helper.Decode(b, off, len, b, size); // NB: decoded in place - size += len - 1; - } - - // Sadly we must copy the byte[] (any way around this?) - var result = new byte[size]; - Array.Copy(b, 0, result, 0, size); - return result; - } - - private async Task ReadJsonObjectStartAsync(CancellationToken cancellationToken) - { - await Context.ReadAsync(cancellationToken); - await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBrace, cancellationToken); - PushContext(new JSONPairContext(this)); - } - - private async Task ReadJsonObjectEndAsync(CancellationToken cancellationToken) - { - await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBrace, cancellationToken); - PopContext(); - } - - private async Task ReadJsonArrayStartAsync(CancellationToken cancellationToken) - { - await Context.ReadAsync(cancellationToken); - await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.LeftBracket, cancellationToken); - PushContext(new JSONListContext(this)); - } - - private async Task ReadJsonArrayEndAsync(CancellationToken cancellationToken) - { - await ReadJsonSyntaxCharAsync(TJSONProtocolConstants.RightBracket, cancellationToken); - PopContext(); - } - - public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) - { - var message = new TMessage(); - await ReadJsonArrayStartAsync(cancellationToken); - if (await ReadJsonIntegerAsync(cancellationToken) != Version) - { - throw new TProtocolException(TProtocolException.BAD_VERSION, "Message contained bad version."); - } - - var buf = await ReadJsonStringAsync(false, cancellationToken); - message.Name = Utf8Encoding.GetString(buf, 0, buf.Length); - message.Type = (TMessageType) await ReadJsonIntegerAsync(cancellationToken); - message.SeqID = (int) await ReadJsonIntegerAsync(cancellationToken); - return message; - } - - public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) - { - await ReadJsonArrayEndAsync(cancellationToken); - } - - public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) - { - await ReadJsonObjectStartAsync(cancellationToken); - return new TStruct(); - } - - public override async Task ReadStructEndAsync(CancellationToken cancellationToken) - { - await ReadJsonObjectEndAsync(cancellationToken); - } - - public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) - { - var field = new TField(); - var ch = await Reader.PeekAsync(cancellationToken); - if (ch == TJSONProtocolConstants.RightBrace[0]) - { - field.Type = TType.Stop; - } - else - { - field.ID = (short) await ReadJsonIntegerAsync(cancellationToken); - await ReadJsonObjectStartAsync(cancellationToken); - field.Type = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); - } - return field; - } - - public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) - { - await ReadJsonObjectEndAsync(cancellationToken); - } - - public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) - { - var map = new TMap(); - await ReadJsonArrayStartAsync(cancellationToken); - map.KeyType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); - map.ValueType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); - map.Count = (int) await ReadJsonIntegerAsync(cancellationToken); - await ReadJsonObjectStartAsync(cancellationToken); - return map; - } - - public override async Task ReadMapEndAsync(CancellationToken cancellationToken) - { - await ReadJsonObjectEndAsync(cancellationToken); - await ReadJsonArrayEndAsync(cancellationToken); - } - - public override async Task ReadListBeginAsync(CancellationToken cancellationToken) - { - var list = new TList(); - await ReadJsonArrayStartAsync(cancellationToken); - list.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); - list.Count = (int) await ReadJsonIntegerAsync(cancellationToken); - return list; - } - - public override async Task ReadListEndAsync(CancellationToken cancellationToken) - { - await ReadJsonArrayEndAsync(cancellationToken); - } - - public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) - { - var set = new TSet(); - await ReadJsonArrayStartAsync(cancellationToken); - set.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); - set.Count = (int) await ReadJsonIntegerAsync(cancellationToken); - return set; - } - - public override async Task ReadSetEndAsync(CancellationToken cancellationToken) - { - await ReadJsonArrayEndAsync(cancellationToken); - } - - public override async Task ReadBoolAsync(CancellationToken cancellationToken) - { - return await ReadJsonIntegerAsync(cancellationToken) != 0; - } - - public override async Task ReadByteAsync(CancellationToken cancellationToken) - { - return (sbyte) await ReadJsonIntegerAsync(cancellationToken); - } - - public override async Task ReadI16Async(CancellationToken cancellationToken) - { - return (short) await ReadJsonIntegerAsync(cancellationToken); - } - - public override async Task ReadI32Async(CancellationToken cancellationToken) - { - return (int) await ReadJsonIntegerAsync(cancellationToken); - } - - public override async Task ReadI64Async(CancellationToken cancellationToken) - { - return await ReadJsonIntegerAsync(cancellationToken); - } - - public override async Task ReadDoubleAsync(CancellationToken cancellationToken) - { - return await ReadJsonDoubleAsync(cancellationToken); - } - - public override async Task ReadStringAsync(CancellationToken cancellationToken) - { - var buf = await ReadJsonStringAsync(false, cancellationToken); - return Utf8Encoding.GetString(buf, 0, buf.Length); - } - - public override async Task ReadBinaryAsync(CancellationToken cancellationToken) - { - return await ReadJsonBase64Async(cancellationToken); - } - - /// - /// Factory for JSON protocol objects - /// - public class Factory : ITProtocolFactory - { - public TProtocol GetProtocol(TClientTransport trans) - { - return new TJsonProtocol(trans); - } - } - - /// - /// Base class for tracking JSON contexts that may require - /// inserting/Reading additional JSON syntax characters - /// This base context does nothing. - /// - protected class JSONBaseContext - { - protected TJsonProtocol Proto; - - public JSONBaseContext(TJsonProtocol proto) - { - Proto = proto; - } - - public virtual async Task WriteAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public virtual async Task ReadAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public virtual bool EscapeNumbers() - { - return false; - } - } - - /// - /// Context for JSON lists. Will insert/Read commas before each item except - /// for the first one - /// - protected class JSONListContext : JSONBaseContext - { - private bool _first = true; - - public JSONListContext(TJsonProtocol protocol) - : base(protocol) - { - } - - public override async Task WriteAsync(CancellationToken cancellationToken) - { - if (_first) - { - _first = false; - } - else - { - await Proto.Trans.WriteAsync(TJSONProtocolConstants.Comma, cancellationToken); - } - } - - public override async Task ReadAsync(CancellationToken cancellationToken) - { - if (_first) - { - _first = false; - } - else - { - await Proto.ReadJsonSyntaxCharAsync(TJSONProtocolConstants.Comma, cancellationToken); - } - } - } - - /// - /// 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). - /// - // ReSharper disable once InconsistentNaming - protected class JSONPairContext : JSONBaseContext - { - private bool _colon = true; - - private bool _first = true; - - public JSONPairContext(TJsonProtocol proto) - : base(proto) - { - } - - public override async Task WriteAsync(CancellationToken cancellationToken) - { - if (_first) - { - _first = false; - _colon = true; - } - else - { - await Proto.Trans.WriteAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken); - _colon = !_colon; - } - } - - public override async Task ReadAsync(CancellationToken cancellationToken) - { - if (_first) - { - _first = false; - _colon = true; - } - else - { - await Proto.ReadJsonSyntaxCharAsync(_colon ? TJSONProtocolConstants.Colon : TJSONProtocolConstants.Comma, cancellationToken); - _colon = !_colon; - } - } - - public override bool EscapeNumbers() - { - return _colon; - } - } - - /// - /// Holds up to one byte from the transport - /// - protected class LookaheadReader - { - private readonly byte[] _data = new byte[1]; - - private bool _hasData; - protected TJsonProtocol Proto; - - public LookaheadReader(TJsonProtocol proto) - { - Proto = proto; - } - - /// - /// 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. - /// - public async Task ReadAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - if (_hasData) - { - _hasData = false; - } - else - { - // find more easy way to avoid exception on reading primitive types - await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken); - } - return _data[0]; - } - - /// - /// Return the next byte to be Read without consuming, filling the data - /// buffer if it has not been filled alReady. - /// - public async Task PeekAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - if (!_hasData) - { - // find more easy way to avoid exception on reading primitive types - await Proto.Trans.ReadAllAsync(_data, 0, 1, cancellationToken); - } - _hasData = true; - return _data[0]; - } - } - } -} diff --git a/lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs b/lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs deleted file mode 100644 index 367e4e64486..00000000000 --- a/lib/netcore/Thrift/Protocols/TMultiplexedProtocol.cs +++ /dev/null @@ -1,91 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols.Entities; - -namespace Thrift.Protocols -{ - /** - * 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 TO BE USED BY SERVERS. - * On the server, use TMultiplexedProcessor to handle requests from a multiplexing client. - * - * This example uses a single socket transport to invoke two services: - * - * TSocketClientTransport transport = new TSocketClientTransport("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()); - * - */ - - //TODO: implementation of TProtocol - - // ReSharper disable once InconsistentNaming - public class TMultiplexedProtocol : TProtocolDecorator - { - /** Used to delimit the service name from the function name */ - public const string Separator = ":"; - - private readonly string _serviceName; - - /** - * 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. - * - * Args: - * protocol Your communication protocol of choice, e.g. TBinaryProtocol - * serviceName The service name of the service communicating via this protocol. - */ - - public TMultiplexedProtocol(TProtocol protocol, string serviceName) - : base(protocol) - { - _serviceName = serviceName; - } - - public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) - { - switch (message.Type) - { - case TMessageType.Call: - case TMessageType.Oneway: - await base.WriteMessageBeginAsync(new TMessage($"{_serviceName}{Separator}{message.Name}", message.Type, message.SeqID), cancellationToken); - break; - default: - await base.WriteMessageBeginAsync(message, cancellationToken); - break; - } - } - } -} diff --git a/lib/netcore/Thrift/Protocols/TProtocol.cs b/lib/netcore/Thrift/Protocols/TProtocol.cs deleted file mode 100644 index 91e009d639b..00000000000 --- a/lib/netcore/Thrift/Protocols/TProtocol.cs +++ /dev/null @@ -1,376 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols.Entities; -using Thrift.Transports; - -namespace Thrift.Protocols -{ - // ReSharper disable once InconsistentNaming - public abstract class TProtocol : IDisposable - { - public const int DefaultRecursionDepth = 64; - private bool _isDisposed; - protected int RecursionDepth; - - protected TClientTransport Trans; - - protected TProtocol(TClientTransport trans) - { - Trans = trans; - RecursionLimit = DefaultRecursionDepth; - RecursionDepth = 0; - } - - public TClientTransport Transport => Trans; - - protected int RecursionLimit { get; set; } - - public void Dispose() - { - Dispose(true); - } - - public void IncrementRecursionDepth() - { - if (RecursionDepth < RecursionLimit) - { - ++RecursionDepth; - } - else - { - throw new TProtocolException(TProtocolException.DEPTH_LIMIT, "Depth limit exceeded"); - } - } - - public void DecrementRecursionDepth() - { - --RecursionDepth; - } - - protected virtual void Dispose(bool disposing) - { - if (!_isDisposed) - { - if (disposing) - { - (Trans as IDisposable)?.Dispose(); - } - } - _isDisposed = true; - } - - public virtual async Task WriteMessageBeginAsync(TMessage message) - { - await WriteMessageBeginAsync(message, CancellationToken.None); - } - - public abstract Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken); - - public virtual async Task WriteMessageEndAsync() - { - await WriteMessageEndAsync(CancellationToken.None); - } - - public abstract Task WriteMessageEndAsync(CancellationToken cancellationToken); - - public virtual async Task WriteStructBeginAsync(TStruct @struct) - { - await WriteStructBeginAsync(@struct, CancellationToken.None); - } - - public abstract Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken); - - public virtual async Task WriteStructEndAsync() - { - await WriteStructEndAsync(CancellationToken.None); - } - - public abstract Task WriteStructEndAsync(CancellationToken cancellationToken); - - public virtual async Task WriteFieldBeginAsync(TField field) - { - await WriteFieldBeginAsync(field, CancellationToken.None); - } - - public abstract Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken); - - public virtual async Task WriteFieldEndAsync() - { - await WriteFieldEndAsync(CancellationToken.None); - } - - public abstract Task WriteFieldEndAsync(CancellationToken cancellationToken); - - public virtual async Task WriteFieldStopAsync() - { - await WriteFieldStopAsync(CancellationToken.None); - } - - public abstract Task WriteFieldStopAsync(CancellationToken cancellationToken); - - public virtual async Task WriteMapBeginAsync(TMap map) - { - await WriteMapBeginAsync(map, CancellationToken.None); - } - - public abstract Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken); - - public virtual async Task WriteMapEndAsync() - { - await WriteMapEndAsync(CancellationToken.None); - } - - public abstract Task WriteMapEndAsync(CancellationToken cancellationToken); - - public virtual async Task WriteListBeginAsync(TList list) - { - await WriteListBeginAsync(list, CancellationToken.None); - } - - public abstract Task WriteListBeginAsync(TList list, CancellationToken cancellationToken); - - public virtual async Task WriteListEndAsync() - { - await WriteListEndAsync(CancellationToken.None); - } - - public abstract Task WriteListEndAsync(CancellationToken cancellationToken); - - public virtual async Task WriteSetBeginAsync(TSet set) - { - await WriteSetBeginAsync(set, CancellationToken.None); - } - - public abstract Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken); - - public virtual async Task WriteSetEndAsync() - { - await WriteSetEndAsync(CancellationToken.None); - } - - public abstract Task WriteSetEndAsync(CancellationToken cancellationToken); - - public virtual async Task WriteBoolAsync(bool b) - { - await WriteBoolAsync(b, CancellationToken.None); - } - - public abstract Task WriteBoolAsync(bool b, CancellationToken cancellationToken); - - public virtual async Task WriteByteAsync(sbyte b) - { - await WriteByteAsync(b, CancellationToken.None); - } - - public abstract Task WriteByteAsync(sbyte b, CancellationToken cancellationToken); - - public virtual async Task WriteI16Async(short i16) - { - await WriteI16Async(i16, CancellationToken.None); - } - - public abstract Task WriteI16Async(short i16, CancellationToken cancellationToken); - - public virtual async Task WriteI32Async(int i32) - { - await WriteI32Async(i32, CancellationToken.None); - } - - public abstract Task WriteI32Async(int i32, CancellationToken cancellationToken); - - public virtual async Task WriteI64Async(long i64) - { - await WriteI64Async(i64, CancellationToken.None); - } - - public abstract Task WriteI64Async(long i64, CancellationToken cancellationToken); - - public virtual async Task WriteDoubleAsync(double d) - { - await WriteDoubleAsync(d, CancellationToken.None); - } - - public abstract Task WriteDoubleAsync(double d, CancellationToken cancellationToken); - - public virtual async Task WriteStringAsync(string s) - { - await WriteStringAsync(s, CancellationToken.None); - } - - public virtual async Task WriteStringAsync(string s, CancellationToken cancellationToken) - { - var bytes = Encoding.UTF8.GetBytes(s); - await WriteBinaryAsync(bytes, cancellationToken); - } - - public virtual async Task WriteBinaryAsync(byte[] bytes) - { - await WriteBinaryAsync(bytes, CancellationToken.None); - } - - public abstract Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken); - - public virtual async Task ReadMessageBeginAsync() - { - return await ReadMessageBeginAsync(CancellationToken.None); - } - - public abstract Task ReadMessageBeginAsync(CancellationToken cancellationToken); - - public virtual async Task ReadMessageEndAsync() - { - await ReadMessageEndAsync(CancellationToken.None); - } - - public abstract Task ReadMessageEndAsync(CancellationToken cancellationToken); - - public virtual async Task ReadStructBeginAsync() - { - return await ReadStructBeginAsync(CancellationToken.None); - } - - public abstract Task ReadStructBeginAsync(CancellationToken cancellationToken); - - public virtual async Task ReadStructEndAsync() - { - await ReadStructEndAsync(CancellationToken.None); - } - - public abstract Task ReadStructEndAsync(CancellationToken cancellationToken); - - public virtual async Task ReadFieldBeginAsync() - { - return await ReadFieldBeginAsync(CancellationToken.None); - } - - public abstract Task ReadFieldBeginAsync(CancellationToken cancellationToken); - - public virtual async Task ReadFieldEndAsync() - { - await ReadFieldEndAsync(CancellationToken.None); - } - - public abstract Task ReadFieldEndAsync(CancellationToken cancellationToken); - - public virtual async Task ReadMapBeginAsync() - { - return await ReadMapBeginAsync(CancellationToken.None); - } - - public abstract Task ReadMapBeginAsync(CancellationToken cancellationToken); - - public virtual async Task ReadMapEndAsync() - { - await ReadMapEndAsync(CancellationToken.None); - } - - public abstract Task ReadMapEndAsync(CancellationToken cancellationToken); - - public virtual async Task ReadListBeginAsync() - { - return await ReadListBeginAsync(CancellationToken.None); - } - - public abstract Task ReadListBeginAsync(CancellationToken cancellationToken); - - public virtual async Task ReadListEndAsync() - { - await ReadListEndAsync(CancellationToken.None); - } - - public abstract Task ReadListEndAsync(CancellationToken cancellationToken); - - public virtual async Task ReadSetBeginAsync() - { - return await ReadSetBeginAsync(CancellationToken.None); - } - - public abstract Task ReadSetBeginAsync(CancellationToken cancellationToken); - - public virtual async Task ReadSetEndAsync() - { - await ReadSetEndAsync(CancellationToken.None); - } - - public abstract Task ReadSetEndAsync(CancellationToken cancellationToken); - - public virtual async Task ReadBoolAsync() - { - return await ReadBoolAsync(CancellationToken.None); - } - - public abstract Task ReadBoolAsync(CancellationToken cancellationToken); - - public virtual async Task ReadByteAsync() - { - return await ReadByteAsync(CancellationToken.None); - } - - public abstract Task ReadByteAsync(CancellationToken cancellationToken); - - public virtual async Task ReadI16Async() - { - return await ReadI16Async(CancellationToken.None); - } - - public abstract Task ReadI16Async(CancellationToken cancellationToken); - - public virtual async Task ReadI32Async() - { - return await ReadI32Async(CancellationToken.None); - } - - public abstract Task ReadI32Async(CancellationToken cancellationToken); - - public virtual async Task ReadI64Async() - { - return await ReadI64Async(CancellationToken.None); - } - - public abstract Task ReadI64Async(CancellationToken cancellationToken); - - public virtual async Task ReadDoubleAsync() - { - return await ReadDoubleAsync(CancellationToken.None); - } - - public abstract Task ReadDoubleAsync(CancellationToken cancellationToken); - - public virtual async Task ReadStringAsync() - { - return await ReadStringAsync(CancellationToken.None); - } - - public virtual async Task ReadStringAsync(CancellationToken cancellationToken) - { - var buf = await ReadBinaryAsync(cancellationToken); - return Encoding.UTF8.GetString(buf, 0, buf.Length); - } - - public virtual async Task ReadBinaryAsync() - { - return await ReadBinaryAsync(CancellationToken.None); - } - - public abstract Task ReadBinaryAsync(CancellationToken cancellationToken); - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/TProtocolDecorator.cs b/lib/netcore/Thrift/Protocols/TProtocolDecorator.cs deleted file mode 100644 index 3222754a871..00000000000 --- a/lib/netcore/Thrift/Protocols/TProtocolDecorator.cs +++ /dev/null @@ -1,247 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols.Entities; - -namespace Thrift.Protocols -{ - // ReSharper disable once InconsistentNaming - /// - /// 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. - /// - public abstract class TProtocolDecorator : TProtocol - { - private readonly TProtocol _wrappedProtocol; - - protected TProtocolDecorator(TProtocol protocol) - : base(protocol.Transport) - { - _wrappedProtocol = protocol ?? throw new ArgumentNullException(nameof(protocol)); - } - - public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteMessageBeginAsync(message, cancellationToken); - } - - public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteMessageEndAsync(cancellationToken); - } - - public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteStructBeginAsync(@struct, cancellationToken); - } - - public override async Task WriteStructEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteStructEndAsync(cancellationToken); - } - - public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteFieldBeginAsync(field, cancellationToken); - } - - public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteFieldEndAsync(cancellationToken); - } - - public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteFieldStopAsync(cancellationToken); - } - - public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteMapBeginAsync(map, cancellationToken); - } - - public override async Task WriteMapEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteMapEndAsync(cancellationToken); - } - - public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteListBeginAsync(list, cancellationToken); - } - - public override async Task WriteListEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteListEndAsync(cancellationToken); - } - - public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteSetBeginAsync(set, cancellationToken); - } - - public override async Task WriteSetEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteSetEndAsync(cancellationToken); - } - - public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteBoolAsync(b, cancellationToken); - } - - public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteByteAsync(b, cancellationToken); - } - - public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteI16Async(i16, cancellationToken); - } - - public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteI32Async(i32, cancellationToken); - } - - public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteI64Async(i64, cancellationToken); - } - - public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteDoubleAsync(d, cancellationToken); - } - - public override async Task WriteStringAsync(string s, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteStringAsync(s, cancellationToken); - } - - public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) - { - await _wrappedProtocol.WriteBinaryAsync(bytes, cancellationToken); - } - - public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadMessageBeginAsync(cancellationToken); - } - - public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.ReadMessageEndAsync(cancellationToken); - } - - public override async Task ReadStructBeginAsync(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadStructBeginAsync(cancellationToken); - } - - public override async Task ReadStructEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.ReadStructEndAsync(cancellationToken); - } - - public override async Task ReadFieldBeginAsync(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadFieldBeginAsync(cancellationToken); - } - - public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.ReadFieldEndAsync(cancellationToken); - } - - public override async Task ReadMapBeginAsync(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadMapBeginAsync(cancellationToken); - } - - public override async Task ReadMapEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.ReadMapEndAsync(cancellationToken); - } - - public override async Task ReadListBeginAsync(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadListBeginAsync(cancellationToken); - } - - public override async Task ReadListEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.ReadListEndAsync(cancellationToken); - } - - public override async Task ReadSetBeginAsync(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadSetBeginAsync(cancellationToken); - } - - public override async Task ReadSetEndAsync(CancellationToken cancellationToken) - { - await _wrappedProtocol.ReadSetEndAsync(cancellationToken); - } - - public override async Task ReadBoolAsync(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadBoolAsync(cancellationToken); - } - - public override async Task ReadByteAsync(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadByteAsync(cancellationToken); - } - - public override async Task ReadI16Async(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadI16Async(cancellationToken); - } - - public override async Task ReadI32Async(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadI32Async(cancellationToken); - } - - public override async Task ReadI64Async(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadI64Async(cancellationToken); - } - - public override async Task ReadDoubleAsync(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadDoubleAsync(cancellationToken); - } - - public override async Task ReadStringAsync(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadStringAsync(cancellationToken); - } - - public override async Task ReadBinaryAsync(CancellationToken cancellationToken) - { - return await _wrappedProtocol.ReadBinaryAsync(cancellationToken); - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/TProtocolException.cs b/lib/netcore/Thrift/Protocols/TProtocolException.cs deleted file mode 100644 index 8c67c3bfdf9..00000000000 --- a/lib/netcore/Thrift/Protocols/TProtocolException.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -// ReSharper disable InconsistentNaming -namespace Thrift.Protocols -{ - public class TProtocolException : TException - { - // do not rename public constants - they used in generated files - public const int UNKNOWN = 0; - public const int INVALID_DATA = 1; - public const int NEGATIVE_SIZE = 2; - public const int SIZE_LIMIT = 3; - public const int BAD_VERSION = 4; - public const int NOT_IMPLEMENTED = 5; - public const int DEPTH_LIMIT = 6; - - protected int Type = UNKNOWN; - - public TProtocolException() - { - } - - public TProtocolException(int type) - { - Type = type; - } - - public TProtocolException(int type, string message) - : base(message) - { - Type = type; - } - - public TProtocolException(string message) - : base(message) - { - } - - public int GetExceptionType() - { - return Type; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Utilities/TBase64Helper.cs b/lib/netcore/Thrift/Protocols/Utilities/TBase64Helper.cs deleted file mode 100644 index 7eff5e181d1..00000000000 --- a/lib/netcore/Thrift/Protocols/Utilities/TBase64Helper.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; - -namespace Thrift.Protocols.Utilities -{ - // ReSharper disable once InconsistentNaming - internal static class TBase64Helper - { - //TODO: Constants - //TODO: Check for args - //TODO: Unitests - - internal const string EncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - private static readonly int[] DecodeTable = - { - -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 - }; - - internal static void Encode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) - { - if (src == null) - { - throw new ArgumentNullException(nameof(src)); - } - - dst[dstOff] = (byte) EncodeTable[(src[srcOff] >> 2) & 0x3F]; - - if (len == 3) - { - dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; - dst[dstOff + 2] = (byte) EncodeTable[((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)]; - dst[dstOff + 3] = (byte) EncodeTable[src[srcOff + 2] & 0x3F]; - } - else if (len == 2) - { - dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; - dst[dstOff + 2] = (byte) EncodeTable[(src[srcOff + 1] << 2) & 0x3C]; - } - else - { - // len == 1 - dst[dstOff + 1] = (byte) EncodeTable[(src[srcOff] << 4) & 0x30]; - } - } - - internal static void Decode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) - { - if (src == null) - { - throw new ArgumentNullException(nameof(src)); - } - - dst[dstOff] = (byte) ((DecodeTable[src[srcOff] & 0x0FF] << 2) | (DecodeTable[src[srcOff + 1] & 0x0FF] >> 4)); - - if (len > 2) - { - dst[dstOff + 1] = - (byte) - (((DecodeTable[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) | (DecodeTable[src[srcOff + 2] & 0x0FF] >> 2)); - if (len > 3) - { - dst[dstOff + 2] = - (byte) - (((DecodeTable[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) | DecodeTable[src[srcOff + 3] & 0x0FF]); - } - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Utilities/TBase64Utils.cs b/lib/netcore/Thrift/Protocols/Utilities/TBase64Utils.cs deleted file mode 100644 index 15fd45cbef9..00000000000 --- a/lib/netcore/Thrift/Protocols/Utilities/TBase64Utils.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; - -namespace Thrift.Protocols.Utilities -{ - // ReSharper disable once InconsistentNaming - internal static class TBase64Utils - { - //TODO: Constants - //TODO: Check for args - //TODO: Unitests - - internal const string EncodeTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - private static readonly int[] DecodeTable = - { - -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 - }; - - internal static void Encode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) - { - if (src == null) - { - throw new ArgumentNullException(nameof(src)); - } - - dst[dstOff] = (byte) EncodeTable[(src[srcOff] >> 2) & 0x3F]; - - if (len == 3) - { - dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; - dst[dstOff + 2] = (byte) EncodeTable[((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)]; - dst[dstOff + 3] = (byte) EncodeTable[src[srcOff + 2] & 0x3F]; - } - else if (len == 2) - { - dst[dstOff + 1] = (byte) EncodeTable[((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; - dst[dstOff + 2] = (byte) EncodeTable[(src[srcOff + 1] << 2) & 0x3C]; - } - else - { - // len == 1 - dst[dstOff + 1] = (byte) EncodeTable[(src[srcOff] << 4) & 0x30]; - } - } - - internal static void Decode(byte[] src, int srcOff, int len, byte[] dst, int dstOff) - { - if (src == null) - { - throw new ArgumentNullException(nameof(src)); - } - - dst[dstOff] = (byte) ((DecodeTable[src[srcOff] & 0x0FF] << 2) | (DecodeTable[src[srcOff + 1] & 0x0FF] >> 4)); - - if (len > 2) - { - dst[dstOff + 1] = - (byte) - (((DecodeTable[src[srcOff + 1] & 0x0FF] << 4) & 0xF0) | (DecodeTable[src[srcOff + 2] & 0x0FF] >> 2)); - if (len > 3) - { - dst[dstOff + 2] = - (byte) - (((DecodeTable[src[srcOff + 2] & 0x0FF] << 6) & 0xC0) | DecodeTable[src[srcOff + 3] & 0x0FF]); - } - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs b/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs deleted file mode 100644 index 93eff785555..00000000000 --- a/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolConstants.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -namespace Thrift.Protocols.Utilities -{ - // ReSharper disable once InconsistentNaming - public static class TJSONProtocolConstants - { - //TODO Check for performance for reusing ImmutableArray from System.Collections.Immutable (https://blogs.msdn.microsoft.com/dotnet/2013/06/24/please-welcome-immutablearrayt/) - // can be possible to get better performance and also better GC - - public static readonly byte[] Comma = {(byte) ','}; - public static readonly byte[] Colon = {(byte) ':'}; - public static readonly byte[] LeftBrace = {(byte) '{'}; - public static readonly byte[] RightBrace = {(byte) '}'}; - public static readonly byte[] LeftBracket = {(byte) '['}; - public static readonly byte[] RightBracket = {(byte) ']'}; - public static readonly byte[] Quote = {(byte) '"'}; - public static readonly byte[] Backslash = {(byte) '\\'}; - - public static readonly byte[] JsonCharTable = - { - 0, 0, 0, 0, 0, 0, 0, 0, (byte) 'b', (byte) 't', (byte) 'n', 0, (byte) 'f', (byte) 'r', 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, (byte) '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 - }; - - public static readonly char[] EscapeChars = "\"\\/bfnrt".ToCharArray(); - public static readonly byte[] EscapeCharValues = {(byte) '"', (byte) '\\', (byte) '/', (byte) '\b', (byte) '\f', (byte) '\n', (byte) '\r', (byte) '\t'}; - public static readonly byte[] EscSequences = {(byte) '\\', (byte) 'u', (byte) '0', (byte) '0'}; - - public static class TypeNames - { - public static readonly byte[] NameBool = { (byte)'t', (byte)'f' }; - public static readonly byte[] NameByte = { (byte)'i', (byte)'8' }; - public static readonly byte[] NameI16 = { (byte)'i', (byte)'1', (byte)'6' }; - public static readonly byte[] NameI32 = { (byte)'i', (byte)'3', (byte)'2' }; - public static readonly byte[] NameI64 = { (byte)'i', (byte)'6', (byte)'4' }; - public static readonly byte[] NameDouble = { (byte)'d', (byte)'b', (byte)'l' }; - public static readonly byte[] NameStruct = { (byte)'r', (byte)'e', (byte)'c' }; - public static readonly byte[] NameString = { (byte)'s', (byte)'t', (byte)'r' }; - public static readonly byte[] NameMap = { (byte)'m', (byte)'a', (byte)'p' }; - public static readonly byte[] NameList = { (byte)'l', (byte)'s', (byte)'t' }; - public static readonly byte[] NameSet = { (byte)'s', (byte)'e', (byte)'t' }; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs b/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs deleted file mode 100644 index adc26a9af01..00000000000 --- a/lib/netcore/Thrift/Protocols/Utilities/TJsonProtocolHelper.cs +++ /dev/null @@ -1,176 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using Thrift.Protocols.Entities; - -namespace Thrift.Protocols.Utilities -{ - // ReSharper disable once InconsistentNaming - public static class TJSONProtocolHelper - { - public static byte[] GetTypeNameForTypeId(TType typeId) - { - switch (typeId) - { - case TType.Bool: - return TJSONProtocolConstants.TypeNames.NameBool; - case TType.Byte: - return TJSONProtocolConstants.TypeNames.NameByte; - case TType.I16: - return TJSONProtocolConstants.TypeNames.NameI16; - case TType.I32: - return TJSONProtocolConstants.TypeNames.NameI32; - case TType.I64: - return TJSONProtocolConstants.TypeNames.NameI64; - case TType.Double: - return TJSONProtocolConstants.TypeNames.NameDouble; - case TType.String: - return TJSONProtocolConstants.TypeNames.NameString; - case TType.Struct: - return TJSONProtocolConstants.TypeNames.NameStruct; - case TType.Map: - return TJSONProtocolConstants.TypeNames.NameMap; - case TType.Set: - return TJSONProtocolConstants.TypeNames.NameSet; - case TType.List: - return TJSONProtocolConstants.TypeNames.NameList; - default: - throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType"); - } - } - - public static TType GetTypeIdForTypeName(byte[] name) - { - var result = TType.Stop; - if (name.Length > 1) - { - switch (name[0]) - { - case (byte) 'd': - result = TType.Double; - break; - case (byte) 'i': - switch (name[1]) - { - case (byte) '8': - result = TType.Byte; - break; - case (byte) '1': - result = TType.I16; - break; - case (byte) '3': - result = TType.I32; - break; - case (byte) '6': - result = TType.I64; - break; - } - break; - case (byte) 'l': - result = TType.List; - break; - case (byte) 'm': - result = TType.Map; - break; - case (byte) 'r': - result = TType.Struct; - break; - case (byte) 's': - if (name[1] == (byte) 't') - { - result = TType.String; - } - else if (name[1] == (byte) 'e') - { - result = TType.Set; - } - break; - case (byte) 't': - result = TType.Bool; - break; - } - } - if (result == TType.Stop) - { - throw new TProtocolException(TProtocolException.NOT_IMPLEMENTED, "Unrecognized exType"); - } - return result; - } - - /// - /// Return true if the given byte could be a valid part of a JSON number. - /// - public static bool IsJsonNumeric(byte b) - { - switch (b) - { - case (byte)'+': - case (byte)'-': - case (byte)'.': - case (byte)'0': - case (byte)'1': - case (byte)'2': - case (byte)'3': - case (byte)'4': - case (byte)'5': - case (byte)'6': - case (byte)'7': - case (byte)'8': - case (byte)'9': - case (byte)'E': - case (byte)'e': - return true; - default: - return false; - } - } - - /// - /// Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its - /// corresponding hex value - /// - public static byte ToHexVal(byte ch) - { - if (ch >= '0' && ch <= '9') - { - return (byte)((char)ch - '0'); - } - - if (ch >= 'a' && ch <= 'f') - { - ch += 10; - return (byte)((char)ch - 'a'); - } - - throw new TProtocolException(TProtocolException.INVALID_DATA, "Expected hex character"); - } - - /// - /// Convert a byte containing a hex value to its corresponding hex character - /// - public static byte ToHexChar(byte val) - { - val &= 0x0F; - if (val < 10) - { - return (byte)((char)val + '0'); - } - val -= 10; - return (byte)((char)val + 'a'); - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs b/lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs deleted file mode 100644 index 50b038566e1..00000000000 --- a/lib/netcore/Thrift/Protocols/Utilities/TProtocolUtil.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols.Entities; - -namespace Thrift.Protocols.Utilities -{ - // ReSharper disable once InconsistentNaming - public static class TProtocolUtil - { - public static async Task SkipAsync(TProtocol protocol, TType type, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - protocol.IncrementRecursionDepth(); - try - { - switch (type) - { - case TType.Bool: - await protocol.ReadBoolAsync(cancellationToken); - break; - case TType.Byte: - await protocol.ReadByteAsync(cancellationToken); - break; - case TType.I16: - await protocol.ReadI16Async(cancellationToken); - break; - case TType.I32: - await protocol.ReadI32Async(cancellationToken); - break; - case TType.I64: - await protocol.ReadI64Async(cancellationToken); - break; - case TType.Double: - await protocol.ReadDoubleAsync(cancellationToken); - break; - case TType.String: - // Don't try to decode the string, just skip it. - await protocol.ReadBinaryAsync(cancellationToken); - break; - case TType.Struct: - await protocol.ReadStructBeginAsync(cancellationToken); - while (true) - { - var field = await protocol.ReadFieldBeginAsync(cancellationToken); - if (field.Type == TType.Stop) - { - break; - } - await SkipAsync(protocol, field.Type, cancellationToken); - await protocol.ReadFieldEndAsync(cancellationToken); - } - await protocol.ReadStructEndAsync(cancellationToken); - break; - case TType.Map: - var map = await protocol.ReadMapBeginAsync(cancellationToken); - for (var i = 0; i < map.Count; i++) - { - await SkipAsync(protocol, map.KeyType, cancellationToken); - await SkipAsync(protocol, map.ValueType, cancellationToken); - } - await protocol.ReadMapEndAsync(cancellationToken); - break; - case TType.Set: - var set = await protocol.ReadSetBeginAsync(cancellationToken); - for (var i = 0; i < set.Count; i++) - { - await SkipAsync(protocol, set.ElementType, cancellationToken); - } - await protocol.ReadSetEndAsync(cancellationToken); - break; - case TType.List: - var list = await protocol.ReadListBeginAsync(cancellationToken); - for (var i = 0; i < list.Count; i++) - { - await SkipAsync(protocol, list.ElementType, cancellationToken); - } - await protocol.ReadListEndAsync(cancellationToken); - break; - default: - throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d")); - } - } - finally - { - protocol.DecrementRecursionDepth(); - } - } - } -} diff --git a/lib/netcore/Thrift/Server/AsyncBaseServer.cs b/lib/netcore/Thrift/Server/AsyncBaseServer.cs deleted file mode 100644 index 325c39c7164..00000000000 --- a/lib/netcore/Thrift/Server/AsyncBaseServer.cs +++ /dev/null @@ -1,183 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Thrift.Protocols; -using Thrift.Transports; - -namespace Thrift.Server -{ - //TODO: unhandled exceptions, etc. - - // ReSharper disable once InconsistentNaming - public class AsyncBaseServer : TBaseServer - { - private readonly int _clientWaitingDelay; - private volatile Task _serverTask; - - public AsyncBaseServer(ITAsyncProcessor processor, TServerTransport serverTransport, - ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory, - ILoggerFactory loggerFactory, int clientWaitingDelay = 10) - : this(new SingletonTProcessorFactory(processor), serverTransport, - new TTransportFactory(), new TTransportFactory(), - inputProtocolFactory, outputProtocolFactory, - loggerFactory.CreateLogger(nameof(AsyncBaseServer)), clientWaitingDelay) - { - } - - public AsyncBaseServer(ITProcessorFactory itProcessorFactory, TServerTransport serverTransport, - TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, - ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory, - ILogger logger, int clientWaitingDelay = 10) - : base(itProcessorFactory, serverTransport, inputTransportFactory, outputTransportFactory, - inputProtocolFactory, outputProtocolFactory, logger) - { - _clientWaitingDelay = clientWaitingDelay; - } - - public override async Task ServeAsync(CancellationToken cancellationToken) - { - try - { - // cancelation token - _serverTask = Task.Factory.StartNew(() => StartListening(cancellationToken), TaskCreationOptions.LongRunning); - await _serverTask; - } - catch (Exception ex) - { - Logger.LogError(ex.ToString()); - } - } - - private async Task StartListening(CancellationToken cancellationToken) - { - ServerTransport.Listen(); - - Logger.LogTrace("Started listening at server"); - - if (ServerEventHandler != null) - { - await ServerEventHandler.PreServeAsync(cancellationToken); - } - - while (!cancellationToken.IsCancellationRequested) - { - if (ServerTransport.IsClientPending()) - { - Logger.LogTrace("Waiting for client connection"); - - try - { - var client = await ServerTransport.AcceptAsync(cancellationToken); - await Task.Factory.StartNew(() => Execute(client, cancellationToken), cancellationToken); - } - catch (TTransportException ttx) - { - Logger.LogTrace($"Transport exception: {ttx}"); - - if (ttx.Type != TTransportException.ExceptionType.Interrupted) - { - Logger.LogError(ttx.ToString()); - } - } - } - else - { - try - { - await Task.Delay(TimeSpan.FromMilliseconds(_clientWaitingDelay), cancellationToken); - } - catch(TaskCanceledException) { } - } - } - - ServerTransport.Close(); - - Logger.LogTrace("Completed listening at server"); - } - - public override void Stop() - { - } - - private async Task Execute(TClientTransport client, CancellationToken cancellationToken) - { - Logger.LogTrace("Started client request processing"); - - var processor = ItProcessorFactory.GetAsyncProcessor(client, this); - - TClientTransport inputTransport = null; - TClientTransport outputTransport = null; - TProtocol inputProtocol = null; - TProtocol outputProtocol = null; - object connectionContext = null; - - try - { - inputTransport = InputTransportFactory.GetTransport(client); - outputTransport = OutputTransportFactory.GetTransport(client); - - inputProtocol = InputProtocolFactory.GetProtocol(inputTransport); - outputProtocol = OutputProtocolFactory.GetProtocol(outputTransport); - - if (ServerEventHandler != null) - { - connectionContext = await ServerEventHandler.CreateContextAsync(inputProtocol, outputProtocol, cancellationToken); - } - - while (!cancellationToken.IsCancellationRequested) - { - if (!await inputTransport.PeekAsync(cancellationToken)) - { - break; - } - - if (ServerEventHandler != null) - { - await ServerEventHandler.ProcessContextAsync(connectionContext, inputTransport, cancellationToken); - } - - if (!await processor.ProcessAsync(inputProtocol, outputProtocol, cancellationToken)) - { - break; - } - } - } - catch (TTransportException ttx) - { - Logger.LogTrace($"Transport exception: {ttx}"); - } - catch (Exception x) - { - Logger.LogError($"Error: {x}"); - } - - if (ServerEventHandler != null) - { - await ServerEventHandler.DeleteContextAsync(connectionContext, inputProtocol, outputProtocol, cancellationToken); - } - - inputTransport?.Close(); - outputTransport?.Close(); - - Logger.LogTrace("Completed client request processing"); - } - } -} diff --git a/lib/netcore/Thrift/Server/TBaseServer.cs b/lib/netcore/Thrift/Server/TBaseServer.cs deleted file mode 100644 index 741dd5c95ad..00000000000 --- a/lib/netcore/Thrift/Server/TBaseServer.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Thrift.Protocols; -using Thrift.Transports; - -namespace Thrift.Server -{ - // ReSharper disable once InconsistentNaming - public abstract class TBaseServer - { - protected readonly ILogger Logger; - protected ITProtocolFactory InputProtocolFactory; - protected TTransportFactory InputTransportFactory; - protected ITProcessorFactory ItProcessorFactory; - protected ITProtocolFactory OutputProtocolFactory; - protected TTransportFactory OutputTransportFactory; - - protected TServerEventHandler ServerEventHandler; - protected TServerTransport ServerTransport; - - protected TBaseServer(ITProcessorFactory itProcessorFactory, TServerTransport serverTransport, - TTransportFactory inputTransportFactory, TTransportFactory outputTransportFactory, - ITProtocolFactory inputProtocolFactory, ITProtocolFactory outputProtocolFactory, - ILogger logger) - { - ItProcessorFactory = itProcessorFactory ?? throw new ArgumentNullException(nameof(itProcessorFactory)); - ServerTransport = serverTransport; - InputTransportFactory = inputTransportFactory ?? throw new ArgumentNullException(nameof(inputTransportFactory)); - OutputTransportFactory = outputTransportFactory ?? throw new ArgumentNullException(nameof(outputTransportFactory)); - InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory)); - OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory)); - Logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } - - public void SetEventHandler(TServerEventHandler seh) - { - ServerEventHandler = seh; - } - - public TServerEventHandler GetEventHandler() - { - return ServerEventHandler; - } - - public abstract void Stop(); - - public virtual void Start() - { - // do nothing - } - - public virtual async Task ServeAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Server/TServerEventHandler.cs b/lib/netcore/Thrift/Server/TServerEventHandler.cs deleted file mode 100644 index 733bb4bef7c..00000000000 --- a/lib/netcore/Thrift/Server/TServerEventHandler.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols; -using Thrift.Transports; - -namespace Thrift.Server -{ - //TODO: replacement by event? - - /// - /// Interface implemented by server users to handle events from the server - /// - // ReSharper disable once InconsistentNaming - public interface TServerEventHandler - { - /// - /// Called before the server begins */ - /// - Task PreServeAsync(CancellationToken cancellationToken); - - /// - /// Called when a new client has connected and is about to being processing */ - /// - Task CreateContextAsync(TProtocol input, TProtocol output, CancellationToken cancellationToken); - - /// - /// Called when a client has finished request-handling to delete server context */ - /// - Task DeleteContextAsync(object serverContext, TProtocol input, TProtocol output, - CancellationToken cancellationToken); - - /// - /// Called when a client is about to call the processor */ - /// - Task ProcessContextAsync(object serverContext, TClientTransport transport, CancellationToken cancellationToken); - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/SingletonTProcessorFactory.cs b/lib/netcore/Thrift/SingletonTProcessorFactory.cs deleted file mode 100644 index c35123348ba..00000000000 --- a/lib/netcore/Thrift/SingletonTProcessorFactory.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using Thrift.Server; -using Thrift.Transports; - -namespace Thrift -{ - // ReSharper disable once InconsistentNaming - public class SingletonTProcessorFactory : ITProcessorFactory - { - private readonly ITAsyncProcessor _tAsyncProcessor; - - public SingletonTProcessorFactory(ITAsyncProcessor tAsyncProcessor) - { - _tAsyncProcessor = tAsyncProcessor; - } - - public ITAsyncProcessor GetAsyncProcessor(TClientTransport trans, TBaseServer baseServer = null) - { - return _tAsyncProcessor; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/TApplicationException.cs b/lib/netcore/Thrift/TApplicationException.cs deleted file mode 100644 index 9ec145a8529..00000000000 --- a/lib/netcore/Thrift/TApplicationException.cs +++ /dev/null @@ -1,150 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols; -using Thrift.Protocols.Entities; -using Thrift.Protocols.Utilities; - -namespace Thrift -{ - // ReSharper disable once InconsistentNaming - public class TApplicationException : TException - { - public enum ExceptionType - { - Unknown, - UnknownMethod, - InvalidMessageType, - WrongMethodName, - BadSequenceId, - MissingResult, - InternalError, - ProtocolError, - InvalidTransform, - InvalidProtocol, - UnsupportedClientType - } - - private const int MessageTypeFieldId = 1; - private const int ExTypeFieldId = 2; - - protected ExceptionType Type; - - public TApplicationException() - { - } - - public TApplicationException(ExceptionType type) - { - Type = type; - } - - public TApplicationException(ExceptionType type, string message) - : base(message) - { - Type = type; - } - - public static async Task ReadAsync(TProtocol inputProtocol, CancellationToken cancellationToken) - { - string message = null; - var type = ExceptionType.Unknown; - - await inputProtocol.ReadStructBeginAsync(cancellationToken); - while (true) - { - var field = await inputProtocol.ReadFieldBeginAsync(cancellationToken); - if (field.Type == TType.Stop) - { - break; - } - - switch (field.ID) - { - case MessageTypeFieldId: - if (field.Type == TType.String) - { - message = await inputProtocol.ReadStringAsync(cancellationToken); - } - else - { - await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); - } - break; - case ExTypeFieldId: - if (field.Type == TType.I32) - { - type = (ExceptionType) await inputProtocol.ReadI32Async(cancellationToken); - } - else - { - await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); - } - break; - default: - await TProtocolUtil.SkipAsync(inputProtocol, field.Type, cancellationToken); - break; - } - - await inputProtocol.ReadFieldEndAsync(cancellationToken); - } - - await inputProtocol.ReadStructEndAsync(cancellationToken); - - return new TApplicationException(type, message); - } - - public async Task WriteAsync(TProtocol outputProtocol, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - const string messageTypeFieldName = "message"; - const string exTypeFieldName = "exType"; - const string structApplicationExceptionName = "TApplicationException"; - - var struc = new TStruct(structApplicationExceptionName); - var field = new TField(); - - await outputProtocol.WriteStructBeginAsync(struc, cancellationToken); - - if (!string.IsNullOrEmpty(Message)) - { - field.Name = messageTypeFieldName; - field.Type = TType.String; - field.ID = MessageTypeFieldId; - await outputProtocol.WriteFieldBeginAsync(field, cancellationToken); - await outputProtocol.WriteStringAsync(Message, cancellationToken); - await outputProtocol.WriteFieldEndAsync(cancellationToken); - } - - field.Name = exTypeFieldName; - field.Type = TType.I32; - field.ID = ExTypeFieldId; - - await outputProtocol.WriteFieldBeginAsync(field, cancellationToken); - await outputProtocol.WriteI32Async((int) Type, cancellationToken); - await outputProtocol.WriteFieldEndAsync(cancellationToken); - await outputProtocol.WriteFieldStopAsync(cancellationToken); - await outputProtocol.WriteStructEndAsync(cancellationToken); - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/TBaseClient.cs b/lib/netcore/Thrift/TBaseClient.cs deleted file mode 100644 index e0192515347..00000000000 --- a/lib/netcore/Thrift/TBaseClient.cs +++ /dev/null @@ -1,91 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols; - -namespace Thrift -{ - // ReSharper disable once InconsistentNaming - /// - /// TBaseClient. - /// Base client for generated clients. - /// Do not change this class without checking generated code (namings, etc.) - /// - public abstract class TBaseClient - { - private readonly TProtocol _inputProtocol; - private readonly TProtocol _outputProtocol; - private bool _isDisposed; - private int _seqId; - public readonly Guid ClientId = Guid.NewGuid(); - - protected TBaseClient(TProtocol inputProtocol, TProtocol outputProtocol) - { - _inputProtocol = inputProtocol ?? throw new ArgumentNullException(nameof(inputProtocol)); - _outputProtocol = outputProtocol ?? throw new ArgumentNullException(nameof(outputProtocol)); - } - - public TProtocol InputProtocol => _inputProtocol; - - public TProtocol OutputProtocol => _outputProtocol; - - public int SeqId - { - get { return ++_seqId; } - } - - public virtual async Task OpenTransportAsync() - { - await OpenTransportAsync(CancellationToken.None); - } - - public virtual async Task OpenTransportAsync(CancellationToken cancellationToken) - { - if (!_inputProtocol.Transport.IsOpen) - { - await _inputProtocol.Transport.OpenAsync(cancellationToken); - } - - if (!_inputProtocol.Transport.IsOpen) - { - await _outputProtocol.Transport.OpenAsync(cancellationToken); - } - } - - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - if (!_isDisposed) - { - if (disposing) - { - _inputProtocol?.Dispose(); - _outputProtocol?.Dispose(); - } - } - - _isDisposed = true; - } - } -} diff --git a/lib/netcore/Thrift/TException.cs b/lib/netcore/Thrift/TException.cs deleted file mode 100644 index 6aa588d7f34..00000000000 --- a/lib/netcore/Thrift/TException.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; - -namespace Thrift -{ - // ReSharper disable once InconsistentNaming - public class TException : Exception - { - public TException() - { - } - - public TException(string message) - : base(message) - { - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/TMultiplexedProcessor.cs b/lib/netcore/Thrift/TMultiplexedProcessor.cs deleted file mode 100644 index ad0e749e071..00000000000 --- a/lib/netcore/Thrift/TMultiplexedProcessor.cs +++ /dev/null @@ -1,143 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Protocols; -using Thrift.Protocols.Entities; - -namespace Thrift -{ - // ReSharper disable once InconsistentNaming - public class TMultiplexedProcessor : ITAsyncProcessor - { - //TODO: Localization - - private readonly Dictionary _serviceProcessorMap = - new Dictionary(); - - public async Task ProcessAsync(TProtocol iprot, TProtocol oprot) - { - return await ProcessAsync(iprot, oprot, CancellationToken.None); - } - - public async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - try - { - var message = await iprot.ReadMessageBeginAsync(cancellationToken); - - if ((message.Type != TMessageType.Call) && (message.Type != TMessageType.Oneway)) - { - await FailAsync(oprot, message, TApplicationException.ExceptionType.InvalidMessageType, - "Message exType CALL or ONEWAY expected", cancellationToken); - return false; - } - - // Extract the service name - var index = message.Name.IndexOf(TMultiplexedProtocol.Separator, StringComparison.Ordinal); - if (index < 0) - { - await FailAsync(oprot, message, TApplicationException.ExceptionType.InvalidProtocol, - $"Service name not found in message name: {message.Name}. Did you forget to use a TMultiplexProtocol in your client?", - cancellationToken); - return false; - } - - // Create a new TMessage, something that can be consumed by any TProtocol - var serviceName = message.Name.Substring(0, index); - ITAsyncProcessor actualProcessor; - if (!_serviceProcessorMap.TryGetValue(serviceName, out actualProcessor)) - { - await FailAsync(oprot, message, TApplicationException.ExceptionType.InternalError, - $"Service name not found: {serviceName}. Did you forget to call RegisterProcessor()?", - cancellationToken); - return false; - } - - // Create a new TMessage, removing the service name - var newMessage = new TMessage( - message.Name.Substring(serviceName.Length + TMultiplexedProtocol.Separator.Length), - message.Type, - message.SeqID); - - // Dispatch processing to the stored processor - return - await - actualProcessor.ProcessAsync(new StoredMessageProtocol(iprot, newMessage), oprot, - cancellationToken); - } - catch (IOException) - { - return false; // similar to all other processors - } - } - - public void RegisterProcessor(string serviceName, ITAsyncProcessor processor) - { - if (_serviceProcessorMap.ContainsKey(serviceName)) - { - throw new InvalidOperationException( - $"Processor map already contains processor with name: '{serviceName}'"); - } - - _serviceProcessorMap.Add(serviceName, processor); - } - - private async Task FailAsync(TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, - string etxt, CancellationToken cancellationToken) - { - var appex = new TApplicationException(extype, etxt); - - var newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID); - - await oprot.WriteMessageBeginAsync(newMessage, cancellationToken); - await appex.WriteAsync(oprot, cancellationToken); - await oprot.WriteMessageEndAsync(cancellationToken); - await oprot.Transport.FlushAsync(cancellationToken); - } - - private class StoredMessageProtocol : TProtocolDecorator - { - readonly TMessage _msgBegin; - - public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) - : base(protocol) - { - _msgBegin = messageBegin; - } - - public override async Task ReadMessageBeginAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - return _msgBegin; - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Thrift.csproj b/lib/netcore/Thrift/Thrift.csproj deleted file mode 100644 index 6a2ccc30d47..00000000000 --- a/lib/netcore/Thrift/Thrift.csproj +++ /dev/null @@ -1,33 +0,0 @@ - - - - netstandard2.0 - Thrift - Thrift - true - true - false - false - false - false - false - false - false - false - true - thrift.snk - - - - - - - - - - - - - - - diff --git a/lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs deleted file mode 100644 index 761f1ac783c..00000000000 --- a/lib/netcore/Thrift/Transports/Client/TBufferedClientTransport.cs +++ /dev/null @@ -1,206 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Transports.Client -{ - // ReSharper disable once InconsistentNaming - public class TBufferedClientTransport : TClientTransport - { - private readonly int _bufSize; - private readonly MemoryStream _inputBuffer = new MemoryStream(0); - private readonly MemoryStream _outputBuffer = new MemoryStream(0); - private readonly TClientTransport _transport; - private bool _isDisposed; - - //TODO: should support only specified input transport? - public TBufferedClientTransport(TClientTransport transport, int bufSize = 1024) - { - if (bufSize <= 0) - { - throw new ArgumentOutOfRangeException(nameof(bufSize), "Buffer size must be a positive number."); - } - - _transport = transport ?? throw new ArgumentNullException(nameof(transport)); - _bufSize = bufSize; - } - - public TClientTransport UnderlyingTransport - { - get - { - CheckNotDisposed(); - - return _transport; - } - } - - public override bool IsOpen => !_isDisposed && _transport.IsOpen; - - public override async Task OpenAsync(CancellationToken cancellationToken) - { - CheckNotDisposed(); - - await _transport.OpenAsync(cancellationToken); - } - - public override void Close() - { - CheckNotDisposed(); - - _transport.Close(); - } - - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) - { - //TODO: investigate how it should work correctly - CheckNotDisposed(); - - ValidateBufferArgs(buffer, offset, length); - - if (!IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - if (_inputBuffer.Capacity < _bufSize) - { - _inputBuffer.Capacity = _bufSize; - } - - var got = await _inputBuffer.ReadAsync(buffer, offset, length, cancellationToken); - if (got > 0) - { - return got; - } - - _inputBuffer.Seek(0, SeekOrigin.Begin); - _inputBuffer.SetLength(_inputBuffer.Capacity); - - ArraySegment bufSegment; - _inputBuffer.TryGetBuffer(out bufSegment); - - // investigate - var filled = await _transport.ReadAsync(bufSegment.Array, 0, (int) _inputBuffer.Length, cancellationToken); - _inputBuffer.SetLength(filled); - - if (filled == 0) - { - return 0; - } - - return await ReadAsync(buffer, offset, length, cancellationToken); - } - - public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) - { - CheckNotDisposed(); - - ValidateBufferArgs(buffer, offset, length); - - if (!IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - // Relative offset from "off" argument - var writtenCount = 0; - if (_outputBuffer.Length > 0) - { - var capa = (int) (_outputBuffer.Capacity - _outputBuffer.Length); - var writeSize = capa <= length ? capa : length; - await _outputBuffer.WriteAsync(buffer, offset, writeSize, cancellationToken); - - writtenCount += writeSize; - if (writeSize == capa) - { - //ArraySegment bufSegment; - //_outputBuffer.TryGetBuffer(out bufSegment); - var data = _outputBuffer.ToArray(); - //await _transport.WriteAsync(bufSegment.Array, cancellationToken); - await _transport.WriteAsync(data, cancellationToken); - _outputBuffer.SetLength(0); - } - } - - while (length - writtenCount >= _bufSize) - { - await _transport.WriteAsync(buffer, offset + writtenCount, _bufSize, cancellationToken); - writtenCount += _bufSize; - } - - var remain = length - writtenCount; - if (remain > 0) - { - if (_outputBuffer.Capacity < _bufSize) - { - _outputBuffer.Capacity = _bufSize; - } - await _outputBuffer.WriteAsync(buffer, offset + writtenCount, remain, cancellationToken); - } - } - - public override async Task FlushAsync(CancellationToken cancellationToken) - { - CheckNotDisposed(); - - if (!IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - if (_outputBuffer.Length > 0) - { - //ArraySegment bufSegment; - var data = _outputBuffer.ToArray(); // TryGetBuffer(out bufSegment); - - await _transport.WriteAsync(data /*bufSegment.Array*/, cancellationToken); - _outputBuffer.SetLength(0); - } - - await _transport.FlushAsync(cancellationToken); - } - - private void CheckNotDisposed() - { - if (_isDisposed) - { - throw new ObjectDisposedException(nameof(_transport)); - } - } - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_isDisposed) - { - if (disposing) - { - _inputBuffer?.Dispose(); - _outputBuffer?.Dispose(); - _transport?.Dispose(); - } - } - _isDisposed = true; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs deleted file mode 100644 index d11bb959a2b..00000000000 --- a/lib/netcore/Thrift/Transports/Client/TFramedClientTransport.cs +++ /dev/null @@ -1,201 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Transports.Client -{ - //TODO: check for correct implementation - - // ReSharper disable once InconsistentNaming - public class TFramedClientTransport : TClientTransport - { - private const int HeaderSize = 4; - private readonly byte[] _headerBuf = new byte[HeaderSize]; - private readonly MemoryStream _readBuffer = new MemoryStream(1024); - private readonly TClientTransport _transport; - private readonly MemoryStream _writeBuffer = new MemoryStream(1024); - - private bool _isDisposed; - - public TFramedClientTransport(TClientTransport transport) - { - _transport = transport ?? throw new ArgumentNullException(nameof(transport)); - - InitWriteBuffer(); - } - - public override bool IsOpen => !_isDisposed && _transport.IsOpen; - - public override async Task OpenAsync(CancellationToken cancellationToken) - { - CheckNotDisposed(); - - await _transport.OpenAsync(cancellationToken); - } - - public override void Close() - { - CheckNotDisposed(); - - _transport.Close(); - } - - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) - { - CheckNotDisposed(); - - ValidateBufferArgs(buffer, offset, length); - - if (!IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - var got = await _readBuffer.ReadAsync(buffer, offset, length, cancellationToken); - if (got > 0) - { - return got; - } - - // Read another frame of data - await ReadFrameAsync(cancellationToken); - - return await _readBuffer.ReadAsync(buffer, offset, length, cancellationToken); - } - - private async Task ReadFrameAsync(CancellationToken cancellationToken) - { - await _transport.ReadAllAsync(_headerBuf, 0, HeaderSize, cancellationToken); - - var size = DecodeFrameSize(_headerBuf); - - _readBuffer.SetLength(size); - _readBuffer.Seek(0, SeekOrigin.Begin); - - ArraySegment bufSegment; - _readBuffer.TryGetBuffer(out bufSegment); - - var buff = bufSegment.Array; - - await _transport.ReadAllAsync(buff, 0, size, cancellationToken); - } - - public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) - { - CheckNotDisposed(); - - ValidateBufferArgs(buffer, offset, length); - - if (!IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - if (_writeBuffer.Length + length > int.MaxValue) - { - await FlushAsync(cancellationToken); - } - - await _writeBuffer.WriteAsync(buffer, offset, length, cancellationToken); - } - - public override async Task FlushAsync(CancellationToken cancellationToken) - { - CheckNotDisposed(); - - if (!IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - //ArraySegment bufSegment; - //_writeBuffer.TryGetBuffer(out bufSegment); - //var buf = bufSegment.Array; - var buf = _writeBuffer.ToArray(); - - //var len = (int)_writeBuffer.Length; - var dataLen = (int) _writeBuffer.Length - HeaderSize; - if (dataLen < 0) - { - throw new InvalidOperationException(); // logic error actually - } - - // Inject message header into the reserved buffer space - EncodeFrameSize(dataLen, buf); - - // Send the entire message at once - await _transport.WriteAsync(buf, cancellationToken); - - InitWriteBuffer(); - - await _transport.FlushAsync(cancellationToken); - } - - private void InitWriteBuffer() - { - // Reserve space for message header to be put right before sending it out - _writeBuffer.SetLength(HeaderSize); - _writeBuffer.Seek(0, SeekOrigin.End); - } - - private static void EncodeFrameSize(int frameSize, 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)); - } - - private static int DecodeFrameSize(byte[] buf) - { - return - ((buf[0] & 0xff) << 24) | - ((buf[1] & 0xff) << 16) | - ((buf[2] & 0xff) << 8) | - (buf[3] & 0xff); - } - - - private void CheckNotDisposed() - { - if (_isDisposed) - { - throw new ObjectDisposedException("TFramedClientTransport"); - } - } - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_isDisposed) - { - if (disposing) - { - _readBuffer?.Dispose(); - _writeBuffer?.Dispose(); - _transport?.Dispose(); - } - } - _isDisposed = true; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs b/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs deleted file mode 100644 index b2ff8040cbf..00000000000 --- a/lib/netcore/Thrift/Transports/Client/THttpClientTransport.cs +++ /dev/null @@ -1,227 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Security.Cryptography.X509Certificates; -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Transports.Client -{ - // ReSharper disable once InconsistentNaming - public class THttpClientTransport : TClientTransport - { - private readonly X509Certificate[] _certificates; - private readonly Uri _uri; - - // Timeouts in milliseconds - private int _connectTimeout = 30000; - private HttpClient _httpClient; - private Stream _inputStream; - - private bool _isDisposed; - private MemoryStream _outputStream = new MemoryStream(); - - public THttpClientTransport(Uri u, IDictionary customHeaders) - : this(u, Enumerable.Empty(), customHeaders) - { - } - - public THttpClientTransport(Uri u, IEnumerable certificates, - IDictionary customHeaders) - { - _uri = u; - _certificates = (certificates ?? Enumerable.Empty()).ToArray(); - CustomHeaders = customHeaders; - - // due to current bug with performance of Dispose in netcore https://github.com/dotnet/corefx/issues/8809 - // this can be switched to default way (create client->use->dispose per flush) later - _httpClient = CreateClient(); - } - - public IDictionary CustomHeaders { get; } - - public int ConnectTimeout - { - set { _connectTimeout = value; } - get { return _connectTimeout; } - } - - public override bool IsOpen => true; - - public override async Task OpenAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override void Close() - { - if (_inputStream != null) - { - _inputStream.Dispose(); - _inputStream = null; - } - - if (_outputStream != null) - { - _outputStream.Dispose(); - _outputStream = null; - } - - if (_httpClient != null) - { - _httpClient.Dispose(); - _httpClient = null; - } - } - - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - if (_inputStream == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No request has been sent"); - } - - try - { - var ret = await _inputStream.ReadAsync(buffer, offset, length, cancellationToken); - - if (ret == -1) - { - throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "No more data available"); - } - - return ret; - } - catch (IOException iox) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString()); - } - } - - public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - await _outputStream.WriteAsync(buffer, offset, length, cancellationToken); - } - - private HttpClient CreateClient() - { - var handler = new HttpClientHandler(); - handler.ClientCertificates.AddRange(_certificates); - - var httpClient = new HttpClient(handler); - - if (_connectTimeout > 0) - { - httpClient.Timeout = TimeSpan.FromMilliseconds(_connectTimeout); - } - - httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-thrift")); - httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("THttpClientTransport", "0.14.0")); - - if (CustomHeaders != null) - { - foreach (var item in CustomHeaders) - { - httpClient.DefaultRequestHeaders.Add(item.Key, item.Value); - } - } - - return httpClient; - } - - public override async Task FlushAsync(CancellationToken cancellationToken) - { - try - { - try - { - if (_outputStream.CanSeek) - { - _outputStream.Seek(0, SeekOrigin.Begin); - } - - using (var outStream = new StreamContent(_outputStream)) - { - var msg = await _httpClient.PostAsync(_uri, outStream, cancellationToken); - - msg.EnsureSuccessStatusCode(); - - if (_inputStream != null) - { - _inputStream.Dispose(); - _inputStream = null; - } - - _inputStream = await msg.Content.ReadAsStreamAsync(); - if (_inputStream.CanSeek) - { - _inputStream.Seek(0, SeekOrigin.Begin); - } - } - } - catch (IOException iox) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString()); - } - catch (HttpRequestException wx) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, - "Couldn't connect to server: " + wx); - } - } - finally - { - _outputStream = new MemoryStream(); - } - } - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_isDisposed) - { - if (disposing) - { - _inputStream?.Dispose(); - _outputStream?.Dispose(); - _httpClient?.Dispose(); - } - } - _isDisposed = true; - } - } -} diff --git a/lib/netcore/Thrift/Transports/Client/TMemoryBufferClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TMemoryBufferClientTransport.cs deleted file mode 100644 index 46a55a64a1e..00000000000 --- a/lib/netcore/Thrift/Transports/Client/TMemoryBufferClientTransport.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Transports.Client -{ - // ReSharper disable once InconsistentNaming - public class TMemoryBufferClientTransport : TClientTransport - { - private readonly MemoryStream _byteStream; - private bool _isDisposed; - - public TMemoryBufferClientTransport() - { - _byteStream = new MemoryStream(); - } - - public TMemoryBufferClientTransport(byte[] buf) - { - _byteStream = new MemoryStream(buf); - } - - public override bool IsOpen => true; - - public override async Task OpenAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override void Close() - { - /** do nothing **/ - } - - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) - { - return await _byteStream.ReadAsync(buffer, offset, length, cancellationToken); - } - - public override async Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) - { - await _byteStream.WriteAsync(buffer, 0, buffer.Length, cancellationToken); - } - - public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) - { - await _byteStream.WriteAsync(buffer, offset, length, cancellationToken); - } - - public override async Task FlushAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public byte[] GetBuffer() - { - return _byteStream.ToArray(); - } - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_isDisposed) - { - if (disposing) - { - _byteStream?.Dispose(); - } - } - _isDisposed = true; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Client/TNamedPipeClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TNamedPipeClientTransport.cs deleted file mode 100644 index f5e4baf4a12..00000000000 --- a/lib/netcore/Thrift/Transports/Client/TNamedPipeClientTransport.cs +++ /dev/null @@ -1,95 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.IO.Pipes; -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Transports.Client -{ - // ReSharper disable once InconsistentNaming - public class TNamedPipeClientTransport : TClientTransport - { - private NamedPipeClientStream _client; - - public TNamedPipeClientTransport(string pipe) : this(".", pipe) - { - } - - public TNamedPipeClientTransport(string server, string pipe) - { - var serverName = string.IsNullOrWhiteSpace(server) ? server : "."; - - _client = new NamedPipeClientStream(serverName, pipe, PipeDirection.InOut, PipeOptions.None); - } - - public override bool IsOpen => _client != null && _client.IsConnected; - - public override async Task OpenAsync(CancellationToken cancellationToken) - { - if (IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen); - } - - await _client.ConnectAsync(cancellationToken); - } - - public override void Close() - { - if (_client != null) - { - _client.Dispose(); - _client = null; - } - } - - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) - { - if (_client == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - return await _client.ReadAsync(buffer, offset, length, cancellationToken); - } - - public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) - { - if (_client == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - await _client.WriteAsync(buffer, offset, length, cancellationToken); - } - - public override async Task FlushAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - protected override void Dispose(bool disposing) - { - _client.Dispose(); - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs deleted file mode 100644 index e769d14211e..00000000000 --- a/lib/netcore/Thrift/Transports/Client/TSocketClientTransport.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Transports.Client -{ - // ReSharper disable once InconsistentNaming - public class TSocketClientTransport : TStreamClientTransport - { - private bool _isDisposed; - - public TSocketClientTransport(TcpClient client) - { - TcpClient = client ?? throw new ArgumentNullException(nameof(client)); - - if (IsOpen) - { - InputStream = client.GetStream(); - OutputStream = client.GetStream(); - } - } - - public TSocketClientTransport(IPAddress host, int port) - : this(host, port, 0) - { - } - - public TSocketClientTransport(IPAddress host, int port, int timeout) - { - Host = host; - Port = port; - - TcpClient = new TcpClient(); - TcpClient.ReceiveTimeout = TcpClient.SendTimeout = timeout; - TcpClient.Client.NoDelay = true; - } - - public TcpClient TcpClient { get; private set; } - public IPAddress Host { get; } - public int Port { get; } - - public int Timeout - { - set - { - if (TcpClient != null) - { - TcpClient.ReceiveTimeout = TcpClient.SendTimeout = value; - } - } - } - - public override bool IsOpen - { - get - { - if (TcpClient == null) - { - return false; - } - - return TcpClient.Connected; - } - } - - public override async Task OpenAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - if (IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); - } - - if (Port <= 0) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); - } - - if (TcpClient == null) - { - throw new InvalidOperationException("Invalid or not initialized tcp client"); - } - - await TcpClient.ConnectAsync(Host, Port); - - InputStream = TcpClient.GetStream(); - OutputStream = TcpClient.GetStream(); - } - - public override void Close() - { - base.Close(); - - if (TcpClient != null) - { - TcpClient.Dispose(); - TcpClient = null; - } - } - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_isDisposed) - { - if (disposing) - { - TcpClient?.Dispose(); - - base.Dispose(disposing); - } - } - _isDisposed = true; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Client/TStreamClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TStreamClientTransport.cs deleted file mode 100644 index be2011e83bc..00000000000 --- a/lib/netcore/Thrift/Transports/Client/TStreamClientTransport.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Transports.Client -{ - // ReSharper disable once InconsistentNaming - public class TStreamClientTransport : TClientTransport - { - private bool _isDisposed; - - protected TStreamClientTransport() - { - } - - public TStreamClientTransport(Stream inputStream, Stream outputStream) - { - InputStream = inputStream; - OutputStream = outputStream; - } - - protected Stream OutputStream { get; set; } - - protected Stream InputStream { get; set; } - - public override bool IsOpen => true; - - public override async Task OpenAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override void Close() - { - if (InputStream != null) - { - InputStream.Dispose(); - InputStream = null; - } - - if (OutputStream != null) - { - OutputStream.Dispose(); - OutputStream = null; - } - } - - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) - { - if (InputStream == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, - "Cannot read from null inputstream"); - } - - return await InputStream.ReadAsync(buffer, offset, length, cancellationToken); - } - - public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) - { - if (OutputStream == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, - "Cannot write to null outputstream"); - } - - await OutputStream.WriteAsync(buffer, offset, length, cancellationToken); - } - - public override async Task FlushAsync(CancellationToken cancellationToken) - { - await OutputStream.FlushAsync(cancellationToken); - } - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_isDisposed) - { - if (disposing) - { - InputStream?.Dispose(); - OutputStream?.Dispose(); - } - } - _isDisposed = true; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs b/lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs deleted file mode 100644 index c8be4ede188..00000000000 --- a/lib/netcore/Thrift/Transports/Client/TTlsSocketClientTransport.cs +++ /dev/null @@ -1,237 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Net; -using System.Net.Security; -using System.Net.Sockets; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Transports.Client -{ - //TODO: check for correct work - - // ReSharper disable once InconsistentNaming - public class TTlsSocketClientTransport : TStreamClientTransport - { - private readonly X509Certificate2 _certificate; - private readonly RemoteCertificateValidationCallback _certValidator; - private readonly IPAddress _host; - private readonly bool _isServer; - private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; - private readonly int _port; - private readonly SslProtocols _sslProtocols; - private TcpClient _client; - private SslStream _secureStream; - private int _timeout; - - public TTlsSocketClientTransport(TcpClient client, X509Certificate2 certificate, bool isServer = false, - RemoteCertificateValidationCallback certValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - SslProtocols sslProtocols = SslProtocols.Tls12) - { - _client = client; - _certificate = certificate; - _certValidator = certValidator; - _localCertificateSelectionCallback = localCertificateSelectionCallback; - _sslProtocols = sslProtocols; - _isServer = isServer; - - if (isServer && certificate == null) - { - throw new ArgumentException("TTlsSocketClientTransport needs certificate to be used for server", - nameof(certificate)); - } - - if (IsOpen) - { - InputStream = client.GetStream(); - OutputStream = client.GetStream(); - } - } - - public TTlsSocketClientTransport(IPAddress host, int port, string certificatePath, - RemoteCertificateValidationCallback certValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - SslProtocols sslProtocols = SslProtocols.Tls12) - : this(host, port, 0, - new X509Certificate2(certificatePath), - certValidator, - localCertificateSelectionCallback, - sslProtocols) - { - } - - public TTlsSocketClientTransport(IPAddress host, int port, - X509Certificate2 certificate = null, - RemoteCertificateValidationCallback certValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - SslProtocols sslProtocols = SslProtocols.Tls12) - : this(host, port, 0, - certificate, - certValidator, - localCertificateSelectionCallback, - sslProtocols) - { - } - - public TTlsSocketClientTransport(IPAddress host, int port, int timeout, - X509Certificate2 certificate, - RemoteCertificateValidationCallback certValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - SslProtocols sslProtocols = SslProtocols.Tls12) - { - _host = host; - _port = port; - _timeout = timeout; - _certificate = certificate; - _certValidator = certValidator; - _localCertificateSelectionCallback = localCertificateSelectionCallback; - _sslProtocols = sslProtocols; - - InitSocket(); - } - - public int Timeout - { - set { _client.ReceiveTimeout = _client.SendTimeout = _timeout = value; } - } - - public TcpClient TcpClient => _client; - - public IPAddress Host => _host; - - public int Port => _port; - - public override bool IsOpen - { - get - { - if (_client == null) - { - return false; - } - - return _client.Connected; - } - } - - private void InitSocket() - { - _client = new TcpClient(); - _client.ReceiveTimeout = _client.SendTimeout = _timeout; - _client.Client.NoDelay = true; - } - - private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, - SslPolicyErrors sslValidationErrors) - { - return sslValidationErrors == SslPolicyErrors.None; - } - - public override async Task OpenAsync(CancellationToken cancellationToken) - { - if (IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); - } - - if (_host == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); - } - - if (_port <= 0) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); - } - - if (_client == null) - { - InitSocket(); - } - - if (_client != null) - { - await _client.ConnectAsync(_host, _port); - await SetupTlsAsync(); - } - } - - public async Task SetupTlsAsync() - { - var validator = _certValidator ?? DefaultCertificateValidator; - - if (_localCertificateSelectionCallback != null) - { - _secureStream = new SslStream(_client.GetStream(), false, validator, _localCertificateSelectionCallback); - } - else - { - _secureStream = new SslStream(_client.GetStream(), false, validator); - } - - try - { - if (_isServer) - { - // Server authentication - await - _secureStream.AuthenticateAsServerAsync(_certificate, _certValidator != null, _sslProtocols, - true); - } - else - { - // Client authentication - var certs = _certificate != null - ? new X509CertificateCollection {_certificate} - : new X509CertificateCollection(); - - var targetHost = _host.ToString(); - await _secureStream.AuthenticateAsClientAsync(targetHost, certs, _sslProtocols, true); - } - } - catch (Exception) - { - Close(); - throw; - } - - InputStream = _secureStream; - OutputStream = _secureStream; - } - - public override void Close() - { - base.Close(); - if (_client != null) - { - _client.Dispose(); - _client = null; - } - - if (_secureStream != null) - { - _secureStream.Dispose(); - _secureStream = null; - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs b/lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs deleted file mode 100644 index 032063a3778..00000000000 --- a/lib/netcore/Thrift/Transports/Server/THttpServerTransport.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Logging; -using Thrift.Protocols; -using Thrift.Transports.Client; - -namespace Thrift.Transports.Server -{ - // ReSharper disable once InconsistentNaming - public class THttpServerTransport - { - protected const string ContentType = "application/x-thrift"; - private readonly ILogger _logger; - private readonly RequestDelegate _next; - protected Encoding Encoding = Encoding.UTF8; - - protected ITProtocolFactory InputProtocolFactory; - protected ITProtocolFactory OutputProtocolFactory; - - protected ITAsyncProcessor Processor; - - public THttpServerTransport(ITAsyncProcessor processor, RequestDelegate next, ILoggerFactory loggerFactory) - : this(processor, new TBinaryProtocol.Factory(), next, loggerFactory) - { - } - - public THttpServerTransport(ITAsyncProcessor processor, ITProtocolFactory protocolFactory, RequestDelegate next, - ILoggerFactory loggerFactory) - : this(processor, protocolFactory, protocolFactory, next, loggerFactory) - { - } - - public THttpServerTransport(ITAsyncProcessor processor, ITProtocolFactory inputProtocolFactory, - ITProtocolFactory outputProtocolFactory, RequestDelegate next, ILoggerFactory loggerFactory) - { - if (loggerFactory == null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - Processor = processor ?? throw new ArgumentNullException(nameof(processor)); - InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory)); - OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory)); - - _next = next; - _logger = loggerFactory.CreateLogger(); - } - - public async Task Invoke(HttpContext context) - { - context.Response.ContentType = ContentType; - await ProcessRequestAsync(context, context.RequestAborted); //TODO: check for correct logic - } - - public async Task ProcessRequestAsync(HttpContext context, CancellationToken cancellationToken) - { - var transport = new TStreamClientTransport(context.Request.Body, context.Response.Body); - - try - { - var input = InputProtocolFactory.GetProtocol(transport); - var output = OutputProtocolFactory.GetProtocol(transport); - - while (await Processor.ProcessAsync(input, output, cancellationToken)) - { - } - } - catch (TTransportException) - { - // Client died, just move on - } - finally - { - transport.Close(); - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs b/lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs deleted file mode 100644 index 186786ed256..00000000000 --- a/lib/netcore/Thrift/Transports/Server/TNamedPipeServerTransport.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.IO.Pipes; -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Transports.Server -{ - // ReSharper disable once InconsistentNaming - public class TNamedPipeServerTransport : TServerTransport - { - /// - /// This is the address of the Pipe on the localhost. - /// - private readonly string _pipeAddress; - - private bool _asyncMode = true; - private volatile bool _isPending = true; - - private NamedPipeServerStream _stream = null; - - public TNamedPipeServerTransport(string pipeAddress) - { - _pipeAddress = pipeAddress; - } - - public override void Listen() - { - // nothing to do here - } - - public override void Close() - { - if (_stream != null) - { - try - { - //TODO: check for disconection - _stream.Disconnect(); - _stream.Dispose(); - } - finally - { - _stream = null; - _isPending = false; - } - } - } - - public override bool IsClientPending() - { - return _isPending; - } - - private void EnsurePipeInstance() - { - if (_stream == null) - { - var direction = PipeDirection.InOut; - var maxconn = 254; - var mode = PipeTransmissionMode.Byte; - var options = _asyncMode ? PipeOptions.Asynchronous : PipeOptions.None; - var inbuf = 4096; - var outbuf = 4096; - // TODO: security - - try - { - _stream = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, outbuf); - } - catch (NotImplementedException) // Mono still does not support async, fallback to sync - { - if (_asyncMode) - { - options &= (~PipeOptions.Asynchronous); - _stream = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, - outbuf); - _asyncMode = false; - } - else - { - throw; - } - } - } - } - - protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) - { - try - { - EnsurePipeInstance(); - - await _stream.WaitForConnectionAsync(cancellationToken); - - var trans = new ServerTransport(_stream); - _stream = null; // pass ownership to ServerTransport - - //_isPending = false; - - return trans; - } - catch (TTransportException) - { - Close(); - throw; - } - catch (Exception e) - { - Close(); - throw new TTransportException(TTransportException.ExceptionType.NotOpen, e.Message); - } - } - - private class ServerTransport : TClientTransport - { - private readonly NamedPipeServerStream _stream; - - public ServerTransport(NamedPipeServerStream stream) - { - _stream = stream; - } - - public override bool IsOpen => _stream != null && _stream.IsConnected; - - public override async Task OpenAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - public override void Close() - { - _stream?.Dispose(); - } - - public override async Task ReadAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) - { - if (_stream == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - return await _stream.ReadAsync(buffer, offset, length, cancellationToken); - } - - public override async Task WriteAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) - { - if (_stream == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - await _stream.WriteAsync(buffer, offset, length, cancellationToken); - } - - public override async Task FlushAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - } - - protected override void Dispose(bool disposing) - { - _stream?.Dispose(); - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Server/TServerFramedTransport.cs b/lib/netcore/Thrift/Transports/Server/TServerFramedTransport.cs deleted file mode 100644 index 0b86e9ebba1..00000000000 --- a/lib/netcore/Thrift/Transports/Server/TServerFramedTransport.cs +++ /dev/null @@ -1,150 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Transports.Client; - -namespace Thrift.Transports.Server -{ - // ReSharper disable once InconsistentNaming - public class TServerFramedTransport : TServerTransport - { - private readonly int _clientTimeout; - private readonly int _port; - private TcpListener _server; - - public TServerFramedTransport(TcpListener listener) - : this(listener, 0) - { - } - - public TServerFramedTransport(TcpListener listener, int clientTimeout) - { - _server = listener; - _clientTimeout = clientTimeout; - } - - public TServerFramedTransport(int port) - : this(port, 0) - { - } - - public TServerFramedTransport(int port, int clientTimeout) - { - _port = port; - _clientTimeout = clientTimeout; - try - { - // Make server socket - _server = new TcpListener(IPAddress.Any, _port); - _server.Server.NoDelay = true; - } - catch (Exception) - { - _server = null; - throw new TTransportException("Could not create ServerSocket on port " + port + "."); - } - } - - public override void Listen() - { - // Make sure not to block on accept - if (_server != null) - { - try - { - _server.Start(); - } - catch (SocketException sx) - { - throw new TTransportException("Could not accept on listening socket: " + sx.Message); - } - } - } - - public override bool IsClientPending() - { - return _server.Pending(); - } - - protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - if (_server == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); - } - - try - { - TFramedClientTransport tSocketTransport = null; - var tcpClient = await _server.AcceptTcpClientAsync(); - - try - { - tSocketTransport = new TFramedClientTransport(new TSocketClientTransport(tcpClient) - { - Timeout = _clientTimeout - }); - - return tSocketTransport; - } - catch (Exception) - { - if (tSocketTransport != null) - { - tSocketTransport.Dispose(); - } - else // Otherwise, clean it up ourselves. - { - ((IDisposable) tcpClient).Dispose(); - } - - throw; - } - } - catch (Exception ex) - { - throw new TTransportException(ex.ToString()); - } - } - - public override void Close() - { - if (_server != null) - { - try - { - _server.Stop(); - } - catch (Exception ex) - { - throw new TTransportException("WARNING: Could not close server socket: " + ex); - } - _server = null; - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs b/lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs deleted file mode 100644 index 3a9d8a17d0a..00000000000 --- a/lib/netcore/Thrift/Transports/Server/TServerSocketTransport.cs +++ /dev/null @@ -1,174 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Transports.Client; - -namespace Thrift.Transports.Server -{ - // ReSharper disable once InconsistentNaming - public class TServerSocketTransport : TServerTransport - { - private readonly int _clientTimeout; - private readonly int _port; - private readonly bool _useBufferedSockets; - private readonly bool _useFramedTransport; - private TcpListener _server; - - public TServerSocketTransport(TcpListener listener) - : this(listener, 0) - { - } - - public TServerSocketTransport(TcpListener listener, int clientTimeout) - { - _server = listener; - _clientTimeout = clientTimeout; - } - - public TServerSocketTransport(int port) - : this(port, 0) - { - } - - public TServerSocketTransport(int port, int clientTimeout) - : this(port, clientTimeout, false) - { - } - - public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets): - this(port, clientTimeout, useBufferedSockets, false) - { - } - - public TServerSocketTransport(int port, int clientTimeout, bool useBufferedSockets, bool useFramedTransport) - { - _port = port; - _clientTimeout = clientTimeout; - _useBufferedSockets = useBufferedSockets; - _useFramedTransport = useFramedTransport; - try - { - // Make server socket - _server = new TcpListener(IPAddress.Any, _port); - _server.Server.NoDelay = true; - } - catch (Exception) - { - _server = null; - throw new TTransportException("Could not create ServerSocket on port " + port + "."); - } - } - - public override void Listen() - { - // Make sure not to block on accept - if (_server != null) - { - try - { - _server.Start(); - } - catch (SocketException sx) - { - throw new TTransportException("Could not accept on listening socket: " + sx.Message); - } - } - } - - public override bool IsClientPending() - { - return _server.Pending(); - } - - protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - if (_server == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); - } - - try - { - TClientTransport tSocketTransport = null; - var tcpClient = await _server.AcceptTcpClientAsync(); - - try - { - tSocketTransport = new TSocketClientTransport(tcpClient) - { - Timeout = _clientTimeout - }; - - if (_useBufferedSockets) - { - tSocketTransport = new TBufferedClientTransport(tSocketTransport); - } - - if (_useFramedTransport) - { - tSocketTransport = new TFramedClientTransport(tSocketTransport); - } - - return tSocketTransport; - } - catch (Exception) - { - if (tSocketTransport != null) - { - tSocketTransport.Dispose(); - } - else // Otherwise, clean it up ourselves. - { - ((IDisposable) tcpClient).Dispose(); - } - - throw; - } - } - catch (Exception ex) - { - throw new TTransportException(ex.ToString()); - } - } - - public override void Close() - { - if (_server != null) - { - try - { - _server.Stop(); - } - catch (Exception ex) - { - throw new TTransportException("WARNING: Could not close server socket: " + ex); - } - _server = null; - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs b/lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs deleted file mode 100644 index 759feeddd8d..00000000000 --- a/lib/netcore/Thrift/Transports/Server/TTlsServerSocketTransport.cs +++ /dev/null @@ -1,177 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Net; -using System.Net.Security; -using System.Net.Sockets; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Transports.Client; - -namespace Thrift.Transports.Server -{ - // ReSharper disable once InconsistentNaming - public class TTlsServerSocketTransport : TServerTransport - { - private readonly RemoteCertificateValidationCallback _clientCertValidator; - private readonly int _clientTimeout = 0; - private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; - private readonly int _port; - private readonly X509Certificate2 _serverCertificate; - private readonly SslProtocols _sslProtocols; - private readonly bool _useBufferedSockets; - private readonly bool _useFramedTransport; - private TcpListener _server; - - public TTlsServerSocketTransport(int port, X509Certificate2 certificate) - : this(port, false, certificate) - { - } - - public TTlsServerSocketTransport( - int port, - bool useBufferedSockets, - X509Certificate2 certificate, - RemoteCertificateValidationCallback clientCertValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - SslProtocols sslProtocols = SslProtocols.Tls12) - : this(port, useBufferedSockets, false, certificate, - clientCertValidator, localCertificateSelectionCallback, sslProtocols) - { - } - - public TTlsServerSocketTransport( - int port, - bool useBufferedSockets, - bool useFramedTransport, - X509Certificate2 certificate, - RemoteCertificateValidationCallback clientCertValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - SslProtocols sslProtocols = SslProtocols.Tls12) - { - if (!certificate.HasPrivateKey) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, - "Your server-certificate needs to have a private key"); - } - - _port = port; - _serverCertificate = certificate; - _useBufferedSockets = useBufferedSockets; - _useFramedTransport = useFramedTransport; - _clientCertValidator = clientCertValidator; - _localCertificateSelectionCallback = localCertificateSelectionCallback; - _sslProtocols = sslProtocols; - - try - { - // Create server socket - _server = new TcpListener(IPAddress.Any, _port); - _server.Server.NoDelay = true; - } - catch (Exception) - { - _server = null; - throw new TTransportException($"Could not create ServerSocket on port {port}."); - } - } - - public override void Listen() - { - // Make sure accept is not blocking - if (_server != null) - { - try - { - _server.Start(); - } - catch (SocketException sx) - { - throw new TTransportException($"Could not accept on listening socket: {sx.Message}"); - } - } - } - - public override bool IsClientPending() - { - return _server.Pending(); - } - - protected override async Task AcceptImplementationAsync(CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - if (_server == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); - } - - try - { - var client = await _server.AcceptTcpClientAsync(); - client.SendTimeout = client.ReceiveTimeout = _clientTimeout; - - //wrap the client in an SSL Socket passing in the SSL cert - var tTlsSocket = new TTlsSocketClientTransport(client, _serverCertificate, true, _clientCertValidator, - _localCertificateSelectionCallback, _sslProtocols); - - await tTlsSocket.SetupTlsAsync(); - - TClientTransport trans = tTlsSocket; - - if (_useBufferedSockets) - { - trans = new TBufferedClientTransport(trans); - } - - if (_useFramedTransport) - { - trans = new TFramedClientTransport(trans); - } - - return trans; - } - catch (Exception ex) - { - throw new TTransportException(ex.ToString()); - } - } - - public override void Close() - { - if (_server != null) - { - try - { - _server.Stop(); - } - catch (Exception ex) - { - throw new TTransportException($"WARNING: Could not close server socket: {ex}"); - } - - _server = null; - } - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/TClientTransport.cs b/lib/netcore/Thrift/Transports/TClientTransport.cs deleted file mode 100644 index 0dd96cb36fc..00000000000 --- a/lib/netcore/Thrift/Transports/TClientTransport.cs +++ /dev/null @@ -1,179 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Transports -{ - //TODO: think about client info - // ReSharper disable once InconsistentNaming - public abstract class TClientTransport : IDisposable - { - //TODO: think how to avoid peek byte - private readonly byte[] _peekBuffer = new byte[1]; - private bool _hasPeekByte; - public abstract bool IsOpen { get; } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - public async Task PeekAsync(CancellationToken cancellationToken) - { - //If we already have a byte read but not consumed, do nothing. - if (_hasPeekByte) - { - return true; - } - - //If transport closed we can't peek. - if (!IsOpen) - { - return false; - } - - //Try to read one byte. If succeeds we will need to store it for the next read. - try - { - var bytes = await ReadAsync(_peekBuffer, 0, 1, cancellationToken); - if (bytes == 0) - { - return false; - } - } - catch (IOException) - { - return false; - } - - _hasPeekByte = true; - return true; - } - - public virtual async Task OpenAsync() - { - await OpenAsync(CancellationToken.None); - } - - public abstract Task OpenAsync(CancellationToken cancellationToken); - - public abstract void Close(); - - protected static void ValidateBufferArgs(byte[] buffer, int offset, int length) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - if (offset < 0) - { - throw new ArgumentOutOfRangeException(nameof(offset), "Buffer offset is smaller than zero."); - } - - if (length < 0) - { - throw new ArgumentOutOfRangeException(nameof(length), "Buffer length is smaller than zero."); - } - - if (offset + length > buffer.Length) - { - throw new ArgumentOutOfRangeException(nameof(buffer), "Not enough data."); - } - } - - public virtual async Task ReadAsync(byte[] buffer, int offset, int length) - { - return await ReadAsync(buffer, offset, length, CancellationToken.None); - } - - public abstract Task ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); - - public virtual async Task ReadAllAsync(byte[] buffer, int offset, int length) - { - return await ReadAllAsync(buffer, offset, length, CancellationToken.None); - } - - public virtual async Task ReadAllAsync(byte[] buffer, int offset, int length, - CancellationToken cancellationToken) - { - ValidateBufferArgs(buffer, offset, length); - - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var retrieved = 0; - - //If we previously peeked a byte, we need to use that first. - if (_hasPeekByte) - { - buffer[offset + retrieved++] = _peekBuffer[0]; - _hasPeekByte = false; - } - - while (retrieved < length) - { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - var returnedCount = await ReadAsync(buffer, offset + retrieved, length - retrieved, cancellationToken); - if (returnedCount <= 0) - { - throw new TTransportException(TTransportException.ExceptionType.EndOfFile, - "Cannot read, Remote side has closed"); - } - retrieved += returnedCount; - } - return retrieved; - } - - public virtual async Task WriteAsync(byte[] buffer) - { - await WriteAsync(buffer, CancellationToken.None); - } - - public virtual async Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) - { - await WriteAsync(buffer, 0, buffer.Length, CancellationToken.None); - } - - public virtual async Task WriteAsync(byte[] buffer, int offset, int length) - { - await WriteAsync(buffer, offset, length, CancellationToken.None); - } - - public abstract Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); - - public virtual async Task FlushAsync() - { - await FlushAsync(CancellationToken.None); - } - - public abstract Task FlushAsync(CancellationToken cancellationToken); - - protected abstract void Dispose(bool disposing); - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/TServerTransport.cs b/lib/netcore/Thrift/Transports/TServerTransport.cs deleted file mode 100644 index 0d45a55f9b5..00000000000 --- a/lib/netcore/Thrift/Transports/TServerTransport.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Threading; -using System.Threading.Tasks; - -namespace Thrift.Transports -{ - // ReSharper disable once InconsistentNaming - public abstract class TServerTransport - { - public abstract void Listen(); - public abstract void Close(); - public abstract bool IsClientPending(); - - protected virtual async Task AcceptImplementationAsync() - { - return await AcceptImplementationAsync(CancellationToken.None); - } - - protected abstract Task AcceptImplementationAsync(CancellationToken cancellationToken); - - public async Task AcceptAsync() - { - return await AcceptAsync(CancellationToken.None); - } - - public async Task AcceptAsync(CancellationToken cancellationToken) - { - var transport = await AcceptImplementationAsync(cancellationToken); - - if (transport == null) - { - throw new TTransportException($"{nameof(AcceptImplementationAsync)} should not return null"); - } - - return transport; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/TTransportException.cs b/lib/netcore/Thrift/Transports/TTransportException.cs deleted file mode 100644 index b7c42e33a87..00000000000 --- a/lib/netcore/Thrift/Transports/TTransportException.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -namespace Thrift.Transports -{ - // ReSharper disable once InconsistentNaming - public class TTransportException : TException - { - public enum ExceptionType - { - Unknown, - NotOpen, - AlreadyOpen, - TimedOut, - EndOfFile, - Interrupted - } - - protected ExceptionType ExType; - - public TTransportException() - { - } - - public TTransportException(ExceptionType exType) - : this() - { - ExType = exType; - } - - public TTransportException(ExceptionType exType, string message) - : base(message) - { - ExType = exType; - } - - public TTransportException(string message) - : base(message) - { - } - - public ExceptionType Type => ExType; - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/Transports/TTransportFactory.cs b/lib/netcore/Thrift/Transports/TTransportFactory.cs deleted file mode 100644 index 26c3cc4714d..00000000000 --- a/lib/netcore/Thrift/Transports/TTransportFactory.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -namespace Thrift.Transports -{ - /// - /// From Mark Slee & Aditya Agarwal of Facebook: - /// 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) - /// - // ReSharper disable once InconsistentNaming - public class TTransportFactory - { - public virtual TClientTransport GetTransport(TClientTransport trans) - { - return trans; - } - } -} \ No newline at end of file diff --git a/lib/netcore/Thrift/thrift.snk b/lib/netcore/Thrift/thrift.snk deleted file mode 100644 index 97bc5812b81ce10bd7a3e7fa85ffe4fca58837a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096M(P*E7L9A{Nz%0-6F4Ni!Qh(Kbg{5KA z2E1b23-+!Xd}C$U<2C<(&MT@p-O1qWT;=lE^6FoDjaj)hfK()avE=qA0UjD_dnyJKp4oD4IAF%k%(##bch;%0k!ErNuo!=V%U6um{k+ zxGJw2Q3!4o9q~6a_(HZlq8e8vm^F-F8s*Oq9GC*du(tuh3*S(r46R#&$m*dVSmw9< zkJro_Em0r8sB0u|@B$Ms&W(3}U!PWN$0Rb0UTs5hRh#5^;9Sd{Oc1;2rF@$Tv@h%{ iLR4J<2AKHW9M~)kpNz1bB-?e{-!;;q{yCP(dwHkK- diff --git a/lib/netcore/build.cmd b/lib/netcore/build.cmd deleted file mode 100644 index 863c4b45eae..00000000000 --- a/lib/netcore/build.cmd +++ /dev/null @@ -1,27 +0,0 @@ -@echo off -rem /* -rem * Licensed to the Apache Software Foundation (ASF) under one -rem * or more contributor license agreements. See the NOTICE file -rem * distributed with this work for additional information -rem * regarding copyright ownership. The ASF licenses this file -rem * to you under the Apache License, Version 2.0 (the -rem * "License"); you may not use this file except in compliance -rem * with the License. You may obtain a copy of the License at -rem * -rem * http://www.apache.org/licenses/LICENSE-2.0 -rem * -rem * Unless required by applicable law or agreed to in writing, -rem * software distributed under the License is distributed on an -rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -rem * KIND, either express or implied. See the License for the -rem * specific language governing permissions and limitations -rem * under the License. -rem */ - -setlocal - -thrift -version -dotnet --info -dotnet build - -:eof diff --git a/lib/netcore/build.sh b/lib/netcore/build.sh deleted file mode 100644 index ae18bce9bf2..00000000000 --- a/lib/netcore/build.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -#exit if any command fails -#set -e - -thrift --version -dotnet --info -dotnet build - -#revision=${TRAVIS_JOB_ID:=1} -#revision=$(printf "%04d" $revision) - -#dotnet pack ./src/PROJECT_NAME -c Release -o ./artifacts --version-suffix=$revision diff --git a/lib/netcore/runtests.cmd b/lib/netcore/runtests.cmd deleted file mode 100644 index 5114bc594d8..00000000000 --- a/lib/netcore/runtests.cmd +++ /dev/null @@ -1,28 +0,0 @@ -@echo off -rem /* -rem * Licensed to the Apache Software Foundation (ASF) under one -rem * or more contributor license agreements. See the NOTICE file -rem * distributed with this work for additional information -rem * regarding copyright ownership. The ASF licenses this file -rem * to you under the Apache License, Version 2.0 (the -rem * "License"); you may not use this file except in compliance -rem * with the License. You may obtain a copy of the License at -rem * -rem * http://www.apache.org/licenses/LICENSE-2.0 -rem * -rem * Unless required by applicable law or agreed to in writing, -rem * software distributed under the License is distributed on an -rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -rem * KIND, either express or implied. See the License for the -rem * specific language governing permissions and limitations -rem * under the License. -rem */ -setlocal - -thrift -version -dotnet --info - -dotnet test Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj -dotnet test Tests\Thrift.Tests\Thrift.Tests.csproj - -:eof diff --git a/lib/netcore/runtests.sh b/lib/netcore/runtests.sh deleted file mode 100644 index a26cc36ac23..00000000000 --- a/lib/netcore/runtests.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -thrift -version -dotnet --info - -dotnet test Tests\Thrift.IntegrationTests\Thrift.IntegrationTests.csproj -dotnet test Tests\Thrift.Tests\Thrift.Tests.csproj \ No newline at end of file diff --git a/lib/netstd/Makefile.am b/lib/netstd/Makefile.am index f6faacae5ba..bb2aac5a8c3 100644 --- a/lib/netstd/Makefile.am +++ b/lib/netstd/Makefile.am @@ -24,7 +24,7 @@ all-local: check-local: $(DOTNETCORE) test Tests/Thrift.Tests/Thrift.Tests.csproj - ${DOTNETCORE} test Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj + $(DOTNETCORE) test Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj clean-local: $(RM) -r Thrift/bin diff --git a/test/Makefile.am b/test/Makefile.am index c2fbbd45941..fdb2645bd0b 100755 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -78,7 +78,6 @@ SUBDIRS += haxe endif if WITH_DOTNET -SUBDIRS += netcore SUBDIRS += netstd endif diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift index cf28b2adf13..bdc6d879d08 100644 --- a/test/ThriftTest.thrift +++ b/test/ThriftTest.thrift @@ -29,7 +29,6 @@ namespace go thrifttest namespace java thrift.test namespace js ThriftTest namespace lua ThriftTest -namespace netcore ThriftTest namespace netstd ThriftTest namespace perl ThriftTest namespace php ThriftTest diff --git a/test/netcore/Client/.gitignore b/test/netcore/Client/.gitignore deleted file mode 100644 index 67d55106a4b..00000000000 --- a/test/netcore/Client/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# ignore for autogenerated files -/ThriftTest diff --git a/test/netcore/Client/Client.csproj b/test/netcore/Client/Client.csproj deleted file mode 100644 index f16af390a52..00000000000 --- a/test/netcore/Client/Client.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - netcoreapp2.0 - Client - Client - Exe - false - false - false - false - false - false - - - - - - - - - - - - - - - - - - - diff --git a/test/netcore/Client/Program.cs b/test/netcore/Client/Program.cs deleted file mode 100644 index 72139d9def5..00000000000 --- a/test/netcore/Client/Program.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using ThriftTest; - -namespace Client -{ - public class Program - { - public static int Main(string[] args) - { - try - { - Console.SetBufferSize(Console.BufferWidth, 4096); - } - catch (Exception) - { - Console.WriteLine("Failed to grow scroll-back buffer"); - } - - // split mode and options - var subArgs = new List(args); - var firstArg = string.Empty; - if (subArgs.Count > 0) - { - firstArg = subArgs[0]; - subArgs.RemoveAt(0); - } - - // run whatever mode is choosen - switch(firstArg) - { - case "client": - return TestClient.Execute(subArgs); - case "--help": - PrintHelp(); - return 0; - default: - PrintHelp(); - return -1; - } - } - - private static void PrintHelp() - { - Console.WriteLine("Usage:"); - Console.WriteLine(" Client client [options]'"); - Console.WriteLine(" Client --help"); - Console.WriteLine(""); - - TestClient.PrintOptionsHelp(); - } - } -} - - diff --git a/test/netcore/Client/Properties/AssemblyInfo.cs b/test/netcore/Client/Properties/AssemblyInfo.cs deleted file mode 100644 index 157152b4dbb..00000000000 --- a/test/netcore/Client/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyTitle("Client")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("B0C13DA0-3117-4844-8AE8-B1775E46223D")] - diff --git a/test/netcore/Client/TestClient.cs b/test/netcore/Client/TestClient.cs deleted file mode 100644 index 8be198c692a..00000000000 --- a/test/netcore/Client/TestClient.cs +++ /dev/null @@ -1,943 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Net; -using System.Reflection; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; -using System.ServiceModel; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Thrift.Collections; -using Thrift.Protocols; -using Thrift.Transports; -using Thrift.Transports.Client; - -namespace ThriftTest -{ - public class TestClient - { - private class TestParams - { - public int numIterations = 1; - public IPAddress host = IPAddress.Any; - public int port = 9090; - public int numThreads = 1; - public string url; - public string pipe; - public bool buffered; - public bool framed; - public string protocol; - public bool encrypted = false; - - internal void Parse( List args) - { - for (var i = 0; i < args.Count; ++i) - { - if (args[i] == "-u") - { - url = args[++i]; - } - else if (args[i] == "-n") - { - numIterations = Convert.ToInt32(args[++i]); - } - else if (args[i].StartsWith("--pipe=")) - { - pipe = args[i].Substring(args[i].IndexOf("=") + 1); - Console.WriteLine("Using named pipes transport"); - } - else if (args[i].StartsWith("--host=")) - { - // check there for ipaddress - host = new IPAddress(Encoding.Unicode.GetBytes(args[i].Substring(args[i].IndexOf("=") + 1))); - } - else if (args[i].StartsWith("--port=")) - { - port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); - } - else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") - { - buffered = true; - Console.WriteLine("Using buffered sockets"); - } - else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") - { - framed = true; - Console.WriteLine("Using framed transport"); - } - else if (args[i] == "-t") - { - numThreads = Convert.ToInt32(args[++i]); - } - else if (args[i] == "--binary" || args[i] == "--protocol=binary") - { - protocol = "binary"; - Console.WriteLine("Using binary protocol"); - } - else if (args[i] == "--compact" || args[i] == "--protocol=compact") - { - protocol = "compact"; - Console.WriteLine("Using compact protocol"); - } - else if (args[i] == "--json" || args[i] == "--protocol=json") - { - protocol = "json"; - Console.WriteLine("Using JSON protocol"); - } - else if (args[i] == "--ssl") - { - encrypted = true; - Console.WriteLine("Using encrypted transport"); - } - else - { - //throw new ArgumentException(args[i]); - } - } - } - - private static X509Certificate2 GetClientCert() - { - var clientCertName = "client.p12"; - var possiblePaths = new List - { - "../../../keys/", - "../../keys/", - "../keys/", - "keys/", - }; - - string existingPath = null; - foreach (var possiblePath in possiblePaths) - { - var path = Path.GetFullPath(possiblePath + clientCertName); - if (File.Exists(path)) - { - existingPath = path; - break; - } - } - - if (string.IsNullOrEmpty(existingPath)) - { - throw new FileNotFoundException($"Cannot find file: {clientCertName}"); - } - - var cert = new X509Certificate2(existingPath, "thrift"); - - return cert; - } - - public TClientTransport CreateTransport() - { - if (url == null) - { - // endpoint transport - TClientTransport trans = null; - - if (pipe != null) - { - trans = new TNamedPipeClientTransport(pipe); - } - else - { - if (encrypted) - { - var cert = GetClientCert(); - - if (cert == null || !cert.HasPrivateKey) - { - throw new InvalidOperationException("Certificate doesn't contain private key"); - } - - trans = new TTlsSocketClientTransport(host, port, 0, cert, - (sender, certificate, chain, errors) => true, - null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); - } - else - { - trans = new TSocketClientTransport(host, port); - } - } - - // layered transport - if (buffered) - { - trans = new TBufferedClientTransport(trans); - } - - if (framed) - { - trans = new TFramedClientTransport(trans); - } - - return trans; - } - - return new THttpClientTransport(new Uri(url), null); - } - - public TProtocol CreateProtocol(TClientTransport transport) - { - if (protocol == "compact") - { - return new TCompactProtocol(transport); - } - - if (protocol == "json") - { - return new TJsonProtocol(transport); - } - - return new TBinaryProtocol(transport); - } - } - - - private const int ErrorBaseTypes = 1; - private const int ErrorStructs = 2; - private const int ErrorContainers = 4; - private const int ErrorExceptions = 8; - private const int ErrorUnknown = 64; - - private class ClientTest - { - private readonly TClientTransport transport; - private readonly ThriftTest.Client client; - private readonly int numIterations; - private bool done; - - public int ReturnCode { get; set; } - - public ClientTest(TestParams param) - { - transport = param.CreateTransport(); - client = new ThriftTest.Client(param.CreateProtocol(transport)); - numIterations = param.numIterations; - } - - public void Execute() - { - var token = CancellationToken.None; - - if (done) - { - Console.WriteLine("Execute called more than once"); - throw new InvalidOperationException(); - } - - for (var i = 0; i < numIterations; i++) - { - try - { - if (!transport.IsOpen) - { - transport.OpenAsync(token).GetAwaiter().GetResult(); - } - } - catch (TTransportException ex) - { - Console.WriteLine("*** FAILED ***"); - Console.WriteLine("Connect failed: " + ex.Message); - ReturnCode |= ErrorUnknown; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - continue; - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - Console.WriteLine("Connect failed: " + ex.Message); - ReturnCode |= ErrorUnknown; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - continue; - } - - try - { - ReturnCode |= ExecuteClientTestAsync(client).GetAwaiter().GetResult(); ; - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - ReturnCode |= ErrorUnknown; - } - } - try - { - transport.Close(); - } - catch (Exception ex) - { - Console.WriteLine("Error while closing transport"); - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - done = true; - } - } - - internal static void PrintOptionsHelp() - { - Console.WriteLine("Client options:"); - Console.WriteLine(" -u "); - Console.WriteLine(" -t <# of threads to run> default = 1"); - Console.WriteLine(" -n <# of iterations> per thread"); - Console.WriteLine(" --pipe="); - Console.WriteLine(" --host="); - Console.WriteLine(" --port="); - Console.WriteLine(" --transport= one of buffered,framed (defaults to none)"); - Console.WriteLine(" --protocol= one of compact,json (defaults to binary)"); - Console.WriteLine(" --ssl"); - Console.WriteLine(); - } - - public static int Execute(List args) - { - try - { - var param = new TestParams(); - - try - { - param.Parse(args); - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - Console.WriteLine("Error while parsing arguments"); - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - return ErrorUnknown; - } - - var tests = Enumerable.Range(0, param.numThreads).Select(_ => new ClientTest(param)).ToArray(); - - //issue tests on separate threads simultaneously - var threads = tests.Select(test => new Task(test.Execute)).ToArray(); - var start = DateTime.Now; - foreach (var t in threads) - { - t.Start(); - } - - Task.WaitAll(threads); - - Console.WriteLine("Total time: " + (DateTime.Now - start)); - Console.WriteLine(); - return tests.Select(t => t.ReturnCode).Aggregate((r1, r2) => r1 | r2); - } - catch (Exception outerEx) - { - Console.WriteLine("*** FAILED ***"); - Console.WriteLine("Unexpected error"); - Console.WriteLine(outerEx.Message + " ST: " + outerEx.StackTrace); - return ErrorUnknown; - } - } - - public static string BytesToHex(byte[] data) - { - return BitConverter.ToString(data).Replace("-", string.Empty); - } - - public static byte[] PrepareTestData(bool randomDist) - { - var retval = new byte[0x100]; - var initLen = Math.Min(0x100, retval.Length); - - // linear distribution, unless random is requested - if (!randomDist) - { - for (var i = 0; i < initLen; ++i) - { - retval[i] = (byte)i; - } - return retval; - } - - // random distribution - for (var i = 0; i < initLen; ++i) - { - retval[i] = (byte)0; - } - var rnd = new Random(); - for (var i = 1; i < initLen; ++i) - { - while (true) - { - var nextPos = rnd.Next() % initLen; - if (retval[nextPos] == 0) - { - retval[nextPos] = (byte)i; - break; - } - } - } - return retval; - } - - public static async Task ExecuteClientTestAsync(ThriftTest.Client client) - { - var token = CancellationToken.None; - var returnCode = 0; - - Console.Write("testVoid()"); - await client.testVoidAsync(token); - Console.WriteLine(" = void"); - - Console.Write("testString(\"Test\")"); - var s = await client.testStringAsync("Test", token); - Console.WriteLine(" = \"" + s + "\""); - if ("Test" != s) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - Console.Write("testBool(true)"); - var t = await client.testBoolAsync((bool)true, token); - Console.WriteLine(" = " + t); - if (!t) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - Console.Write("testBool(false)"); - var f = await client.testBoolAsync((bool)false, token); - Console.WriteLine(" = " + f); - if (f) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - Console.Write("testByte(1)"); - var i8 = await client.testByteAsync((sbyte)1, token); - Console.WriteLine(" = " + i8); - if (1 != i8) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - Console.Write("testI32(-1)"); - var i32 = await client.testI32Async(-1, token); - Console.WriteLine(" = " + i32); - if (-1 != i32) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - Console.Write("testI64(-34359738368)"); - var i64 = await client.testI64Async(-34359738368, token); - Console.WriteLine(" = " + i64); - if (-34359738368 != i64) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - // TODO: Validate received message - Console.Write("testDouble(5.325098235)"); - var dub = await client.testDoubleAsync(5.325098235, token); - Console.WriteLine(" = " + dub); - if (5.325098235 != dub) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - Console.Write("testDouble(-0.000341012439638598279)"); - dub = await client.testDoubleAsync(-0.000341012439638598279, token); - Console.WriteLine(" = " + dub); - if (-0.000341012439638598279 != dub) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - var binOut = PrepareTestData(true); - Console.Write("testBinary(" + BytesToHex(binOut) + ")"); - try - { - var binIn = await client.testBinaryAsync(binOut, token); - Console.WriteLine(" = " + BytesToHex(binIn)); - if (binIn.Length != binOut.Length) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - for (var ofs = 0; ofs < Math.Min(binIn.Length, binOut.Length); ++ofs) - if (binIn[ofs] != binOut[ofs]) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - } - catch (Thrift.TApplicationException ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - - // binary equals? only with hashcode option enabled ... - Console.WriteLine("Test CrazyNesting"); - var one = new CrazyNesting(); - var two = new CrazyNesting(); - one.String_field = "crazy"; - two.String_field = "crazy"; - one.Binary_field = new byte[] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; - two.Binary_field = new byte[10] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; - if (typeof(CrazyNesting).GetMethod("Equals")?.DeclaringType == typeof(CrazyNesting)) - { - if (!one.Equals(two)) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorContainers; - throw new Exception("CrazyNesting.Equals failed"); - } - } - - // TODO: Validate received message - Console.Write("testStruct({\"Zero\", 1, -3, -5})"); - var o = new Xtruct(); - o.String_thing = "Zero"; - o.Byte_thing = (sbyte)1; - o.I32_thing = -3; - o.I64_thing = -5; - var i = await client.testStructAsync(o, token); - Console.WriteLine(" = {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}"); - - // TODO: Validate received message - Console.Write("testNest({1, {\"Zero\", 1, -3, -5}, 5})"); - var o2 = new Xtruct2(); - o2.Byte_thing = (sbyte)1; - o2.Struct_thing = o; - o2.I32_thing = 5; - var i2 = await client.testNestAsync(o2, token); - i = i2.Struct_thing; - Console.WriteLine(" = {" + i2.Byte_thing + ", {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}, " + i2.I32_thing + "}"); - - var mapout = new Dictionary(); - for (var j = 0; j < 5; j++) - { - mapout[j] = j - 10; - } - Console.Write("testMap({"); - var first = true; - foreach (var key in mapout.Keys) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(key + " => " + mapout[key]); - } - Console.Write("})"); - - var mapin = await client.testMapAsync(mapout, token); - - Console.Write(" = {"); - first = true; - foreach (var key in mapin.Keys) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(key + " => " + mapin[key]); - } - Console.WriteLine("}"); - - // TODO: Validate received message - var listout = new List(); - for (var j = -2; j < 3; j++) - { - listout.Add(j); - } - Console.Write("testList({"); - first = true; - foreach (var j in listout) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(j); - } - Console.Write("})"); - - var listin = await client.testListAsync(listout, token); - - Console.Write(" = {"); - first = true; - foreach (var j in listin) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(j); - } - Console.WriteLine("}"); - - //set - // TODO: Validate received message - var setout = new THashSet(); - for (var j = -2; j < 3; j++) - { - setout.Add(j); - } - Console.Write("testSet({"); - first = true; - foreach (int j in setout) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(j); - } - Console.Write("})"); - - var setin = await client.testSetAsync(setout, token); - - Console.Write(" = {"); - first = true; - foreach (int j in setin) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(j); - } - Console.WriteLine("}"); - - - Console.Write("testEnum(ONE)"); - var ret = await client.testEnumAsync(Numberz.ONE, token); - Console.WriteLine(" = " + ret); - if (Numberz.ONE != ret) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - Console.Write("testEnum(TWO)"); - ret = await client.testEnumAsync(Numberz.TWO, token); - Console.WriteLine(" = " + ret); - if (Numberz.TWO != ret) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - Console.Write("testEnum(THREE)"); - ret = await client.testEnumAsync(Numberz.THREE, token); - Console.WriteLine(" = " + ret); - if (Numberz.THREE != ret) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - Console.Write("testEnum(FIVE)"); - ret = await client.testEnumAsync(Numberz.FIVE, token); - Console.WriteLine(" = " + ret); - if (Numberz.FIVE != ret) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - Console.Write("testEnum(EIGHT)"); - ret = await client.testEnumAsync(Numberz.EIGHT, token); - Console.WriteLine(" = " + ret); - if (Numberz.EIGHT != ret) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - Console.Write("testTypedef(309858235082523)"); - var uid = await client.testTypedefAsync(309858235082523L, token); - Console.WriteLine(" = " + uid); - if (309858235082523L != uid) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - // TODO: Validate received message - Console.Write("testMapMap(1)"); - var mm = await client.testMapMapAsync(1, token); - Console.Write(" = {"); - foreach (var key in mm.Keys) - { - Console.Write(key + " => {"); - var m2 = mm[key]; - foreach (var k2 in m2.Keys) - { - Console.Write(k2 + " => " + m2[k2] + ", "); - } - Console.Write("}, "); - } - Console.WriteLine("}"); - - // TODO: Validate received message - var insane = new Insanity(); - insane.UserMap = new Dictionary(); - insane.UserMap[Numberz.FIVE] = 5000L; - var truck = new Xtruct(); - truck.String_thing = "Truck"; - truck.Byte_thing = (sbyte)8; - truck.I32_thing = 8; - truck.I64_thing = 8; - insane.Xtructs = new List(); - insane.Xtructs.Add(truck); - Console.Write("testInsanity()"); - var whoa = await client.testInsanityAsync(insane, token); - Console.Write(" = {"); - foreach (var key in whoa.Keys) - { - var val = whoa[key]; - Console.Write(key + " => {"); - - foreach (var k2 in val.Keys) - { - var v2 = val[k2]; - - Console.Write(k2 + " => {"); - var userMap = v2.UserMap; - - Console.Write("{"); - if (userMap != null) - { - foreach (var k3 in userMap.Keys) - { - Console.Write(k3 + " => " + userMap[k3] + ", "); - } - } - else - { - Console.Write("null"); - } - Console.Write("}, "); - - var xtructs = v2.Xtructs; - - Console.Write("{"); - if (xtructs != null) - { - foreach (var x in xtructs) - { - Console.Write("{\"" + x.String_thing + "\", " + x.Byte_thing + ", " + x.I32_thing + ", " + x.I32_thing + "}, "); - } - } - else - { - Console.Write("null"); - } - Console.Write("}"); - - Console.Write("}, "); - } - Console.Write("}, "); - } - Console.WriteLine("}"); - - sbyte arg0 = 1; - var arg1 = 2; - var arg2 = long.MaxValue; - var multiDict = new Dictionary(); - multiDict[1] = "one"; - - var tmpMultiDict = new List(); - foreach (var pair in multiDict) - tmpMultiDict.Add(pair.Key +" => "+ pair.Value); - - var arg4 = Numberz.FIVE; - long arg5 = 5000000; - Console.Write("Test Multi(" + arg0 + "," + arg1 + "," + arg2 + ",{" + string.Join(",", tmpMultiDict) + "}," + arg4 + "," + arg5 + ")"); - var multiResponse = await client.testMultiAsync(arg0, arg1, arg2, multiDict, arg4, arg5, token); - Console.Write(" = Xtruct(byte_thing:" + multiResponse.Byte_thing + ",String_thing:" + multiResponse.String_thing - + ",i32_thing:" + multiResponse.I32_thing + ",i64_thing:" + multiResponse.I64_thing + ")\n"); - - try - { - Console.WriteLine("testException(\"Xception\")"); - await client.testExceptionAsync("Xception", token); - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - catch (Xception ex) - { - if (ex.ErrorCode != 1001 || ex.Message != "Xception") - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - try - { - Console.WriteLine("testException(\"TException\")"); - await client.testExceptionAsync("TException", token); - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - catch (Thrift.TException) - { - // OK - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - try - { - Console.WriteLine("testException(\"ok\")"); - await client.testExceptionAsync("ok", token); - // OK - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - - try - { - Console.WriteLine("testMultiException(\"Xception\", ...)"); - await client.testMultiExceptionAsync("Xception", "ignore", token); - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - catch (Xception ex) - { - if (ex.ErrorCode != 1001 || ex.Message != "This is an Xception") - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - try - { - Console.WriteLine("testMultiException(\"Xception2\", ...)"); - await client.testMultiExceptionAsync("Xception2", "ignore", token); - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - catch (Xception2 ex) - { - if (ex.ErrorCode != 2002 || ex.Struct_thing.String_thing != "This is an Xception2") - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - try - { - Console.WriteLine("testMultiException(\"success\", \"OK\")"); - if ("OK" != (await client.testMultiExceptionAsync("success", "OK", token)).String_thing) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - - var sw = new Stopwatch(); - sw.Start(); - Console.WriteLine("Test Oneway(1)"); - await client.testOnewayAsync(1, token); - sw.Stop(); - if (sw.ElapsedMilliseconds > 1000) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - Console.Write("Test Calltime()"); - var times = 50; - sw.Reset(); - sw.Start(); - for (var k = 0; k < times; ++k) - await client.testVoidAsync(token); - sw.Stop(); - Console.WriteLine(" = {0} ms a testVoid() call", sw.ElapsedMilliseconds / times); - return returnCode; - } - } -} diff --git a/test/netcore/Makefile.am b/test/netcore/Makefile.am deleted file mode 100644 index 2fff4ba3a33..00000000000 --- a/test/netcore/Makefile.am +++ /dev/null @@ -1,50 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -SUBDIRS = . - -all-local: - $(DOTNETCORE) build - -precross: - $(DOTNETCORE) build - -clean-local: - $(RM) -r Client/bin - $(RM) -r Client/obj - $(RM) -r Client/ThriftTest - $(RM) -r Server/bin - $(RM) -r Server/obj - $(RM) -r Server/ThriftTest - -dist-hook: - $(RM) -r $(distdir)/Client/bin - $(RM) -r $(distdir)/Client/obj - $(RM) -r $(distdir)/Client/ThriftTest - $(RM) -r $(distdir)/Server/bin - $(RM) -r $(distdir)/Server/obj - $(RM) -r $(distdir)/Server/ThriftTest - -EXTRA_DIST = \ - Client \ - README.md \ - Server \ - ThriftTest.sln \ - build.cmd \ - build.sh diff --git a/test/netcore/README.md b/test/netcore/README.md deleted file mode 100644 index ed728d1bac4..00000000000 --- a/test/netcore/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Apache Thrift net-core-lib tests - -Tests for Thrift client library ported to Microsoft .Net Core - -# Content -- ThriftTest - tests for Thrift library - -# Reused components -- NET Core Standard 1.6 (SDK 2.0.0) - -# How to build on Windows -- Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable -- Open ThriftTest.sln in Visual Studio and build -or -- Build with scripts - -# How to build on Unix -- Ensure you have .NET Core 2.0.0 SDK installed or use the Ubuntu Xenial docker image -- Follow common build practice for Thrift: bootstrap, configure, and make precross - diff --git a/test/netcore/Server/.gitignore b/test/netcore/Server/.gitignore deleted file mode 100644 index 67d55106a4b..00000000000 --- a/test/netcore/Server/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# ignore for autogenerated files -/ThriftTest diff --git a/test/netcore/Server/Program.cs b/test/netcore/Server/Program.cs deleted file mode 100644 index e647e5b2a58..00000000000 --- a/test/netcore/Server/Program.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using ThriftTest; - -namespace Server -{ - public class Program - { - public static int Main(string[] args) - { - try - { - Console.SetBufferSize(Console.BufferWidth, 4096); - } - catch (Exception) - { - Console.WriteLine("Failed to grow scroll-back buffer"); - } - - // split mode and options - var subArgs = new List(args); - var firstArg = string.Empty; - if (subArgs.Count > 0) - { - firstArg = subArgs[0]; - subArgs.RemoveAt(0); - } - - // run whatever mode is choosen - switch(firstArg) - { - case "server": - return TestServer.Execute(subArgs); - case "--help": - PrintHelp(); - return 0; - default: - PrintHelp(); - return -1; - } - } - - private static void PrintHelp() - { - Console.WriteLine("Usage:"); - Console.WriteLine(" Server server [options]'"); - Console.WriteLine(" Server --help"); - Console.WriteLine(""); - - TestServer.PrintOptionsHelp(); - } - } -} - - diff --git a/test/netcore/Server/Properties/AssemblyInfo.cs b/test/netcore/Server/Properties/AssemblyInfo.cs deleted file mode 100644 index 265495c0535..00000000000 --- a/test/netcore/Server/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyTitle("Server")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("B0C13DA0-3117-4844-8AE8-B1775E46223D")] - diff --git a/test/netcore/Server/Server.csproj b/test/netcore/Server/Server.csproj deleted file mode 100644 index 2f9b4b1f586..00000000000 --- a/test/netcore/Server/Server.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - netcoreapp2.0 - Server - Server - Exe - false - false - false - false - false - false - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/test/netcore/Server/TestServer.cs b/test/netcore/Server/TestServer.cs deleted file mode 100644 index bfd33357fae..00000000000 --- a/test/netcore/Server/TestServer.cs +++ /dev/null @@ -1,594 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Thrift; -using Thrift.Collections; -using Thrift.Protocols; -using Thrift.Server; -using Thrift.Transports; -using Thrift.Transports.Server; - -namespace ThriftTest -{ - internal class ServerParam - { - internal bool useBufferedSockets = false; - internal bool useFramed = false; - internal bool useEncryption = false; - internal bool compact = false; - internal bool json = false; - internal int port = 9090; - internal string pipe = null; - - internal void Parse(List args) - { - for (var i = 0; i < args.Count; i++) - { - if (args[i].StartsWith("--pipe=")) - { - pipe = args[i].Substring(args[i].IndexOf("=") + 1); - } - else if (args[i].StartsWith("--port=")) - { - port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); - } - else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") - { - useBufferedSockets = true; - } - else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") - { - useFramed = true; - } - else if (args[i] == "--binary" || args[i] == "--protocol=binary") - { - // nothing needed - } - else if (args[i] == "--compact" || args[i] == "--protocol=compact") - { - compact = true; - } - else if (args[i] == "--json" || args[i] == "--protocol=json") - { - json = true; - } - else if (args[i] == "--threaded" || args[i] == "--server-type=threaded") - { - throw new NotImplementedException(args[i]); - } - else if (args[i] == "--threadpool" || args[i] == "--server-type=threadpool") - { - throw new NotImplementedException(args[i]); - } - else if (args[i] == "--prototype" || args[i] == "--processor=prototype") - { - throw new NotImplementedException(args[i]); - } - else if (args[i] == "--ssl") - { - useEncryption = true; - } - else - { - //throw new ArgumentException(args[i]); - } - } - - } - } - - public class TestServer - { - public static int _clientID = -1; - public delegate void TestLogDelegate(string msg, params object[] values); - - public class MyServerEventHandler : TServerEventHandler - { - public int callCount = 0; - - public Task PreServeAsync(CancellationToken cancellationToken) - { - callCount++; - return Task.CompletedTask; - } - - public Task CreateContextAsync(TProtocol input, TProtocol output, CancellationToken cancellationToken) - { - callCount++; - return Task.FromResult(null); - } - - public Task DeleteContextAsync(object serverContext, TProtocol input, TProtocol output, CancellationToken cancellationToken) - { - callCount++; - return Task.CompletedTask; - } - - public Task ProcessContextAsync(object serverContext, TClientTransport transport, CancellationToken cancellationToken) - { - callCount++; - return Task.CompletedTask; - } - } - - public class TestHandlerAsync : ThriftTest.IAsync - { - public TBaseServer server { get; set; } - private int handlerID; - private StringBuilder sb = new StringBuilder(); - private TestLogDelegate logger; - - public TestHandlerAsync() - { - handlerID = Interlocked.Increment(ref _clientID); - logger += testConsoleLogger; - logger.Invoke("New TestHandler instance created"); - } - - public void testConsoleLogger(string msg, params object[] values) - { - sb.Clear(); - sb.AppendFormat("handler{0:D3}:", handlerID); - sb.AppendFormat(msg, values); - sb.AppendLine(); - Console.Write(sb.ToString()); - } - - public Task testVoidAsync(CancellationToken cancellationToken) - { - logger.Invoke("testVoid()"); - return Task.CompletedTask; - } - - public Task testStringAsync(string thing, CancellationToken cancellationToken) - { - logger.Invoke("testString({0})", thing); - return Task.FromResult(thing); - } - - public Task testBoolAsync(bool thing, CancellationToken cancellationToken) - { - logger.Invoke("testBool({0})", thing); - return Task.FromResult(thing); - } - - public Task testByteAsync(sbyte thing, CancellationToken cancellationToken) - { - logger.Invoke("testByte({0})", thing); - return Task.FromResult(thing); - } - - public Task testI32Async(int thing, CancellationToken cancellationToken) - { - logger.Invoke("testI32({0})", thing); - return Task.FromResult(thing); - } - - public Task testI64Async(long thing, CancellationToken cancellationToken) - { - logger.Invoke("testI64({0})", thing); - return Task.FromResult(thing); - } - - public Task testDoubleAsync(double thing, CancellationToken cancellationToken) - { - logger.Invoke("testDouble({0})", thing); - return Task.FromResult(thing); - } - - public Task testBinaryAsync(byte[] thing, CancellationToken cancellationToken) - { - var hex = BitConverter.ToString(thing).Replace("-", string.Empty); - logger.Invoke("testBinary({0:X})", hex); - return Task.FromResult(thing); - } - - public Task testStructAsync(Xtruct thing, CancellationToken cancellationToken) - { - logger.Invoke("testStruct({{\"{0}\", {1}, {2}, {3}}})", thing.String_thing, thing.Byte_thing, thing.I32_thing, thing.I64_thing); - return Task.FromResult(thing); - } - - public Task testNestAsync(Xtruct2 nest, CancellationToken cancellationToken) - { - var thing = nest.Struct_thing; - logger.Invoke("testNest({{{0}, {{\"{1}\", {2}, {3}, {4}, {5}}}}})", - nest.Byte_thing, - thing.String_thing, - thing.Byte_thing, - thing.I32_thing, - thing.I64_thing, - nest.I32_thing); - return Task.FromResult(nest); - } - - public Task> testMapAsync(Dictionary thing, CancellationToken cancellationToken) - { - sb.Clear(); - sb.Append("testMap({{"); - var first = true; - foreach (var key in thing.Keys) - { - if (first) - { - first = false; - } - else - { - sb.Append(", "); - } - sb.AppendFormat("{0} => {1}", key, thing[key]); - } - sb.Append("}})"); - logger.Invoke(sb.ToString()); - return Task.FromResult(thing); - } - - public Task> testStringMapAsync(Dictionary thing, CancellationToken cancellationToken) - { - sb.Clear(); - sb.Append("testStringMap({{"); - var first = true; - foreach (var key in thing.Keys) - { - if (first) - { - first = false; - } - else - { - sb.Append(", "); - } - sb.AppendFormat("{0} => {1}", key, thing[key]); - } - sb.Append("}})"); - logger.Invoke(sb.ToString()); - return Task.FromResult(thing); - } - - public Task> testSetAsync(THashSet thing, CancellationToken cancellationToken) - { - sb.Clear(); - sb.Append("testSet({{"); - var first = true; - foreach (int elem in thing) - { - if (first) - { - first = false; - } - else - { - sb.Append(", "); - } - sb.AppendFormat("{0}", elem); - } - sb.Append("}})"); - logger.Invoke(sb.ToString()); - return Task.FromResult(thing); - } - - public Task> testListAsync(List thing, CancellationToken cancellationToken) - { - sb.Clear(); - sb.Append("testList({{"); - var first = true; - foreach (var elem in thing) - { - if (first) - { - first = false; - } - else - { - sb.Append(", "); - } - sb.AppendFormat("{0}", elem); - } - sb.Append("}})"); - logger.Invoke(sb.ToString()); - return Task.FromResult(thing); - } - - public Task testEnumAsync(Numberz thing, CancellationToken cancellationToken) - { - logger.Invoke("testEnum({0})", thing); - return Task.FromResult(thing); - } - - public Task testTypedefAsync(long thing, CancellationToken cancellationToken) - { - logger.Invoke("testTypedef({0})", thing); - return Task.FromResult(thing); - } - - public Task>> testMapMapAsync(int hello, CancellationToken cancellationToken) - { - logger.Invoke("testMapMap({0})", hello); - var mapmap = new Dictionary>(); - - var pos = new Dictionary(); - var neg = new Dictionary(); - for (var i = 1; i < 5; i++) - { - pos[i] = i; - neg[-i] = -i; - } - - mapmap[4] = pos; - mapmap[-4] = neg; - - return Task.FromResult(mapmap); - } - - public Task>> testInsanityAsync(Insanity argument, CancellationToken cancellationToken) - { - logger.Invoke("testInsanity()"); - - /** from ThriftTest.thrift: - * So you think you've got this all worked, out eh? - * - * Creates a the returned map with these values and prints it out: - * { 1 => { 2 => argument, - * 3 => argument, - * }, - * 2 => { 6 => , }, - * } - * @return map> - a map with the above values - */ - - var first_map = new Dictionary(); - var second_map = new Dictionary(); ; - - first_map[Numberz.TWO] = argument; - first_map[Numberz.THREE] = argument; - - second_map[Numberz.SIX] = new Insanity(); - - var insane = new Dictionary> - { - [1] = first_map, - [2] = second_map - }; - - return Task.FromResult(insane); - } - - public Task testMultiAsync(sbyte arg0, int arg1, long arg2, Dictionary arg3, Numberz arg4, long arg5, - CancellationToken cancellationToken) - { - logger.Invoke("testMulti()"); - - var hello = new Xtruct(); ; - hello.String_thing = "Hello2"; - hello.Byte_thing = arg0; - hello.I32_thing = arg1; - hello.I64_thing = arg2; - return Task.FromResult(hello); - } - - public Task testExceptionAsync(string arg, CancellationToken cancellationToken) - { - logger.Invoke("testException({0})", arg); - if (arg == "Xception") - { - var x = new Xception - { - ErrorCode = 1001, - Message = arg - }; - throw x; - } - if (arg == "TException") - { - throw new TException(); - } - return Task.CompletedTask; - } - - public Task testMultiExceptionAsync(string arg0, string arg1, CancellationToken cancellationToken) - { - logger.Invoke("testMultiException({0}, {1})", arg0, arg1); - if (arg0 == "Xception") - { - var x = new Xception - { - ErrorCode = 1001, - Message = "This is an Xception" - }; - throw x; - } - - if (arg0 == "Xception2") - { - var x = new Xception2 - { - ErrorCode = 2002, - Struct_thing = new Xtruct { String_thing = "This is an Xception2" } - }; - throw x; - } - - var result = new Xtruct { String_thing = arg1 }; - return Task.FromResult(result); - } - - public Task testOnewayAsync(int secondsToSleep, CancellationToken cancellationToken) - { - logger.Invoke("testOneway({0}), sleeping...", secondsToSleep); - Task.Delay(secondsToSleep * 1000, cancellationToken).GetAwaiter().GetResult(); - logger.Invoke("testOneway finished"); - - return Task.CompletedTask; - } - } - - internal static void PrintOptionsHelp() - { - Console.WriteLine("Server options:"); - Console.WriteLine(" --pipe="); - Console.WriteLine(" --port="); - Console.WriteLine(" --transport= one of buffered,framed (defaults to none)"); - Console.WriteLine(" --protocol= one of compact,json (defaults to binary)"); - Console.WriteLine(" --server-type= one of threaded,threadpool (defaults to simple)"); - Console.WriteLine(" --processor="); - Console.WriteLine(" --ssl"); - Console.WriteLine(); - } - - private static X509Certificate2 GetServerCert() - { - var serverCertName = "server.p12"; - var possiblePaths = new List - { - "../../../keys/", - "../../keys/", - "../keys/", - "keys/", - }; - - string existingPath = null; - foreach (var possiblePath in possiblePaths) - { - var path = Path.GetFullPath(possiblePath + serverCertName); - if (File.Exists(path)) - { - existingPath = path; - break; - } - } - - if (string.IsNullOrEmpty(existingPath)) - { - throw new FileNotFoundException($"Cannot find file: {serverCertName}"); - } - - var cert = new X509Certificate2(existingPath, "thrift"); - - return cert; - } - - public static int Execute(List args) - { - var loggerFactory = new LoggerFactory();//.AddConsole().AddDebug(); - var logger = new LoggerFactory().CreateLogger("Test"); - - try - { - var param = new ServerParam(); - - try - { - param.Parse(args); - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - Console.WriteLine("Error while parsing arguments"); - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - return 1; - } - - - // Transport - TServerTransport trans; - if (param.pipe != null) - { - trans = new TNamedPipeServerTransport(param.pipe); - } -// else if (param.useFramed) -// { -// trans = new TServerFramedTransport(param.port); -// } - else - { - if (param.useEncryption) - { - var cert = GetServerCert(); - - if (cert == null || !cert.HasPrivateKey) - { - throw new InvalidOperationException("Certificate doesn't contain private key"); - } - - trans = new TTlsServerSocketTransport(param.port, param.useBufferedSockets, param.useFramed, cert, - (sender, certificate, chain, errors) => true, - null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); - } - else - { - trans = new TServerSocketTransport(param.port, 0, param.useBufferedSockets, param.useFramed); - } - } - - ITProtocolFactory proto; - if (param.compact) - proto = new TCompactProtocol.Factory(); - else if (param.json) - proto = new TJsonProtocol.Factory(); - else - proto = new TBinaryProtocol.Factory(); - - ITProcessorFactory processorFactory; - - // Processor - var testHandler = new TestHandlerAsync(); - var testProcessor = new ThriftTest.AsyncProcessor(testHandler); - processorFactory = new SingletonTProcessorFactory(testProcessor); - - TTransportFactory transFactory = new TTransportFactory(); - - TBaseServer serverEngine = new AsyncBaseServer(processorFactory, trans, transFactory, transFactory, proto, proto, logger); - - //Server event handler - var serverEvents = new MyServerEventHandler(); - serverEngine.SetEventHandler(serverEvents); - - // Run it - var where = (! string.IsNullOrEmpty(param.pipe)) ? "on pipe " + param.pipe : "on port " + param.port; - Console.WriteLine("Starting the AsyncBaseServer " + where + - " with processor TPrototypeProcessorFactory prototype factory " + - (param.useBufferedSockets ? " with buffered socket" : "") + - (param.useFramed ? " with framed transport" : "") + - (param.useEncryption ? " with encryption" : "") + - (param.compact ? " with compact protocol" : "") + - (param.json ? " with json protocol" : "") + - "..."); - serverEngine.ServeAsync(CancellationToken.None).GetAwaiter().GetResult(); - Console.ReadLine(); - } - catch (Exception x) - { - Console.Error.Write(x); - return 1; - } - Console.WriteLine("done."); - return 0; - } - } - -} diff --git a/test/netcore/ThriftTest.sln b/test/netcore/ThriftTest.sln deleted file mode 100644 index 2ab241add75..00000000000 --- a/test/netcore/ThriftTest.sln +++ /dev/null @@ -1,64 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.12 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netcore\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{21039F25-6ED7-4E80-A545-EBC93472EBD1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{0C6E8685-F191-4479-9842-882A38961127}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.Build.0 = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.ActiveCfg = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.Build.0 = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.Build.0 = Release|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.ActiveCfg = Release|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.ActiveCfg = Debug|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x64.Build.0 = Debug|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.ActiveCfg = Debug|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Debug|x86.Build.0 = Debug|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|Any CPU.Build.0 = Release|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.ActiveCfg = Release|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x64.Build.0 = Release|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.ActiveCfg = Release|Any CPU - {21039F25-6ED7-4E80-A545-EBC93472EBD1}.Release|x86.Build.0 = Release|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.ActiveCfg = Debug|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Debug|x64.Build.0 = Debug|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.ActiveCfg = Debug|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Debug|x86.Build.0 = Debug|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Release|Any CPU.Build.0 = Release|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Release|x64.ActiveCfg = Release|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Release|x64.Build.0 = Release|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Release|x86.ActiveCfg = Release|Any CPU - {0C6E8685-F191-4479-9842-882A38961127}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {52CE9A12-F6CB-4F0C-BB42-0105612F5FF4} - EndGlobalSection -EndGlobal diff --git a/test/netcore/build.cmd b/test/netcore/build.cmd deleted file mode 100644 index 9b84ef27606..00000000000 --- a/test/netcore/build.cmd +++ /dev/null @@ -1,25 +0,0 @@ -@echo off -rem /* -rem * Licensed to the Apache Software Foundation (ASF) under one -rem * or more contributor license agreements. See the NOTICE file -rem * distributed with this work for additional information -rem * regarding copyright ownership. The ASF licenses this file -rem * to you under the Apache License, Version 2.0 (the -rem * "License"); you may not use this file except in compliance -rem * with the License. You may obtain a copy of the License at -rem * -rem * http://www.apache.org/licenses/LICENSE-2.0 -rem * -rem * Unless required by applicable law or agreed to in writing, -rem * software distributed under the License is distributed on an -rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -rem * KIND, either express or implied. See the License for the -rem * specific language governing permissions and limitations -rem * under the License. -rem */ -setlocal - -dotnet --info -dotnet build - -:eof diff --git a/test/netcore/build.sh b/test/netcore/build.sh deleted file mode 100755 index c97e310f011..00000000000 --- a/test/netcore/build.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -#exit if any command fails -set -e - -dotnet --info -dotnet build diff --git a/tutorial/Makefile.am b/tutorial/Makefile.am index 49d18fb2606..f7a49d00217 100755 --- a/tutorial/Makefile.am +++ b/tutorial/Makefile.am @@ -59,7 +59,6 @@ SUBDIRS += haxe endif if WITH_DOTNET -SUBDIRS += netcore SUBDIRS += netstd endif diff --git a/tutorial/netcore/.gitignore b/tutorial/netcore/.gitignore deleted file mode 100644 index 9938bb237a0..00000000000 --- a/tutorial/netcore/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!**/*.pfx \ No newline at end of file diff --git a/tutorial/netcore/Client/Client.csproj b/tutorial/netcore/Client/Client.csproj deleted file mode 100644 index 911272d3f63..00000000000 --- a/tutorial/netcore/Client/Client.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - netcoreapp2.0 - Client - Client - Exe - false - false - false - false - - - - - - - - diff --git a/tutorial/netcore/Client/Program.cs b/tutorial/netcore/Client/Program.cs deleted file mode 100644 index ce5d8c7e4d7..00000000000 --- a/tutorial/netcore/Client/Program.cs +++ /dev/null @@ -1,355 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Thrift; -using Thrift.Protocols; -using Thrift.Transports; -using Thrift.Transports.Client; -using tutorial; -using shared; - -namespace Client -{ - public class Program - { - private static readonly ILogger Logger = new LoggerFactory().AddConsole().AddDebug().CreateLogger(nameof(Client)); - - private static void DisplayHelp() - { - Logger.LogInformation(@" -Usage: - Client.exe -help - will diplay help information - - Client.exe -tr: -pr: -mc: - will run client with specified arguments (tcp transport and binary protocol by default) and with 1 client - -Options: - -tr (transport): - tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) - tcpbuffered - buffered transport over tcp will be used (host - ""localhost"", port - 9090) - namedpipe - namedpipe transport will be used (pipe address - "".test"") - http - http transport will be used (address - ""http://localhost:9090"") - tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) - framed - tcp framed transport will be used (host - ""localhost"", port - 9090) - - -pr (protocol): - binary - (default) binary protocol will be used - compact - compact protocol will be used - json - json protocol will be used - multiplexed - multiplexed protocol will be used - - -mc (multiple clients): - - number of multiple clients to connect to server (max 100, default 1) - -Sample: - Client.exe -tr:tcp -p:binary -"); - } - - public static void Main(string[] args) - { - args = args ?? new string[0]; - - if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) - { - DisplayHelp(); - return; - } - - Logger.LogInformation("Starting client..."); - - using (var source = new CancellationTokenSource()) - { - RunAsync(args, source.Token).GetAwaiter().GetResult(); - } - } - - private static async Task RunAsync(string[] args, CancellationToken cancellationToken) - { - var numClients = GetNumberOfClients(args); - - Logger.LogInformation($"Selected # of clients: {numClients}"); - - var transports = new TClientTransport[numClients]; - for (int i = 0; i < numClients; i++) - { - var t = GetTransport(args); - transports[i] = t; - } - - Logger.LogInformation($"Selected client transport: {transports[0]}"); - - var protocols = new Tuple[numClients]; - for (int i = 0; i < numClients; i++) - { - var p = GetProtocol(args, transports[i]); - protocols[i] = p; - } - - Logger.LogInformation($"Selected client protocol: {protocols[0].Item1}"); - - var tasks = new Task[numClients]; - for (int i = 0; i < numClients; i++) - { - var task = RunClientAsync(protocols[i], cancellationToken); - tasks[i] = task; - } - - Task.WaitAll(tasks); - - await Task.CompletedTask; - } - - private static TClientTransport GetTransport(string[] args) - { - var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; - - Transport selectedTransport; - if (Enum.TryParse(transport, true, out selectedTransport)) - { - switch (selectedTransport) - { - case Transport.Tcp: - return new TSocketClientTransport(IPAddress.Loopback, 9090); - case Transport.NamedPipe: - return new TNamedPipeClientTransport(".test"); - case Transport.Http: - return new THttpClientTransport(new Uri("http://localhost:9090"), null); - case Transport.TcpBuffered: - return new TBufferedClientTransport(new TSocketClientTransport(IPAddress.Loopback, 9090)); - case Transport.TcpTls: - return new TTlsSocketClientTransport(IPAddress.Loopback, 9090, GetCertificate(), CertValidator, LocalCertificateSelectionCallback); - case Transport.Framed: - return new TFramedClientTransport(new TSocketClientTransport(IPAddress.Loopback, 9090)); - } - } - - return new TSocketClientTransport(IPAddress.Loopback, 9090); - } - - private static int GetNumberOfClients(string[] args) - { - var numClients = args.FirstOrDefault(x => x.StartsWith("-mc"))?.Split(':')?[1]; - - Logger.LogInformation($"Selected # of clients: {numClients}"); - - int c; - if( int.TryParse(numClients, out c) && (0 < c) && (c <= 100)) - return c; - else - return 1; - } - - private static X509Certificate2 GetCertificate() - { - // due to files location in net core better to take certs from top folder - var certFile = GetCertPath(Directory.GetParent(Directory.GetCurrentDirectory())); - return new X509Certificate2(certFile, "ThriftTest"); - } - - private static string GetCertPath(DirectoryInfo di, int maxCount = 6) - { - var topDir = di; - var certFile = - topDir.EnumerateFiles("ThriftTest.pfx", SearchOption.AllDirectories) - .FirstOrDefault(); - if (certFile == null) - { - if (maxCount == 0) - throw new FileNotFoundException("Cannot find file in directories"); - return GetCertPath(di.Parent, maxCount - 1); - } - - return certFile.FullName; - } - - private static X509Certificate LocalCertificateSelectionCallback(object sender, - string targetHost, X509CertificateCollection localCertificates, - X509Certificate remoteCertificate, string[] acceptableIssuers) - { - return GetCertificate(); - } - - private static bool CertValidator(object sender, X509Certificate certificate, - X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - return true; - } - - private static Tuple GetProtocol(string[] args, TClientTransport transport) - { - var protocol = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; - - Protocol selectedProtocol; - if (Enum.TryParse(protocol, true, out selectedProtocol)) - { - switch (selectedProtocol) - { - case Protocol.Binary: - return new Tuple(selectedProtocol, new TBinaryProtocol(transport)); - case Protocol.Compact: - return new Tuple(selectedProtocol, new TCompactProtocol(transport)); - case Protocol.Json: - return new Tuple(selectedProtocol, new TJsonProtocol(transport)); - case Protocol.Multiplexed: - // it returns BinaryProtocol to avoid making wrapped protocol as public in TProtocolDecorator (in RunClientAsync it will be wrapped into Multiplexed protocol) - return new Tuple(selectedProtocol, new TBinaryProtocol(transport)); - } - } - - return new Tuple(selectedProtocol, new TBinaryProtocol(transport)); - } - - private static async Task RunClientAsync(Tuple protocolTuple, CancellationToken cancellationToken) - { - try - { - var protocol = protocolTuple.Item2; - var protocolType = protocolTuple.Item1; - - TBaseClient client = null; - - try - { - if (protocolType != Protocol.Multiplexed) - { - - client = new Calculator.Client(protocol); - await ExecuteCalculatorClientOperations(cancellationToken, (Calculator.Client)client); - } - else - { - // it uses binary protocol there to create Multiplexed protocols - var multiplex = new TMultiplexedProtocol(protocol, nameof(Calculator)); - client = new Calculator.Client(multiplex); - await ExecuteCalculatorClientOperations(cancellationToken, (Calculator.Client)client); - - multiplex = new TMultiplexedProtocol(protocol, nameof(SharedService)); - client = new SharedService.Client(multiplex); - await ExecuteSharedServiceClientOperations(cancellationToken, (SharedService.Client)client); - } - } - catch (Exception ex) - { - Logger.LogError($"{client?.ClientId} " + ex); - } - finally - { - protocol.Transport.Close(); - } - } - catch (TApplicationException x) - { - Logger.LogError(x.ToString()); - } - } - - private static async Task ExecuteCalculatorClientOperations(CancellationToken cancellationToken, Calculator.Client client) - { - await client.OpenTransportAsync(cancellationToken); - - // Async version - - Logger.LogInformation($"{client.ClientId} PingAsync()"); - await client.pingAsync(cancellationToken); - - Logger.LogInformation($"{client.ClientId} AddAsync(1,1)"); - var sum = await client.addAsync(1, 1, cancellationToken); - Logger.LogInformation($"{client.ClientId} AddAsync(1,1)={sum}"); - - var work = new Work - { - Op = Operation.DIVIDE, - Num1 = 1, - Num2 = 0 - }; - - try - { - Logger.LogInformation($"{client.ClientId} CalculateAsync(1)"); - await client.calculateAsync(1, work, cancellationToken); - Logger.LogInformation($"{client.ClientId} Whoa we can divide by 0"); - } - catch (InvalidOperation io) - { - Logger.LogInformation($"{client.ClientId} Invalid operation: " + io); - } - - work.Op = Operation.SUBTRACT; - work.Num1 = 15; - work.Num2 = 10; - - try - { - Logger.LogInformation($"{client.ClientId} CalculateAsync(1)"); - var diff = await client.calculateAsync(1, work, cancellationToken); - Logger.LogInformation($"{client.ClientId} 15-10={diff}"); - } - catch (InvalidOperation io) - { - Logger.LogInformation($"{client.ClientId} Invalid operation: " + io); - } - - Logger.LogInformation($"{client.ClientId} GetStructAsync(1)"); - var log = await client.getStructAsync(1, cancellationToken); - Logger.LogInformation($"{client.ClientId} Check log: {log.Value}"); - - Logger.LogInformation($"{client.ClientId} ZipAsync() with delay 100mc on server side"); - await client.zipAsync(cancellationToken); - } - private static async Task ExecuteSharedServiceClientOperations(CancellationToken cancellationToken, SharedService.Client client) - { - await client.OpenTransportAsync(cancellationToken); - - // Async version - - Logger.LogInformation($"{client.ClientId} SharedService GetStructAsync(1)"); - var log = await client.getStructAsync(1, cancellationToken); - Logger.LogInformation($"{client.ClientId} SharedService Value: {log.Value}"); - } - - - private enum Transport - { - Tcp, - NamedPipe, - Http, - TcpBuffered, - Framed, - TcpTls - } - - private enum Protocol - { - Binary, - Compact, - Json, - Multiplexed - } - } -} diff --git a/tutorial/netcore/Client/Properties/AssemblyInfo.cs b/tutorial/netcore/Client/Properties/AssemblyInfo.cs deleted file mode 100644 index 568382e66dc..00000000000 --- a/tutorial/netcore/Client/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("de78a01b-f7c6-49d1-97da-669d2ed37641")] \ No newline at end of file diff --git a/tutorial/netcore/Client/Properties/launchSettings.json b/tutorial/netcore/Client/Properties/launchSettings.json deleted file mode 100644 index 6b7b60d78f4..00000000000 --- a/tutorial/netcore/Client/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "Client": { - "commandName": "Project", - "commandLineArgs": "-p:multiplexed" - } - } -} \ No newline at end of file diff --git a/tutorial/netcore/Client/ThriftTest.pfx b/tutorial/netcore/Client/ThriftTest.pfx deleted file mode 100644 index f0ded28173dc2c33cebbb2b74e1e9e9e870b5876..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2661 zcmY+Fc{r5q7ssC&Gb1!J$(kiQNi-_kNTzK}lBB4-#%>tDNgCV8K7;IKOK6d75tC&a zp={ZTH)}K@WXZmpv83PB^)A`wF(pXt7XpsY=bHUSlV3;5-A{d&ZS=A9rAjL!JLlxE zU_0M6u}dL5dyZUM*eZRTK7%!HnQk@RhDO-B4XYapVO%Fw7K^smqmrq9#TGaL=NEIm z?!`FK&>hR?Z@)%UKPau-%?m`A(>#}=i#q*6>Xe+P#mwBs6Q0@@Ixp|5@9I+wut zA#tRevtir~_G0T(aAFKzvy!O$=C`*W)A|(nrt(YY1n}Kp^LEZq_lyzXl)hwOG@G=i zxbiB-SnTQD^sz>x%QCdt1fw!Er?MpQ>#O~U^B1Ih|GdFM1{`4ISt#RHN4|ZYyq|=< z{j;$~n=*954;otf@)^47LvcfPIKt$_Y2BL+D}7sV7s{aov!F89pkkhg#@d`RVvtv8 zqhf(QFGtL@?Vi^c`LJWbZE9|TN_1?X9?l3DaIjMO5`V9F;~;j1FwiWFV#DZK zPZjSTs!0RAwSeaugCPfE_z~82e~?}o;1!SDpMJeV`Q?+Y@TQRE z%jhKjwXIG1?LW{8%1ry~$CvoFtuttc!kQ${aiZfTlsc}(9#g1pD3VzLU3ij7h2^CD z;6Lz8^m(Xe5?)8Y0Gr#QxBP*P)`mX~ycEnzpRed9N46To2eUk?5^Lp}$Xu=>65C8xu{J&6G(`>&f z-~~7X>HrGR1atr=u0{d&fFqaa0!O&99#K(?2gPlgcy9MFU_Ez}9Obs^@?Q}%0v{+j;MU>669QYwovF;u<-Oys<_RI{b3>F|lw0+!xJ>$_T%M|8 z*-&MWR7IRjyg|Rdz}Y^1c3>+=Wp`aAotnEcJk{mR2!9S=p@lzc?XYcYm9LJXMtHbTOVA7ageNhdBfi0|v1eLr9PtqI`)XEsA zC0p*r#f2MT4Hybzy5V<-3)*Qcno)THYn1lrjq6Dik zc86XkszLcvn;9QTVpJ9nk<@$OqssciMrRF6FvCqZbspu(u*qkj2*`%Mz8yK zJdDp2+luWj&vuSBXbE_thM;=6A| zTxptZh*kG4;p+`oVSXP~RY=Ckmncb%Q_UISo?$+pr{w0qs^nnM(Hjvem6Iv&+#MtM zv{NJq4}S()s9l6QL`u&D)**e1PVG7Kle}4G&E6j*6WUk@Gf{A7t$m7Kzgxiio)Vux zaUZfKT(@FZ>2x``Vy-=XKo?(27vH5gZ(9I{TgrlFvqh3z9qJGySLfwbj9a-H4Nq*qFpUg@ld}K z)hFz#CqBwVT7Rl=a|*hQAa-`0o9X{L*g@fX}@vnbf G^#21?=Cu0& diff --git a/tutorial/netcore/Interfaces/.gitignore b/tutorial/netcore/Interfaces/.gitignore deleted file mode 100644 index 2e7446e33e7..00000000000 --- a/tutorial/netcore/Interfaces/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# ignore for autogenerated files -/shared -/tutorial diff --git a/tutorial/netcore/Interfaces/Interfaces.csproj b/tutorial/netcore/Interfaces/Interfaces.csproj deleted file mode 100644 index 4297a0654a7..00000000000 --- a/tutorial/netcore/Interfaces/Interfaces.csproj +++ /dev/null @@ -1,30 +0,0 @@ - - - - netstandard2.0 - Interfaces - Interfaces - false - false - false - false - - - - - - - - - - - - - - - - - - - - diff --git a/tutorial/netcore/Interfaces/Properties/AssemblyInfo.cs b/tutorial/netcore/Interfaces/Properties/AssemblyInfo.cs deleted file mode 100644 index 9126b173e7c..00000000000 --- a/tutorial/netcore/Interfaces/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("4d13163d-9067-4c9c-8af0-64e08451397d")] \ No newline at end of file diff --git a/tutorial/netcore/Makefile.am b/tutorial/netcore/Makefile.am deleted file mode 100644 index bd19dfe6a6f..00000000000 --- a/tutorial/netcore/Makefile.am +++ /dev/null @@ -1,51 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -SUBDIRS = . - -all-local: - $(DOTNETCORE) build - -clean-local: - $(RM) Interfaces.dll - $(RM) -r Client/bin - $(RM) -r Client/obj - $(RM) -r Server/bin - $(RM) -r Server/obj - $(RM) -r Interfaces/bin - $(RM) -r Interfaces/obj - -dist-hook: - $(RM) $(distdir)/Interfaces.dll - $(RM) -r $(distdir)/Client/bin - $(RM) -r $(distdir)/Client/obj - $(RM) -r $(distdir)/Server/bin - $(RM) -r $(distdir)/Server/obj - $(RM) -r $(distdir)/Interfaces/bin - $(RM) -r $(distdir)/Interfaces/obj - -EXTRA_DIST = \ - Client \ - Interfaces \ - README.md \ - Server \ - Tutorial.sln \ - build.cmd \ - build.sh - diff --git a/tutorial/netcore/README.md b/tutorial/netcore/README.md deleted file mode 100644 index 626ef921269..00000000000 --- a/tutorial/netcore/README.md +++ /dev/null @@ -1,278 +0,0 @@ -# Building of samples for different platforms - -# Reused components -- NET Core Standard 2.0 -- NET Core App 2.0 - -# How to build -- Download and install the latest .NET Core SDK for your platform https://www.microsoft.com/net/core#windowsvs2015 (archive for SDK 1.0.0-preview2-003121 located by: https://github.com/dotnet/core/blob/master/release-notes/download-archive.md) -- Ensure that you have thrift.exe which supports netcore lib and it added to PATH -- Go to current folder -- Run **build.sh** or **build.cmd** from the root of cloned repository -- Check tests in **src/Tests** folder -- Continue with /tutorials/netcore - -# How to run - -Notes: dotnet run supports passing arguments to app after -- symbols (https://docs.microsoft.com/en-us/dotnet/articles/core/tools/dotnet-run) - example: **dotnet run -- -h** will show help for app - -- build -- go to folder (Client/Server) -- run with specifying of correct parameters **dotnet run -tr:tcp -pr:multiplexed**, **dotnet run -help** (later, after migration to csproj and latest SDK will be possibility to use more usable form **dotnet run -- arguments**) - -#Notes -- Possible adding additional platforms after stabilization of .NET Core (runtimes, platforms (Red Hat Linux, OpenSuse, etc.) - -#Known issues -- In trace logging mode you can see some not important internal exceptions - -# Running of samples -Please install Thrift C# .NET Core library or copy sources and build them to correcly build and run samples - -# NetCore Server - -Usage: - - Server.exe -h - will diplay help information - - Server.exe -tr: -pr: - will run server with specified arguments (tcp transport and binary protocol by default) - -Options: - - -tr (transport): - tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) - tcpbuffered - tcp buffered transport will be used (host - ""localhost"", port - 9090) - namedpipe - namedpipe transport will be used (pipe address - "".test"") - http - http transport will be used (http address - ""localhost:9090"") - tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) - framed - tcp framed transport will be used (host - ""localhost"", port - 9090) - - -pr (protocol): - binary - (default) binary protocol will be used - compact - compact protocol will be used - json - json protocol will be used - -Sample: - - Server.exe -tr:tcp - -**Remarks**: - - For TcpTls mode certificate's file ThriftTest.pfx should be in directory with binaries in case of command line usage (or at project level in case of debugging from IDE). - Password for certificate - "ThriftTest". - - - -# NetCore Client - -Usage: - - Client.exe -h - will diplay help information - - Client.exe -tr: -pr: -mc: - will run client with specified arguments (tcp transport and binary protocol by default) - -Options: - - -tr (transport): - tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) - tcpbuffered - buffered transport over tcp will be used (host - ""localhost"", port - 9090) - namedpipe - namedpipe transport will be used (pipe address - "".test"") - http - http transport will be used (address - ""http://localhost:9090"") - tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) - framed - tcp framed transport will be used (host - ""localhost"", port - 9090) - - -pr (protocol): - binary - (default) binary protocol will be used - compact - compact protocol will be used - json - json protocol will be used - - -mc (multiple clients): - - number of multiple clients to connect to server (max 100, default 1) - -Sample: - - Client.exe -tr:tcp -pr:binary -mc:10 - -Remarks: - - For TcpTls mode certificate's file ThriftTest.pfx should be in directory - with binaries in case of command line usage (or at project level in case of debugging from IDE). - Password for certificate - "ThriftTest". - -# How to test communication between NetCore and Python - -* Generate code with the latest **thrift.exe** util -* Ensure that **thrift.exe** util generated folder **gen-py** with generated code for Python -* Create **client.py** and **server.py** from the code examples below and save them to the folder with previosly generated folder **gen-py** -* Run netcore samples (client and server) and python samples (client and server) - -Remarks: - -Samples of client and server code below use correct methods (operations) -and fields (properties) according to generated contracts from *.thrift files - -At Windows 10 add record **127.0.0.1 testserver** to **C:\Windows\System32\drivers\etc\hosts** file -for correct work of python server - - -**Python Client:** - -```python -import sys -import glob -sys.path.append('gen-py') - -from tutorial import Calculator -from tutorial.ttypes import InvalidOperation, Operation, Work - -from thrift import Thrift -from thrift.transport import TSocket -from thrift.transport import TTransport -from thrift.protocol import TBinaryProtocol - - -def main(): - # Make socket - transport = TSocket.TSocket('127.0.0.1', 9090) - - # Buffering is critical. Raw sockets are very slow - transport = TTransport.TBufferedTransport(transport) - - # Wrap in a protocol - protocol = TBinaryProtocol.TBinaryProtocol(transport) - - # Create a client to use the protocol encoder - client = Calculator.Client(protocol) - - # Connect! - transport.open() - - client.Ping() - print('ping()') - - sum = client.Add(1, 1) - print(('1+1=%d' % (sum))) - - work = Work() - - work.Op = Operation.Divide - work.Num1 = 1 - work.Num2 = 0 - - try: - quotient = client.Calculate(1, work) - print('Whoa? You know how to divide by zero?') - print('FYI the answer is %d' % quotient) - except InvalidOperation as e: - print(('InvalidOperation: %r' % e)) - - work.Op = Operation.Substract - work.Num1 = 15 - work.Num2 = 10 - - diff = client.Calculate(1, work) - print(('15-10=%d' % (diff))) - - log = client.GetStruct(1) - print(('Check log: %s' % (log.Value))) - - client.Zip() - print('zip()') - - # Close! - transport.close() - -if __name__ == '__main__': - try: - main() - except Thrift.TException as tx: - print('%s' % tx.message) -``` - - -**Python Server:** - - -```python -import glob -import sys -sys.path.append('gen-py') - -from tutorial import Calculator -from tutorial.ttypes import InvalidOperation, Operation - -from shared.ttypes import SharedStruct - -from thrift.transport import TSocket -from thrift.transport import TTransport -from thrift.protocol import TBinaryProtocol -from thrift.server import TServer - - -class CalculatorHandler: - def __init__(self): - self.log = {} - - def Ping(self): - print('ping()') - - def Add(self, n1, n2): - print('add(%d,%d)' % (n1, n2)) - return n1 + n2 - - def Calculate(self, logid, work): - print('calculate(%d, %r)' % (logid, work)) - - if work.Op == Operation.Add: - val = work.Num1 + work.Num2 - elif work.Op == Operation.Substract: - val = work.Num1 - work.Num2 - elif work.Op == Operation.Multiply: - val = work.Num1 * work.Num2 - elif work.Op == Operation.Divide: - if work.Num2 == 0: - x = InvalidOperation() - x.WhatOp = work.Op - x.Why = 'Cannot divide by 0' - raise x - val = work.Num1 / work.Num2 - else: - x = InvalidOperation() - x.WhatOp = work.Op - x.Why = 'Invalid operation' - raise x - - log = SharedStruct() - log.Key = logid - log.Value = '%d' % (val) - self.log[logid] = log - - return val - - def GetStruct(self, key): - print('getStruct(%d)' % (key)) - return self.log[key] - - def Zip(self): - print('zip()') - -if __name__ == '__main__': - handler = CalculatorHandler() - processor = Calculator.Processor(handler) - transport = TSocket.TServerSocket(host="testserver", port=9090) - tfactory = TTransport.TBufferedTransportFactory() - pfactory = TBinaryProtocol.TBinaryProtocolFactory() - - server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) - print('Starting the server...') - server.serve() - print('done.') - - # You could do one of these for a multithreaded server - # server = TServer.TThreadedServer(processor, transport, tfactory, pfactory) - # server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory) -``` diff --git a/tutorial/netcore/Server/Program.cs b/tutorial/netcore/Server/Program.cs deleted file mode 100644 index 6a181bab750..00000000000 --- a/tutorial/netcore/Server/Program.cs +++ /dev/null @@ -1,428 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Thrift; -using Thrift.Protocols; -using Thrift.Server; -using Thrift.Transports; -using Thrift.Transports.Server; -using tutorial; -using shared; - -namespace Server -{ - public class Program - { - private static readonly ILogger Logger = new LoggerFactory().AddConsole(LogLevel.Trace).AddDebug(LogLevel.Trace).CreateLogger(nameof(Server)); - - public static void Main(string[] args) - { - args = args ?? new string[0]; - - if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) - { - DisplayHelp(); - return; - } - - using (var source = new CancellationTokenSource()) - { - RunAsync(args, source.Token).GetAwaiter().GetResult(); - - Logger.LogInformation("Press any key to stop..."); - - Console.ReadLine(); - source.Cancel(); - } - - Logger.LogInformation("Server stopped"); - } - - private static void DisplayHelp() - { - Logger.LogInformation(@" -Usage: - Server.exe -help - will diplay help information - - Server.exe -tr: -pr: - will run server with specified arguments (tcp transport and binary protocol by default) - -Options: - -tr (transport): - tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) - tcpbuffered - tcp buffered transport will be used (host - ""localhost"", port - 9090) - namedpipe - namedpipe transport will be used (pipe address - "".test"") - http - http transport will be used (http address - ""localhost:9090"") - tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) - framed - tcp framed transport will be used (host - ""localhost"", port - 9090) - - -pr (protocol): - binary - (default) binary protocol will be used - compact - compact protocol will be used - json - json protocol will be used - multiplexed - multiplexed protocol will be used - -Sample: - Server.exe -tr:tcp -"); - } - - private static async Task RunAsync(string[] args, CancellationToken cancellationToken) - { - var selectedTransport = GetTransport(args); - var selectedProtocol = GetProtocol(args); - - if (selectedTransport == Transport.Http) - { - new HttpServerSample().Run(cancellationToken); - } - else - { - await RunSelectedConfigurationAsync(selectedTransport, selectedProtocol, cancellationToken); - } - } - - private static Protocol GetProtocol(string[] args) - { - var transport = args.FirstOrDefault(x => x.StartsWith("-pr"))?.Split(':')?[1]; - - Enum.TryParse(transport, true, out Protocol selectedProtocol); - - return selectedProtocol; - } - - private static Transport GetTransport(string[] args) - { - var transport = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; - - Enum.TryParse(transport, true, out Transport selectedTransport); - - return selectedTransport; - } - - private static async Task RunSelectedConfigurationAsync(Transport transport, Protocol protocol, CancellationToken cancellationToken) - { - var fabric = new LoggerFactory().AddConsole(LogLevel.Trace).AddDebug(LogLevel.Trace); - var handler = new CalculatorAsyncHandler(); - ITAsyncProcessor processor = null; - - TServerTransport serverTransport = null; - - switch (transport) - { - case Transport.Tcp: - serverTransport = new TServerSocketTransport(9090); - break; - case Transport.TcpBuffered: - serverTransport = new TServerSocketTransport(port: 9090, clientTimeout: 10000, useBufferedSockets: true); - break; - case Transport.NamedPipe: - serverTransport = new TNamedPipeServerTransport(".test"); - break; - case Transport.TcpTls: - serverTransport = new TTlsServerSocketTransport(9090, false, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback); - break; - case Transport.Framed: - serverTransport = new TServerFramedTransport(9090); - break; - } - - ITProtocolFactory inputProtocolFactory; - ITProtocolFactory outputProtocolFactory; - - switch (protocol) - { - case Protocol.Binary: - { - inputProtocolFactory = new TBinaryProtocol.Factory(); - outputProtocolFactory = new TBinaryProtocol.Factory(); - processor = new Calculator.AsyncProcessor(handler); - } - break; - case Protocol.Compact: - { - inputProtocolFactory = new TCompactProtocol.Factory(); - outputProtocolFactory = new TCompactProtocol.Factory(); - processor = new Calculator.AsyncProcessor(handler); - } - break; - case Protocol.Json: - { - inputProtocolFactory = new TJsonProtocol.Factory(); - outputProtocolFactory = new TJsonProtocol.Factory(); - processor = new Calculator.AsyncProcessor(handler); - } - break; - case Protocol.Multiplexed: - { - inputProtocolFactory = new TBinaryProtocol.Factory(); - outputProtocolFactory = new TBinaryProtocol.Factory(); - - var calcHandler = new CalculatorAsyncHandler(); - var calcProcessor = new Calculator.AsyncProcessor(calcHandler); - - var sharedServiceHandler = new SharedServiceAsyncHandler(); - var sharedServiceProcessor = new SharedService.AsyncProcessor(sharedServiceHandler); - - var multiplexedProcessor = new TMultiplexedProcessor(); - multiplexedProcessor.RegisterProcessor(nameof(Calculator), calcProcessor); - multiplexedProcessor.RegisterProcessor(nameof(SharedService), sharedServiceProcessor); - - processor = multiplexedProcessor; - } - break; - default: - throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null); - } - - try - { - Logger.LogInformation( - $"Selected TAsyncServer with {serverTransport} transport, {processor} processor and {inputProtocolFactory} protocol factories"); - - var server = new AsyncBaseServer(processor, serverTransport, inputProtocolFactory, outputProtocolFactory, fabric); - - Logger.LogInformation("Starting the server..."); - await server.ServeAsync(cancellationToken); - } - catch (Exception x) - { - Logger.LogInformation(x.ToString()); - } - } - - private static X509Certificate2 GetCertificate() - { - // due to files location in net core better to take certs from top folder - var certFile = GetCertPath(Directory.GetParent(Directory.GetCurrentDirectory())); - return new X509Certificate2(certFile, "ThriftTest"); - } - - private static string GetCertPath(DirectoryInfo di, int maxCount = 6) - { - var topDir = di; - var certFile = - topDir.EnumerateFiles("ThriftTest.pfx", SearchOption.AllDirectories) - .FirstOrDefault(); - if (certFile == null) - { - if (maxCount == 0) - throw new FileNotFoundException("Cannot find file in directories"); - return GetCertPath(di.Parent, maxCount - 1); - } - - return certFile.FullName; - } - - private static X509Certificate LocalCertificateSelectionCallback(object sender, - string targetHost, X509CertificateCollection localCertificates, - X509Certificate remoteCertificate, string[] acceptableIssuers) - { - return GetCertificate(); - } - - private static bool ClientCertValidator(object sender, X509Certificate certificate, - X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - return true; - } - - private enum Transport - { - Tcp, - TcpBuffered, - NamedPipe, - Http, - TcpTls, - Framed - } - - private enum Protocol - { - Binary, - Compact, - Json, - Multiplexed - } - - public class HttpServerSample - { - public void Run(CancellationToken cancellationToken) - { - var config = new ConfigurationBuilder() - .AddEnvironmentVariables(prefix: "ASPNETCORE_") - .Build(); - - var host = new WebHostBuilder() - .UseConfiguration(config) - .UseKestrel() - .UseUrls("http://localhost:9090") - .UseContentRoot(Directory.GetCurrentDirectory()) - .UseStartup() - .Build(); - - host.RunAsync(cancellationToken).GetAwaiter().GetResult(); - } - - public class Startup - { - public Startup(IHostingEnvironment env) - { - var builder = new ConfigurationBuilder() - .SetBasePath(env.ContentRootPath) - .AddEnvironmentVariables(); - - Configuration = builder.Build(); - } - - public IConfigurationRoot Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env, - ILoggerFactory loggerFactory) - { - app.UseMiddleware(); - } - } - } - - public class CalculatorAsyncHandler : Calculator.IAsync - { - private readonly Dictionary _log = new Dictionary(); - - public CalculatorAsyncHandler() - { - } - - public async Task getStructAsync(int key, - CancellationToken cancellationToken) - { - Logger.LogInformation("GetStructAsync({0})", key); - return await Task.FromResult(_log[key]); - } - - public async Task pingAsync(CancellationToken cancellationToken) - { - Logger.LogInformation("PingAsync()"); - await Task.CompletedTask; - } - - public async Task addAsync(int num1, int num2, CancellationToken cancellationToken) - { - Logger.LogInformation($"AddAsync({num1},{num2})"); - return await Task.FromResult(num1 + num2); - } - - public async Task calculateAsync(int logid, Work w, CancellationToken cancellationToken) - { - Logger.LogInformation($"CalculateAsync({logid}, [{w.Op},{w.Num1},{w.Num2}])"); - - var val = 0; - switch (w.Op) - { - case Operation.ADD: - val = w.Num1 + w.Num2; - break; - - case Operation.SUBTRACT: - val = w.Num1 - w.Num2; - break; - - case Operation.MULTIPLY: - val = w.Num1 * w.Num2; - break; - - case Operation.DIVIDE: - if (w.Num2 == 0) - { - var io = new InvalidOperation - { - WhatOp = (int) w.Op, - Why = "Cannot divide by 0" - }; - - throw io; - } - val = w.Num1 / w.Num2; - break; - - default: - { - var io = new InvalidOperation - { - WhatOp = (int) w.Op, - Why = "Unknown operation" - }; - - throw io; - } - } - - var entry = new SharedStruct - { - Key = logid, - Value = val.ToString() - }; - - _log[logid] = entry; - - return await Task.FromResult(val); - } - - public async Task zipAsync(CancellationToken cancellationToken) - { - Logger.LogInformation("ZipAsync() with delay 100mc"); - await Task.Delay(100, CancellationToken.None); - } - } - - public class SharedServiceAsyncHandler : SharedService.IAsync - { - public async Task getStructAsync(int key, CancellationToken cancellationToken) - { - Logger.LogInformation("GetStructAsync({0})", key); - return await Task.FromResult(new SharedStruct() - { - Key = key, - Value = "GetStructAsync" - }); - } - } - } -} diff --git a/tutorial/netcore/Server/Properties/AssemblyInfo.cs b/tutorial/netcore/Server/Properties/AssemblyInfo.cs deleted file mode 100644 index a0442350bd9..00000000000 --- a/tutorial/netcore/Server/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Licensed to the Apache Software Foundation(ASF) under one -// or more contributor license agreements.See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership.The ASF licenses this file -// to you under the Apache License, Version 2.0 (the -// "License"); you may not use this file except in compliance -// with the License. You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, -// software distributed under the License is distributed on an -// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -// KIND, either express or implied. See the License for the -// specific language governing permissions and limitations -// under the License. - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("e210fc10-5aff-4b04-ac21-58afc7b74b0c")] \ No newline at end of file diff --git a/tutorial/netcore/Server/Properties/launchSettings.json b/tutorial/netcore/Server/Properties/launchSettings.json deleted file mode 100644 index 78076ff7cf5..00000000000 --- a/tutorial/netcore/Server/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "Server": { - "commandName": "Project", - "commandLineArgs": "-p:multiplexed" - } - } -} \ No newline at end of file diff --git a/tutorial/netcore/Server/Server.csproj b/tutorial/netcore/Server/Server.csproj deleted file mode 100644 index 0fbd3032398..00000000000 --- a/tutorial/netcore/Server/Server.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - netcoreapp2.0 - Server - Server - Exe - false - false - false - false - - - - - - - - - - - - - - - diff --git a/tutorial/netcore/Server/ThriftTest.pfx b/tutorial/netcore/Server/ThriftTest.pfx deleted file mode 100644 index f0ded28173dc2c33cebbb2b74e1e9e9e870b5876..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2661 zcmY+Fc{r5q7ssC&Gb1!J$(kiQNi-_kNTzK}lBB4-#%>tDNgCV8K7;IKOK6d75tC&a zp={ZTH)}K@WXZmpv83PB^)A`wF(pXt7XpsY=bHUSlV3;5-A{d&ZS=A9rAjL!JLlxE zU_0M6u}dL5dyZUM*eZRTK7%!HnQk@RhDO-B4XYapVO%Fw7K^smqmrq9#TGaL=NEIm z?!`FK&>hR?Z@)%UKPau-%?m`A(>#}=i#q*6>Xe+P#mwBs6Q0@@Ixp|5@9I+wut zA#tRevtir~_G0T(aAFKzvy!O$=C`*W)A|(nrt(YY1n}Kp^LEZq_lyzXl)hwOG@G=i zxbiB-SnTQD^sz>x%QCdt1fw!Er?MpQ>#O~U^B1Ih|GdFM1{`4ISt#RHN4|ZYyq|=< z{j;$~n=*954;otf@)^47LvcfPIKt$_Y2BL+D}7sV7s{aov!F89pkkhg#@d`RVvtv8 zqhf(QFGtL@?Vi^c`LJWbZE9|TN_1?X9?l3DaIjMO5`V9F;~;j1FwiWFV#DZK zPZjSTs!0RAwSeaugCPfE_z~82e~?}o;1!SDpMJeV`Q?+Y@TQRE z%jhKjwXIG1?LW{8%1ry~$CvoFtuttc!kQ${aiZfTlsc}(9#g1pD3VzLU3ij7h2^CD z;6Lz8^m(Xe5?)8Y0Gr#QxBP*P)`mX~ycEnzpRed9N46To2eUk?5^Lp}$Xu=>65C8xu{J&6G(`>&f z-~~7X>HrGR1atr=u0{d&fFqaa0!O&99#K(?2gPlgcy9MFU_Ez}9Obs^@?Q}%0v{+j;MU>669QYwovF;u<-Oys<_RI{b3>F|lw0+!xJ>$_T%M|8 z*-&MWR7IRjyg|Rdz}Y^1c3>+=Wp`aAotnEcJk{mR2!9S=p@lzc?XYcYm9LJXMtHbTOVA7ageNhdBfi0|v1eLr9PtqI`)XEsA zC0p*r#f2MT4Hybzy5V<-3)*Qcno)THYn1lrjq6Dik zc86XkszLcvn;9QTVpJ9nk<@$OqssciMrRF6FvCqZbspu(u*qkj2*`%Mz8yK zJdDp2+luWj&vuSBXbE_thM;=6A| zTxptZh*kG4;p+`oVSXP~RY=Ckmncb%Q_UISo?$+pr{w0qs^nnM(Hjvem6Iv&+#MtM zv{NJq4}S()s9l6QL`u&D)**e1PVG7Kle}4G&E6j*6WUk@Gf{A7t$m7Kzgxiio)Vux zaUZfKT(@FZ>2x``Vy-=XKo?(27vH5gZ(9I{TgrlFvqh3z9qJGySLfwbj9a-H4Nq*qFpUg@ld}K z)hFz#CqBwVT7Rl=a|*hQAa-`0o9X{L*g@fX}@vnbf G^#21?=Cu0& diff --git a/tutorial/netcore/Tutorial.sln b/tutorial/netcore/Tutorial.sln deleted file mode 100644 index 2ddcd4617c0..00000000000 --- a/tutorial/netcore/Tutorial.sln +++ /dev/null @@ -1,78 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26114.2 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netcore\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Interfaces", "Interfaces\Interfaces.csproj", "{B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{E08F5B84-2B4A-4E09-82D1-E0715775CE5E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.ActiveCfg = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x64.Build.0 = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.ActiveCfg = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Debug|x86.Build.0 = Debug|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|Any CPU.Build.0 = Release|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.ActiveCfg = Release|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x64.Build.0 = Release|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.ActiveCfg = Release|Any CPU - {C20EA2A9-7660-47DE-9A49-D1EF12FB2895}.Release|x86.Build.0 = Release|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.ActiveCfg = Debug|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x64.Build.0 = Debug|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.ActiveCfg = Debug|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Debug|x86.Build.0 = Debug|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|Any CPU.Build.0 = Release|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.ActiveCfg = Release|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x64.Build.0 = Release|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.ActiveCfg = Release|Any CPU - {B9E24D84-2712-4158-8F1A-DDE44CD1BB0A}.Release|x86.Build.0 = Release|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.ActiveCfg = Debug|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x64.Build.0 = Debug|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.ActiveCfg = Debug|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Debug|x86.Build.0 = Debug|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|Any CPU.Build.0 = Release|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.ActiveCfg = Release|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x64.Build.0 = Release|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.ActiveCfg = Release|Any CPU - {E4CA1EF0-B181-4A5D-A02C-DB0750A59CDF}.Release|x86.Build.0 = Release|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.ActiveCfg = Debug|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x64.Build.0 = Debug|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.ActiveCfg = Debug|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Debug|x86.Build.0 = Debug|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|Any CPU.Build.0 = Release|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.ActiveCfg = Release|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x64.Build.0 = Release|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.ActiveCfg = Release|Any CPU - {E08F5B84-2B4A-4E09-82D1-E0715775CE5E}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {070A5D1D-B29D-4603-999D-693DB444AD0D} - EndGlobalSection -EndGlobal diff --git a/tutorial/netcore/build.cmd b/tutorial/netcore/build.cmd deleted file mode 100644 index 9b84ef27606..00000000000 --- a/tutorial/netcore/build.cmd +++ /dev/null @@ -1,25 +0,0 @@ -@echo off -rem /* -rem * Licensed to the Apache Software Foundation (ASF) under one -rem * or more contributor license agreements. See the NOTICE file -rem * distributed with this work for additional information -rem * regarding copyright ownership. The ASF licenses this file -rem * to you under the Apache License, Version 2.0 (the -rem * "License"); you may not use this file except in compliance -rem * with the License. You may obtain a copy of the License at -rem * -rem * http://www.apache.org/licenses/LICENSE-2.0 -rem * -rem * Unless required by applicable law or agreed to in writing, -rem * software distributed under the License is distributed on an -rem * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -rem * KIND, either express or implied. See the License for the -rem * specific language governing permissions and limitations -rem * under the License. -rem */ -setlocal - -dotnet --info -dotnet build - -:eof diff --git a/tutorial/netcore/build.sh b/tutorial/netcore/build.sh deleted file mode 100755 index c97e310f011..00000000000 --- a/tutorial/netcore/build.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -#exit if any command fails -set -e - -dotnet --info -dotnet build diff --git a/tutorial/shared.thrift b/tutorial/shared.thrift index 5747f06bfc3..3c6a69db871 100644 --- a/tutorial/shared.thrift +++ b/tutorial/shared.thrift @@ -30,7 +30,6 @@ namespace java shared namespace perl shared namespace php shared namespace haxe shared -namespace netcore shared namespace netstd shared diff --git a/tutorial/tutorial.thrift b/tutorial/tutorial.thrift index ea18b73ddce..f1e291297dd 100644 --- a/tutorial/tutorial.thrift +++ b/tutorial/tutorial.thrift @@ -71,7 +71,6 @@ namespace java tutorial namespace php tutorial namespace perl tutorial namespace haxe tutorial -namespace netcore tutorial namespace netstd tutorial /** From 6e4c581fddae9106c2c5a59c4d0bfbe6ad3e4560 Mon Sep 17 00:00:00 2001 From: pengzhouhu Date: Mon, 21 Oct 2019 22:21:11 +0800 Subject: [PATCH 404/756] THRIFT-4949: Improve HTTP/1 server test case Client: java This closes #1886. --- lib/java/gradle.properties | 4 +- lib/java/gradle/environment.gradle | 6 ++- lib/java/gradle/functionalTests.gradle | 24 ++++++++- lib/java/gradle/sourceConfiguration.gradle | 1 + .../org/apache/thrift/test/TestClient.java | 13 ++++- .../org/apache/thrift/test/TestServlet.java | 52 +++++++++++++++++++ .../thrift/test/TestTServletServer.java | 52 +++++++++++++++++++ 7 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 lib/java/test/org/apache/thrift/test/TestServlet.java create mode 100644 lib/java/test/org/apache/thrift/test/TestTServletServer.java diff --git a/lib/java/gradle.properties b/lib/java/gradle.properties index 8559464c9da..1cdf095b562 100644 --- a/lib/java/gradle.properties +++ b/lib/java/gradle.properties @@ -28,7 +28,9 @@ maven-repository-id=apache.releases.https httpclient.version=4.5.10 httpcore.version=4.4.12 slf4j.version=1.7.28 -servlet.version=2.5 +#servlet.version=2.5 +#It contains servlet3 +tomcat.embed.version=8.5.46 junit.version=4.12 mockito.version=1.10.19 javax.annotation.version=1.3.2 diff --git a/lib/java/gradle/environment.gradle b/lib/java/gradle/environment.gradle index 45fa63a1754..965a9088177 100644 --- a/lib/java/gradle/environment.gradle +++ b/lib/java/gradle/environment.gradle @@ -44,7 +44,8 @@ ext.mavenRepositoryUrl = property('maven-repository-url') // Versions used in this project ext.httpclientVersion = property('httpclient.version') ext.httpcoreVersion = property('httpcore.version') -ext.servletVersion = property('servlet.version') +//ext.servletVersion = property('servlet.version') +ext.tomcatEmbedVersion = property('tomcat.embed.version') ext.slf4jVersion = property('slf4j.version') ext.junitVersion = property('junit.version') ext.mockitoVersion = property('mockito.version') @@ -66,7 +67,8 @@ dependencies { compile "org.slf4j:slf4j-api:${slf4jVersion}" compile "org.apache.httpcomponents:httpclient:${httpclientVersion}" compile "org.apache.httpcomponents:httpcore:${httpcoreVersion}" - compile "javax.servlet:servlet-api:${servletVersion}" + //compile "javax.servlet:servlet-api:${servletVersion}" + compile "org.apache.tomcat.embed:tomcat-embed-core:${tomcatEmbedVersion}" compile "javax.annotation:javax.annotation-api:${javaxAnnotationVersion}" testCompile "junit:junit:${junitVersion}" diff --git a/lib/java/gradle/functionalTests.gradle b/lib/java/gradle/functionalTests.gradle index c420d122c44..6a388a697de 100644 --- a/lib/java/gradle/functionalTests.gradle +++ b/lib/java/gradle/functionalTests.gradle @@ -34,6 +34,7 @@ sourceSets { include '**/test/TestClient.java' include '**/test/TestServer.java' include '**/test/TestNonblockingServer.java' + include '**/test/TestTServletServer.java' } } } @@ -55,7 +56,7 @@ dependencies { shadowJar { description = 'Assemble a test JAR file for cross-check execution' // make sure the runners are created when this runs - dependsOn 'generateRunnerScriptForClient', 'generateRunnerScriptForServer', 'generateRunnerScriptForNonblockingServer' + dependsOn 'generateRunnerScriptForClient', 'generateRunnerScriptForServer', 'generateRunnerScriptForNonblockingServer', 'generateRunnerScriptForTServletServer' baseName = 'functionalTest' destinationDir = file("$buildDir/functionalTestJar") @@ -153,3 +154,24 @@ ${scriptHead} serverFile.setExecutable(true, false) } } + +task generateRunnerScriptForTServletServer(group: 'Build') { + description = 'Generate a runner script for cross-check tests with TestTServletServer' + + def serverFile = file("$buildDir/runservletserver${scriptExt}") + + def runServerText = """\ +${scriptHead} + +"${javaExe}" -cp "$jarPath" "-Djavax.net.ssl.keyStore=$keyStore" -Djavax.net.ssl.keyStorePassword=thrift org.apache.thrift.test.TestTServletServer $args +""" + + inputs.property 'runServerText', runServerText + outputs.file serverFile + + doLast { + serverFile.parentFile.mkdirs() + serverFile.text = runServerText + serverFile.setExecutable(true, false) + } +} diff --git a/lib/java/gradle/sourceConfiguration.gradle b/lib/java/gradle/sourceConfiguration.gradle index 8dd0331f799..3bd432a0f01 100644 --- a/lib/java/gradle/sourceConfiguration.gradle +++ b/lib/java/gradle/sourceConfiguration.gradle @@ -34,6 +34,7 @@ sourceSets { exclude '**/test/TestClient.java' exclude '**/test/TestServer.java' exclude '**/test/TestNonblockingServer.java' + exclude '**/test/TestTServletServer.java' } resources { srcDir 'test' diff --git a/lib/java/test/org/apache/thrift/test/TestClient.java b/lib/java/test/org/apache/thrift/test/TestClient.java index 84410cea0c2..dbada08ffa2 100644 --- a/lib/java/test/org/apache/thrift/test/TestClient.java +++ b/lib/java/test/org/apache/thrift/test/TestClient.java @@ -27,6 +27,7 @@ import java.util.Map; import java.util.Set; +import org.apache.http.impl.client.HttpClients; import org.apache.thrift.TApplicationException; import org.apache.thrift.TException; import org.apache.thrift.TSerializer; @@ -76,6 +77,7 @@ public static void main(String [] args) { String protocol_type = "binary"; String transport_type = "buffered"; boolean ssl = false; + boolean http_client = false; int socketTimeout = 1000; @@ -99,6 +101,8 @@ public static void main(String [] args) { transport_type.trim(); } else if (args[i].equals("--ssl")) { ssl = true; + } else if (args[i].equals("--client")) { + http_client = true; } else if (args[i].equals("--help")) { System.out.println("Allowed options:"); System.out.println(" --help\t\t\tProduce help message"); @@ -145,8 +149,13 @@ public static void main(String [] args) { try { if (transport_type.equals("http")) { - String url = "http://" + host + ":" + port + "/service"; - transport = new THttpClient(url); + String url = "http://" + host + ":" + port + "/test/service"; + if (http_client == true) { + + transport = new THttpClient(url, HttpClients.createDefault()); + } else { + transport = new THttpClient(url); + } } else { TSocket socket = null; if (ssl == true) { diff --git a/lib/java/test/org/apache/thrift/test/TestServlet.java b/lib/java/test/org/apache/thrift/test/TestServlet.java new file mode 100644 index 00000000000..e63109da8ad --- /dev/null +++ b/lib/java/test/org/apache/thrift/test/TestServlet.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 org.apache.thrift.test; + +import org.apache.thrift.TProcessor; +import org.apache.thrift.protocol.TCompactProtocol; +import org.apache.thrift.protocol.TProtocolFactory; +import org.apache.thrift.server.ServerTestBase.TestHandler; +import org.apache.thrift.server.TExtensibleServlet; + +import thrift.test.ThriftTest; + +@SuppressWarnings("serial") +public class TestServlet extends TExtensibleServlet { + + @Override + protected TProtocolFactory getInProtocolFactory(){ + TProtocolFactory tProtocolFactory = new TCompactProtocol.Factory(); + return tProtocolFactory; + } + + @Override + protected TProtocolFactory getOutProtocolFactory(){ + TProtocolFactory tProtocolFactory = new TCompactProtocol.Factory(); + return tProtocolFactory; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Override + protected TProcessor getProcessor(){ + TestHandler testHandler = new TestHandler(); + ThriftTest.Processor testProcessor = new ThriftTest.Processor(testHandler); + return testProcessor; + } +} diff --git a/lib/java/test/org/apache/thrift/test/TestTServletServer.java b/lib/java/test/org/apache/thrift/test/TestTServletServer.java new file mode 100644 index 00000000000..93e7944f820 --- /dev/null +++ b/lib/java/test/org/apache/thrift/test/TestTServletServer.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 org.apache.thrift.test; + +import org.apache.catalina.core.StandardContext; +import org.apache.catalina.startup.Tomcat; +import org.apache.catalina.startup.Tomcat.FixContextListener; + + +/** + * run tomcat for test TServlet + */ +public class TestTServletServer { + + static final int port = 9090; + + public static void main(String [] args) throws Exception{ + Tomcat tomcat = new Tomcat(); + tomcat.setPort( port ); + tomcat.setBaseDir(System.getProperty("user.dir")+"\\build"); + tomcat.getHost().setAutoDeploy( false ); + + String contextPath = "/test"; + StandardContext context = new StandardContext(); + context.setPath( contextPath ); + context.addLifecycleListener( new FixContextListener() ); + tomcat.getHost().addChild( context ); + + tomcat.addServlet( contextPath, "testServlet", new TestServlet() ); + context.addServletMappingDecoded( "/service", "testServlet"); + tomcat.start(); + tomcat.getServer().await(); + } + +} From 9cb1c794cd39cfb276771f8e52f0306eb8d462fd Mon Sep 17 00:00:00 2001 From: Qinghui Xu Date: Mon, 21 Oct 2019 02:17:02 +0200 Subject: [PATCH 405/756] THRIFT-4252: Close sockets when shut down server In TThreadPoolServer, threads are blocking in io with open sockets, as long as clients don't close the connection, server threads are never stopped even after a shutdown is called on server (because they are blocked waiting for io). To be able to stop all server threads properly, server should proactively close sockets once a shutdown is initiated. --- .../thrift/server/TThreadPoolServer.java | 36 ++++++----- .../thrift/server/TestThreadPoolServer.java | 62 +++++++++++++++++++ 2 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 lib/java/test/org/apache/thrift/server/TestThreadPoolServer.java diff --git a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java index 87e873381d2..e1b6e768b76 100644 --- a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java +++ b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java @@ -19,9 +19,8 @@ package org.apache.thrift.server; -import java.util.Arrays; -import java.util.List; import java.util.Random; +import java.util.WeakHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.SynchronousQueue; @@ -39,8 +38,7 @@ /** * Server which uses Java's built in ThreadPool management to spawn off - * a worker pool that - * + * a worker pool that deals with client connections in blocking way. */ public class TThreadPoolServer extends TServer { private static final Logger LOGGER = LoggerFactory.getLogger(TThreadPoolServer.class.getName()); @@ -109,6 +107,7 @@ public Args executorService(ExecutorService executorService) { // Executor service for handling client connections private ExecutorService executorService_; + private WeakHashMap activeWorkers = new WeakHashMap<>(); private final TimeUnit stopTimeoutUnit; @@ -148,7 +147,7 @@ private static ExecutorService createDefaultExecutorService(Args args) { protected ExecutorService getExecutorService() { return executorService_; } - + protected boolean preServe() { try { serverTransport_.listen(); @@ -163,7 +162,6 @@ protected boolean preServe() { } stopped_ = false; setServing(true); - return true; } @@ -173,13 +171,14 @@ public void serve() { } execute(); - waitForShutdown(); - + if (!waitForShutdown()) { + LOGGER.error("Shutdown is not done after " + stopTimeoutVal + stopTimeoutUnit); + } + setServing(false); } - + protected void execute() { - int failureCount = 0; while (!stopped_) { try { TTransport client = serverTransport_.accept(); @@ -190,6 +189,7 @@ protected void execute() { while(true) { try { executorService_.execute(wp); + activeWorkers.put(wp, Boolean.TRUE); break; } catch(Throwable t) { if (t instanceof RejectedExecutionException) { @@ -226,16 +226,13 @@ protected void execute() { } } catch (TTransportException ttx) { if (!stopped_) { - ++failureCount; LOGGER.warn("Transport error occurred during acceptance of message.", ttx); } } } } - - protected void waitForShutdown() { - executorService_.shutdown(); + protected boolean waitForShutdown() { // 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 @@ -245,18 +242,23 @@ protected void waitForShutdown() { while (timeoutMS >= 0) { try { executorService_.awaitTermination(timeoutMS, TimeUnit.MILLISECONDS); - break; + return true; } catch (InterruptedException ix) { long newnow = System.currentTimeMillis(); timeoutMS -= (newnow - now); now = newnow; } } + return false; } public void stop() { stopped_ = true; serverTransport_.interrupt(); + executorService_.shutdown(); + for (WorkerProcess wp : activeWorkers.keySet()) { + wp.stop(); + } } private class WorkerProcess implements Runnable { @@ -355,5 +357,9 @@ else if (x.getCause() instanceof TTransportException) { } return false; } + + private void stop() { + client_.close(); + } } } diff --git a/lib/java/test/org/apache/thrift/server/TestThreadPoolServer.java b/lib/java/test/org/apache/thrift/server/TestThreadPoolServer.java new file mode 100644 index 00000000000..e81d8012f5e --- /dev/null +++ b/lib/java/test/org/apache/thrift/server/TestThreadPoolServer.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift.server; + +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.transport.TServerSocket; +import org.apache.thrift.transport.TServerTransport; +import org.apache.thrift.transport.TSocket; +import org.junit.Assert; +import org.junit.Test; +import thrift.test.ThriftTest; + +import java.util.concurrent.ThreadPoolExecutor; + +public class TestThreadPoolServer { + + /** + * Test server is shut down properly even with some open clients. + */ + @Test + public void testStopServerWithOpenClient() throws Exception { + TServerSocket serverSocket = new TServerSocket(0); + TThreadPoolServer server = buildServer(serverSocket); + Thread serverThread = new Thread(() -> server.serve()); + serverThread.start(); + try (TSocket client = new TSocket("localhost", serverSocket.getServerSocket().getLocalPort())) { + client.open(); + Thread.sleep(1000); + // There is a thread listening to the client + Assert.assertEquals(1, ((ThreadPoolExecutor) server.getExecutorService()).getActiveCount()); + server.stop(); + server.waitForShutdown(); + // After server is stopped, the executor thread pool should be shut down + Assert.assertTrue("Server thread pool should be terminated.", server.getExecutorService().isTerminated()); + Assert.assertTrue("Client is still open.", client.isOpen()); + } + } + + private TThreadPoolServer buildServer(TServerTransport serverSocket) { + TThreadPoolServer.Args args = new TThreadPoolServer.Args(serverSocket) + .protocolFactory(new TBinaryProtocol.Factory()) + .processor(new ThriftTest.Processor<>(new ServerTestBase.TestHandler())); + return new TThreadPoolServer(args); + } +} From c03e2aa196615bc3149d1829b8b8ed01e58c7aa1 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Wed, 23 Oct 2019 13:43:09 -0700 Subject: [PATCH 406/756] THRIFT-4984: Ignore EOF error in TSimpleServer ReadFrame call EOF isn't an error that should be bubbled up to the caller and we are already ignoring other EOF errors in TSimpleServer.processRequest [0]. Client: go This closes #1904. [0]: https://github.com/apache/thrift/blob/cecee50308fc7e6f77f55b3fd906c1c6c471fa2f/lib/go/thrift/simple_server.go#L265-L266 --- lib/go/thrift/simple_server.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go index f8efbed914d..c1ab95750f5 100644 --- a/lib/go/thrift/simple_server.go +++ b/lib/go/thrift/simple_server.go @@ -20,6 +20,7 @@ package thrift import ( + "io" "log" "runtime/debug" "sync" @@ -231,7 +232,7 @@ func (p *TSimpleServer) processRequests(client TTransport) error { defer func() { if e := recover(); e != nil { - log.Printf("panic in processor: %s: %s", e, debug.Stack()) + log.Printf("panic in processor: %v: %s", e, debug.Stack()) } }() @@ -255,9 +256,12 @@ func (p *TSimpleServer) processRequests(client TTransport) error { // won't break when it's called again later when we // actually start to read the message. if err := headerProtocol.ReadFrame(); err != nil { + if err == io.EOF { + return nil + } return err } - ctx = AddReadTHeaderToContext(defaultCtx, headerProtocol.GetReadHeaders()) + ctx = AddReadTHeaderToContext(ctx, headerProtocol.GetReadHeaders()) ctx = SetWriteHeaderList(ctx, p.forwardHeaders) } From e4870a3571475726dfd53997d7742044d71fd353 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Thu, 24 Oct 2019 13:23:30 -0700 Subject: [PATCH 407/756] THRIFT-4985: Refactor logging in Go library - Add a new Logger type to make logging configurable - Use the new logger in TSimpleServer and TDebugProtocol - Remove pointless log in TZlibTransport - Remove panic recovery from TSimpleServer. Thrift shouldn't catch panics caused by caller-defined RPC handlers. Client: go This closes #1906. --- lib/go/thrift/debug_protocol.go | 110 +++++++++++++++++++------------- lib/go/thrift/logger.go | 69 ++++++++++++++++++++ lib/go/thrift/simple_server.go | 23 ++++--- lib/go/thrift/zlib_transport.go | 2 - 4 files changed, 149 insertions(+), 55 deletions(-) create mode 100644 lib/go/thrift/logger.go diff --git a/lib/go/thrift/debug_protocol.go b/lib/go/thrift/debug_protocol.go index 57943e0f35d..c33fba879ad 100644 --- a/lib/go/thrift/debug_protocol.go +++ b/lib/go/thrift/debug_protocol.go @@ -21,23 +21,40 @@ package thrift import ( "context" - "log" + "fmt" ) type TDebugProtocol struct { Delegate TProtocol LogPrefix string + Logger Logger } type TDebugProtocolFactory struct { Underlying TProtocolFactory LogPrefix string + Logger Logger } +// NewTDebugProtocolFactory creates a TDebugProtocolFactory. +// +// Deprecated: Please use NewTDebugProtocolFactoryWithLogger or the struct +// itself instead. This version will use the default logger from standard +// library. func NewTDebugProtocolFactory(underlying TProtocolFactory, logPrefix string) *TDebugProtocolFactory { return &TDebugProtocolFactory{ Underlying: underlying, LogPrefix: logPrefix, + Logger: StdLogger(nil), + } +} + +// NewTDebugProtocolFactoryWithLogger creates a TDebugProtocolFactory. +func NewTDebugProtocolFactoryWithLogger(underlying TProtocolFactory, logPrefix string, logger Logger) *TDebugProtocolFactory { + return &TDebugProtocolFactory{ + Underlying: underlying, + LogPrefix: logPrefix, + Logger: logger, } } @@ -45,223 +62,228 @@ func (t *TDebugProtocolFactory) GetProtocol(trans TTransport) TProtocol { return &TDebugProtocol{ Delegate: t.Underlying.GetProtocol(trans), LogPrefix: t.LogPrefix, + Logger: fallbackLogger(t.Logger), } } +func (tdp *TDebugProtocol) logf(format string, v ...interface{}) { + fallbackLogger(tdp.Logger)(fmt.Sprintf(format, v...)) +} + func (tdp *TDebugProtocol) WriteMessageBegin(name string, typeId TMessageType, seqid int32) error { err := tdp.Delegate.WriteMessageBegin(name, typeId, seqid) - log.Printf("%sWriteMessageBegin(name=%#v, typeId=%#v, seqid=%#v) => %#v", tdp.LogPrefix, name, typeId, seqid, err) + tdp.logf("%sWriteMessageBegin(name=%#v, typeId=%#v, seqid=%#v) => %#v", tdp.LogPrefix, name, typeId, seqid, err) return err } func (tdp *TDebugProtocol) WriteMessageEnd() error { err := tdp.Delegate.WriteMessageEnd() - log.Printf("%sWriteMessageEnd() => %#v", tdp.LogPrefix, err) + tdp.logf("%sWriteMessageEnd() => %#v", tdp.LogPrefix, err) return err } func (tdp *TDebugProtocol) WriteStructBegin(name string) error { err := tdp.Delegate.WriteStructBegin(name) - log.Printf("%sWriteStructBegin(name=%#v) => %#v", tdp.LogPrefix, name, err) + tdp.logf("%sWriteStructBegin(name=%#v) => %#v", tdp.LogPrefix, name, err) return err } func (tdp *TDebugProtocol) WriteStructEnd() error { err := tdp.Delegate.WriteStructEnd() - log.Printf("%sWriteStructEnd() => %#v", tdp.LogPrefix, err) + tdp.logf("%sWriteStructEnd() => %#v", tdp.LogPrefix, err) return err } func (tdp *TDebugProtocol) WriteFieldBegin(name string, typeId TType, id int16) error { err := tdp.Delegate.WriteFieldBegin(name, typeId, id) - log.Printf("%sWriteFieldBegin(name=%#v, typeId=%#v, id%#v) => %#v", tdp.LogPrefix, name, typeId, id, err) + tdp.logf("%sWriteFieldBegin(name=%#v, typeId=%#v, id%#v) => %#v", tdp.LogPrefix, name, typeId, id, err) return err } func (tdp *TDebugProtocol) WriteFieldEnd() error { err := tdp.Delegate.WriteFieldEnd() - log.Printf("%sWriteFieldEnd() => %#v", tdp.LogPrefix, err) + tdp.logf("%sWriteFieldEnd() => %#v", tdp.LogPrefix, err) return err } func (tdp *TDebugProtocol) WriteFieldStop() error { err := tdp.Delegate.WriteFieldStop() - log.Printf("%sWriteFieldStop() => %#v", tdp.LogPrefix, err) + tdp.logf("%sWriteFieldStop() => %#v", tdp.LogPrefix, err) return err } func (tdp *TDebugProtocol) WriteMapBegin(keyType TType, valueType TType, size int) error { err := tdp.Delegate.WriteMapBegin(keyType, valueType, size) - log.Printf("%sWriteMapBegin(keyType=%#v, valueType=%#v, size=%#v) => %#v", tdp.LogPrefix, keyType, valueType, size, err) + tdp.logf("%sWriteMapBegin(keyType=%#v, valueType=%#v, size=%#v) => %#v", tdp.LogPrefix, keyType, valueType, size, err) return err } func (tdp *TDebugProtocol) WriteMapEnd() error { err := tdp.Delegate.WriteMapEnd() - log.Printf("%sWriteMapEnd() => %#v", tdp.LogPrefix, err) + tdp.logf("%sWriteMapEnd() => %#v", tdp.LogPrefix, err) return err } func (tdp *TDebugProtocol) WriteListBegin(elemType TType, size int) error { err := tdp.Delegate.WriteListBegin(elemType, size) - log.Printf("%sWriteListBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err) + tdp.logf("%sWriteListBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err) return err } func (tdp *TDebugProtocol) WriteListEnd() error { err := tdp.Delegate.WriteListEnd() - log.Printf("%sWriteListEnd() => %#v", tdp.LogPrefix, err) + tdp.logf("%sWriteListEnd() => %#v", tdp.LogPrefix, err) return err } func (tdp *TDebugProtocol) WriteSetBegin(elemType TType, size int) error { err := tdp.Delegate.WriteSetBegin(elemType, size) - log.Printf("%sWriteSetBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err) + tdp.logf("%sWriteSetBegin(elemType=%#v, size=%#v) => %#v", tdp.LogPrefix, elemType, size, err) return err } func (tdp *TDebugProtocol) WriteSetEnd() error { err := tdp.Delegate.WriteSetEnd() - log.Printf("%sWriteSetEnd() => %#v", tdp.LogPrefix, err) + tdp.logf("%sWriteSetEnd() => %#v", tdp.LogPrefix, err) return err } func (tdp *TDebugProtocol) WriteBool(value bool) error { err := tdp.Delegate.WriteBool(value) - log.Printf("%sWriteBool(value=%#v) => %#v", tdp.LogPrefix, value, err) + tdp.logf("%sWriteBool(value=%#v) => %#v", tdp.LogPrefix, value, err) return err } func (tdp *TDebugProtocol) WriteByte(value int8) error { err := tdp.Delegate.WriteByte(value) - log.Printf("%sWriteByte(value=%#v) => %#v", tdp.LogPrefix, value, err) + tdp.logf("%sWriteByte(value=%#v) => %#v", tdp.LogPrefix, value, err) return err } func (tdp *TDebugProtocol) WriteI16(value int16) error { err := tdp.Delegate.WriteI16(value) - log.Printf("%sWriteI16(value=%#v) => %#v", tdp.LogPrefix, value, err) + tdp.logf("%sWriteI16(value=%#v) => %#v", tdp.LogPrefix, value, err) return err } func (tdp *TDebugProtocol) WriteI32(value int32) error { err := tdp.Delegate.WriteI32(value) - log.Printf("%sWriteI32(value=%#v) => %#v", tdp.LogPrefix, value, err) + tdp.logf("%sWriteI32(value=%#v) => %#v", tdp.LogPrefix, value, err) return err } func (tdp *TDebugProtocol) WriteI64(value int64) error { err := tdp.Delegate.WriteI64(value) - log.Printf("%sWriteI64(value=%#v) => %#v", tdp.LogPrefix, value, err) + tdp.logf("%sWriteI64(value=%#v) => %#v", tdp.LogPrefix, value, err) return err } func (tdp *TDebugProtocol) WriteDouble(value float64) error { err := tdp.Delegate.WriteDouble(value) - log.Printf("%sWriteDouble(value=%#v) => %#v", tdp.LogPrefix, value, err) + tdp.logf("%sWriteDouble(value=%#v) => %#v", tdp.LogPrefix, value, err) return err } func (tdp *TDebugProtocol) WriteString(value string) error { err := tdp.Delegate.WriteString(value) - log.Printf("%sWriteString(value=%#v) => %#v", tdp.LogPrefix, value, err) + tdp.logf("%sWriteString(value=%#v) => %#v", tdp.LogPrefix, value, err) return err } func (tdp *TDebugProtocol) WriteBinary(value []byte) error { err := tdp.Delegate.WriteBinary(value) - log.Printf("%sWriteBinary(value=%#v) => %#v", tdp.LogPrefix, value, err) + tdp.logf("%sWriteBinary(value=%#v) => %#v", tdp.LogPrefix, value, err) return err } func (tdp *TDebugProtocol) ReadMessageBegin() (name string, typeId TMessageType, seqid int32, err error) { name, typeId, seqid, err = tdp.Delegate.ReadMessageBegin() - log.Printf("%sReadMessageBegin() (name=%#v, typeId=%#v, seqid=%#v, err=%#v)", tdp.LogPrefix, name, typeId, seqid, err) + tdp.logf("%sReadMessageBegin() (name=%#v, typeId=%#v, seqid=%#v, err=%#v)", tdp.LogPrefix, name, typeId, seqid, err) return } func (tdp *TDebugProtocol) ReadMessageEnd() (err error) { err = tdp.Delegate.ReadMessageEnd() - log.Printf("%sReadMessageEnd() err=%#v", tdp.LogPrefix, err) + tdp.logf("%sReadMessageEnd() err=%#v", tdp.LogPrefix, err) return } func (tdp *TDebugProtocol) ReadStructBegin() (name string, err error) { name, err = tdp.Delegate.ReadStructBegin() - log.Printf("%sReadStructBegin() (name%#v, err=%#v)", tdp.LogPrefix, name, err) + tdp.logf("%sReadStructBegin() (name%#v, err=%#v)", tdp.LogPrefix, name, err) return } func (tdp *TDebugProtocol) ReadStructEnd() (err error) { err = tdp.Delegate.ReadStructEnd() - log.Printf("%sReadStructEnd() err=%#v", tdp.LogPrefix, err) + tdp.logf("%sReadStructEnd() err=%#v", tdp.LogPrefix, err) return } func (tdp *TDebugProtocol) ReadFieldBegin() (name string, typeId TType, id int16, err error) { name, typeId, id, err = tdp.Delegate.ReadFieldBegin() - log.Printf("%sReadFieldBegin() (name=%#v, typeId=%#v, id=%#v, err=%#v)", tdp.LogPrefix, name, typeId, id, err) + tdp.logf("%sReadFieldBegin() (name=%#v, typeId=%#v, id=%#v, err=%#v)", tdp.LogPrefix, name, typeId, id, err) return } func (tdp *TDebugProtocol) ReadFieldEnd() (err error) { err = tdp.Delegate.ReadFieldEnd() - log.Printf("%sReadFieldEnd() err=%#v", tdp.LogPrefix, err) + tdp.logf("%sReadFieldEnd() err=%#v", tdp.LogPrefix, err) return } func (tdp *TDebugProtocol) ReadMapBegin() (keyType TType, valueType TType, size int, err error) { keyType, valueType, size, err = tdp.Delegate.ReadMapBegin() - log.Printf("%sReadMapBegin() (keyType=%#v, valueType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, keyType, valueType, size, err) + tdp.logf("%sReadMapBegin() (keyType=%#v, valueType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, keyType, valueType, size, err) return } func (tdp *TDebugProtocol) ReadMapEnd() (err error) { err = tdp.Delegate.ReadMapEnd() - log.Printf("%sReadMapEnd() err=%#v", tdp.LogPrefix, err) + tdp.logf("%sReadMapEnd() err=%#v", tdp.LogPrefix, err) return } func (tdp *TDebugProtocol) ReadListBegin() (elemType TType, size int, err error) { elemType, size, err = tdp.Delegate.ReadListBegin() - log.Printf("%sReadListBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err) + tdp.logf("%sReadListBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err) return } func (tdp *TDebugProtocol) ReadListEnd() (err error) { err = tdp.Delegate.ReadListEnd() - log.Printf("%sReadListEnd() err=%#v", tdp.LogPrefix, err) + tdp.logf("%sReadListEnd() err=%#v", tdp.LogPrefix, err) return } func (tdp *TDebugProtocol) ReadSetBegin() (elemType TType, size int, err error) { elemType, size, err = tdp.Delegate.ReadSetBegin() - log.Printf("%sReadSetBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err) + tdp.logf("%sReadSetBegin() (elemType=%#v, size=%#v, err=%#v)", tdp.LogPrefix, elemType, size, err) return } func (tdp *TDebugProtocol) ReadSetEnd() (err error) { err = tdp.Delegate.ReadSetEnd() - log.Printf("%sReadSetEnd() err=%#v", tdp.LogPrefix, err) + tdp.logf("%sReadSetEnd() err=%#v", tdp.LogPrefix, err) return } func (tdp *TDebugProtocol) ReadBool() (value bool, err error) { value, err = tdp.Delegate.ReadBool() - log.Printf("%sReadBool() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + tdp.logf("%sReadBool() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) return } func (tdp *TDebugProtocol) ReadByte() (value int8, err error) { value, err = tdp.Delegate.ReadByte() - log.Printf("%sReadByte() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + tdp.logf("%sReadByte() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) return } func (tdp *TDebugProtocol) ReadI16() (value int16, err error) { value, err = tdp.Delegate.ReadI16() - log.Printf("%sReadI16() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + tdp.logf("%sReadI16() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) return } func (tdp *TDebugProtocol) ReadI32() (value int32, err error) { value, err = tdp.Delegate.ReadI32() - log.Printf("%sReadI32() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + tdp.logf("%sReadI32() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) return } func (tdp *TDebugProtocol) ReadI64() (value int64, err error) { value, err = tdp.Delegate.ReadI64() - log.Printf("%sReadI64() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + tdp.logf("%sReadI64() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) return } func (tdp *TDebugProtocol) ReadDouble() (value float64, err error) { value, err = tdp.Delegate.ReadDouble() - log.Printf("%sReadDouble() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + tdp.logf("%sReadDouble() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) return } func (tdp *TDebugProtocol) ReadString() (value string, err error) { value, err = tdp.Delegate.ReadString() - log.Printf("%sReadString() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + tdp.logf("%sReadString() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) return } func (tdp *TDebugProtocol) ReadBinary() (value []byte, err error) { value, err = tdp.Delegate.ReadBinary() - log.Printf("%sReadBinary() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) + tdp.logf("%sReadBinary() (value=%#v, err=%#v)", tdp.LogPrefix, value, err) return } func (tdp *TDebugProtocol) Skip(fieldType TType) (err error) { err = tdp.Delegate.Skip(fieldType) - log.Printf("%sSkip(fieldType=%#v) (err=%#v)", tdp.LogPrefix, fieldType, err) + tdp.logf("%sSkip(fieldType=%#v) (err=%#v)", tdp.LogPrefix, fieldType, err) return } func (tdp *TDebugProtocol) Flush(ctx context.Context) (err error) { err = tdp.Delegate.Flush(ctx) - log.Printf("%sFlush() (err=%#v)", tdp.LogPrefix, err) + tdp.logf("%sFlush() (err=%#v)", tdp.LogPrefix, err) return } diff --git a/lib/go/thrift/logger.go b/lib/go/thrift/logger.go new file mode 100644 index 00000000000..c42aac998b7 --- /dev/null +++ b/lib/go/thrift/logger.go @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "log" + "os" + "testing" +) + +// Logger is a simple wrapper of a logging function. +// +// In reality the users might actually use different logging libraries, and they +// are not always compatible with each other. +// +// Logger is meant to be a simple common ground that it's easy to wrap whatever +// logging library they use into. +// +// See https://issues.apache.org/jira/browse/THRIFT-4985 for the design +// discussion behind it. +type Logger func(msg string) + +// NopLogger is a Logger implementation that does nothing. +func NopLogger(msg string) {} + +// StdLogger wraps stdlib log package into a Logger. +// +// If logger passed in is nil, it will fallback to use stderr and default flags. +func StdLogger(logger *log.Logger) Logger { + if logger == nil { + logger = log.New(os.Stderr, "", log.LstdFlags) + } + return func(msg string) { + logger.Print(msg) + } +} + +// TestLogger is a Logger implementation can be used in test codes. +// +// It fails the test when being called. +func TestLogger(tb testing.TB) Logger { + return func(msg string) { + tb.Errorf("logger called with msg: %q", msg) + } +} + +func fallbackLogger(logger Logger) Logger { + if logger == nil { + return StdLogger(nil) + } + return logger +} diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go index c1ab95750f5..51e3509c180 100644 --- a/lib/go/thrift/simple_server.go +++ b/lib/go/thrift/simple_server.go @@ -20,9 +20,8 @@ package thrift import ( + "fmt" "io" - "log" - "runtime/debug" "sync" "sync/atomic" ) @@ -46,6 +45,8 @@ type TSimpleServer struct { // Headers to auto forward in THeaderProtocol forwardHeaders []string + + logger Logger } func NewTSimpleServer2(processor TProcessor, serverTransport TServerTransport) *TSimpleServer { @@ -149,6 +150,14 @@ func (p *TSimpleServer) SetForwardHeaders(headers []string) { p.forwardHeaders = keys } +// SetLogger sets the logger used by this TSimpleServer. +// +// If no logger was set before Serve is called, a default logger using standard +// log library will be used. +func (p *TSimpleServer) SetLogger(logger Logger) { + p.logger = logger +} + func (p *TSimpleServer) innerAccept() (int32, error) { client, err := p.serverTransport.Accept() p.mu.Lock() @@ -165,7 +174,7 @@ func (p *TSimpleServer) innerAccept() (int32, error) { go func() { defer p.wg.Done() if err := p.processRequests(client); err != nil { - log.Println("error processing request:", err) + p.logger(fmt.Sprintf("error processing request: %v", err)) } }() } @@ -185,6 +194,8 @@ func (p *TSimpleServer) AcceptLoop() error { } func (p *TSimpleServer) Serve() error { + p.logger = fallbackLogger(p.logger) + err := p.Listen() if err != nil { return err @@ -230,12 +241,6 @@ func (p *TSimpleServer) processRequests(client TTransport) error { outputProtocol = p.outputProtocolFactory.GetProtocol(outputTransport) } - defer func() { - if e := recover(); e != nil { - log.Printf("panic in processor: %v: %s", e, debug.Stack()) - } - }() - if inputTransport != nil { defer inputTransport.Close() } diff --git a/lib/go/thrift/zlib_transport.go b/lib/go/thrift/zlib_transport.go index f3d42673af9..e7efdfb9e53 100644 --- a/lib/go/thrift/zlib_transport.go +++ b/lib/go/thrift/zlib_transport.go @@ -23,7 +23,6 @@ import ( "compress/zlib" "context" "io" - "log" ) // TZlibTransportFactory is a factory for TZlibTransport instances @@ -67,7 +66,6 @@ func NewTZlibTransportFactoryWithFactory(level int, factory TTransportFactory) * func NewTZlibTransport(trans TTransport, level int) (*TZlibTransport, error) { w, err := zlib.NewWriterLevel(trans, level) if err != nil { - log.Println(err) return nil, err } From 9ea48f362a578ee8556fcf3ca84215cefbc1b99e Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 2 Nov 2019 12:20:29 +0100 Subject: [PATCH 408/756] Fix PHP style errors (by means of phpcbf) [ci skip] --- lib/php/test/Fixtures.php | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/php/test/Fixtures.php b/lib/php/test/Fixtures.php index 996f4af36cd..fd57d831c5e 100644 --- a/lib/php/test/Fixtures.php +++ b/lib/php/test/Fixtures.php @@ -66,32 +66,32 @@ public static function populateTestArgs() self::$testArgs['testStruct'] = new Xtruct( - array( + array( 'string_thing' => 'worked', 'byte_thing' => 0x01, 'i32_thing' => pow(2, 30), 'i64_thing' => self::$testArgs['testI64'] ) - ); + ); self::$testArgs['testNestNested'] = new Xtruct( - array( + array( 'string_thing' => 'worked', 'byte_thing' => 0x01, 'i32_thing' => pow(2, 30), 'i64_thing' => self::$testArgs['testI64'] ) - ); + ); self::$testArgs['testNest'] = new Xtruct2( - array( + array( 'byte_thing' => 0x01, 'struct_thing' => self::$testArgs['testNestNested'], 'i32_thing' => pow(2, 15) ) - ); + ); self::$testArgs['testMap'] = array( @@ -138,23 +138,23 @@ public static function populateTestArgs() $xtruct1 = new Xtruct( - array( + array( 'string_thing' => 'Goodbye4', 'byte_thing' => 4, 'i32_thing' => 4, 'i64_thing' => 4 ) - ); + ); $xtruct2 = new Xtruct( - array( + array( 'string_thing' => 'Hello2', 'byte_thing' => 2, 'i32_thing' => 2, 'i64_thing' => 2 ) - ); + ); $userMap = array( @@ -164,21 +164,21 @@ public static function populateTestArgs() $insanity2 = new Insanity( - array( + array( 'userMap' => $userMap, 'xtructs' => array($xtruct1, $xtruct2) ) - ); + ); $insanity3 = $insanity2; $insanity6 = new Insanity( - array( + array( 'userMap' => null, 'xtructs' => null ) - ); + ); self::$testArgs['testInsanityExpectedResult'] = array( From b1d4b3afcccb64a68b846a55c4f8bb1a11aa56cb Mon Sep 17 00:00:00 2001 From: David Furey Date: Fri, 1 Nov 2019 09:52:37 +0000 Subject: [PATCH 409/756] THRIFT-4989: Fix run time exception when using Swift TCompactProtocol Client: Swift Patch: David Furey This closes #1908 Sort TStruct members by key before generating class properties so that Swift Thrift lib can use delta encoding for CompactProtocol. --- compiler/cpp/src/thrift/generate/t_swift_generator.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/cpp/src/thrift/generate/t_swift_generator.cc b/compiler/cpp/src/thrift/generate/t_swift_generator.cc index eb746c10966..4a2f87d3bcb 100644 --- a/compiler/cpp/src/thrift/generate/t_swift_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_swift_generator.cc @@ -697,7 +697,9 @@ void t_swift_generator::generate_swift_struct(ostream& out, } block_open(out); - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + vector sorted = members; + sort(sorted.begin(), sorted.end(), [](t_field *a, t_field *b) { return (a->get_key() < b->get_key()); } ); + for (m_iter = sorted.begin(); m_iter != sorted.end(); ++m_iter) { out << endl; // TODO: Defaults From ec439548c531e5848a4e85684d666745d747926f Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 1 Nov 2019 19:19:44 +0100 Subject: [PATCH 410/756] THRIFT-4990 Switch to .NET core 3.0 Client: netstsd Patch: Jens Geyer This closes #1909 --- CHANGES.md | 8 ++++++++ build/docker/README.md | 2 +- build/docker/ubuntu-bionic/Dockerfile | 2 +- build/docker/ubuntu-disco/Dockerfile | 2 +- build/docker/ubuntu-xenial/Dockerfile | 2 +- configure.ac | 2 +- lib/netstd/README.md | 2 +- .../Thrift.IntegrationTests.csproj | 2 +- .../Thrift.PublicInterfaces.Compile.Tests.csproj | 2 +- lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj | 2 +- lib/netstd/Thrift/Thrift.csproj | 2 +- test/netstd/Client/Client.csproj | 2 +- test/netstd/Client/Program.cs | 14 +++++++------- test/netstd/README.md | 6 +++--- test/netstd/Server/Program.cs | 10 +++++----- test/netstd/Server/Server.csproj | 2 +- tutorial/netstd/Client/Client.csproj | 2 +- tutorial/netstd/Interfaces/Interfaces.csproj | 2 +- tutorial/netstd/README.md | 6 +++--- tutorial/netstd/Server/Program.cs | 4 ++-- tutorial/netstd/Server/Server.csproj | 2 +- 21 files changed, 43 insertions(+), 35 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 72c7eb8faa3..8fffab6b3f6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,13 @@ # Apache Thrift Changelog +## 0.14.0 + +### Breaking Changes + +- [THRIFT-4990](https://issues.apache.org/jira/browse/THRIFT-4990) - Upgrade to .NET Core 3.0 +- [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base + + ## 0.13.0 ### New Languages diff --git a/build/docker/README.md b/build/docker/README.md index 08c13725757..e33c4e0a4ad 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -177,7 +177,7 @@ Last updated: October 1, 2017 | d | 2.075.1 | 2.087.0 | | | dart | 2.0.0 | 2.4.0 | | | delphi | | | Not in CI | -| dotnet | 2.1.503 | 2.2.300 | | +| dotnet | 3.0 | 3.0 | | | erlang | 18.3 | 22.0 | | | go | 1.10.8 | 1.12.6 | | | haskell | 7.10.3 | 8.0.2 | | diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index 5f9833f12c2..d38901f3ff9 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -130,7 +130,7 @@ ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ - dotnet-sdk-2.2 + dotnet-sdk-3.0 RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ diff --git a/build/docker/ubuntu-disco/Dockerfile b/build/docker/ubuntu-disco/Dockerfile index b017c4e2164..b63fd58fe96 100644 --- a/build/docker/ubuntu-disco/Dockerfile +++ b/build/docker/ubuntu-disco/Dockerfile @@ -130,7 +130,7 @@ ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ - dotnet-sdk-2.2 + dotnet-sdk-3.0 RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index 8dc6497dce9..714a80dba46 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -127,7 +127,7 @@ ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ - dotnet-sdk-2.1 + dotnet-sdk-3.0 RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ diff --git a/configure.ac b/configure.ac index d5d7ecbc968..f11ab1352e6 100755 --- a/configure.ac +++ b/configure.ac @@ -505,7 +505,7 @@ AX_THRIFT_LIB(netstd, [.NET Core], yes) if test "$with_netstd" = "yes"; then AC_PATH_PROG([DOTNETCORE], [dotnet]) if [[ -x "$DOTNETCORE" ]] ; then - AX_PROG_DOTNETCORE_VERSION( [2.0.0], have_netstd="yes", have_netstd="no") + AX_PROG_DOTNETCORE_VERSION( [3.0.0], have_netstd="yes", have_netstd="no") fi fi AM_CONDITIONAL(WITH_DOTNET, [test "$have_netstd" = "yes"]) diff --git a/lib/netstd/README.md b/lib/netstd/README.md index 88ba73aebcd..74f5ed86d72 100644 --- a/lib/netstd/README.md +++ b/lib/netstd/README.md @@ -11,7 +11,7 @@ or - Build with scripts ## How to build on Unix/Linux -- Ensure you have .NET SDK >= 2.0 installed, or use the [Ubuntu docker image](../../build/docker/README.md) +- Ensure you have .NET Core SDK 3.0 installed, or use the [Ubuntu docker image](../../build/docker/README.md) - Follow common automake build practice: `./ bootstrap && ./ configure && make` ## Known issues diff --git a/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj b/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj index 381d8aa471a..c3cdc111319 100644 --- a/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj +++ b/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj @@ -19,7 +19,7 @@ --> - netcoreapp2.0 + netcoreapp3.0 Thrift.IntegrationTests Thrift.IntegrationTests Exe diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj index 58f61a2f16c..498191f60af 100644 --- a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj @@ -19,7 +19,7 @@ --> - netcoreapp2.0 + netcoreapp3.0 Thrift.PublicInterfaces.Compile.Tests Thrift.PublicInterfaces.Compile.Tests false diff --git a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj index 434424dbae0..b0601825c9f 100644 --- a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj +++ b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj @@ -18,7 +18,7 @@ under the License. --> - netcoreapp2.0 + netcoreapp3.0 diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj index 5d8a9c3c966..783b9e9d3aa 100644 --- a/lib/netstd/Thrift/Thrift.csproj +++ b/lib/netstd/Thrift/Thrift.csproj @@ -19,7 +19,7 @@ --> - netstandard2.0 + netstandard2.1 Thrift Thrift true diff --git a/test/netstd/Client/Client.csproj b/test/netstd/Client/Client.csproj index ed30c30dd27..c406f17c35d 100644 --- a/test/netstd/Client/Client.csproj +++ b/test/netstd/Client/Client.csproj @@ -19,7 +19,7 @@ --> - netcoreapp2.0 + netcoreapp3.0 Client Client Exe diff --git a/test/netstd/Client/Program.cs b/test/netstd/Client/Program.cs index 62933e62e6f..8dbff1a23c8 100644 --- a/test/netstd/Client/Program.cs +++ b/test/netstd/Client/Program.cs @@ -47,24 +47,24 @@ public static int Main(string[] args) switch(firstArg) { case "client": - return TestClient.Execute(subArgs); - case "performance": + Console.WriteLine("The 'client' argument is no longer required."); + PrintHelp(); + return -1; + case "--performance-test": return Tests.PerformanceTests.Execute(); case "--help": PrintHelp(); return 0; default: - Console.WriteLine("Invalid argument: {0}", firstArg); - PrintHelp(); - return -1; + return TestClient.Execute(subArgs); } } private static void PrintHelp() { Console.WriteLine("Usage:"); - Console.WriteLine(" Client client [options]"); - Console.WriteLine(" Client performance"); + Console.WriteLine(" Client [options]"); + Console.WriteLine(" Client --performance-test"); Console.WriteLine(" Client --help"); Console.WriteLine(""); diff --git a/test/netstd/README.md b/test/netstd/README.md index ed728d1bac4..8350728e57f 100644 --- a/test/netstd/README.md +++ b/test/netstd/README.md @@ -1,12 +1,12 @@ # Apache Thrift net-core-lib tests -Tests for Thrift client library ported to Microsoft .Net Core +Tests for Thrift client library ported to Microsoft .NET Core # Content - ThriftTest - tests for Thrift library # Reused components -- NET Core Standard 1.6 (SDK 2.0.0) +- NET Core SDK 3.0 # How to build on Windows - Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable @@ -15,6 +15,6 @@ or - Build with scripts # How to build on Unix -- Ensure you have .NET Core 2.0.0 SDK installed or use the Ubuntu Xenial docker image +- Ensure you have .NET Core 3.0 SDK installed or use the Ubuntu Xenial docker image - Follow common build practice for Thrift: bootstrap, configure, and make precross diff --git a/test/netstd/Server/Program.cs b/test/netstd/Server/Program.cs index 8bfa3714fd3..4525ab75cd8 100644 --- a/test/netstd/Server/Program.cs +++ b/test/netstd/Server/Program.cs @@ -47,21 +47,21 @@ public static int Main(string[] args) switch(firstArg) { case "server": - return TestServer.Execute(subArgs); + Console.WriteLine("The 'server' argument is no longer required."); + PrintHelp(); + return -1; case "--help": PrintHelp(); return 0; default: - Console.WriteLine("Invalid argument: {0}", firstArg); - PrintHelp(); - return -1; + return TestServer.Execute(subArgs); } } private static void PrintHelp() { Console.WriteLine("Usage:"); - Console.WriteLine(" Server server [options]'"); + Console.WriteLine(" Server [options]"); Console.WriteLine(" Server --help"); Console.WriteLine(""); diff --git a/test/netstd/Server/Server.csproj b/test/netstd/Server/Server.csproj index 44f46c90c04..4f2463ce665 100644 --- a/test/netstd/Server/Server.csproj +++ b/test/netstd/Server/Server.csproj @@ -19,7 +19,7 @@ --> - netcoreapp2.0 + netcoreapp3.0 Server Server Exe diff --git a/tutorial/netstd/Client/Client.csproj b/tutorial/netstd/Client/Client.csproj index a1470a9d374..2abf53cd8ed 100644 --- a/tutorial/netstd/Client/Client.csproj +++ b/tutorial/netstd/Client/Client.csproj @@ -19,7 +19,7 @@ --> - netcoreapp2.0 + netcoreapp3.0 Client Client Exe diff --git a/tutorial/netstd/Interfaces/Interfaces.csproj b/tutorial/netstd/Interfaces/Interfaces.csproj index 4ebeb4f4297..2d8a4408885 100644 --- a/tutorial/netstd/Interfaces/Interfaces.csproj +++ b/tutorial/netstd/Interfaces/Interfaces.csproj @@ -19,7 +19,7 @@ --> - netstandard2.0 + netstandard2.1 Interfaces Interfaces false diff --git a/tutorial/netstd/README.md b/tutorial/netstd/README.md index b1dea4ecbd5..11fd5411ad2 100644 --- a/tutorial/netstd/README.md +++ b/tutorial/netstd/README.md @@ -1,11 +1,11 @@ # Building of samples for different platforms # Reused components -- NET Core Standard 2.0 -- NET Core App 2.0 +- NET Core Standard 3.0 +- NET Core App 3.0 # How to build -- Download and install the latest .NET Core SDK for your platform https://www.microsoft.com/net/core#windowsvs2015 (archive for SDK 1.0.0-preview2-003121 located by: https://github.com/dotnet/core/blob/master/release-notes/download-archive.md) +- Download and install the latest .NET Core SDK for your platform https://dotnet.microsoft.com/download/dotnet-core - Ensure that you have thrift.exe which supports netstd lib and it added to PATH - Go to current folder - Run **build.sh** or **build.cmd** from the root of cloned repository diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs index 25e7daeedaa..e1dab01e032 100644 --- a/tutorial/netstd/Server/Program.cs +++ b/tutorial/netstd/Server/Program.cs @@ -346,7 +346,7 @@ public void Run(CancellationToken cancellationToken) public class Startup { - public Startup(IHostingEnvironment env) + public Startup(IWebHostEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) @@ -366,7 +366,7 @@ public void ConfigureServices(IServiceCollection services) } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory) { app.UseMiddleware(); } diff --git a/tutorial/netstd/Server/Server.csproj b/tutorial/netstd/Server/Server.csproj index fbc2c03706e..454f332d599 100644 --- a/tutorial/netstd/Server/Server.csproj +++ b/tutorial/netstd/Server/Server.csproj @@ -19,7 +19,7 @@ --> - netcoreapp2.0 + netcoreapp3.0 Server Server Exe From 43a93f1e6e7bc0d4247c8fe40c99cdcb8123b334 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 2 Nov 2019 23:21:14 +0100 Subject: [PATCH 411/756] fix typo in cmake Patch: Jens Geyer This closes #1910 --- lib/hs/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/hs/CMakeLists.txt b/lib/hs/CMakeLists.txt index 1a5b8fd32eb..c477c9b56ed 100644 --- a/lib/hs/CMakeLists.txt +++ b/lib/hs/CMakeLists.txt @@ -37,7 +37,7 @@ set(haskell_sources ) if(BUILD_TESTING) - list(APPEND haskell_soruces + list(APPEND haskell_sources test/Spec.hs test/BinarySpec.hs test/CompactSpec.hs From bc75467e4426c76d201c83621f08fa211660b6c3 Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Sat, 2 Nov 2019 21:13:34 -0700 Subject: [PATCH 412/756] Fix "thruth" typo Client: Go Patch: Kevin Wojniak This closes #1911 --- lib/go/thrift/http_client.go | 2 +- lib/go/thrift/iostream_transport.go | 2 +- lib/go/thrift/ssl_socket.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/go/thrift/http_client.go b/lib/go/thrift/http_client.go index 5c82bf53875..d093eebb6d8 100644 --- a/lib/go/thrift/http_client.go +++ b/lib/go/thrift/http_client.go @@ -218,7 +218,7 @@ func (p *THttpClient) RemainingBytes() (num_bytes uint64) { } const maxSize = ^uint64(0) - return maxSize // the thruth is, we just don't know unless framed is used + return maxSize // the truth is, we just don't know unless framed is used } // Deprecated: Use NewTHttpClientTransportFactory instead. diff --git a/lib/go/thrift/iostream_transport.go b/lib/go/thrift/iostream_transport.go index fea93bceffa..0b1775d06cb 100644 --- a/lib/go/thrift/iostream_transport.go +++ b/lib/go/thrift/iostream_transport.go @@ -210,5 +210,5 @@ func (p *StreamTransport) WriteString(s string) (n int, err error) { func (p *StreamTransport) RemainingBytes() (num_bytes uint64) { const maxSize = ^uint64(0) - return maxSize // the thruth is, we just don't know unless framed is used + return maxSize // the truth is, we just don't know unless framed is used } diff --git a/lib/go/thrift/ssl_socket.go b/lib/go/thrift/ssl_socket.go index ba63377263a..45bf38a289b 100644 --- a/lib/go/thrift/ssl_socket.go +++ b/lib/go/thrift/ssl_socket.go @@ -172,5 +172,5 @@ func (p *TSSLSocket) Interrupt() error { func (p *TSSLSocket) RemainingBytes() (num_bytes uint64) { const maxSize = ^uint64(0) - return maxSize // the thruth is, we just don't know unless framed is used + return maxSize // the truth is, we just don't know unless framed is used } From cf73b66cd83e2e883d00dff518d3c0250bb839cc Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Sat, 2 Nov 2019 22:01:56 -0700 Subject: [PATCH 413/756] Remove unused exception variable Client: Python Patch: Kevin Wojniak This closes #1912 Fixes MSVC warning seen in logs: > [00:11:03] src\ext/protocol.tcc(177): warning C4101: 'ex': unreferenced > local variable [C:\projects\build\MSVC2015\x86\lib\py\python_build.vcxproj] --- lib/py/src/ext/protocol.tcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/py/src/ext/protocol.tcc b/lib/py/src/ext/protocol.tcc index e15df7ea0fd..ede2bb46ae2 100644 --- a/lib/py/src/ext/protocol.tcc +++ b/lib/py/src/ext/protocol.tcc @@ -174,7 +174,7 @@ inline bool ProtocolBase::writeBuffer(char* data, size_t size) { if (output_->buf.capacity() < need) { try { output_->buf.reserve(need); - } catch (std::bad_alloc& ex) { + } catch (std::bad_alloc&) { PyErr_SetString(PyExc_MemoryError, "Failed to allocate write buffer"); return false; } From 1ce7317cae2c580ded065db6dad54647e96d3359 Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Sun, 3 Nov 2019 00:26:55 -0700 Subject: [PATCH 414/756] Replace unknown BUILD_THRIFT variable Patch: Kevin Wojniak This closes #1914 It should be BUILD_COMPILER. There are no other references to BUILD_THRIFT in the repo. --- build/cmake/DefineOptions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 778be8dffa2..6a69c6d09f3 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -151,7 +151,7 @@ message(STATUS "Build configuration summary") message(STATUS " Build compiler: ${BUILD_COMPILER}") message(STATUS " Build libraries: ${BUILD_LIBRARIES}") message(STATUS " Build tests: ${BUILD_TESTING}") -MESSAGE_DEP(HAVE_COMPILER "Disabled because BUILD_THRIFT=OFF and no valid THRIFT_COMPILER is given") +MESSAGE_DEP(HAVE_COMPILER "Disabled because BUILD_COMPILER=OFF and no valid THRIFT_COMPILER is given") message(STATUS " Build type: ${CMAKE_BUILD_TYPE}") message(STATUS) message(STATUS "Language libraries:") From 3adb44aa26023e4016ba844ab4bda32525d5c4fb Mon Sep 17 00:00:00 2001 From: xiongjieqing Date: Thu, 26 Sep 2019 18:27:25 +0800 Subject: [PATCH 415/756] thrift lua TcompactProtocol bug fix --- lib/lua/TCompactProtocol.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lua/TCompactProtocol.lua b/lib/lua/TCompactProtocol.lua index 877595a5d61..7b75967a925 100644 --- a/lib/lua/TCompactProtocol.lua +++ b/lib/lua/TCompactProtocol.lua @@ -124,8 +124,8 @@ function TCompactProtocol:writeStructBegin(name) end function TCompactProtocol:writeStructEnd() - self.lastFieldIndex = self.lastFieldIndex - 1 self.lastFieldId = self.lastField[self.lastFieldIndex] + self.lastFieldIndex = self.lastFieldIndex - 1 end function TCompactProtocol:writeFieldBegin(name, ttype, id) From c5fadee94a88e4f5c8d8323305513fdb7ef552d9 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 3 Nov 2019 19:07:04 +0100 Subject: [PATCH 416/756] Revert "thrift lua TcompactProtocol bug fix" This reverts commit 3adb44aa26023e4016ba844ab4bda32525d5c4fb. --- lib/lua/TCompactProtocol.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lua/TCompactProtocol.lua b/lib/lua/TCompactProtocol.lua index 7b75967a925..877595a5d61 100644 --- a/lib/lua/TCompactProtocol.lua +++ b/lib/lua/TCompactProtocol.lua @@ -124,8 +124,8 @@ function TCompactProtocol:writeStructBegin(name) end function TCompactProtocol:writeStructEnd() - self.lastFieldId = self.lastField[self.lastFieldIndex] self.lastFieldIndex = self.lastFieldIndex - 1 + self.lastFieldId = self.lastField[self.lastFieldIndex] end function TCompactProtocol:writeFieldBegin(name, ttype, id) From a5b2bf5b0bc82545b26b7a42bbf7b5dc9ef51b33 Mon Sep 17 00:00:00 2001 From: xiongjieqing Date: Thu, 26 Sep 2019 18:27:25 +0800 Subject: [PATCH 417/756] THRIFT-4992 thrift lua TcompactProtocol bug fix #1881 Client: Lua Patch: xiongjieqing --- lib/lua/TCompactProtocol.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lua/TCompactProtocol.lua b/lib/lua/TCompactProtocol.lua index 877595a5d61..7b75967a925 100644 --- a/lib/lua/TCompactProtocol.lua +++ b/lib/lua/TCompactProtocol.lua @@ -124,8 +124,8 @@ function TCompactProtocol:writeStructBegin(name) end function TCompactProtocol:writeStructEnd() - self.lastFieldIndex = self.lastFieldIndex - 1 self.lastFieldId = self.lastField[self.lastFieldIndex] + self.lastFieldIndex = self.lastFieldIndex - 1 end function TCompactProtocol:writeFieldBegin(name, ttype, id) From 24045b7211318b7b62dce83a7f0e962e20292f1b Mon Sep 17 00:00:00 2001 From: Qinghui Xu Date: Mon, 4 Nov 2019 10:21:47 +0100 Subject: [PATCH 418/756] Fix indentation Use white space for indentation instead of tabulation. --- lib/java/src/org/apache/thrift/server/TThreadPoolServer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java index e1b6e768b76..e2f31d550a0 100644 --- a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java +++ b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java @@ -171,7 +171,7 @@ public void serve() { } execute(); - if (!waitForShutdown()) { + if (!waitForShutdown()) { LOGGER.error("Shutdown is not done after " + stopTimeoutVal + stopTimeoutUnit); } From f7b219791653d206a03d236e2bd69e79c4d4a392 Mon Sep 17 00:00:00 2001 From: Eugen Kandakov Date: Mon, 4 Nov 2019 13:15:35 +0100 Subject: [PATCH 419/756] THRIFT-4994 changed this to self in forEach callback Client: nodejs Patch: Eugen Kandakov This closes #1918 --- lib/nodejs/lib/thrift/ws_transport.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/nodejs/lib/thrift/ws_transport.js b/lib/nodejs/lib/thrift/ws_transport.js index 3513b84be8d..4cf62b9f9bf 100644 --- a/lib/nodejs/lib/thrift/ws_transport.js +++ b/lib/nodejs/lib/thrift/ws_transport.js @@ -83,8 +83,8 @@ TWebSocketTransport.prototype.__onOpen = function() { //If the user made calls before the connection was fully //open, send them now this.send_pending.forEach(function(elem) { - this.socket.send(elem.buf); - this.callbacks.push((function() { + self.socket.send(elem.buf); + self.callbacks.push((function() { var clientCallback = elem.cb; return function(msg) { self.setRecvBuffer(msg); From 508d9951d5fd8a539788caff6d38f08db564d50b Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Sun, 3 Nov 2019 20:27:53 +0100 Subject: [PATCH 420/756] THRIFT-4959 Pin Chocolately Haskell packages Client: Haskell Patch: Kevin Wojniak This closes #1915 pin cabal, pin Chocolately Haskell package --- build/appveyor/MSVC-appveyor-install.bat | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/appveyor/MSVC-appveyor-install.bat b/build/appveyor/MSVC-appveyor-install.bat index bc4655a762f..09b7cc49445 100644 --- a/build/appveyor/MSVC-appveyor-install.bat +++ b/build/appveyor/MSVC-appveyor-install.bat @@ -56,7 +56,8 @@ pip.exe ^ tornado ^ twisted || EXIT /B -cinst -y ghc || EXIT /B +cinst -y cabal --version 2.4.1.0 || EXIT /B +cinst -y ghc --version 8.6.5 || EXIT /B :: Adobe Flex SDK 4.6 for ActionScript MKDIR "C:\Adobe\Flex\SDK\4.6" || EXIT /B From 4653009035db96228e33e8965e432752b41c8ed1 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Tue, 5 Nov 2019 13:31:13 -0800 Subject: [PATCH 421/756] THRIFT-4984: Ignore EOF errors in TSimpleServer, take 2 This is a different approach to take THRIFT-4984: Instead of checking EOF errors in place, handle them in a consolidated, deferred function. Also improve test error messages. Client: go This closes #1907. --- lib/go/test/tests/thrifttest_driver.go | 17 ++++++++-------- lib/go/thrift/simple_server.go | 27 +++++++++++++++++++------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/lib/go/test/tests/thrifttest_driver.go b/lib/go/test/tests/thrifttest_driver.go index de54cbcaa93..4fc5baab451 100644 --- a/lib/go/test/tests/thrifttest_driver.go +++ b/lib/go/test/tests/thrifttest_driver.go @@ -213,24 +213,25 @@ func (p *ThriftTestDriver) Start() { 2: {thrifttest.Numberz_SIX: crazyEmpty}, } if r, err := client.TestInsanity(defaultCtx, crazy); !reflect.DeepEqual(r, insanity) || err != nil { - t.Fatal("TestInsanity failed") + t.Fatal("TestInsanity failed:", err) } if err := client.TestException(defaultCtx, "TException"); err == nil { - t.Fatal("TestException TException failed") + t.Fatal("TestException TException failed:", err) } - if err, ok := client.TestException(defaultCtx, "Xception").(*thrifttest.Xception); ok == false || err == nil { - t.Fatal("TestException Xception failed") - } else if err.ErrorCode != 1001 || err.Message != "Xception" { - t.Fatal("TestException Xception failed") + err := client.TestException(defaultCtx, "Xception") + if e, ok := err.(*thrifttest.Xception); ok == false || e == nil { + t.Fatal("TestException Xception failed:", err) + } else if e.ErrorCode != 1001 || e.Message != "Xception" { + t.Fatal("TestException Xception failed:", e) } if err := client.TestException(defaultCtx, "no Exception"); err != nil { - t.Fatal("TestException no Exception failed") + t.Fatal("TestException no Exception failed:", err) } if err := client.TestOneway(defaultCtx, 0); err != nil { - t.Fatal("TestOneway failed") + t.Fatal("TestOneway failed:", err) } } diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go index 51e3509c180..aa5a6a6851a 100644 --- a/lib/go/thrift/simple_server.go +++ b/lib/go/thrift/simple_server.go @@ -216,7 +216,25 @@ func (p *TSimpleServer) Stop() error { return nil } -func (p *TSimpleServer) processRequests(client TTransport) error { +// If err is actually EOF, return nil, otherwise return err as-is. +func treatEOFErrorsAsNil(err error) error { + if err == nil { + return nil + } + if err == io.EOF { + return nil + } + if err, ok := err.(TTransportException); ok && err.TypeId() == END_OF_FILE { + return nil + } + return err +} + +func (p *TSimpleServer) processRequests(client TTransport) (err error) { + defer func() { + err = treatEOFErrorsAsNil(err) + }() + processor := p.processorFactory.GetProcessor(client) inputTransport, err := p.inputTransportFactory.GetTransport(client) if err != nil { @@ -261,9 +279,6 @@ func (p *TSimpleServer) processRequests(client TTransport) error { // won't break when it's called again later when we // actually start to read the message. if err := headerProtocol.ReadFrame(); err != nil { - if err == io.EOF { - return nil - } return err } ctx = AddReadTHeaderToContext(ctx, headerProtocol.GetReadHeaders()) @@ -271,9 +286,7 @@ func (p *TSimpleServer) processRequests(client TTransport) error { } ok, err := processor.Process(ctx, inputProtocol, outputProtocol) - if err, ok := err.(TTransportException); ok && err.TypeId() == END_OF_FILE { - return nil - } else if err != nil { + if _, ok := err.(TTransportException); ok && err != nil { return err } if err, ok := err.(TApplicationException); ok && err.TypeId() == UNKNOWN_METHOD { From 596e25f9b07f4eb626e8644b6cc18b93c417b4e5 Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Sun, 3 Nov 2019 15:09:51 -0800 Subject: [PATCH 422/756] Fix unknown pragma warnings on mingw Client: cpp Patch: Kevin Wojniak This closes #1917 These pragmas are only valid for MSVC. Fixes warnings found in the logs: > In file included from C:\projects\thrift\lib\cpp\test\processor\ProcessorTest.cpp:40: 731C:\projects\thrift\lib\cpp\test\processor\Handlers.h:143: warning: ignoring #pragma warning [-Wunknown-pragmas] 732 143 | #pragma warning( push ) 733 | 734C:\projects\thrift\lib\cpp\test\processor\Handlers.h:144: warning: ignoring #pragma warning [-Wunknown-pragmas] 735 144 | #pragma warning (disable : 4250 ) //inheriting methods via dominance 736 | 737C:\projects\thrift\lib\cpp\test\processor\Handlers.h:172: warning: ignoring #pragma warning [-Wunknown-pragmas] 738 172 | #pragma warning( pop ) 739 | --- lib/cpp/test/processor/Handlers.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cpp/test/processor/Handlers.h b/lib/cpp/test/processor/Handlers.h index 05d19edd967..d72a23c9072 100644 --- a/lib/cpp/test/processor/Handlers.h +++ b/lib/cpp/test/processor/Handlers.h @@ -139,7 +139,7 @@ class ParentHandler : virtual public ParentServiceIf { std::shared_ptr log_; }; -#ifdef _WIN32 +#ifdef _MSC_VER #pragma warning( push ) #pragma warning (disable : 4250 ) //inheriting methods via dominance #endif @@ -168,7 +168,7 @@ class ChildHandler : public ParentHandler, virtual public ChildServiceIf { int32_t value_; }; -#ifdef _WIN32 +#ifdef _MSC_VER #pragma warning( pop ) #endif From 963812ae62579f6040b805218d9e798e1e66b324 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Fri, 8 Nov 2019 01:02:00 -0800 Subject: [PATCH 423/756] THRIFT-4984: Handle wrapped io.EOF errors TCompactProtocol (which is used by THeaderTransport to read headers) could wrap the underlying error with TProtocolException, which breaks err == io.EOF test in some cases. Client: go This closes #1922. --- lib/go/thrift/simple_server.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go index aa5a6a6851a..756d4cf3b15 100644 --- a/lib/go/thrift/simple_server.go +++ b/lib/go/thrift/simple_server.go @@ -221,7 +221,9 @@ func treatEOFErrorsAsNil(err error) error { if err == nil { return nil } - if err == io.EOF { + // err could be io.EOF wrapped with TProtocolException, + // so that err == io.EOF doesn't necessarily work in some cases. + if err.Error() == io.EOF.Error() { return nil } if err, ok := err.(TTransportException); ok && err.TypeId() == END_OF_FILE { From 50caa4de84210d792632c61941c3bb4180f0c665 Mon Sep 17 00:00:00 2001 From: zembord Date: Wed, 6 Nov 2019 14:29:41 +0300 Subject: [PATCH 424/756] THRIFT-4990: Upgrade to .NET Core 3.0 Client: netstsd Patch: Edward Zhuravlov This closes #1921 --- lib/netstd/Thrift/Thrift.csproj | 2 +- tutorial/netstd/Interfaces/Interfaces.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj index 783b9e9d3aa..5d8a9c3c966 100644 --- a/lib/netstd/Thrift/Thrift.csproj +++ b/lib/netstd/Thrift/Thrift.csproj @@ -19,7 +19,7 @@ --> - netstandard2.1 + netstandard2.0 Thrift Thrift true diff --git a/tutorial/netstd/Interfaces/Interfaces.csproj b/tutorial/netstd/Interfaces/Interfaces.csproj index 2d8a4408885..4ebeb4f4297 100644 --- a/tutorial/netstd/Interfaces/Interfaces.csproj +++ b/tutorial/netstd/Interfaces/Interfaces.csproj @@ -19,7 +19,7 @@ --> - netstandard2.1 + netstandard2.0 Interfaces Interfaces false From 4c27181a06cf18154e9e1e8abeb711a75b5cf435 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Sat, 9 Nov 2019 11:20:09 -0800 Subject: [PATCH 425/756] THRIFT-4914: Add TResponseHelper This is the third part of THRIFT-4914, which handles the server writing part in the response (server -> client direction). Define a new type, TResponseHelper, which only contains THeader related functions for now, but can be extended for other functions in the future. In TSimpleServer, inject a TResponseHelper into the context object passed into the handler functions. Handler function code could retrieve the injected TResponseHelper to set headers to be written to the client. Client: go This closes #1923. --- lib/go/thrift/response_helper.go | 94 ++++++++++++++++++ lib/go/thrift/response_helper_test.go | 137 ++++++++++++++++++++++++++ lib/go/thrift/simple_server.go | 7 +- 3 files changed, 237 insertions(+), 1 deletion(-) create mode 100644 lib/go/thrift/response_helper.go create mode 100644 lib/go/thrift/response_helper_test.go diff --git a/lib/go/thrift/response_helper.go b/lib/go/thrift/response_helper.go new file mode 100644 index 00000000000..d884c6ac6c4 --- /dev/null +++ b/lib/go/thrift/response_helper.go @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "context" +) + +// See https://godoc.org/context#WithValue on why do we need the unexported typedefs. +type responseHelperKey struct{} + +// TResponseHelper defines a object with a set of helper functions that can be +// retrieved from the context object passed into server handler functions. +// +// Use GetResponseHelper to retrieve the injected TResponseHelper implementation +// from the context object. +// +// The zero value of TResponseHelper is valid with all helper functions being +// no-op. +type TResponseHelper struct { + // THeader related functions + *THeaderResponseHelper +} + +// THeaderResponseHelper defines THeader related TResponseHelper functions. +// +// The zero value of *THeaderResponseHelper is valid with all helper functions +// being no-op. +type THeaderResponseHelper struct { + proto *THeaderProtocol +} + +// NewTHeaderResponseHelper creates a new THeaderResponseHelper from the +// underlying TProtocol. +func NewTHeaderResponseHelper(proto TProtocol) *THeaderResponseHelper { + if hp, ok := proto.(*THeaderProtocol); ok { + return &THeaderResponseHelper{ + proto: hp, + } + } + return nil +} + +// SetHeader sets a response header. +// +// It's no-op if the underlying protocol/transport does not support THeader. +func (h *THeaderResponseHelper) SetHeader(key, value string) { + if h != nil && h.proto != nil { + h.proto.SetWriteHeader(key, value) + } +} + +// ClearHeaders clears all the response headers previously set. +// +// It's no-op if the underlying protocol/transport does not support THeader. +func (h *THeaderResponseHelper) ClearHeaders() { + if h != nil && h.proto != nil { + h.proto.ClearWriteHeaders() + } +} + +// GetResponseHelper retrieves the TResponseHelper implementation injected into +// the context object. +// +// If no helper was found in the context object, a nop helper with ok == false +// will be returned. +func GetResponseHelper(ctx context.Context) (helper TResponseHelper, ok bool) { + if v := ctx.Value(responseHelperKey{}); v != nil { + helper, ok = v.(TResponseHelper) + } + return +} + +// SetResponseHelper injects TResponseHelper into the context object. +func SetResponseHelper(ctx context.Context, helper TResponseHelper) context.Context { + return context.WithValue(ctx, responseHelperKey{}, helper) +} diff --git a/lib/go/thrift/response_helper_test.go b/lib/go/thrift/response_helper_test.go new file mode 100644 index 00000000000..69f76d36515 --- /dev/null +++ b/lib/go/thrift/response_helper_test.go @@ -0,0 +1,137 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "context" + "testing" +) + +func TestResponseHelperContext(t *testing.T) { + ctx := context.Background() + + t.Run( + "empty-noop", + func(t *testing.T) { + helper, ok := GetResponseHelper(ctx) + if ok { + t.Error("GetResponseHelper expected ok == false") + } + // Just make sure those function calls does not panic + helper.SetHeader("foo", "bar") + helper.ClearHeaders() + }, + ) + + t.Run( + "set-get", + func(t *testing.T) { + trans := NewTHeaderTransport(NewTMemoryBuffer()) + proto := NewTHeaderProtocol(trans) + ctx = SetResponseHelper( + ctx, + TResponseHelper{ + THeaderResponseHelper: NewTHeaderResponseHelper(proto), + }, + ) + helper, ok := GetResponseHelper(ctx) + if !ok { + t.Error("GetResponseHelper expected ok == true") + } + if helper.THeaderResponseHelper == nil { + t.Error("GetResponseHelper expected THeaderResponseHelper to be non-nil") + } + }, + ) +} + +func TestHeaderHelper(t *testing.T) { + t.Run( + "THeaderProtocol", + func(t *testing.T) { + trans := NewTHeaderTransport(NewTMemoryBuffer()) + proto := NewTHeaderProtocol(trans) + helper := NewTHeaderResponseHelper(proto) + + const ( + key = "key" + value = "value" + ) + helper.SetHeader(key, value) + if len(trans.writeHeaders) != 1 { + t.Errorf( + "Expected THeaderTransport.writeHeaders to be with size of 1, got %+v", + trans.writeHeaders, + ) + } + actual := trans.writeHeaders[key] + if actual != value { + t.Errorf( + "Expected THeaderTransport.writeHeaders to have %q:%q, got %+v", + key, + value, + trans.writeHeaders, + ) + } + helper.ClearHeaders() + if len(trans.writeHeaders) != 0 { + t.Errorf( + "Expected THeaderTransport.writeHeaders to be empty after ClearHeaders call, got %+v", + trans.writeHeaders, + ) + } + }, + ) + + t.Run( + "other-protocol", + func(t *testing.T) { + trans := NewTMemoryBuffer() + proto := NewTCompactProtocol(trans) + helper := NewTHeaderResponseHelper(proto) + + // We only need to make sure that functions in helper + // don't panic here. + helper.SetHeader("foo", "bar") + helper.ClearHeaders() + }, + ) + + t.Run( + "zero-value", + func(t *testing.T) { + var helper *THeaderResponseHelper + + // We only need to make sure that functions in helper + // don't panic here. + helper.SetHeader("foo", "bar") + helper.ClearHeaders() + }, + ) +} + +func TestTResponseHelperZeroValue(t *testing.T) { + var helper THeaderResponseHelper + + // We only need to make sure that functions in helper + // don't panic here. + helper.SetHeader("foo", "bar") + helper.ClearHeaders() +} diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go index 756d4cf3b15..5a9c9c9e127 100644 --- a/lib/go/thrift/simple_server.go +++ b/lib/go/thrift/simple_server.go @@ -272,7 +272,12 @@ func (p *TSimpleServer) processRequests(client TTransport) (err error) { return nil } - ctx := defaultCtx + ctx := SetResponseHelper( + defaultCtx, + TResponseHelper{ + THeaderResponseHelper: NewTHeaderResponseHelper(outputProtocol), + }, + ) if headerProtocol != nil { // We need to call ReadFrame here, otherwise we won't // get any headers on the AddReadTHeaderToContext call. From 59694a796f824ffcde745065efa36b8d0ddf8275 Mon Sep 17 00:00:00 2001 From: John Boiles Date: Sat, 9 Nov 2019 11:22:26 -0800 Subject: [PATCH 426/756] THRIFT-5002: Fix argument containers for inherited functions Fix a bug where remote.go client fails to compile when services extend other services and the parent service has a function that needs a container for its arguments. Client:go This closes #1925. --- .../cpp/src/thrift/generate/t_go_generator.cc | 30 +++++++++++++++---- lib/go/test/Makefile.am | 5 ++-- lib/go/test/ServicesTest.thrift | 7 +++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index 33b7547b4c5..e153a7851a3 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -311,6 +311,7 @@ class t_go_generator : public t_generator { std::string camelcase(const std::string& value) const; void fix_common_initialism(std::string& value, int i) const; std::string publicize(const std::string& value, bool is_args_or_result = false) const; + std::string publicize(const std::string& value, bool is_args_or_result, const std::string& service_name) const; std::string privatize(const std::string& value) const; std::string new_prefix(const std::string& value) const; static std::string variable_name_to_go_name(const std::string& value); @@ -464,7 +465,7 @@ void t_go_generator::fix_common_initialism(std::string& value, int i) const { } } -std::string t_go_generator::publicize(const std::string& value, bool is_args_or_result) const { +std::string t_go_generator::publicize(const std::string& value, bool is_args_or_result, const std::string& service_name) const { if (value.size() <= 0) { return value; } @@ -506,12 +507,16 @@ std::string t_go_generator::publicize(const std::string& value, bool is_args_or_ // Avoid naming collisions with other services if (is_args_or_result) { - prefix += publicize(service_name_); + prefix += publicize(service_name); } return prefix + value2; } +std::string t_go_generator::publicize(const std::string& value, bool is_args_or_result) const { + return publicize(value, is_args_or_result, service_name_); +} + std::string t_go_generator::new_prefix(const std::string& value) const { if (value.size() <= 0) { return value; @@ -2121,13 +2126,26 @@ void t_go_generator::generate_service_client(t_service* tservice) { * @param tservice The service to generate a remote for. */ void t_go_generator::generate_service_remote(t_service* tservice) { - vector functions = tservice->get_functions(); - t_service* parent = tservice->get_extends(); + vector functions; + std::unordered_map func_to_service; - // collect inherited functions + // collect all functions including inherited functions + t_service* parent = tservice; while (parent != NULL) { vector p_functions = parent->get_functions(); functions.insert(functions.end(), p_functions.begin(), p_functions.end()); + + // We need to maintain a map of functions names to the name of their parent. + // This is because functions may come from a parent service, and if we need + // to create the arguments struct (e.g. `NewParentServiceNameFuncNameArgs()`) + // we need to make sure to specify the correct service name. + for (vector::iterator f_iter = p_functions.begin(); f_iter != p_functions.end(); ++f_iter) { + auto it = func_to_service.find((*f_iter)->get_name()); + if (it == func_to_service.end()) { + func_to_service.emplace((*f_iter)->get_name(), parent->get_name()); + } + } + parent = parent->get_extends(); } @@ -2340,7 +2358,7 @@ void t_go_generator::generate_service_remote(t_service* tservice) { std::vector::size_type num_args = args.size(); string funcName((*f_iter)->get_name()); string pubName(publicize(funcName)); - string argumentsName(publicize(funcName + "_args", true)); + string argumentsName(publicize(funcName + "_args", true, func_to_service[funcName])); f_remote << indent() << "case \"" << escape_string(funcName) << "\":" << endl; indent_up(); f_remote << indent() << "if flag.NArg() - 1 != " << num_args << " {" << endl; diff --git a/lib/go/test/Makefile.am b/lib/go/test/Makefile.am index 244ddff1fd6..2a9d3f5732b 100644 --- a/lib/go/test/Makefile.am +++ b/lib/go/test/Makefile.am @@ -93,7 +93,8 @@ check: gopath ignoreinitialismstest \ unionbinarytest \ conflictnamespacetestsuperthing \ - conflict/context/conflict_service-remote + conflict/context/conflict_service-remote \ + servicestest/container_test-remote GOPATH=`pwd`/gopath $(GO) test thrift tests dontexportrwtest clean-local: @@ -127,5 +128,5 @@ EXTRA_DIST = \ ConflictNamespaceTestB.thrift \ ConflictNamespaceTestC.thrift \ ConflictNamespaceTestD.thrift \ - ConflictNamespaceTestSuperThing.thrift + ConflictNamespaceTestSuperThing.thrift \ ConflictNamespaceServiceTest.thrift diff --git a/lib/go/test/ServicesTest.thrift b/lib/go/test/ServicesTest.thrift index 882b03acbcb..666197f15b7 100644 --- a/lib/go/test/ServicesTest.thrift +++ b/lib/go/test/ServicesTest.thrift @@ -107,5 +107,12 @@ service a_serv { struct_a struct_a_func_2ex_1int_1s(1: i64 i, 2: string s) throws(1: moderate_disaster err1, 2:total_disaster err2) struct_a struct_a_func_1struct_a(1: struct_a st) +} + +service container_test_parent { + void parent_only_func(1: set s) +} +service container_test extends container_test_parent { + void child_only_func(1: set s) } From 24fa9d0728c5893b11901f6ffb25a9e74a4647c8 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Sat, 9 Nov 2019 14:21:10 -0800 Subject: [PATCH 427/756] THRIFT-4914: Add GetResponseHeadersFromClient helper function This is the fourth and final part of THRIFT-4914, which handles the client reading part in the response (server -> client direction). Client: go This closes #1926. --- lib/go/thrift/header_protocol.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/go/thrift/header_protocol.go b/lib/go/thrift/header_protocol.go index 46205b28ba6..99deaf7dcff 100644 --- a/lib/go/thrift/header_protocol.go +++ b/lib/go/thrift/header_protocol.go @@ -303,3 +303,17 @@ func (p *THeaderProtocol) ReadBinary() (value []byte, err error) { func (p *THeaderProtocol) Skip(fieldType TType) error { return p.protocol.Skip(fieldType) } + +// GetResponseHeadersFromClient is a helper function to get the read THeaderMap +// from the last response received from the given client. +// +// If the last response was not sent over THeader protocol, +// a nil map will be returned. +func GetResponseHeadersFromClient(c TClient) THeaderMap { + if sc, ok := c.(*TStandardClient); ok { + if hp, ok := sc.iprot.(*THeaderProtocol); ok { + return hp.transport.readHeaders + } + } + return nil +} From 9f11c1e545a9aa0db076e9b5be9b7e397e594f4a Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 9 Nov 2019 19:39:20 +0100 Subject: [PATCH 428/756] THRIFT-5004 Make exception implementations more consistent [ci skip] Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.Protocol.pas | 125 +++++++++++++++++------ lib/delphi/src/Thrift.Transport.pas | 98 +++++++++++++----- lib/delphi/src/Thrift.pas | 149 ++++++++++++++++++++++------ 3 files changed, 291 insertions(+), 81 deletions(-) diff --git a/lib/delphi/src/Thrift.Protocol.pas b/lib/delphi/src/Thrift.Protocol.pas index 609dfc60504..47e88fe67b0 100644 --- a/lib/delphi/src/Thrift.Protocol.pas +++ b/lib/delphi/src/Thrift.Protocol.pas @@ -112,24 +112,27 @@ TThriftSet = record function GetProtocol( const trans: ITransport): IProtocol; end; - TProtocolException = class( TException) + TProtocolException = class abstract( TException) public - const // TODO(jensg): change into enum - UNKNOWN = 0; - INVALID_DATA = 1; - NEGATIVE_SIZE = 2; - SIZE_LIMIT = 3; - BAD_VERSION = 4; - NOT_IMPLEMENTED = 5; - DEPTH_LIMIT = 6; + type TExceptionType = ( + UNKNOWN = 0, + INVALID_DATA = 1, + NEGATIVE_SIZE = 2, + SIZE_LIMIT = 3, + BAD_VERSION = 4, + NOT_IMPLEMENTED = 5, + DEPTH_LIMIT = 6 + ); protected constructor HiddenCreate(const Msg: string); + class function GetType: TExceptionType; virtual; abstract; public // purposefully hide inherited constructor class function Create(const Msg: string): TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)'; class function Create: TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)'; - class function Create( type_: Integer): TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)'; - class function Create( type_: Integer; const msg: string): TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)'; + class function Create( aType: TExceptionType): TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)'; + class function Create( aType: TExceptionType; const msg: string): TProtocolException; overload; deprecated 'Use specialized TProtocolException types (or regenerate from IDL)'; + property Type_: TExceptionType read GetType; end; // Needed to remove deprecation warning @@ -138,13 +141,41 @@ TProtocolExceptionSpecialized = class abstract (TProtocolException) constructor Create(const Msg: string); end; - TProtocolExceptionUnknown = class (TProtocolExceptionSpecialized); - TProtocolExceptionInvalidData = class (TProtocolExceptionSpecialized); - TProtocolExceptionNegativeSize = class (TProtocolExceptionSpecialized); - TProtocolExceptionSizeLimit = class (TProtocolExceptionSpecialized); - TProtocolExceptionBadVersion = class (TProtocolExceptionSpecialized); - TProtocolExceptionNotImplemented = class (TProtocolExceptionSpecialized); - TProtocolExceptionDepthLimit = class (TProtocolExceptionSpecialized); + TProtocolExceptionUnknown = class (TProtocolExceptionSpecialized) + protected + class function GetType: TProtocolException.TExceptionType; override; + end; + + TProtocolExceptionInvalidData = class (TProtocolExceptionSpecialized) + protected + class function GetType: TProtocolException.TExceptionType; override; + end; + + TProtocolExceptionNegativeSize = class (TProtocolExceptionSpecialized) + protected + class function GetType: TProtocolException.TExceptionType; override; + end; + + TProtocolExceptionSizeLimit = class (TProtocolExceptionSpecialized) + protected + class function GetType: TProtocolException.TExceptionType; override; + end; + + TProtocolExceptionBadVersion = class (TProtocolExceptionSpecialized) + protected + class function GetType: TProtocolException.TExceptionType; override; + end; + + TProtocolExceptionNotImplemented = class (TProtocolExceptionSpecialized) + protected + class function GetType: TProtocolException.TExceptionType; override; + end; + + TProtocolExceptionDepthLimit = class (TProtocolExceptionSpecialized) + protected + class function GetType: TProtocolException.TExceptionType; override; + end; + TProtocolUtil = class @@ -1000,23 +1031,24 @@ class function TProtocolException.Create: TProtocolException; Result := TProtocolExceptionUnknown.Create(''); end; -class function TProtocolException.Create(type_: Integer): TProtocolException; +class function TProtocolException.Create(aType: TExceptionType): TProtocolException; begin {$WARN SYMBOL_DEPRECATED OFF} - Result := Create(type_, ''); + Result := Create(aType, ''); {$WARN SYMBOL_DEPRECATED DEFAULT} end; -class function TProtocolException.Create(type_: Integer; const msg: string): TProtocolException; +class function TProtocolException.Create(aType: TExceptionType; const msg: string): TProtocolException; begin - case type_ of - INVALID_DATA: Result := TProtocolExceptionInvalidData.Create(msg); - NEGATIVE_SIZE: Result := TProtocolExceptionNegativeSize.Create(msg); - SIZE_LIMIT: Result := TProtocolExceptionSizeLimit.Create(msg); - BAD_VERSION: Result := TProtocolExceptionBadVersion.Create(msg); - NOT_IMPLEMENTED: Result := TProtocolExceptionNotImplemented.Create(msg); - DEPTH_LIMIT: Result := TProtocolExceptionDepthLimit.Create(msg); + case aType of + TExceptionType.INVALID_DATA: Result := TProtocolExceptionInvalidData.Create(msg); + TExceptionType.NEGATIVE_SIZE: Result := TProtocolExceptionNegativeSize.Create(msg); + TExceptionType.SIZE_LIMIT: Result := TProtocolExceptionSizeLimit.Create(msg); + TExceptionType.BAD_VERSION: Result := TProtocolExceptionBadVersion.Create(msg); + TExceptionType.NOT_IMPLEMENTED: Result := TProtocolExceptionNotImplemented.Create(msg); + TExceptionType.DEPTH_LIMIT: Result := TProtocolExceptionDepthLimit.Create(msg); else + ASSERT( TExceptionType.UNKNOWN = aType); Result := TProtocolExceptionUnknown.Create(msg); end; end; @@ -1028,6 +1060,43 @@ constructor TProtocolExceptionSpecialized.Create(const Msg: string); inherited HiddenCreate(Msg); end; +{ specialized TProtocolExceptions } + +class function TProtocolExceptionUnknown.GetType: TProtocolException.TExceptionType; +begin + result := TExceptionType.UNKNOWN; +end; + +class function TProtocolExceptionInvalidData.GetType: TProtocolException.TExceptionType; +begin + result := TExceptionType.INVALID_DATA; +end; + +class function TProtocolExceptionNegativeSize.GetType: TProtocolException.TExceptionType; +begin + result := TExceptionType.NEGATIVE_SIZE; +end; + +class function TProtocolExceptionSizeLimit.GetType: TProtocolException.TExceptionType; +begin + result := TExceptionType.SIZE_LIMIT; +end; + +class function TProtocolExceptionBadVersion.GetType: TProtocolException.TExceptionType; +begin + result := TExceptionType.BAD_VERSION; +end; + +class function TProtocolExceptionNotImplemented.GetType: TProtocolException.TExceptionType; +begin + result := TExceptionType.NOT_IMPLEMENTED; +end; + +class function TProtocolExceptionDepthLimit.GetType: TProtocolException.TExceptionType; +begin + result := TExceptionType.DEPTH_LIMIT; +end; + { TBinaryProtocolImpl.TFactory } constructor TBinaryProtocolImpl.TFactory.Create(AStrictRead, AStrictWrite: Boolean); diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index c2071df89da..df087a1e4c6 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -81,7 +81,7 @@ TTransportImpl = class( TInterfacedObject, ITransport) procedure Flush; virtual; end; - TTransportException = class( TException) + TTransportException = class abstract( TException) public type TExceptionType = ( @@ -93,10 +93,9 @@ TTransportException = class( TException) BadArgs, Interrupted ); - private - function GetType: TExceptionType; protected constructor HiddenCreate(const Msg: string); + class function GetType: TExceptionType; virtual; abstract; public class function Create( AType: TExceptionType): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)'; class function Create( const msg: string): TTransportException; reintroduce; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)'; @@ -110,13 +109,40 @@ TTransportExceptionSpecialized = class abstract (TTransportException) constructor Create(const Msg: string); end; - TTransportExceptionUnknown = class (TTransportExceptionSpecialized); - TTransportExceptionNotOpen = class (TTransportExceptionSpecialized); - TTransportExceptionAlreadyOpen = class (TTransportExceptionSpecialized); - TTransportExceptionTimedOut = class (TTransportExceptionSpecialized); - TTransportExceptionEndOfFile = class (TTransportExceptionSpecialized); - TTransportExceptionBadArgs = class (TTransportExceptionSpecialized); - TTransportExceptionInterrupted = class (TTransportExceptionSpecialized); + TTransportExceptionUnknown = class (TTransportExceptionSpecialized) + protected + class function GetType: TTransportException.TExceptionType; override; + end; + + TTransportExceptionNotOpen = class (TTransportExceptionSpecialized) + protected + class function GetType: TTransportException.TExceptionType; override; + end; + + TTransportExceptionAlreadyOpen = class (TTransportExceptionSpecialized) + protected + class function GetType: TTransportException.TExceptionType; override; + end; + + TTransportExceptionTimedOut = class (TTransportExceptionSpecialized) + protected + class function GetType: TTransportException.TExceptionType; override; + end; + + TTransportExceptionEndOfFile = class (TTransportExceptionSpecialized) + protected + class function GetType: TTransportException.TExceptionType; override; + end; + + TTransportExceptionBadArgs = class (TTransportExceptionSpecialized) + protected + class function GetType: TTransportException.TExceptionType; override; + end; + + TTransportExceptionInterrupted = class (TTransportExceptionSpecialized) + protected + class function GetType: TTransportException.TExceptionType; override; + end; TSecureProtocol = ( SSL_2, SSL_3, TLS_1, // outdated, for compatibilty only @@ -446,17 +472,6 @@ procedure TTransportImpl.Write( const pBuf : Pointer; len : Integer); { TTransportException } -function TTransportException.GetType: TExceptionType; -begin - if Self is TTransportExceptionNotOpen then Result := TExceptionType.NotOpen - else if Self is TTransportExceptionAlreadyOpen then Result := TExceptionType.AlreadyOpen - else if Self is TTransportExceptionTimedOut then Result := TExceptionType.TimedOut - else if Self is TTransportExceptionEndOfFile then Result := TExceptionType.EndOfFile - else if Self is TTransportExceptionBadArgs then Result := TExceptionType.BadArgs - else if Self is TTransportExceptionInterrupted then Result := TExceptionType.Interrupted - else Result := TExceptionType.Unknown; -end; - constructor TTransportException.HiddenCreate(const Msg: string); begin inherited Create(Msg); @@ -470,8 +485,7 @@ class function TTransportException.Create(AType: TExceptionType): TTransportExce {$WARN SYMBOL_DEPRECATED DEFAULT} end; -class function TTransportException.Create(AType: TExceptionType; - const msg: string): TTransportException; +class function TTransportException.Create(aType: TExceptionType; const msg: string): TTransportException; begin case AType of TExceptionType.NotOpen: Result := TTransportExceptionNotOpen.Create(msg); @@ -481,6 +495,7 @@ class function TTransportException.Create(AType: TExceptionType; TExceptionType.BadArgs: Result := TTransportExceptionBadArgs.Create(msg); TExceptionType.Interrupted: Result := TTransportExceptionInterrupted.Create(msg); else + ASSERT( TExceptionType.Unknown = aType); Result := TTransportExceptionUnknown.Create(msg); end; end; @@ -497,6 +512,43 @@ constructor TTransportExceptionSpecialized.Create(const Msg: string); inherited HiddenCreate(Msg); end; +{ specialized TTransportExceptions } + +class function TTransportExceptionUnknown.GetType: TTransportException.TExceptionType; +begin + result := TExceptionType.Unknown; +end; + +class function TTransportExceptionNotOpen.GetType: TTransportException.TExceptionType; +begin + result := TExceptionType.NotOpen; +end; + +class function TTransportExceptionAlreadyOpen.GetType: TTransportException.TExceptionType; +begin + result := TExceptionType.AlreadyOpen; +end; + +class function TTransportExceptionTimedOut.GetType: TTransportException.TExceptionType; +begin + result := TExceptionType.TimedOut; +end; + +class function TTransportExceptionEndOfFile.GetType: TTransportException.TExceptionType; +begin + result := TExceptionType.EndOfFile; +end; + +class function TTransportExceptionBadArgs.GetType: TTransportException.TExceptionType; +begin + result := TExceptionType.BadArgs; +end; + +class function TTransportExceptionInterrupted.GetType: TTransportException.TExceptionType; +begin + result := TExceptionType.Interrupted; +end; + { TTransportFactoryImpl } function TTransportFactoryImpl.GetTransport( const ATrans: ITransport): ITransport; diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index e127380cab5..abc0c1eb699 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -34,7 +34,7 @@ interface TApplicationExceptionSpecializedClass = class of TApplicationExceptionSpecialized; - TApplicationException = class( TException) + TApplicationException = class abstract( TException) public type {$SCOPEDENUMS ON} @@ -52,10 +52,10 @@ TApplicationException = class( TException) UnsupportedClientType ); {$SCOPEDENUMS OFF} - private - function GetType: TExceptionType; protected constructor HiddenCreate(const Msg: string); + class function GetType: TExceptionType; virtual; abstract; + class function GetSpecializedExceptionType(AType: TExceptionType): TApplicationExceptionSpecializedClass; public // purposefully hide inherited constructor class function Create(const Msg: string): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)'; @@ -63,7 +63,7 @@ TApplicationException = class( TException) class function Create( AType: TExceptionType): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)'; class function Create( AType: TExceptionType; const msg: string): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)'; - class function GetSpecializedExceptionType(AType: TExceptionType): TApplicationExceptionSpecializedClass; + property Type_: TExceptionType read GetType; class function Read( const iprot: IProtocol): TApplicationException; procedure Write( const oprot: IProtocol ); @@ -75,38 +75,67 @@ TApplicationExceptionSpecialized = class abstract (TApplicationException) constructor Create(const Msg: string); end; - TApplicationExceptionUnknown = class (TApplicationExceptionSpecialized); - TApplicationExceptionUnknownMethod = class (TApplicationExceptionSpecialized); - TApplicationExceptionInvalidMessageType = class (TApplicationExceptionSpecialized); - TApplicationExceptionWrongMethodName = class (TApplicationExceptionSpecialized); - TApplicationExceptionBadSequenceID = class (TApplicationExceptionSpecialized); - TApplicationExceptionMissingResult = class (TApplicationExceptionSpecialized); - TApplicationExceptionInternalError = class (TApplicationExceptionSpecialized); - TApplicationExceptionProtocolError = class (TApplicationExceptionSpecialized); - TApplicationExceptionInvalidTransform = class (TApplicationExceptionSpecialized); - TApplicationExceptionInvalidProtocol = class (TApplicationExceptionSpecialized); - TApplicationExceptionUnsupportedClientType = class (TApplicationExceptionSpecialized); + TApplicationExceptionUnknown = class (TApplicationExceptionSpecialized) + protected + class function GetType: TApplicationException.TExceptionType; override; + end; + + TApplicationExceptionUnknownMethod = class (TApplicationExceptionSpecialized) + protected + class function GetType: TApplicationException.TExceptionType; override; + end; + + TApplicationExceptionInvalidMessageType = class (TApplicationExceptionSpecialized) + protected + class function GetType: TApplicationException.TExceptionType; override; + end; + + TApplicationExceptionWrongMethodName = class (TApplicationExceptionSpecialized) + protected + class function GetType: TApplicationException.TExceptionType; override; + end; + + TApplicationExceptionBadSequenceID = class (TApplicationExceptionSpecialized) + protected + class function GetType: TApplicationException.TExceptionType; override; + end; + + TApplicationExceptionMissingResult = class (TApplicationExceptionSpecialized) + protected + class function GetType: TApplicationException.TExceptionType; override; + end; + + TApplicationExceptionInternalError = class (TApplicationExceptionSpecialized) + protected + class function GetType: TApplicationException.TExceptionType; override; + end; + + TApplicationExceptionProtocolError = class (TApplicationExceptionSpecialized) + protected + class function GetType: TApplicationException.TExceptionType; override; + end; + + TApplicationExceptionInvalidTransform = class (TApplicationExceptionSpecialized) + protected + class function GetType: TApplicationException.TExceptionType; override; + end; + + TApplicationExceptionInvalidProtocol = class (TApplicationExceptionSpecialized) + protected + class function GetType: TApplicationException.TExceptionType; override; + end; + + TApplicationExceptionUnsupportedClientType = class (TApplicationExceptionSpecialized) + protected + class function GetType: TApplicationException.TExceptionType; override; + end; + implementation { TApplicationException } -function TApplicationException.GetType: TExceptionType; -begin - if Self is TApplicationExceptionUnknownMethod then Result := TExceptionType.UnknownMethod - else if Self is TApplicationExceptionInvalidMessageType then Result := TExceptionType.InvalidMessageType - else if Self is TApplicationExceptionWrongMethodName then Result := TExceptionType.WrongMethodName - else if Self is TApplicationExceptionBadSequenceID then Result := TExceptionType.BadSequenceID - else if Self is TApplicationExceptionMissingResult then Result := TExceptionType.MissingResult - else if Self is TApplicationExceptionInternalError then Result := TExceptionType.InternalError - else if Self is TApplicationExceptionProtocolError then Result := TExceptionType.ProtocolError - else if Self is TApplicationExceptionInvalidTransform then Result := TExceptionType.InvalidTransform - else if Self is TApplicationExceptionInvalidProtocol then Result := TExceptionType.InvalidProtocol - else if Self is TApplicationExceptionUnsupportedClientType then Result := TExceptionType.UnsupportedClientType - else Result := TExceptionType.Unknown; -end; - constructor TApplicationException.HiddenCreate(const Msg: string); begin inherited Create(Msg); @@ -148,10 +177,12 @@ class function TApplicationException.GetSpecializedExceptionType(AType: TExcepti TExceptionType.InvalidProtocol: Result := TApplicationExceptionInvalidProtocol; TExceptionType.UnsupportedClientType: Result := TApplicationExceptionUnsupportedClientType; else + ASSERT( TExceptionType.Unknown = aType); Result := TApplicationExceptionUnknown; end; end; + class function TApplicationException.Read( const iprot: IProtocol): TApplicationException; var field : TThriftField; @@ -236,4 +267,62 @@ constructor TApplicationExceptionSpecialized.Create(const Msg: string); inherited HiddenCreate(Msg); end; +{ specialized TApplicationExceptions } + +class function TApplicationExceptionUnknownMethod.GetType : TApplicationException.TExceptionType; +begin + result := TExceptionType.UnknownMethod; +end; + +class function TApplicationExceptionInvalidMessageType.GetType : TApplicationException.TExceptionType; +begin + result := TExceptionType.InvalidMessageType; +end; + +class function TApplicationExceptionWrongMethodName.GetType : TApplicationException.TExceptionType; +begin + result := TExceptionType.WrongMethodName; +end; + +class function TApplicationExceptionBadSequenceID.GetType : TApplicationException.TExceptionType; +begin + result := TExceptionType.BadSequenceID; +end; + +class function TApplicationExceptionMissingResult.GetType : TApplicationException.TExceptionType; +begin + result := TExceptionType.MissingResult; +end; + +class function TApplicationExceptionInternalError.GetType : TApplicationException.TExceptionType; +begin + result := TExceptionType.InternalError; +end; + +class function TApplicationExceptionProtocolError.GetType : TApplicationException.TExceptionType; +begin + result := TExceptionType.ProtocolError; +end; + +class function TApplicationExceptionInvalidTransform.GetType : TApplicationException.TExceptionType; +begin + result := TExceptionType.InvalidTransform; +end; + +class function TApplicationExceptionInvalidProtocol.GetType : TApplicationException.TExceptionType; +begin + result := TExceptionType.InvalidProtocol; +end; + +class function TApplicationExceptionUnsupportedClientType.GetType : TApplicationException.TExceptionType; +begin + result := TExceptionType.UnsupportedClientType; +end; + +class function TApplicationExceptionUnknown.GetType : TApplicationException.TExceptionType; +begin + result := TExceptionType.Unknown; +end; + + end. From fad7fd3e5a850c0f4bf57e7370fad359d575fdc6 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 9 Nov 2019 23:24:52 +0100 Subject: [PATCH 429/756] THRIFT-5005 Refactoring of the Delphi libs [ci skip] Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.Collections.pas | 12 +- lib/delphi/src/Thrift.Processor.Multiplex.pas | 18 +- lib/delphi/src/Thrift.Protocol.Compact.pas | 16 +- lib/delphi/src/Thrift.Protocol.JSON.pas | 24 +-- lib/delphi/src/Thrift.Protocol.Multiplex.pas | 2 +- lib/delphi/src/Thrift.Protocol.pas | 85 ++++----- lib/delphi/src/Thrift.Serializer.pas | 4 +- lib/delphi/src/Thrift.Server.pas | 162 ++++++++++-------- lib/delphi/src/Thrift.Socket.pas | 6 +- lib/delphi/src/Thrift.Stream.pas | 13 +- lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas | 4 +- lib/delphi/src/Thrift.Transport.Pipes.pas | 2 +- lib/delphi/src/Thrift.Transport.WinHTTP.pas | 10 +- lib/delphi/src/Thrift.Transport.pas | 54 +++--- lib/delphi/src/Thrift.TypeRegistry.pas | 2 +- lib/delphi/src/Thrift.pas | 24 +-- lib/delphi/test/serializer/TestSerializer.dpr | 7 +- 17 files changed, 221 insertions(+), 224 deletions(-) diff --git a/lib/delphi/src/Thrift.Collections.pas b/lib/delphi/src/Thrift.Collections.pas index 3b56fe20564..ad852accaa8 100644 --- a/lib/delphi/src/Thrift.Collections.pas +++ b/lib/delphi/src/Thrift.Collections.pas @@ -65,9 +65,9 @@ interface end; TThriftDictionaryImpl = class( TInterfacedObject, IThriftDictionary, IThriftContainer, ISupportsToString) - private + strict private FDictionaly : TDictionary; - protected + strict protected function GetEnumerator: TEnumerator>; function GetKeys: TDictionary.TKeyCollection; @@ -142,9 +142,9 @@ TThriftDictionaryImpl = class( TInterfacedObject, IThriftDictiona end; TThriftListImpl = class( TInterfacedObject, IThriftList, IThriftContainer, ISupportsToString) - private + strict private FList : TList; - protected + strict protected function GetEnumerator: TEnumerator; function GetCapacity: Integer; procedure SetCapacity(Value: Integer); @@ -205,10 +205,10 @@ TThriftListImpl = class( TInterfacedObject, IThriftList, IThriftContaine end; THashSetImpl = class( TInterfacedObject, IHashSet, IThriftContainer, ISupportsToString) - private + strict private FDictionary : IThriftDictionary; FIsReadOnly: Boolean; - protected + strict protected function GetEnumerator: TEnumerator; function GetIsReadOnly: Boolean; function GetCount: Integer; diff --git a/lib/delphi/src/Thrift.Processor.Multiplex.pas b/lib/delphi/src/Thrift.Processor.Multiplex.pas index 8cf23db0760..622f730f2af 100644 --- a/lib/delphi/src/Thrift.Processor.Multiplex.pas +++ b/lib/delphi/src/Thrift.Processor.Multiplex.pas @@ -62,19 +62,19 @@ interface TMultiplexedProcessorImpl = class( TInterfacedObject, IMultiplexedProcessor, IProcessor) - private type + strict private type // 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. TStoredMessageProtocol = class( TProtocolDecorator) - private + strict private FMessageBegin : TThriftMessage; public constructor Create( const protocol : IProtocol; const aMsgBegin : TThriftMessage); function ReadMessageBegin: TThriftMessage; override; end; - private + strict private FServiceProcessorMap : TDictionary; FDefaultProcessor : IProcessor; @@ -113,12 +113,6 @@ constructor TMultiplexedProcessorImpl.TStoredMessageProtocol.Create( const proto end; -function TMultiplexedProcessorImpl.TStoredMessageProtocol.ReadMessageBegin: TThriftMessage; -begin - result := FMessageBegin; -end; - - constructor TMultiplexedProcessorImpl.Create; begin inherited Create; @@ -136,6 +130,12 @@ destructor TMultiplexedProcessorImpl.Destroy; end; +function TMultiplexedProcessorImpl.TStoredMessageProtocol.ReadMessageBegin: TThriftMessage; +begin + result := FMessageBegin; +end; + + procedure TMultiplexedProcessorImpl.RegisterProcessor( const serviceName : String; const processor : IProcessor; const asDefault : Boolean); begin FServiceProcessorMap.Add( serviceName, processor); diff --git a/lib/delphi/src/Thrift.Protocol.Compact.pas b/lib/delphi/src/Thrift.Protocol.Compact.pas index 07cab9a054c..866bd26e3fd 100644 --- a/lib/delphi/src/Thrift.Protocol.Compact.pas +++ b/lib/delphi/src/Thrift.Protocol.Compact.pas @@ -47,7 +47,7 @@ TFactory = class( TInterfacedObject, IProtocolFactory) function GetProtocol( const trans: ITransport): IProtocol; end; - private const + strict private const { TODO static TStruct ANONYMOUS_STRUCT = new TStruct(""); @@ -61,7 +61,7 @@ TFactory = class( TInterfacedObject, IProtocolFactory) TYPE_BITS = Byte( $07); // 0000 0111 TYPE_SHIFT_AMOUNT = Byte( 5); - private type + strict private type // All of the on-wire type codes. Types = ( STOP = $00, @@ -79,7 +79,7 @@ TFactory = class( TInterfacedObject, IProtocolFactory) STRUCT = $0C ); - private const + strict private const ttypeToCompactType : array[TType] of Types = ( Types.STOP, // Stop = 0, Types(-1), // Void = 1, @@ -115,7 +115,7 @@ TFactory = class( TInterfacedObject, IProtocolFactory) TType.Struct // STRUCT ); - private + strict private // Used to keep track of the last field for the current and previous structs, // so we can do the delta stuff. lastField_ : TStack; @@ -123,11 +123,11 @@ TFactory = class( TInterfacedObject, IProtocolFactory) // If we encounter a boolean field begin, save the TField here so it can // have the value incorporated. - private booleanField_ : TThriftField; + strict private booleanField_ : TThriftField; // If we Read a field header, and it's a boolean field, save the boolean // value here so that ReadBool can use it. - private boolValue_ : ( unused, bool_true, bool_false); + strict private boolValue_ : ( unused, bool_true, bool_false); public constructor Create(const trans : ITransport); @@ -135,7 +135,7 @@ TFactory = class( TInterfacedObject, IProtocolFactory) procedure Reset; - private + strict private procedure WriteByteDirect( const b : Byte); overload; // Writes a byte without any possibility of all that field header nonsense. @@ -145,7 +145,7 @@ TFactory = class( TInterfacedObject, IProtocolFactory) // TODO: make a permanent buffer like WriteVarint64? procedure WriteVarint32( n : Cardinal); - private + strict private // 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. procedure WriteFieldBeginInternal( const field : TThriftField; typeOverride : Byte); diff --git a/lib/delphi/src/Thrift.Protocol.JSON.pas b/lib/delphi/src/Thrift.Protocol.JSON.pas index 30600aa808b..85cb973f9b6 100644 --- a/lib/delphi/src/Thrift.Protocol.JSON.pas +++ b/lib/delphi/src/Thrift.Protocol.JSON.pas @@ -52,17 +52,17 @@ TFactory = class( TInterfacedObject, IProtocolFactory) function GetProtocol( const trans: ITransport): IProtocol; end; - private + strict private class function GetTypeNameForTypeID(typeID : TType) : string; class function GetTypeIDForTypeName( const name : string) : TType; - protected + strict protected type // Base class for tracking JSON contexts that may require // inserting/Reading additional JSON syntax characters. // This base context does nothing. TJSONBaseContext = class - protected + strict protected FProto : Pointer; // weak IJSONProtocol; public constructor Create( const aProto : IJSONProtocol); @@ -74,7 +74,7 @@ TJSONBaseContext = class // Context for JSON lists. // Will insert/Read commas before each item except for the first one. TJSONListContext = class( TJSONBaseContext) - private + strict private FFirst : Boolean; public constructor Create( const aProto : IJSONProtocol); @@ -86,7 +86,7 @@ TJSONListContext = class( TJSONBaseContext) // 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). TJSONPairContext = class( TJSONBaseContext) - private + strict private FFirst, FColon : Boolean; public constructor Create( const aProto : IJSONProtocol); @@ -97,11 +97,13 @@ TJSONPairContext = class( TJSONBaseContext) // Holds up to one byte from the transport TLookaheadReader = class - protected + strict protected FProto : Pointer; // weak IJSONProtocol; + + protected constructor Create( const aProto : IJSONProtocol); - private + strict private FHasData : Boolean; FData : Byte; @@ -115,7 +117,7 @@ TLookaheadReader = class function Peek : Byte; end; - protected + strict protected // Stack of nested contexts that we may be in FContextStack : TStack; @@ -135,12 +137,12 @@ TLookaheadReader = class constructor Create( const aTrans : ITransport); destructor Destroy; override; - protected + strict protected // IJSONProtocol // Read a byte that must match b; otherwise an exception is thrown. procedure ReadJSONSyntaxChar( b : Byte); - private + strict private // Convert a byte containing a hex char ('0'-'9' or 'a'-'f') into its corresponding hex value class function HexVal( ch : Byte) : Byte; @@ -213,7 +215,7 @@ TLookaheadReader = class function ReadBinary: TBytes; override; - private + strict private // Reading methods. // Read in a JSON string, unescaping as appropriate. diff --git a/lib/delphi/src/Thrift.Protocol.Multiplex.pas b/lib/delphi/src/Thrift.Protocol.Multiplex.pas index 93a38380d11..e5e0cd9fe35 100644 --- a/lib/delphi/src/Thrift.Protocol.Multiplex.pas +++ b/lib/delphi/src/Thrift.Protocol.Multiplex.pas @@ -54,7 +54,7 @@ TMultiplexedProtocol = class( TProtocolDecorator) { Used to delimit the service name from the function name } SEPARATOR = ':'; - private + strict private FServiceName : String; public diff --git a/lib/delphi/src/Thrift.Protocol.pas b/lib/delphi/src/Thrift.Protocol.pas index 47e88fe67b0..7c802214d91 100644 --- a/lib/delphi/src/Thrift.Protocol.pas +++ b/lib/delphi/src/Thrift.Protocol.pas @@ -106,7 +106,6 @@ TThriftSet = record end; - IProtocolFactory = interface ['{7CD64A10-4E9F-4E99-93BF-708A31F4A67B}'] function GetProtocol( const trans: ITransport): IProtocol; @@ -123,7 +122,7 @@ TProtocolException = class abstract( TException) NOT_IMPLEMENTED = 5, DEPTH_LIMIT = 6 ); - protected + strict protected constructor HiddenCreate(const Msg: string); class function GetType: TExceptionType; virtual; abstract; public @@ -142,37 +141,37 @@ TProtocolExceptionSpecialized = class abstract (TProtocolException) end; TProtocolExceptionUnknown = class (TProtocolExceptionSpecialized) - protected + strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionInvalidData = class (TProtocolExceptionSpecialized) - protected + strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionNegativeSize = class (TProtocolExceptionSpecialized) - protected + strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionSizeLimit = class (TProtocolExceptionSpecialized) - protected + strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionBadVersion = class (TProtocolExceptionSpecialized) - protected + strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionNotImplemented = class (TProtocolExceptionSpecialized) - protected + strict protected class function GetType: TProtocolException.TExceptionType; override; end; TProtocolExceptionDepthLimit = class (TProtocolExceptionSpecialized) - protected + strict protected class function GetType: TProtocolException.TExceptionType; override; end; @@ -189,7 +188,7 @@ TProtocolUtil = class end; TProtocolRecursionTrackerImpl = class abstract( TInterfacedObject, IProtocolRecursionTracker) - protected + strict protected FProtocol : IProtocol; public constructor Create( prot : IProtocol); @@ -255,7 +254,7 @@ TProtocolRecursionTrackerImpl = class abstract( TInterfacedObject, IProtocolRe end; TProtocolImpl = class abstract( TInterfacedObject, IProtocol) - protected + strict protected FTrans : ITransport; FRecursionLimit : Integer; FRecursionDepth : Integer; @@ -326,33 +325,30 @@ TProtocolImpl = class abstract( TInterfacedObject, IProtocol) TBinaryProtocolImpl = class( TProtocolImpl ) - protected + strict protected const VERSION_MASK : Cardinal = $ffff0000; VERSION_1 : Cardinal = $80010000; - protected + strict protected FStrictRead : Boolean; FStrictWrite : Boolean; - private + strict private function ReadAll( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer ): Integer; inline; function ReadStringBody( size: Integer): string; public - type TFactory = class( TInterfacedObject, IProtocolFactory) - protected + strict protected FStrictRead : Boolean; FStrictWrite : Boolean; - public function GetProtocol( const trans: ITransport): IProtocol; - constructor Create( AStrictRead, AStrictWrite: Boolean ); overload; - constructor Create; overload; + public + constructor Create( const aStrictRead : Boolean = FALSE; const aStrictWrite: Boolean = TRUE); reintroduce; end; - constructor Create( const trans: ITransport); overload; - constructor Create( const trans: ITransport; strictRead: Boolean; strictWrite: Boolean); overload; + constructor Create( const trans: ITransport; strictRead: Boolean = FALSE; strictWrite: Boolean = TRUE); reintroduce; procedure WriteMessageBegin( const msg: TThriftMessage); override; procedure WriteMessageEnd; override; @@ -405,7 +401,7 @@ TFactory = class( TInterfacedObject, IProtocolFactory) See p.175 of Design Patterns (by Gamma et al.) } TProtocolDecorator = class( TProtocolImpl) - private + strict private FWrappedProtocol : IProtocol; public @@ -507,13 +503,13 @@ procedure Init( var rec : TThriftList; const AElementType: TType = Low(TType) implementation -function ConvertInt64ToDouble( const n: Int64): Double; +function ConvertInt64ToDouble( const n: Int64): Double; inline; begin ASSERT( SizeOf(n) = SizeOf(Result)); System.Move( n, Result, SizeOf(Result)); end; -function ConvertDoubleToInt64( const d: Double): Int64; +function ConvertDoubleToInt64( const d: Double): Int64; inline; begin ASSERT( SizeOf(d) = SizeOf(Result)); System.Move( d, Result, SizeOf(Result)); @@ -595,8 +591,7 @@ function TProtocolImpl.ReadAnsiString: AnsiString; Result := ''; b := ReadBinary; len := Length( b ); - if len > 0 then - begin + if len > 0 then begin SetLength( Result, len); System.Move( b[0], Pointer(Result)^, len ); end; @@ -614,8 +609,7 @@ procedure TProtocolImpl.WriteAnsiString(const s: AnsiString); begin len := Length(s); SetLength( b, len); - if len > 0 then - begin + if len > 0 then begin System.Move( Pointer(s)^, b[0], len ); end; WriteBinary( b ); @@ -693,16 +687,9 @@ class procedure TProtocolUtil.Skip( prot: IProtocol; type_: TType); { TBinaryProtocolImpl } -constructor TBinaryProtocolImpl.Create( const trans: ITransport); -begin - //no inherited - Create( trans, False, True); -end; - -constructor TBinaryProtocolImpl.Create( const trans: ITransport; strictRead, - strictWrite: Boolean); +constructor TBinaryProtocolImpl.Create( const trans: ITransport; strictRead, strictWrite: Boolean); begin - inherited Create( trans ); + inherited Create( trans); FStrictRead := strictRead; FStrictWrite := strictWrite; end; @@ -718,7 +705,7 @@ function TBinaryProtocolImpl.ReadBinary: TBytes; buf : TBytes; begin size := ReadI32; - SetLength( buf, size ); + SetLength( buf, size); FTrans.ReadAll( buf, 0, size); Result := buf; end; @@ -853,10 +840,9 @@ procedure TBinaryProtocolImpl.ReadSetEnd; end; function TBinaryProtocolImpl.ReadStringBody( size: Integer): string; -var - buf : TBytes; +var buf : TBytes; begin - SetLength( buf, size ); + SetLength( buf, size); FTrans.ReadAll( buf, 0, size ); Result := TEncoding.UTF8.GetString( buf); end; @@ -971,17 +957,14 @@ procedure TBinaryProtocolImpl.WriteMapEnd; end; procedure TBinaryProtocolImpl.WriteMessageBegin( const msg: TThriftMessage); -var - version : Cardinal; +var version : Cardinal; begin - if FStrictWrite then - begin + if FStrictWrite then begin version := VERSION_1 or Cardinal( msg.Type_); WriteI32( Integer( version) ); WriteString( msg.Name); WriteI32( msg.SeqID); - end else - begin + end else begin WriteString( msg.Name); WriteByte(ShortInt( msg.Type_)); WriteI32( msg.SeqID); @@ -1099,19 +1082,13 @@ class function TProtocolExceptionDepthLimit.GetType: TProtocolException.TExcepti { TBinaryProtocolImpl.TFactory } -constructor TBinaryProtocolImpl.TFactory.Create(AStrictRead, AStrictWrite: Boolean); +constructor TBinaryProtocolImpl.TFactory.Create( const aStrictRead, aStrictWrite: Boolean); begin inherited Create; FStrictRead := AStrictRead; FStrictWrite := AStrictWrite; end; -constructor TBinaryProtocolImpl.TFactory.Create; -begin - //no inherited; - Create( False, True ) -end; - function TBinaryProtocolImpl.TFactory.GetProtocol( const trans: ITransport): IProtocol; begin Result := TBinaryProtocolImpl.Create( trans, FStrictRead, FStrictWrite); diff --git a/lib/delphi/src/Thrift.Serializer.pas b/lib/delphi/src/Thrift.Serializer.pas index 5f2905a97ea..71b695cde17 100644 --- a/lib/delphi/src/Thrift.Serializer.pas +++ b/lib/delphi/src/Thrift.Serializer.pas @@ -36,7 +36,7 @@ interface type // Generic utility for easily serializing objects into a byte array or Stream. TSerializer = class - private + strict private FStream : TMemoryStream; FTransport : ITransport; FProtocol : IProtocol; @@ -60,7 +60,7 @@ TSerializer = class // Generic utility for easily deserializing objects from byte array or Stream. TDeserializer = class - private + strict private FStream : TMemoryStream; FTransport : ITransport; FProtocol : IProtocol; diff --git a/lib/delphi/src/Thrift.Server.pas b/lib/delphi/src/Thrift.Server.pas index 13c5762cf65..c7cce737542 100644 --- a/lib/delphi/src/Thrift.Server.pas +++ b/lib/delphi/src/Thrift.Server.pas @@ -61,7 +61,7 @@ TServerImpl = class abstract( TInterfacedObject, IServer ) public type TLogDelegate = reference to procedure( const str: string); - protected + strict protected FProcessor : IProcessor; FServerTransport : IServerTransport; FInputTransportFactory : ITransportFactory; @@ -80,51 +80,68 @@ TServerImpl = class abstract( TInterfacedObject, IServer ) procedure Stop; virtual; abstract; public constructor Create( - const AProcessor :IProcessor; - const AServerTransport: IServerTransport; - const AInputTransportFactory : ITransportFactory; - const AOutputTransportFactory : ITransportFactory; - const AInputProtocolFactory : IProtocolFactory; - const AOutputProtocolFactory : IProtocolFactory; - const ALogDelegate : TLogDelegate + const aProcessor :IProcessor; + const aServerTransport: IServerTransport; + const aInputTransportFactory : ITransportFactory; + const aOutputTransportFactory : ITransportFactory; + const aInputProtocolFactory : IProtocolFactory; + const aOutputProtocolFactory : IProtocolFactory; + const aLogDelegate : TLogDelegate ); overload; constructor Create( - const AProcessor :IProcessor; - const AServerTransport: IServerTransport + const aProcessor :IProcessor; + const aServerTransport: IServerTransport ); overload; constructor Create( - const AProcessor :IProcessor; - const AServerTransport: IServerTransport; - const ALogDelegate: TLogDelegate + const aProcessor :IProcessor; + const aServerTransport: IServerTransport; + const aLogDelegate: TLogDelegate ); overload; constructor Create( - const AProcessor :IProcessor; - const AServerTransport: IServerTransport; - const ATransportFactory : ITransportFactory + const aProcessor :IProcessor; + const aServerTransport: IServerTransport; + const aTransportFactory : ITransportFactory ); overload; constructor Create( - const AProcessor :IProcessor; - const AServerTransport: IServerTransport; - const ATransportFactory : ITransportFactory; - const AProtocolFactory : IProtocolFactory + const aProcessor :IProcessor; + const aServerTransport: IServerTransport; + const aTransportFactory : ITransportFactory; + const aProtocolFactory : IProtocolFactory ); overload; end; + TSimpleServer = class( TServerImpl) - private + strict private FStop : Boolean; public - constructor Create( const AProcessor: IProcessor; const AServerTransport: IServerTransport); overload; - constructor Create( const AProcessor: IProcessor; const AServerTransport: IServerTransport; - ALogDel: TServerImpl.TLogDelegate); overload; - constructor Create( const AProcessor: IProcessor; const AServerTransport: IServerTransport; - const ATransportFactory: ITransportFactory); overload; - constructor Create( const AProcessor: IProcessor; const AServerTransport: IServerTransport; - const ATransportFactory: ITransportFactory; const AProtocolFactory: IProtocolFactory); overload; + constructor Create( + const aProcessor: IProcessor; + const aServerTransport: IServerTransport + ); overload; + + constructor Create( + const aProcessor: IProcessor; + const aServerTransport: IServerTransport; + const ALogDel: TServerImpl.TLogDelegate + ); overload; + + constructor Create( + const aProcessor: IProcessor; + const aServerTransport: IServerTransport; + const aTransportFactory: ITransportFactory + ); overload; + + constructor Create( + const aProcessor: IProcessor; + const aServerTransport: IServerTransport; + const aTransportFactory: ITransportFactory; + const aProtocolFactory: IProtocolFactory + ); overload; procedure Serve; override; procedure Stop; override; @@ -135,8 +152,9 @@ implementation { TServerImpl } -constructor TServerImpl.Create( const AProcessor: IProcessor; - const AServerTransport: IServerTransport; const ALogDelegate: TLogDelegate); +constructor TServerImpl.Create( const aProcessor: IProcessor; + const aServerTransport: IServerTransport; + const aLogDelegate: TLogDelegate); var InputFactory, OutputFactory : IProtocolFactory; InputTransFactory, OutputTransFactory : ITransportFactory; @@ -149,8 +167,8 @@ constructor TServerImpl.Create( const AProcessor: IProcessor; //no inherited; Create( - AProcessor, - AServerTransport, + aProcessor, + aServerTransport, InputTransFactory, OutputTransFactory, InputFactory, @@ -159,8 +177,8 @@ constructor TServerImpl.Create( const AProcessor: IProcessor; ); end; -constructor TServerImpl.Create(const AProcessor: IProcessor; - const AServerTransport: IServerTransport); +constructor TServerImpl.Create(const aProcessor: IProcessor; + const aServerTransport: IServerTransport); var InputFactory, OutputFactory : IProtocolFactory; InputTransFactory, OutputTransFactory : ITransportFactory; @@ -173,8 +191,8 @@ constructor TServerImpl.Create(const AProcessor: IProcessor; //no inherited; Create( - AProcessor, - AServerTransport, + aProcessor, + aServerTransport, InputTransFactory, OutputTransFactory, InputFactory, @@ -183,8 +201,8 @@ constructor TServerImpl.Create(const AProcessor: IProcessor; ); end; -constructor TServerImpl.Create(const AProcessor: IProcessor; - const AServerTransport: IServerTransport; const ATransportFactory: ITransportFactory); +constructor TServerImpl.Create(const aProcessor: IProcessor; + const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory); var InputProtocolFactory : IProtocolFactory; OutputProtocolFactory : IProtocolFactory; @@ -193,24 +211,24 @@ constructor TServerImpl.Create(const AProcessor: IProcessor; OutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create; //no inherited; - Create( AProcessor, AServerTransport, ATransportFactory, ATransportFactory, + Create( aProcessor, aServerTransport, aTransportFactory, aTransportFactory, InputProtocolFactory, OutputProtocolFactory, DefaultLogDelegate); end; -constructor TServerImpl.Create(const AProcessor: IProcessor; - const AServerTransport: IServerTransport; - const AInputTransportFactory, AOutputTransportFactory: ITransportFactory; - const AInputProtocolFactory, AOutputProtocolFactory: IProtocolFactory; - const ALogDelegate : TLogDelegate); +constructor TServerImpl.Create(const aProcessor: IProcessor; + const aServerTransport: IServerTransport; + const aInputTransportFactory, aOutputTransportFactory: ITransportFactory; + const aInputProtocolFactory, aOutputProtocolFactory: IProtocolFactory; + const aLogDelegate : TLogDelegate); begin inherited Create; - FProcessor := AProcessor; - FServerTransport := AServerTransport; - FInputTransportFactory := AInputTransportFactory; - FOutputTransportFactory := AOutputTransportFactory; - FInputProtocolFactory := AInputProtocolFactory; - FOutputProtocolFactory := AOutputProtocolFactory; - FLogDelegate := ALogDelegate; + FProcessor := aProcessor; + FServerTransport := aServerTransport; + FInputTransportFactory := aInputTransportFactory; + FOutputTransportFactory := aOutputTransportFactory; + FInputProtocolFactory := aInputProtocolFactory; + FOutputProtocolFactory := aOutputProtocolFactory; + FLogDelegate := aLogDelegate; end; class procedure TServerImpl.DefaultLogDelegate( const str: string); @@ -223,14 +241,14 @@ class procedure TServerImpl.DefaultLogDelegate( const str: string); end; end; -constructor TServerImpl.Create( const AProcessor: IProcessor; - const AServerTransport: IServerTransport; const ATransportFactory: ITransportFactory; - const AProtocolFactory: IProtocolFactory); +constructor TServerImpl.Create( const aProcessor: IProcessor; + const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory; + const aProtocolFactory: IProtocolFactory); begin //no inherited; - Create( AProcessor, AServerTransport, - ATransportFactory, ATransportFactory, - AProtocolFactory, AProtocolFactory, + Create( aProcessor, aServerTransport, + aTransportFactory, aTransportFactory, + aProtocolFactory, aProtocolFactory, DefaultLogDelegate); end; @@ -250,8 +268,8 @@ procedure TServerImpl.SetServerEvents( const value : IServerEvents); { TSimpleServer } -constructor TSimpleServer.Create( const AProcessor: IProcessor; - const AServerTransport: IServerTransport); +constructor TSimpleServer.Create( const aProcessor: IProcessor; + const aServerTransport: IServerTransport); var InputProtocolFactory : IProtocolFactory; OutputProtocolFactory : IProtocolFactory; @@ -263,12 +281,12 @@ constructor TSimpleServer.Create( const AProcessor: IProcessor; InputTransportFactory := TTransportFactoryImpl.Create; OutputTransportFactory := TTransportFactoryImpl.Create; - inherited Create( AProcessor, AServerTransport, InputTransportFactory, + inherited Create( aProcessor, aServerTransport, InputTransportFactory, OutputTransportFactory, InputProtocolFactory, OutputProtocolFactory, DefaultLogDelegate); end; -constructor TSimpleServer.Create( const AProcessor: IProcessor; - const AServerTransport: IServerTransport; ALogDel: TServerImpl.TLogDelegate); +constructor TSimpleServer.Create( const aProcessor: IProcessor; + const aServerTransport: IServerTransport; const ALogDel: TServerImpl.TLogDelegate); var InputProtocolFactory : IProtocolFactory; OutputProtocolFactory : IProtocolFactory; @@ -280,23 +298,23 @@ constructor TSimpleServer.Create( const AProcessor: IProcessor; InputTransportFactory := TTransportFactoryImpl.Create; OutputTransportFactory := TTransportFactoryImpl.Create; - inherited Create( AProcessor, AServerTransport, InputTransportFactory, + inherited Create( aProcessor, aServerTransport, InputTransportFactory, OutputTransportFactory, InputProtocolFactory, OutputProtocolFactory, ALogDel); end; -constructor TSimpleServer.Create( const AProcessor: IProcessor; - const AServerTransport: IServerTransport; const ATransportFactory: ITransportFactory); +constructor TSimpleServer.Create( const aProcessor: IProcessor; + const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory); begin - inherited Create( AProcessor, AServerTransport, ATransportFactory, - ATransportFactory, TBinaryProtocolImpl.TFactory.Create, TBinaryProtocolImpl.TFactory.Create, DefaultLogDelegate); + inherited Create( aProcessor, aServerTransport, aTransportFactory, + aTransportFactory, TBinaryProtocolImpl.TFactory.Create, TBinaryProtocolImpl.TFactory.Create, DefaultLogDelegate); end; -constructor TSimpleServer.Create( const AProcessor: IProcessor; - const AServerTransport: IServerTransport; const ATransportFactory: ITransportFactory; - const AProtocolFactory: IProtocolFactory); +constructor TSimpleServer.Create( const aProcessor: IProcessor; + const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory; + const aProtocolFactory: IProtocolFactory); begin - inherited Create( AProcessor, AServerTransport, ATransportFactory, - ATransportFactory, AProtocolFactory, AProtocolFactory, DefaultLogDelegate); + inherited Create( aProcessor, aServerTransport, aTransportFactory, + aTransportFactory, aProtocolFactory, aProtocolFactory, DefaultLogDelegate); end; procedure TSimpleServer.Serve; diff --git a/lib/delphi/src/Thrift.Socket.pas b/lib/delphi/src/Thrift.Socket.pas index f0cab79db28..b33f20276c2 100644 --- a/lib/delphi/src/Thrift.Socket.pas +++ b/lib/delphi/src/Thrift.Socket.pas @@ -81,7 +81,7 @@ TIn6Addr = record TScopeId = record public Value: ULONG; - private + strict private function GetBitField(Loc: Integer): Integer; inline; procedure SetBitField(Loc: Integer; const aValue: Integer); inline; public @@ -125,7 +125,7 @@ function GetNameInfoW(const pSockaddr: TSockAddr; SockaddrLength: Integer; pNode ISmartPointer = reference to function: T; TSmartPointer = class(TInterfacedObject, ISmartPointer) - private + strict private FValue: T; FDestroyer: TSmartPointerDestroyer; public @@ -147,7 +147,7 @@ TBaseSocket = class abstract class constructor Create; class destructor Destroy; class procedure DefaultLogDelegate(const Str: string); - protected type + strict protected type IGetAddrInfoWrapper = interface function Init: Integer; function GetRes: PAddrInfoW; diff --git a/lib/delphi/src/Thrift.Stream.pas b/lib/delphi/src/Thrift.Stream.pas index 3308c53a55f..7cb9219b677 100644 --- a/lib/delphi/src/Thrift.Stream.pas +++ b/lib/delphi/src/Thrift.Stream.pas @@ -36,7 +36,6 @@ interface Thrift.Utils; type - IThriftStream = interface ['{2A77D916-7446-46C1-8545-0AEC0008DBCA}'] procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; @@ -51,9 +50,9 @@ interface end; TThriftStreamImpl = class( TInterfacedObject, IThriftStream) - private + strict private procedure CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer); overload; - protected + strict protected procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; inline; procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; virtual; function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; inline; @@ -66,10 +65,10 @@ TThriftStreamImpl = class( TInterfacedObject, IThriftStream) end; TThriftStreamAdapterDelphi = class( TThriftStreamImpl ) - private + strict private FStream : TStream; FOwnsStream : Boolean; - protected + strict protected procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; procedure Open; override; @@ -83,9 +82,9 @@ TThriftStreamAdapterDelphi = class( TThriftStreamImpl ) end; TThriftStreamAdapterCOM = class( TThriftStreamImpl) - private + strict private FStream : IStream; - protected + strict protected procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; procedure Open; override; diff --git a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas index c666e7fedc9..87bf23b0428 100644 --- a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas @@ -41,7 +41,7 @@ interface type TMsxmlHTTPClientImpl = class( TTransportImpl, IHTTPClient) - private + strict private FUri : string; FInputStream : IThriftStream; FOutputStream : IThriftStream; @@ -52,7 +52,7 @@ TMsxmlHTTPClientImpl = class( TTransportImpl, IHTTPClient) FCustomHeaders : IThriftDictionary; function CreateRequest: IXMLHTTPRequest; - protected + strict protected function GetIsOpen: Boolean; override; procedure Open(); override; procedure Close(); override; diff --git a/lib/delphi/src/Thrift.Transport.Pipes.pas b/lib/delphi/src/Thrift.Transport.Pipes.pas index 77a343b0cac..9368f2fa995 100644 --- a/lib/delphi/src/Thrift.Transport.Pipes.pas +++ b/lib/delphi/src/Thrift.Transport.Pipes.pas @@ -199,7 +199,7 @@ TAnonymousPipeServerTransportImpl = class( TPipeServerTransportBase, IAnonymou FClientAnonWrite : THandle; FTimeOut: DWORD; - protected + strict protected function Accept(const fnAccepting: TProc): ITransport; override; function CreateAnonPipe : Boolean; diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas index 262e38fb129..0bf7e456fbc 100644 --- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas @@ -37,7 +37,7 @@ interface type TWinHTTPClientImpl = class( TTransportImpl, IHTTPClient) - private + strict private FUri : string; FInputStream : IThriftStream; FOutputMemoryStream : TMemoryStream; @@ -51,14 +51,14 @@ TWinHTTPClientImpl = class( TTransportImpl, IHTTPClient) function CreateRequest: IWinHTTPRequest; function SecureProtocolsAsWinHTTPFlags : Cardinal; - private + strict private type TErrorInfo = ( SplitUrl, WinHTTPSession, WinHTTPConnection, WinHTTPRequest, RequestSetup, AutoProxy ); THTTPResponseStream = class( TThriftStreamImpl) - private + strict private FRequest : IWinHTTPRequest; - protected + strict protected procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; procedure Open; override; @@ -71,7 +71,7 @@ THTTPResponseStream = class( TThriftStreamImpl) destructor Destroy; override; end; - protected + strict protected function GetIsOpen: Boolean; override; procedure Open(); override; procedure Close(); override; diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index df087a1e4c6..b6e3c99f69b 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -64,7 +64,7 @@ interface end; TTransportImpl = class( TInterfacedObject, ITransport) - protected + strict protected function GetIsOpen: Boolean; virtual; abstract; property IsOpen: Boolean read GetIsOpen; function Peek: Boolean; virtual; @@ -93,7 +93,7 @@ TTransportException = class abstract( TException) BadArgs, Interrupted ); - protected + strict protected constructor HiddenCreate(const Msg: string); class function GetType: TExceptionType; virtual; abstract; public @@ -110,37 +110,37 @@ TTransportExceptionSpecialized = class abstract (TTransportException) end; TTransportExceptionUnknown = class (TTransportExceptionSpecialized) - protected + strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionNotOpen = class (TTransportExceptionSpecialized) - protected + strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionAlreadyOpen = class (TTransportExceptionSpecialized) - protected + strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionTimedOut = class (TTransportExceptionSpecialized) - protected + strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionEndOfFile = class (TTransportExceptionSpecialized) - protected + strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionBadArgs = class (TTransportExceptionSpecialized) - protected + strict protected class function GetType: TTransportException.TExceptionType; override; end; TTransportExceptionInterrupted = class (TTransportExceptionSpecialized) - protected + strict protected class function GetType: TTransportException.TExceptionType; override; end; @@ -182,7 +182,7 @@ TTransportExceptionInterrupted = class (TTransportExceptionSpecialized) end; TServerTransportImpl = class( TInterfacedObject, IServerTransport) - protected + strict protected procedure Listen; virtual; abstract; procedure Close; virtual; abstract; function Accept( const fnAccepting: TProc): ITransport; virtual; abstract; @@ -199,9 +199,9 @@ TTransportFactoryImpl = class( TInterfacedObject, ITransportFactory) TTcpSocketStreamImpl = class( TThriftStreamImpl ) {$IFDEF OLD_SOCKETS} - private type + strict private type TWaitForData = ( wfd_HaveData, wfd_Timeout, wfd_Error); - private + strict private FTcpClient : TCustomIpClient; FTimeout : Integer; function Select( ReadReady, WriteReady, ExceptFlag: PBoolean; @@ -210,10 +210,10 @@ TTcpSocketStreamImpl = class( TThriftStreamImpl ) var wsaError, bytesReady : Integer): TWaitForData; {$ELSE} FTcpClient: TSocket; - protected const + strict protected const SLEEP_TIME = 200; {$ENDIF} - protected + strict protected procedure Write( const pBuf : Pointer; offset, count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; procedure Open; override; @@ -239,10 +239,10 @@ TTcpSocketStreamImpl = class( TThriftStreamImpl ) end; TStreamTransportImpl = class( TTransportImpl, IStreamTransport) - protected + strict protected FInputStream : IThriftStream; FOutputStream : IThriftStream; - protected + strict protected function GetIsOpen: Boolean; override; function GetInputStream: IThriftStream; @@ -261,12 +261,12 @@ TStreamTransportImpl = class( TTransportImpl, IStreamTransport) end; TBufferedStreamImpl = class( TThriftStreamImpl) - private + strict private FStream : IThriftStream; FBufSize : Integer; FReadBuffer : TMemoryStream; FWriteBuffer : TMemoryStream; - protected + strict protected procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; procedure Open; override; @@ -280,7 +280,7 @@ TBufferedStreamImpl = class( TThriftStreamImpl) end; TServerSocketImpl = class( TServerTransportImpl) - private + strict private {$IFDEF OLD_SOCKETS} FServer : TTcpServer; FPort : Integer; @@ -290,7 +290,7 @@ TServerSocketImpl = class( TServerTransportImpl) {$ENDIF} FUseBufferedSocket : Boolean; FOwnsServer : Boolean; - protected + strict protected function Accept( const fnAccepting: TProc) : ITransport; override; public {$IFDEF OLD_SOCKETS} @@ -306,7 +306,7 @@ TServerSocketImpl = class( TServerTransportImpl) end; TBufferedTransportImpl = class( TTransportImpl ) - private + strict private FInputBuffer : IThriftStream; FOutputBuffer : IThriftStream; FTransport : IStreamTransport; @@ -314,7 +314,7 @@ TBufferedTransportImpl = class( TTransportImpl ) procedure InitBuffers; function GetUnderlyingTransport: ITransport; - protected + strict protected function GetIsOpen: Boolean; override; procedure Flush; override; public @@ -329,7 +329,7 @@ TBufferedTransportImpl = class( TTransportImpl ) end; TSocketImpl = class(TStreamTransportImpl) - private + strict private {$IFDEF OLD_SOCKETS} FClient : TCustomIpClient; {$ELSE} @@ -345,7 +345,7 @@ TSocketImpl = class(TStreamTransportImpl) {$ENDIF} procedure InitSocket; - protected + strict protected function GetIsOpen: Boolean; override; public procedure Open; override; @@ -368,11 +368,11 @@ TSocketImpl = class(TStreamTransportImpl) end; TFramedTransportImpl = class( TTransportImpl) - private const + strict private const FHeaderSize : Integer = 4; - private class var + strict private class var FHeader_Dummy : array of Byte; - protected + strict protected FTransport : ITransport; FWriteBuffer : TMemoryStream; FReadBuffer : TMemoryStream; diff --git a/lib/delphi/src/Thrift.TypeRegistry.pas b/lib/delphi/src/Thrift.TypeRegistry.pas index c18e97fe6e8..3d31c52a3a3 100644 --- a/lib/delphi/src/Thrift.TypeRegistry.pas +++ b/lib/delphi/src/Thrift.TypeRegistry.pas @@ -29,7 +29,7 @@ interface TFactoryMethod = function:T; TypeRegistry = class - private + strict private class var FTypeInfoToFactoryLookup : TDictionary; public class constructor Create; diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index abc0c1eb699..716e4d22c02 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -52,7 +52,7 @@ TApplicationException = class abstract( TException) UnsupportedClientType ); {$SCOPEDENUMS OFF} - protected + strict protected constructor HiddenCreate(const Msg: string); class function GetType: TExceptionType; virtual; abstract; class function GetSpecializedExceptionType(AType: TExceptionType): TApplicationExceptionSpecializedClass; @@ -76,57 +76,57 @@ TApplicationExceptionSpecialized = class abstract (TApplicationException) end; TApplicationExceptionUnknown = class (TApplicationExceptionSpecialized) - protected + strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionUnknownMethod = class (TApplicationExceptionSpecialized) - protected + strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionInvalidMessageType = class (TApplicationExceptionSpecialized) - protected + strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionWrongMethodName = class (TApplicationExceptionSpecialized) - protected + strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionBadSequenceID = class (TApplicationExceptionSpecialized) - protected + strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionMissingResult = class (TApplicationExceptionSpecialized) - protected + strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionInternalError = class (TApplicationExceptionSpecialized) - protected + strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionProtocolError = class (TApplicationExceptionSpecialized) - protected + strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionInvalidTransform = class (TApplicationExceptionSpecialized) - protected + strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionInvalidProtocol = class (TApplicationExceptionSpecialized) - protected + strict protected class function GetType: TApplicationException.TExceptionType; override; end; TApplicationExceptionUnsupportedClientType = class (TApplicationExceptionSpecialized) - protected + strict protected class function GetType: TApplicationException.TExceptionType; override; end; diff --git a/lib/delphi/test/serializer/TestSerializer.dpr b/lib/delphi/test/serializer/TestSerializer.dpr index 56d0d15d47b..39752cf7095 100644 --- a/lib/delphi/test/serializer/TestSerializer.dpr +++ b/lib/delphi/test/serializer/TestSerializer.dpr @@ -22,7 +22,10 @@ program TestSerializer; {$APPTYPE CONSOLE} uses - Classes, Windows, SysUtils, Generics.Collections, + Classes, + Windows, + SysUtils, + Generics.Collections, Thrift in '..\..\src\Thrift.pas', Thrift.Exception in '..\..\src\Thrift.Exception.pas', Thrift.Socket in '..\..\src\Thrift.Socket.pas', @@ -41,8 +44,6 @@ uses DebugProtoTest, TestSerializer.Data; - - type TTestSerializer = class //extends TestCase { private type From 2646bd65b5ba499779e37ab2d19d67a7684cbdb3 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 9 Nov 2019 23:24:52 +0100 Subject: [PATCH 430/756] THRIFT-5006 Implement DEFAULT_MAX_LENGTH at TFramedTransport Client: Delphi Patch: Jens Geyer --- CHANGES.md | 2 +- lib/delphi/src/Thrift.Server.pas | 4 +- lib/delphi/src/Thrift.Transport.pas | 88 ++++++++++++++++------------- lib/delphi/test/TestClient.pas | 4 +- 4 files changed, 54 insertions(+), 44 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8fffab6b3f6..2f128684e5d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,7 +6,7 @@ - [THRIFT-4990](https://issues.apache.org/jira/browse/THRIFT-4990) - Upgrade to .NET Core 3.0 - [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base - +- [THRIFT-5006](https://issues.apache.org/jira/browse/THRIFT-5006) - Implement DEFAULT_MAX_LENGTH at TFramedTransport ## 0.13.0 diff --git a/lib/delphi/src/Thrift.Server.pas b/lib/delphi/src/Thrift.Server.pas index c7cce737542..c9365c6db11 100644 --- a/lib/delphi/src/Thrift.Server.pas +++ b/lib/delphi/src/Thrift.Server.pas @@ -61,7 +61,7 @@ TServerImpl = class abstract( TInterfacedObject, IServer ) public type TLogDelegate = reference to procedure( const str: string); - strict protected + protected FProcessor : IProcessor; FServerTransport : IServerTransport; FInputTransportFactory : ITransportFactory; @@ -116,7 +116,7 @@ TServerImpl = class abstract( TInterfacedObject, IServer ) TSimpleServer = class( TServerImpl) - strict private + private FStop : Boolean; public constructor Create( diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index b6e3c99f69b..3067bcd76e3 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -91,7 +91,8 @@ TTransportException = class abstract( TException) TimedOut, EndOfFile, BadArgs, - Interrupted + Interrupted, + CorruptedData ); strict protected constructor HiddenCreate(const Msg: string); @@ -144,6 +145,11 @@ TTransportExceptionInterrupted = class (TTransportExceptionSpecialized) class function GetType: TTransportException.TExceptionType; override; end; + TTransportExceptionCorruptedData = class (TTransportExceptionSpecialized) + protected + class function GetType: TTransportException.TExceptionType; override; + end; + TSecureProtocol = ( SSL_2, SSL_3, TLS_1, // outdated, for compatibilty only TLS_1_1, TLS_1_2 // secure (as of today) @@ -368,15 +374,17 @@ TSocketImpl = class(TStreamTransportImpl) end; TFramedTransportImpl = class( TTransportImpl) - strict private const - FHeaderSize : Integer = 4; - strict private class var - FHeader_Dummy : array of Byte; + strict protected const + DEFAULT_MAX_LENGTH = 16384000; // this value is used by all Thrift libraries + strict protected type + TFramedHeader = Int32; strict protected FTransport : ITransport; FWriteBuffer : TMemoryStream; FReadBuffer : TMemoryStream; + FMaxFrameSize : Integer; + procedure InitMaxFrameSize; procedure InitWriteBuffer; procedure ReadFrame; public @@ -386,10 +394,6 @@ TFactory = class( TTransportFactoryImpl ) function GetTransport( const ATrans: ITransport): ITransport; override; end; - {$IFDEF HAVE_CLASS_CTOR} - class constructor Create; - {$ENDIF} - constructor Create; overload; constructor Create( const ATrans: ITransport); overload; destructor Destroy; override; @@ -403,9 +407,6 @@ TFactory = class( TTransportFactoryImpl ) procedure Flush; override; end; -{$IFNDEF HAVE_CLASS_CTOR} -procedure TFramedTransportImpl_Initialize; -{$ENDIF} const DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms @@ -549,6 +550,11 @@ class function TTransportExceptionInterrupted.GetType: TTransportException.TExce result := TExceptionType.Interrupted; end; +class function TTransportExceptionCorruptedData.GetType: TTransportException.TExceptionType; +begin + result := TExceptionType.CorruptedData; +end; + { TTransportFactoryImpl } function TTransportFactoryImpl.GetTransport( const ATrans: ITransport): ITransport; @@ -993,7 +999,7 @@ function TStreamTransportImpl.GetOutputStream: IThriftStream; procedure TStreamTransportImpl.Open; begin - + // nothing to do end; function TStreamTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; @@ -1087,35 +1093,19 @@ procedure TBufferedTransportImpl.Write( const pBuf : Pointer; off, len : Integer { TFramedTransportImpl } -{$IFDEF HAVE_CLASS_CTOR} -class constructor TFramedTransportImpl.Create; -begin - SetLength( FHeader_Dummy, FHeaderSize); - FillChar( FHeader_Dummy[0], Length( FHeader_Dummy) * SizeOf( Byte ), 0); -end; -{$ELSE} -procedure TFramedTransportImpl_Initialize; -begin - SetLength( TFramedTransportImpl.FHeader_Dummy, TFramedTransportImpl.FHeaderSize); - FillChar( TFramedTransportImpl.FHeader_Dummy[0], - Length( TFramedTransportImpl.FHeader_Dummy) * SizeOf( Byte ), 0); -end; -{$ENDIF} - constructor TFramedTransportImpl.Create; begin inherited Create; - InitWriteBuffer; -end; -procedure TFramedTransportImpl.Close; -begin - FTransport.Close; + InitMaxFrameSize; + InitWriteBuffer; end; constructor TFramedTransportImpl.Create( const ATrans: ITransport); begin inherited Create; + + InitMaxFrameSize; InitWriteBuffer; FTransport := ATrans; end; @@ -1127,12 +1117,21 @@ destructor TFramedTransportImpl.Destroy; inherited; end; +procedure TFramedTransportImpl.InitMaxFrameSize; +begin + FMaxFrameSize := DEFAULT_MAX_LENGTH; +end; + +procedure TFramedTransportImpl.Close; +begin + FTransport.Close; +end; + procedure TFramedTransportImpl.Flush; var buf : TBytes; len : Integer; data_len : Integer; - begin len := FWriteBuffer.Size; SetLength( buf, len); @@ -1140,7 +1139,7 @@ procedure TFramedTransportImpl.Flush; System.Move( FWriteBuffer.Memory^, buf[0], len ); end; - data_len := len - FHeaderSize; + data_len := len - SizeOf(TFramedHeader); if (data_len < 0) then begin raise TTransportExceptionUnknown.Create('TFramedTransport.Flush: data_len < 0' ); end; @@ -1166,11 +1165,12 @@ TAccessMemoryStream = class(TMemoryStream) end; procedure TFramedTransportImpl.InitWriteBuffer; +const DUMMY_HEADER : TFramedHeader = 0; begin FWriteBuffer.Free; FWriteBuffer := TMemoryStream.Create; TAccessMemoryStream(FWriteBuffer).Capacity := 1024; - FWriteBuffer.Write( Pointer(@FHeader_Dummy[0])^, FHeaderSize); + FWriteBuffer.Write( DUMMY_HEADER, SizeOf(DUMMY_HEADER)); end; procedure TFramedTransportImpl.Open; @@ -1202,17 +1202,27 @@ function TFramedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer procedure TFramedTransportImpl.ReadFrame; var - i32rd : TBytes; + i32rd : packed array[0..SizeOf(TFramedHeader)-1] of Byte; size : Integer; buff : TBytes; begin - SetLength( i32rd, FHeaderSize ); - FTransport.ReadAll( i32rd, 0, FHeaderSize); + FTransport.ReadAll( @i32rd[0], SizeOf(i32rd), 0, SizeOf(i32rd)); size := ((i32rd[0] and $FF) shl 24) or ((i32rd[1] and $FF) shl 16) or ((i32rd[2] and $FF) shl 8) or (i32rd[3] and $FF); + + if size < 0 then begin + Close(); + raise TTransportExceptionCorruptedData.Create('Read a negative frame size ('+IntToStr(size)+')'); + end; + + if size > FMaxFrameSize then begin + Close(); + raise TTransportExceptionCorruptedData.Create('Frame size ('+IntToStr(size)+') larger than allowed maximum ('+IntToStr(FMaxFrameSize)+')'); + end; + SetLength( buff, size ); FTransport.ReadAll( buff, 0, size ); FReadBuffer.Free; diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas index e59c327208b..a488cacaec3 100644 --- a/lib/delphi/test/TestClient.pas +++ b/lib/delphi/test/TestClient.pas @@ -93,7 +93,7 @@ TClientThread = class( TThread ) Normal, // Fairly small array of usual size (256 bytes) ByteArrayTest, // THRIFT-4454 Large writes/reads may cause range check errors in debug mode PipeWriteLimit, // THRIFT-4372 Pipe write operations across a network are limited to 65,535 bytes per write. - TwentyMB // that's quite a bit of data + FifteenMB // quite a bit of data, but still below the default max frame size ); private @@ -1024,7 +1024,7 @@ function TClientThread.PrepareBinaryData( aRandomDist : Boolean; aSize : TTestSi Normal : SetLength( result, $100); ByteArrayTest : SetLength( result, SizeOf(TByteArray) + 128); PipeWriteLimit : SetLength( result, 65535 + 128); - TwentyMB : SetLength( result, 20 * 1024 * 1024); + FifteenMB : SetLength( result, 15 * 1024 * 1024); else raise EArgumentException.Create('aSize'); end; From ed99455e2ec8ec9c8ed95540c63018d395737f30 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 9 Nov 2019 23:24:52 +0100 Subject: [PATCH 431/756] THRIFT-5009 Serializer implemtation lacks support for layered transports Client: Delphi Patch: Jens Geyer --- .gitignore | 1 + lib/delphi/src/Thrift.Serializer.pas | 50 ++- lib/delphi/src/Thrift.Server.pas | 2 +- lib/delphi/src/Thrift.Transport.pas | 265 +++++++------- .../test/serializer/TestSerializer.Tests.pas | 329 ++++++++++++++++++ lib/delphi/test/serializer/TestSerializer.dpr | 228 +----------- 6 files changed, 507 insertions(+), 368 deletions(-) create mode 100644 lib/delphi/test/serializer/TestSerializer.Tests.pas diff --git a/.gitignore b/.gitignore index d10f769cb71..4e2f4276d8b 100644 --- a/.gitignore +++ b/.gitignore @@ -205,6 +205,7 @@ project.lock.json /lib/dart/**/pubspec.lock /lib/delphi/test/skip/*.request /lib/delphi/test/skip/*.response +/lib/delphi/test/serializer/*.dat /lib/delphi/**/*.identcache /lib/delphi/**/*.local /lib/delphi/**/*.dcu diff --git a/lib/delphi/src/Thrift.Serializer.pas b/lib/delphi/src/Thrift.Serializer.pas index 71b695cde17..b95cf61daa1 100644 --- a/lib/delphi/src/Thrift.Serializer.pas +++ b/lib/delphi/src/Thrift.Serializer.pas @@ -49,6 +49,10 @@ TSerializer = class // It will use the TProtocol specified by the factory that is passed in. constructor Create( const factory : IProtocolFactory); overload; + // Create a new TSerializer. + // It will use the TProtocol and layered transports specified by the factories that are passed in. + constructor Create( const protfact : IProtocolFactory; const transfact : ITransportFactory); overload; + // DTOR destructor Destroy; override; @@ -73,6 +77,10 @@ TDeserializer = class // It will use the TProtocol specified by the factory that is passed in. constructor Create( const factory : IProtocolFactory); overload; + // Create a new TDeserializer. + // It will use the TProtocol and layered transports specified by the factories that are passed in. + constructor Create( const protfact : IProtocolFactory; const transfact : ITransportFactory); overload; + // DTOR destructor Destroy; override; @@ -89,24 +97,37 @@ implementation { TSerializer } -constructor TSerializer.Create(); +constructor TSerializer.Create; // Create a new TSerializer that uses the TBinaryProtocol by default. begin //no inherited; - Create( TBinaryProtocolImpl.TFactory.Create); + Create( TBinaryProtocolImpl.TFactory.Create, nil); end; constructor TSerializer.Create( const factory : IProtocolFactory); // Create a new TSerializer. // It will use the TProtocol specified by the factory that is passed in. +begin + //no inherited; + Create( factory, nil); +end; + + +constructor TSerializer.Create( const protfact : IProtocolFactory; const transfact : ITransportFactory); +// Create a new TSerializer. +// It will use the TProtocol specified by the factory that is passed in. var adapter : IThriftStream; begin inherited Create; FStream := TMemoryStream.Create; adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE); FTransport := TStreamTransportImpl.Create( nil, adapter); - FProtocol := factory.GetProtocol( FTransport); + if transfact <> nil then FTransport := transfact.GetTransport( FTransport); + FProtocol := protfact.GetProtocol( FTransport); + + if not FTransport.IsOpen + then FTransport.Open; end; @@ -131,6 +152,8 @@ function TSerializer.Serialize( const input : IBase) : TBytes; try FStream.Size := 0; input.Write( FProtocol); + FTransport.Flush; + SetLength( result, FStream.Size); iBytes := Length(result); if iBytes > 0 @@ -150,6 +173,8 @@ procedure TSerializer.Serialize( const input : IBase; const aStm : TStream); try FStream.Size := 0; input.Write( FProtocol); + FTransport.Flush; + aStm.CopyFrom( FStream, COPY_ENTIRE_STREAM); finally FStream.Size := 0; // free any allocated memory @@ -160,24 +185,37 @@ procedure TSerializer.Serialize( const input : IBase; const aStm : TStream); { TDeserializer } -constructor TDeserializer.Create(); +constructor TDeserializer.Create; // Create a new TDeserializer that uses the TBinaryProtocol by default. begin //no inherited; - Create( TBinaryProtocolImpl.TFactory.Create); + Create( TBinaryProtocolImpl.TFactory.Create, nil); end; constructor TDeserializer.Create( const factory : IProtocolFactory); // Create a new TDeserializer. // It will use the TProtocol specified by the factory that is passed in. +begin + //no inherited; + Create( factory, nil); +end; + + +constructor TDeserializer.Create( const protfact : IProtocolFactory; const transfact : ITransportFactory); +// Create a new TDeserializer. +// It will use the TProtocol specified by the factory that is passed in. var adapter : IThriftStream; begin inherited Create; FStream := TMemoryStream.Create; adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE); FTransport := TStreamTransportImpl.Create( adapter, nil); - FProtocol := factory.GetProtocol( FTransport); + if transfact <> nil then FTransport := transfact.GetTransport( FTransport); + FProtocol := protfact.GetProtocol( FTransport); + + if not FTransport.IsOpen + then FTransport.Open; end; diff --git a/lib/delphi/src/Thrift.Server.pas b/lib/delphi/src/Thrift.Server.pas index c9365c6db11..654ab99425f 100644 --- a/lib/delphi/src/Thrift.Server.pas +++ b/lib/delphi/src/Thrift.Server.pas @@ -61,7 +61,7 @@ TServerImpl = class abstract( TInterfacedObject, IServer ) public type TLogDelegate = reference to procedure( const str: string); - protected + strict protected FProcessor : IProcessor; FServerTransport : IServerTransport; FInputTransportFactory : ITransportFactory; diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index 3067bcd76e3..bede57cd87d 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -200,7 +200,7 @@ TServerTransportImpl = class( TInterfacedObject, IServerTransport) end; TTransportFactoryImpl = class( TInterfacedObject, ITransportFactory) - function GetTransport( const ATrans: ITransport): ITransport; virtual; + function GetTransport( const aTransport: ITransport): ITransport; virtual; end; TTcpSocketStreamImpl = class( TThriftStreamImpl ) @@ -253,17 +253,19 @@ TStreamTransportImpl = class( TTransportImpl, IStreamTransport) function GetInputStream: IThriftStream; function GetOutputStream: IThriftStream; - public - property InputStream : IThriftStream read GetInputStream; - property OutputStream : IThriftStream read GetOutputStream; + protected procedure Open; override; procedure Close; override; procedure Flush; override; function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; - constructor Create( const AInputStream : IThriftStream; const AOutputStream : IThriftStream); + public + constructor Create( const aInputStream, aOutputStream : IThriftStream); destructor Destroy; override; + + property InputStream : IThriftStream read GetInputStream; + property OutputStream : IThriftStream read GetOutputStream; end; TBufferedStreamImpl = class( TThriftStreamImpl) @@ -281,7 +283,7 @@ TBufferedStreamImpl = class( TThriftStreamImpl) function IsOpen: Boolean; override; function ToArray: TBytes; override; public - constructor Create( const AStream: IThriftStream; ABufSize: Integer); + constructor Create( const aStream: IThriftStream; const aBufSize : Integer); destructor Destroy; override; end; @@ -300,11 +302,11 @@ TServerSocketImpl = class( TServerTransportImpl) function Accept( const fnAccepting: TProc) : ITransport; override; public {$IFDEF OLD_SOCKETS} - constructor Create( const AServer: TTcpServer; AClientTimeout: Integer = 0); overload; - constructor Create( APort: Integer; AClientTimeout: Integer = 0; AUseBufferedSockets: Boolean = FALSE); overload; + constructor Create( const aServer: TTcpServer; const aClientTimeout: Integer = 0); overload; + constructor Create( const aPort: Integer; const aClientTimeout: Integer = 0; const aUseBufferedSockets: Boolean = FALSE); overload; {$ELSE} - constructor Create( const AServer: TServerSocket; AClientTimeout: Longword = 0); overload; - constructor Create( APort: Integer; AClientTimeout: Longword = 0; AUseBufferedSockets: Boolean = FALSE); overload; + constructor Create( const aServer: TServerSocket; const aClientTimeout: Longword = 0); overload; + constructor Create( const aPort: Integer; const aClientTimeout: Longword = 0; const aUseBufferedSockets: Boolean = FALSE); overload; {$ENDIF} destructor Destroy; override; procedure Listen; override; @@ -324,12 +326,17 @@ TBufferedTransportImpl = class( TTransportImpl ) function GetIsOpen: Boolean; override; procedure Flush; override; public + type + TFactory = class( TTransportFactoryImpl ) + public + function GetTransport( const aTransport: ITransport): ITransport; override; + end; + + constructor Create( const aTransport : IStreamTransport; const aBufSize: Integer = 1024); procedure Open(); override; procedure Close(); override; function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; - constructor Create( const ATransport : IStreamTransport ); overload; - constructor Create( const ATransport : IStreamTransport; ABufSize: Integer); overload; property UnderlyingTransport: ITransport read GetUnderlyingTransport; property IsOpen: Boolean read GetIsOpen; end; @@ -356,11 +363,11 @@ TSocketImpl = class(TStreamTransportImpl) public procedure Open; override; {$IFDEF OLD_SOCKETS} - constructor Create( const AClient : TCustomIpClient; aOwnsClient : Boolean; ATimeout: Integer = 0); overload; - constructor Create( const AHost: string; APort: Integer; ATimeout: Integer = 0); overload; + constructor Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer = 0); overload; + constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Integer = 0); overload; {$ELSE} - constructor Create(const AClient: TSocket; aOwnsClient: Boolean); overload; - constructor Create( const AHost: string; APort: Integer; ATimeout: Longword = 0); overload; + constructor Create( const aClient: TSocket; const aOwnsClient: Boolean); overload; + constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Longword = 0); overload; {$ENDIF} destructor Destroy; override; procedure Close; override; @@ -387,16 +394,6 @@ TFramedTransportImpl = class( TTransportImpl) procedure InitMaxFrameSize; procedure InitWriteBuffer; procedure ReadFrame; - public - type - TFactory = class( TTransportFactoryImpl ) - public - function GetTransport( const ATrans: ITransport): ITransport; override; - end; - - constructor Create; overload; - constructor Create( const ATrans: ITransport); overload; - destructor Destroy; override; procedure Open(); override; function GetIsOpen: Boolean; override; @@ -405,6 +402,15 @@ TFactory = class( TTransportFactoryImpl ) function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; procedure Flush; override; + public + type + TFactory = class( TTransportFactoryImpl ) + public + function GetTransport( const aTransport: ITransport): ITransport; override; + end; + + constructor Create( const aTransport: ITransport); overload; + destructor Destroy; override; end; @@ -412,10 +418,9 @@ TFactory = class( TTransportFactoryImpl ) DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms DEFAULT_THRIFT_SECUREPROTOCOLS = [ TSecureProtocol.TLS_1_1, TSecureProtocol.TLS_1_2]; - - implementation + { TTransportImpl } procedure TTransportImpl.Flush; @@ -442,18 +447,6 @@ function TTransportImpl.ReadAll(var buf: TBytes; off: Integer; len: Integer): In else result := 0; end; -procedure TTransportImpl.Write( const buf: TBytes); -begin - if Length(buf) > 0 - then Write( @buf[0], 0, Length(buf)); -end; - -procedure TTransportImpl.Write( const buf: TBytes; off: Integer; len: Integer); -begin - if Length(buf) > 0 - then Write( @buf[0], off, len); -end; - function TTransportImpl.ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; var ret : Integer; begin @@ -466,11 +459,24 @@ function TTransportImpl.ReadAll(const pBuf : Pointer; const buflen : Integer; of end; end; +procedure TTransportImpl.Write( const buf: TBytes); +begin + if Length(buf) > 0 + then Write( @buf[0], 0, Length(buf)); +end; + +procedure TTransportImpl.Write( const buf: TBytes; off: Integer; len: Integer); +begin + if Length(buf) > 0 + then Write( @buf[0], off, len); +end; + procedure TTransportImpl.Write( const pBuf : Pointer; len : Integer); begin Self.Write( pBuf, 0, len); end; + { TTransportException } constructor TTransportException.HiddenCreate(const Msg: string); @@ -478,17 +484,17 @@ constructor TTransportException.HiddenCreate(const Msg: string); inherited Create(Msg); end; -class function TTransportException.Create(AType: TExceptionType): TTransportException; +class function TTransportException.Create(aType: TExceptionType): TTransportException; begin //no inherited; {$WARN SYMBOL_DEPRECATED OFF} - Result := Create(AType, '') + Result := Create(aType, '') {$WARN SYMBOL_DEPRECATED DEFAULT} end; class function TTransportException.Create(aType: TExceptionType; const msg: string): TTransportException; begin - case AType of + case aType of TExceptionType.NotOpen: Result := TTransportExceptionNotOpen.Create(msg); TExceptionType.AlreadyOpen: Result := TTransportExceptionAlreadyOpen.Create(msg); TExceptionType.TimedOut: Result := TTransportExceptionTimedOut.Create(msg); @@ -557,40 +563,44 @@ class function TTransportExceptionCorruptedData.GetType: TTransportException.TEx { TTransportFactoryImpl } -function TTransportFactoryImpl.GetTransport( const ATrans: ITransport): ITransport; +function TTransportFactoryImpl.GetTransport( const aTransport: ITransport): ITransport; begin - Result := ATrans; + Result := aTransport; end; { TServerSocket } {$IFDEF OLD_SOCKETS} -constructor TServerSocketImpl.Create( const AServer: TTcpServer; AClientTimeout: Integer); -begin - inherited Create; - FServer := AServer; - FClientTimeout := AClientTimeout; -end; +constructor TServerSocketImpl.Create( const aServer: TTcpServer; const aClientTimeout : Integer); {$ELSE} -constructor TServerSocketImpl.Create( const AServer: TServerSocket; AClientTimeout: Longword); +constructor TServerSocketImpl.Create( const aServer: TServerSocket; const aClientTimeout: Longword); +{$ENDIF} begin inherited Create; - FServer := AServer; - FServer.RecvTimeout := AClientTimeout; - FServer.SendTimeout := AClientTimeout; -end; + FServer := aServer; + +{$IFDEF OLD_SOCKETS} + FClientTimeout := aClientTimeout; +{$ELSE} + FServer.RecvTimeout := aClientTimeout; + FServer.SendTimeout := aClientTimeout; {$ENDIF} +end; + {$IFDEF OLD_SOCKETS} -constructor TServerSocketImpl.Create(APort, AClientTimeout: Integer; AUseBufferedSockets: Boolean); +constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Integer; const aUseBufferedSockets: Boolean); {$ELSE} -constructor TServerSocketImpl.Create(APort: Integer; AClientTimeout: Longword; AUseBufferedSockets: Boolean); +constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Longword; const aUseBufferedSockets: Boolean); {$ENDIF} begin inherited Create; + {$IFDEF OLD_SOCKETS} - FPort := APort; - FClientTimeout := AClientTimeout; + FPort := aPort; + FClientTimeout := aClientTimeout; + + FOwnsServer := True; FServer := TTcpServer.Create( nil ); FServer.BlockMode := bmBlocking; {$IF CompilerVersion >= 21.0} @@ -599,10 +609,11 @@ constructor TServerSocketImpl.Create(APort: Integer; AClientTimeout: Longword; A FServer.LocalPort := IntToStr( FPort); {$IFEND} {$ELSE} - FServer := TServerSocket.Create(APort, AClientTimeout, AClientTimeout); -{$ENDIF} - FUseBufferedSocket := AUseBufferedSockets; FOwnsServer := True; + FServer := TServerSocket.Create(aPort, aClientTimeout, aClientTimeout); +{$ENDIF} + + FUseBufferedSocket := aUseBufferedSockets; end; destructor TServerSocketImpl.Destroy; @@ -665,7 +676,7 @@ function TServerSocketImpl.Accept( const fnAccepting: TProc): ITransport; client := FServer.Accept; try - trans := TSocketImpl.Create(client, True); + trans := TSocketImpl.Create(client, MaxMessageSize, True); client := nil; if FUseBufferedSocket then @@ -714,37 +725,35 @@ procedure TServerSocketImpl.Close; { TSocket } {$IFDEF OLD_SOCKETS} -constructor TSocketImpl.Create( const AClient : TCustomIpClient; aOwnsClient : Boolean; ATimeout: Integer = 0); +constructor TSocketImpl.Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer); +{$ELSE} +constructor TSocketImpl.Create(const aClient: TSocket; const aOwnsClient: Boolean); +{$ENDIF} var stream : IThriftStream; begin - FClient := AClient; - FTimeout := ATimeout; + FClient := aClient; FOwnsClient := aOwnsClient; + +{$IFDEF OLD_SOCKETS} + FTimeout := aTimeout; +{$ELSE} + FTimeout := aClient.RecvTimeout; +{$ENDIF} + stream := TTcpSocketStreamImpl.Create( FClient, FTimeout); inherited Create( stream, stream); end; -{$ELSE} -constructor TSocketImpl.Create(const AClient: TSocket; aOwnsClient: Boolean); -var stream : IThriftStream; -begin - FClient := AClient; - FTimeout := AClient.RecvTimeout; - FOwnsClient := aOwnsClient; - stream := TTcpSocketStreamImpl.Create(FClient, FTimeout); - inherited Create(stream, stream); -end; -{$ENDIF} {$IFDEF OLD_SOCKETS} -constructor TSocketImpl.Create(const AHost: string; APort, ATimeout: Integer); +constructor TSocketImpl.Create(const aHost: string; const aPort, aTimeout: Integer); {$ELSE} -constructor TSocketImpl.Create(const AHost: string; APort: Integer; ATimeout: Longword); +constructor TSocketImpl.Create(const aHost: string; const aPort : Integer; const aTimeout: Longword); {$ENDIF} begin inherited Create(nil,nil); - FHost := AHost; - FPort := APort; - FTimeout := ATimeout; + FHost := aHost; + FPort := aPort; + FTimeout := aTimeout; InitSocket; end; @@ -839,11 +848,11 @@ procedure TBufferedStreamImpl.Close; FWriteBuffer := nil; end; -constructor TBufferedStreamImpl.Create( const AStream: IThriftStream; ABufSize: Integer); +constructor TBufferedStreamImpl.Create( const aStream: IThriftStream; const aBufSize : Integer); begin inherited Create; - FStream := AStream; - FBufSize := ABufSize; + FStream := aStream; + FBufSize := aBufSize; FReadBuffer := TMemoryStream.Create; FWriteBuffer := TMemoryStream.Create; end; @@ -918,6 +927,7 @@ function TBufferedStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; end; end; + function TBufferedStreamImpl.ToArray: TBytes; var len : Integer; begin @@ -953,11 +963,11 @@ procedure TBufferedStreamImpl.Write( const pBuf : Pointer; offset: Integer; coun { TStreamTransportImpl } -constructor TStreamTransportImpl.Create( const AInputStream : IThriftStream; const AOutputStream : IThriftStream); +constructor TStreamTransportImpl.Create( const aInputStream, aOutputStream : IThriftStream); begin inherited Create; - FInputStream := AInputStream; - FOutputStream := AOutputStream; + FInputStream := aInputStream; + FOutputStream := aOutputStream; end; destructor TStreamTransportImpl.Destroy; @@ -1004,35 +1014,29 @@ procedure TStreamTransportImpl.Open; function TStreamTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; begin - if FInputStream = nil then begin - raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' ); - end; + if FInputStream = nil + then raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' ); Result := FInputStream.Read( pBuf,buflen, off, len ); end; procedure TStreamTransportImpl.Write( const pBuf : Pointer; off, len : Integer); begin - if FOutputStream = nil then begin - raise TTransportExceptionNotOpen.Create('Cannot write to null outputstream' ); - end; + if FOutputStream = nil + then raise TTransportExceptionNotOpen.Create('Cannot write to null outputstream' ); FOutputStream.Write( pBuf, off, len ); end; -{ TBufferedTransportImpl } -constructor TBufferedTransportImpl.Create( const ATransport: IStreamTransport); -begin - //no inherited; - Create( ATransport, 1024 ); -end; +{ TBufferedTransportImpl } -constructor TBufferedTransportImpl.Create( const ATransport: IStreamTransport; ABufSize: Integer); +constructor TBufferedTransportImpl.Create( const aTransport : IStreamTransport; const aBufSize: Integer); begin + ASSERT( aTransport <> nil); inherited Create; - FTransport := ATransport; - FBufSize := ABufSize; + FTransport := aTransport; + FBufSize := aBufSize; InitBuffers; end; @@ -1040,7 +1044,7 @@ procedure TBufferedTransportImpl.Close; begin FTransport.Close; FInputBuffer := nil; - FOutputBuffer := nil; + FOutputBuffer := nil; end; procedure TBufferedTransportImpl.Flush; @@ -1078,10 +1082,9 @@ procedure TBufferedTransportImpl.Open; function TBufferedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; begin - Result := 0; - if FInputBuffer <> nil then begin - Result := FInputBuffer.Read( pBuf,buflen, off, len ); - end; + if FInputBuffer <> nil + then Result := FInputBuffer.Read( pBuf,buflen, off, len) + else Result := 0; end; procedure TBufferedTransportImpl.Write( const pBuf : Pointer; off, len : Integer); @@ -1091,23 +1094,24 @@ procedure TBufferedTransportImpl.Write( const pBuf : Pointer; off, len : Integer end; end; -{ TFramedTransportImpl } +{ TBufferedTransportImpl.TFactory } -constructor TFramedTransportImpl.Create; +function TBufferedTransportImpl.TFactory.GetTransport( const aTransport: ITransport): ITransport; begin - inherited Create; - - InitMaxFrameSize; - InitWriteBuffer; + Result := TFramedTransportImpl.Create( aTransport); end; -constructor TFramedTransportImpl.Create( const ATrans: ITransport); + +{ TFramedTransportImpl } + +constructor TFramedTransportImpl.Create( const aTransport: ITransport); begin + ASSERT( aTransport <> nil); inherited Create; InitMaxFrameSize; InitWriteBuffer; - FTransport := ATrans; + FTransport := aTransport; end; destructor TFramedTransportImpl.Destroy; @@ -1189,9 +1193,7 @@ function TFramedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer if (FReadBuffer <> nil) and (len > 0) then begin result := FReadBuffer.Read( pTmp^, len); - if result > 0 then begin - Exit; - end; + if result > 0 then Exit; end; ReadFrame; @@ -1225,7 +1227,8 @@ procedure TFramedTransportImpl.ReadFrame; SetLength( buff, size ); FTransport.ReadAll( buff, 0, size ); - FReadBuffer.Free; + + FreeAndNil( FReadBuffer); FReadBuffer := TMemoryStream.Create; if Length(buff) > 0 then FReadBuffer.Write( Pointer(@buff[0])^, size ); @@ -1243,11 +1246,12 @@ procedure TFramedTransportImpl.Write( const pBuf : Pointer; off, len : Integer); end; end; + { TFramedTransport.TFactory } -function TFramedTransportImpl.TFactory.GetTransport( const ATrans: ITransport): ITransport; +function TFramedTransportImpl.TFactory.GetTransport( const aTransport: ITransport): ITransport; begin - Result := TFramedTransportImpl.Create( ATrans ); + Result := TFramedTransportImpl.Create( aTransport); end; { TTcpSocketStreamImpl } @@ -1258,17 +1262,17 @@ procedure TTcpSocketStreamImpl.Close; end; {$IFDEF OLD_SOCKETS} -constructor TTcpSocketStreamImpl.Create( const ATcpClient: TCustomIpClient; const aTimeout : Integer); +constructor TTcpSocketStreamImpl.Create( const aTcpClient: TCustomIpClient; const aTimeout : Integer); begin inherited Create; - FTcpClient := ATcpClient; + FTcpClient := aTcpClient; FTimeout := aTimeout; end; {$ELSE} -constructor TTcpSocketStreamImpl.Create( const ATcpClient: TSocket; const aTimeout : Longword); +constructor TTcpSocketStreamImpl.Create( const aTcpClient: TSocket; const aTimeout : Longword); begin inherited Create; - FTcpClient := ATcpClient; + FTcpClient := aTcpClient; if aTimeout = 0 then FTcpClient.RecvTimeout := SLEEP_TIME else @@ -1574,12 +1578,5 @@ procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integ {$ENDIF} -{$IF CompilerVersion < 21.0} -initialization -begin - TFramedTransportImpl_Initialize; -end; -{$IFEND} - end. diff --git a/lib/delphi/test/serializer/TestSerializer.Tests.pas b/lib/delphi/test/serializer/TestSerializer.Tests.pas new file mode 100644 index 00000000000..ec8d86db802 --- /dev/null +++ b/lib/delphi/test/serializer/TestSerializer.Tests.pas @@ -0,0 +1,329 @@ +unit TestSerializer.Tests; +(* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 + +uses + Classes, + Windows, + SysUtils, + Generics.Collections, + Thrift, + Thrift.Exception, + Thrift.Socket, + Thrift.Transport, + Thrift.Protocol, + Thrift.Protocol.JSON, + Thrift.Protocol.Compact, + Thrift.Collections, + Thrift.Server, + Thrift.Utils, + Thrift.Serializer, + Thrift.Stream, + Thrift.WinHTTP, + Thrift.TypeRegistry, + System_, + DebugProtoTest, + TestSerializer.Data; + + +type + TFactoryPair = record + prot : IProtocolFactory; + trans : ITransportFactory; + end; + + TTestSerializer = class //extends TestCase { + private type + TMethod = ( + mt_Bytes, + mt_Stream + ); + + private + FProtocols : TList< TFactoryPair>; + procedure AddFactoryCombination( const aProto : IProtocolFactory; const aTrans : ITransportFactory); + class function UserFriendlyName( const factory : TFactoryPair) : string; overload; + class function UserFriendlyName( const method : TMethod) : string; overload; + + class function Serialize(const input : IBase; const factory : TFactoryPair) : TBytes; overload; + class procedure Serialize(const input : IBase; const factory : TFactoryPair; const aStream : TStream); overload; + + class procedure Deserialize( const input : TBytes; const target : IBase; const factory : TFactoryPair); overload; + class procedure Deserialize( const input : TStream; const target : IBase; const factory : TFactoryPair); overload; + + procedure Test_Serializer_Deserializer; + procedure Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); + procedure Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); + + public + constructor Create; + destructor Destroy; override; + + procedure RunTests; + end; + + +implementation + + +{ TTestSerializer } + +constructor TTestSerializer.Create; +begin + inherited Create; + FProtocols := TList< TFactoryPair>.Create; + + AddFactoryCombination( TBinaryProtocolImpl.TFactory.Create, nil); + AddFactoryCombination( TCompactProtocolImpl.TFactory.Create, nil); + AddFactoryCombination( TJSONProtocolImpl.TFactory.Create, nil); + + AddFactoryCombination( TBinaryProtocolImpl.TFactory.Create, TFramedTransportImpl.TFactory.Create); + AddFactoryCombination( TCompactProtocolImpl.TFactory.Create, TFramedTransportImpl.TFactory.Create); + AddFactoryCombination( TJSONProtocolImpl.TFactory.Create, TFramedTransportImpl.TFactory.Create); + + AddFactoryCombination( TBinaryProtocolImpl.TFactory.Create, TBufferedTransportImpl.TFactory.Create); + AddFactoryCombination( TCompactProtocolImpl.TFactory.Create, TBufferedTransportImpl.TFactory.Create); + AddFactoryCombination( TJSONProtocolImpl.TFactory.Create, TBufferedTransportImpl.TFactory.Create); +end; + + +destructor TTestSerializer.Destroy; +begin + try + FreeAndNil( FProtocols); + finally + inherited Destroy; + end; +end; + + +procedure TTestSerializer.AddFactoryCombination( const aProto : IProtocolFactory; const aTrans : ITransportFactory); +var rec : TFactoryPair; +begin + rec.prot := aProto; + rec.trans := aTrans; + FProtocols.Add( rec); +end; + + +procedure TTestSerializer.Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); +var tested, correct : IOneOfEach; + bytes : TBytes; + i : Integer; +begin + // write + tested := Fixtures.CreateOneOfEach; + case method of + mt_Bytes: bytes := Serialize( tested, factory); + mt_Stream: begin + stream.Size := 0; + Serialize( tested, factory, stream); + end + else + ASSERT( FALSE); + end; + + // init + read + tested := TOneOfEachImpl.Create; + case method of + mt_Bytes: Deserialize( bytes, tested, factory); + mt_Stream: begin + stream.Position := 0; + Deserialize( stream, tested, factory); + end + else + ASSERT( FALSE); + end; + + // check + correct := Fixtures.CreateOneOfEach; + ASSERT( tested.Im_true = correct.Im_true); + ASSERT( tested.Im_false = correct.Im_false); + ASSERT( tested.A_bite = correct.A_bite); + ASSERT( tested.Integer16 = correct.Integer16); + ASSERT( tested.Integer32 = correct.Integer32); + ASSERT( tested.Integer64 = correct.Integer64); + ASSERT( Abs( tested.Double_precision - correct.Double_precision) < 1E-12); + ASSERT( tested.Some_characters = correct.Some_characters); + ASSERT( tested.Zomg_unicode = correct.Zomg_unicode); + ASSERT( tested.What_who = correct.What_who); + + ASSERT( Length(tested.Base64) = Length(correct.Base64)); + ASSERT( CompareMem( @tested.Base64[0], @correct.Base64[0], Length(correct.Base64))); + + ASSERT( tested.Byte_list.Count = correct.Byte_list.Count); + for i := 0 to tested.Byte_list.Count-1 + do ASSERT( tested.Byte_list[i] = correct.Byte_list[i]); + + ASSERT( tested.I16_list.Count = correct.I16_list.Count); + for i := 0 to tested.I16_list.Count-1 + do ASSERT( tested.I16_list[i] = correct.I16_list[i]); + + ASSERT( tested.I64_list.Count = correct.I64_list.Count); + for i := 0 to tested.I64_list.Count-1 + do ASSERT( tested.I64_list[i] = correct.I64_list[i]); +end; + + +procedure TTestSerializer.Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); +var tested, correct : ICompactProtoTestStruct; + bytes : TBytes; +begin + // write + tested := Fixtures.CreateCompactProtoTestStruct; + case method of + mt_Bytes: bytes := Serialize( tested, factory); + mt_Stream: begin + stream.Size := 0; + Serialize( tested, factory, stream); + end + else + ASSERT( FALSE); + end; + + // init + read + correct := TCompactProtoTestStructImpl.Create; + case method of + mt_Bytes: Deserialize( bytes, tested, factory); + mt_Stream: begin + stream.Position := 0; + Deserialize( stream, tested, factory); + end + else + ASSERT( FALSE); + end; + + // check + correct := Fixtures.CreateCompactProtoTestStruct; + ASSERT( correct.Field500 = tested.Field500); + ASSERT( correct.Field5000 = tested.Field5000); + ASSERT( correct.Field20000 = tested.Field20000); +end; + + +procedure TTestSerializer.Test_Serializer_Deserializer; +var factory : TFactoryPair; + stream : TFileStream; + method : TMethod; +begin + stream := TFileStream.Create( 'TestSerializer.dat', fmCreate); + try + for method in [Low(TMethod)..High(TMethod)] do begin + Writeln( UserFriendlyName(method)); + + for factory in FProtocols do begin + Writeln('- '+UserFriendlyName(factory)); + + Test_OneOfEach( method, factory, stream); + Test_CompactStruct( method, factory, stream); + end; + + Writeln; + end; + + finally + stream.Free; + end; +end; + + +class function TTestSerializer.UserFriendlyName( const factory : TFactoryPair) : string; +begin + result := Copy( (factory.prot as TObject).ClassName, 2, MAXINT); + + if factory.trans <> nil + then result := Copy( (factory.trans as TObject).ClassName, 2, MAXINT) +' '+ result; + + result := StringReplace( result, 'Impl', '', [rfReplaceAll]); + result := StringReplace( result, 'Transport.TFactory', '', [rfReplaceAll]); + result := StringReplace( result, 'Protocol.TFactory', '', [rfReplaceAll]); +end; + + +class function TTestSerializer.UserFriendlyName( const method : TMethod) : string; +begin + result := EnumUtils.ToString(Ord(method)); + result := StringReplace( result, 'mt_', '', [rfReplaceAll]); +end; + + +procedure TTestSerializer.RunTests; +begin + try + Test_Serializer_Deserializer; + except + on e:Exception do begin + Writeln( e.ClassName+': '+ e.Message); + Write('Hit ENTER to close ... '); Readln; + end; + end; +end; + + +class function TTestSerializer.Serialize(const input : IBase; const factory : TFactoryPair) : TBytes; +var serial : TSerializer; +begin + serial := TSerializer.Create( factory.prot, factory.trans); + try + result := serial.Serialize( input); + finally + serial.Free; + end; +end; + + +class procedure TTestSerializer.Serialize(const input : IBase; const factory : TFactoryPair; const aStream : TStream); +var serial : TSerializer; +begin + serial := TSerializer.Create( factory.prot, factory.trans); + try + serial.Serialize( input, aStream); + finally + serial.Free; + end; +end; + + +class procedure TTestSerializer.Deserialize( const input : TBytes; const target : IBase; const factory : TFactoryPair); +var serial : TDeserializer; +begin + serial := TDeserializer.Create( factory.prot, factory.trans); + try + serial.Deserialize( input, target); + finally + serial.Free; + end; +end; + + +class procedure TTestSerializer.Deserialize( const input : TStream; const target : IBase; const factory : TFactoryPair); +var serial : TDeserializer; +begin + serial := TDeserializer.Create( factory.prot, factory.trans); + try + serial.Deserialize( input, target); + finally + serial.Free; + end; +end; + + +end. diff --git a/lib/delphi/test/serializer/TestSerializer.dpr b/lib/delphi/test/serializer/TestSerializer.dpr index 39752cf7095..bb4cc89260d 100644 --- a/lib/delphi/test/serializer/TestSerializer.dpr +++ b/lib/delphi/test/serializer/TestSerializer.dpr @@ -42,235 +42,9 @@ uses Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', System_, DebugProtoTest, + TestSerializer.Tests, TestSerializer.Data; -type - TTestSerializer = class //extends TestCase { - private type - TMethod = ( - mt_Bytes, - mt_Stream - ); - - private - FProtocols : TList< IProtocolFactory>; - - class function Serialize(const input : IBase; const factory : IProtocolFactory) : TBytes; overload; - class procedure Serialize(const input : IBase; const factory : IProtocolFactory; const aStream : TStream); overload; - class procedure Deserialize( const input : TBytes; const target : IBase; const factory : IProtocolFactory); overload; - class procedure Deserialize( const input : TStream; const target : IBase; const factory : IProtocolFactory); overload; - - procedure Test_Serializer_Deserializer; - procedure Test_OneOfEach( const method : TMethod; const factory : IProtocolFactory; const stream : TFileStream); - procedure Test_CompactStruct( const method : TMethod; const factory : IProtocolFactory; const stream : TFileStream); - - public - constructor Create; - destructor Destroy; override; - - procedure RunTests; - end; - - - -{ TTestSerializer } - -constructor TTestSerializer.Create; -begin - inherited Create; - FProtocols := TList< IProtocolFactory>.Create; - FProtocols.Add( TBinaryProtocolImpl.TFactory.Create); - FProtocols.Add( TCompactProtocolImpl.TFactory.Create); - FProtocols.Add( TJSONProtocolImpl.TFactory.Create); -end; - - -destructor TTestSerializer.Destroy; -begin - try - FreeAndNil( FProtocols); - finally - inherited Destroy; - end; -end; - - -procedure TTestSerializer.Test_OneOfEach( const method : TMethod; const factory : IProtocolFactory; const stream : TFileStream); -var tested, correct : IOneOfEach; - bytes : TBytes; - i : Integer; -begin - // write - tested := Fixtures.CreateOneOfEach; - case method of - mt_Bytes: bytes := Serialize( tested, factory); - mt_Stream: begin - stream.Size := 0; - Serialize( tested, factory, stream); - end - else - ASSERT( FALSE); - end; - - // init + read - tested := TOneOfEachImpl.Create; - case method of - mt_Bytes: Deserialize( bytes, tested, factory); - mt_Stream: begin - stream.Position := 0; - Deserialize( stream, tested, factory); - end - else - ASSERT( FALSE); - end; - - // check - correct := Fixtures.CreateOneOfEach; - ASSERT( tested.Im_true = correct.Im_true); - ASSERT( tested.Im_false = correct.Im_false); - ASSERT( tested.A_bite = correct.A_bite); - ASSERT( tested.Integer16 = correct.Integer16); - ASSERT( tested.Integer32 = correct.Integer32); - ASSERT( tested.Integer64 = correct.Integer64); - ASSERT( Abs( tested.Double_precision - correct.Double_precision) < 1E-12); - ASSERT( tested.Some_characters = correct.Some_characters); - ASSERT( tested.Zomg_unicode = correct.Zomg_unicode); - ASSERT( tested.What_who = correct.What_who); - - ASSERT( Length(tested.Base64) = Length(correct.Base64)); - ASSERT( CompareMem( @tested.Base64[0], @correct.Base64[0], Length(correct.Base64))); - - ASSERT( tested.Byte_list.Count = correct.Byte_list.Count); - for i := 0 to tested.Byte_list.Count-1 - do ASSERT( tested.Byte_list[i] = correct.Byte_list[i]); - - ASSERT( tested.I16_list.Count = correct.I16_list.Count); - for i := 0 to tested.I16_list.Count-1 - do ASSERT( tested.I16_list[i] = correct.I16_list[i]); - - ASSERT( tested.I64_list.Count = correct.I64_list.Count); - for i := 0 to tested.I64_list.Count-1 - do ASSERT( tested.I64_list[i] = correct.I64_list[i]); -end; - - -procedure TTestSerializer.Test_CompactStruct( const method : TMethod; const factory : IProtocolFactory; const stream : TFileStream); -var tested, correct : ICompactProtoTestStruct; - bytes : TBytes; -begin - // write - tested := Fixtures.CreateCompactProtoTestStruct; - case method of - mt_Bytes: bytes := Serialize( tested, factory); - mt_Stream: begin - stream.Size := 0; - Serialize( tested, factory, stream); - end - else - ASSERT( FALSE); - end; - - // init + read - correct := TCompactProtoTestStructImpl.Create; - case method of - mt_Bytes: Deserialize( bytes, tested, factory); - mt_Stream: begin - stream.Position := 0; - Deserialize( stream, tested, factory); - end - else - ASSERT( FALSE); - end; - - // check - correct := Fixtures.CreateCompactProtoTestStruct; - ASSERT( correct.Field500 = tested.Field500); - ASSERT( correct.Field5000 = tested.Field5000); - ASSERT( correct.Field20000 = tested.Field20000); -end; - - -procedure TTestSerializer.Test_Serializer_Deserializer; -var factory : IProtocolFactory; - stream : TFileStream; - method : TMethod; -begin - stream := TFileStream.Create( 'TestSerializer.dat', fmCreate); - try - - for method in [Low(TMethod)..High(TMethod)] do begin - for factory in FProtocols do begin - - Test_OneOfEach( method, factory, stream); - Test_CompactStruct( method, factory, stream); - end; - end; - - finally - stream.Free; - end; -end; - - -procedure TTestSerializer.RunTests; -begin - try - Test_Serializer_Deserializer; - except - on e:Exception do begin - Writeln( e.Message); - Write('Hit ENTER to close ... '); Readln; - end; - end; -end; - - -class function TTestSerializer.Serialize(const input : IBase; const factory : IProtocolFactory) : TBytes; -var serial : TSerializer; -begin - serial := TSerializer.Create( factory); - try - result := serial.Serialize( input); - finally - serial.Free; - end; -end; - - -class procedure TTestSerializer.Serialize(const input : IBase; const factory : IProtocolFactory; const aStream : TStream); -var serial : TSerializer; -begin - serial := TSerializer.Create( factory); - try - serial.Serialize( input, aStream); - finally - serial.Free; - end; -end; - - -class procedure TTestSerializer.Deserialize( const input : TBytes; const target : IBase; const factory : IProtocolFactory); -var serial : TDeserializer; -begin - serial := TDeserializer.Create( factory); - try - serial.Deserialize( input, target); - finally - serial.Free; - end; -end; - -class procedure TTestSerializer.Deserialize( const input : TStream; const target : IBase; const factory : IProtocolFactory); -var serial : TDeserializer; -begin - serial := TDeserializer.Create( factory); - try - serial.Deserialize( input, target); - finally - serial.Free; - end; -end; - var test : TTestSerializer; begin From 41f47aff7ccc1a093eb5e48250377c1178babeec Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 9 Nov 2019 23:24:52 +0100 Subject: [PATCH 432/756] THRIFT-5007 Implement MAX_MESSAGE_SIZE and remaining read bytes control Client: Delphi Patch: Jens Geyer This closes #1932 --- lib/delphi/src/Thrift.Processor.Multiplex.pas | 1 + lib/delphi/src/Thrift.Protocol.Compact.pas | 39 ++- lib/delphi/src/Thrift.Protocol.JSON.pas | 41 +++ lib/delphi/src/Thrift.Protocol.pas | 78 +++++- lib/delphi/src/Thrift.Serializer.pas | 25 +- lib/delphi/src/Thrift.Stream.pas | 126 ++++++--- lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas | 17 +- lib/delphi/src/Thrift.Transport.Pipes.pas | 60 +++-- lib/delphi/src/Thrift.Transport.WinHTTP.pas | 46 +++- lib/delphi/src/Thrift.Transport.pas | 254 +++++++++++++++--- lib/delphi/src/Thrift.WinHTTP.pas | 12 +- lib/delphi/test/TestClient.pas | 2 +- lib/delphi/test/TestServer.pas | 2 +- .../test/serializer/TestSerializer.Tests.pas | 39 ++- 14 files changed, 625 insertions(+), 117 deletions(-) diff --git a/lib/delphi/src/Thrift.Processor.Multiplex.pas b/lib/delphi/src/Thrift.Processor.Multiplex.pas index 622f730f2af..ba77d946446 100644 --- a/lib/delphi/src/Thrift.Processor.Multiplex.pas +++ b/lib/delphi/src/Thrift.Processor.Multiplex.pas @@ -132,6 +132,7 @@ destructor TMultiplexedProcessorImpl.Destroy; function TMultiplexedProcessorImpl.TStoredMessageProtocol.ReadMessageBegin: TThriftMessage; begin + Reset; result := FMessageBegin; end; diff --git a/lib/delphi/src/Thrift.Protocol.Compact.pas b/lib/delphi/src/Thrift.Protocol.Compact.pas index 866bd26e3fd..109e660644c 100644 --- a/lib/delphi/src/Thrift.Protocol.Compact.pas +++ b/lib/delphi/src/Thrift.Protocol.Compact.pas @@ -133,8 +133,6 @@ TFactory = class( TInterfacedObject, IProtocolFactory) constructor Create(const trans : ITransport); destructor Destroy; override; - procedure Reset; - strict private procedure WriteByteDirect( const b : Byte); overload; @@ -172,7 +170,7 @@ TFactory = class( TInterfacedObject, IProtocolFactory) procedure WriteDouble( const dub: Double); override; procedure WriteBinary( const b: TBytes); overload; override; - private + private // unit visible stuff class function DoubleToInt64Bits( const db : Double) : Int64; class function Int64BitsToDouble( const i64 : Int64) : Double; @@ -193,6 +191,10 @@ TFactory = class( TInterfacedObject, IProtocolFactory) //Convert a Int64 into little-endian bytes in buf starting at off and going until off+7. class procedure fixedLongToBytes( const n : Int64; var buf : TBytes); + strict protected + function GetMinSerializedSize( const aType : TType) : Integer; override; + procedure Reset; override; + public function ReadMessageBegin: TThriftMessage; override; procedure ReadMessageEnd(); override; @@ -291,6 +293,7 @@ destructor TCompactProtocolImpl.Destroy; procedure TCompactProtocolImpl.Reset; begin + inherited Reset; lastField_.Clear(); lastFieldId_ := 0; Init( booleanField_, '', TType.Stop, 0); @@ -735,6 +738,7 @@ function TCompactProtocolImpl.ReadMapBegin: TThriftMap; val := getTType( Byte( keyAndValueType and $F)); Init( result, key, val, size); ASSERT( (result.KeyType = key) and (result.ValueType = val)); + CheckReadBytesAvailable(result); end; @@ -755,6 +759,7 @@ function TCompactProtocolImpl.ReadListBegin: TThriftList; type_ := getTType( size_and_type); Init( result, type_, size); + CheckReadBytesAvailable(result); end; @@ -775,6 +780,7 @@ function TCompactProtocolImpl.ReadSetBegin: TThriftSet; type_ := getTType( size_and_type); Init( result, type_, size); + CheckReadBytesAvailable(result); end; @@ -836,6 +842,7 @@ function TCompactProtocolImpl.ReadBinary: TBytes; var length : Integer; begin length := Integer( ReadVarint32); + FTrans.CheckReadBytesAvailable(length); SetLength( result, length); if (length > 0) then Transport.ReadAll( result, 0, length); @@ -968,6 +975,32 @@ class function TCompactProtocolImpl.getCompactType( const ttype : TType) : Byte; end; +function TCompactProtocolImpl.GetMinSerializedSize( const aType : TType) : Integer; +// Return the minimum number of bytes a type will consume on the wire +begin + case aType of + TType.Stop: result := 0; + TType.Void: result := 0; + TType.Bool_: result := SizeOf(Byte); + TType.Byte_: result := SizeOf(Byte); + TType.Double_: result := 8; // uses fixedLongToBytes() which always writes 8 bytes + TType.I16: result := SizeOf(Byte); + TType.I32: result := SizeOf(Byte); + TType.I64: result := SizeOf(Byte); + TType.String_: result := SizeOf(Byte); // string length + TType.Struct: result := 0; // empty struct + TType.Map: result := SizeOf(Byte); // element count + TType.Set_: result := SizeOf(Byte); // element count + TType.List: result := SizeOf(Byte); // element count + else + raise TTransportExceptionBadArgs.Create('Unhandled type code'); + end; +end; + + + + + //--- unit tests ------------------------------------------- {$IFDEF Debug} diff --git a/lib/delphi/src/Thrift.Protocol.JSON.pas b/lib/delphi/src/Thrift.Protocol.JSON.pas index 85cb973f9b6..e72a81dcf90 100644 --- a/lib/delphi/src/Thrift.Protocol.JSON.pas +++ b/lib/delphi/src/Thrift.Protocol.JSON.pas @@ -132,6 +132,10 @@ TLookaheadReader = class procedure PushContext( const aCtx : TJSONBaseContext); procedure PopContext; + strict protected + function GetMinSerializedSize( const aType : TType) : Integer; override; + procedure Reset; override; + public // TJSONProtocolImpl Constructor constructor Create( const aTrans : ITransport); @@ -480,6 +484,13 @@ destructor TJSONProtocolImpl.Destroy; end; +procedure TJSONProtocolImpl.Reset; +begin + inherited Reset; + ResetContextStack; +end; + + procedure TJSONProtocolImpl.ResetContextStack; begin while FContextStack.Count > 0 @@ -683,6 +694,7 @@ procedure TJSONProtocolImpl.WriteJSONArrayEnd; procedure TJSONProtocolImpl.WriteMessageBegin( const aMsg : TThriftMessage); begin + Reset; ResetContextStack; // THRIFT-1473 WriteJSONArrayStart; @@ -1053,6 +1065,7 @@ procedure TJSONProtocolImpl.ReadJSONArrayEnd; function TJSONProtocolImpl.ReadMessageBegin: TThriftMessage; begin + Reset; ResetContextStack; // THRIFT-1473 Init( result); @@ -1123,6 +1136,8 @@ function TJSONProtocolImpl.ReadMapBegin : TThriftMap; result.ValueType := GetTypeIDForTypeName( str); result.Count := ReadJSONInteger; + CheckReadBytesAvailable(result); + ReadJSONObjectStart; end; @@ -1143,6 +1158,7 @@ function TJSONProtocolImpl.ReadListBegin : TThriftList; str := SysUtils.TEncoding.UTF8.GetString( ReadJSONString(FALSE)); result.ElementType := GetTypeIDForTypeName( str); result.Count := ReadJSONInteger; + CheckReadBytesAvailable(result); end; @@ -1161,6 +1177,7 @@ function TJSONProtocolImpl.ReadSetBegin : TThriftSet; str := SysUtils.TEncoding.UTF8.GetString( ReadJSONString(FALSE)); result.ElementType := GetTypeIDForTypeName( str); result.Count := ReadJSONInteger; + CheckReadBytesAvailable(result); end; @@ -1218,6 +1235,30 @@ function TJSONProtocolImpl.ReadBinary : TBytes; end; +function TJSONProtocolImpl.GetMinSerializedSize( const aType : TType) : Integer; +// Return the minimum number of bytes a type will consume on the wire +begin + case aType of + TType.Stop: result := 0; + TType.Void: result := 0; + TType.Bool_: result := 1; + TType.Byte_: result := 1; + TType.Double_: result := 1; + TType.I16: result := 1; + TType.I32: result := 1; + TType.I64: result := 1; + TType.String_: result := 2; // empty string + TType.Struct: result := 2; // empty struct + TType.Map: result := 2; // empty map + TType.Set_: result := 2; // empty set + TType.List: result := 2; // empty list + else + raise TTransportExceptionBadArgs.Create('Unhandled type code'); + end; +end; + + + //--- init code --- procedure InitBytes( var b : TBytes; aData : array of Byte); diff --git a/lib/delphi/src/Thrift.Protocol.pas b/lib/delphi/src/Thrift.Protocol.pas index 7c802214d91..94e6e186351 100644 --- a/lib/delphi/src/Thrift.Protocol.pas +++ b/lib/delphi/src/Thrift.Protocol.pas @@ -196,7 +196,7 @@ TProtocolRecursionTrackerImpl = class abstract( TInterfacedObject, IProtocolRe end; IProtocol = interface - ['{602A7FFB-0D9E-4CD8-8D7F-E5076660588A}'] + ['{7F3640D7-5082-49E7-B562-84202F323C3A}'] function GetTransport: ITransport; procedure WriteMessageBegin( const msg: TThriftMessage); procedure WriteMessageEnd; @@ -248,6 +248,7 @@ TProtocolRecursionTrackerImpl = class abstract( TInterfacedObject, IProtocolRe function NextRecursionLevel : IProtocolRecursionTracker; procedure IncrementRecursionDepth; procedure DecrementRecursionDepth; + function GetMinSerializedSize( const aType : TType) : Integer; property Transport: ITransport read GetTransport; property RecursionLimit : Integer read GetRecursionLimit write SetRecursionLimit; @@ -265,6 +266,12 @@ TProtocolImpl = class abstract( TInterfacedObject, IProtocol) procedure IncrementRecursionDepth; procedure DecrementRecursionDepth; + function GetMinSerializedSize( const aType : TType) : Integer; virtual; abstract; + procedure CheckReadBytesAvailable( const value : TThriftList); overload; inline; + procedure CheckReadBytesAvailable( const value : TThriftSet); overload; inline; + procedure CheckReadBytesAvailable( const value : TThriftMap); overload; inline; + + procedure Reset; virtual; function GetTransport: ITransport; public procedure WriteMessageBegin( const msg: TThriftMessage); virtual; abstract; @@ -332,6 +339,7 @@ TBinaryProtocolImpl = class( TProtocolImpl ) strict protected FStrictRead : Boolean; FStrictWrite : Boolean; + function GetMinSerializedSize( const aType : TType) : Integer; override; strict private function ReadAll( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer ): Integer; inline; @@ -404,6 +412,9 @@ TProtocolDecorator = class( TProtocolImpl) strict private FWrappedProtocol : IProtocol; + strict protected + function GetMinSerializedSize( const aType : TType) : Integer; override; + public // Encloses the specified protocol. // All operations will be forward to the given protocol. Must be non-null. @@ -583,6 +594,12 @@ function TProtocolImpl.GetTransport: ITransport; Result := FTrans; end; +procedure TProtocolImpl.Reset; +begin + if FTrans.TransportControl <> nil + then FTrans.TransportControl.ResetConsumedMessageSize; +end; + function TProtocolImpl.ReadAnsiString: AnsiString; var b : TBytes; @@ -623,6 +640,29 @@ procedure TProtocolImpl.WriteString(const s: string); WriteBinary( b ); end; + +procedure TProtocolImpl.CheckReadBytesAvailable( const value : TThriftList); +begin + FTrans.CheckReadBytesAvailable( value.Count * GetMinSerializedSize(value.ElementType)); +end; + + +procedure TProtocolImpl.CheckReadBytesAvailable( const value : TThriftSet); +begin + FTrans.CheckReadBytesAvailable( value.Count * GetMinSerializedSize(value.ElementType)); +end; + + +procedure TProtocolImpl.CheckReadBytesAvailable( const value : TThriftMap); +var nPairSize : Integer +; +begin + nPairSize := GetMinSerializedSize(value.KeyType) + GetMinSerializedSize(value.ValueType); + FTrans.CheckReadBytesAvailable( value.Count * nPairSize); +end; + + + { TProtocolUtil } class procedure TProtocolUtil.Skip( prot: IProtocol; type_: TType); @@ -705,6 +745,7 @@ function TBinaryProtocolImpl.ReadBinary: TBytes; buf : TBytes; begin size := ReadI32; + FTrans.CheckReadBytesAvailable( size); SetLength( buf, size); FTrans.ReadAll( buf, 0, size); Result := buf; @@ -777,6 +818,7 @@ function TBinaryProtocolImpl.ReadListBegin: TThriftList; begin result.ElementType := TType(ReadByte); result.Count := ReadI32; + CheckReadBytesAvailable(result); end; procedure TBinaryProtocolImpl.ReadListEnd; @@ -789,6 +831,7 @@ function TBinaryProtocolImpl.ReadMapBegin: TThriftMap; result.KeyType := TType(ReadByte); result.ValueType := TType(ReadByte); result.Count := ReadI32; + CheckReadBytesAvailable(result); end; procedure TBinaryProtocolImpl.ReadMapEnd; @@ -801,6 +844,7 @@ function TBinaryProtocolImpl.ReadMessageBegin: TThriftMessage; size : Integer; version : Integer; begin + Reset; Init( result); size := ReadI32; if (size < 0) then begin @@ -832,6 +876,7 @@ function TBinaryProtocolImpl.ReadSetBegin: TThriftSet; begin result.ElementType := TType(ReadByte); result.Count := ReadI32; + CheckReadBytesAvailable(result); end; procedure TBinaryProtocolImpl.ReadSetEnd; @@ -842,6 +887,7 @@ procedure TBinaryProtocolImpl.ReadSetEnd; function TBinaryProtocolImpl.ReadStringBody( size: Integer): string; var buf : TBytes; begin + FTrans.CheckReadBytesAvailable( size); SetLength( buf, size); FTrans.ReadAll( buf, 0, size ); Result := TEncoding.UTF8.GetString( buf); @@ -959,6 +1005,7 @@ procedure TBinaryProtocolImpl.WriteMapEnd; procedure TBinaryProtocolImpl.WriteMessageBegin( const msg: TThriftMessage); var version : Cardinal; begin + Reset; if FStrictWrite then begin version := VERSION_1 or Cardinal( msg.Type_); WriteI32( Integer( version) ); @@ -997,6 +1044,29 @@ procedure TBinaryProtocolImpl.WriteStructEnd; end; +function TBinaryProtocolImpl.GetMinSerializedSize( const aType : TType) : Integer; +// Return the minimum number of bytes a type will consume on the wire +begin + case aType of + TType.Stop: result := 0; + TType.Void: result := 0; + TType.Bool_: result := SizeOf(Byte); + TType.Byte_: result := SizeOf(Byte); + TType.Double_: result := SizeOf(Double); + TType.I16: result := SizeOf(Int16); + TType.I32: result := SizeOf(Int32); + TType.I64: result := SizeOf(Int64); + TType.String_: result := SizeOf(Int32); // string length + TType.Struct: result := 0; // empty struct + TType.Map: result := SizeOf(Int32); // element count + TType.Set_: result := SizeOf(Int32); // element count + TType.List: result := SizeOf(Int32); // element count + else + raise TTransportExceptionBadArgs.Create('Unhandled type code'); + end; +end; + + { TProtocolException } constructor TProtocolException.HiddenCreate(const Msg: string); @@ -1363,6 +1433,12 @@ function TProtocolDecorator.ReadAnsiString: AnsiString; end; +function TProtocolDecorator.GetMinSerializedSize( const aType : TType) : Integer; +begin + result := FWrappedProtocol.GetMinSerializedSize(aType); +end; + + { Init helper functions } procedure Init( var rec : TThriftMessage; const AName: string; const AMessageType: TMessageType; const ASeqID: Integer); diff --git a/lib/delphi/src/Thrift.Serializer.pas b/lib/delphi/src/Thrift.Serializer.pas index b95cf61daa1..1cbcbec5ff3 100644 --- a/lib/delphi/src/Thrift.Serializer.pas +++ b/lib/delphi/src/Thrift.Serializer.pas @@ -71,15 +71,18 @@ TDeserializer = class public // Create a new TDeserializer that uses the TBinaryProtocol by default. - constructor Create; overload; + constructor Create( const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE); overload; // Create a new TDeserializer. // It will use the TProtocol specified by the factory that is passed in. - constructor Create( const factory : IProtocolFactory); overload; + constructor Create( const factory : IProtocolFactory; + const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE); overload; // Create a new TDeserializer. // It will use the TProtocol and layered transports specified by the factories that are passed in. - constructor Create( const protfact : IProtocolFactory; const transfact : ITransportFactory); overload; + constructor Create( const protfact : IProtocolFactory; + const transfact : ITransportFactory; + const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE); overload; // DTOR destructor Destroy; override; @@ -122,7 +125,7 @@ constructor TSerializer.Create( const protfact : IProtocolFactory; const transfa inherited Create; FStream := TMemoryStream.Create; adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE); - FTransport := TStreamTransportImpl.Create( nil, adapter); + FTransport := TStreamTransportImpl.Create( nil, adapter, TTransportControlImpl.Create(0)); // we don't read anything here if transfact <> nil then FTransport := transfact.GetTransport( FTransport); FProtocol := protfact.GetProtocol( FTransport); @@ -185,24 +188,26 @@ procedure TSerializer.Serialize( const input : IBase; const aStm : TStream); { TDeserializer } -constructor TDeserializer.Create; +constructor TDeserializer.Create( const aMaxMessageSize : Integer); // Create a new TDeserializer that uses the TBinaryProtocol by default. begin //no inherited; - Create( TBinaryProtocolImpl.TFactory.Create, nil); + Create( TBinaryProtocolImpl.TFactory.Create, nil, aMaxMessageSize); end; -constructor TDeserializer.Create( const factory : IProtocolFactory); +constructor TDeserializer.Create( const factory : IProtocolFactory; const aMaxMessageSize : Integer); // Create a new TDeserializer. // It will use the TProtocol specified by the factory that is passed in. begin //no inherited; - Create( factory, nil); + Create( factory, nil, aMaxMessageSize); end; -constructor TDeserializer.Create( const protfact : IProtocolFactory; const transfact : ITransportFactory); +constructor TDeserializer.Create( const protfact : IProtocolFactory; + const transfact : ITransportFactory; + const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE); // Create a new TDeserializer. // It will use the TProtocol specified by the factory that is passed in. var adapter : IThriftStream; @@ -210,7 +215,7 @@ constructor TDeserializer.Create( const protfact : IProtocolFactory; const trans inherited Create; FStream := TMemoryStream.Create; adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE); - FTransport := TStreamTransportImpl.Create( adapter, nil); + FTransport := TStreamTransportImpl.Create( adapter, nil, TTransportControlImpl.Create(aMaxMessageSize)); if transfact <> nil then FTransport := transfact.GetTransport( FTransport); FProtocol := protfact.GetProtocol( FTransport); diff --git a/lib/delphi/src/Thrift.Stream.pas b/lib/delphi/src/Thrift.Stream.pas index 7cb9219b677..0f4e723e85b 100644 --- a/lib/delphi/src/Thrift.Stream.pas +++ b/lib/delphi/src/Thrift.Stream.pas @@ -37,11 +37,12 @@ interface type IThriftStream = interface - ['{2A77D916-7446-46C1-8545-0AEC0008DBCA}'] + ['{DBE61E28-2A77-42DB-A5A3-3CCB8A2D09FA}'] procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; + procedure CheckReadBytesAvailable( const value : Integer); procedure Open; procedure Close; procedure Flush; @@ -49,14 +50,24 @@ interface function ToArray: TBytes; end; - TThriftStreamImpl = class( TInterfacedObject, IThriftStream) + + IThriftStream2 = interface( IThriftStream) + ['{1F55D9FE-F617-4B80-B8CA-4A300D8E33F6}'] + function Size : Int64; + function Position : Int64; + end; + + + TThriftStreamImpl = class abstract( TInterfacedObject, IThriftStream) strict private procedure CheckSizeAndOffset( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer); overload; strict protected + // IThriftStream procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; inline; procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; virtual; function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; inline; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; virtual; + procedure CheckReadBytesAvailable( const value : Integer); virtual; abstract; procedure Open; virtual; abstract; procedure Close; virtual; abstract; procedure Flush; virtual; abstract; @@ -64,40 +75,54 @@ TThriftStreamImpl = class( TInterfacedObject, IThriftStream) function ToArray: TBytes; virtual; abstract; end; - TThriftStreamAdapterDelphi = class( TThriftStreamImpl ) + TThriftStreamAdapterDelphi = class( TThriftStreamImpl, IThriftStream2) strict private FStream : TStream; FOwnsStream : Boolean; strict protected + // IThriftStream procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; + procedure CheckReadBytesAvailable( const value : Integer); override; procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; + + // IThriftStream2 + function Size : Int64; + function Position : Int64; public - constructor Create( const AStream: TStream; AOwnsStream : Boolean); + constructor Create( const aStream: TStream; aOwnsStream : Boolean); destructor Destroy; override; end; - TThriftStreamAdapterCOM = class( TThriftStreamImpl) + TThriftStreamAdapterCOM = class( TThriftStreamImpl, IThriftStream2) strict private FStream : IStream; strict protected + // IThriftStream procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; + procedure CheckReadBytesAvailable( const value : Integer); override; procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; + + // IThriftStream2 + function Size : Int64; + function Position : Int64; public - constructor Create( const AStream: IStream); + constructor Create( const aStream: IStream); end; implementation +uses Thrift.Transport; + { TThriftStreamAdapterCOM } procedure TThriftStreamAdapterCOM.Close; @@ -105,10 +130,10 @@ procedure TThriftStreamAdapterCOM.Close; FStream := nil; end; -constructor TThriftStreamAdapterCOM.Create( const AStream: IStream); +constructor TThriftStreamAdapterCOM.Create( const aStream: IStream); begin inherited Create; - FStream := AStream; + FStream := aStream; end; procedure TThriftStreamAdapterCOM.Flush; @@ -120,6 +145,24 @@ procedure TThriftStreamAdapterCOM.Flush; end; end; +function TThriftStreamAdapterCOM.Size : Int64; +var statstg: TStatStg; +begin + FillChar( statstg, SizeOf( statstg), 0); + if IsOpen + and Succeeded( FStream.Stat( statstg, STATFLAG_NONAME )) + then result := statstg.cbSize + else result := 0; +end; + +function TThriftStreamAdapterCOM.Position : Int64; +var newpos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND}; +begin + if SUCCEEDED( FStream.Seek( 0, STREAM_SEEK_CUR, newpos)) + then result := Int64(newpos) + else raise TTransportExceptionEndOfFile.Create('Seek() error'); +end; + function TThriftStreamAdapterCOM.IsOpen: Boolean; begin Result := FStream <> nil; @@ -148,21 +191,21 @@ function TThriftStreamAdapterCOM.Read( const pBuf : Pointer; const buflen : Inte end; end; +procedure TThriftStreamAdapterCOM.CheckReadBytesAvailable( const value : Integer); +var nRemaining : Int64; +begin + nRemaining := Self.Size - Self.Position; + if nRemaining < value + then raise TTransportExceptionEndOfFile.Create('Not enough input data'); +end; + function TThriftStreamAdapterCOM.ToArray: TBytes; var - statstg: TStatStg; - len : Integer; + len : Int64; NewPos : {$IF CompilerVersion >= 29.0} UInt64 {$ELSE} Int64 {$IFEND}; cbRead : Integer; begin - FillChar( statstg, SizeOf( statstg), 0); - len := 0; - if IsOpen then begin - if Succeeded( FStream.Stat( statstg, STATFLAG_NONAME )) then begin - len := statstg.cbSize; - end; - end; - + len := Self.Size; SetLength( Result, len ); if len > 0 then begin @@ -226,6 +269,21 @@ procedure TThriftStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: { TThriftStreamAdapterDelphi } +constructor TThriftStreamAdapterDelphi.Create( const aStream: TStream; aOwnsStream: Boolean); +begin + inherited Create; + FStream := aStream; + FOwnsStream := aOwnsStream; +end; + +destructor TThriftStreamAdapterDelphi.Destroy; +begin + if FOwnsStream + then Close; + + inherited; +end; + procedure TThriftStreamAdapterDelphi.Close; begin FStream.Free; @@ -233,24 +291,19 @@ procedure TThriftStreamAdapterDelphi.Close; FOwnsStream := False; end; -constructor TThriftStreamAdapterDelphi.Create( const AStream: TStream; AOwnsStream: Boolean); +procedure TThriftStreamAdapterDelphi.Flush; begin - inherited Create; - FStream := AStream; - FOwnsStream := AOwnsStream; + // nothing to do end; -destructor TThriftStreamAdapterDelphi.Destroy; +function TThriftStreamAdapterDelphi.Size : Int64; begin - if FOwnsStream - then Close; - - inherited; + result := FStream.Size; end; -procedure TThriftStreamAdapterDelphi.Flush; +function TThriftStreamAdapterDelphi.Position : Int64; begin - // nothing to do + result := FStream.Position; end; function TThriftStreamAdapterDelphi.IsOpen: Boolean; @@ -279,16 +332,21 @@ function TThriftStreamAdapterDelphi.Read(const pBuf : Pointer; const buflen : In else Result := 0; end; +procedure TThriftStreamAdapterDelphi.CheckReadBytesAvailable( const value : Integer); +var nRemaining : Int64; +begin + nRemaining := FStream.Size - FStream.Position; + if nRemaining < value then raise TTransportExceptionEndOfFile.Create('Not enough input data'); +end; + function TThriftStreamAdapterDelphi.ToArray: TBytes; var OrgPos : Integer; len : Integer; begin - len := 0; - if FStream <> nil then - begin - len := FStream.Size; - end; + if FStream <> nil + then len := FStream.Size + else len := 0; SetLength( Result, len ); diff --git a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas index 87bf23b0428..b92cce1e12b 100644 --- a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas @@ -59,6 +59,7 @@ TMsxmlHTTPClientImpl = class( TTransportImpl, IHTTPClient) function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; procedure Flush; override; + procedure CheckReadBytesAvailable( const value : Integer); override; procedure SetDnsResolveTimeout(const Value: Integer); function GetDnsResolveTimeout: Integer; @@ -80,7 +81,7 @@ TMsxmlHTTPClientImpl = class( TTransportImpl, IHTTPClient) property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout; property CustomHeaders: IThriftDictionary read GetCustomHeaders; public - constructor Create( const AUri: string); + constructor Create( const AUri: string; const aTransportCtl : ITransportControl = nil); destructor Destroy; override; end; @@ -90,9 +91,9 @@ implementation { TMsxmlHTTPClientImpl } -constructor TMsxmlHTTPClientImpl.Create(const AUri: string); +constructor TMsxmlHTTPClientImpl.Create(const AUri: string; const aTransportCtl : ITransportControl); begin - inherited Create; + inherited Create( aTransportCtl); FUri := AUri; // defaults according to MSDN @@ -218,6 +219,13 @@ procedure TMsxmlHTTPClientImpl.Flush; end; end; +procedure TMsxmlHTTPClientImpl.CheckReadBytesAvailable( const value : Integer); +begin + if FInputStream <> nil + then FInputStream.CheckReadBytesAvailable( value) + else raise TTransportExceptionNotOpen.Create('No request has been sent'); +end; + function TMsxmlHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; begin if FInputStream = nil then begin @@ -225,7 +233,8 @@ function TMsxmlHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer end; try - Result := FInputStream.Read( pBuf, buflen, off, len) + Result := FInputStream.Read( pBuf, buflen, off, len); + ConsumeReadBytes( result); except on E: Exception do raise TTransportExceptionUnknown.Create(E.Message); diff --git a/lib/delphi/src/Thrift.Transport.Pipes.pas b/lib/delphi/src/Thrift.Transport.Pipes.pas index 9368f2fa995..b602b64c8d6 100644 --- a/lib/delphi/src/Thrift.Transport.Pipes.pas +++ b/lib/delphi/src/Thrift.Transport.Pipes.pas @@ -53,6 +53,7 @@ TPipeStreamBase = class( TThriftStreamImpl) //procedure Open; override; - see derived classes procedure Close; override; procedure Flush; override; + procedure CheckReadBytesAvailable( const value : Integer); override; function ReadDirect( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; function ReadOverlapped( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; @@ -123,13 +124,17 @@ TPipeTransportBase = class( TStreamTransportImpl, IPipeTransport) TNamedPipeTransportClientEndImpl = class( TPipeTransportBase) public // Named pipe constructors - constructor Create( aPipe : THandle; aOwnsHandle : Boolean; - const aTimeOut : DWORD); overload; + constructor Create( const aPipe : THandle; + const aOwnsHandle : Boolean; + const aTimeOut : DWORD; + const aTransportCtl : ITransportControl); overload; + constructor Create( const aPipeName : string; const aShareMode: DWORD = 0; const aSecurityAttributes: PSecurityAttributes = nil; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; - const aOpenTimeOut : DWORD = DEFAULT_THRIFT_PIPE_OPEN_TIMEOUT); overload; + const aOpenTimeOut : DWORD = DEFAULT_THRIFT_PIPE_OPEN_TIMEOUT; + const aTransportCtl : ITransportControl = nil); overload; end; @@ -139,17 +144,20 @@ TNamedPipeTransportServerEndImpl = class( TNamedPipeTransportClientEndImpl) public // ITransport procedure Close; override; - constructor Create( aPipe : THandle; aOwnsHandle : Boolean; - const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT); reintroduce; + constructor Create( const aPipe : THandle; + const aOwnsHandle : Boolean; + const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; + const aTransportCtl : ITransportControl = nil); reintroduce; end; TAnonymousPipeTransportImpl = class( TPipeTransportBase) public // Anonymous pipe constructor - constructor Create(const aPipeRead, aPipeWrite : THandle; - aOwnsHandles : Boolean; - const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT); overload; + constructor Create( const aPipeRead, aPipeWrite : THandle; + const aOwnsHandles : Boolean; + const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; + const aTransportCtl : ITransportControl = nil); overload; end; @@ -310,6 +318,12 @@ function TPipeStreamBase.IsOpen: Boolean; end; +procedure TPipeStreamBase.CheckReadBytesAvailable( const value : Integer); +begin + // can't tell how much we can suck out of the pipe +end; + + procedure TPipeStreamBase.Write( const pBuf : Pointer; offset, count : Integer); begin if FOverlapped @@ -642,21 +656,24 @@ procedure TPipeTransportBase.Close; constructor TNamedPipeTransportClientEndImpl.Create( const aPipeName : string; const aShareMode: DWORD; - const aSecurityAttributes: PSecurityAttributes; - const aTimeOut, aOpenTimeOut : DWORD); + const aSecurityAttributes: PSecurityAttributes; + const aTimeOut, aOpenTimeOut : DWORD; + const aTransportCtl : ITransportControl); // Named pipe constructor begin - inherited Create( nil, nil); + inherited Create( nil, nil, aTransportCtl); FInputStream := TNamedPipeStreamImpl.Create( aPipeName, TRUE, aShareMode, aSecurityAttributes, aTimeOut, aOpenTimeOut); FOutputStream := FInputStream; // true for named pipes end; -constructor TNamedPipeTransportClientEndImpl.Create( aPipe : THandle; aOwnsHandle : Boolean; - const aTimeOut : DWORD); +constructor TNamedPipeTransportClientEndImpl.Create( const aPipe : THandle; + const aOwnsHandle : Boolean; + const aTimeOut : DWORD; + const aTransportCtl : ITransportControl); // Named pipe constructor begin - inherited Create( nil, nil); + inherited Create( nil, nil, aTransportCtl); FInputStream := THandlePipeStreamImpl.Create( aPipe, TRUE, aOwnsHandle, aTimeOut); FOutputStream := FInputStream; // true for named pipes end; @@ -665,12 +682,14 @@ constructor TNamedPipeTransportClientEndImpl.Create( aPipe : THandle; aOwnsHandl { TNamedPipeTransportServerEndImpl } -constructor TNamedPipeTransportServerEndImpl.Create( aPipe : THandle; aOwnsHandle : Boolean; - const aTimeOut : DWORD); +constructor TNamedPipeTransportServerEndImpl.Create( const aPipe : THandle; + const aOwnsHandle : Boolean; + const aTimeOut : DWORD; + const aTransportCtl : ITransportControl); // Named pipe constructor begin FHandle := DuplicatePipeHandle( aPipe); - inherited Create( aPipe, aOwnsHandle, aTimeOut); + inherited Create( aPipe, aOwnsHandle, aTimeOut, aTransportCtl); end; @@ -688,11 +707,12 @@ procedure TNamedPipeTransportServerEndImpl.Close; constructor TAnonymousPipeTransportImpl.Create( const aPipeRead, aPipeWrite : THandle; - aOwnsHandles : Boolean; - const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT); + const aOwnsHandles : Boolean; + const aTimeOut : DWORD; + const aTransportCtl : ITransportControl); // Anonymous pipe constructor begin - inherited Create( nil, nil); + inherited Create( nil, nil, aTransportCtl); // overlapped is not supported with AnonPipes, see MSDN FInputStream := THandlePipeStreamImpl.Create( aPipeRead, aOwnsHandles, FALSE, aTimeOut); FOutputStream := THandlePipeStreamImpl.Create( aPipeWrite, aOwnsHandles, FALSE, aTimeOut); diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas index 0bf7e456fbc..ec8c87f085e 100644 --- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas @@ -58,16 +58,19 @@ TWinHTTPClientImpl = class( TTransportImpl, IHTTPClient) THTTPResponseStream = class( TThriftStreamImpl) strict private FRequest : IWinHTTPRequest; + FTransportControl : ITransportControl; strict protected procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; + procedure CheckReadBytesAvailable( const value : Integer); override; + procedure ConsumeReadBytes( const count : Integer); procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; public - constructor Create( const aRequest : IWinHTTPRequest); + constructor Create( const aRequest : IWinHTTPRequest; const aTransportCtl : ITransportControl); destructor Destroy; override; end; @@ -78,6 +81,7 @@ THTTPResponseStream = class( TThriftStreamImpl) function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; procedure Flush; override; + procedure CheckReadBytesAvailable( const value : Integer); override; procedure SetDnsResolveTimeout(const Value: Integer); function GetDnsResolveTimeout: Integer; @@ -99,7 +103,7 @@ THTTPResponseStream = class( TThriftStreamImpl) property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout; property CustomHeaders: IThriftDictionary read GetCustomHeaders; public - constructor Create( const AUri: string); + constructor Create( const AUri: string; const aTransportCtl : ITransportControl = nil); destructor Destroy; override; end; @@ -108,9 +112,9 @@ implementation { TWinHTTPClientImpl } -constructor TWinHTTPClientImpl.Create(const AUri: string); +constructor TWinHTTPClientImpl.Create(const AUri: string; const aTransportCtl : ITransportControl); begin - inherited Create; + inherited Create( aTransportCtl); FUri := AUri; // defaults according to MSDN @@ -284,6 +288,13 @@ procedure TWinHTTPClientImpl.Flush; end; end; +procedure TWinHTTPClientImpl.CheckReadBytesAvailable( const value : Integer); +begin + if FInputStream <> nil + then FInputStream.CheckReadBytesAvailable( value) + else raise TTransportExceptionNotOpen.Create('No request has been sent'); +end; + function TWinHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; begin if FInputStream = nil then begin @@ -291,7 +302,8 @@ function TWinHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; end; try - Result := FInputStream.Read( pBuf, buflen, off, len) + Result := FInputStream.Read( pBuf, buflen, off, len); + ConsumeReadBytes( result); except on E: Exception do raise TTransportExceptionUnknown.Create(E.Message); @@ -301,6 +313,7 @@ function TWinHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; procedure TWinHTTPClientImpl.SendRequest; var http : IWinHTTPRequest; + ctrl : ITransportControl; pData : PByte; len : Integer; error : Cardinal; @@ -327,7 +340,8 @@ procedure TWinHTTPClientImpl.SendRequest; else raise TTransportExceptionInterrupted.Create( sMsg); end; - FInputStream := THTTPResponseStream.Create(http); + ctrl := TTransportControlImpl.Create( TransportControl.MaxAllowedMessageSize); + FInputStream := THTTPResponseStream.Create( http, ctrl); end; procedure TWinHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer); @@ -341,10 +355,12 @@ procedure TWinHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer); { TWinHTTPClientImpl.THTTPResponseStream } -constructor TWinHTTPClientImpl.THTTPResponseStream.Create( const aRequest : IWinHTTPRequest); +constructor TWinHTTPClientImpl.THTTPResponseStream.Create( const aRequest : IWinHTTPRequest; const aTransportCtl : ITransportControl); begin inherited Create; FRequest := aRequest; + FTransportControl := aTransportCtl; + ASSERT( FTransportControl <> nil); end; destructor TWinHTTPClientImpl.THTTPResponseStream.Destroy; @@ -390,6 +406,8 @@ function TWinHTTPClientImpl.THTTPResponseStream.Read(const pBuf : Pointer; const if count >= buflen-offset then count := buflen-offset; + CheckReadBytesAvailable(count); + if count > 0 then begin pTmp := pBuf; Inc( pTmp, offset); @@ -397,6 +415,20 @@ function TWinHTTPClientImpl.THTTPResponseStream.Read(const pBuf : Pointer; const ASSERT( Result >= 0); end else Result := 0; + + ConsumeReadBytes( result); +end; + +procedure TWinHTTPClientImpl.THTTPResponseStream.ConsumeReadBytes( const count : Integer); +begin + if FTransportControl <> nil + then FTransportControl.ConsumeReadBytes( count); +end; + +procedure TWinHTTPClientImpl.THTTPResponseStream.CheckReadBytesAvailable( const value : Integer); +begin + if Int64(value) > Int64(FRequest.QueryDataAvailable) + then raise TTransportExceptionEndOfFile.Create('Not enough input data'); end; function TWinHTTPClientImpl.THTTPResponseStream.ToArray: TBytes; diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index bede57cd87d..a3476bf2a3e 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -44,14 +44,39 @@ interface Thrift.WinHTTP, Thrift.Stream; +const + DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024; // 100 MB + DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms + type + ITransportControl = interface + ['{CDA35E2C-F1D2-4BE3-9927-7F1540923265}'] + function MaxAllowedMessageSize : Integer; + procedure ConsumeReadBytes( const count : Integer); + procedure ResetConsumedMessageSize; + end; + + TTransportControlImpl = class( TInterfacedObject, ITransportControl) + strict private + FMaxAllowedMsgSize : Integer; + FRemainingMsgSize : Integer; + strict protected + // ITransportControl + function MaxAllowedMessageSize : Integer; + procedure ConsumeReadBytes( const count : Integer); + procedure ResetConsumedMessageSize; + public + constructor Create( const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE); reintroduce; + end; + ITransport = interface - ['{DB84961E-8BB3-4532-99E1-A8C7AC2300F7}'] + ['{938F6EB5-1848-43D5-8AC4-07633C55B229}'] function GetIsOpen: Boolean; property IsOpen: Boolean read GetIsOpen; function Peek: Boolean; procedure Open; procedure Close; + function Read(var buf: TBytes; off: Integer; len: Integer): Integer; overload; function Read(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload; function ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; overload; @@ -61,15 +86,22 @@ interface procedure Write( const pBuf : Pointer; off, len : Integer); overload; procedure Write( const pBuf : Pointer; len : Integer); overload; procedure Flush; + + function TransportControl : ITransportControl; + procedure CheckReadBytesAvailable( const value : Integer); end; TTransportImpl = class( TInterfacedObject, ITransport) + strict private + FTransportControl : ITransportControl; + strict protected function GetIsOpen: Boolean; virtual; abstract; property IsOpen: Boolean read GetIsOpen; function Peek: Boolean; virtual; procedure Open(); virtual; abstract; procedure Close(); virtual; abstract; + function Read(var buf: TBytes; off: Integer; len: Integer): Integer; overload; inline; function Read(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; overload; virtual; abstract; function ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; overload; inline; @@ -79,6 +111,13 @@ TTransportImpl = class( TInterfacedObject, ITransport) procedure Write( const pBuf : Pointer; len : Integer); overload; inline; procedure Write( const pBuf : Pointer; off, len : Integer); overload; virtual; abstract; procedure Flush; virtual; + + function TransportControl : ITransportControl; inline; + procedure ConsumeReadBytes( const count : Integer); inline; + procedure CheckReadBytesAvailable( const value : Integer); virtual; abstract; + + public + constructor Create( const aTransportCtl : ITransportControl); reintroduce; end; TTransportException = class abstract( TException) @@ -98,9 +137,9 @@ TTransportException = class abstract( TException) constructor HiddenCreate(const Msg: string); class function GetType: TExceptionType; virtual; abstract; public - class function Create( AType: TExceptionType): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)'; + class function Create( aType: TExceptionType): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)'; class function Create( const msg: string): TTransportException; reintroduce; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)'; - class function Create( AType: TExceptionType; const msg: string): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)'; + class function Create( aType: TExceptionType; const msg: string): TTransportException; overload; deprecated 'Use specialized TTransportException types (or regenerate from IDL)'; property Type_: TExceptionType read GetType; end; @@ -196,7 +235,7 @@ TServerTransportImpl = class( TInterfacedObject, IServerTransport) ITransportFactory = interface ['{DD809446-000F-49E1-9BFF-E0D0DC76A9D7}'] - function GetTransport( const ATrans: ITransport): ITransport; + function GetTransport( const aTransport: ITransport): ITransport; end; TTransportFactoryImpl = class( TInterfacedObject, ITransportFactory) @@ -222,6 +261,7 @@ TTcpSocketStreamImpl = class( TThriftStreamImpl ) strict protected procedure Write( const pBuf : Pointer; offset, count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; + procedure CheckReadBytesAvailable( const value : Integer); override; procedure Open; override; procedure Close; override; procedure Flush; override; @@ -230,9 +270,9 @@ TTcpSocketStreamImpl = class( TThriftStreamImpl ) function ToArray: TBytes; override; public {$IFDEF OLD_SOCKETS} - constructor Create( const ATcpClient: TCustomIpClient; const aTimeout : Integer = 0); + constructor Create( const aTcpClient: TCustomIpClient; const aTimeout : Integer = 0); {$ELSE} - constructor Create( const ATcpClient: TSocket; const aTimeout : Longword = 0); + constructor Create( const aTcpClient: TSocket; const aTimeout : Longword = 0); {$ENDIF} end; @@ -254,14 +294,15 @@ TStreamTransportImpl = class( TTransportImpl, IStreamTransport) function GetInputStream: IThriftStream; function GetOutputStream: IThriftStream; - protected + procedure CheckReadBytesAvailable( const value : Integer); override; + strict protected procedure Open; override; procedure Close; override; procedure Flush; override; function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; public - constructor Create( const aInputStream, aOutputStream : IThriftStream); + constructor Create( const aInputStream, aOutputStream : IThriftStream; const aTransportCtl : ITransportControl = nil); destructor Destroy; override; property InputStream : IThriftStream read GetInputStream; @@ -277,6 +318,7 @@ TBufferedStreamImpl = class( TThriftStreamImpl) strict protected procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; + procedure CheckReadBytesAvailable( const value : Integer); override; procedure Open; override; procedure Close; override; procedure Flush; override; @@ -298,15 +340,19 @@ TServerSocketImpl = class( TServerTransportImpl) {$ENDIF} FUseBufferedSocket : Boolean; FOwnsServer : Boolean; + FTransportControl : ITransportControl; + strict protected function Accept( const fnAccepting: TProc) : ITransport; override; + property TransportControl : ITransportControl read FTransportControl; + public {$IFDEF OLD_SOCKETS} - constructor Create( const aServer: TTcpServer; const aClientTimeout: Integer = 0); overload; - constructor Create( const aPort: Integer; const aClientTimeout: Integer = 0; const aUseBufferedSockets: Boolean = FALSE); overload; + constructor Create( const aServer: TTcpServer; const aClientTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload; + constructor Create( const aPort: Integer; const aClientTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; aUseBufferedSockets: Boolean = FALSE; const aTransportCtl : ITransportControl = nil); overload; {$ELSE} - constructor Create( const aServer: TServerSocket; const aClientTimeout: Longword = 0); overload; - constructor Create( const aPort: Integer; const aClientTimeout: Longword = 0; const aUseBufferedSockets: Boolean = FALSE); overload; + constructor Create( const aServer: TServerSocket; const aClientTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload; + constructor Create( const aPort: Integer; const aClientTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; aUseBufferedSockets: Boolean = FALSE; const aTransportCtl : ITransportControl = nil); overload; {$ENDIF} destructor Destroy; override; procedure Listen; override; @@ -325,6 +371,7 @@ TBufferedTransportImpl = class( TTransportImpl ) strict protected function GetIsOpen: Boolean; override; procedure Flush; override; + procedure CheckReadBytesAvailable( const value : Integer); override; public type TFactory = class( TTransportFactoryImpl ) @@ -363,11 +410,11 @@ TSocketImpl = class(TStreamTransportImpl) public procedure Open; override; {$IFDEF OLD_SOCKETS} - constructor Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer = 0); overload; - constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Integer = 0); overload; + constructor Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload; + constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload; {$ELSE} - constructor Create( const aClient: TSocket; const aOwnsClient: Boolean); overload; - constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Longword = 0); overload; + constructor Create(const aClient: TSocket; const aOwnsClient: Boolean; const aTransportCtl : ITransportControl = nil); overload; + constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload; {$ENDIF} destructor Destroy; override; procedure Close; override; @@ -402,6 +449,7 @@ TFramedTransportImpl = class( TTransportImpl) function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; procedure Flush; override; + procedure CheckReadBytesAvailable( const value : Integer); override; public type TFactory = class( TTransportFactoryImpl ) @@ -409,20 +457,67 @@ TFactory = class( TTransportFactoryImpl ) function GetTransport( const aTransport: ITransport): ITransport; override; end; + constructor Create( const aTransportCtl : ITransportControl); overload; constructor Create( const aTransport: ITransport); overload; destructor Destroy; override; end; const - DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms DEFAULT_THRIFT_SECUREPROTOCOLS = [ TSecureProtocol.TLS_1_1, TSecureProtocol.TLS_1_2]; implementation +{ TTransportControlImpl } + +constructor TTransportControlImpl.Create( const aMaxMessageSize : Integer); +begin + inherited Create; + + if aMaxMessageSize > 0 + then FMaxAllowedMsgSize := aMaxMessageSize + else FMaxAllowedMsgSize := DEFAULT_MAX_MESSAGE_SIZE; + + ResetConsumedMessageSize; +end; + +function TTransportControlImpl.MaxAllowedMessageSize : Integer; +begin + result := FMaxAllowedMsgSize; +end; + +procedure TTransportControlImpl.ResetConsumedMessageSize; +begin + FRemainingMsgSize := MaxAllowedMessageSize; +end; + + +procedure TTransportControlImpl.ConsumeReadBytes( const count : Integer); +begin + if FRemainingMsgSize >= count + then Dec( FRemainingMsgSize, count) + else begin + FRemainingMsgSize := 0; + if FRemainingMsgSize < count + then raise TTransportExceptionEndOfFile.Create('Maximum message size reached'); + end; +end; + + { TTransportImpl } +constructor TTransportImpl.Create( const aTransportCtl : ITransportControl); +begin + inherited Create; + + if aTransportCtl <> nil + then FTransportControl := aTransportCtl + else FTransportControl := TTransportControlImpl.Create; + ASSERT( FTransportControl <> nil); +end; + + procedure TTransportImpl.Flush; begin // nothing to do @@ -477,6 +572,19 @@ procedure TTransportImpl.Write( const pBuf : Pointer; len : Integer); end; +function TTransportImpl.TransportControl : ITransportControl; +begin + result := FTransportControl; +end; + + +procedure TTransportImpl.ConsumeReadBytes( const count : Integer); +begin + if FTransportControl <> nil + then FTransportControl.ConsumeReadBytes( count); +end; + + { TTransportException } constructor TTransportException.HiddenCreate(const Msg: string); @@ -571,13 +679,15 @@ function TTransportFactoryImpl.GetTransport( const aTransport: ITransport): ITra { TServerSocket } {$IFDEF OLD_SOCKETS} -constructor TServerSocketImpl.Create( const aServer: TTcpServer; const aClientTimeout : Integer); +constructor TServerSocketImpl.Create( const aServer: TTcpServer; const aClientTimeout : Integer; const aTransportCtl : ITransportControl); {$ELSE} -constructor TServerSocketImpl.Create( const aServer: TServerSocket; const aClientTimeout: Longword); +constructor TServerSocketImpl.Create( const aServer: TServerSocket; const aClientTimeout: Longword; const aTransportCtl : ITransportControl); {$ENDIF} begin inherited Create; FServer := aServer; + FTransportControl := aTransportCtl; + ASSERT( FTransportControl <> nil); {$IFDEF OLD_SOCKETS} FClientTimeout := aClientTimeout; @@ -589,13 +699,18 @@ constructor TServerSocketImpl.Create( const aServer: TServerSocket; const aClien {$IFDEF OLD_SOCKETS} -constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Integer; const aUseBufferedSockets: Boolean); +constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Integer; aUseBufferedSockets: Boolean; const aTransportCtl : ITransportControl); {$ELSE} -constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Longword; const aUseBufferedSockets: Boolean); +constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Longword; aUseBufferedSockets: Boolean; const aTransportCtl : ITransportControl); {$ENDIF} begin inherited Create; + if aTransportCtl <> nil + then FTransportControl := aTransportCtl + else FTransportControl := TTransportControlImpl.Create; + ASSERT( FTransportControl <> nil); + {$IFDEF OLD_SOCKETS} FPort := aPort; FClientTimeout := aClientTimeout; @@ -657,7 +772,7 @@ function TServerSocketImpl.Accept( const fnAccepting: TProc): ITransport; Exit; end; - trans := TSocketImpl.Create( client, TRUE, FClientTimeout); + trans := TSocketImpl.Create( client, TRUE, FClientTimeout, TransportControl); client := nil; // trans owns it now if FUseBufferedSocket @@ -676,7 +791,7 @@ function TServerSocketImpl.Accept( const fnAccepting: TProc): ITransport; client := FServer.Accept; try - trans := TSocketImpl.Create(client, MaxMessageSize, True); + trans := TSocketImpl.Create(client, True, TransportControl); client := nil; if FUseBufferedSocket then @@ -725,9 +840,9 @@ procedure TServerSocketImpl.Close; { TSocket } {$IFDEF OLD_SOCKETS} -constructor TSocketImpl.Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer); +constructor TSocketImpl.Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer; const aTransportCtl : ITransportControl); {$ELSE} -constructor TSocketImpl.Create(const aClient: TSocket; const aOwnsClient: Boolean); +constructor TSocketImpl.Create(const aClient: TSocket; const aOwnsClient: Boolean; const aTransportCtl : ITransportControl); {$ENDIF} var stream : IThriftStream; begin @@ -741,16 +856,16 @@ constructor TSocketImpl.Create(const aClient: TSocket; const aOwnsClient: Boolea {$ENDIF} stream := TTcpSocketStreamImpl.Create( FClient, FTimeout); - inherited Create( stream, stream); + inherited Create( stream, stream, aTransportCtl); end; {$IFDEF OLD_SOCKETS} -constructor TSocketImpl.Create(const aHost: string; const aPort, aTimeout: Integer); +constructor TSocketImpl.Create(const aHost: string; const aPort, aTimeout: Integer; const aTransportCtl : ITransportControl); {$ELSE} -constructor TSocketImpl.Create(const aHost: string; const aPort : Integer; const aTimeout: Longword); +constructor TSocketImpl.Create(const aHost: string; const aPort : Integer; const aTimeout: Longword; const aTransportCtl : ITransportControl); {$ENDIF} begin - inherited Create(nil,nil); + inherited Create(nil,nil, aTransportCtl); FHost := aHost; FPort := aPort; FTimeout := aTimeout; @@ -928,6 +1043,22 @@ function TBufferedStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; end; +procedure TBufferedStreamImpl.CheckReadBytesAvailable( const value : Integer); +var nRequired : Integer; +begin + nRequired := value; + + if FReadBuffer <> nil then begin + Dec( nRequired, (FReadBuffer.Position - FReadBuffer.Size)); + if nRequired <= 0 then Exit; + end; + + if FStream <> nil + then FStream.CheckReadBytesAvailable( nRequired) + else raise TTransportExceptionEndOfFile.Create('Not enough input data'); +end; + + function TBufferedStreamImpl.ToArray: TBytes; var len : Integer; begin @@ -963,9 +1094,9 @@ procedure TBufferedStreamImpl.Write( const pBuf : Pointer; offset: Integer; coun { TStreamTransportImpl } -constructor TStreamTransportImpl.Create( const aInputStream, aOutputStream : IThriftStream); +constructor TStreamTransportImpl.Create( const aInputStream, aOutputStream : IThriftStream; const aTransportCtl : ITransportControl); begin - inherited Create; + inherited Create( aTransportCtl); FInputStream := aInputStream; FOutputStream := aOutputStream; end; @@ -1018,6 +1149,7 @@ function TStreamTransportImpl.Read( const pBuf : Pointer; const buflen : Integer then raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' ); Result := FInputStream.Read( pBuf,buflen, off, len ); + ConsumeReadBytes( result); end; procedure TStreamTransportImpl.Write( const pBuf : Pointer; off, len : Integer); @@ -1028,13 +1160,20 @@ procedure TStreamTransportImpl.Write( const pBuf : Pointer; off, len : Integer); FOutputStream.Write( pBuf, off, len ); end; +procedure TStreamTransportImpl.CheckReadBytesAvailable( const value : Integer); +begin + if FInputStream <> nil + then FInputStream.CheckReadBytesAvailable( value) + else raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' ); +end; + { TBufferedTransportImpl } constructor TBufferedTransportImpl.Create( const aTransport : IStreamTransport; const aBufSize: Integer); begin ASSERT( aTransport <> nil); - inherited Create; + inherited Create( aTransport.TransportControl); FTransport := aTransport; FBufSize := aBufSize; InitBuffers; @@ -1094,6 +1233,23 @@ procedure TBufferedTransportImpl.Write( const pBuf : Pointer; off, len : Integer end; end; +procedure TBufferedTransportImpl.CheckReadBytesAvailable( const value : Integer); +var stm2 : IThriftStream2; + need : Integer; +begin + need := value; + + // buffered bytes + if Supports( FInputBuffer, IThriftStream2, stm2) then begin + Dec( need, stm2.Size - stm2.Position); + if need <= 0 then Exit; + end; + + if FInputBuffer <> nil + then FInputBuffer.CheckReadBytesAvailable( need) + else raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' ); +end; + { TBufferedTransportImpl.TFactory } function TBufferedTransportImpl.TFactory.GetTransport( const aTransport: ITransport): ITransport; @@ -1104,10 +1260,18 @@ function TBufferedTransportImpl.TFactory.GetTransport( const aTransport: ITransp { TFramedTransportImpl } +constructor TFramedTransportImpl.Create( const aTransportCtl : ITransportControl); +begin + inherited Create( aTransportCtl); + + InitMaxFrameSize; + InitWriteBuffer; +end; + constructor TFramedTransportImpl.Create( const aTransport: ITransport); begin ASSERT( aTransport <> nil); - inherited Create; + inherited Create( aTransport.TransportControl); InitMaxFrameSize; InitWriteBuffer; @@ -1122,8 +1286,15 @@ destructor TFramedTransportImpl.Destroy; end; procedure TFramedTransportImpl.InitMaxFrameSize; +var maxLen : Integer; begin FMaxFrameSize := DEFAULT_MAX_LENGTH; + + // MaxAllowedMessageSize may be smaller, but not larger + if TransportControl <> nil then begin + maxLen := TransportControl.MaxAllowedMessageSize - SizeOf(TFramedHeader); + FMaxFrameSize := Min( FMaxFrameSize, maxLen); + end; end; procedure TFramedTransportImpl.Close; @@ -1225,6 +1396,7 @@ procedure TFramedTransportImpl.ReadFrame; raise TTransportExceptionCorruptedData.Create('Frame size ('+IntToStr(size)+') larger than allowed maximum ('+IntToStr(FMaxFrameSize)+')'); end; + FTransport.CheckReadBytesAvailable( size); SetLength( buff, size ); FTransport.ReadAll( buff, 0, size ); @@ -1247,6 +1419,18 @@ procedure TFramedTransportImpl.Write( const pBuf : Pointer; off, len : Integer); end; +procedure TFramedTransportImpl.CheckReadBytesAvailable( const value : Integer); +var nRemaining : Int64; +begin + if FReadBuffer = nil + then raise TTransportExceptionEndOfFile.Create('Cannot read from null inputstream'); + + nRemaining := FReadBuffer.Size - FReadBuffer.Position; + if value > nRemaining + then raise TTransportExceptionEndOfFile.Create('Not enough input data'); +end; + + { TFramedTransport.TFactory } function TFramedTransportImpl.TFactory.GetTransport( const aTransport: ITransport): ITransport; @@ -1577,6 +1761,10 @@ procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integ {$ENDIF} +procedure TTcpSocketStreamImpl.CheckReadBytesAvailable( const value : Integer); +begin + // we can't really tell, no further checks possible +end; end. diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index 854d7c08016..dc29bec52e8 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -486,7 +486,7 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; IWinHTTPConnection = interface; IWinHTTPRequest = interface - ['{F65952F2-2F3B-47DC-B524-F1694E6D2AD7}'] + ['{7862DC7C-3128-4AA1-B9B0-0EB0FE8B15B9}'] function Handle : HINTERNET; function Connection : IWinHTTPConnection; function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; @@ -498,6 +498,7 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; function FlushAndReceiveResponse : Boolean; function ReadData( const dwRead : DWORD) : TBytes; overload; function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; + function QueryDataAvailable : DWORD; end; IWinHTTPConnection = interface @@ -616,6 +617,7 @@ TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest) function FlushAndReceiveResponse : Boolean; function ReadData( const dwRead : DWORD) : TBytes; overload; function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; + function QueryDataAvailable : DWORD; public constructor Create( const aConnection : IWinHTTPConnection; @@ -1111,6 +1113,14 @@ function TWinHTTPRequestImpl.ReadData( const pBuf : Pointer; const dwRead : DWOR end; +function TWinHTTPRequestImpl.QueryDataAvailable : DWORD; +begin + if not WinHttpQueryDataAvailable( FHandle, result) + then result := 0; +end; + + + { TWinHTTPUrlImpl } constructor TWinHTTPUrlImpl.Create(const aUri: UnicodeString); diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas index a488cacaec3..3562dabb83e 100644 --- a/lib/delphi/test/TestClient.pas +++ b/lib/delphi/test/TestClient.pas @@ -1396,7 +1396,7 @@ procedure TClientThread.InitializeProtocolTransportStack; case FSetup.endpoint of trns_Sockets: begin Console.WriteLine('Using sockets ('+FSetup.host+' port '+IntToStr(FSetup.port)+')'); - streamtrans := TSocketImpl.Create( FSetup.host, FSetup.port ); + streamtrans := TSocketImpl.Create( FSetup.host, FSetup.port, DEFAULT_THRIFT_TIMEOUT); FTransport := streamtrans; end; diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas index 2a80d52a737..a9c71fb8330 100644 --- a/lib/delphi/test/TestServer.pas +++ b/lib/delphi/test/TestServer.pas @@ -585,7 +585,7 @@ class procedure TTestServer.Execute( const args: array of string); trns_Sockets : begin Console.WriteLine('- sockets (port '+IntToStr(port)+')'); if (trns_Buffered in layered) then Console.WriteLine('- buffered'); - servertrans := TServerSocketImpl.Create( Port, 0, (trns_Buffered in layered)); + servertrans := TServerSocketImpl.Create( Port, DEFAULT_THRIFT_TIMEOUT, (trns_Buffered in layered)); end; trns_MsxmlHttp, diff --git a/lib/delphi/test/serializer/TestSerializer.Tests.pas b/lib/delphi/test/serializer/TestSerializer.Tests.pas index ec8d86db802..fe69f4efc60 100644 --- a/lib/delphi/test/serializer/TestSerializer.Tests.pas +++ b/lib/delphi/test/serializer/TestSerializer.Tests.pas @@ -69,6 +69,9 @@ TTestSerializer = class //extends TestCase { class procedure Deserialize( const input : TBytes; const target : IBase; const factory : TFactoryPair); overload; class procedure Deserialize( const input : TStream; const target : IBase; const factory : TFactoryPair); overload; + class procedure ValidateReadToEnd( const input : TBytes; const serial : TDeserializer); overload; + class procedure ValidateReadToEnd( const input : TStream; const serial : TDeserializer); overload; + procedure Test_Serializer_Deserializer; procedure Test_OneOfEach( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); procedure Test_CompactStruct( const method : TMethod; const factory : TFactoryPair; const stream : TFileStream); @@ -305,9 +308,10 @@ class procedure TTestSerializer.Serialize(const input : IBase; const factory : T class procedure TTestSerializer.Deserialize( const input : TBytes; const target : IBase; const factory : TFactoryPair); var serial : TDeserializer; begin - serial := TDeserializer.Create( factory.prot, factory.trans); + serial := TDeserializer.Create( factory.prot, factory.trans, Length(input)); try serial.Deserialize( input, target); + ValidateReadToEnd( input, serial); finally serial.Free; end; @@ -317,13 +321,44 @@ class procedure TTestSerializer.Deserialize( const input : TBytes; const target class procedure TTestSerializer.Deserialize( const input : TStream; const target : IBase; const factory : TFactoryPair); var serial : TDeserializer; begin - serial := TDeserializer.Create( factory.prot, factory.trans); + serial := TDeserializer.Create( factory.prot, factory.trans, input.Size); try serial.Deserialize( input, target); + ValidateReadToEnd( input, serial); finally serial.Free; end; end; +class procedure TTestSerializer.ValidateReadToEnd( const input : TBytes; const serial : TDeserializer); +// we should not have any more byte to read +var dummy : IBase; +begin + try + dummy := TOneOfEachImpl.Create; + serial.Deserialize( input, dummy); + raise EInOutError.Create('Expected exception not thrown?'); + except + on e:TTransportExceptionEndOfFile do {expected}; + on e:Exception do raise; // unexpected + end; +end; + + +class procedure TTestSerializer.ValidateReadToEnd( const input : TStream; const serial : TDeserializer); +// we should not have any more byte to read +var dummy : IBase; +begin + try + input.Position := 0; + dummy := TOneOfEachImpl.Create; + serial.Deserialize( input, dummy); + raise EInOutError.Create('Expected exception not thrown?'); + except + on e:TTransportExceptionEndOfFile do {expected}; + on e:Exception do raise; // unexpected + end; +end; + end. From 528a0f0731cc98d8ba2ea4ee146e2d9b0cea9fc6 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Mon, 18 Nov 2019 20:17:03 +0100 Subject: [PATCH 433/756] THRIFT-5015 WinHTTP QueryDataAvailable cannot be used to retrieve total response size Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.Transport.WinHTTP.pas | 4 +- lib/delphi/src/Thrift.Transport.pas | 5 +- lib/delphi/src/Thrift.WinHTTP.pas | 116 +++++++++++++++++++- 3 files changed, 119 insertions(+), 6 deletions(-) diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas index ec8c87f085e..2f961a00168 100644 --- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas @@ -262,7 +262,7 @@ function TWinHTTPClientImpl.GetCustomHeaders: IThriftDictionary; function TWinHTTPClientImpl.GetIsOpen: Boolean; begin - Result := True; + Result := Assigned( FOutputMemoryStream); end; procedure TWinHTTPClientImpl.Open; @@ -427,7 +427,7 @@ procedure TWinHTTPClientImpl.THTTPResponseStream.ConsumeReadBytes( const count : procedure TWinHTTPClientImpl.THTTPResponseStream.CheckReadBytesAvailable( const value : Integer); begin - if Int64(value) > Int64(FRequest.QueryDataAvailable) + if Int64(value) > Int64(FRequest.QueryTotalResponseSize) then raise TTransportExceptionEndOfFile.Create('Not enough input data'); end; diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index a3476bf2a3e..7695b22daec 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -1308,6 +1308,9 @@ procedure TFramedTransportImpl.Flush; len : Integer; data_len : Integer; begin + if not IsOpen + then raise TTransportExceptionNotOpen.Create('not open'); + len := FWriteBuffer.Size; SetLength( buf, len); if len > 0 then begin @@ -1342,7 +1345,7 @@ TAccessMemoryStream = class(TMemoryStream) procedure TFramedTransportImpl.InitWriteBuffer; const DUMMY_HEADER : TFramedHeader = 0; begin - FWriteBuffer.Free; + FreeAndNil( FWriteBuffer); FWriteBuffer := TMemoryStream.Create; TAccessMemoryStream(FWriteBuffer).Capacity := 1024; FWriteBuffer.Write( DUMMY_HEADER, SizeOf(DUMMY_HEADER)); diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index dc29bec52e8..6d886fe9bd2 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -205,6 +205,8 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; // flags for WinHttpOpen(): WINHTTP_FLAG_ASYNC = $10000000; // want async session, requires WinHttpSetStatusCallback() usage + WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH = 0; + // ports INTERNET_DEFAULT_PORT = 0; // use the protocol-specific default (80 or 443) @@ -218,8 +220,16 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; WINHTTP_FLAG_ESCAPE_DISABLE_QUERY = $00000080; // if escaping enabled escape path part, but do not escape query // flags for WinHttpSendRequest(): + WINHTTP_NO_PROXY_NAME = nil; + WINHTTP_NO_PROXY_BYPASS = nil; + WINHTTP_NO_CLIENT_CERT_CONTEXT = nil; + WINHTTP_NO_REFERER = nil; + WINHTTP_DEFAULT_ACCEPT_TYPES = nil; WINHTTP_NO_ADDITIONAL_HEADERS = nil; WINHTTP_NO_REQUEST_DATA = nil; + WINHTTP_HEADER_NAME_BY_INDEX = nil; + WINHTTP_NO_OUTPUT_BUFFER = nil; + WINHTTP_NO_HEADER_INDEX = nil; // WinHttpAddRequestHeaders() dwModifiers WINHTTP_ADDREQ_INDEX_MASK = $0000FFFF; @@ -247,8 +257,6 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; INTERNET_SCHEME_HTTP = INTERNET_SCHEME(1); INTERNET_SCHEME_HTTPS = INTERNET_SCHEME(2); - WINHTTP_NO_CLIENT_CERT_CONTEXT = nil; - // options manifests for WinHttp{Query|Set}Option WINHTTP_OPTION_CALLBACK = 1; WINHTTP_OPTION_RESOLVE_TIMEOUT = 2; @@ -384,6 +392,88 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; SECURITY_FLAG_STRENGTH_MEDIUM = $40000000; SECURITY_FLAG_STRENGTH_STRONG = $20000000; + // query flags + WINHTTP_QUERY_MIME_VERSION = 0; + WINHTTP_QUERY_CONTENT_TYPE = 1; + WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING = 2; + WINHTTP_QUERY_CONTENT_ID = 3; + WINHTTP_QUERY_CONTENT_DESCRIPTION = 4; + WINHTTP_QUERY_CONTENT_LENGTH = 5; + WINHTTP_QUERY_CONTENT_LANGUAGE = 6; + WINHTTP_QUERY_ALLOW = 7; + WINHTTP_QUERY_PUBLIC = 8; + WINHTTP_QUERY_DATE = 9; + WINHTTP_QUERY_EXPIRES = 10; + WINHTTP_QUERY_LAST_MODIFIED = 11; + WINHTTP_QUERY_MESSAGE_ID = 12; + WINHTTP_QUERY_URI = 13; + WINHTTP_QUERY_DERIVED_FROM = 14; + WINHTTP_QUERY_COST = 15; + WINHTTP_QUERY_LINK = 16; + WINHTTP_QUERY_PRAGMA = 17; + WINHTTP_QUERY_VERSION = 18; + WINHTTP_QUERY_STATUS_CODE = 19; + WINHTTP_QUERY_STATUS_TEXT = 20; + WINHTTP_QUERY_RAW_HEADERS = 21; + WINHTTP_QUERY_RAW_HEADERS_CRLF = 22; + WINHTTP_QUERY_CONNECTION = 23; + WINHTTP_QUERY_ACCEPT = 24; + WINHTTP_QUERY_ACCEPT_CHARSET = 25; + WINHTTP_QUERY_ACCEPT_ENCODING = 26; + WINHTTP_QUERY_ACCEPT_LANGUAGE = 27; + WINHTTP_QUERY_AUTHORIZATION = 28; + WINHTTP_QUERY_CONTENT_ENCODING = 29; + WINHTTP_QUERY_FORWARDED = 30; + WINHTTP_QUERY_FROM = 31; + WINHTTP_QUERY_IF_MODIFIED_SINCE = 32; + WINHTTP_QUERY_LOCATION = 33; + WINHTTP_QUERY_ORIG_URI = 34; + WINHTTP_QUERY_REFERER = 35; + WINHTTP_QUERY_RETRY_AFTER = 36; + WINHTTP_QUERY_SERVER = 37; + WINHTTP_QUERY_TITLE = 38; + WINHTTP_QUERY_USER_AGENT = 39; + WINHTTP_QUERY_WWW_AUTHENTICATE = 40; + WINHTTP_QUERY_PROXY_AUTHENTICATE = 41; + WINHTTP_QUERY_ACCEPT_RANGES = 42; + WINHTTP_QUERY_SET_COOKIE = 43; + WINHTTP_QUERY_COOKIE = 44; + WINHTTP_QUERY_REQUEST_METHOD = 45; + WINHTTP_QUERY_REFRESH = 46; + WINHTTP_QUERY_CONTENT_DISPOSITION = 47; + WINHTTP_QUERY_AGE = 48; + WINHTTP_QUERY_CACHE_CONTROL = 49; + WINHTTP_QUERY_CONTENT_BASE = 50; + WINHTTP_QUERY_CONTENT_LOCATION = 51; + WINHTTP_QUERY_CONTENT_MD5 = 52; + WINHTTP_QUERY_CONTENT_RANGE = 53; + WINHTTP_QUERY_ETAG = 54; + WINHTTP_QUERY_HOST = 55; + WINHTTP_QUERY_IF_MATCH = 56; + WINHTTP_QUERY_IF_NONE_MATCH = 57; + WINHTTP_QUERY_IF_RANGE = 58; + WINHTTP_QUERY_IF_UNMODIFIED_SINCE = 59; + WINHTTP_QUERY_MAX_FORWARDS = 60; + WINHTTP_QUERY_PROXY_AUTHORIZATION = 61; + WINHTTP_QUERY_RANGE = 62; + WINHTTP_QUERY_TRANSFER_ENCODING = 63; + WINHTTP_QUERY_UPGRADE = 64; + WINHTTP_QUERY_VARY = 65; + WINHTTP_QUERY_VIA = 66; + WINHTTP_QUERY_WARNING = 67; + WINHTTP_QUERY_EXPECT = 68; + WINHTTP_QUERY_PROXY_CONNECTION = 69; + WINHTTP_QUERY_UNLESS_MODIFIED_SINCE = 70; + WINHTTP_QUERY_PROXY_SUPPORT = 75; + WINHTTP_QUERY_AUTHENTICATION_INFO = 76; + WINHTTP_QUERY_PASSPORT_URLS = 77; + WINHTTP_QUERY_PASSPORT_CONFIG = 78; + WINHTTP_QUERY_MAX = 78; + WINHTTP_QUERY_CUSTOM = 65535; + WINHTTP_QUERY_FLAG_REQUEST_HEADERS = $80000000; + WINHTTP_QUERY_FLAG_SYSTEMTIME = $40000000; + WINHTTP_QUERY_FLAG_NUMBER = $20000000; + // Secure connection error status flags WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED = $00000001; WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT = $00000002; @@ -486,7 +576,7 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; IWinHTTPConnection = interface; IWinHTTPRequest = interface - ['{7862DC7C-3128-4AA1-B9B0-0EB0FE8B15B9}'] + ['{7A8E7255-5440-4621-A8A8-1E9FFAA6D6FA}'] function Handle : HINTERNET; function Connection : IWinHTTPConnection; function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; @@ -499,6 +589,7 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; function ReadData( const dwRead : DWORD) : TBytes; overload; function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; function QueryDataAvailable : DWORD; + function QueryTotalResponseSize : DWORD; end; IWinHTTPConnection = interface @@ -618,6 +709,7 @@ TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest) function ReadData( const dwRead : DWORD) : TBytes; overload; function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; function QueryDataAvailable : DWORD; + function QueryTotalResponseSize : DWORD; public constructor Create( const aConnection : IWinHTTPConnection; @@ -1120,6 +1212,24 @@ function TWinHTTPRequestImpl.QueryDataAvailable : DWORD; end; +function TWinHTTPRequestImpl.QueryTotalResponseSize : DWORD; +var dwBytes, dwError, dwIndex : DWORD; +begin + dwBytes := SizeOf( result); + dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX); + if not WinHttpQueryHeaders( FHandle, + WINHTTP_QUERY_CONTENT_LENGTH or WINHTTP_QUERY_FLAG_NUMBER, + WINHTTP_HEADER_NAME_BY_INDEX, + @result, dwBytes, + dwIndex) + then begin + dwError := GetLastError; + ASSERT( dwError = ERROR_WINHTTP_HEADER_NOT_FOUND); // anything else would be an real error + result := MAXINT; // we don't know + end; +end; + + { TWinHTTPUrlImpl } From 225646b554e6c37de31657e11d907bf35d50679d Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Tue, 19 Nov 2019 21:43:45 +0100 Subject: [PATCH 434/756] THRIFT-4862 C++ TBinaryProtocol crashes on port scan Client: cpp Patch: Michael Patrick This closes #1939 --- lib/cpp/src/thrift/server/TNonblockingServer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.cpp b/lib/cpp/src/thrift/server/TNonblockingServer.cpp index eea0427d253..26ffa686fc3 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.cpp +++ b/lib/cpp/src/thrift/server/TNonblockingServer.cpp @@ -492,7 +492,11 @@ void TNonblockingServer::TConnection::workSocket() { case SOCKET_RECV: // It is an error to be in this state if we already have all the data - assert(readBufferPos_ < readWant_); + if (!(readBufferPos_ < readWant_)) { + GlobalOutput.printf("TNonblockingServer: frame size too short"); + close(); + return; + } try { // Read from the socket From f4475ff76fe3dcc1b3774d52bf28b333ab9acd01 Mon Sep 17 00:00:00 2001 From: Duru Can Celasun Date: Wed, 20 Nov 2019 15:31:35 +0000 Subject: [PATCH 435/756] THRIFT-5019: Duplicate imports from multiple includes from a namespace If a thrift file includes two files from the same namespace into a separate file, the generated Go code has duplicate imports for that namespace. This fixes that. Client: go --- compiler/cpp/src/thrift/generate/t_go_generator.cc | 5 +++++ lib/go/test/DuplicateImportsTest.thrift | 5 +++++ lib/go/test/Makefile.am | 7 +++++-- lib/go/test/common/a.thrift | 5 +++++ lib/go/test/common/b.thrift | 5 +++++ 5 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 lib/go/test/DuplicateImportsTest.thrift create mode 100644 lib/go/test/common/a.thrift create mode 100644 lib/go/test/common/b.thrift diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index e153a7851a3..2093841c60e 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -777,11 +777,16 @@ string t_go_generator::render_included_programs(string& unused_prot) { const vector& includes = program_->get_includes(); string result = ""; string local_namespace = program_->get_namespace("go"); + std::set included; for (auto include : includes) { if (!local_namespace.empty() && local_namespace == include->get_namespace("go")) { continue; } + if (!included.insert(include->get_namespace("go")).second) { + continue; + } + result += render_program_import(include, unused_prot); } return result; diff --git a/lib/go/test/DuplicateImportsTest.thrift b/lib/go/test/DuplicateImportsTest.thrift new file mode 100644 index 00000000000..ffe1caff2c3 --- /dev/null +++ b/lib/go/test/DuplicateImportsTest.thrift @@ -0,0 +1,5 @@ +include "common/a.thrift" +include "common/b.thrift" + +typedef a.A A +typedef b.B B diff --git a/lib/go/test/Makefile.am b/lib/go/test/Makefile.am index 2a9d3f5732b..f5de26e6f29 100644 --- a/lib/go/test/Makefile.am +++ b/lib/go/test/Makefile.am @@ -45,7 +45,8 @@ gopath: $(THRIFT) $(THRIFTTEST) \ ConflictNamespaceTestC.thrift \ ConflictNamespaceTestD.thrift \ ConflictNamespaceTestSuperThing.thrift \ - ConflictNamespaceServiceTest.thrift + ConflictNamespaceServiceTest.thrift \ + DuplicateImportsTest.thrift mkdir -p gopath/src grep -v list.*map.*list.*map $(THRIFTTEST) | grep -v 'set' > ThriftTest.thrift $(THRIFT) $(THRIFTARGS) -r IncludesTest.thrift @@ -71,6 +72,7 @@ gopath: $(THRIFT) $(THRIFTTEST) \ $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestD.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestSuperThing.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceServiceTest.thrift + $(THRIFT) $(THRIFTARGS) -r DuplicateImportsTest.thrift GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock || true sed -i 's/\"context\"/\"golang.org\/x\/net\/context\"/g' gopath/src/github.com/golang/mock/gomock/controller.go || true GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock @@ -94,7 +96,8 @@ check: gopath unionbinarytest \ conflictnamespacetestsuperthing \ conflict/context/conflict_service-remote \ - servicestest/container_test-remote + servicestest/container_test-remote \ + duplicateimportstest GOPATH=`pwd`/gopath $(GO) test thrift tests dontexportrwtest clean-local: diff --git a/lib/go/test/common/a.thrift b/lib/go/test/common/a.thrift new file mode 100644 index 00000000000..37e0e1cf421 --- /dev/null +++ b/lib/go/test/common/a.thrift @@ -0,0 +1,5 @@ +namespace go common + +struct A { + 1: optional string a +} diff --git a/lib/go/test/common/b.thrift b/lib/go/test/common/b.thrift new file mode 100644 index 00000000000..19930e7d325 --- /dev/null +++ b/lib/go/test/common/b.thrift @@ -0,0 +1,5 @@ +namespace go common + +struct B { + 1: optional string b +} From 261cad3417841a47d3f8caf46f344f0af7d41511 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 20 Nov 2019 19:03:14 +0100 Subject: [PATCH 436/756] THRIFT-5020 Refactoring & minor fixes for netstd library Client: netstd Patch: Jens Geyer This closes #1941 --- .../Thrift/Server/TSimpleAsyncServer.cs | 3 +- .../Thrift/Transport/Client/THttpTransport.cs | 5 - .../Client/TMemoryBufferTransport.cs | 9 +- .../Transport/Client/TNamedPipeTransport.cs | 7 +- .../Transport/Client/TSocketTransport.cs | 11 +- .../Transport/Client/TTlsSocketTransport.cs | 12 +- .../Transport/Server/THttpServerTransport.cs | 9 +- .../Server/TNamedPipeServerTransport.cs | 13 +- .../{ => Server}/TServerTransport.cs | 4 +- .../Server/TTlsServerSocketTransport.cs | 6 +- test/netstd/Client/TestClient.cs | 59 +++-- test/netstd/Server/TestServer.cs | 204 +++++++++--------- 12 files changed, 182 insertions(+), 160 deletions(-) rename lib/netstd/Thrift/Transport/{ => Server}/TServerTransport.cs (96%) diff --git a/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs b/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs index bdaa3489c98..45e55139c44 100644 --- a/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs +++ b/lib/netstd/Thrift/Server/TSimpleAsyncServer.cs @@ -66,7 +66,8 @@ public TSimpleAsyncServer(ITProcessorFactory itProcessorFactory, outputTransportFactory, inputProtocolFactory, outputProtocolFactory, - loggerFactory.CreateLogger()) + loggerFactory.CreateLogger(), + clientWaitingDelay) { } diff --git a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs index c84df83ae89..4f8454c0b2c 100644 --- a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs @@ -99,19 +99,14 @@ public override void Close() public override async ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) - { return await Task.FromCanceled(cancellationToken); - } if (_inputStream == null) - { throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No request has been sent"); - } try { var ret = await _inputStream.ReadAsync(buffer, offset, length, cancellationToken); - if (ret == -1) { throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "No more data available"); diff --git a/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs index 25895c2b7e0..cdbbc0d36dc 100644 --- a/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs @@ -30,14 +30,9 @@ public class TMemoryBufferTransport : TTransport private byte[] Bytes; private int _bytesUsed; - public TMemoryBufferTransport() + public TMemoryBufferTransport(int initialCapacity = 2048) { - Bytes = new byte[2048]; // default size - } - - public TMemoryBufferTransport(int initialCapacity) - { - Bytes = new byte[initialCapacity]; // default size + Bytes = new byte[initialCapacity]; } public TMemoryBufferTransport(byte[] buf) diff --git a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs index 7dfe0131ed0..1ae6074b86c 100644 --- a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs @@ -26,7 +26,7 @@ namespace Thrift.Transport.Client public class TNamedPipeTransport : TTransport { private NamedPipeClientStream PipeStream; - private int ConnectTimeout; + private readonly int ConnectTimeout; public TNamedPipeTransport(string pipe, int timeout = Timeout.Infinite) : this(".", pipe, timeout) @@ -102,7 +102,10 @@ public override async Task FlushAsync(CancellationToken cancellationToken) protected override void Dispose(bool disposing) { - PipeStream.Dispose(); + if(disposing) + { + PipeStream?.Dispose(); + } } } } diff --git a/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs b/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs index 00da045813a..dd506bc981c 100644 --- a/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs @@ -36,12 +36,7 @@ public TSocketTransport(TcpClient client) SetInputOutputStream(); } - public TSocketTransport(IPAddress host, int port) - : this(host, port, 0) - { - } - - public TSocketTransport(IPAddress host, int port, int timeout) + public TSocketTransport(IPAddress host, int port, int timeout = 0) { Host = host; Port = port; @@ -84,7 +79,7 @@ private void SetInputOutputStream() } } - public TcpClient TcpClient { get; private set; } + public TcpClient TcpClient { get; private set; } public IPAddress Host { get; } public int Port { get; } @@ -159,4 +154,4 @@ protected override void Dispose(bool disposing) _isDisposed = true; } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs index 9295bb01b43..a926a38f985 100644 --- a/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs @@ -42,7 +42,8 @@ public class TTlsSocketTransport : TStreamTransport private SslStream _secureStream; private int _timeout; - public TTlsSocketTransport(TcpClient client, X509Certificate2 certificate, bool isServer = false, + public TTlsSocketTransport(TcpClient client, + X509Certificate2 certificate, bool isServer = false, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) @@ -67,7 +68,8 @@ public TTlsSocketTransport(TcpClient client, X509Certificate2 certificate, bool } } - public TTlsSocketTransport(IPAddress host, int port, string certificatePath, + public TTlsSocketTransport(IPAddress host, int port, + string certificatePath, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) @@ -79,7 +81,7 @@ public TTlsSocketTransport(IPAddress host, int port, string certificatePath, { } - public TTlsSocketTransport(IPAddress host, int port, + public TTlsSocketTransport(IPAddress host, int port, X509Certificate2 certificate = null, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, @@ -92,7 +94,7 @@ public TTlsSocketTransport(IPAddress host, int port, { } - public TTlsSocketTransport(IPAddress host, int port, int timeout, + public TTlsSocketTransport(IPAddress host, int port, int timeout, X509Certificate2 certificate, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, @@ -109,7 +111,7 @@ public TTlsSocketTransport(IPAddress host, int port, int timeout, InitSocket(); } - public TTlsSocketTransport(string host, int port, int timeout, + public TTlsSocketTransport(string host, int port, int timeout, X509Certificate2 certificate, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, diff --git a/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs index 056300cfe3d..2a40db39672 100644 --- a/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs @@ -43,13 +43,16 @@ public class THttpServerTransport protected ITAsyncProcessor Processor; - public THttpServerTransport(ITAsyncProcessor processor, RequestDelegate next = null, ILoggerFactory loggerFactory = null) + public THttpServerTransport( + ITAsyncProcessor processor, + RequestDelegate next = null, + ILoggerFactory loggerFactory = null) : this(processor, new TBinaryProtocol.Factory(), null, next, loggerFactory) { } public THttpServerTransport( - ITAsyncProcessor processor, + ITAsyncProcessor processor, TProtocolFactory protocolFactory, TTransportFactory transFactory = null, RequestDelegate next = null, @@ -59,7 +62,7 @@ public THttpServerTransport( } public THttpServerTransport( - ITAsyncProcessor processor, + ITAsyncProcessor processor, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, TTransportFactory inputTransFactory = null, diff --git a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs index 77b82514316..b2f29b4e1d3 100644 --- a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs @@ -92,10 +92,16 @@ private void EnsurePipeInstance() try { var handle = CreatePipeNative(_pipeAddress, inbuf, outbuf); - if( (handle != null) && (!handle.IsInvalid)) + if ((handle != null) && (!handle.IsInvalid)) + { _stream = new NamedPipeServerStream(PipeDirection.InOut, _asyncMode, false, handle); + handle = null; // we don't own it any longer + } else + { + handle?.Dispose(); _stream = new NamedPipeServerStream(_pipeAddress, direction, maxconn, mode, options, inbuf, outbuf/*, pipesec*/); + } } catch (NotImplementedException) // Mono still does not support async, fallback to sync { @@ -301,7 +307,10 @@ public override async Task FlushAsync(CancellationToken cancellationToken) protected override void Dispose(bool disposing) { - PipeStream?.Dispose(); + if (disposing) + { + PipeStream?.Dispose(); + } } } } diff --git a/lib/netstd/Thrift/Transport/TServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerTransport.cs similarity index 96% rename from lib/netstd/Thrift/Transport/TServerTransport.cs rename to lib/netstd/Thrift/Transport/Server/TServerTransport.cs index 74c54cd0e66..dd60f6a125a 100644 --- a/lib/netstd/Thrift/Transport/TServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TServerTransport.cs @@ -34,7 +34,7 @@ protected virtual async ValueTask AcceptImplementationAsync() protected abstract ValueTask AcceptImplementationAsync(CancellationToken cancellationToken); - public async ValueTask AcceptAsync() + public async ValueTask AcceptAsync() { return await AcceptAsync(CancellationToken.None); } @@ -51,4 +51,4 @@ public async ValueTask AcceptAsync(CancellationToken cancellationTok return transport; } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs index 128680599a6..231b83f5ac6 100644 --- a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs @@ -63,7 +63,7 @@ public TTlsServerSocketTransport( RemoteCertificateValidationCallback clientCertValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) - : this(null, certificate, clientCertValidator, localCertificateSelectionCallback) + : this(null, certificate, clientCertValidator, localCertificateSelectionCallback, sslProtocols) { try { @@ -117,7 +117,9 @@ protected override async ValueTask AcceptImplementationAsync(Cancell client.SendTimeout = client.ReceiveTimeout = _clientTimeout; //wrap the client in an SSL Socket passing in the SSL cert - var tTlsSocket = new TTlsSocketTransport(client, _serverCertificate, true, _clientCertValidator, + var tTlsSocket = new TTlsSocketTransport( + client, + _serverCertificate, true, _clientCertValidator, _localCertificateSelectionCallback, _sslProtocols); await tTlsSocket.SetupTlsAsync(); diff --git a/test/netstd/Client/TestClient.cs b/test/netstd/Client/TestClient.cs index 0f58f95ed8e..13ae3134303 100644 --- a/test/netstd/Client/TestClient.cs +++ b/test/netstd/Client/TestClient.cs @@ -448,7 +448,7 @@ public enum BinaryTestSize public static byte[] PrepareTestData(bool randomDist, BinaryTestSize testcase) { - int amount = -1; + int amount; switch (testcase) { case BinaryTestSize.Empty: @@ -622,26 +622,29 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) { Console.WriteLine("*** FAILED ***"); returnCode |= ErrorContainers; - throw new Exception("CrazyNesting.Equals failed"); } } // TODO: Validate received message Console.Write("testStruct({\"Zero\", 1, -3, -5})"); - var o = new Xtruct(); - o.String_thing = "Zero"; - o.Byte_thing = (sbyte)1; - o.I32_thing = -3; - o.I64_thing = -5; + var o = new Xtruct + { + String_thing = "Zero", + Byte_thing = (sbyte)1, + I32_thing = -3, + I64_thing = -5 + }; var i = await client.testStructAsync(o, MakeTimeoutToken()); Console.WriteLine(" = {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}"); // TODO: Validate received message Console.Write("testNest({1, {\"Zero\", 1, -3, -5}, 5})"); - var o2 = new Xtruct2(); - o2.Byte_thing = (sbyte)1; - o2.Struct_thing = o; - o2.I32_thing = 5; + var o2 = new Xtruct2 + { + Byte_thing = (sbyte)1, + Struct_thing = o, + I32_thing = 5 + }; var i2 = await client.testNestAsync(o2, MakeTimeoutToken()); i = i2.Struct_thing; Console.WriteLine(" = {" + i2.Byte_thing + ", {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}, " + i2.I32_thing + "}"); @@ -838,16 +841,24 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) Console.WriteLine("}"); // TODO: Validate received message - var insane = new Insanity(); - insane.UserMap = new Dictionary(); - insane.UserMap[Numberz.FIVE] = 5000L; - var truck = new Xtruct(); - truck.String_thing = "Truck"; - truck.Byte_thing = (sbyte)8; - truck.I32_thing = 8; - truck.I64_thing = 8; - insane.Xtructs = new List(); - insane.Xtructs.Add(truck); + var insane = new Insanity + { + UserMap = new Dictionary + { + [Numberz.FIVE] = 5000L + } + }; + var truck = new Xtruct + { + String_thing = "Truck", + Byte_thing = (sbyte)8, + I32_thing = 8, + I64_thing = 8 + }; + insane.Xtructs = new List + { + truck + }; Console.Write("testInsanity()"); var whoa = await client.testInsanityAsync(insane, MakeTimeoutToken()); Console.Write(" = {"); @@ -902,8 +913,10 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) sbyte arg0 = 1; var arg1 = 2; var arg2 = long.MaxValue; - var multiDict = new Dictionary(); - multiDict[1] = "one"; + var multiDict = new Dictionary + { + [1] = "one" + }; var tmpMultiDict = new List(); foreach (var pair in multiDict) diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs index 25c2afc1f6d..280f4e98381 100644 --- a/test/netstd/Server/TestServer.cs +++ b/test/netstd/Server/TestServer.cs @@ -181,19 +181,19 @@ public Task ProcessContextAsync(object serverContext, TTransport transport, Canc public class TestHandlerAsync : ThriftTest.IAsync { - public TServer server { get; set; } - private int handlerID; - private StringBuilder sb = new StringBuilder(); - private TestLogDelegate logger; + public TServer Server { get; set; } + private readonly int handlerID; + private readonly StringBuilder sb = new StringBuilder(); + private readonly TestLogDelegate logger; public TestHandlerAsync() { handlerID = Interlocked.Increment(ref _clientID); - logger += testConsoleLogger; + logger += TestConsoleLogger; logger.Invoke("New TestHandler instance created"); } - public void testConsoleLogger(string msg, params object[] values) + public void TestConsoleLogger(string msg, params object[] values) { sb.Clear(); sb.AppendFormat("handler{0:D3}:", handlerID); @@ -525,117 +525,121 @@ private static X509Certificate2 GetServerCert() public static int Execute(List args) { - var loggerFactory = new LoggerFactory();//.AddConsole().AddDebug(); - var logger = new LoggerFactory().CreateLogger("Test"); - - try + using (var loggerFactory = new LoggerFactory()) //.AddConsole().AddDebug(); { - var param = new ServerParam(); + var logger = loggerFactory.CreateLogger("Test"); try { - param.Parse(args); - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - Console.WriteLine("Error while parsing arguments"); - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - return 1; - } + var param = new ServerParam(); + + try + { + param.Parse(args); + } + catch (Exception ex) + { + Console.WriteLine("*** FAILED ***"); + Console.WriteLine("Error while parsing arguments"); + Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + return 1; + } - // Endpoint transport (mandatory) - TServerTransport trans; - switch (param.transport) - { - case TransportChoice.NamedPipe: - Debug.Assert(param.pipe != null); - trans = new TNamedPipeServerTransport(param.pipe); - break; + // Endpoint transport (mandatory) + TServerTransport trans; + switch (param.transport) + { + case TransportChoice.NamedPipe: + Debug.Assert(param.pipe != null); + trans = new TNamedPipeServerTransport(param.pipe); + break; - case TransportChoice.TlsSocket: - var cert = GetServerCert(); - if (cert == null || !cert.HasPrivateKey) - { - throw new InvalidOperationException("Certificate doesn't contain private key"); - } + case TransportChoice.TlsSocket: + var cert = GetServerCert(); + if (cert == null || !cert.HasPrivateKey) + { + cert?.Dispose(); + throw new InvalidOperationException("Certificate doesn't contain private key"); + } trans = new TTlsServerSocketTransport( param.port, cert, - (sender, certificate, chain, errors) => true, - null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); - break; + (sender, certificate, chain, errors) => true, + null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); + break; - case TransportChoice.Socket: - default: + case TransportChoice.Socket: + default: trans = new TServerSocketTransport(param.port, 0); - break; - } + break; + } - // Layered transport (mandatory) - TTransportFactory transFactory = null; - switch (param.buffering) - { - case BufferChoice.Framed: - transFactory = new TFramedTransport.Factory(); - break; - case BufferChoice.Buffered: - transFactory = new TBufferedTransport.Factory(); - break; - default: - Debug.Assert(param.buffering == BufferChoice.None, "unhandled case"); - transFactory = null; // no layered transprt - break; - } + // Layered transport (mandatory) + TTransportFactory transFactory = null; + switch (param.buffering) + { + case BufferChoice.Framed: + transFactory = new TFramedTransport.Factory(); + break; + case BufferChoice.Buffered: + transFactory = new TBufferedTransport.Factory(); + break; + default: + Debug.Assert(param.buffering == BufferChoice.None, "unhandled case"); + transFactory = null; // no layered transprt + break; + } - // Protocol (mandatory) - TProtocolFactory proto; - switch (param.protocol) + // Protocol (mandatory) + TProtocolFactory proto; + switch (param.protocol) + { + case ProtocolChoice.Compact: + proto = new TCompactProtocol.Factory(); + break; + case ProtocolChoice.Json: + proto = new TJsonProtocol.Factory(); + break; + case ProtocolChoice.Binary: + default: + proto = new TBinaryProtocol.Factory(); + break; + } + + // Processor + var testHandler = new TestHandlerAsync(); + var testProcessor = new ThriftTest.AsyncProcessor(testHandler); + var processorFactory = new TSingletonProcessorFactory(testProcessor); + + TServer serverEngine = new TSimpleAsyncServer(processorFactory, trans, transFactory, transFactory, proto, proto, logger); + + //Server event handler + var serverEvents = new MyServerEventHandler(); + serverEngine.SetEventHandler(serverEvents); + + // Run it + var where = (!string.IsNullOrEmpty(param.pipe)) ? "on pipe " + param.pipe : "on port " + param.port; + Console.WriteLine("Starting the AsyncBaseServer " + where + + " with processor TPrototypeProcessorFactory prototype factory " + + (param.buffering == BufferChoice.Buffered ? " with buffered transport" : "") + + (param.buffering == BufferChoice.Framed ? " with framed transport" : "") + + (param.transport == TransportChoice.TlsSocket ? " with encryption" : "") + + (param.protocol == ProtocolChoice.Compact ? " with compact protocol" : "") + + (param.protocol == ProtocolChoice.Json ? " with json protocol" : "") + + "..."); + serverEngine.ServeAsync(CancellationToken.None).GetAwaiter().GetResult(); + Console.ReadLine(); + } + catch (Exception x) { - case ProtocolChoice.Compact: - proto = new TCompactProtocol.Factory(); - break; - case ProtocolChoice.Json: - proto = new TJsonProtocol.Factory(); - break; - case ProtocolChoice.Binary: - default: - proto = new TBinaryProtocol.Factory(); - break; + Console.Error.Write(x); + return 1; } - // Processor - var testHandler = new TestHandlerAsync(); - var testProcessor = new ThriftTest.AsyncProcessor(testHandler); - var processorFactory = new TSingletonProcessorFactory(testProcessor); - - TServer serverEngine = new TSimpleAsyncServer(processorFactory, trans, transFactory, transFactory, proto, proto, logger); - - //Server event handler - var serverEvents = new MyServerEventHandler(); - serverEngine.SetEventHandler(serverEvents); - - // Run it - var where = (! string.IsNullOrEmpty(param.pipe)) ? "on pipe " + param.pipe : "on port " + param.port; - Console.WriteLine("Starting the AsyncBaseServer " + where + - " with processor TPrototypeProcessorFactory prototype factory " + - (param.buffering == BufferChoice.Buffered ? " with buffered transport" : "") + - (param.buffering == BufferChoice.Framed ? " with framed transport" : "") + - (param.transport == TransportChoice.TlsSocket ? " with encryption" : "") + - (param.protocol == ProtocolChoice.Compact ? " with compact protocol" : "") + - (param.protocol == ProtocolChoice.Json ? " with json protocol" : "") + - "..."); - serverEngine.ServeAsync(CancellationToken.None).GetAwaiter().GetResult(); - Console.ReadLine(); - } - catch (Exception x) - { - Console.Error.Write(x); - return 1; - } - Console.WriteLine("done."); - return 0; + Console.WriteLine("done."); + return 0; + } } } From 8ae80a7f8466e5c340388fcb1d797dc3779d9f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Seux?= Date: Thu, 7 Nov 2019 11:33:58 +0100 Subject: [PATCH 437/756] =?UTF-8?q?THRIFT-4999:=20Raise=20proper=20excepti?= =?UTF-8?q?on=20on=20transport=20error=20Client:=20ruby=20Patch:=20Gr?= =?UTF-8?q?=C3=A9goire=20Seux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This closes #1924 Before this patch, any error on the http layer was ignored and usually seen by the user as ProtocolException instead of TransportException --- .../thrift/transport/http_client_transport.rb | 2 ++ lib/rb/spec/http_client_spec.rb | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/lib/rb/lib/thrift/transport/http_client_transport.rb b/lib/rb/lib/thrift/transport/http_client_transport.rb index 5c1dd5c8a9c..c84304d9912 100644 --- a/lib/rb/lib/thrift/transport/http_client_transport.rb +++ b/lib/rb/lib/thrift/transport/http_client_transport.rb @@ -47,6 +47,8 @@ def flush http.use_ssl = @url.scheme == 'https' http.verify_mode = @ssl_verify_mode if @url.scheme == 'https' resp = http.post(@url.request_uri, @outbuf, @headers) + raise TransportException.new(TransportException::UNKNOWN, "#{self.class.name} Could not connect to #{@url}, HTTP status code #{resp.code.to_i}") unless (200..299).include?(resp.code.to_i) + data = resp.body data = Bytes.force_binary_encoding(data) @inbuf = StringIO.new data diff --git a/lib/rb/spec/http_client_spec.rb b/lib/rb/spec/http_client_spec.rb index df472ab335e..292c7521ebb 100644 --- a/lib/rb/spec/http_client_spec.rb +++ b/lib/rb/spec/http_client_spec.rb @@ -45,6 +45,7 @@ expect(http).to receive(:post).with("/path/to/service?param=value", "a test frame", {"Content-Type"=>"application/x-thrift"}) do double("Net::HTTPOK").tap do |response| expect(response).to receive(:body).and_return "data" + expect(response).to receive(:code).and_return "200" end end end @@ -65,6 +66,7 @@ expect(http).to receive(:post).with("/path/to/service?param=value", "test", headers) do double("Net::HTTPOK").tap do |response| expect(response).to receive(:body).and_return "data" + expect(response).to receive(:code).and_return "200" end end end @@ -86,6 +88,24 @@ expect(@client.instance_variable_get(:@outbuf)).to eq(Thrift::Bytes.empty_byte_buffer) end + it 'should raise TransportError on HTTP failures' do + @client.write "test" + + expect(Net::HTTP).to receive(:new).with("my.domain.com", 80) do + double("Net::HTTP").tap do |http| + expect(http).to receive(:use_ssl=).with(false) + expect(http).to receive(:post).with("/path/to/service?param=value", "test", {"Content-Type"=>"application/x-thrift"}) do + double("Net::HTTPOK").tap do |response| + expect(response).not_to receive(:body) + expect(response).to receive(:code).at_least(:once).and_return "503" + end + end + end + end + + expect { @client.flush }.to raise_error(Thrift::TransportException) + end + end describe 'ssl enabled' do @@ -107,6 +127,7 @@ "Content-Type" => "application/x-thrift") do double("Net::HTTPOK").tap do |response| expect(response).to receive(:body).and_return "data" + expect(response).to receive(:code).and_return "200" end end end @@ -128,6 +149,7 @@ "Content-Type" => "application/x-thrift") do double("Net::HTTPOK").tap do |response| expect(response).to receive(:body).and_return "data" + expect(response).to receive(:code).and_return "200" end end end From eacd1d48c85ea756fd5edd10d7c328ee11a0657f Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 20 Nov 2019 19:03:14 +0100 Subject: [PATCH 438/756] THRIFT-5021 Implement MAX_MESSAGE_SIZE and centralize limits into a TConfiguration class Client: netstd Patch: Jens Geyer This closes #1943 --- .../Protocols/ProtocolsOperationsTests.cs | 3 +- .../Protocols/TJsonProtocolTests.cs | 5 +- lib/netstd/Thrift/Protocol/TProtocol.cs | 3 +- lib/netstd/Thrift/TConfiguration.cs | 19 +++++ .../Thrift/Transport/Client/THttpTransport.cs | 14 +++- .../Client/TMemoryBufferTransport.cs | 15 +++- .../Transport/Client/TNamedPipeTransport.cs | 17 +++-- .../Transport/Client/TSocketTransport.cs | 9 ++- .../Transport/Client/TStreamTransport.cs | 19 ++++- .../Transport/Client/TTlsSocketTransport.cs | 17 +++-- .../{ => Layered}/TBufferedTransport.cs | 18 ++--- .../{ => Layered}/TFramedTransport.cs | 18 +++-- .../Transport/Layered/TLayeredTransport.cs | 23 ++++++ .../Transport/Server/THttpServerTransport.cs | 12 ++- .../Server/TNamedPipeServerTransport.cs | 17 +++-- .../Server/TServerSocketTransport.cs | 9 ++- .../Transport/Server/TServerTransport.cs | 7 ++ .../Server/TTlsServerSocketTransport.cs | 9 ++- .../Thrift/Transport/TEndpointTransport.cs | 75 +++++++++++++++++++ lib/netstd/Thrift/Transport/TTransport.cs | 3 + .../Client/Performance/PerformanceTests.cs | 11 ++- test/netstd/Client/TestClient.cs | 11 ++- test/netstd/Server/TestServer.cs | 9 ++- tutorial/netstd/Client/Program.cs | 12 +-- tutorial/netstd/Server/Program.cs | 8 +- 25 files changed, 282 insertions(+), 81 deletions(-) create mode 100644 lib/netstd/Thrift/TConfiguration.cs rename lib/netstd/Thrift/Transport/{ => Layered}/TBufferedTransport.cs (92%) rename lib/netstd/Thrift/Transport/{ => Layered}/TFramedTransport.cs (91%) create mode 100644 lib/netstd/Thrift/Transport/Layered/TLayeredTransport.cs create mode 100644 lib/netstd/Thrift/Transport/TEndpointTransport.cs diff --git a/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs index b1f841892c3..b8df515dec0 100644 --- a/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs +++ b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs @@ -31,6 +31,7 @@ namespace Thrift.IntegrationTests.Protocols public class ProtocolsOperationsTests { private readonly CompareLogic _compareLogic = new CompareLogic(); + private static readonly TConfiguration Configuration = null; // or new TConfiguration() if needed [DataTestMethod] [DataRow(typeof(TBinaryProtocol), TMessageType.Call)] @@ -494,7 +495,7 @@ public async Task WriteReadBinary_Test(Type protocolType) private static Tuple GetProtocolInstance(Type protocolType) { var memoryStream = new MemoryStream(); - var streamClientTransport = new TStreamTransport(memoryStream, memoryStream); + var streamClientTransport = new TStreamTransport(memoryStream, memoryStream,Configuration); var protocol = (TProtocol) Activator.CreateInstance(protocolType, streamClientTransport); return new Tuple(memoryStream, protocol); } diff --git a/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs b/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs index 970ce7ecec5..4054a29f255 100644 --- a/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs +++ b/lib/netstd/Tests/Thrift.Tests/Protocols/TJsonProtocolTests.cs @@ -21,7 +21,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; -using NSubstitute; using Thrift.Protocol; using Thrift.Protocol.Entities; using Thrift.Transport; @@ -36,7 +35,7 @@ public class TJSONProtocolTests [TestMethod] public void TJSONProtocol_Can_Create_Instance_Test() { - var httpClientTransport = Substitute.For(new Uri("http://localhost"), null, null); + var httpClientTransport = new THttpTransport( new Uri("http://localhost"), null, null, null); var result = new TJSONProtocolWrapper(httpClientTransport); @@ -45,7 +44,7 @@ public void TJSONProtocol_Can_Create_Instance_Test() Assert.IsNotNull(result.WrappedReader); Assert.IsNotNull(result.Transport); Assert.IsTrue(result.WrappedRecursionDepth == 0); - Assert.IsTrue(result.WrappedRecursionLimit == TProtocol.DefaultRecursionDepth); + Assert.IsTrue(result.WrappedRecursionLimit == TConfiguration.DEFAULT_RECURSION_DEPTH); Assert.IsTrue(result.Transport.Equals(httpClientTransport)); Assert.IsTrue(result.WrappedContext.GetType().Name.Equals("JSONBaseContext", StringComparison.OrdinalIgnoreCase)); diff --git a/lib/netstd/Thrift/Protocol/TProtocol.cs b/lib/netstd/Thrift/Protocol/TProtocol.cs index 75edb11d1f7..dca3f9efc85 100644 --- a/lib/netstd/Thrift/Protocol/TProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TProtocol.cs @@ -27,7 +27,6 @@ namespace Thrift.Protocol // ReSharper disable once InconsistentNaming public abstract class TProtocol : IDisposable { - public const int DefaultRecursionDepth = 64; private bool _isDisposed; protected int RecursionDepth; @@ -36,7 +35,7 @@ public abstract class TProtocol : IDisposable protected TProtocol(TTransport trans) { Trans = trans; - RecursionLimit = DefaultRecursionDepth; + RecursionLimit = trans.Configuration.RecursionLimit; RecursionDepth = 0; } diff --git a/lib/netstd/Thrift/TConfiguration.cs b/lib/netstd/Thrift/TConfiguration.cs new file mode 100644 index 00000000000..c8dde10434f --- /dev/null +++ b/lib/netstd/Thrift/TConfiguration.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Thrift +{ + public class TConfiguration + { + public const int DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024; + public const int DEFAULT_MAX_FRAME_SIZE = 16384000; // this value is used consistently across all Thrift libraries + public const int DEFAULT_RECURSION_DEPTH = 64; + + public int MaxMessageSize { get; set; } = DEFAULT_MAX_MESSAGE_SIZE; + public int MaxFrameSize { get; set; } = DEFAULT_MAX_FRAME_SIZE; + public int RecursionLimit { get; set; } = DEFAULT_RECURSION_DEPTH; + + // TODO(JensG): add connection and i/o timeouts + } +} diff --git a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs index 4f8454c0b2c..bbd94fa98e9 100644 --- a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs @@ -28,7 +28,7 @@ namespace Thrift.Transport.Client { // ReSharper disable once InconsistentNaming - public class THttpTransport : TTransport + public class THttpTransport : TEndpointTransport { private readonly X509Certificate[] _certificates; private readonly Uri _uri; @@ -39,13 +39,14 @@ public class THttpTransport : TTransport private MemoryStream _outputStream = new MemoryStream(); private bool _isDisposed; - public THttpTransport(Uri uri, IDictionary customRequestHeaders = null, string userAgent = null) - : this(uri, Enumerable.Empty(), customRequestHeaders, userAgent) + public THttpTransport(Uri uri, TConfiguration config, IDictionary customRequestHeaders = null, string userAgent = null) + : this(uri, config, Enumerable.Empty(), customRequestHeaders, userAgent) { } - public THttpTransport(Uri uri, IEnumerable certificates, + public THttpTransport(Uri uri, TConfiguration config, IEnumerable certificates, IDictionary customRequestHeaders, string userAgent = null) + : base(config) { _uri = uri; _certificates = (certificates ?? Enumerable.Empty()).ToArray(); @@ -104,6 +105,8 @@ public override async ValueTask ReadAsync(byte[] buffer, int offset, int le if (_inputStream == null) throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No request has been sent"); + CheckReadBytesAvailable(length); + try { var ret = await _inputStream.ReadAsync(buffer, offset, length, cancellationToken); @@ -112,6 +115,7 @@ public override async ValueTask ReadAsync(byte[] buffer, int offset, int le throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "No more data available"); } + CountConsumedMessageBytes(ret); return ret; } catch (IOException iox) @@ -196,9 +200,11 @@ public override async Task FlushAsync(CancellationToken cancellationToken) finally { _outputStream = new MemoryStream(); + ResetConsumedMessageSize(); } } + // IDisposable protected override void Dispose(bool disposing) { diff --git a/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs index cdbbc0d36dc..abf8f14c404 100644 --- a/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs @@ -24,18 +24,20 @@ namespace Thrift.Transport.Client { // ReSharper disable once InconsistentNaming - public class TMemoryBufferTransport : TTransport + public class TMemoryBufferTransport : TEndpointTransport { private bool IsDisposed; private byte[] Bytes; private int _bytesUsed; - public TMemoryBufferTransport(int initialCapacity = 2048) + public TMemoryBufferTransport(TConfiguration config, int initialCapacity = 2048) + : base(config) { Bytes = new byte[initialCapacity]; } - public TMemoryBufferTransport(byte[] buf) + public TMemoryBufferTransport(byte[] buf, TConfiguration config) + :base(config) { Bytes = (byte[])buf.Clone(); _bytesUsed = Bytes.Length; @@ -112,13 +114,18 @@ public void Seek(int delta, SeekOrigin origin) if ((0 > newPos) || (newPos > _bytesUsed)) throw new ArgumentException(nameof(origin)); Position = newPos; + + ResetConsumedMessageSize(); + CountConsumedMessageBytes(Position); } public override ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { + CheckReadBytesAvailable(length); var count = Math.Min(Length - Position, length); Buffer.BlockCopy(Bytes, Position, buffer, offset, count); Position += count; + CountConsumedMessageBytes(count); return new ValueTask(count); } @@ -142,6 +149,7 @@ public override async Task FlushAsync(CancellationToken cancellationToken) { await Task.FromCanceled(cancellationToken); } + ResetConsumedMessageSize(); } public byte[] GetBuffer() @@ -157,7 +165,6 @@ internal bool TryGetBuffer(out ArraySegment bufSegment) return true; } - // IDisposable protected override void Dispose(bool disposing) { diff --git a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs index 1ae6074b86c..f7f10b71ad6 100644 --- a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs @@ -23,17 +23,18 @@ namespace Thrift.Transport.Client { // ReSharper disable once InconsistentNaming - public class TNamedPipeTransport : TTransport + public class TNamedPipeTransport : TEndpointTransport { private NamedPipeClientStream PipeStream; private readonly int ConnectTimeout; - public TNamedPipeTransport(string pipe, int timeout = Timeout.Infinite) - : this(".", pipe, timeout) + public TNamedPipeTransport(string pipe, TConfiguration config, int timeout = Timeout.Infinite) + : this(".", pipe, config, timeout) { } - public TNamedPipeTransport(string server, string pipe, int timeout = Timeout.Infinite) + public TNamedPipeTransport(string server, string pipe, TConfiguration config, int timeout = Timeout.Infinite) + : base(config) { var serverName = string.IsNullOrWhiteSpace(server) ? server : "."; ConnectTimeout = (timeout > 0) ? timeout : Timeout.Infinite; @@ -51,6 +52,7 @@ public override async Task OpenAsync(CancellationToken cancellationToken) } await PipeStream.ConnectAsync( ConnectTimeout, cancellationToken); + ResetConsumedMessageSize(); } public override void Close() @@ -69,7 +71,10 @@ public override async ValueTask ReadAsync(byte[] buffer, int offset, int le throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - return await PipeStream.ReadAsync(buffer, offset, length, cancellationToken); + CheckReadBytesAvailable(length); + var numRead = await PipeStream.ReadAsync(buffer, offset, length, cancellationToken); + CountConsumedMessageBytes(numRead); + return numRead; } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) @@ -98,8 +103,10 @@ public override async Task FlushAsync(CancellationToken cancellationToken) { await Task.FromCanceled(cancellationToken); } + ResetConsumedMessageSize(); } + protected override void Dispose(bool disposing) { if(disposing) diff --git a/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs b/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs index dd506bc981c..d5591543441 100644 --- a/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs @@ -30,13 +30,15 @@ public class TSocketTransport : TStreamTransport private bool _isDisposed; - public TSocketTransport(TcpClient client) + public TSocketTransport(TcpClient client, TConfiguration config) + : base(config) { TcpClient = client ?? throw new ArgumentNullException(nameof(client)); SetInputOutputStream(); } - public TSocketTransport(IPAddress host, int port, int timeout = 0) + public TSocketTransport(IPAddress host, int port, TConfiguration config, int timeout = 0) + : base(config) { Host = host; Port = port; @@ -47,7 +49,8 @@ public TSocketTransport(IPAddress host, int port, int timeout = 0) SetInputOutputStream(); } - public TSocketTransport(string host, int port, int timeout = 0) + public TSocketTransport(string host, int port, TConfiguration config, int timeout = 0) + : base(config) { try { diff --git a/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs b/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs index d8574d610c3..e04b3b3336e 100644 --- a/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs @@ -22,15 +22,17 @@ namespace Thrift.Transport.Client { // ReSharper disable once InconsistentNaming - public class TStreamTransport : TTransport + public class TStreamTransport : TEndpointTransport { private bool _isDisposed; - protected TStreamTransport() + protected TStreamTransport(TConfiguration config) + :base(config) { } - public TStreamTransport(Stream inputStream, Stream outputStream) + public TStreamTransport(Stream inputStream, Stream outputStream, TConfiguration config) + : base(config) { InputStream = inputStream; OutputStream = outputStream; @@ -38,7 +40,14 @@ public TStreamTransport(Stream inputStream, Stream outputStream) protected Stream OutputStream { get; set; } - protected Stream InputStream { get; set; } + private Stream _InputStream = null; + protected Stream InputStream { + get => _InputStream; + set { + _InputStream = value; + ResetConsumedMessageSize(); + } + } public override bool IsOpen => true; @@ -90,8 +99,10 @@ public override async Task WriteAsync(byte[] buffer, int offset, int length, Can public override async Task FlushAsync(CancellationToken cancellationToken) { await OutputStream.FlushAsync(cancellationToken); + ResetConsumedMessageSize(); } + // IDisposable protected override void Dispose(bool disposing) { diff --git a/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs index a926a38f985..0980526f23e 100644 --- a/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs @@ -42,11 +42,12 @@ public class TTlsSocketTransport : TStreamTransport private SslStream _secureStream; private int _timeout; - public TTlsSocketTransport(TcpClient client, + public TTlsSocketTransport(TcpClient client, TConfiguration config, X509Certificate2 certificate, bool isServer = false, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) + : base(config) { _client = client; _certificate = certificate; @@ -68,12 +69,12 @@ public TTlsSocketTransport(TcpClient client, } } - public TTlsSocketTransport(IPAddress host, int port, + public TTlsSocketTransport(IPAddress host, int port, TConfiguration config, string certificatePath, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) - : this(host, port, 0, + : this(host, port, config, 0, new X509Certificate2(certificatePath), certValidator, localCertificateSelectionCallback, @@ -81,12 +82,12 @@ public TTlsSocketTransport(IPAddress host, int port, { } - public TTlsSocketTransport(IPAddress host, int port, + public TTlsSocketTransport(IPAddress host, int port, TConfiguration config, X509Certificate2 certificate = null, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) - : this(host, port, 0, + : this(host, port, config, 0, certificate, certValidator, localCertificateSelectionCallback, @@ -94,11 +95,12 @@ public TTlsSocketTransport(IPAddress host, int port, { } - public TTlsSocketTransport(IPAddress host, int port, int timeout, + public TTlsSocketTransport(IPAddress host, int port, TConfiguration config, int timeout, X509Certificate2 certificate, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) + : base(config) { _host = host; _port = port; @@ -111,11 +113,12 @@ public TTlsSocketTransport(IPAddress host, int port, int timeout, InitSocket(); } - public TTlsSocketTransport(string host, int port, int timeout, + public TTlsSocketTransport(string host, int port, TConfiguration config, int timeout, X509Certificate2 certificate, RemoteCertificateValidationCallback certValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) + : base(config) { try { diff --git a/lib/netstd/Thrift/Transport/TBufferedTransport.cs b/lib/netstd/Thrift/Transport/Layered/TBufferedTransport.cs similarity index 92% rename from lib/netstd/Thrift/Transport/TBufferedTransport.cs rename to lib/netstd/Thrift/Transport/Layered/TBufferedTransport.cs index e4fdd3a8dfc..10cec3c3d52 100644 --- a/lib/netstd/Thrift/Transport/TBufferedTransport.cs +++ b/lib/netstd/Thrift/Transport/Layered/TBufferedTransport.cs @@ -24,12 +24,11 @@ namespace Thrift.Transport { // ReSharper disable once InconsistentNaming - public class TBufferedTransport : TTransport + public class TBufferedTransport : TLayeredTransport { private readonly int DesiredBufferSize; - private readonly Client.TMemoryBufferTransport ReadBuffer = new Client.TMemoryBufferTransport(1024); - private readonly Client.TMemoryBufferTransport WriteBuffer = new Client.TMemoryBufferTransport(1024); - private readonly TTransport InnerTransport; + private readonly Client.TMemoryBufferTransport ReadBuffer; + private readonly Client.TMemoryBufferTransport WriteBuffer; private bool IsDisposed; public class Factory : TTransportFactory @@ -42,19 +41,20 @@ public override TTransport GetTransport(TTransport trans) //TODO: should support only specified input transport? public TBufferedTransport(TTransport transport, int bufSize = 1024) + : base(transport) { if (bufSize <= 0) { throw new ArgumentOutOfRangeException(nameof(bufSize), "Buffer size must be a positive number."); } - InnerTransport = transport ?? throw new ArgumentNullException(nameof(transport)); DesiredBufferSize = bufSize; - if (DesiredBufferSize != ReadBuffer.Capacity) - ReadBuffer.Capacity = DesiredBufferSize; - if (DesiredBufferSize != WriteBuffer.Capacity) - WriteBuffer.Capacity = DesiredBufferSize; + WriteBuffer = new Client.TMemoryBufferTransport(InnerTransport.Configuration, bufSize); + ReadBuffer = new Client.TMemoryBufferTransport(InnerTransport.Configuration, bufSize); + + Debug.Assert(DesiredBufferSize == ReadBuffer.Capacity); + Debug.Assert(DesiredBufferSize == WriteBuffer.Capacity); } public TTransport UnderlyingTransport diff --git a/lib/netstd/Thrift/Transport/TFramedTransport.cs b/lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs similarity index 91% rename from lib/netstd/Thrift/Transport/TFramedTransport.cs rename to lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs index de6df723886..c842a16aaa5 100644 --- a/lib/netstd/Thrift/Transport/TFramedTransport.cs +++ b/lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs @@ -23,13 +23,12 @@ namespace Thrift.Transport { // ReSharper disable once InconsistentNaming - public class TFramedTransport : TTransport + public class TFramedTransport : TLayeredTransport { private const int HeaderSize = 4; private readonly byte[] HeaderBuf = new byte[HeaderSize]; - private readonly Client.TMemoryBufferTransport ReadBuffer = new Client.TMemoryBufferTransport(); - private readonly Client.TMemoryBufferTransport WriteBuffer = new Client.TMemoryBufferTransport(); - private readonly TTransport InnerTransport; + private readonly Client.TMemoryBufferTransport ReadBuffer; + private readonly Client.TMemoryBufferTransport WriteBuffer; private bool IsDisposed; @@ -42,9 +41,10 @@ public override TTransport GetTransport(TTransport trans) } public TFramedTransport(TTransport transport) + : base(transport) { - InnerTransport = transport ?? throw new ArgumentNullException(nameof(transport)); - + ReadBuffer = new Client.TMemoryBufferTransport(Configuration); + WriteBuffer = new Client.TMemoryBufferTransport(Configuration); InitWriteBuffer(); } @@ -86,7 +86,11 @@ public override async ValueTask ReadAsync(byte[] buffer, int offset, int le private async ValueTask ReadFrameAsync(CancellationToken cancellationToken) { await InnerTransport.ReadAllAsync(HeaderBuf, 0, HeaderSize, cancellationToken); - var size = DecodeFrameSize(HeaderBuf); + int size = DecodeFrameSize(HeaderBuf); + + if ((0 > size) || (size > Configuration.MaxFrameSize)) // size must be in the range 0 to allowed max + throw new TTransportException(TTransportException.ExceptionType.Unknown, $"Maximum frame size exceeded ({size} bytes)"); + UpdateKnownMessageSize(size + HeaderSize); ReadBuffer.SetLength(size); ReadBuffer.Seek(0, SeekOrigin.Begin); diff --git a/lib/netstd/Thrift/Transport/Layered/TLayeredTransport.cs b/lib/netstd/Thrift/Transport/Layered/TLayeredTransport.cs new file mode 100644 index 00000000000..59d98ff1d0d --- /dev/null +++ b/lib/netstd/Thrift/Transport/Layered/TLayeredTransport.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Thrift.Transport +{ + public abstract class TLayeredTransport : TTransport + { + public readonly TTransport InnerTransport; + + public override TConfiguration Configuration { get => InnerTransport.Configuration; } + + public TLayeredTransport(TTransport transport) + { + InnerTransport = transport ?? throw new ArgumentNullException(nameof(transport)); + } + + public override void UpdateKnownMessageSize(long size) + { + InnerTransport.UpdateKnownMessageSize(size); + } + } +} diff --git a/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs index 2a40db39672..7271f504e3d 100644 --- a/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/THttpServerTransport.cs @@ -42,27 +42,31 @@ public class THttpServerTransport protected TTransportFactory OutputTransportFactory; protected ITAsyncProcessor Processor; + protected TConfiguration Configuration; public THttpServerTransport( ITAsyncProcessor processor, + TConfiguration config, RequestDelegate next = null, ILoggerFactory loggerFactory = null) - : this(processor, new TBinaryProtocol.Factory(), null, next, loggerFactory) + : this(processor, config, new TBinaryProtocol.Factory(), null, next, loggerFactory) { } public THttpServerTransport( ITAsyncProcessor processor, + TConfiguration config, TProtocolFactory protocolFactory, TTransportFactory transFactory = null, RequestDelegate next = null, ILoggerFactory loggerFactory = null) - : this(processor, protocolFactory, protocolFactory, transFactory, transFactory, next, loggerFactory) + : this(processor, config, protocolFactory, protocolFactory, transFactory, transFactory, next, loggerFactory) { } public THttpServerTransport( ITAsyncProcessor processor, + TConfiguration config, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, TTransportFactory inputTransFactory = null, @@ -73,6 +77,8 @@ public THttpServerTransport( // loggerFactory == null is not illegal anymore Processor = processor ?? throw new ArgumentNullException(nameof(processor)); + Configuration = config; // may be null + InputProtocolFactory = inputProtocolFactory ?? throw new ArgumentNullException(nameof(inputProtocolFactory)); OutputProtocolFactory = outputProtocolFactory ?? throw new ArgumentNullException(nameof(outputProtocolFactory)); @@ -91,7 +97,7 @@ public async Task Invoke(HttpContext context) public async Task ProcessRequestAsync(HttpContext context, CancellationToken cancellationToken) { - var transport = new TStreamTransport(context.Request.Body, context.Response.Body); + var transport = new TStreamTransport(context.Request.Body, context.Response.Body, Configuration); try { diff --git a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs index b2f29b4e1d3..a8b64c495f0 100644 --- a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs @@ -38,7 +38,8 @@ public class TNamedPipeServerTransport : TServerTransport private volatile bool _isPending = true; private NamedPipeServerStream _stream = null; - public TNamedPipeServerTransport(string pipeAddress) + public TNamedPipeServerTransport(string pipeAddress, TConfiguration config) + : base(config) { _pipeAddress = pipeAddress; } @@ -224,7 +225,7 @@ protected override async ValueTask AcceptImplementationAsync(Cancell await _stream.WaitForConnectionAsync(cancellationToken); - var trans = new ServerTransport(_stream); + var trans = new ServerTransport(_stream, Configuration); _stream = null; // pass ownership to ServerTransport //_isPending = false; @@ -243,11 +244,12 @@ protected override async ValueTask AcceptImplementationAsync(Cancell } } - private class ServerTransport : TTransport + private class ServerTransport : TEndpointTransport { private readonly NamedPipeServerStream PipeStream; - public ServerTransport(NamedPipeServerStream stream) + public ServerTransport(NamedPipeServerStream stream, TConfiguration config) + : base(config) { PipeStream = stream; } @@ -274,7 +276,10 @@ public override async ValueTask ReadAsync(byte[] buffer, int offset, int le throw new TTransportException(TTransportException.ExceptionType.NotOpen); } - return await PipeStream.ReadAsync(buffer, offset, length, cancellationToken); + CheckReadBytesAvailable(length); + var numBytes = await PipeStream.ReadAsync(buffer, offset, length, cancellationToken); + CountConsumedMessageBytes(numBytes); + return numBytes; } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) @@ -303,6 +308,8 @@ public override async Task FlushAsync(CancellationToken cancellationToken) { await Task.FromCanceled(cancellationToken); } + + ResetConsumedMessageSize(); } protected override void Dispose(bool disposing) diff --git a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs index 86d82e3fc73..6656b641a81 100644 --- a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs @@ -31,14 +31,15 @@ public class TServerSocketTransport : TServerTransport private readonly int _clientTimeout; private TcpListener _server; - public TServerSocketTransport(TcpListener listener, int clientTimeout = 0) + public TServerSocketTransport(TcpListener listener, TConfiguration config, int clientTimeout = 0) + : base(config) { _server = listener; _clientTimeout = clientTimeout; } - public TServerSocketTransport(int port, int clientTimeout = 0) - : this(null, clientTimeout) + public TServerSocketTransport(int port, TConfiguration config, int clientTimeout = 0) + : this(null, config, clientTimeout) { try { @@ -93,7 +94,7 @@ protected override async ValueTask AcceptImplementationAsync(Cancell try { - tSocketTransport = new TSocketTransport(tcpClient) + tSocketTransport = new TSocketTransport(tcpClient,Configuration) { Timeout = _clientTimeout }; diff --git a/lib/netstd/Thrift/Transport/Server/TServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerTransport.cs index dd60f6a125a..31f578d5496 100644 --- a/lib/netstd/Thrift/Transport/Server/TServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TServerTransport.cs @@ -23,6 +23,13 @@ namespace Thrift.Transport // ReSharper disable once InconsistentNaming public abstract class TServerTransport { + public readonly TConfiguration Configuration; + + public TServerTransport(TConfiguration config) + { + Configuration = config ?? new TConfiguration(); + } + public abstract void Listen(); public abstract void Close(); public abstract bool IsClientPending(); diff --git a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs index 231b83f5ac6..9f74562521d 100644 --- a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs @@ -39,10 +39,12 @@ public class TTlsServerSocketTransport : TServerTransport public TTlsServerSocketTransport( TcpListener listener, + TConfiguration config, X509Certificate2 certificate, RemoteCertificateValidationCallback clientCertValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) + : base(config) { if (!certificate.HasPrivateKey) { @@ -59,11 +61,12 @@ public TTlsServerSocketTransport( public TTlsServerSocketTransport( int port, + TConfiguration config, X509Certificate2 certificate, RemoteCertificateValidationCallback clientCertValidator = null, LocalCertificateSelectionCallback localCertificateSelectionCallback = null, SslProtocols sslProtocols = SslProtocols.Tls12) - : this(null, certificate, clientCertValidator, localCertificateSelectionCallback, sslProtocols) + : this(null, config, certificate, clientCertValidator, localCertificateSelectionCallback, sslProtocols) { try { @@ -117,8 +120,8 @@ protected override async ValueTask AcceptImplementationAsync(Cancell client.SendTimeout = client.ReceiveTimeout = _clientTimeout; //wrap the client in an SSL Socket passing in the SSL cert - var tTlsSocket = new TTlsSocketTransport( - client, + var tTlsSocket = new TTlsSocketTransport( + client, Configuration, _serverCertificate, true, _clientCertValidator, _localCertificateSelectionCallback, _sslProtocols); diff --git a/lib/netstd/Thrift/Transport/TEndpointTransport.cs b/lib/netstd/Thrift/Transport/TEndpointTransport.cs new file mode 100644 index 00000000000..810f3f4ad64 --- /dev/null +++ b/lib/netstd/Thrift/Transport/TEndpointTransport.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; + +namespace Thrift.Transport +{ + + abstract public class TEndpointTransport : TTransport + { + protected long MaxMessageSize { get => Configuration.MaxMessageSize; } + protected long RemainingMessageSize { get; private set; } + + private readonly TConfiguration _configuration; + public override TConfiguration Configuration { get => _configuration; } + + public TEndpointTransport( TConfiguration config) + { + _configuration = config ?? new TConfiguration(); + Debug.Assert(Configuration != null); + + ResetConsumedMessageSize(); + } + + /// + /// Resets RemainingMessageSize to the configured maximum + /// + protected void ResetConsumedMessageSize(long knownSize = -1) + { + if(knownSize >= 0) + RemainingMessageSize = Math.Min( MaxMessageSize, knownSize); + else + RemainingMessageSize = MaxMessageSize; + } + + /// + /// Updates RemainingMessageSize to reflect then known real message size (e.g. framed transport). + /// Will throw if we already consumed too many bytes. + /// + /// + public override void UpdateKnownMessageSize(long size) + { + var consumed = MaxMessageSize - RemainingMessageSize; + ResetConsumedMessageSize(size); + CountConsumedMessageBytes(consumed); + } + + /// + /// Throws if there are not enough bytes in the input stream to satisfy a read of numBytes bytes of data + /// + /// + protected void CheckReadBytesAvailable(long numBytes) + { + if (RemainingMessageSize < numBytes) + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "MaxMessageSize reached"); + } + + /// + /// Consumes numBytes from the RemainingMessageSize. + /// + /// + protected void CountConsumedMessageBytes(long numBytes) + { + if (RemainingMessageSize >= numBytes) + { + RemainingMessageSize -= numBytes; + } + else + { + RemainingMessageSize = 0; + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "MaxMessageSize reached"); + } + } + } +} diff --git a/lib/netstd/Thrift/Transport/TTransport.cs b/lib/netstd/Thrift/Transport/TTransport.cs index 7998012025e..8f510ddb935 100644 --- a/lib/netstd/Thrift/Transport/TTransport.cs +++ b/lib/netstd/Thrift/Transport/TTransport.cs @@ -30,7 +30,10 @@ public abstract class TTransport : IDisposable //TODO: think how to avoid peek byte private readonly byte[] _peekBuffer = new byte[1]; private bool _hasPeekByte; + public abstract bool IsOpen { get; } + public abstract TConfiguration Configuration { get; } + public abstract void UpdateKnownMessageSize(long size); public void Dispose() { diff --git a/test/netstd/Client/Performance/PerformanceTests.cs b/test/netstd/Client/Performance/PerformanceTests.cs index 041d12eaea9..05c64b240d5 100644 --- a/test/netstd/Client/Performance/PerformanceTests.cs +++ b/test/netstd/Client/Performance/PerformanceTests.cs @@ -20,6 +20,7 @@ using System.Text; using ThriftTest; using Thrift.Collections; +using Thrift; using Thrift.Protocol; using System.Threading; using Thrift.Transport.Client; @@ -36,6 +37,7 @@ public class PerformanceTests private TMemoryBufferTransport MemBuffer; private TTransport Transport; private LayeredChoice Layered; + private readonly TConfiguration Configuration = new TConfiguration(); internal static int Execute() { @@ -52,6 +54,11 @@ internal static int Execute() return 0; } + public PerformanceTests() + { + Configuration.MaxFrameSize = Configuration.MaxMessageSize; // default frame size is too small for this test + } + private async Task ProtocolPeformanceTestAsync() { Console.WriteLine("Setting up for ProtocolPeformanceTestAsync ..."); @@ -76,9 +83,9 @@ private Task GenericProtocolFactory(bool forWrite) { // read happens after write here, so let's take over the written bytes if (forWrite) - MemBuffer = new TMemoryBufferTransport(); + MemBuffer = new TMemoryBufferTransport(Configuration); else - MemBuffer = new TMemoryBufferTransport(MemBuffer.GetBuffer()); + MemBuffer = new TMemoryBufferTransport(MemBuffer.GetBuffer(), Configuration); // layered transports anyone? switch (Layered) diff --git a/test/netstd/Client/TestClient.cs b/test/netstd/Client/TestClient.cs index 13ae3134303..0c147dcc73b 100644 --- a/test/netstd/Client/TestClient.cs +++ b/test/netstd/Client/TestClient.cs @@ -28,6 +28,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Thrift; using Thrift.Collections; using Thrift.Protocol; using Thrift.Transport; @@ -72,6 +73,7 @@ private class TestParams public LayeredChoice layered = LayeredChoice.None; public ProtocolChoice protocol = ProtocolChoice.Binary; public TransportChoice transport = TransportChoice.Socket; + private readonly TConfiguration Configuration = null; // or new TConfiguration() if needed internal void Parse(List args) { @@ -235,12 +237,12 @@ public TTransport CreateTransport() { case TransportChoice.Http: Debug.Assert(url != null); - trans = new THttpTransport(new Uri(url), null); + trans = new THttpTransport(new Uri(url), Configuration); break; case TransportChoice.NamedPipe: Debug.Assert(pipe != null); - trans = new TNamedPipeTransport(pipe); + trans = new TNamedPipeTransport(pipe,Configuration); break; case TransportChoice.TlsSocket: @@ -250,14 +252,15 @@ public TTransport CreateTransport() throw new InvalidOperationException("Certificate doesn't contain private key"); } - trans = new TTlsSocketTransport(host, port, 0, cert, + trans = new TTlsSocketTransport(host, port, Configuration, 0, + cert, (sender, certificate, chain, errors) => true, null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); break; case TransportChoice.Socket: default: - trans = new TSocketTransport(host, port); + trans = new TSocketTransport(host, port, Configuration); break; } diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs index 280f4e98381..68461dc9c05 100644 --- a/test/netstd/Server/TestServer.cs +++ b/test/netstd/Server/TestServer.cs @@ -148,6 +148,8 @@ internal static void PrintOptionsHelp() public class TestServer { public static int _clientID = -1; + private static readonly TConfiguration Configuration = null; // or new TConfiguration() if needed + public delegate void TestLogDelegate(string msg, params object[] values); public class MyServerEventHandler : TServerEventHandler @@ -552,7 +554,7 @@ public static int Execute(List args) { case TransportChoice.NamedPipe: Debug.Assert(param.pipe != null); - trans = new TNamedPipeServerTransport(param.pipe); + trans = new TNamedPipeServerTransport(param.pipe, Configuration); break; @@ -564,14 +566,15 @@ public static int Execute(List args) throw new InvalidOperationException("Certificate doesn't contain private key"); } - trans = new TTlsServerSocketTransport( param.port, cert, + trans = new TTlsServerSocketTransport(param.port, Configuration, + cert, (sender, certificate, chain, errors) => true, null, SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12); break; case TransportChoice.Socket: default: - trans = new TServerSocketTransport(param.port, 0); + trans = new TServerSocketTransport(param.port, Configuration); break; } diff --git a/tutorial/netstd/Client/Program.cs b/tutorial/netstd/Client/Program.cs index f9509fa2d9a..857b3e80836 100644 --- a/tutorial/netstd/Client/Program.cs +++ b/tutorial/netstd/Client/Program.cs @@ -40,6 +40,7 @@ public class Program { private static ServiceCollection ServiceCollection = new ServiceCollection(); private static ILogger Logger; + private static readonly TConfiguration Configuration = null; // new TConfiguration() if needed private static void DisplayHelp() { @@ -143,7 +144,7 @@ private static async Task RunAsync(string[] args, CancellationToken cancellation private static TTransport GetTransport(string[] args) { - TTransport transport = new TSocketTransport(IPAddress.Loopback, 9090); + TTransport transport = new TSocketTransport(IPAddress.Loopback, 9090, Configuration); // construct endpoint transport var transportArg = args.FirstOrDefault(x => x.StartsWith("-tr"))?.Split(':')?[1]; @@ -152,19 +153,20 @@ private static TTransport GetTransport(string[] args) switch (selectedTransport) { case Transport.Tcp: - transport = new TSocketTransport(IPAddress.Loopback, 9090); + transport = new TSocketTransport(IPAddress.Loopback, 9090, Configuration); break; case Transport.NamedPipe: - transport = new TNamedPipeTransport(".test"); + transport = new TNamedPipeTransport(".test", Configuration); break; case Transport.Http: - transport = new THttpTransport(new Uri("http://localhost:9090"), null); + transport = new THttpTransport(new Uri("http://localhost:9090"), Configuration); break; case Transport.TcpTls: - transport = new TTlsSocketTransport(IPAddress.Loopback, 9090, GetCertificate(), CertValidator, LocalCertificateSelectionCallback); + transport = new TTlsSocketTransport(IPAddress.Loopback, 9090, Configuration, + GetCertificate(), CertValidator, LocalCertificateSelectionCallback); break; default: diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs index e1dab01e032..c1e0cb3ece9 100644 --- a/tutorial/netstd/Server/Program.cs +++ b/tutorial/netstd/Server/Program.cs @@ -44,6 +44,7 @@ public class Program { private static ServiceCollection ServiceCollection = new ServiceCollection(); private static ILogger Logger; + private static readonly TConfiguration Configuration = null; // new TConfiguration() if needed public static void Main(string[] args) { @@ -163,13 +164,14 @@ private static async Task RunSelectedConfigurationAsync(Transport transport, Buf switch (transport) { case Transport.Tcp: - serverTransport = new TServerSocketTransport(9090); + serverTransport = new TServerSocketTransport(9090, Configuration); break; case Transport.NamedPipe: - serverTransport = new TNamedPipeServerTransport(".test"); + serverTransport = new TNamedPipeServerTransport(".test", Configuration); break; case Transport.TcpTls: - serverTransport = new TTlsServerSocketTransport(9090, GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback); + serverTransport = new TTlsServerSocketTransport(9090, Configuration, + GetCertificate(), ClientCertValidator, LocalCertificateSelectionCallback); break; } From 9d958a3caf5c82b25a00b0b6cd4ab431bc1fed18 Mon Sep 17 00:00:00 2001 From: zembord Date: Thu, 21 Nov 2019 13:11:44 +0300 Subject: [PATCH 439/756] THRIFT-5010 BinaryPrimitives.Read/WriteInt32BigEndian should be used to convert to/from network byte order Client: netstd Patch: Edward Zhuravlov This closes #1944 --- lib/netstd/Thrift/Protocol/TBinaryProtocol.cs | 48 +++---------------- .../Thrift/Protocol/TCompactProtocol.cs | 40 ++-------------- .../Transport/Layered/TFramedTransport.cs | 23 ++------- 3 files changed, 14 insertions(+), 97 deletions(-) diff --git a/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs index 3f30d4aa161..f0772aa516d 100644 --- a/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs @@ -16,6 +16,7 @@ // under the License. using System; +using System.Buffers.Binary; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -215,9 +216,7 @@ public override async Task WriteI16Async(short i16, CancellationToken cancellati { return; } - - PreAllocatedBuffer[0] = (byte)(0xff & (i16 >> 8)); - PreAllocatedBuffer[1] = (byte)(0xff & i16); + BinaryPrimitives.WriteInt16BigEndian(PreAllocatedBuffer, i16); await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken); } @@ -229,10 +228,7 @@ public override async Task WriteI32Async(int i32, CancellationToken cancellation return; } - PreAllocatedBuffer[0] = (byte)(0xff & (i32 >> 24)); - PreAllocatedBuffer[1] = (byte)(0xff & (i32 >> 16)); - PreAllocatedBuffer[2] = (byte)(0xff & (i32 >> 8)); - PreAllocatedBuffer[3] = (byte)(0xff & i32); + BinaryPrimitives.WriteInt32BigEndian(PreAllocatedBuffer, i32); await Trans.WriteAsync(PreAllocatedBuffer, 0, 4, cancellationToken); } @@ -245,14 +241,7 @@ public override async Task WriteI64Async(long i64, CancellationToken cancellatio return; } - PreAllocatedBuffer[0] = (byte)(0xff & (i64 >> 56)); - PreAllocatedBuffer[1] = (byte)(0xff & (i64 >> 48)); - PreAllocatedBuffer[2] = (byte)(0xff & (i64 >> 40)); - PreAllocatedBuffer[3] = (byte)(0xff & (i64 >> 32)); - PreAllocatedBuffer[4] = (byte)(0xff & (i64 >> 24)); - PreAllocatedBuffer[5] = (byte)(0xff & (i64 >> 16)); - PreAllocatedBuffer[6] = (byte)(0xff & (i64 >> 8)); - PreAllocatedBuffer[7] = (byte)(0xff & i64); + BinaryPrimitives.WriteInt64BigEndian(PreAllocatedBuffer, i64); await Trans.WriteAsync(PreAllocatedBuffer, 0, 8, cancellationToken); } @@ -470,7 +459,7 @@ public override async ValueTask ReadI16Async(CancellationToken cancellati } await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 2, cancellationToken); - var result = (short) (((PreAllocatedBuffer[0] & 0xff) << 8) | PreAllocatedBuffer[1] & 0xff); + var result = BinaryPrimitives.ReadInt16BigEndian(PreAllocatedBuffer); return result; } @@ -483,34 +472,11 @@ public override async ValueTask ReadI32Async(CancellationToken cancellation await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 4, cancellationToken); - var result = - ((PreAllocatedBuffer[0] & 0xff) << 24) | - ((PreAllocatedBuffer[1] & 0xff) << 16) | - ((PreAllocatedBuffer[2] & 0xff) << 8) | - PreAllocatedBuffer[3] & 0xff; - - return result; - } - -#pragma warning disable 675 - - protected internal long ReadI64FromPreAllocatedBuffer() - { - var result = - ((long) (PreAllocatedBuffer[0] & 0xff) << 56) | - ((long) (PreAllocatedBuffer[1] & 0xff) << 48) | - ((long) (PreAllocatedBuffer[2] & 0xff) << 40) | - ((long) (PreAllocatedBuffer[3] & 0xff) << 32) | - ((long) (PreAllocatedBuffer[4] & 0xff) << 24) | - ((long) (PreAllocatedBuffer[5] & 0xff) << 16) | - ((long) (PreAllocatedBuffer[6] & 0xff) << 8) | - PreAllocatedBuffer[7] & 0xff; + var result = BinaryPrimitives.ReadInt32BigEndian(PreAllocatedBuffer); return result; } -#pragma warning restore 675 - public override async ValueTask ReadI64Async(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) @@ -519,7 +485,7 @@ public override async ValueTask ReadI64Async(CancellationToken cancellatio } await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken); - return ReadI64FromPreAllocatedBuffer(); + return BinaryPrimitives.ReadInt64BigEndian(PreAllocatedBuffer); } public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) diff --git a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs index c26633a14c0..921507c4806 100644 --- a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs @@ -16,6 +16,7 @@ // under the License. using System; +using System.Buffers.Binary; using System.Collections.Generic; using System.Diagnostics; using System.Text; @@ -399,8 +400,7 @@ public override async Task WriteDoubleAsync(double d, CancellationToken cancella { return; } - - FixedLongToBytes(BitConverter.DoubleToInt64Bits(d), PreAllocatedBuffer, 0); + BinaryPrimitives.WriteInt64LittleEndian(PreAllocatedBuffer, BitConverter.DoubleToInt64Bits(d)); await Trans.WriteAsync(PreAllocatedBuffer, 0, 8, cancellationToken); } @@ -683,8 +683,8 @@ public override async ValueTask ReadDoubleAsync(CancellationToken cancel } await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken); - - return BitConverter.Int64BitsToDouble(BytesToLong(PreAllocatedBuffer)); + + return BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64LittleEndian(PreAllocatedBuffer)); } public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) @@ -838,25 +838,6 @@ private static long ZigzagToLong(ulong n) return (long) (n >> 1) ^ -(long) (n & 1); } - private static long BytesToLong(byte[] bytes) - { - /* - 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. - */ - - 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); - } - private static TType GetTType(byte type) { // Given a TCompactProtocol.Types constant, convert it to its corresponding TType value. @@ -875,19 +856,6 @@ private static uint IntToZigzag(int n) return (uint) (n << 1) ^ (uint) (n >> 31); } - private static void FixedLongToBytes(long n, byte[] buf, int off) - { - // Convert a long into little-endian bytes in buf starting at off and going until off+7. - 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); - } - public class Factory : TProtocolFactory { public override TProtocol GetProtocol(TTransport trans) diff --git a/lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs b/lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs index c842a16aaa5..58b45f7434a 100644 --- a/lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs +++ b/lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs @@ -16,6 +16,7 @@ // under the License. using System; +using System.Buffers.Binary; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -86,7 +87,7 @@ public override async ValueTask ReadAsync(byte[] buffer, int offset, int le private async ValueTask ReadFrameAsync(CancellationToken cancellationToken) { await InnerTransport.ReadAllAsync(HeaderBuf, 0, HeaderSize, cancellationToken); - int size = DecodeFrameSize(HeaderBuf); + int size = BinaryPrimitives.ReadInt32BigEndian(HeaderBuf); if ((0 > size) || (size > Configuration.MaxFrameSize)) // size must be in the range 0 to allowed max throw new TTransportException(TTransportException.ExceptionType.Unknown, $"Maximum frame size exceeded ({size} bytes)"); @@ -137,7 +138,7 @@ public override async Task FlushAsync(CancellationToken cancellationToken) } // Inject message header into the reserved buffer space - EncodeFrameSize(dataLen, bufSegment.Array); + BinaryPrimitives.WriteInt32BigEndian(bufSegment.Array, dataLen); // Send the entire message at once await InnerTransport.WriteAsync(bufSegment.Array, 0, bufSegment.Count, cancellationToken); @@ -154,24 +155,6 @@ private void InitWriteBuffer() WriteBuffer.Seek(0, SeekOrigin.End); } - private static void EncodeFrameSize(int frameSize, 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)); - } - - private static int DecodeFrameSize(byte[] buf) - { - return - ((buf[0] & 0xff) << 24) | - ((buf[1] & 0xff) << 16) | - ((buf[2] & 0xff) << 8) | - (buf[3] & 0xff); - } - - private void CheckNotDisposed() { if (IsDisposed) From b541c6f2b126219867963c8b577b4c08d72e866d Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 23 Nov 2019 18:50:22 +0100 Subject: [PATCH 440/756] THRIFT-5026 TestClient/Server ignores first cmdline argument Client: netstd Patch: Jens Geyer This closes #1945 --- test/netstd/Client/Program.cs | 16 ++++------------ test/netstd/Server/Program.cs | 16 ++++------------ 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/test/netstd/Client/Program.cs b/test/netstd/Client/Program.cs index 8dbff1a23c8..47dabd3c903 100644 --- a/test/netstd/Client/Program.cs +++ b/test/netstd/Client/Program.cs @@ -34,17 +34,9 @@ public static int Main(string[] args) Console.WriteLine("Failed to grow scroll-back buffer"); } - // split mode and options - var subArgs = new List(args); - var firstArg = string.Empty; - if (subArgs.Count > 0) - { - firstArg = subArgs[0]; - subArgs.RemoveAt(0); - } - - // run whatever mode is choosen - switch(firstArg) + // run whatever mode is choosen, default to test impl + var firstArg = args.Length > 0 ? args[0] : string.Empty; + switch (firstArg) { case "client": Console.WriteLine("The 'client' argument is no longer required."); @@ -56,7 +48,7 @@ public static int Main(string[] args) PrintHelp(); return 0; default: - return TestClient.Execute(subArgs); + return TestClient.Execute(new List(args)); } } diff --git a/test/netstd/Server/Program.cs b/test/netstd/Server/Program.cs index 4525ab75cd8..1b8ffd46a8e 100644 --- a/test/netstd/Server/Program.cs +++ b/test/netstd/Server/Program.cs @@ -34,17 +34,9 @@ public static int Main(string[] args) Console.WriteLine("Failed to grow scroll-back buffer"); } - // split mode and options - var subArgs = new List(args); - var firstArg = string.Empty; - if (subArgs.Count > 0) - { - firstArg = subArgs[0]; - subArgs.RemoveAt(0); - } - - // run whatever mode is choosen - switch(firstArg) + // run whatever mode is choosen, default to test impl + var firstArg = args.Length > 0 ? args[0] : string.Empty; + switch (firstArg) { case "server": Console.WriteLine("The 'server' argument is no longer required."); @@ -54,7 +46,7 @@ public static int Main(string[] args) PrintHelp(); return 0; default: - return TestServer.Execute(subArgs); + return TestServer.Execute(new List( args)); } } From 5080645cb0ffe52de9d82685b2ab2d6b03aa6f3e Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 23 Nov 2019 01:55:58 +0100 Subject: [PATCH 441/756] THRIFT-5027 Implement remaining read bytes checks Client: netstd Patch: Jens Geyer This closes #1946 --- lib/netstd/Thrift/Protocol/TBinaryProtocol.cs | 30 +++++++++++++++-- .../Thrift/Protocol/TCompactProtocol.cs | 32 +++++++++++++++++-- lib/netstd/Thrift/Protocol/TJSONProtocol.cs | 25 +++++++++++++++ lib/netstd/Thrift/Protocol/TProtocol.cs | 21 ++++++++++++ .../Thrift/Protocol/TProtocolDecorator.cs | 8 +++++ .../Client/TMemoryBufferTransport.cs | 2 +- .../Transport/Layered/TBufferedTransport.cs | 11 +++++++ .../Transport/Layered/TFramedTransport.cs | 10 ++++++ .../Transport/Layered/TLayeredTransport.cs | 5 +++ .../Thrift/Transport/TEndpointTransport.cs | 26 +++++++++++---- lib/netstd/Thrift/Transport/TTransport.cs | 2 +- .../Client/Performance/PerformanceTests.cs | 3 +- test/netstd/Client/TestClient.cs | 6 ++-- 13 files changed, 162 insertions(+), 19 deletions(-) diff --git a/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs index f0772aa516d..a00c5c162bb 100644 --- a/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs @@ -370,7 +370,7 @@ public override async ValueTask ReadMapBeginAsync(CancellationToken cancel ValueType = (TType) await ReadByteAsync(cancellationToken), Count = await ReadI32Async(cancellationToken) }; - + CheckReadBytesAvailable(map); return map; } @@ -394,7 +394,7 @@ public override async ValueTask ReadListBeginAsync(CancellationToken canc ElementType = (TType) await ReadByteAsync(cancellationToken), Count = await ReadI32Async(cancellationToken) }; - + CheckReadBytesAvailable(list); return list; } @@ -418,7 +418,7 @@ public override async ValueTask ReadSetBeginAsync(CancellationToken cancel ElementType = (TType) await ReadByteAsync(cancellationToken), Count = await ReadI32Async(cancellationToken) }; - + CheckReadBytesAvailable(set); return set; } @@ -507,6 +507,7 @@ public override async ValueTask ReadBinaryAsync(CancellationToken cancel } var size = await ReadI32Async(cancellationToken); + Transport.CheckReadBytesAvailable(size); var buf = new byte[size]; await Trans.ReadAllAsync(buf, 0, size, cancellationToken); return buf; @@ -536,11 +537,34 @@ private async ValueTask ReadStringBodyAsync(int size, CancellationToken return Encoding.UTF8.GetString(PreAllocatedBuffer, 0, size); } + Transport.CheckReadBytesAvailable(size); var buf = new byte[size]; await Trans.ReadAllAsync(buf, 0, size, cancellationToken); return Encoding.UTF8.GetString(buf, 0, buf.Length); } + // Return the minimum number of bytes a type will consume on the wire + public override int GetMinSerializedSize(TType type) + { + switch (type) + { + case TType.Stop: return 0; + case TType.Void: return 0; + case TType.Bool: return sizeof(byte); + case TType.Byte: return sizeof(byte); + case TType.Double: return sizeof(double); + case TType.I16: return sizeof(short); + case TType.I32: return sizeof(int); + case TType.I64: return sizeof(long); + case TType.String: return sizeof(int); // string length + case TType.Struct: return 0; // empty struct + case TType.Map: return sizeof(int); // element count + case TType.Set: return sizeof(int); // element count + case TType.List: return sizeof(int); // element count + default: throw new TTransportException(TTransportException.ExceptionType.Unknown, "unrecognized type code"); + } + } + public class Factory : TProtocolFactory { protected bool StrictRead; diff --git a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs index 921507c4806..a8a46f2a4fc 100644 --- a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs @@ -590,7 +590,9 @@ and value exType. This means that 0-length maps will yield TMaps without the var size = (int) await ReadVarInt32Async(cancellationToken); var keyAndValueType = size == 0 ? (byte) 0 : (byte) await ReadByteAsync(cancellationToken); - return new TMap(GetTType((byte) (keyAndValueType >> 4)), GetTType((byte) (keyAndValueType & 0xf)), size); + var map = new TMap(GetTType((byte) (keyAndValueType >> 4)), GetTType((byte) (keyAndValueType & 0xf)), size); + CheckReadBytesAvailable(map); + return map; } public override async Task ReadMapEndAsync(CancellationToken cancellationToken) @@ -703,6 +705,7 @@ public override async ValueTask ReadStringAsync(CancellationToken cancel return Encoding.UTF8.GetString(PreAllocatedBuffer, 0, length); } + Transport.CheckReadBytesAvailable(length); var buf = new byte[length]; await Trans.ReadAllAsync(buf, 0, length, cancellationToken); return Encoding.UTF8.GetString(buf, 0, length); @@ -718,6 +721,7 @@ public override async ValueTask ReadBinaryAsync(CancellationToken cancel } // read data + Transport.CheckReadBytesAvailable(length); var buf = new byte[length]; await Trans.ReadAllAsync(buf, 0, length, cancellationToken); return buf; @@ -745,7 +749,9 @@ true size. } var type = GetTType(sizeAndType); - return new TList(type, size); + var list = new TList(type, size); + CheckReadBytesAvailable(list); + return list; } public override async Task ReadListEndAsync(CancellationToken cancellationToken) @@ -856,6 +862,28 @@ private static uint IntToZigzag(int n) return (uint) (n << 1) ^ (uint) (n >> 31); } + // Return the minimum number of bytes a type will consume on the wire + public override int GetMinSerializedSize(TType type) + { + switch (type) + { + case TType.Stop: return 0; + case TType.Void: return 0; + case TType.Bool: return sizeof(byte); + case TType.Double: return 8; // uses fixedLongToBytes() which always writes 8 bytes + case TType.Byte: return sizeof(byte); + case TType.I16: return sizeof(byte); // zigzag + case TType.I32: return sizeof(byte); // zigzag + case TType.I64: return sizeof(byte); // zigzag + case TType.String: return sizeof(byte); // string length + case TType.Struct: return 0; // empty struct + case TType.Map: return sizeof(byte); // element count + case TType.Set: return sizeof(byte); // element count + case TType.List: return sizeof(byte); // element count + default: throw new TTransportException(TTransportException.ExceptionType.Unknown, "unrecognized type code"); + } + } + public class Factory : TProtocolFactory { public override TProtocol GetProtocol(TTransport trans) diff --git a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs index 464bd62ff99..7bc713054aa 100644 --- a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs @@ -703,6 +703,7 @@ public override async ValueTask ReadMapBeginAsync(CancellationToken cancel map.KeyType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); map.ValueType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); map.Count = (int) await ReadJsonIntegerAsync(cancellationToken); + CheckReadBytesAvailable(map); await ReadJsonObjectStartAsync(cancellationToken); return map; } @@ -719,6 +720,7 @@ public override async ValueTask ReadListBeginAsync(CancellationToken canc await ReadJsonArrayStartAsync(cancellationToken); list.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); list.Count = (int) await ReadJsonIntegerAsync(cancellationToken); + CheckReadBytesAvailable(list); return list; } @@ -733,6 +735,7 @@ public override async ValueTask ReadSetBeginAsync(CancellationToken cancel await ReadJsonArrayStartAsync(cancellationToken); set.ElementType = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); set.Count = (int) await ReadJsonIntegerAsync(cancellationToken); + CheckReadBytesAvailable(set); return set; } @@ -782,6 +785,28 @@ public override async ValueTask ReadBinaryAsync(CancellationToken cancel return await ReadJsonBase64Async(cancellationToken); } + // Return the minimum number of bytes a type will consume on the wire + public override int GetMinSerializedSize(TType type) + { + switch (type) + { + case TType.Stop: return 0; + case TType.Void: return 0; + case TType.Bool: return 1; // written as int + case TType.Byte: return 1; + case TType.Double: return 1; + case TType.I16: return 1; + case TType.I32: return 1; + case TType.I64: return 1; + case TType.String: return 2; // empty string + case TType.Struct: return 2; // empty struct + case TType.Map: return 2; // empty map + case TType.Set: return 2; // empty set + case TType.List: return 2; // empty list + default: throw new TTransportException(TTransportException.ExceptionType.Unknown, "unrecognized type code"); + } + } + /// /// Factory for JSON protocol objects /// diff --git a/lib/netstd/Thrift/Protocol/TProtocol.cs b/lib/netstd/Thrift/Protocol/TProtocol.cs index dca3f9efc85..5275c9cd18c 100644 --- a/lib/netstd/Thrift/Protocol/TProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TProtocol.cs @@ -77,6 +77,27 @@ protected virtual void Dispose(bool disposing) _isDisposed = true; } + + protected void CheckReadBytesAvailable(TSet set) + { + Transport.CheckReadBytesAvailable(set.Count * GetMinSerializedSize(set.ElementType)); + } + + protected void CheckReadBytesAvailable(TList list) + { + Transport.CheckReadBytesAvailable(list.Count * GetMinSerializedSize(list.ElementType)); + } + + protected void CheckReadBytesAvailable(TMap map) + { + var elmSize = GetMinSerializedSize(map.KeyType) + GetMinSerializedSize(map.ValueType); + Transport.CheckReadBytesAvailable(map.Count * elmSize); + } + + // Returns the minimum amount of bytes needed to store the smallest possible instance of TType. + public abstract int GetMinSerializedSize(TType type); + + public virtual async Task WriteMessageBeginAsync(TMessage message) { await WriteMessageBeginAsync(message, CancellationToken.None); diff --git a/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs b/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs index 845c8274908..b032e836a60 100644 --- a/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs +++ b/lib/netstd/Thrift/Protocol/TProtocolDecorator.cs @@ -243,5 +243,13 @@ public override async ValueTask ReadBinaryAsync(CancellationToken cancel { return await _wrappedProtocol.ReadBinaryAsync(cancellationToken); } + + // Returns the minimum amount of bytes needed to store the smallest possible instance of TType. + public override int GetMinSerializedSize(TType type) + { + return _wrappedProtocol.GetMinSerializedSize(type); + } + + } } diff --git a/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs index abf8f14c404..290e50cc5ea 100644 --- a/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs @@ -41,6 +41,7 @@ public TMemoryBufferTransport(byte[] buf, TConfiguration config) { Bytes = (byte[])buf.Clone(); _bytesUsed = Bytes.Length; + UpdateKnownMessageSize(_bytesUsed); } public int Position { get; set; } @@ -121,7 +122,6 @@ public void Seek(int delta, SeekOrigin origin) public override ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { - CheckReadBytesAvailable(length); var count = Math.Min(Length - Position, length); Buffer.BlockCopy(Bytes, Position, buffer, offset, count); Position += count; diff --git a/lib/netstd/Thrift/Transport/Layered/TBufferedTransport.cs b/lib/netstd/Thrift/Transport/Layered/TBufferedTransport.cs index 10cec3c3d52..dee52ddb18c 100644 --- a/lib/netstd/Thrift/Transport/Layered/TBufferedTransport.cs +++ b/lib/netstd/Thrift/Transport/Layered/TBufferedTransport.cs @@ -172,6 +172,17 @@ public override async Task FlushAsync(CancellationToken cancellationToken) await InnerTransport.FlushAsync(cancellationToken); } + public override void CheckReadBytesAvailable(long numBytes) + { + var buffered = ReadBuffer.Length - ReadBuffer.Position; + if (buffered < numBytes) + { + numBytes -= buffered; + InnerTransport.CheckReadBytesAvailable(numBytes); + } + } + + private void CheckNotDisposed() { if (IsDisposed) diff --git a/lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs b/lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs index 58b45f7434a..be1513fcf9c 100644 --- a/lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs +++ b/lib/netstd/Thrift/Transport/Layered/TFramedTransport.cs @@ -155,6 +155,16 @@ private void InitWriteBuffer() WriteBuffer.Seek(0, SeekOrigin.End); } + public override void CheckReadBytesAvailable(long numBytes) + { + var buffered = ReadBuffer.Length - ReadBuffer.Position; + if (buffered < numBytes) + { + numBytes -= buffered; + InnerTransport.CheckReadBytesAvailable(numBytes); + } + } + private void CheckNotDisposed() { if (IsDisposed) diff --git a/lib/netstd/Thrift/Transport/Layered/TLayeredTransport.cs b/lib/netstd/Thrift/Transport/Layered/TLayeredTransport.cs index 59d98ff1d0d..2137ae458ff 100644 --- a/lib/netstd/Thrift/Transport/Layered/TLayeredTransport.cs +++ b/lib/netstd/Thrift/Transport/Layered/TLayeredTransport.cs @@ -19,5 +19,10 @@ public override void UpdateKnownMessageSize(long size) { InnerTransport.UpdateKnownMessageSize(size); } + + public override void CheckReadBytesAvailable(long numBytes) + { + InnerTransport.CheckReadBytesAvailable(numBytes); + } } } diff --git a/lib/netstd/Thrift/Transport/TEndpointTransport.cs b/lib/netstd/Thrift/Transport/TEndpointTransport.cs index 810f3f4ad64..fa2ac6bddc0 100644 --- a/lib/netstd/Thrift/Transport/TEndpointTransport.cs +++ b/lib/netstd/Thrift/Transport/TEndpointTransport.cs @@ -9,6 +9,7 @@ namespace Thrift.Transport abstract public class TEndpointTransport : TTransport { protected long MaxMessageSize { get => Configuration.MaxMessageSize; } + protected long KnownMessageSize { get; private set; } protected long RemainingMessageSize { get; private set; } private readonly TConfiguration _configuration; @@ -25,22 +26,33 @@ public TEndpointTransport( TConfiguration config) /// /// Resets RemainingMessageSize to the configured maximum /// - protected void ResetConsumedMessageSize(long knownSize = -1) + protected void ResetConsumedMessageSize(long newSize = -1) { - if(knownSize >= 0) - RemainingMessageSize = Math.Min( MaxMessageSize, knownSize); - else + // full reset + if (newSize < 0) + { + KnownMessageSize = MaxMessageSize; RemainingMessageSize = MaxMessageSize; + return; + } + + // update only: message size can shrink, but not grow + Debug.Assert(KnownMessageSize <= MaxMessageSize); + if (newSize > KnownMessageSize) + throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "MaxMessageSize reached"); + + KnownMessageSize = newSize; + RemainingMessageSize = newSize; } /// /// Updates RemainingMessageSize to reflect then known real message size (e.g. framed transport). - /// Will throw if we already consumed too many bytes. + /// Will throw if we already consumed too many bytes or if the new size is larger than allowed. /// /// public override void UpdateKnownMessageSize(long size) { - var consumed = MaxMessageSize - RemainingMessageSize; + var consumed = KnownMessageSize - RemainingMessageSize; ResetConsumedMessageSize(size); CountConsumedMessageBytes(consumed); } @@ -49,7 +61,7 @@ public override void UpdateKnownMessageSize(long size) /// Throws if there are not enough bytes in the input stream to satisfy a read of numBytes bytes of data /// /// - protected void CheckReadBytesAvailable(long numBytes) + public override void CheckReadBytesAvailable(long numBytes) { if (RemainingMessageSize < numBytes) throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "MaxMessageSize reached"); diff --git a/lib/netstd/Thrift/Transport/TTransport.cs b/lib/netstd/Thrift/Transport/TTransport.cs index 8f510ddb935..dedd51dc520 100644 --- a/lib/netstd/Thrift/Transport/TTransport.cs +++ b/lib/netstd/Thrift/Transport/TTransport.cs @@ -34,7 +34,7 @@ public abstract class TTransport : IDisposable public abstract bool IsOpen { get; } public abstract TConfiguration Configuration { get; } public abstract void UpdateKnownMessageSize(long size); - + public abstract void CheckReadBytesAvailable(long numBytes); public void Dispose() { Dispose(true); diff --git a/test/netstd/Client/Performance/PerformanceTests.cs b/test/netstd/Client/Performance/PerformanceTests.cs index 05c64b240d5..2c79aa6ef22 100644 --- a/test/netstd/Client/Performance/PerformanceTests.cs +++ b/test/netstd/Client/Performance/PerformanceTests.cs @@ -68,10 +68,9 @@ private async Task ProtocolPeformanceTestAsync() foreach (var layered in Enum.GetValues(typeof(LayeredChoice))) { Layered = (LayeredChoice)layered; - await RunTestAsync(async (bool b) => { return await GenericProtocolFactory(b); }); await RunTestAsync(async (bool b) => { return await GenericProtocolFactory(b); }); - //await RunTestAsync(async (bool b) => { return await GenericProtocolFactory(b); }); + await RunTestAsync(async (bool b) => { return await GenericProtocolFactory(b); }); } } diff --git a/test/netstd/Client/TestClient.cs b/test/netstd/Client/TestClient.cs index 0c147dcc73b..3eab8654500 100644 --- a/test/netstd/Client/TestClient.cs +++ b/test/netstd/Client/TestClient.cs @@ -446,7 +446,7 @@ public enum BinaryTestSize Normal, // Fairly small array of usual size (256 bytes) Large, // Large writes/reads may cause range check errors PipeWriteLimit, // Windows Limit: Pipe write operations across a network are limited to 65,535 bytes per write. - TwentyMB // that's quite a bit of data + FifteenMB // that's quite a bit of data }; public static byte[] PrepareTestData(bool randomDist, BinaryTestSize testcase) @@ -466,8 +466,8 @@ public static byte[] PrepareTestData(bool randomDist, BinaryTestSize testcase) case BinaryTestSize.PipeWriteLimit: amount = 0xFFFF + 128; break; - case BinaryTestSize.TwentyMB: - amount = 20 * 1024 * 1024; + case BinaryTestSize.FifteenMB: + amount = 15 * 1024 * 1024; break; default: throw new ArgumentException(nameof(testcase)); From 622937162aeccf2a27d9196937ebf7ead40036f5 Mon Sep 17 00:00:00 2001 From: Andy Seaborne Date: Mon, 25 Nov 2019 09:58:52 +0000 Subject: [PATCH 442/756] THRIFT-5022: Fix TIOStreamTransport.isOpen for input or output only use Client: java This closes #1942. --- CHANGES.md | 3 + .../thrift/transport/TIOStreamTransport.java | 29 +++++---- .../transport/TestTIOStreamTransport.java | 62 +++++++++++++++++++ 3 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 lib/java/test/org/apache/thrift/transport/TestTIOStreamTransport.java diff --git a/CHANGES.md b/CHANGES.md index 2f128684e5d..30622e5fb2e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,9 @@ - [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base - [THRIFT-5006](https://issues.apache.org/jira/browse/THRIFT-5006) - Implement DEFAULT_MAX_LENGTH at TFramedTransport +### Java + +- [THRIFT-5022](https://issues.apache.org/jira/browse/THRIFT-5022) - TIOStreamTransport.isOpen returns true for one-sided transports (see THRIFT-2530). ## 0.13.0 ### New Languages diff --git a/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java b/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java index 2d31f392f43..c6ec02c6c91 100644 --- a/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java @@ -83,7 +83,7 @@ public TIOStreamTransport(InputStream is, OutputStream os) { * @return false after close is called. */ public boolean isOpen() { - return inputStream_ != null && outputStream_ != null; + return inputStream_ != null || outputStream_ != null; } /** @@ -95,20 +95,23 @@ 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); + try { + 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); + if (outputStream_ != null) { + try { + outputStream_.close(); + } catch (IOException iox) { + LOGGER.warn("Error closing output stream.", iox); + } } + } finally { + inputStream_ = null; outputStream_ = null; } } diff --git a/lib/java/test/org/apache/thrift/transport/TestTIOStreamTransport.java b/lib/java/test/org/apache/thrift/transport/TestTIOStreamTransport.java new file mode 100644 index 00000000000..5965446f897 --- /dev/null +++ b/lib/java/test/org/apache/thrift/transport/TestTIOStreamTransport.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 org.apache.thrift.transport; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +import junit.framework.TestCase; + +public class TestTIOStreamTransport extends TestCase { + + // THRIFT-5022 + public void testOpenClose_2streams() throws TTransportException { + byte[] dummy = {20}; // So the input stream isn't EOF immediately. + InputStream input = new ByteArrayInputStream(dummy); + OutputStream output = new ByteArrayOutputStream(); + TTransport transport = new TIOStreamTransport(input, output); + runOpenClose(transport); + } + + // THRIFT-5022 + public void testOpenClose_1input() throws TTransportException { + byte[] dummy = {20}; + InputStream input = new ByteArrayInputStream(dummy); + TTransport transport = new TIOStreamTransport(input); + runOpenClose(transport); + } + + // THRIFT-5022 + public void testIOpenClose_1output() throws TTransportException { + OutputStream output = new ByteArrayOutputStream(); + TTransport transport = new TIOStreamTransport(output); + runOpenClose(transport); + } + + private void runOpenClose(TTransport transport) throws TTransportException { + transport.open(); + boolean b1 = transport.isOpen(); + assertTrue(b1); + transport.close(); + boolean b2 = transport.isOpen(); + assertFalse(b2); + } +} From bf2cad9cfae28b602b5bb899e9becacee975057c Mon Sep 17 00:00:00 2001 From: wineandcheeze Date: Mon, 25 Nov 2019 22:40:52 +0100 Subject: [PATCH 443/756] THRIFT-5031: Fix TIOStreamTransport javadoc Clarify input/output only transport. Client: java This closes #1948. --- .../apache/thrift/transport/TIOStreamTransport.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java b/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java index c6ec02c6c91..d97d5063e93 100644 --- a/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TIOStreamTransport.java @@ -27,8 +27,8 @@ 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 is the most commonly used base transport. It takes an InputStream or + * an OutputStream or both and uses it/them to perform transport operations. * This allows for compatibility with all the nice constructs Java already * has to provide a variety of types of streams. * @@ -50,7 +50,7 @@ public class TIOStreamTransport extends TTransport { protected TIOStreamTransport() {} /** - * Input stream constructor. + * Input stream constructor, constructs an input only transport. * * @param is Input stream to read from */ @@ -59,9 +59,9 @@ public TIOStreamTransport(InputStream is) { } /** - * Output stream constructor. + * Output stream constructor, constructs an output only transport. * - * @param os Output stream to read from + * @param os Output stream to write to */ public TIOStreamTransport(OutputStream os) { outputStream_ = os; From c140bb90b0c2ed6175afe8c9c579acd8ea9c7d0b Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 27 Nov 2019 22:18:12 +0100 Subject: [PATCH 444/756] THRIFT-5036 buffered transport over sockets may run into unexpected timeouts [ci skip] Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.Server.pas | 9 +++------ lib/delphi/src/Thrift.Transport.pas | 2 +- lib/delphi/test/TestServer.pas | 6 ++---- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/lib/delphi/src/Thrift.Server.pas b/lib/delphi/src/Thrift.Server.pas index 654ab99425f..da053b96bc5 100644 --- a/lib/delphi/src/Thrift.Server.pas +++ b/lib/delphi/src/Thrift.Server.pas @@ -390,20 +390,17 @@ procedure TSimpleServer.Serve; end; except - on E: TTransportException do - begin + on E: TTransportException do begin if FStop then FLogDelegate('TSimpleServer was shutting down, caught ' + E.ToString) else FLogDelegate( E.ToString); end; - on E: Exception do - begin + on E: Exception do begin FLogDelegate( E.ToString); end; end; - if context <> nil - then begin + if context <> nil then begin context.CleanupContext; context := nil; end; diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index 7695b22daec..0a9a39e041d 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -1628,7 +1628,7 @@ function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer result := 0; pTmp := pBuf; Inc( pTmp, offset); - while count > 0 do begin + while (count > 0) and (result = 0) do begin while TRUE do begin wfd := WaitForData( msecs, pTmp, count, wsaError, nBytes); diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas index a9c71fb8330..da804fdc027 100644 --- a/lib/delphi/test/TestServer.pas +++ b/lib/delphi/test/TestServer.pas @@ -157,13 +157,11 @@ function TTestServer.TTestHandlerImpl.testEnum(thing: TNumberz): TNumberz; procedure TTestServer.TTestHandlerImpl.testException(const arg: string); begin Console.WriteLine('testException(' + arg + ')'); - if ( arg = 'Xception') then - begin + if ( arg = 'Xception') then begin raise TXception.Create( 1001, arg); end; - if (arg = 'TException') then - begin + if (arg = 'TException') then begin raise TException.Create('TException'); end; From a019cda66ceccdf9068c9f5e2c27f890c450f9ec Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 9 Nov 2019 23:24:52 +0100 Subject: [PATCH 445/756] THRIFT-5012 Centralize configuration aspects into a commonly used configuration object [ci skip] Client: Delphi Patch: Jens Geyer This closes #1955 --- lib/delphi/src/Thrift.Configuration.pas | 121 ++++ lib/delphi/src/Thrift.Protocol.Compact.pas | 3 +- lib/delphi/src/Thrift.Protocol.JSON.pas | 3 +- lib/delphi/src/Thrift.Protocol.pas | 53 +- lib/delphi/src/Thrift.Serializer.pas | 104 ++-- lib/delphi/src/Thrift.Server.pas | 219 ++----- lib/delphi/src/Thrift.Stream.pas | 57 +- lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas | 30 +- lib/delphi/src/Thrift.Transport.Pipes.pas | 110 ++-- lib/delphi/src/Thrift.Transport.WinHTTP.pas | 59 +- lib/delphi/src/Thrift.Transport.pas | 557 ++++++++++-------- lib/delphi/src/Thrift.WinHTTP.pas | 4 +- lib/delphi/test/Performance/PerfTests.pas | 36 +- lib/delphi/test/TestClient.pas | 29 +- lib/delphi/test/TestServer.pas | 5 +- lib/delphi/test/client.dpr | 1 + .../multiplexed/Multiplex.Client.Main.pas | 5 +- .../multiplexed/Multiplex.Server.Main.pas | 6 +- .../multiplexed/Multiplex.Test.Client.dpr | 1 + .../multiplexed/Multiplex.Test.Server.dpr | 1 + .../test/serializer/TestSerializer.Tests.pas | 25 +- lib/delphi/test/serializer/TestSerializer.dpr | 5 +- lib/delphi/test/server.dpr | 1 + lib/delphi/test/skip/skiptest_version1.dpr | 5 +- lib/delphi/test/skip/skiptest_version2.dpr | 5 +- .../test/typeregistry/TestTypeRegistry.dpr | 1 + tutorial/delphi/DelphiClient/DelphiClient.dpr | 1 + .../delphi/DelphiClient/DelphiClient.dproj | 1 + tutorial/delphi/DelphiServer/DelphiServer.dpr | 1 + .../delphi/DelphiServer/DelphiServer.dproj | 1 + 30 files changed, 725 insertions(+), 725 deletions(-) create mode 100644 lib/delphi/src/Thrift.Configuration.pas diff --git a/lib/delphi/src/Thrift.Configuration.pas b/lib/delphi/src/Thrift.Configuration.pas new file mode 100644 index 00000000000..0cb11af350e --- /dev/null +++ b/lib/delphi/src/Thrift.Configuration.pas @@ -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. + *) + +unit Thrift.Configuration; + +interface + +uses + SysUtils, Generics.Collections, Generics.Defaults; + +const + DEFAULT_RECURSION_LIMIT = 64; + DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024; // 100 MB + DEFAULT_MAX_FRAME_SIZE = 16384000; // this value is used consistently across all Thrift libraries + + DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms + +type + IThriftConfiguration = interface + ['{ADD75449-1A67-4B78-9B75-502A1E338CFC}'] + function GetRecursionLimit : Cardinal; + procedure SetRecursionLimit( const value : Cardinal); + function GetMaxFrameSize : Cardinal; + procedure SetMaxFrameSize( const value : Cardinal); + function GetMaxMessageSize : Cardinal; + procedure SetMaxMessageSize( const value : Cardinal); + + property RecursionLimit : Cardinal read GetRecursionLimit write SetRecursionLimit; + property MaxFrameSize : Cardinal read GetMaxFrameSize write SetMaxFrameSize; + property MaxMessageSize : Cardinal read GetMaxMessageSize write SetMaxMessageSize; + end; + + + TThriftConfigurationImpl = class( TInterfacedObject, IThriftConfiguration) + strict protected + FRecursionLimit : Cardinal; + FMaxFrameSize : Cardinal; + FMaxMessageSize : Cardinal; + + // IThriftConfiguration + function GetRecursionLimit : Cardinal; + procedure SetRecursionLimit( const value : Cardinal); + function GetMaxFrameSize : Cardinal; + procedure SetMaxFrameSize( const value : Cardinal); + function GetMaxMessageSize : Cardinal; + procedure SetMaxMessageSize( const value : Cardinal); + + public + constructor Create; + end; + + +implementation + + +{ TThriftConfigurationImpl } + + +constructor TThriftConfigurationImpl.Create; +begin + inherited Create; + + FRecursionLimit := DEFAULT_RECURSION_LIMIT; + FMaxFrameSize := DEFAULT_MAX_FRAME_SIZE; + FMaxMessageSize := DEFAULT_MAX_MESSAGE_SIZE; +end; + + +function TThriftConfigurationImpl.GetRecursionLimit: Cardinal; +begin + result := FRecursionLimit; +end; + + +procedure TThriftConfigurationImpl.SetRecursionLimit(const value: Cardinal); +begin + FRecursionLimit := value; +end; + + +function TThriftConfigurationImpl.GetMaxFrameSize: Cardinal; +begin + result := FMaxFrameSize; +end; + + +procedure TThriftConfigurationImpl.SetMaxFrameSize(const value: Cardinal); +begin + FMaxFrameSize := value; +end; + + +function TThriftConfigurationImpl.GetMaxMessageSize: Cardinal; +begin + result := FMaxMessageSize; +end; + + +procedure TThriftConfigurationImpl.SetMaxMessageSize(const value: Cardinal); +begin + FMaxMessageSize := value; +end; + + +end. diff --git a/lib/delphi/src/Thrift.Protocol.Compact.pas b/lib/delphi/src/Thrift.Protocol.Compact.pas index 109e660644c..665cfc4ba34 100644 --- a/lib/delphi/src/Thrift.Protocol.Compact.pas +++ b/lib/delphi/src/Thrift.Protocol.Compact.pas @@ -28,6 +28,7 @@ interface SysUtils, Math, Generics.Collections, + Thrift.Configuration, Thrift.Transport, Thrift.Protocol, Thrift.Utils; @@ -268,7 +269,7 @@ function TCompactProtocolImpl.TFactory.GetProtocol( const trans: ITransport): IP //--- TCompactProtocolImpl ------------------------------------------------- -constructor TCompactProtocolImpl.Create(const trans: ITransport); +constructor TCompactProtocolImpl.Create( const trans : ITransport); begin inherited Create( trans); diff --git a/lib/delphi/src/Thrift.Protocol.JSON.pas b/lib/delphi/src/Thrift.Protocol.JSON.pas index e72a81dcf90..61cad8b627c 100644 --- a/lib/delphi/src/Thrift.Protocol.JSON.pas +++ b/lib/delphi/src/Thrift.Protocol.JSON.pas @@ -29,6 +29,7 @@ interface SysUtils, Math, Generics.Collections, + Thrift.Configuration, Thrift.Transport, Thrift.Protocol, Thrift.Utils; @@ -298,7 +299,7 @@ implementation function TJSONProtocolImpl.TFactory.GetProtocol( const trans: ITransport): IProtocol; begin - result := TJSONProtocolImpl.Create(trans); + result := TJSONProtocolImpl.Create( trans); end; class function TJSONProtocolImpl.GetTypeNameForTypeID(typeID : TType) : string; diff --git a/lib/delphi/src/Thrift.Protocol.pas b/lib/delphi/src/Thrift.Protocol.pas index 94e6e186351..d5a758797eb 100644 --- a/lib/delphi/src/Thrift.Protocol.pas +++ b/lib/delphi/src/Thrift.Protocol.pas @@ -31,6 +31,7 @@ interface Thrift.Stream, Thrift.Utils, Thrift.Collections, + Thrift.Configuration, Thrift.Transport; type @@ -67,9 +68,6 @@ interface VALID_MESSAGETYPES = [Low(TMessageType)..High(TMessageType)]; -const - DEFAULT_RECURSION_LIMIT = 64; - type IProtocol = interface; @@ -196,7 +194,7 @@ TProtocolRecursionTrackerImpl = class abstract( TInterfacedObject, IProtocolRe end; IProtocol = interface - ['{7F3640D7-5082-49E7-B562-84202F323C3A}'] + ['{F0040D99-937F-400D-9932-AF04F665899F}'] function GetTransport: ITransport; procedure WriteMessageBegin( const msg: TThriftMessage); procedure WriteMessageEnd; @@ -243,15 +241,13 @@ TProtocolRecursionTrackerImpl = class abstract( TInterfacedObject, IProtocolRe function ReadString: string; function ReadAnsiString: AnsiString; - procedure SetRecursionLimit( value : Integer); - function GetRecursionLimit : Integer; function NextRecursionLevel : IProtocolRecursionTracker; procedure IncrementRecursionDepth; procedure DecrementRecursionDepth; function GetMinSerializedSize( const aType : TType) : Integer; property Transport: ITransport read GetTransport; - property RecursionLimit : Integer read GetRecursionLimit write SetRecursionLimit; + function Configuration : IThriftConfiguration; end; TProtocolImpl = class abstract( TInterfacedObject, IProtocol) @@ -260,8 +256,6 @@ TProtocolImpl = class abstract( TInterfacedObject, IProtocol) FRecursionLimit : Integer; FRecursionDepth : Integer; - procedure SetRecursionLimit( value : Integer); - function GetRecursionLimit : Integer; function NextRecursionLevel : IProtocolRecursionTracker; procedure IncrementRecursionDepth; procedure DecrementRecursionDepth; @@ -272,8 +266,9 @@ TProtocolImpl = class abstract( TInterfacedObject, IProtocol) procedure CheckReadBytesAvailable( const value : TThriftMap); overload; inline; procedure Reset; virtual; - function GetTransport: ITransport; - public + function GetTransport: ITransport; + function Configuration : IThriftConfiguration; + procedure WriteMessageBegin( const msg: TThriftMessage); virtual; abstract; procedure WriteMessageEnd; virtual; abstract; procedure WriteStructBegin( const struc: TThriftStruct); virtual; abstract; @@ -319,9 +314,10 @@ TProtocolImpl = class abstract( TInterfacedObject, IProtocol) function ReadString: string; virtual; function ReadAnsiString: AnsiString; virtual; - property Transport: ITransport read GetTransport; + property Transport: ITransport read GetTransport; - constructor Create( trans: ITransport ); + public + constructor Create( const aTransport : ITransport); end; IBase = interface( ISupportsToString) @@ -554,24 +550,14 @@ destructor TProtocolRecursionTrackerImpl.Destroy; { TProtocolImpl } -constructor TProtocolImpl.Create(trans: ITransport); +constructor TProtocolImpl.Create( const aTransport : ITransport); begin inherited Create; - FTrans := trans; - FRecursionLimit := DEFAULT_RECURSION_LIMIT; + FTrans := aTransport; + FRecursionLimit := aTransport.Configuration.RecursionLimit; FRecursionDepth := 0; end; -procedure TProtocolImpl.SetRecursionLimit( value : Integer); -begin - FRecursionLimit := value; -end; - -function TProtocolImpl.GetRecursionLimit : Integer; -begin - result := FRecursionLimit; -end; - function TProtocolImpl.NextRecursionLevel : IProtocolRecursionTracker; begin result := TProtocolRecursionTrackerImpl.Create(Self); @@ -594,10 +580,14 @@ function TProtocolImpl.GetTransport: ITransport; Result := FTrans; end; +function TProtocolImpl.Configuration : IThriftConfiguration; +begin + Result := FTrans.Configuration; +end; + procedure TProtocolImpl.Reset; begin - if FTrans.TransportControl <> nil - then FTrans.TransportControl.ResetConsumedMessageSize; + FTrans.ResetConsumedMessageSize; end; function TProtocolImpl.ReadAnsiString: AnsiString; @@ -654,15 +644,12 @@ procedure TProtocolImpl.CheckReadBytesAvailable( const value : TThriftSet); procedure TProtocolImpl.CheckReadBytesAvailable( const value : TThriftMap); -var nPairSize : Integer -; +var nPairSize : Integer; begin nPairSize := GetMinSerializedSize(value.KeyType) + GetMinSerializedSize(value.ValueType); FTrans.CheckReadBytesAvailable( value.Count * nPairSize); end; - - { TProtocolUtil } class procedure TProtocolUtil.Skip( prot: IProtocol; type_: TType); @@ -1486,7 +1473,5 @@ procedure Init( var rec : TThriftList; const AElementType: TType; const ACount: - - end. diff --git a/lib/delphi/src/Thrift.Serializer.pas b/lib/delphi/src/Thrift.Serializer.pas index 1cbcbec5ff3..cb62603dbf0 100644 --- a/lib/delphi/src/Thrift.Serializer.pas +++ b/lib/delphi/src/Thrift.Serializer.pas @@ -28,6 +28,7 @@ interface {$ELSE} System.Classes, Winapi.Windows, System.SysUtils, {$ENDIF} + Thrift.Configuration, Thrift.Protocol, Thrift.Transport, Thrift.Stream; @@ -42,16 +43,9 @@ TSerializer = class FProtocol : IProtocol; public - // Create a new TSerializer that uses the TBinaryProtocol by default. - constructor Create; overload; - - // Create a new TSerializer. - // It will use the TProtocol specified by the factory that is passed in. - constructor Create( const factory : IProtocolFactory); overload; - - // Create a new TSerializer. - // It will use the TProtocol and layered transports specified by the factories that are passed in. - constructor Create( const protfact : IProtocolFactory; const transfact : ITransportFactory); overload; + constructor Create( const aProtFact : IProtocolFactory = nil; // defaults to TBinaryProtocol + const aTransFact : ITransportFactory = nil; + const aConfig : IThriftConfiguration = nil); // DTOR destructor Destroy; override; @@ -70,19 +64,9 @@ TDeserializer = class FProtocol : IProtocol; public - // Create a new TDeserializer that uses the TBinaryProtocol by default. - constructor Create( const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE); overload; - - // Create a new TDeserializer. - // It will use the TProtocol specified by the factory that is passed in. - constructor Create( const factory : IProtocolFactory; - const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE); overload; - - // Create a new TDeserializer. - // It will use the TProtocol and layered transports specified by the factories that are passed in. - constructor Create( const protfact : IProtocolFactory; - const transfact : ITransportFactory; - const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE); overload; + constructor Create( const aProtFact : IProtocolFactory = nil; // defaults to TBinaryProtocol + const aTransFact : ITransportFactory = nil; + const aConfig : IThriftConfiguration = nil); // DTOR destructor Destroy; override; @@ -100,34 +84,24 @@ implementation { TSerializer } -constructor TSerializer.Create; -// Create a new TSerializer that uses the TBinaryProtocol by default. -begin - //no inherited; - Create( TBinaryProtocolImpl.TFactory.Create, nil); -end; - - -constructor TSerializer.Create( const factory : IProtocolFactory); -// Create a new TSerializer. -// It will use the TProtocol specified by the factory that is passed in. -begin - //no inherited; - Create( factory, nil); -end; - - -constructor TSerializer.Create( const protfact : IProtocolFactory; const transfact : ITransportFactory); -// Create a new TSerializer. -// It will use the TProtocol specified by the factory that is passed in. +constructor TSerializer.Create( const aProtFact : IProtocolFactory; + const aTransFact : ITransportFactory; + const aConfig : IThriftConfiguration); var adapter : IThriftStream; + protfact : IProtocolFactory; begin inherited Create; + FStream := TMemoryStream.Create; adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE); - FTransport := TStreamTransportImpl.Create( nil, adapter, TTransportControlImpl.Create(0)); // we don't read anything here - if transfact <> nil then FTransport := transfact.GetTransport( FTransport); - FProtocol := protfact.GetProtocol( FTransport); + + FTransport := TStreamTransportImpl.Create( nil, adapter, aConfig); + if aTransfact <> nil then FTransport := aTransfact.GetTransport( FTransport); + + if aProtFact <> nil + then protfact := aProtFact + else protfact := TBinaryProtocolImpl.TFactory.Create; + FProtocol := protfact.GetProtocol( FTransport); if not FTransport.IsOpen then FTransport.Open; @@ -188,36 +162,24 @@ procedure TSerializer.Serialize( const input : IBase; const aStm : TStream); { TDeserializer } -constructor TDeserializer.Create( const aMaxMessageSize : Integer); -// Create a new TDeserializer that uses the TBinaryProtocol by default. -begin - //no inherited; - Create( TBinaryProtocolImpl.TFactory.Create, nil, aMaxMessageSize); -end; - - -constructor TDeserializer.Create( const factory : IProtocolFactory; const aMaxMessageSize : Integer); -// Create a new TDeserializer. -// It will use the TProtocol specified by the factory that is passed in. -begin - //no inherited; - Create( factory, nil, aMaxMessageSize); -end; - - -constructor TDeserializer.Create( const protfact : IProtocolFactory; - const transfact : ITransportFactory; - const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE); -// Create a new TDeserializer. -// It will use the TProtocol specified by the factory that is passed in. +constructor TDeserializer.Create( const aProtFact : IProtocolFactory; + const aTransFact : ITransportFactory; + const aConfig : IThriftConfiguration); var adapter : IThriftStream; + protfact : IProtocolFactory; begin inherited Create; + FStream := TMemoryStream.Create; adapter := TThriftStreamAdapterDelphi.Create( FStream, FALSE); - FTransport := TStreamTransportImpl.Create( adapter, nil, TTransportControlImpl.Create(aMaxMessageSize)); - if transfact <> nil then FTransport := transfact.GetTransport( FTransport); - FProtocol := protfact.GetProtocol( FTransport); + + FTransport := TStreamTransportImpl.Create( adapter, nil, aConfig); + if aTransfact <> nil then FTransport := aTransfact.GetTransport( FTransport); + + if aProtFact <> nil + then protfact := aProtFact + else protfact := TBinaryProtocolImpl.TFactory.Create; + FProtocol := protfact.GetProtocol( FTransport); if not FTransport.IsOpen then FTransport.Open; diff --git a/lib/delphi/src/Thrift.Server.pas b/lib/delphi/src/Thrift.Server.pas index da053b96bc5..a73e6cb4475 100644 --- a/lib/delphi/src/Thrift.Server.pas +++ b/lib/delphi/src/Thrift.Server.pas @@ -32,7 +32,8 @@ interface {$ENDIF} Thrift, Thrift.Protocol, - Thrift.Transport; + Thrift.Transport, + Thrift.Configuration; type IServerEvents = interface @@ -70,6 +71,7 @@ TServerImpl = class abstract( TInterfacedObject, IServer ) FOutputProtocolFactory : IProtocolFactory; FLogDelegate : TLogDelegate; FServerEvents : IServerEvents; + FConfiguration : IThriftConfiguration; class procedure DefaultLogDelegate( const str: string); @@ -86,31 +88,17 @@ TServerImpl = class abstract( TInterfacedObject, IServer ) const aOutputTransportFactory : ITransportFactory; const aInputProtocolFactory : IProtocolFactory; const aOutputProtocolFactory : IProtocolFactory; + const aConfig : IThriftConfiguration; const aLogDelegate : TLogDelegate ); overload; constructor Create( - const aProcessor :IProcessor; - const aServerTransport: IServerTransport - ); overload; - - constructor Create( - const aProcessor :IProcessor; - const aServerTransport: IServerTransport; - const aLogDelegate: TLogDelegate - ); overload; - - constructor Create( - const aProcessor :IProcessor; - const aServerTransport: IServerTransport; - const aTransportFactory : ITransportFactory - ); overload; - - constructor Create( - const aProcessor :IProcessor; + const aProcessor: IProcessor; const aServerTransport: IServerTransport; - const aTransportFactory : ITransportFactory; - const aProtocolFactory : IProtocolFactory + const aTransportFactory: ITransportFactory = nil; + const aProtocolFactory: IProtocolFactory = nil; + const aConfig : IThriftConfiguration = nil; + const aLogDel: TServerImpl.TLogDelegate = nil ); overload; end; @@ -119,30 +107,6 @@ TSimpleServer = class( TServerImpl) private FStop : Boolean; public - constructor Create( - const aProcessor: IProcessor; - const aServerTransport: IServerTransport - ); overload; - - constructor Create( - const aProcessor: IProcessor; - const aServerTransport: IServerTransport; - const ALogDel: TServerImpl.TLogDelegate - ); overload; - - constructor Create( - const aProcessor: IProcessor; - const aServerTransport: IServerTransport; - const aTransportFactory: ITransportFactory - ); overload; - - constructor Create( - const aProcessor: IProcessor; - const aServerTransport: IServerTransport; - const aTransportFactory: ITransportFactory; - const aProtocolFactory: IProtocolFactory - ); overload; - procedure Serve; override; procedure Stop; override; end; @@ -154,83 +118,55 @@ implementation constructor TServerImpl.Create( const aProcessor: IProcessor; const aServerTransport: IServerTransport; - const aLogDelegate: TLogDelegate); -var - InputFactory, OutputFactory : IProtocolFactory; - InputTransFactory, OutputTransFactory : ITransportFactory; - + const aInputTransportFactory, aOutputTransportFactory: ITransportFactory; + const aInputProtocolFactory, aOutputProtocolFactory: IProtocolFactory; + const aConfig : IThriftConfiguration; + const aLogDelegate : TLogDelegate); begin - InputFactory := TBinaryProtocolImpl.TFactory.Create; - OutputFactory := TBinaryProtocolImpl.TFactory.Create; - InputTransFactory := TTransportFactoryImpl.Create; - OutputTransFactory := TTransportFactoryImpl.Create; - - //no inherited; - Create( - aProcessor, - aServerTransport, - InputTransFactory, - OutputTransFactory, - InputFactory, - OutputFactory, - ALogDelegate - ); -end; + inherited Create; + FProcessor := aProcessor; + FServerTransport := aServerTransport; -constructor TServerImpl.Create(const aProcessor: IProcessor; - const aServerTransport: IServerTransport); -var - InputFactory, OutputFactory : IProtocolFactory; - InputTransFactory, OutputTransFactory : ITransportFactory; + if aConfig <> nil + then FConfiguration := aConfig + else FConfiguration := TThriftConfigurationImpl.Create; -begin - InputFactory := TBinaryProtocolImpl.TFactory.Create; - OutputFactory := TBinaryProtocolImpl.TFactory.Create; - InputTransFactory := TTransportFactoryImpl.Create; - OutputTransFactory := TTransportFactoryImpl.Create; - - //no inherited; - Create( - aProcessor, - aServerTransport, - InputTransFactory, - OutputTransFactory, - InputFactory, - OutputFactory, - DefaultLogDelegate - ); -end; + if aInputTransportFactory <> nil + then FInputTransportFactory := aInputTransportFactory + else FInputTransportFactory := TTransportFactoryImpl.Create; -constructor TServerImpl.Create(const aProcessor: IProcessor; - const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory); -var - InputProtocolFactory : IProtocolFactory; - OutputProtocolFactory : IProtocolFactory; -begin - InputProtocolFactory := TBinaryProtocolImpl.TFactory.Create; - OutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create; + if aOutputTransportFactory <> nil + then FOutputTransportFactory := aOutputTransportFactory + else FOutputTransportFactory := TTransportFactoryImpl.Create; + + if aInputProtocolFactory <> nil + then FInputProtocolFactory := aInputProtocolFactory + else FInputProtocolFactory := TBinaryProtocolImpl.TFactory.Create; + + if aOutputProtocolFactory <> nil + then FOutputProtocolFactory := aOutputProtocolFactory + else FOutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create; - //no inherited; - Create( aProcessor, aServerTransport, aTransportFactory, aTransportFactory, - InputProtocolFactory, OutputProtocolFactory, DefaultLogDelegate); + if Assigned(aLogDelegate) + then FLogDelegate := aLogDelegate + else FLogDelegate := DefaultLogDelegate; end; -constructor TServerImpl.Create(const aProcessor: IProcessor; - const aServerTransport: IServerTransport; - const aInputTransportFactory, aOutputTransportFactory: ITransportFactory; - const aInputProtocolFactory, aOutputProtocolFactory: IProtocolFactory; - const aLogDelegate : TLogDelegate); + +constructor TServerImpl.Create( const aProcessor: IProcessor; + const aServerTransport: IServerTransport; + const aTransportFactory: ITransportFactory; + const aProtocolFactory: IProtocolFactory; + const aConfig : IThriftConfiguration; + const aLogDel: TServerImpl.TLogDelegate); begin - inherited Create; - FProcessor := aProcessor; - FServerTransport := aServerTransport; - FInputTransportFactory := aInputTransportFactory; - FOutputTransportFactory := aOutputTransportFactory; - FInputProtocolFactory := aInputProtocolFactory; - FOutputProtocolFactory := aOutputProtocolFactory; - FLogDelegate := aLogDelegate; + Create( aProcessor, aServerTransport, + aTransportFactory, aTransportFactory, + aProtocolFactory, aProtocolFactory, + aConfig, aLogDel); end; + class procedure TServerImpl.DefaultLogDelegate( const str: string); begin try @@ -241,16 +177,6 @@ class procedure TServerImpl.DefaultLogDelegate( const str: string); end; end; -constructor TServerImpl.Create( const aProcessor: IProcessor; - const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory; - const aProtocolFactory: IProtocolFactory); -begin - //no inherited; - Create( aProcessor, aServerTransport, - aTransportFactory, aTransportFactory, - aProtocolFactory, aProtocolFactory, - DefaultLogDelegate); -end; function TServerImpl.GetServerEvents : IServerEvents; @@ -268,55 +194,6 @@ procedure TServerImpl.SetServerEvents( const value : IServerEvents); { TSimpleServer } -constructor TSimpleServer.Create( const aProcessor: IProcessor; - const aServerTransport: IServerTransport); -var - InputProtocolFactory : IProtocolFactory; - OutputProtocolFactory : IProtocolFactory; - InputTransportFactory : ITransportFactory; - OutputTransportFactory : ITransportFactory; -begin - InputProtocolFactory := TBinaryProtocolImpl.TFactory.Create; - OutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create; - InputTransportFactory := TTransportFactoryImpl.Create; - OutputTransportFactory := TTransportFactoryImpl.Create; - - inherited Create( aProcessor, aServerTransport, InputTransportFactory, - OutputTransportFactory, InputProtocolFactory, OutputProtocolFactory, DefaultLogDelegate); -end; - -constructor TSimpleServer.Create( const aProcessor: IProcessor; - const aServerTransport: IServerTransport; const ALogDel: TServerImpl.TLogDelegate); -var - InputProtocolFactory : IProtocolFactory; - OutputProtocolFactory : IProtocolFactory; - InputTransportFactory : ITransportFactory; - OutputTransportFactory : ITransportFactory; -begin - InputProtocolFactory := TBinaryProtocolImpl.TFactory.Create; - OutputProtocolFactory := TBinaryProtocolImpl.TFactory.Create; - InputTransportFactory := TTransportFactoryImpl.Create; - OutputTransportFactory := TTransportFactoryImpl.Create; - - inherited Create( aProcessor, aServerTransport, InputTransportFactory, - OutputTransportFactory, InputProtocolFactory, OutputProtocolFactory, ALogDel); -end; - -constructor TSimpleServer.Create( const aProcessor: IProcessor; - const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory); -begin - inherited Create( aProcessor, aServerTransport, aTransportFactory, - aTransportFactory, TBinaryProtocolImpl.TFactory.Create, TBinaryProtocolImpl.TFactory.Create, DefaultLogDelegate); -end; - -constructor TSimpleServer.Create( const aProcessor: IProcessor; - const aServerTransport: IServerTransport; const aTransportFactory: ITransportFactory; - const aProtocolFactory: IProtocolFactory); -begin - inherited Create( aProcessor, aServerTransport, aTransportFactory, - aTransportFactory, aProtocolFactory, aProtocolFactory, DefaultLogDelegate); -end; - procedure TSimpleServer.Serve; var client : ITransport; diff --git a/lib/delphi/src/Thrift.Stream.pas b/lib/delphi/src/Thrift.Stream.pas index 0f4e723e85b..16680591c9f 100644 --- a/lib/delphi/src/Thrift.Stream.pas +++ b/lib/delphi/src/Thrift.Stream.pas @@ -37,22 +37,16 @@ interface type IThriftStream = interface - ['{DBE61E28-2A77-42DB-A5A3-3CCB8A2D09FA}'] + ['{3A61A8A6-3639-4B91-A260-EFCA23944F3A}'] procedure Write( const buffer: TBytes; offset: Integer; count: Integer); overload; procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; - procedure CheckReadBytesAvailable( const value : Integer); procedure Open; procedure Close; procedure Flush; function IsOpen: Boolean; function ToArray: TBytes; - end; - - - IThriftStream2 = interface( IThriftStream) - ['{1F55D9FE-F617-4B80-B8CA-4A300D8E33F6}'] function Size : Int64; function Position : Int64; end; @@ -67,15 +61,16 @@ TThriftStreamImpl = class abstract( TInterfacedObject, IThriftStream) procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); overload; virtual; function Read( var buffer: TBytes; offset: Integer; count: Integer): Integer; overload; inline; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; virtual; - procedure CheckReadBytesAvailable( const value : Integer); virtual; abstract; procedure Open; virtual; abstract; procedure Close; virtual; abstract; procedure Flush; virtual; abstract; function IsOpen: Boolean; virtual; abstract; function ToArray: TBytes; virtual; abstract; + function Size : Int64; virtual; + function Position : Int64; virtual; end; - TThriftStreamAdapterDelphi = class( TThriftStreamImpl, IThriftStream2) + TThriftStreamAdapterDelphi = class( TThriftStreamImpl) strict private FStream : TStream; FOwnsStream : Boolean; @@ -83,38 +78,32 @@ TThriftStreamAdapterDelphi = class( TThriftStreamImpl, IThriftStream2) // IThriftStream procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; - procedure CheckReadBytesAvailable( const value : Integer); override; procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; - - // IThriftStream2 - function Size : Int64; - function Position : Int64; + function Size : Int64; override; + function Position : Int64; override; public constructor Create( const aStream: TStream; aOwnsStream : Boolean); destructor Destroy; override; end; - TThriftStreamAdapterCOM = class( TThriftStreamImpl, IThriftStream2) + TThriftStreamAdapterCOM = class( TThriftStreamImpl) strict private FStream : IStream; strict protected // IThriftStream procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; - procedure CheckReadBytesAvailable( const value : Integer); override; procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; - - // IThriftStream2 - function Size : Int64; - function Position : Int64; + function Size : Int64; override; + function Position : Int64; override; public constructor Create( const aStream: IStream); end; @@ -191,14 +180,6 @@ function TThriftStreamAdapterCOM.Read( const pBuf : Pointer; const buflen : Inte end; end; -procedure TThriftStreamAdapterCOM.CheckReadBytesAvailable( const value : Integer); -var nRemaining : Int64; -begin - nRemaining := Self.Size - Self.Position; - if nRemaining < value - then raise TTransportExceptionEndOfFile.Create('Not enough input data'); -end; - function TThriftStreamAdapterCOM.ToArray: TBytes; var len : Int64; @@ -267,6 +248,19 @@ procedure TThriftStreamImpl.Write( const pBuf : Pointer; offset: Integer; count: CheckSizeAndOffset( pBuf, offset+count, offset, count); end; +function TThriftStreamImpl.Size : Int64; +begin + ASSERT(FALSE); + raise ENotImplemented.Create(ClassName+'.Size'); +end; + +function TThriftStreamImpl.Position : Int64; +begin + ASSERT(FALSE); + raise ENotImplemented.Create(ClassName+'.Position'); +end; + + { TThriftStreamAdapterDelphi } constructor TThriftStreamAdapterDelphi.Create( const aStream: TStream; aOwnsStream: Boolean); @@ -332,13 +326,6 @@ function TThriftStreamAdapterDelphi.Read(const pBuf : Pointer; const buflen : In else Result := 0; end; -procedure TThriftStreamAdapterDelphi.CheckReadBytesAvailable( const value : Integer); -var nRemaining : Int64; -begin - nRemaining := FStream.Size - FStream.Position; - if nRemaining < value then raise TTransportExceptionEndOfFile.Create('Not enough input data'); -end; - function TThriftStreamAdapterDelphi.ToArray: TBytes; var OrgPos : Integer; diff --git a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas index b92cce1e12b..bdc65d1fdaf 100644 --- a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas @@ -34,13 +34,14 @@ interface Winapi.ActiveX, Winapi.msxml, {$ENDIF} Thrift.Collections, + Thrift.Configuration, Thrift.Transport, Thrift.Exception, Thrift.Utils, Thrift.Stream; type - TMsxmlHTTPClientImpl = class( TTransportImpl, IHTTPClient) + TMsxmlHTTPClientImpl = class( TEndpointTransportBase, IHTTPClient) strict private FUri : string; FInputStream : IThriftStream; @@ -59,7 +60,6 @@ TMsxmlHTTPClientImpl = class( TTransportImpl, IHTTPClient) function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; procedure Flush; override; - procedure CheckReadBytesAvailable( const value : Integer); override; procedure SetDnsResolveTimeout(const Value: Integer); function GetDnsResolveTimeout: Integer; @@ -81,26 +81,29 @@ TMsxmlHTTPClientImpl = class( TTransportImpl, IHTTPClient) property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout; property CustomHeaders: IThriftDictionary read GetCustomHeaders; public - constructor Create( const AUri: string; const aTransportCtl : ITransportControl = nil); + constructor Create( const aUri: string; const aConfig : IThriftConfiguration); reintroduce; destructor Destroy; override; end; implementation +const + XMLHTTP_CONNECTION_TIMEOUT = 60 * 1000; + XMLHTTP_SENDRECV_TIMEOUT = 30 * 1000; { TMsxmlHTTPClientImpl } -constructor TMsxmlHTTPClientImpl.Create(const AUri: string; const aTransportCtl : ITransportControl); +constructor TMsxmlHTTPClientImpl.Create( const aUri: string; const aConfig : IThriftConfiguration); begin - inherited Create( aTransportCtl); - FUri := AUri; + inherited Create( aConfig); + FUri := aUri; // defaults according to MSDN FDnsResolveTimeout := 0; // no timeout - FConnectionTimeout := 60 * 1000; - FSendTimeout := 30 * 1000; - FReadTimeout := 30 * 1000; + FConnectionTimeout := XMLHTTP_CONNECTION_TIMEOUT; + FSendTimeout := XMLHTTP_SENDRECV_TIMEOUT; + FReadTimeout := XMLHTTP_SENDRECV_TIMEOUT; FCustomHeaders := TThriftDictionaryImpl.Create; FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True); @@ -219,13 +222,6 @@ procedure TMsxmlHTTPClientImpl.Flush; end; end; -procedure TMsxmlHTTPClientImpl.CheckReadBytesAvailable( const value : Integer); -begin - if FInputStream <> nil - then FInputStream.CheckReadBytesAvailable( value) - else raise TTransportExceptionNotOpen.Create('No request has been sent'); -end; - function TMsxmlHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; begin if FInputStream = nil then begin @@ -234,7 +230,6 @@ function TMsxmlHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer try Result := FInputStream.Read( pBuf, buflen, off, len); - ConsumeReadBytes( result); except on E: Exception do raise TTransportExceptionUnknown.Create(E.Message); @@ -261,6 +256,7 @@ procedure TMsxmlHTTPClientImpl.SendRequest; xmlhttp.send( IUnknown( TStreamAdapter.Create( ms, soReference ))); FInputStream := nil; FInputStream := TThriftStreamAdapterCOM.Create( IUnknown( xmlhttp.responseStream) as IStream); + UpdateKnownMessageSize( FInputStream.Size); finally ms.Free; end; diff --git a/lib/delphi/src/Thrift.Transport.Pipes.pas b/lib/delphi/src/Thrift.Transport.Pipes.pas index b602b64c8d6..635a8417859 100644 --- a/lib/delphi/src/Thrift.Transport.Pipes.pas +++ b/lib/delphi/src/Thrift.Transport.Pipes.pas @@ -29,6 +29,7 @@ interface {$ELSE} Winapi.Windows, System.SysUtils, System.Math, Winapi.AccCtrl, Winapi.AclAPI, System.SyncObjs, {$ENDIF} + Thrift.Configuration, Thrift.Transport, Thrift.Utils, Thrift.Stream; @@ -53,7 +54,6 @@ TPipeStreamBase = class( TThriftStreamImpl) //procedure Open; override; - see derived classes procedure Close; override; procedure Flush; override; - procedure CheckReadBytesAvailable( const value : Integer); override; function ReadDirect( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; function ReadOverlapped( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; overload; @@ -65,7 +65,9 @@ TPipeStreamBase = class( TThriftStreamImpl) public constructor Create( aEnableOverlapped : Boolean; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; - const aOpenTimeOut : DWORD = DEFAULT_THRIFT_PIPE_OPEN_TIMEOUT); + const aOpenTimeOut : DWORD = DEFAULT_THRIFT_PIPE_OPEN_TIMEOUT + ); reintroduce; overload; + destructor Destroy; override; end; @@ -85,7 +87,8 @@ TNamedPipeStreamImpl = class sealed( TPipeStreamBase) const aShareMode: DWORD = 0; const aSecurityAttributes: PSecurityAttributes = nil; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; - const aOpenTimeOut : DWORD = DEFAULT_THRIFT_PIPE_OPEN_TIMEOUT); overload; + const aOpenTimeOut : DWORD = DEFAULT_THRIFT_PIPE_OPEN_TIMEOUT + ); reintroduce; overload; end; @@ -99,7 +102,9 @@ THandlePipeStreamImpl = class sealed( TPipeStreamBase) public constructor Create( const aPipeHandle : THandle; const aOwnsHandle, aEnableOverlapped : Boolean; - const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT); overload; + const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT + ); reintroduce; overload; + destructor Destroy; override; end; @@ -113,7 +118,7 @@ THandlePipeStreamImpl = class sealed( TPipeStreamBase) TPipeTransportBase = class( TStreamTransportImpl, IPipeTransport) - public + strict protected // ITransport function GetIsOpen: Boolean; override; procedure Open; override; @@ -127,27 +132,32 @@ TNamedPipeTransportClientEndImpl = class( TPipeTransportBase) constructor Create( const aPipe : THandle; const aOwnsHandle : Boolean; const aTimeOut : DWORD; - const aTransportCtl : ITransportControl); overload; + const aConfig : IThriftConfiguration = nil + ); reintroduce; overload; constructor Create( const aPipeName : string; const aShareMode: DWORD = 0; const aSecurityAttributes: PSecurityAttributes = nil; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; const aOpenTimeOut : DWORD = DEFAULT_THRIFT_PIPE_OPEN_TIMEOUT; - const aTransportCtl : ITransportControl = nil); overload; + const aConfig : IThriftConfiguration = nil + ); reintroduce; overload; end; TNamedPipeTransportServerEndImpl = class( TNamedPipeTransportClientEndImpl) strict private FHandle : THandle; - public + strict protected // ITransport procedure Close; override; + public constructor Create( const aPipe : THandle; const aOwnsHandle : Boolean; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; - const aTransportCtl : ITransportControl = nil); reintroduce; + const aConfig : IThriftConfiguration = nil + ); reintroduce; overload; + end; @@ -157,7 +167,8 @@ TAnonymousPipeTransportImpl = class( TPipeTransportBase) constructor Create( const aPipeRead, aPipeWrite : THandle; const aOwnsHandles : Boolean; const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; - const aTransportCtl : ITransportControl = nil); overload; + const aConfig : IThriftConfiguration = nil + ); reintroduce; overload; end; @@ -187,7 +198,7 @@ TPipeServerTransportBase = class( TServerTransportImpl) procedure InternalClose; virtual; abstract; function QueryStopServer : Boolean; public - constructor Create; + constructor Create( const aConfig : IThriftConfiguration); destructor Destroy; override; procedure Listen; override; procedure Close; override; @@ -221,7 +232,10 @@ TAnonymousPipeServerTransportImpl = class( TPipeServerTransportBase, IAnonymou procedure InternalClose; override; public - constructor Create(aBufsize : Cardinal = 4096; aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT); + constructor Create( const aBufsize : Cardinal = 4096; + const aTimeOut : DWORD = DEFAULT_THRIFT_TIMEOUT; + const aConfig : IThriftConfiguration = nil + ); reintroduce; overload; end; @@ -245,9 +259,12 @@ TNamedPipeServerTransportImpl = class( TPipeServerTransportBase, INamedPipeSer procedure InternalClose; override; public - constructor Create( aPipename : string; aBufsize : Cardinal = 4096; - aMaxConns : Cardinal = PIPE_UNLIMITED_INSTANCES; - aTimeOut : Cardinal = INFINITE); + constructor Create( const aPipename : string; + const aBufsize : Cardinal = 4096; + const aMaxConns : Cardinal = PIPE_UNLIMITED_INSTANCES; + const aTimeOut : Cardinal = INFINITE; + const aConfig : IThriftConfiguration = nil + ); reintroduce; overload; end; @@ -278,15 +295,14 @@ function DuplicatePipeHandle( const hSource : THandle) : THandle; { TPipeStreamBase } -constructor TPipeStreamBase.Create( aEnableOverlapped : Boolean; - const aTimeOut, aOpenTimeOut : DWORD); +constructor TPipeStreamBase.Create( aEnableOverlapped : Boolean; const aTimeOut, aOpenTimeOut : DWORD); begin inherited Create; - ASSERT( aTimeout > 0); // aOpenTimeout may be 0 FPipe := INVALID_HANDLE_VALUE; FTimeout := aTimeOut; FOpenTimeOut := aOpenTimeOut; FOverlapped := aEnableOverlapped; + ASSERT( FTimeout > 0); // FOpenTimeout may be 0 end; @@ -318,12 +334,6 @@ function TPipeStreamBase.IsOpen: Boolean; end; -procedure TPipeStreamBase.CheckReadBytesAvailable( const value : Integer); -begin - // can't tell how much we can suck out of the pipe -end; - - procedure TPipeStreamBase.Write( const pBuf : Pointer; offset, count : Integer); begin if FOverlapped @@ -538,7 +548,7 @@ constructor TNamedPipeStreamImpl.Create( const aPipeName : string; const aSecurityAttributes: PSecurityAttributes; const aTimeOut, aOpenTimeOut : DWORD); begin - inherited Create( aEnableOverlapped, aTimeout, aOpenTimeOut); + inherited Create( aEnableOverlapped, aTimeOut, aOpenTimeOut); FPipeName := aPipeName; FShareMode := aShareMode; @@ -601,7 +611,7 @@ constructor THandlePipeStreamImpl.Create( const aPipeHandle : THandle; const aOwnsHandle, aEnableOverlapped : Boolean; const aTimeOut : DWORD); begin - inherited Create( aEnableOverlapped, aTimeOut); + inherited Create( aEnableOverlapped, aTimeout, aTimeout); if aOwnsHandle then FSrcHandle := aPipeHandle @@ -655,13 +665,14 @@ procedure TPipeTransportBase.Close; { TNamedPipeTransportClientEndImpl } -constructor TNamedPipeTransportClientEndImpl.Create( const aPipeName : string; const aShareMode: DWORD; +constructor TNamedPipeTransportClientEndImpl.Create( const aPipeName : string; + const aShareMode: DWORD; const aSecurityAttributes: PSecurityAttributes; const aTimeOut, aOpenTimeOut : DWORD; - const aTransportCtl : ITransportControl); + const aConfig : IThriftConfiguration); // Named pipe constructor begin - inherited Create( nil, nil, aTransportCtl); + inherited Create( nil, nil, aConfig); FInputStream := TNamedPipeStreamImpl.Create( aPipeName, TRUE, aShareMode, aSecurityAttributes, aTimeOut, aOpenTimeOut); FOutputStream := FInputStream; // true for named pipes end; @@ -670,11 +681,11 @@ constructor TNamedPipeTransportClientEndImpl.Create( const aPipeName : string; c constructor TNamedPipeTransportClientEndImpl.Create( const aPipe : THandle; const aOwnsHandle : Boolean; const aTimeOut : DWORD; - const aTransportCtl : ITransportControl); + const aConfig : IThriftConfiguration); // Named pipe constructor begin - inherited Create( nil, nil, aTransportCtl); - FInputStream := THandlePipeStreamImpl.Create( aPipe, TRUE, aOwnsHandle, aTimeOut); + inherited Create( nil, nil, aConfig); + FInputStream := THandlePipeStreamImpl.Create( aPipe, aOwnsHandle, TRUE, aTimeOut); FOutputStream := FInputStream; // true for named pipes end; @@ -685,11 +696,11 @@ constructor TNamedPipeTransportClientEndImpl.Create( const aPipe : THandle; constructor TNamedPipeTransportServerEndImpl.Create( const aPipe : THandle; const aOwnsHandle : Boolean; const aTimeOut : DWORD; - const aTransportCtl : ITransportControl); + const aConfig : IThriftConfiguration); // Named pipe constructor begin FHandle := DuplicatePipeHandle( aPipe); - inherited Create( aPipe, aOwnsHandle, aTimeOut, aTransportCtl); + inherited Create( aPipe, aOwnsHandle, aTimeout, aConfig); end; @@ -709,22 +720,22 @@ procedure TNamedPipeTransportServerEndImpl.Close; constructor TAnonymousPipeTransportImpl.Create( const aPipeRead, aPipeWrite : THandle; const aOwnsHandles : Boolean; const aTimeOut : DWORD; - const aTransportCtl : ITransportControl); + const aConfig : IThriftConfiguration); // Anonymous pipe constructor begin - inherited Create( nil, nil, aTransportCtl); + inherited Create( nil, nil, aConfig); // overlapped is not supported with AnonPipes, see MSDN - FInputStream := THandlePipeStreamImpl.Create( aPipeRead, aOwnsHandles, FALSE, aTimeOut); - FOutputStream := THandlePipeStreamImpl.Create( aPipeWrite, aOwnsHandles, FALSE, aTimeOut); + FInputStream := THandlePipeStreamImpl.Create( aPipeRead, aOwnsHandles, FALSE, aTimeout); + FOutputStream := THandlePipeStreamImpl.Create( aPipeWrite, aOwnsHandles, FALSE, aTimeout); end; { TPipeServerTransportBase } -constructor TPipeServerTransportBase.Create; +constructor TPipeServerTransportBase.Create( const aConfig : IThriftConfiguration); begin - inherited Create; + inherited Create( aConfig); FStopServer := TEvent.Create(nil,TRUE,FALSE,''); // manual reset end; @@ -761,11 +772,12 @@ procedure TPipeServerTransportBase.Close; { TAnonymousPipeServerTransportImpl } - -constructor TAnonymousPipeServerTransportImpl.Create(aBufsize : Cardinal; aTimeOut : DWORD); +constructor TAnonymousPipeServerTransportImpl.Create( const aBufsize : Cardinal; + const aTimeOut : DWORD; + const aConfig : IThriftConfiguration); // Anonymous pipe CTOR begin - inherited Create; + inherited Create(aConfig); FBufsize := aBufSize; FReadHandle := INVALID_HANDLE_VALUE; FWriteHandle := INVALID_HANDLE_VALUE; @@ -794,7 +806,7 @@ function TAnonymousPipeServerTransportImpl.Accept(const fnAccepting: TProc): ITr then raise TTransportExceptionNotOpen.Create('TServerPipe unable to initiate pipe communication'); // create the transport impl - result := TAnonymousPipeTransportImpl.Create( FReadHandle, FWriteHandle, FALSE, FTimeOut); + result := TAnonymousPipeTransportImpl.Create( FReadHandle, FWriteHandle, FALSE, FTimeOut, Configuration); end; @@ -872,17 +884,19 @@ function TAnonymousPipeServerTransportImpl.CreateAnonPipe : Boolean; { TNamedPipeServerTransportImpl } -constructor TNamedPipeServerTransportImpl.Create( aPipename : string; aBufsize, aMaxConns, aTimeOut : Cardinal); +constructor TNamedPipeServerTransportImpl.Create( const aPipename : string; + const aBufsize, aMaxConns, aTimeOut : Cardinal; + const aConfig : IThriftConfiguration); // Named Pipe CTOR begin - inherited Create; - ASSERT( aTimeout > 0); + inherited Create( aConfig); FPipeName := aPipename; FBufsize := aBufSize; FMaxConns := Max( 1, Min( PIPE_UNLIMITED_INSTANCES, aMaxConns)); FHandle := INVALID_HANDLE_VALUE; FTimeout := aTimeOut; FConnected := FALSE; + ASSERT( FTimeout > 0); if Copy(FPipeName,1,2) <> '\\' then FPipeName := '\\.\pipe\' + FPipeName; // assume localhost @@ -951,7 +965,7 @@ function TNamedPipeServerTransportImpl.CreateTransportInstance : ITransport; hPipe := THandle( InterlockedExchangePointer( Pointer(FHandle), Pointer(INVALID_HANDLE_VALUE))); try FConnected := FALSE; - result := TNamedPipeTransportServerEndImpl.Create( hPipe, TRUE, FTimeout); + result := TNamedPipeTransportServerEndImpl.Create( hPipe, TRUE, FTimeout, Configuration); except ClosePipeHandle(hPipe); raise; diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas index 2f961a00168..7a1b48fa2f5 100644 --- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas @@ -29,6 +29,7 @@ interface Math, Generics.Collections, Thrift.Collections, + Thrift.Configuration, Thrift.Transport, Thrift.Exception, Thrift.Utils, @@ -36,7 +37,7 @@ interface Thrift.Stream; type - TWinHTTPClientImpl = class( TTransportImpl, IHTTPClient) + TWinHTTPClientImpl = class( TEndpointTransportBase, IHTTPClient) strict private FUri : string; FInputStream : IThriftStream; @@ -58,19 +59,16 @@ TWinHTTPClientImpl = class( TTransportImpl, IHTTPClient) THTTPResponseStream = class( TThriftStreamImpl) strict private FRequest : IWinHTTPRequest; - FTransportControl : ITransportControl; strict protected procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; - procedure CheckReadBytesAvailable( const value : Integer); override; - procedure ConsumeReadBytes( const count : Integer); procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; public - constructor Create( const aRequest : IWinHTTPRequest; const aTransportCtl : ITransportControl); + constructor Create( const aRequest : IWinHTTPRequest); destructor Destroy; override; end; @@ -81,7 +79,6 @@ THTTPResponseStream = class( TThriftStreamImpl) function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; procedure Flush; override; - procedure CheckReadBytesAvailable( const value : Integer); override; procedure SetDnsResolveTimeout(const Value: Integer); function GetDnsResolveTimeout: Integer; @@ -103,25 +100,29 @@ THTTPResponseStream = class( TThriftStreamImpl) property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout; property CustomHeaders: IThriftDictionary read GetCustomHeaders; public - constructor Create( const AUri: string; const aTransportCtl : ITransportControl = nil); + constructor Create( const aUri: string; const aConfig : IThriftConfiguration = nil); destructor Destroy; override; end; implementation +const + WINHTTP_CONNECTION_TIMEOUT = 60 * 1000; + WINHTTP_SENDRECV_TIMEOUT = 30 * 1000; + { TWinHTTPClientImpl } -constructor TWinHTTPClientImpl.Create(const AUri: string; const aTransportCtl : ITransportControl); +constructor TWinHTTPClientImpl.Create( const aUri: string; const aConfig : IThriftConfiguration); begin - inherited Create( aTransportCtl); + inherited Create( aConfig); FUri := AUri; // defaults according to MSDN FDnsResolveTimeout := 0; // no timeout - FConnectionTimeout := 60 * 1000; - FSendTimeout := 30 * 1000; - FReadTimeout := 30 * 1000; + FConnectionTimeout := WINHTTP_CONNECTION_TIMEOUT; + FSendTimeout := WINHTTP_SENDRECV_TIMEOUT; + FReadTimeout := WINHTTP_SENDRECV_TIMEOUT; FSecureProtocols := DEFAULT_THRIFT_SECUREPROTOCOLS; @@ -288,13 +289,6 @@ procedure TWinHTTPClientImpl.Flush; end; end; -procedure TWinHTTPClientImpl.CheckReadBytesAvailable( const value : Integer); -begin - if FInputStream <> nil - then FInputStream.CheckReadBytesAvailable( value) - else raise TTransportExceptionNotOpen.Create('No request has been sent'); -end; - function TWinHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; begin if FInputStream = nil then begin @@ -303,7 +297,7 @@ function TWinHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; try Result := FInputStream.Read( pBuf, buflen, off, len); - ConsumeReadBytes( result); + CountConsumedMessageBytes( result); except on E: Exception do raise TTransportExceptionUnknown.Create(E.Message); @@ -313,7 +307,6 @@ function TWinHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; procedure TWinHTTPClientImpl.SendRequest; var http : IWinHTTPRequest; - ctrl : ITransportControl; pData : PByte; len : Integer; error : Cardinal; @@ -340,8 +333,8 @@ procedure TWinHTTPClientImpl.SendRequest; else raise TTransportExceptionInterrupted.Create( sMsg); end; - ctrl := TTransportControlImpl.Create( TransportControl.MaxAllowedMessageSize); - FInputStream := THTTPResponseStream.Create( http, ctrl); + FInputStream := THTTPResponseStream.Create( http); + UpdateKnownMessageSize( http.QueryTotalResponseSize); end; procedure TWinHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer); @@ -355,12 +348,10 @@ procedure TWinHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer); { TWinHTTPClientImpl.THTTPResponseStream } -constructor TWinHTTPClientImpl.THTTPResponseStream.Create( const aRequest : IWinHTTPRequest; const aTransportCtl : ITransportControl); +constructor TWinHTTPClientImpl.THTTPResponseStream.Create( const aRequest : IWinHTTPRequest); begin inherited Create; FRequest := aRequest; - FTransportControl := aTransportCtl; - ASSERT( FTransportControl <> nil); end; destructor TWinHTTPClientImpl.THTTPResponseStream.Destroy; @@ -406,8 +397,6 @@ function TWinHTTPClientImpl.THTTPResponseStream.Read(const pBuf : Pointer; const if count >= buflen-offset then count := buflen-offset; - CheckReadBytesAvailable(count); - if count > 0 then begin pTmp := pBuf; Inc( pTmp, offset); @@ -415,20 +404,6 @@ function TWinHTTPClientImpl.THTTPResponseStream.Read(const pBuf : Pointer; const ASSERT( Result >= 0); end else Result := 0; - - ConsumeReadBytes( result); -end; - -procedure TWinHTTPClientImpl.THTTPResponseStream.ConsumeReadBytes( const count : Integer); -begin - if FTransportControl <> nil - then FTransportControl.ConsumeReadBytes( count); -end; - -procedure TWinHTTPClientImpl.THTTPResponseStream.CheckReadBytesAvailable( const value : Integer); -begin - if Int64(value) > Int64(FRequest.QueryTotalResponseSize) - then raise TTransportExceptionEndOfFile.Create('Not enough input data'); end; function TWinHTTPClientImpl.THTTPResponseStream.ToArray: TBytes; diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index 0a9a39e041d..af62548db33 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -38,6 +38,7 @@ interface Thrift.Socket, {$ENDIF} {$ENDIF} + Thrift.Configuration, Thrift.Collections, Thrift.Exception, Thrift.Utils, @@ -49,28 +50,10 @@ interface DEFAULT_THRIFT_TIMEOUT = 5 * 1000; // ms type - ITransportControl = interface - ['{CDA35E2C-F1D2-4BE3-9927-7F1540923265}'] - function MaxAllowedMessageSize : Integer; - procedure ConsumeReadBytes( const count : Integer); - procedure ResetConsumedMessageSize; - end; - - TTransportControlImpl = class( TInterfacedObject, ITransportControl) - strict private - FMaxAllowedMsgSize : Integer; - FRemainingMsgSize : Integer; - strict protected - // ITransportControl - function MaxAllowedMessageSize : Integer; - procedure ConsumeReadBytes( const count : Integer); - procedure ResetConsumedMessageSize; - public - constructor Create( const aMaxMessageSize : Integer = DEFAULT_MAX_MESSAGE_SIZE); reintroduce; - end; + IStreamTransport = interface; ITransport = interface - ['{938F6EB5-1848-43D5-8AC4-07633C55B229}'] + ['{52F81383-F880-492F-8AA7-A66B85B93D6B}'] function GetIsOpen: Boolean; property IsOpen: Boolean read GetIsOpen; function Peek: Boolean; @@ -87,14 +70,14 @@ TTransportControlImpl = class( TInterfacedObject, ITransportControl) procedure Write( const pBuf : Pointer; len : Integer); overload; procedure Flush; - function TransportControl : ITransportControl; - procedure CheckReadBytesAvailable( const value : Integer); + function Configuration : IThriftConfiguration; + function MaxMessageSize : Integer; + procedure ResetConsumedMessageSize( const knownSize : Int64 = -1); + procedure CheckReadBytesAvailable( const numBytes : Int64); + procedure UpdateKnownMessageSize( const size : Int64); end; - TTransportImpl = class( TInterfacedObject, ITransport) - strict private - FTransportControl : ITransportControl; - + TTransportBase = class abstract( TInterfacedObject) strict protected function GetIsOpen: Boolean; virtual; abstract; property IsOpen: Boolean read GetIsOpen; @@ -112,12 +95,44 @@ TTransportImpl = class( TInterfacedObject, ITransport) procedure Write( const pBuf : Pointer; off, len : Integer); overload; virtual; abstract; procedure Flush; virtual; - function TransportControl : ITransportControl; inline; - procedure ConsumeReadBytes( const count : Integer); inline; - procedure CheckReadBytesAvailable( const value : Integer); virtual; abstract; + function Configuration : IThriftConfiguration; virtual; abstract; + procedure UpdateKnownMessageSize( const size : Int64); virtual; abstract; + end; + + // base class for all endpoint transports, e.g. sockets, pipes or HTTP + TEndpointTransportBase = class abstract( TTransportBase, ITransport) + strict private + FRemainingMessageSize : Int64; + FKnownMessageSize : Int64; + FConfiguration : IThriftConfiguration; + strict protected + function Configuration : IThriftConfiguration; override; + function MaxMessageSize : Integer; + property RemainingMessageSize : Int64 read FRemainingMessageSize; + property KnownMessageSize : Int64 read FKnownMessageSize; + procedure ResetConsumedMessageSize( const newSize : Int64 = -1); inline; + procedure UpdateKnownMessageSize(const size : Int64); override; + procedure CheckReadBytesAvailable(const numBytes : Int64); inline; + procedure CountConsumedMessageBytes(const numBytes : Int64); inline; + public + constructor Create( const aConfig : IThriftConfiguration); reintroduce; + end; + // base class for all layered transports, e.g. framed + TLayeredTransportBase = class abstract( TTransportBase, ITransport) + strict private + FTransport : T; + strict protected + property InnerTransport : T read FTransport; + function GetUnderlyingTransport: ITransport; + function Configuration : IThriftConfiguration; override; + procedure UpdateKnownMessageSize( const size : Int64); override; + function MaxMessageSize : Integer; inline; + procedure ResetConsumedMessageSize( const knownSize : Int64 = -1); inline; + procedure CheckReadBytesAvailable( const numBytes : Int64); virtual; public - constructor Create( const aTransportCtl : ITransportControl); reintroduce; + constructor Create( const aTransport: T); reintroduce; + property UnderlyingTransport: ITransport read GetUnderlyingTransport; end; TTransportException = class abstract( TException) @@ -220,17 +235,23 @@ TTransportExceptionCorruptedData = class (TTransportExceptionSpecialized) end; IServerTransport = interface - ['{C43B87ED-69EA-47C4-B77C-15E288252900}'] + ['{FA01363F-6B40-482F-971E-4A085535EFC8}'] procedure Listen; procedure Close; function Accept( const fnAccepting: TProc): ITransport; + function Configuration : IThriftConfiguration; end; TServerTransportImpl = class( TInterfacedObject, IServerTransport) + strict private + FConfig : IThriftConfiguration; strict protected + function Configuration : IThriftConfiguration; procedure Listen; virtual; abstract; procedure Close; virtual; abstract; - function Accept( const fnAccepting: TProc): ITransport; virtual; abstract; + function Accept( const fnAccepting: TProc): ITransport; virtual; abstract; + public + constructor Create( const aConfig : IThriftConfiguration); end; ITransportFactory = interface @@ -238,11 +259,13 @@ TServerTransportImpl = class( TInterfacedObject, IServerTransport) function GetTransport( const aTransport: ITransport): ITransport; end; - TTransportFactoryImpl = class( TInterfacedObject, ITransportFactory) + TTransportFactoryImpl = class ( TInterfacedObject, ITransportFactory) + strict protected function GetTransport( const aTransport: ITransport): ITransport; virtual; end; - TTcpSocketStreamImpl = class( TThriftStreamImpl ) + + TTcpSocketStreamImpl = class( TThriftStreamImpl) {$IFDEF OLD_SOCKETS} strict private type TWaitForData = ( wfd_HaveData, wfd_Timeout, wfd_Error); @@ -261,7 +284,6 @@ TTcpSocketStreamImpl = class( TThriftStreamImpl ) strict protected procedure Write( const pBuf : Pointer; offset, count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; - procedure CheckReadBytesAvailable( const value : Integer); override; procedure Open; override; procedure Close; override; procedure Flush; override; @@ -270,9 +292,9 @@ TTcpSocketStreamImpl = class( TThriftStreamImpl ) function ToArray: TBytes; override; public {$IFDEF OLD_SOCKETS} - constructor Create( const aTcpClient: TCustomIpClient; const aTimeout : Integer = 0); + constructor Create( const aTcpClient: TCustomIpClient; const aTimeout : Integer = DEFAULT_THRIFT_TIMEOUT); {$ELSE} - constructor Create( const aTcpClient: TSocket; const aTimeout : Longword = 0); + constructor Create( const aTcpClient: TSocket; const aTimeout : Longword = DEFAULT_THRIFT_TIMEOUT); {$ENDIF} end; @@ -284,7 +306,7 @@ TTcpSocketStreamImpl = class( TThriftStreamImpl ) property OutputStream : IThriftStream read GetOutputStream; end; - TStreamTransportImpl = class( TTransportImpl, IStreamTransport) + TStreamTransportImpl = class( TEndpointTransportBase, IStreamTransport) strict protected FInputStream : IThriftStream; FOutputStream : IThriftStream; @@ -294,7 +316,6 @@ TStreamTransportImpl = class( TTransportImpl, IStreamTransport) function GetInputStream: IThriftStream; function GetOutputStream: IThriftStream; - procedure CheckReadBytesAvailable( const value : Integer); override; strict protected procedure Open; override; procedure Close; override; @@ -302,7 +323,7 @@ TStreamTransportImpl = class( TTransportImpl, IStreamTransport) function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; public - constructor Create( const aInputStream, aOutputStream : IThriftStream; const aTransportCtl : ITransportControl = nil); + constructor Create( const aInputStream, aOutputStream : IThriftStream; const aConfig : IThriftConfiguration = nil); reintroduce; destructor Destroy; override; property InputStream : IThriftStream read GetInputStream; @@ -318,12 +339,13 @@ TBufferedStreamImpl = class( TThriftStreamImpl) strict protected procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override; function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override; - procedure CheckReadBytesAvailable( const value : Integer); override; procedure Open; override; procedure Close; override; procedure Flush; override; function IsOpen: Boolean; override; function ToArray: TBytes; override; + function Size : Int64; override; + function Position : Int64; override; public constructor Create( const aStream: IThriftStream; const aBufSize : Integer); destructor Destroy; override; @@ -340,38 +362,34 @@ TServerSocketImpl = class( TServerTransportImpl) {$ENDIF} FUseBufferedSocket : Boolean; FOwnsServer : Boolean; - FTransportControl : ITransportControl; strict protected function Accept( const fnAccepting: TProc) : ITransport; override; - property TransportControl : ITransportControl read FTransportControl; public -{$IFDEF OLD_SOCKETS} - constructor Create( const aServer: TTcpServer; const aClientTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload; - constructor Create( const aPort: Integer; const aClientTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; aUseBufferedSockets: Boolean = FALSE; const aTransportCtl : ITransportControl = nil); overload; -{$ELSE} - constructor Create( const aServer: TServerSocket; const aClientTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload; - constructor Create( const aPort: Integer; const aClientTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; aUseBufferedSockets: Boolean = FALSE; const aTransportCtl : ITransportControl = nil); overload; -{$ENDIF} + {$IFDEF OLD_SOCKETS} + constructor Create( const aServer: TTcpServer; const aClientTimeout : Integer = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil); overload; + constructor Create( const aPort: Integer; const aClientTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; aUseBufferedSockets: Boolean = FALSE; const aConfig : IThriftConfiguration = nil); overload; + {$ELSE} + constructor Create( const aServer: TServerSocket; const aClientTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil); overload; + constructor Create( const aPort: Integer; const aClientTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; aUseBufferedSockets: Boolean = FALSE; const aConfig : IThriftConfiguration = nil); overload; + {$ENDIF} + destructor Destroy; override; procedure Listen; override; procedure Close; override; end; - TBufferedTransportImpl = class( TTransportImpl ) + TBufferedTransportImpl = class( TLayeredTransportBase) strict private FInputBuffer : IThriftStream; FOutputBuffer : IThriftStream; - FTransport : IStreamTransport; FBufSize : Integer; procedure InitBuffers; - function GetUnderlyingTransport: ITransport; strict protected function GetIsOpen: Boolean; override; procedure Flush; override; - procedure CheckReadBytesAvailable( const value : Integer); override; public type TFactory = class( TTransportFactoryImpl ) @@ -384,7 +402,7 @@ TFactory = class( TTransportFactoryImpl ) procedure Close(); override; function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; - property UnderlyingTransport: ITransport read GetUnderlyingTransport; + procedure CheckReadBytesAvailable( const value : Int64); override; property IsOpen: Boolean read GetIsOpen; end; @@ -408,15 +426,16 @@ TSocketImpl = class(TStreamTransportImpl) strict protected function GetIsOpen: Boolean; override; public - procedure Open; override; {$IFDEF OLD_SOCKETS} - constructor Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload; - constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload; + constructor Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil); overload; + constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Integer = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil); overload; {$ELSE} - constructor Create(const aClient: TSocket; const aOwnsClient: Boolean; const aTransportCtl : ITransportControl = nil); overload; - constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; const aTransportCtl : ITransportControl = nil); overload; + constructor Create(const aClient: TSocket; const aOwnsClient: Boolean; const aConfig : IThriftConfiguration = nil); overload; + constructor Create( const aHost: string; const aPort: Integer; const aTimeout: Longword = DEFAULT_THRIFT_TIMEOUT; const aConfig : IThriftConfiguration = nil); overload; {$ENDIF} destructor Destroy; override; + + procedure Open; override; procedure Close; override; {$IFDEF OLD_SOCKETS} property TcpClient: TCustomIpClient read FClient; @@ -427,29 +446,25 @@ TSocketImpl = class(TStreamTransportImpl) property Port: Integer read FPort; end; - TFramedTransportImpl = class( TTransportImpl) - strict protected const - DEFAULT_MAX_LENGTH = 16384000; // this value is used by all Thrift libraries + TFramedTransportImpl = class( TLayeredTransportBase) strict protected type TFramedHeader = Int32; strict protected - FTransport : ITransport; FWriteBuffer : TMemoryStream; FReadBuffer : TMemoryStream; - FMaxFrameSize : Integer; - procedure InitMaxFrameSize; procedure InitWriteBuffer; procedure ReadFrame; procedure Open(); override; - function GetIsOpen: Boolean; override; + function GetIsOpen: Boolean; override; procedure Close(); override; function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override; procedure Write( const pBuf : Pointer; off, len : Integer); override; + procedure CheckReadBytesAvailable( const value : Int64); override; procedure Flush; override; - procedure CheckReadBytesAvailable( const value : Integer); override; + public type TFactory = class( TTransportFactoryImpl ) @@ -457,7 +472,6 @@ TFactory = class( TTransportFactoryImpl ) function GetTransport( const aTransport: ITransport): ITransport; override; end; - constructor Create( const aTransportCtl : ITransportControl); overload; constructor Create( const aTransport: ITransport); overload; destructor Destroy; override; end; @@ -469,122 +483,182 @@ TFactory = class( TTransportFactoryImpl ) implementation -{ TTransportControlImpl } +{ TTransportBase } -constructor TTransportControlImpl.Create( const aMaxMessageSize : Integer); +procedure TTransportBase.Flush; begin - inherited Create; + // nothing to do +end; - if aMaxMessageSize > 0 - then FMaxAllowedMsgSize := aMaxMessageSize - else FMaxAllowedMsgSize := DEFAULT_MAX_MESSAGE_SIZE; +function TTransportBase.Peek: Boolean; +begin + Result := IsOpen; +end; - ResetConsumedMessageSize; +function TTransportBase.Read(var buf: TBytes; off: Integer; len: Integer): Integer; +begin + if Length(buf) > 0 + then result := Read( @buf[0], Length(buf), off, len) + else result := 0; end; -function TTransportControlImpl.MaxAllowedMessageSize : Integer; +function TTransportBase.ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; begin - result := FMaxAllowedMsgSize; + if Length(buf) > 0 + then result := ReadAll( @buf[0], Length(buf), off, len) + else result := 0; end; -procedure TTransportControlImpl.ResetConsumedMessageSize; +function TTransportBase.ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; +var ret : Integer; begin - FRemainingMsgSize := MaxAllowedMessageSize; + result := 0; + while result < len do begin + ret := Read( pBuf, buflen, off + result, len - result); + if ret > 0 + then Inc( result, ret) + else raise TTransportExceptionNotOpen.Create( 'Cannot read, Remote side has closed' ); + end; end; +procedure TTransportBase.Write( const buf: TBytes); +begin + if Length(buf) > 0 + then Write( @buf[0], 0, Length(buf)); +end; -procedure TTransportControlImpl.ConsumeReadBytes( const count : Integer); +procedure TTransportBase.Write( const buf: TBytes; off: Integer; len: Integer); begin - if FRemainingMsgSize >= count - then Dec( FRemainingMsgSize, count) - else begin - FRemainingMsgSize := 0; - if FRemainingMsgSize < count - then raise TTransportExceptionEndOfFile.Create('Maximum message size reached'); - end; + if Length(buf) > 0 + then Write( @buf[0], off, len); end; +procedure TTransportBase.Write( const pBuf : Pointer; len : Integer); +begin + Self.Write( pBuf, 0, len); +end; -{ TTransportImpl } -constructor TTransportImpl.Create( const aTransportCtl : ITransportControl); +{ TEndpointTransportBase } + +constructor TEndpointTransportBase.Create( const aConfig : IThriftConfiguration); begin inherited Create; - if aTransportCtl <> nil - then FTransportControl := aTransportCtl - else FTransportControl := TTransportControlImpl.Create; - ASSERT( FTransportControl <> nil); + if aConfig <> nil + then FConfiguration := aConfig + else FConfiguration := TThriftConfigurationImpl.Create; + + ResetConsumedMessageSize; end; -procedure TTransportImpl.Flush; +function TEndpointTransportBase.Configuration : IThriftConfiguration; begin - // nothing to do + result := FConfiguration; end; -function TTransportImpl.Peek: Boolean; + +function TEndpointTransportBase.MaxMessageSize : Integer; begin - Result := IsOpen; + ASSERT( Configuration <> nil); + result := Configuration.MaxMessageSize; end; -function TTransportImpl.Read(var buf: TBytes; off: Integer; len: Integer): Integer; + +procedure TEndpointTransportBase.ResetConsumedMessageSize( const newSize : Int64); +// Resets RemainingMessageSize to the configured maximum begin - if Length(buf) > 0 - then result := Read( @buf[0], Length(buf), off, len) - else result := 0; + // full reset + if newSize < 0 then begin + FKnownMessageSize := MaxMessageSize; + FRemainingMessageSize := MaxMessageSize; + Exit; + end; + + // update only: message size can shrink, but not grow + ASSERT( KnownMessageSize <= MaxMessageSize); + if newSize > KnownMessageSize + then TTransportExceptionEndOfFile.Create('MaxMessageSize reached'); + + FKnownMessageSize := newSize; + FRemainingMessageSize := newSize; end; -function TTransportImpl.ReadAll(var buf: TBytes; off: Integer; len: Integer): Integer; + +procedure TEndpointTransportBase.UpdateKnownMessageSize( const size : Int64); +// Updates RemainingMessageSize to reflect then known real message size (e.g. framed transport). +// Will throw if we already consumed too many bytes. +var consumed : Int64; begin - if Length(buf) > 0 - then result := ReadAll( @buf[0], Length(buf), off, len) - else result := 0; + consumed := KnownMessageSize - RemainingMessageSize; + ResetConsumedMessageSize(size); + CountConsumedMessageBytes(consumed); end; -function TTransportImpl.ReadAll(const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; -var ret : Integer; + +procedure TEndpointTransportBase.CheckReadBytesAvailable( const numBytes : Int64); +// Throws if there are not enough bytes in the input stream to satisfy a read of numBytes bytes of data begin - result := 0; - while result < len do begin - ret := Read( pBuf, buflen, off + result, len - result); - if ret > 0 - then Inc( result, ret) - else raise TTransportExceptionNotOpen.Create( 'Cannot read, Remote side has closed' ); + if RemainingMessageSize < numBytes + then raise TTransportExceptionEndOfFile.Create('MaxMessageSize reached'); +end; + + +procedure TEndpointTransportBase.CountConsumedMessageBytes( const numBytes : Int64); +// Consumes numBytes from the RemainingMessageSize. +begin + if (RemainingMessageSize >= numBytes) + then Dec( FRemainingMessageSize, numBytes) + else begin + FRemainingMessageSize := 0; + raise TTransportExceptionEndOfFile.Create('MaxMessageSize reached'); end; end; -procedure TTransportImpl.Write( const buf: TBytes); +{ TLayeredTransportBase } + +constructor TLayeredTransportBase.Create( const aTransport: T); begin - if Length(buf) > 0 - then Write( @buf[0], 0, Length(buf)); + inherited Create; + FTransport := aTransport; end; -procedure TTransportImpl.Write( const buf: TBytes; off: Integer; len: Integer); +function TLayeredTransportBase.GetUnderlyingTransport: ITransport; begin - if Length(buf) > 0 - then Write( @buf[0], off, len); + result := InnerTransport; end; -procedure TTransportImpl.Write( const pBuf : Pointer; len : Integer); +function TLayeredTransportBase.Configuration : IThriftConfiguration; begin - Self.Write( pBuf, 0, len); + result := InnerTransport.Configuration; +end; + +procedure TLayeredTransportBase.UpdateKnownMessageSize( const size : Int64); +begin + InnerTransport.UpdateKnownMessageSize( size); end; -function TTransportImpl.TransportControl : ITransportControl; +function TLayeredTransportBase.MaxMessageSize : Integer; begin - result := FTransportControl; + result := InnerTransport.MaxMessageSize; end; -procedure TTransportImpl.ConsumeReadBytes( const count : Integer); +procedure TLayeredTransportBase.ResetConsumedMessageSize( const knownSize : Int64 = -1); begin - if FTransportControl <> nil - then FTransportControl.ConsumeReadBytes( count); + InnerTransport.ResetConsumedMessageSize( knownSize); end; +procedure TLayeredTransportBase.CheckReadBytesAvailable( const numBytes : Int64); +begin + InnerTransport.CheckReadBytesAvailable( numBytes); +end; + + + { TTransportException } constructor TTransportException.HiddenCreate(const Msg: string); @@ -676,18 +750,33 @@ function TTransportFactoryImpl.GetTransport( const aTransport: ITransport): ITra Result := aTransport; end; + +{ TServerTransportImpl } + +constructor TServerTransportImpl.Create( const aConfig : IThriftConfiguration); +begin + inherited Create; + if aConfig <> nil + then FConfig := aConfig + else FConfig := TThriftConfigurationImpl.Create; +end; + +function TServerTransportImpl.Configuration : IThriftConfiguration; +begin + result := FConfig; +end; + { TServerSocket } {$IFDEF OLD_SOCKETS} -constructor TServerSocketImpl.Create( const aServer: TTcpServer; const aClientTimeout : Integer; const aTransportCtl : ITransportControl); +constructor TServerSocketImpl.Create( const aServer: TTcpServer; const aClientTimeout : Integer; const aConfig : IThriftConfiguration); {$ELSE} -constructor TServerSocketImpl.Create( const aServer: TServerSocket; const aClientTimeout: Longword; const aTransportCtl : ITransportControl); +constructor TServerSocketImpl.Create( const aServer: TServerSocket; const aClientTimeout: Longword; const aConfig : IThriftConfiguration); {$ENDIF} begin - inherited Create; + inherited Create( aConfig); FServer := aServer; - FTransportControl := aTransportCtl; - ASSERT( FTransportControl <> nil); + {$IFDEF OLD_SOCKETS} FClientTimeout := aClientTimeout; @@ -699,17 +788,12 @@ constructor TServerSocketImpl.Create( const aServer: TServerSocket; const aClien {$IFDEF OLD_SOCKETS} -constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Integer; aUseBufferedSockets: Boolean; const aTransportCtl : ITransportControl); +constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Integer; aUseBufferedSockets: Boolean; const aConfig : IThriftConfiguration); {$ELSE} -constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Longword; aUseBufferedSockets: Boolean; const aTransportCtl : ITransportControl); +constructor TServerSocketImpl.Create( const aPort: Integer; const aClientTimeout: Longword; aUseBufferedSockets: Boolean; const aConfig : IThriftConfiguration); {$ENDIF} begin - inherited Create; - - if aTransportCtl <> nil - then FTransportControl := aTransportCtl - else FTransportControl := TTransportControlImpl.Create; - ASSERT( FTransportControl <> nil); + inherited Create( aConfig); {$IFDEF OLD_SOCKETS} FPort := aPort; @@ -772,7 +856,7 @@ function TServerSocketImpl.Accept( const fnAccepting: TProc): ITransport; Exit; end; - trans := TSocketImpl.Create( client, TRUE, FClientTimeout, TransportControl); + trans := TSocketImpl.Create( client, TRUE, FClientTimeout, Configuration); client := nil; // trans owns it now if FUseBufferedSocket @@ -791,7 +875,7 @@ function TServerSocketImpl.Accept( const fnAccepting: TProc): ITransport; client := FServer.Accept; try - trans := TSocketImpl.Create(client, True, TransportControl); + trans := TSocketImpl.Create(client, TRUE, Configuration); client := nil; if FUseBufferedSocket then @@ -840,9 +924,9 @@ procedure TServerSocketImpl.Close; { TSocket } {$IFDEF OLD_SOCKETS} -constructor TSocketImpl.Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer; const aTransportCtl : ITransportControl); +constructor TSocketImpl.Create( const aClient : TCustomIpClient; const aOwnsClient : Boolean; const aTimeout: Integer; const aConfig : IThriftConfiguration); {$ELSE} -constructor TSocketImpl.Create(const aClient: TSocket; const aOwnsClient: Boolean; const aTransportCtl : ITransportControl); +constructor TSocketImpl.Create(const aClient: TSocket; const aOwnsClient: Boolean; const aConfig : IThriftConfiguration); {$ENDIF} var stream : IThriftStream; begin @@ -856,16 +940,17 @@ constructor TSocketImpl.Create(const aClient: TSocket; const aOwnsClient: Boolea {$ENDIF} stream := TTcpSocketStreamImpl.Create( FClient, FTimeout); - inherited Create( stream, stream, aTransportCtl); + inherited Create( stream, stream, aConfig); end; + {$IFDEF OLD_SOCKETS} -constructor TSocketImpl.Create(const aHost: string; const aPort, aTimeout: Integer; const aTransportCtl : ITransportControl); +constructor TSocketImpl.Create(const aHost: string; const aPort, aTimeout: Integer; const aConfig : IThriftConfiguration); {$ELSE} -constructor TSocketImpl.Create(const aHost: string; const aPort : Integer; const aTimeout: Longword; const aTransportCtl : ITransportControl); +constructor TSocketImpl.Create(const aHost: string; const aPort : Integer; const aTimeout: Longword; const aConfig : IThriftConfiguration); {$ENDIF} begin - inherited Create(nil,nil, aTransportCtl); + inherited Create(nil,nil, aConfig); FHost := aHost; FPort := aPort; FTimeout := aTimeout; @@ -1043,30 +1128,12 @@ function TBufferedStreamImpl.Read( const pBuf : Pointer; const buflen : Integer; end; -procedure TBufferedStreamImpl.CheckReadBytesAvailable( const value : Integer); -var nRequired : Integer; -begin - nRequired := value; - - if FReadBuffer <> nil then begin - Dec( nRequired, (FReadBuffer.Position - FReadBuffer.Size)); - if nRequired <= 0 then Exit; - end; - - if FStream <> nil - then FStream.CheckReadBytesAvailable( nRequired) - else raise TTransportExceptionEndOfFile.Create('Not enough input data'); -end; - - function TBufferedStreamImpl.ToArray: TBytes; var len : Integer; begin - len := 0; - - if IsOpen then begin - len := FReadBuffer.Size; - end; + if IsOpen + then len := FReadBuffer.Size + else len := 0; SetLength( Result, len); @@ -1092,11 +1159,24 @@ procedure TBufferedStreamImpl.Write( const pBuf : Pointer; offset: Integer; coun end; end; + +function TBufferedStreamImpl.Size : Int64; +begin + result := FReadBuffer.Size; +end; + + +function TBufferedStreamImpl.Position : Int64; +begin + result := FReadBuffer.Position; +end; + + { TStreamTransportImpl } -constructor TStreamTransportImpl.Create( const aInputStream, aOutputStream : IThriftStream; const aTransportCtl : ITransportControl); +constructor TStreamTransportImpl.Create( const aInputStream, aOutputStream : IThriftStream; const aConfig : IThriftConfiguration); begin - inherited Create( aTransportCtl); + inherited Create( aConfig); FInputStream := aInputStream; FOutputStream := aOutputStream; end; @@ -1149,7 +1229,7 @@ function TStreamTransportImpl.Read( const pBuf : Pointer; const buflen : Integer then raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' ); Result := FInputStream.Read( pBuf,buflen, off, len ); - ConsumeReadBytes( result); + CountConsumedMessageBytes( result); end; procedure TStreamTransportImpl.Write( const pBuf : Pointer; off, len : Integer); @@ -1160,28 +1240,19 @@ procedure TStreamTransportImpl.Write( const pBuf : Pointer; off, len : Integer); FOutputStream.Write( pBuf, off, len ); end; -procedure TStreamTransportImpl.CheckReadBytesAvailable( const value : Integer); -begin - if FInputStream <> nil - then FInputStream.CheckReadBytesAvailable( value) - else raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' ); -end; - - { TBufferedTransportImpl } constructor TBufferedTransportImpl.Create( const aTransport : IStreamTransport; const aBufSize: Integer); begin ASSERT( aTransport <> nil); - inherited Create( aTransport.TransportControl); - FTransport := aTransport; + inherited Create( aTransport); FBufSize := aBufSize; InitBuffers; end; procedure TBufferedTransportImpl.Close; begin - FTransport.Close; + InnerTransport.Close; FInputBuffer := nil; FOutputBuffer := nil; end; @@ -1195,34 +1266,29 @@ procedure TBufferedTransportImpl.Flush; function TBufferedTransportImpl.GetIsOpen: Boolean; begin - Result := FTransport.IsOpen; -end; - -function TBufferedTransportImpl.GetUnderlyingTransport: ITransport; -begin - Result := FTransport; + Result := InnerTransport.IsOpen; end; procedure TBufferedTransportImpl.InitBuffers; begin - if FTransport.InputStream <> nil then begin - FInputBuffer := TBufferedStreamImpl.Create( FTransport.InputStream, FBufSize ); + if InnerTransport.InputStream <> nil then begin + FInputBuffer := TBufferedStreamImpl.Create( InnerTransport.InputStream, FBufSize ); end; - if FTransport.OutputStream <> nil then begin - FOutputBuffer := TBufferedStreamImpl.Create( FTransport.OutputStream, FBufSize ); + if InnerTransport.OutputStream <> nil then begin + FOutputBuffer := TBufferedStreamImpl.Create( InnerTransport.OutputStream, FBufSize ); end; end; procedure TBufferedTransportImpl.Open; begin - FTransport.Open; + InnerTransport.Open; InitBuffers; // we need to get the buffers to match FTransport substreams again end; function TBufferedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; begin if FInputBuffer <> nil - then Result := FInputBuffer.Read( pBuf,buflen, off, len) + then Result := FInputBuffer.Read( pBuf,buflen, off, len ) else Result := 0; end; @@ -1233,23 +1299,18 @@ procedure TBufferedTransportImpl.Write( const pBuf : Pointer; off, len : Integer end; end; -procedure TBufferedTransportImpl.CheckReadBytesAvailable( const value : Integer); -var stm2 : IThriftStream2; - need : Integer; +procedure TBufferedTransportImpl.CheckReadBytesAvailable( const value : Int64); +var buffered, need : Int64; begin need := value; // buffered bytes - if Supports( FInputBuffer, IThriftStream2, stm2) then begin - Dec( need, stm2.Size - stm2.Position); - if need <= 0 then Exit; - end; - - if FInputBuffer <> nil - then FInputBuffer.CheckReadBytesAvailable( need) - else raise TTransportExceptionNotOpen.Create('Cannot read from null inputstream' ); + buffered := FInputBuffer.Size - FInputBuffer.Position; + if buffered < need + then InnerTransport.CheckReadBytesAvailable( need - buffered); end; + { TBufferedTransportImpl.TFactory } function TBufferedTransportImpl.TFactory.GetTransport( const aTransport: ITransport): ITransport; @@ -1260,53 +1321,33 @@ function TBufferedTransportImpl.TFactory.GetTransport( const aTransport: ITransp { TFramedTransportImpl } -constructor TFramedTransportImpl.Create( const aTransportCtl : ITransportControl); -begin - inherited Create( aTransportCtl); - - InitMaxFrameSize; - InitWriteBuffer; -end; - constructor TFramedTransportImpl.Create( const aTransport: ITransport); begin ASSERT( aTransport <> nil); - inherited Create( aTransport.TransportControl); + inherited Create( aTransport); - InitMaxFrameSize; InitWriteBuffer; - FTransport := aTransport; end; destructor TFramedTransportImpl.Destroy; begin FWriteBuffer.Free; + FWriteBuffer := nil; FReadBuffer.Free; + FReadBuffer := nil; inherited; end; -procedure TFramedTransportImpl.InitMaxFrameSize; -var maxLen : Integer; -begin - FMaxFrameSize := DEFAULT_MAX_LENGTH; - - // MaxAllowedMessageSize may be smaller, but not larger - if TransportControl <> nil then begin - maxLen := TransportControl.MaxAllowedMessageSize - SizeOf(TFramedHeader); - FMaxFrameSize := Min( FMaxFrameSize, maxLen); - end; -end; - procedure TFramedTransportImpl.Close; begin - FTransport.Close; + InnerTransport.Close; end; procedure TFramedTransportImpl.Flush; var buf : TBytes; len : Integer; - data_len : Integer; + data_len : Int64; begin if not IsOpen then raise TTransportExceptionNotOpen.Create('not open'); @@ -1318,9 +1359,9 @@ procedure TFramedTransportImpl.Flush; end; data_len := len - SizeOf(TFramedHeader); - if (data_len < 0) then begin - raise TTransportExceptionUnknown.Create('TFramedTransport.Flush: data_len < 0' ); - end; + if (0 > data_len) or (data_len > Configuration.MaxFrameSize) + then raise TTransportExceptionUnknown.Create('TFramedTransport.Flush: invalid frame size ('+IntToStr(data_len)+')') + else UpdateKnownMessageSize( len); InitWriteBuffer; @@ -1329,13 +1370,13 @@ procedure TFramedTransportImpl.Flush; buf[2] := Byte($FF and (data_len shr 8)); buf[3] := Byte($FF and data_len); - FTransport.Write( buf, 0, len ); - FTransport.Flush; + InnerTransport.Write( buf, 0, len ); + InnerTransport.Flush; end; function TFramedTransportImpl.GetIsOpen: Boolean; begin - Result := FTransport.IsOpen; + Result := InnerTransport.IsOpen; end; type @@ -1353,7 +1394,7 @@ procedure TFramedTransportImpl.InitWriteBuffer; procedure TFramedTransportImpl.Open; begin - FTransport.Open; + InnerTransport.Open; end; function TFramedTransportImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; @@ -1382,7 +1423,7 @@ procedure TFramedTransportImpl.ReadFrame; size : Integer; buff : TBytes; begin - FTransport.ReadAll( @i32rd[0], SizeOf(i32rd), 0, SizeOf(i32rd)); + InnerTransport.ReadAll( @i32rd[0], SizeOf(i32rd), 0, SizeOf(i32rd)); size := ((i32rd[0] and $FF) shl 24) or ((i32rd[1] and $FF) shl 16) or @@ -1394,14 +1435,15 @@ procedure TFramedTransportImpl.ReadFrame; raise TTransportExceptionCorruptedData.Create('Read a negative frame size ('+IntToStr(size)+')'); end; - if size > FMaxFrameSize then begin + if Int64(size) > Int64(Configuration.MaxFrameSize) then begin Close(); - raise TTransportExceptionCorruptedData.Create('Frame size ('+IntToStr(size)+') larger than allowed maximum ('+IntToStr(FMaxFrameSize)+')'); + raise TTransportExceptionCorruptedData.Create('Frame size ('+IntToStr(size)+') larger than allowed maximum ('+IntToStr(Configuration.MaxFrameSize)+')'); end; - FTransport.CheckReadBytesAvailable( size); + UpdateKnownMessageSize(size + SizeOf(size)); + SetLength( buff, size ); - FTransport.ReadAll( buff, 0, size ); + InnerTransport.ReadAll( buff, 0, size ); FreeAndNil( FReadBuffer); FReadBuffer := TMemoryStream.Create; @@ -1422,15 +1464,15 @@ procedure TFramedTransportImpl.Write( const pBuf : Pointer; off, len : Integer); end; -procedure TFramedTransportImpl.CheckReadBytesAvailable( const value : Integer); -var nRemaining : Int64; +procedure TFramedTransportImpl.CheckReadBytesAvailable( const value : Int64); +var buffered, need : Int64; begin - if FReadBuffer = nil - then raise TTransportExceptionEndOfFile.Create('Cannot read from null inputstream'); + need := value; - nRemaining := FReadBuffer.Size - FReadBuffer.Position; - if value > nRemaining - then raise TTransportExceptionEndOfFile.Create('Not enough input data'); + // buffered bytes + buffered := FReadBuffer.Size - FReadBuffer.Position; + if buffered < need + then InnerTransport.CheckReadBytesAvailable( need - buffered); end; @@ -1470,9 +1512,10 @@ constructor TTcpSocketStreamImpl.Create( const aTcpClient: TSocket; const aTimeo procedure TTcpSocketStreamImpl.Flush; begin - + // nothing to do end; + function TTcpSocketStreamImpl.IsOpen: Boolean; begin {$IFDEF OLD_SOCKETS} @@ -1557,7 +1600,7 @@ function TTcpSocketStreamImpl.Select( ReadReady, WriteReady, ExceptFlag: PBoolea {$IFDEF LINUX} result := Libc.select( socket + 1, ReadFdsptr, WriteFdsptr, ExceptFdsptr, Timeptr); {$ENDIF} - + if result = SOCKET_ERROR then wsaError := WSAGetLastError; @@ -1638,10 +1681,7 @@ function TTcpSocketStreamImpl.Read( const pBuf : Pointer; const buflen : Integer TWaitForData.wfd_Timeout : begin if (FTimeout = 0) then Exit - else begin - raise TTransportExceptionTimedOut.Create(SysErrorMessage(Cardinal(wsaError))); - - end; + else raise TTransportExceptionTimedOut.Create(SysErrorMessage(Cardinal(wsaError))); end; else ASSERT( FALSE); @@ -1764,10 +1804,5 @@ procedure TTcpSocketStreamImpl.Write( const pBuf : Pointer; offset, count: Integ {$ENDIF} -procedure TTcpSocketStreamImpl.CheckReadBytesAvailable( const value : Integer); -begin - // we can't really tell, no further checks possible -end; - end. diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index 6d886fe9bd2..d06006626a5 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -1224,8 +1224,8 @@ function TWinHTTPRequestImpl.QueryTotalResponseSize : DWORD; dwIndex) then begin dwError := GetLastError; - ASSERT( dwError = ERROR_WINHTTP_HEADER_NOT_FOUND); // anything else would be an real error - result := MAXINT; // we don't know + if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error + result := MAXINT; // we don't know end; end; diff --git a/lib/delphi/test/Performance/PerfTests.pas b/lib/delphi/test/Performance/PerfTests.pas index 2c820b1f3e9..e485212b0c0 100644 --- a/lib/delphi/test/Performance/PerfTests.pas +++ b/lib/delphi/test/Performance/PerfTests.pas @@ -21,6 +21,7 @@ interface uses Windows, Classes, SysUtils, Thrift.Collections, + Thrift.Configuration, Thrift.Test, Thrift.Protocol, Thrift.Protocol.JSON, @@ -34,9 +35,10 @@ interface type TPerformanceTests = class strict private - Testdata : ICrazyNesting; - MemBuffer : TMemoryStream; - Transport : ITransport; + FTestdata : ICrazyNesting; + FMemBuffer : TMemoryStream; + FTransport : ITransport; + FConfig : IThriftConfiguration; procedure ProtocolPeformanceTest; procedure RunTest( const ptyp : TKnownProtocol; const layered : TLayeredTransport); @@ -74,7 +76,7 @@ procedure TPerformanceTests.ProtocolPeformanceTest; var layered : TLayeredTransport; begin Console.WriteLine('Setting up for ProtocolPeformanceTest ...'); - Testdata := TestDataFactory.CreateCrazyNesting(); + FTestdata := TestDataFactory.CreateCrazyNesting(); for layered := Low(TLayeredTransport) to High(TLayeredTransport) do begin RunTest( TKnownProtocol.prot_Binary, layered); @@ -91,10 +93,12 @@ procedure TPerformanceTests.RunTest( const ptyp : TKnownProtocol; const layered begin QueryPerformanceFrequency( freq); + FConfig := TThriftConfigurationImpl.Create; + proto := GenericProtocolFactory( ptyp, layered, TRUE); QueryPerformanceCounter( start); - Testdata.Write(proto); - Transport.Flush; + FTestdata.Write(proto); + FTransport.Flush; QueryPerformanceCounter( stop); Console.WriteLine( Format('RunTest(%s): write = %d msec', [ GetProtocolTransportName(ptyp,layered), @@ -121,24 +125,24 @@ function TPerformanceTests.GenericProtocolFactory(const ptyp : TKnownProtocol; c begin // read happens after write here, so let's take over the written bytes newBuf := TMemoryStream.Create; - if not forWrite then newBuf.CopyFrom( MemBuffer, COPY_ENTIRE_STREAM); - MemBuffer := newBuf; - MemBuffer.Position := 0; + if not forWrite then newBuf.CopyFrom( FMemBuffer, COPY_ENTIRE_STREAM); + FMemBuffer := newBuf; + FMemBuffer.Position := 0; // layered transports anyone? stream := TThriftStreamAdapterDelphi.Create( newBuf, TRUE); if forWrite - then trans := TStreamTransportImpl.Create( nil, stream) - else trans := TStreamTransportImpl.Create( stream, nil); + then trans := TStreamTransportImpl.Create( nil, stream, FConfig) + else trans := TStreamTransportImpl.Create( stream, nil, FConfig); case layered of - trns_Framed : Transport := TFramedTransportImpl.Create( trans); - trns_Buffered : Transport := TBufferedTransportImpl.Create( trans); + trns_Framed : FTransport := TFramedTransportImpl.Create( trans); + trns_Buffered : FTransport := TBufferedTransportImpl.Create( trans); else - Transport := trans; + FTransport := trans; end; - if not Transport.IsOpen - then Transport.Open; + if not FTransport.IsOpen + then FTransport.Open; case ptyp of prot_Binary : result := TBinaryProtocolImpl.Create(trans); diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas index 3562dabb83e..1579bd5f647 100644 --- a/lib/delphi/test/TestClient.pas +++ b/lib/delphi/test/TestClient.pas @@ -53,6 +53,8 @@ interface Thrift.Test, Thrift.WinHTTP, Thrift.Utils, + + Thrift.Configuration, Thrift.Collections; type @@ -122,7 +124,7 @@ TClientThread = class( TThread ) procedure InitializeProtocolTransportStack; procedure ShutdownProtocolTransportStack; - function InitializeHttpTransport( const aTimeoutSetting : Integer) : IHTTPClient; + function InitializeHttpTransport( const aTimeoutSetting : Integer; const aConfig : IThriftConfiguration = nil) : IHTTPClient; procedure JSONProtocolReadWriteTest; function PrepareBinaryData( aRandomDist : Boolean; aSize : TTestSize) : TBytes; @@ -1068,6 +1070,7 @@ procedure TClientThread.JSONProtocolReadWriteTest; var prot : IProtocol; stm : TStringStream; list : TThriftList; + config : IThriftConfiguration; binary, binRead, emptyBinary : TBytes; i,iErr : Integer; const @@ -1089,6 +1092,8 @@ procedure TClientThread.JSONProtocolReadWriteTest; try StartTestGroup( 'JsonProtocolTest', test_Unknown); + config := TThriftConfigurationImpl.Create; + // prepare binary data binary := PrepareBinaryData( FALSE, Normal); SetLength( emptyBinary, 0); // empty binary data block @@ -1096,7 +1101,7 @@ procedure TClientThread.JSONProtocolReadWriteTest; // output setup prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( - nil, TThriftStreamAdapterDelphi.Create( stm, FALSE))); + nil, TThriftStreamAdapterDelphi.Create( stm, FALSE), config)); // write Init( list, TType.String_, 9); @@ -1119,7 +1124,7 @@ procedure TClientThread.JSONProtocolReadWriteTest; stm.Position := 0; prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( - TThriftStreamAdapterDelphi.Create( stm, FALSE), nil)); + TThriftStreamAdapterDelphi.Create( stm, FALSE), nil, config)); // read and compare list := prot.ReadListBegin; @@ -1161,7 +1166,7 @@ procedure TClientThread.JSONProtocolReadWriteTest; stm.Position := 0; prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( - TThriftStreamAdapterDelphi.Create( stm, FALSE), nil)); + TThriftStreamAdapterDelphi.Create( stm, FALSE), nil, config)); Expect( prot.ReadString = SOLIDUS_EXCPECTED, 'Solidus encoding'); @@ -1172,12 +1177,12 @@ procedure TClientThread.JSONProtocolReadWriteTest; stm.Size := 0; prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( - nil, TThriftStreamAdapterDelphi.Create( stm, FALSE))); + nil, TThriftStreamAdapterDelphi.Create( stm, FALSE), config)); prot.WriteString( G_CLEF_AND_CYRILLIC_TEXT); stm.Position := 0; prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( - TThriftStreamAdapterDelphi.Create( stm, FALSE), nil)); + TThriftStreamAdapterDelphi.Create( stm, FALSE), nil, config)); Expect( prot.ReadString = G_CLEF_AND_CYRILLIC_TEXT, 'Writing JSON with chars > 8 bit'); // Widechars should work with hex-encoding too. Do they? @@ -1187,7 +1192,7 @@ procedure TClientThread.JSONProtocolReadWriteTest; stm.Position := 0; prot := TJSONProtocolImpl.Create( TStreamTransportImpl.Create( - TThriftStreamAdapterDelphi.Create( stm, FALSE), nil)); + TThriftStreamAdapterDelphi.Create( stm, FALSE), nil, config)); Expect( prot.ReadString = G_CLEF_AND_CYRILLIC_TEXT, 'Reading JSON with chars > 8 bit'); @@ -1330,7 +1335,7 @@ procedure TClientThread.Execute; end; -function TClientThread.InitializeHttpTransport( const aTimeoutSetting : Integer) : IHTTPClient; +function TClientThread.InitializeHttpTransport( const aTimeoutSetting : Integer; const aConfig : IThriftConfiguration) : IHTTPClient; var sUrl : string; comps : URL_COMPONENTS; dwChars : DWORD; @@ -1367,8 +1372,8 @@ function TClientThread.InitializeHttpTransport( const aTimeoutSetting : Integer) Console.WriteLine('Target URL: '+sUrl); case FSetup.endpoint of - trns_MsxmlHttp : result := TMsxmlHTTPClientImpl.Create( sUrl); - trns_WinHttp : result := TWinHTTPClientImpl.Create( sUrl); + trns_MsxmlHttp : result := TMsxmlHTTPClientImpl.Create( sUrl, aConfig); + trns_WinHttp : result := TWinHTTPClientImpl.Create( sUrl, aConfig); else raise Exception.Create(ENDPOINT_TRANSPORTS[FSetup.endpoint]+' unhandled case'); end; @@ -1396,7 +1401,7 @@ procedure TClientThread.InitializeProtocolTransportStack; case FSetup.endpoint of trns_Sockets: begin Console.WriteLine('Using sockets ('+FSetup.host+' port '+IntToStr(FSetup.port)+')'); - streamtrans := TSocketImpl.Create( FSetup.host, FSetup.port, DEFAULT_THRIFT_TIMEOUT); + streamtrans := TSocketImpl.Create( FSetup.host, FSetup.port); FTransport := streamtrans; end; @@ -1417,7 +1422,7 @@ procedure TClientThread.InitializeProtocolTransportStack; end; trns_AnonPipes: begin - streamtrans := TAnonymousPipeTransportImpl.Create( FSetup.hAnonRead, FSetup.hAnonWrite, FALSE); + streamtrans := TAnonymousPipeTransportImpl.Create( FSetup.hAnonRead, FSetup.hAnonWrite, FALSE, PIPE_TIMEOUT); FTransport := streamtrans; end; diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas index da804fdc027..bbc798beda1 100644 --- a/lib/delphi/test/TestServer.pas +++ b/lib/delphi/test/TestServer.pas @@ -36,6 +36,7 @@ interface Thrift.Protocol.JSON, Thrift.Protocol.Compact, Thrift.Collections, + Thrift.Configuration, Thrift.Utils, Thrift.Test, Thrift, @@ -593,7 +594,7 @@ class procedure TTestServer.Execute( const args: array of string); trns_NamedPipes : begin Console.WriteLine('- named pipe ('+sPipeName+')'); - namedpipe := TNamedPipeServerTransportImpl.Create( sPipeName, 4096, PIPE_UNLIMITED_INSTANCES); + namedpipe := TNamedPipeServerTransportImpl.Create( sPipeName, 4096, PIPE_UNLIMITED_INSTANCES, INFINITE); servertrans := namedpipe; end; @@ -614,7 +615,7 @@ class procedure TTestServer.Execute( const args: array of string); if (trns_Framed in layered) then begin Console.WriteLine('- framed transport'); - TransportFactory := TFramedTransportImpl.TFactory.Create + TransportFactory := TFramedTransportImpl.TFactory.Create; end else begin TransportFactory := TTransportFactoryImpl.Create; diff --git a/lib/delphi/test/client.dpr b/lib/delphi/test/client.dpr index 83727f61951..d4875b8a933 100644 --- a/lib/delphi/test/client.dpr +++ b/lib/delphi/test/client.dpr @@ -31,6 +31,7 @@ uses Thrift in '..\src\Thrift.pas', Thrift.Transport in '..\src\Thrift.Transport.pas', Thrift.Socket in '..\src\Thrift.Socket.pas', + Thrift.Configuration in '..\src\Thrift.Configuration.pas', Thrift.Exception in '..\src\Thrift.Exception.pas', Thrift.Transport.Pipes in '..\src\Thrift.Transport.Pipes.pas', Thrift.Transport.WinHTTP in '..\src\Thrift.Transport.WinHTTP.pas', diff --git a/lib/delphi/test/multiplexed/Multiplex.Client.Main.pas b/lib/delphi/test/multiplexed/Multiplex.Client.Main.pas index 35fdf6f5b73..4b6a0a22168 100644 --- a/lib/delphi/test/multiplexed/Multiplex.Client.Main.pas +++ b/lib/delphi/test/multiplexed/Multiplex.Client.Main.pas @@ -35,6 +35,7 @@ interface Thrift.Transport, Thrift.Stream, Thrift.Collections, + Thrift.Configuration, Benchmark, // in gen-delphi folder Aggr, // in gen-delphi folder Multiplex.Test.Common; @@ -93,8 +94,10 @@ procedure TTestClient.ParseArgs( const args: array of string); procedure TTestClient.Setup; var trans : ITransport; + config : IThriftConfiguration; begin - trans := TSocketImpl.Create( 'localhost', 9090); + config := TThriftConfigurationImpl.Create; + trans := TSocketImpl.Create( 'localhost', 9090, DEFAULT_THRIFT_TIMEOUT, config); trans := TFramedTransportImpl.Create( trans); trans.Open; FProtocol := TBinaryProtocolImpl.Create( trans, TRUE, TRUE); diff --git a/lib/delphi/test/multiplexed/Multiplex.Server.Main.pas b/lib/delphi/test/multiplexed/Multiplex.Server.Main.pas index 3860f5ace0b..a23ff37ea8a 100644 --- a/lib/delphi/test/multiplexed/Multiplex.Server.Main.pas +++ b/lib/delphi/test/multiplexed/Multiplex.Server.Main.pas @@ -35,6 +35,7 @@ interface Thrift.Protocol.Multiplex, Thrift.Processor.Multiplex, Thrift.Collections, + Thrift.Configuration, Thrift.Utils, Thrift, Benchmark, // in gen-delphi folder @@ -156,11 +157,14 @@ class procedure TTestServer.Execute( const args: array of string); aggrProcessor : IProcessor; multiplex : IMultiplexedProcessor; ServerEngine : IServer; + config : IThriftConfiguration; begin try + config := TThriftConfigurationImpl.Create; + // create protocol factory, default to BinaryProtocol ProtocolFactory := TBinaryProtocolImpl.TFactory.Create( TRUE, TRUE); - servertrans := TServerSocketImpl.Create( 9090, 0, FALSE); + servertrans := TServerSocketImpl.Create( 9090, DEFAULT_THRIFT_TIMEOUT, FALSE, config); TransportFactory := TFramedTransportImpl.TFactory.Create; benchHandler := TBenchmarkServiceImpl.Create; diff --git a/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr b/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr index a57e93a2ef8..19f8f6adf45 100644 --- a/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr +++ b/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr @@ -33,6 +33,7 @@ uses Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.Multiplex in '..\..\src\Thrift.Protocol.Multiplex.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', + Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Stream in '..\..\src\Thrift.Stream.pas', Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', diff --git a/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr b/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr index 81ed3ddc4fc..307a9c2dc70 100644 --- a/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr +++ b/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr @@ -33,6 +33,7 @@ uses Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.Multiplex in '..\..\src\Thrift.Protocol.Multiplex.pas', Thrift.Processor.Multiplex in '..\..\src\Thrift.Processor.Multiplex.pas', + Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', diff --git a/lib/delphi/test/serializer/TestSerializer.Tests.pas b/lib/delphi/test/serializer/TestSerializer.Tests.pas index fe69f4efc60..83d67b1dc66 100644 --- a/lib/delphi/test/serializer/TestSerializer.Tests.pas +++ b/lib/delphi/test/serializer/TestSerializer.Tests.pas @@ -33,6 +33,7 @@ interface Thrift.Protocol.JSON, Thrift.Protocol.Compact, Thrift.Collections, + Thrift.Configuration, Thrift.Server, Thrift.Utils, Thrift.Serializer, @@ -283,8 +284,12 @@ procedure TTestSerializer.RunTests; class function TTestSerializer.Serialize(const input : IBase; const factory : TFactoryPair) : TBytes; var serial : TSerializer; + config : IThriftConfiguration; begin - serial := TSerializer.Create( factory.prot, factory.trans); + config := TThriftConfigurationImpl.Create; + config.MaxMessageSize := 0; // we don't read anything here + + serial := TSerializer.Create( factory.prot, factory.trans, config); try result := serial.Serialize( input); finally @@ -295,8 +300,12 @@ class function TTestSerializer.Serialize(const input : IBase; const factory : TF class procedure TTestSerializer.Serialize(const input : IBase; const factory : TFactoryPair; const aStream : TStream); var serial : TSerializer; + config : IThriftConfiguration; begin - serial := TSerializer.Create( factory.prot, factory.trans); + config := TThriftConfigurationImpl.Create; + config.MaxMessageSize := 0; // we don't read anything here + + serial := TSerializer.Create( factory.prot, factory.trans, config); try serial.Serialize( input, aStream); finally @@ -307,8 +316,12 @@ class procedure TTestSerializer.Serialize(const input : IBase; const factory : T class procedure TTestSerializer.Deserialize( const input : TBytes; const target : IBase; const factory : TFactoryPair); var serial : TDeserializer; + config : IThriftConfiguration; begin - serial := TDeserializer.Create( factory.prot, factory.trans, Length(input)); + config := TThriftConfigurationImpl.Create; + config.MaxMessageSize := Length(input); + + serial := TDeserializer.Create( factory.prot, factory.trans, config); try serial.Deserialize( input, target); ValidateReadToEnd( input, serial); @@ -320,8 +333,12 @@ class procedure TTestSerializer.Deserialize( const input : TBytes; const target class procedure TTestSerializer.Deserialize( const input : TStream; const target : IBase; const factory : TFactoryPair); var serial : TDeserializer; + config : IThriftConfiguration; begin - serial := TDeserializer.Create( factory.prot, factory.trans, input.Size); + config := TThriftConfigurationImpl.Create; + config.MaxMessageSize := input.Size; + + serial := TDeserializer.Create( factory.prot, factory.trans, config); try serial.Deserialize( input, target); ValidateReadToEnd( input, serial); diff --git a/lib/delphi/test/serializer/TestSerializer.dpr b/lib/delphi/test/serializer/TestSerializer.dpr index bb4cc89260d..062001461d2 100644 --- a/lib/delphi/test/serializer/TestSerializer.dpr +++ b/lib/delphi/test/serializer/TestSerializer.dpr @@ -34,6 +34,7 @@ uses Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas', Thrift.Protocol.Compact in '..\..\src\Thrift.Protocol.Compact.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', + Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.Serializer in '..\..\src\Thrift.Serializer.pas', @@ -42,8 +43,8 @@ uses Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas', System_, DebugProtoTest, - TestSerializer.Tests, - TestSerializer.Data; + TestSerializer.Tests in 'TestSerializer.Tests.pas', + TestSerializer.Data in 'TestSerializer.Data.pas'; var test : TTestSerializer; diff --git a/lib/delphi/test/server.dpr b/lib/delphi/test/server.dpr index 9731dd4fada..954d0b60684 100644 --- a/lib/delphi/test/server.dpr +++ b/lib/delphi/test/server.dpr @@ -37,6 +37,7 @@ uses Thrift.Protocol.Multiplex in '..\src\Thrift.Protocol.Multiplex.pas', Thrift.Processor.Multiplex in '..\src\Thrift.Processor.Multiplex.pas', Thrift.Collections in '..\src\Thrift.Collections.pas', + Thrift.Configuration in '..\src\Thrift.Configuration.pas', Thrift.Server in '..\src\Thrift.Server.pas', Thrift.TypeRegistry in '..\src\Thrift.TypeRegistry.pas', Thrift.Utils in '..\src\Thrift.Utils.pas', diff --git a/lib/delphi/test/skip/skiptest_version1.dpr b/lib/delphi/test/skip/skiptest_version1.dpr index 0bfe96fef04..c97e50b6f45 100644 --- a/lib/delphi/test/skip/skiptest_version1.dpr +++ b/lib/delphi/test/skip/skiptest_version1.dpr @@ -31,6 +31,7 @@ uses Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', + Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', @@ -70,8 +71,8 @@ var adapt : IThriftStream; begin adapt := TThriftStreamAdapterDelphi.Create( stm, FALSE); if aForInput - then trans := TStreamTransportImpl.Create( adapt, nil) - else trans := TStreamTransportImpl.Create( nil, adapt); + then trans := TStreamTransportImpl.Create( adapt, nil, TThriftConfigurationImpl.Create) + else trans := TStreamTransportImpl.Create( nil, adapt, TThriftConfigurationImpl.Create); result := protfact.GetProtocol( trans); end; diff --git a/lib/delphi/test/skip/skiptest_version2.dpr b/lib/delphi/test/skip/skiptest_version2.dpr index 7893748a06f..07c2c9af475 100644 --- a/lib/delphi/test/skip/skiptest_version2.dpr +++ b/lib/delphi/test/skip/skiptest_version2.dpr @@ -31,6 +31,7 @@ uses Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', + Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas', @@ -96,8 +97,8 @@ var adapt : IThriftStream; begin adapt := TThriftStreamAdapterDelphi.Create( stm, FALSE); if aForInput - then trans := TStreamTransportImpl.Create( adapt, nil) - else trans := TStreamTransportImpl.Create( nil, adapt); + then trans := TStreamTransportImpl.Create( adapt, nil, TThriftConfigurationImpl.Create) + else trans := TStreamTransportImpl.Create( nil, adapt, TThriftConfigurationImpl.Create); result := protfact.GetProtocol( trans); end; diff --git a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr b/lib/delphi/test/typeregistry/TestTypeRegistry.dpr index fd5e3dd4e03..31c0fb2f192 100644 --- a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr +++ b/lib/delphi/test/typeregistry/TestTypeRegistry.dpr @@ -30,6 +30,7 @@ uses Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', + Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', Thrift.Utils in '..\..\src\Thrift.Utils.pas', Thrift.Serializer in '..\..\src\Thrift.Serializer.pas', diff --git a/tutorial/delphi/DelphiClient/DelphiClient.dpr b/tutorial/delphi/DelphiClient/DelphiClient.dpr index 4ea9eb3e992..64d7d685786 100644 --- a/tutorial/delphi/DelphiClient/DelphiClient.dpr +++ b/tutorial/delphi/DelphiClient/DelphiClient.dpr @@ -26,6 +26,7 @@ uses Generics.Collections, Thrift in '..\..\..\lib\delphi\src\Thrift.pas', Thrift.Collections in '..\..\..\lib\delphi\src\Thrift.Collections.pas', + Thrift.Configuration in '..\..\..\lib\delphi\src\Thrift.Configuration.pas', Thrift.Exception in '..\..\..\lib\delphi\src\Thrift.Exception.pas', Thrift.Utils in '..\..\..\lib\delphi\src\Thrift.Utils.pas', Thrift.Stream in '..\..\..\lib\delphi\src\Thrift.Stream.pas', diff --git a/tutorial/delphi/DelphiClient/DelphiClient.dproj b/tutorial/delphi/DelphiClient/DelphiClient.dproj index f9adf858b23..2612f149b64 100644 --- a/tutorial/delphi/DelphiClient/DelphiClient.dproj +++ b/tutorial/delphi/DelphiClient/DelphiClient.dproj @@ -52,6 +52,7 @@ + diff --git a/tutorial/delphi/DelphiServer/DelphiServer.dpr b/tutorial/delphi/DelphiServer/DelphiServer.dpr index fc9997a3fb3..41a3514d018 100644 --- a/tutorial/delphi/DelphiServer/DelphiServer.dpr +++ b/tutorial/delphi/DelphiServer/DelphiServer.dpr @@ -28,6 +28,7 @@ uses Generics.Collections, Thrift in '..\..\..\lib\delphi\src\Thrift.pas', Thrift.Collections in '..\..\..\lib\delphi\src\Thrift.Collections.pas', + Thrift.Configuration in '..\..\..\lib\delphi\src\Thrift.Configuration.pas', Thrift.Exception in '..\..\..\lib\delphi\src\Thrift.Exception.pas', Thrift.Utils in '..\..\..\lib\delphi\src\Thrift.Utils.pas', Thrift.Stream in '..\..\..\lib\delphi\src\Thrift.Stream.pas', diff --git a/tutorial/delphi/DelphiServer/DelphiServer.dproj b/tutorial/delphi/DelphiServer/DelphiServer.dproj index 132d1bfb42b..f62257e2245 100644 --- a/tutorial/delphi/DelphiServer/DelphiServer.dproj +++ b/tutorial/delphi/DelphiServer/DelphiServer.dproj @@ -51,6 +51,7 @@ + From 4266faef0e800db2c51d11419296c448fa815dc4 Mon Sep 17 00:00:00 2001 From: Paulo Neves Date: Sun, 24 Nov 2019 22:46:37 +0100 Subject: [PATCH 446/756] THRIFT-5032 netstd: Use PascalCase for Properties. Client: netstd Patch: Paulo Neves This closes #1949 --- .../src/thrift/generate/t_netstd_generator.cc | 57 ++++++++++++++----- .../src/thrift/generate/t_netstd_generator.h | 2 + test/netstd/Server/Server.csproj | 4 +- test/netstd/Server/TestServer.cs | 28 ++++----- 4 files changed, 61 insertions(+), 30 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index ffe51ab0b24..ba559605fef 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -51,10 +51,11 @@ t_netstd_generator::t_netstd_generator(t_program* program, const map::const_iterator iter; @@ -75,9 +76,12 @@ t_netstd_generator::t_netstd_generator(t_program* program, const mapsecond; } - else + else if (iter->first.compare("pascal") == 0) { - throw "unknown option netstd:" + iter->first; + use_pascal_case_properties = true; + } + else { + throw "unknown option netstd:" + iter->first; } } @@ -188,6 +192,7 @@ void t_netstd_generator::init_generator() pverbose("- union ...... %s\n", (is_union_enabled() ? "ON" : "off")); pverbose("- serialize .. %s\n", (is_serialize_enabled() ? "ON" : "off")); pverbose("- wcf ........ %s\n", (is_wcf_enabled() ? "ON" : "off")); + pverbose("- pascal ..... %s\n", (use_pascal_case_properties ? "ON" : "off")); } string t_netstd_generator::normalize_name(string name) @@ -2674,18 +2679,41 @@ void t_netstd_generator::prepare_member_name_mapping(void* scope, const vectorget_name()); - if (suppress_mapping) - { - name[0] = toupper(name[0]); - } - else - { - name = get_mapped_member_name(name); + +string t_netstd_generator::convert_to_pascal_case(const string& str) { + string out; + bool must_capitalize = true; + bool first_character = true; + for (auto it = str.begin(); it != str.end(); ++it) { + if (std::isalnum(*it)) { + if (must_capitalize) { + out.append(1, (char)::toupper(*it)); + must_capitalize = false; + } else { + out.append(1, *it); + } + } else { + if (first_character) //this is a private variable and should not be PascalCased + return str; + must_capitalize = true; } - return name; + first_character = false; + } + return out; +} + + +string t_netstd_generator::prop_name(t_field* tfield, bool suppress_mapping) { + string name(tfield->get_name()); + if (suppress_mapping) { + name[0] = toupper(name[0]); + if (use_pascal_case_properties) + name = t_netstd_generator::convert_to_pascal_case(name); + } else { + name = get_mapped_member_name(name); + } + + return name; } string t_netstd_generator::type_name(t_type* ttype) @@ -3020,4 +3048,5 @@ THRIFT_REGISTER_GENERATOR( " wcf: Adds bindings for WCF to generated classes.\n" " serial: Add serialization support to generated classes.\n" " union: Use new union typing, which includes a static read function for union types.\n" + " pascal: Generate Pascal Case property names according to Microsoft naming convention.\n" ) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.h b/compiler/cpp/src/thrift/generate/t_netstd_generator.h index fd9e6c07035..1e23f91cb4b 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.h +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.h @@ -134,6 +134,7 @@ class t_netstd_generator : public t_oop_generator string argument_list(t_struct* tstruct); string type_to_enum(t_type* ttype); string prop_name(t_field* tfield, bool suppress_mapping = false); + string convert_to_pascal_case(const string& str); string get_enum_class_name(t_type* type); private: @@ -145,6 +146,7 @@ class t_netstd_generator : public t_oop_generator bool hashcode_; bool serialize_; bool wcf_; + bool use_pascal_case_properties; string wcf_namespace_; map netstd_keywords; diff --git a/test/netstd/Server/Server.csproj b/test/netstd/Server/Server.csproj index 4f2463ce665..5d33aa09dc4 100644 --- a/test/netstd/Server/Server.csproj +++ b/test/netstd/Server/Server.csproj @@ -47,6 +47,6 @@ - + - \ No newline at end of file + diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs index 68461dc9c05..493d89deede 100644 --- a/test/netstd/Server/TestServer.cs +++ b/test/netstd/Server/TestServer.cs @@ -254,20 +254,20 @@ public Task testBinaryAsync(byte[] thing, CancellationToken cancellation public Task testStructAsync(Xtruct thing, CancellationToken cancellationToken) { - logger.Invoke("testStruct({{\"{0}\", {1}, {2}, {3}}})", thing.String_thing, thing.Byte_thing, thing.I32_thing, thing.I64_thing); + logger.Invoke("testStruct({{\"{0}\", {1}, {2}, {3}}})", thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing); return Task.FromResult(thing); } public Task testNestAsync(Xtruct2 nest, CancellationToken cancellationToken) { - var thing = nest.Struct_thing; + var thing = nest.StructThing; logger.Invoke("testNest({{{0}, {{\"{1}\", {2}, {3}, {4}, {5}}}}})", - nest.Byte_thing, - thing.String_thing, - thing.Byte_thing, - thing.I32_thing, - thing.I64_thing, - nest.I32_thing); + nest.ByteThing, + thing.StringThing, + thing.ByteThing, + thing.I32Thing, + thing.I64Thing, + nest.I32Thing); return Task.FromResult(nest); } @@ -429,10 +429,10 @@ public Task testMultiAsync(sbyte arg0, int arg1, long arg2, Dictionary testMultiExceptionAsync(string arg0, string arg1, Cancellati var x = new Xception2 { ErrorCode = 2002, - Struct_thing = new Xtruct { String_thing = "This is an Xception2" } + StructThing = new Xtruct { StringThing = "This is an Xception2" } }; throw x; } - var result = new Xtruct { String_thing = arg1 }; + var result = new Xtruct { StringThing = arg1 }; return Task.FromResult(result); } From 98ce2c8f2b3bb5aaee3e67a5b461dd1a87685cc0 Mon Sep 17 00:00:00 2001 From: Marcin Pajkowski Date: Tue, 5 Nov 2019 00:20:15 +0100 Subject: [PATCH 447/756] THRIFT-4995 Use `ToSocketAddrs` for net addresses --- lib/rs/src/server/threaded.rs | 7 +++---- lib/rs/src/transport/socket.rs | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/rs/src/server/threaded.rs b/lib/rs/src/server/threaded.rs index 8f8c082d67b..cc658bd9dd7 100644 --- a/lib/rs/src/server/threaded.rs +++ b/lib/rs/src/server/threaded.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -use std::net::{TcpListener, TcpStream}; +use std::net::{TcpListener, TcpStream, ToSocketAddrs}; use std::sync::Arc; use threadpool::ThreadPool; @@ -162,14 +162,13 @@ where /// Listen for incoming connections on `listen_address`. /// - /// `listen_address` should be in the form `host:port`, - /// for example: `127.0.0.1:8080`. + /// `listen_address` should implement `ToSocketAddrs` trait. /// /// Return `()` if successful. /// /// Return `Err` when the server cannot bind to `listen_address` or there /// is an unrecoverable error. - pub fn listen(&mut self, listen_address: &str) -> ::Result<()> { + pub fn listen(&mut self, listen_address: A) -> ::Result<()> { let listener = TcpListener::bind(listen_address)?; for stream in listener.incoming() { match stream { diff --git a/lib/rs/src/transport/socket.rs b/lib/rs/src/transport/socket.rs index 0bef67bed00..a2e567e1963 100644 --- a/lib/rs/src/transport/socket.rs +++ b/lib/rs/src/transport/socket.rs @@ -18,7 +18,7 @@ use std::convert::From; use std::io; use std::io::{ErrorKind, Read, Write}; -use std::net::{Shutdown, TcpStream}; +use std::net::{Shutdown, TcpStream, ToSocketAddrs}; use super::{ReadHalf, TIoChannel, WriteHalf}; use {new_transport_error, TransportErrorKind}; @@ -81,8 +81,8 @@ impl TTcpChannel { } } - /// Connect to `remote_address`, which should have the form `host:port`. - pub fn open(&mut self, remote_address: &str) -> ::Result<()> { + /// Connect to `remote_address`, which should implement `ToSocketAddrs` trait. + pub fn open(&mut self, remote_address: A) -> ::Result<()> { if self.stream.is_some() { Err(new_transport_error( TransportErrorKind::AlreadyOpen, From c63084193a8c2131267b7278823b76a726fcef7b Mon Sep 17 00:00:00 2001 From: Marcin Pajkowski Date: Mon, 2 Dec 2019 11:39:28 +0100 Subject: [PATCH 448/756] THRIFT-5042 Fix failing tests Client: Rust Patch: Marcin Pajkowski This closes #1958 --- lib/rs/src/protocol/stored.rs | 4 ++-- lib/rs/src/server/mod.rs | 2 +- lib/rs/src/server/threaded.rs | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/rs/src/protocol/stored.rs b/lib/rs/src/protocol/stored.rs index faa51288e42..bf2d8baf5b0 100644 --- a/lib/rs/src/protocol/stored.rs +++ b/lib/rs/src/protocol/stored.rs @@ -52,8 +52,8 @@ use ProtocolErrorKind; /// impl TProcessor for ActualProcessor { /// fn process( /// &self, -/// _: &mut TInputProtocol, -/// _: &mut TOutputProtocol +/// _: &mut dyn TInputProtocol, +/// _: &mut dyn TOutputProtocol /// ) -> thrift::Result<()> { /// unimplemented!() /// } diff --git a/lib/rs/src/server/mod.rs b/lib/rs/src/server/mod.rs index b719d1ba8d7..f24c1134e4b 100644 --- a/lib/rs/src/server/mod.rs +++ b/lib/rs/src/server/mod.rs @@ -56,7 +56,7 @@ pub use self::threaded::TServer; /// /// // `TProcessor` implementation for `SimpleService` /// impl TProcessor for SimpleServiceSyncProcessor { -/// fn process(&self, i: &mut TInputProtocol, o: &mut TOutputProtocol) -> thrift::Result<()> { +/// fn process(&self, i: &mut dyn TInputProtocol, o: &mut dyn TOutputProtocol) -> thrift::Result<()> { /// unimplemented!(); /// } /// } diff --git a/lib/rs/src/server/threaded.rs b/lib/rs/src/server/threaded.rs index 8f8c082d67b..b33239aaba6 100644 --- a/lib/rs/src/server/threaded.rs +++ b/lib/rs/src/server/threaded.rs @@ -64,7 +64,7 @@ use super::TProcessor; /// /// // `TProcessor` implementation for `SimpleService` /// impl TProcessor for SimpleServiceSyncProcessor { -/// fn process(&self, i: &mut TInputProtocol, o: &mut TOutputProtocol) -> thrift::Result<()> { +/// fn process(&self, i: &mut dyn TInputProtocol, o: &mut dyn TOutputProtocol) -> thrift::Result<()> { /// unimplemented!(); /// } /// } @@ -90,10 +90,10 @@ use super::TProcessor; /// let processor = SimpleServiceSyncProcessor::new(SimpleServiceHandlerImpl {}); /// /// // instantiate the server -/// let i_tr_fact: Box = Box::new(TBufferedReadTransportFactory::new()); -/// let i_pr_fact: Box = Box::new(TBinaryInputProtocolFactory::new()); -/// let o_tr_fact: Box = Box::new(TBufferedWriteTransportFactory::new()); -/// let o_pr_fact: Box = Box::new(TBinaryOutputProtocolFactory::new()); +/// let i_tr_fact: Box = Box::new(TBufferedReadTransportFactory::new()); +/// let i_pr_fact: Box = Box::new(TBinaryInputProtocolFactory::new()); +/// let o_tr_fact: Box = Box::new(TBufferedWriteTransportFactory::new()); +/// let o_pr_fact: Box = Box::new(TBinaryOutputProtocolFactory::new()); /// /// let mut server = TServer::new( /// i_tr_fact, From b34680f01a09896cfbf3536b4b791e4d7c0ee0a3 Mon Sep 17 00:00:00 2001 From: Marcin Pajkowski Date: Mon, 2 Dec 2019 10:29:16 +0100 Subject: [PATCH 449/756] THRIFT-4915 Fix encoding/decoding doubles in TCompactProtocol Client: Rust Patch: Marcin Pajkowski This closes #1957 --- lib/rs/src/protocol/compact.rs | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/rs/src/protocol/compact.rs b/lib/rs/src/protocol/compact.rs index 1750bc42e9b..3e17398a0d8 100644 --- a/lib/rs/src/protocol/compact.rs +++ b/lib/rs/src/protocol/compact.rs @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use integer_encoding::{VarIntReader, VarIntWriter}; use std::convert::{From, TryFrom}; use std::io; @@ -247,7 +247,7 @@ where } fn read_double(&mut self) -> ::Result { - self.transport.read_f64::().map_err(From::from) + self.transport.read_f64::().map_err(From::from) } fn read_string(&mut self) -> ::Result { @@ -521,7 +521,7 @@ where } fn write_double(&mut self, d: f64) -> ::Result<()> { - self.transport.write_f64::(d).map_err(From::from) + self.transport.write_f64::(d).map_err(From::from) } fn write_string(&mut self, s: &str) -> ::Result<()> { @@ -2374,6 +2374,29 @@ mod tests { (i_prot, o_prot) } + #[test] + fn must_read_write_double() { + let (mut i_prot, mut o_prot) = test_objects(); + + let double = 3.141592653589793238462643; + o_prot.write_double(double).unwrap(); + copy_write_buffer_to_read_buffer!(o_prot); + + assert_eq!(i_prot.read_double().unwrap(), double); + } + + #[test] + fn must_encode_double_as_other_langs() { + let (_, mut o_prot) = test_objects(); + let expected = [24, 45, 68, 84, 251, 33, 9, 64]; + + let double = 3.141592653589793238462643; + o_prot.write_double(double).unwrap(); + + assert_eq_written_bytes!(o_prot, expected); + + } + fn assert_no_write(mut write_fn: F) where F: FnMut(&mut TCompactOutputProtocol>) -> ::Result<()>, From 9c6c6bf81a3c934e96378b26fc133f50cf4226a2 Mon Sep 17 00:00:00 2001 From: Julian Tescher Date: Sun, 1 Dec 2019 21:43:01 -0800 Subject: [PATCH 450/756] THRIFT-5043 Make TBufferChannel clonable Client: Rust Patch: Julian Tescher This closes #1956 It is useful for `TBufferChannel` to be `Clone` so that you can use it to read bytes that were written by a client for use cases like testing or sending over alternative transports like UDP. --- lib/rs/src/transport/mem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rs/src/transport/mem.rs b/lib/rs/src/transport/mem.rs index 82c4b579f60..9874257604e 100644 --- a/lib/rs/src/transport/mem.rs +++ b/lib/rs/src/transport/mem.rs @@ -31,7 +31,7 @@ use super::{ReadHalf, TIoChannel, WriteHalf}; /// `set_readable_bytes(...)`. Callers can then read until the buffer is /// depleted. No further reads are accepted until the internal read buffer is /// replenished again. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct TBufferChannel { read: Arc>, write: Arc>, From 1e049101c580fd2dfd044cb00e2489090199cf0a Mon Sep 17 00:00:00 2001 From: kahotv Date: Thu, 28 Nov 2019 01:34:42 +0800 Subject: [PATCH 451/756] Generate comments for the output cpp file Client: cpp Patch: kahotv This closes #1954 --- compiler/cpp/src/thrift/generate/t_cpp_generator.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc index d66b6e6e16b..896c43fcfa1 100644 --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc @@ -504,6 +504,7 @@ void t_cpp_generator::close_generator() { * @param ttypedef The type definition */ void t_cpp_generator::generate_typedef(t_typedef* ttypedef) { + generate_java_doc(f_types_, ttypedef); f_types_ << indent() << "typedef " << type_name(ttypedef->get_type(), true) << " " << ttypedef->get_symbolic() << ";" << endl << endl; } @@ -524,6 +525,7 @@ void t_cpp_generator::generate_enum_constant_list(std::ostream& f, } else { f << "," << endl; } + generate_java_doc(f, *c_iter); indent(f) << prefix << (*c_iter)->get_name() << suffix; if (include_values) { f << " = " << (*c_iter)->get_value(); @@ -547,6 +549,7 @@ void t_cpp_generator::generate_enum(t_enum* tenum) { std::string enum_name = tenum->get_name(); if (!gen_pure_enums_) { enum_name = "type"; + generate_java_doc(f_types_, tenum); f_types_ << indent() << "struct " << tenum->get_name() << " {" << endl; indent_up(); } @@ -1075,6 +1078,8 @@ void t_cpp_generator::generate_struct_declaration(ostream& out, out << endl; + generate_java_doc(out, tstruct); + // Open struct def out << indent() << "class " << tstruct->get_name() << extends << " {" << endl << indent() << " public:" << endl << endl; @@ -1147,6 +1152,7 @@ void t_cpp_generator::generate_struct_declaration(ostream& out, // Declare all fields for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + generate_java_doc(out, *m_iter); indent(out) << declare_field(*m_iter, false, (pointers && !(*m_iter)->get_type()->is_xception()), @@ -1933,6 +1939,9 @@ void t_cpp_generator::generate_service_interface(t_service* tservice, string sty if (style == "CobCl" && gen_templates_) { f_header_ << "template " << endl; } + + generate_java_doc(f_header_, tservice); + f_header_ << "class " << service_if_name << extends << " {" << endl << " public:" << endl; indent_up(); f_header_ << indent() << "virtual ~" << service_if_name << "() {}" << endl; @@ -2225,6 +2234,7 @@ void t_cpp_generator::generate_service_multiface(t_service* tservice) { indent_up(); for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + generate_java_doc(f_header_, *f_iter); t_struct* arglist = (*f_iter)->get_arglist(); const vector& args = arglist->get_members(); vector::const_iterator a_iter; @@ -2438,6 +2448,8 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) } if (style == "Cob") { + generate_java_doc(f_header_, tservice); + f_header_ << indent() << "::std::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() {" << endl << indent() << " return " << _this << "channel_;" << endl << indent() << "}" << endl; @@ -2449,6 +2461,7 @@ void t_cpp_generator::generate_service_client(t_service* tservice, string style) vector functions = tservice->get_functions(); vector::const_iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { + generate_java_doc(f_header_, *f_iter); indent(f_header_) << function_signature(*f_iter, ifstyle) << ";" << endl; // TODO(dreiss): Use private inheritance to avoid generating thise in cob-style. if (style == "Concurrent" && !(*f_iter)->is_oneway()) { From 450bc69248043f0ea5ca336d786583ebf3e9d826 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Tue, 3 Dec 2019 23:28:03 +0100 Subject: [PATCH 452/756] THRIFT-4915 Deserializing double into OrderedFloat always returns zero when using TCompactProtocol Documentation fix Patch: Jens Geyer --- doc/specs/thrift-compact-protocol.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/specs/thrift-compact-protocol.md b/doc/specs/thrift-compact-protocol.md index 02467dd19fa..6be2a62f8cd 100644 --- a/doc/specs/thrift-compact-protocol.md +++ b/doc/specs/thrift-compact-protocol.md @@ -97,8 +97,9 @@ Where: ### Double encoding Values of type `double` are first converted to an int64 according to the IEEE 754 floating-point "double format" bit -layout. Most run-times provide a library to make this conversion. Both the binary protocol as the compact protocol then -encode the int64 in 8 bytes in big endian order. +layout. Most run-times provide a library to make this conversion. But while the binary protocol encodes the int64 +in 8 bytes in big endian order, the compact protocol encodes it in little endian order - this is due to an early +implementation bug that finally became the de-facto standard. ### Boolean encoding From 65e352bbf3ad677cfc1e5fb9b2a363336754c745 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 4 Dec 2019 00:39:41 +0100 Subject: [PATCH 453/756] THRIFT-5037 Documentation for TConfiguration Patch: Jens Geyer This closes #1959 --- doc/specs/thrift-tconfiguration.md | 92 ++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 doc/specs/thrift-tconfiguration.md diff --git a/doc/specs/thrift-tconfiguration.md b/doc/specs/thrift-tconfiguration.md new file mode 100644 index 00000000000..e7736cf9c29 --- /dev/null +++ b/doc/specs/thrift-tconfiguration.md @@ -0,0 +1,92 @@ +Thrift TConfiguration +==================================================================== + +Last Modified: 2019-Dec-03 + + + +Starting with THRIFT-5021 the need to centralize certain limit settings that are used throughout the whole protocol / transport stack became an obvious need. Previous patches already added some of these limits, but they were not consistently managed and just randomly distributed across the code base. + +# Design goals + +Following the tradition of similar experience across languages in Thrift, any implementation should meet these design goals: + + * There MUST be a standard CTOR (or equivalent thereof) that provides a default TConfiguration instance. + * The default values used SHOULD be implemented as outlined below. + * For backwards compatibility, the protocol / transport stack should accept null TConfiguration argument, in which case it should fallback to a default instance automatically. This is to prevent from code-breaking changes as much as possible. + +# Implementation + +The new TConfiguration class or struct currently holds three settings: + +## MaxMessageSize + +The MaxMessageSize member defines the maximum size of a (received) message, in bytes. The default value is represented by a constant named DEFAULT_MAX_MESSAGE_SIZE, whose value is 100 * 1024 * 1024 bytes. + +## MaxFrameSize + +MaxFrameSize limits the size of one frame of data for the TFramedTransport. Since all implementations currently send messages in one frame only if TFramedTransport is used, this value may interfere with MaxMessageSize. In the case of an conflict, the smaller value of the two is used (see remark below). The default value is called DEFAULT_MAX_FRAME_SIZE and has a value of 16384000 bytes. + +## RecursionLimit + +The RecursionLimit defines, how deep structures may be nested into each other. The default named DEFAULT_RECURSION_DEPTH allows for structures nested up to 64 levels deep. + +# Further considerations + +## MaxFrameSize vs. MaxMessageSize + +The difference between the two options is, that MaxFrameSize exists much longer and it is used only in conjunction with TFramedTransport. In contrast, MaxMessageSize is intended to be a general device to be used with any transport or protocol. + +In order to combine both approaches in the most optimal way when using TFramedTransport, it is recommended that the implementation SHOULD update the remaining number of bytes to read based on the received frame size value for the current message. + +For calculation purposes it is important to know, that MaxFrameSize excludes the 4 bytes that hold the frame size, while MaxMessageSize is always looking at the whole data. Hence, when updating the remaining read byte count, the known message size should be set to frameSize + sizeof(i32). + +## Error handling + +If any limit is exceeded, an error should be thrown. Additionally, it may be helpful to check larger memory allocations against the remaining max number of bytes before the allocation attempt takes place. + +# Q&A + +## Is this a breaking change or not? + +There is actually two answers to that question. + +1. If done right, it should not be a breaking change vis-á-vis compiling your source code that uses Thrift. + +1. It may, however, be a breaking change in the way it limits the accepted overall size of messages or the accepted frame size. This behaviour is by design. If your application hits any of these limits during normal operation, it may require you to instantiate an actual TConfiguration and tweak the settings according to your needs. + +## Is splitting the general transport base class into Endpoint and Layered transport base classes necessary? + +No, it's not. However, it turned out that this split is a great help when it comes to managing the TConfiguration instance that is passed through the stack. Having two distinct base classes for each of the different transport types not only allows to implement a shared solution for this. + +The added benefit is, that a clear distinction between the two transport types makes the Thrift architectural idea much more clear to "newbie" developers. + +## I want to contribute an implementation of TConfiguration and I am not sure whether to pick class or struct? + +Short answer: Pick whatever is more efficient in the language of your choice. + +Technically, remember that the instance is passed down the stack and should therefore be cheap on copying. To ensure this and to make sure all pieces of the protocol / transport stack are really pointing to the same TConfiguration instance, we want to pass the instance **by reference** rather than by value. + +For example, in the C# language a class is a suitable choice for this, because classes are naturally reference parameters, while structs are not. + From e780855d336beb23119cc83d1ca6c3008f842541 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 4 Dec 2019 21:24:08 +0100 Subject: [PATCH 454/756] THRIFT-5044 Improve serialization support for TApplicationExceptions and custom exceptions Client: Delphi Patch: Jens Geyer This closes #1960 --- .../src/thrift/generate/t_delphi_generator.cc | 140 +++++++++++------- lib/delphi/src/Thrift.Exception.pas | 14 +- lib/delphi/src/Thrift.pas | 105 +++++++++---- 3 files changed, 174 insertions(+), 85 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc index 4a2ebdaafb5..cffe3058edf 100644 --- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc @@ -152,11 +152,13 @@ class t_delphi_generator : public t_oop_generator { void generate_delphi_struct_writer_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, - bool is_exception); + bool is_exception, + bool is_x_factory); void generate_delphi_struct_result_writer_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, - bool is_exception); + bool is_exception, + bool is_x_factory); void generate_delphi_struct_tostring_impl(ostream& out, std::string cls_prefix, @@ -169,7 +171,8 @@ class t_delphi_generator : public t_oop_generator { void generate_delphi_struct_reader_impl(ostream& out, std::string cls_prefix, t_struct* tstruct, - bool is_exception); + bool is_exception, + bool is_x_factory); void generate_delphi_create_exception_impl(ostream& out, string cls_prefix, t_struct* tstruct, @@ -1532,11 +1535,30 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out, indent_impl(out) << "begin" << endl; indent_up_impl(); indent_impl(out) << "if F" << exception_factory_name << " = nil" << endl; - indent_impl(out) << "then F" << exception_factory_name << " := T" << exception_factory_name << "Impl.Create;" << endl; - indent_impl(out) << endl; + indent_impl(out) << "then F" << exception_factory_name << " := T" << exception_factory_name << "Impl.Create;" << endl << endl; indent_impl(out) << "result := F" << exception_factory_name << ";" << endl; indent_down_impl(); indent_impl(out) << "end;" << endl << endl; + indent_impl(out) << "function " << cls_prefix << cls_nm << ".QueryInterface(const IID: TGUID; out Obj): HRESULT;" << endl; + indent_impl(out) << "begin" << endl; + indent_up_impl(); + indent_impl(out) << "if GetInterface(IID, Obj)" << endl; + indent_impl(out) << "then result := S_OK" << endl; + indent_impl(out) << "else result := E_NOINTERFACE;" << endl; + indent_down_impl(); + indent_impl(out) << "end;" << endl << endl; + indent_impl(out) << "function " << cls_prefix << cls_nm << "._AddRef: Integer;" << endl; + indent_impl(out) << "begin" << endl; + indent_up_impl(); + indent_impl(out) << "result := -1; // not refcounted" << endl; + indent_down_impl(); + indent_impl(out) << "end;" << endl << endl; + indent_impl(out) << "function " << cls_prefix << cls_nm << "._Release: Integer;" << endl; + indent_impl(out) << "begin" << endl; + indent_up_impl(); + indent_impl(out) << "result := -1; // not refcounted" << endl; + indent_down_impl(); + indent_impl(out) << "end;" << endl << endl; } if (tstruct->is_union()) { @@ -1586,13 +1608,11 @@ void t_delphi_generator::generate_delphi_struct_impl(ostream& out, } } - if ((!is_exception) || is_x_factory) { - generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, is_exception); - if (is_result) { - generate_delphi_struct_result_writer_impl(out, cls_prefix, tstruct, is_exception); - } else { - generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, is_exception); - } + generate_delphi_struct_reader_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); + if (is_result) { + generate_delphi_struct_result_writer_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); + } else { + generate_delphi_struct_writer_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); } generate_delphi_struct_tostring_impl(out, cls_prefix, tstruct, is_exception, is_x_factory); @@ -1741,7 +1761,7 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, } out << "class("; if (is_exception && (!is_x_factory)) { - out << "TException"; + out << "TException, IInterface, IBase, ISupportsToString"; } else { out << "TInterfacedObject, IBase, ISupportsToString, " << struct_intf_name; } @@ -1801,8 +1821,18 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, } } - indent_down(); + if (is_exception && (!is_x_factory)) { + out << endl; + indent_down(); + indent(out) << "strict protected" << endl; + indent_up(); + indent(out) << "function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;" << endl; + indent(out) << "function _AddRef: Integer; stdcall;" << endl; + indent(out) << "function _Release: Integer; stdcall;" << endl; + out << endl; + } + indent_down(); indent(out) << "public" << endl; indent_up(); @@ -1825,12 +1855,10 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, indent(out) << "function " << exception_factory_name << ": " << struct_intf_name << ";" << endl; } - if ((!is_exception) || is_x_factory) { - out << endl; - indent(out) << "// IBase" << endl; - indent(out) << "procedure Read( const iprot: IProtocol);" << endl; - indent(out) << "procedure Write( const oprot: IProtocol);" << endl; - } + out << endl; + indent(out) << "// IBase" << endl; + indent(out) << "procedure Read( const iprot: IProtocol);" << endl; + indent(out) << "procedure Write( const oprot: IProtocol);" << endl; if (is_exception && is_x_factory) { out << endl; @@ -2163,9 +2191,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { indent_impl(s_service_impl) << "begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << msgvar << " := iprot_.ReadMessageBegin();" << endl; - indent_impl(s_service_impl) << "if (" << msgvar << ".Type_ = TMessageType.Exception) then" - << endl; - indent_impl(s_service_impl) << "begin" << endl; + indent_impl(s_service_impl) << "if (" << msgvar << ".Type_ = TMessageType.Exception) then begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << appexvar << " := TApplicationException.Read(iprot_);" << endl; indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl; @@ -2178,8 +2204,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { indent_impl(s_service_impl) << "iprot_.ReadMessageEnd();" << endl; if (!(*f_iter)->get_returntype()->is_void()) { - indent_impl(s_service_impl) << "if (" << retvar << ".__isset_success) then" << endl; - indent_impl(s_service_impl) << "begin" << endl; + indent_impl(s_service_impl) << "if (" << retvar << ".__isset_success) then begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "Result := " << retvar << ".Success;" << endl; t_type* type = (*f_iter)->get_returntype(); @@ -2195,8 +2220,7 @@ void t_delphi_generator::generate_service_client(t_service* tservice) { vector::const_iterator x_iter; for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { indent_impl(s_service_impl) << "if (" << retvar << ".__isset_" << prop_name(*x_iter) - << ") then" << endl; - indent_impl(s_service_impl) << "begin" << endl; + << ") then begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << exceptvar << " := " << retvar << "." << prop_name(*x_iter) << ".CreateException;" << endl; @@ -2324,8 +2348,7 @@ void t_delphi_generator::generate_service_server(t_service* tservice) { indent_impl(s_service_impl) << "msg := iprot.ReadMessageBegin();" << endl; indent_impl(s_service_impl) << "fn := nil;" << endl; indent_impl(s_service_impl) << "if not processMap_.TryGetValue(msg.Name, fn)" << endl; - indent_impl(s_service_impl) << "or not Assigned(fn) then" << endl; - indent_impl(s_service_impl) << "begin" << endl; + indent_impl(s_service_impl) << "or not Assigned(fn) then begin" << endl; indent_up_impl(); indent_impl(s_service_impl) << "TProtocolUtil.Skip(iprot, TType.Struct);" << endl; indent_impl(s_service_impl) << "iprot.ReadMessageEnd();" << endl; @@ -2716,8 +2739,7 @@ void t_delphi_generator::generate_deserialize_container(ostream& out, indent_impl(out) << obj << " := iprot.ReadListBegin();" << endl; } - indent_impl(out) << "for " << counter << " := 0 to " << obj << ".Count - 1 do" << endl; - indent_impl(out) << "begin" << endl; + indent_impl(out) << "for " << counter << " := 0 to " << obj << ".Count - 1 do begin" << endl; indent_up_impl(); if (ttype->is_map()) { generate_deserialize_map_element(out, is_xception, (t_map*)ttype, name, local_vars); @@ -2904,20 +2926,17 @@ void t_delphi_generator::generate_serialize_container(ostream& out, string iter = tmp("_iter"); if (ttype->is_map()) { local_vars << " " << iter << ": " << type_name(((t_map*)ttype)->get_key_type()) << ";" << endl; - indent_impl(out) << "for " << iter << " in " << prefix << ".Keys do" << endl; - indent_impl(out) << "begin" << endl; + indent_impl(out) << "for " << iter << " in " << prefix << ".Keys do begin" << endl; indent_up_impl(); } else if (ttype->is_set()) { local_vars << " " << iter << ": " << type_name(((t_set*)ttype)->get_elem_type()) << ";" << endl; - indent_impl(out) << "for " << iter << " in " << prefix << " do" << endl; - indent_impl(out) << "begin" << endl; + indent_impl(out) << "for " << iter << " in " << prefix << " do begin" << endl; indent_up_impl(); } else if (ttype->is_list()) { local_vars << " " << iter << ": " << type_name(((t_list*)ttype)->get_elem_type()) << ";" << endl; - indent_impl(out) << "for " << iter << " in " << prefix << " do" << endl; - indent_impl(out) << "begin" << endl; + indent_impl(out) << "for " << iter << " in " << prefix << " do begin" << endl; indent_up_impl(); } @@ -3575,7 +3594,8 @@ void t_delphi_generator::generate_delphi_create_exception_impl(ostream& out, void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, string cls_prefix, t_struct* tstruct, - bool is_exception) { + bool is_exception, + bool is_x_factory) { ostringstream local_vars; ostringstream code_block; @@ -3604,32 +3624,28 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, indent_impl(code_block) << "try" << endl; indent_up_impl(); - indent_impl(code_block) << "while (true) do" << endl; - indent_impl(code_block) << "begin" << endl; + indent_impl(code_block) << "while (true) do begin" << endl; indent_up_impl(); indent_impl(code_block) << "field_ := iprot.ReadFieldBegin();" << endl; - indent_impl(code_block) << "if (field_.Type_ = TType.Stop) then" << endl; - indent_impl(code_block) << "begin" << endl; - indent_up_impl(); - indent_impl(code_block) << "Break;" << endl; - indent_down_impl(); - indent_impl(code_block) << "end;" << endl; + indent_impl(code_block) << "if (field_.Type_ = TType.Stop) then Break;" << endl; bool first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if (first) { + code_block << endl; indent_impl(code_block) << "case field_.ID of" << endl; indent_up_impl(); } first = false; if (f_iter != fields.begin()) { - code_block << ";" << endl; + code_block << endl; } + indent_impl(code_block) << (*f_iter)->get_key() << ": begin" << endl; indent_up_impl(); indent_impl(code_block) << "if (field_.Type_ = " << type_to_enum((*f_iter)->get_type()) @@ -3652,12 +3668,13 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, indent_down_impl(); indent_impl(code_block) << "end;" << endl; indent_down_impl(); - indent_impl(code_block) << "end"; + indent_impl(code_block) << "end;"; } if (!first) { code_block << endl; - indent_impl(code_block) << "else begin" << endl; + indent_down_impl(); + indent_impl(code_block) << "else" << endl; indent_up_impl(); } @@ -3666,8 +3683,6 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, if (!first) { indent_down_impl(); indent_impl(code_block) << "end;" << endl; - indent_down_impl(); - indent_impl(code_block) << "end;" << endl; } indent_impl(code_block) << "iprot.ReadFieldEnd;" << endl; @@ -3684,8 +3699,13 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, indent_impl(code_block) << "end;" << endl; // all required fields have been read? + first = true; for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { if ((*f_iter)->get_req() == t_field::T_REQUIRED) { + if(first) { + code_block << endl; + first = false; + } indent_impl(code_block) << "if not _req_isset_" << prop_name(*f_iter, is_exception) << endl; indent_impl(code_block) << "then raise TProtocolExceptionInvalidData.Create(" @@ -3693,13 +3713,17 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, << endl; } } - + + if( is_exception && (!is_x_factory)) { + code_block << endl; + indent_impl(code_block) << "UpdateMessageProperty;" << endl; + } indent_down_impl(); indent_impl(code_block) << "end;" << endl << endl; string cls_nm; - cls_nm = type_name(tstruct, true, false, is_exception, is_exception); + cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory); indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Read( const iprot: IProtocol);" << endl; @@ -3715,7 +3739,8 @@ void t_delphi_generator::generate_delphi_struct_reader_impl(ostream& out, void t_delphi_generator::generate_delphi_struct_result_writer_impl(ostream& out, string cls_prefix, t_struct* tstruct, - bool is_exception) { + bool is_exception, + bool is_x_factory) { ostringstream local_vars; ostringstream code_block; @@ -3759,7 +3784,7 @@ void t_delphi_generator::generate_delphi_struct_result_writer_impl(ostream& out, string cls_nm; - cls_nm = type_name(tstruct, true, false, is_exception, is_exception); + cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory); indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);" << endl; @@ -3779,7 +3804,8 @@ void t_delphi_generator::generate_delphi_struct_result_writer_impl(ostream& out, void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out, string cls_prefix, t_struct* tstruct, - bool is_exception) { + bool is_exception, + bool is_x_factory) { ostringstream local_vars; ostringstream code_block; @@ -3847,7 +3873,7 @@ void t_delphi_generator::generate_delphi_struct_writer_impl(ostream& out, string cls_nm; - cls_nm = type_name(tstruct, true, false, is_exception, is_exception); + cls_nm = type_name(tstruct, true, is_exception && (!is_x_factory), is_x_factory, is_x_factory); indent_impl(out) << "procedure " << cls_prefix << cls_nm << ".Write( const oprot: IProtocol);" << endl; diff --git a/lib/delphi/src/Thrift.Exception.pas b/lib/delphi/src/Thrift.Exception.pas index 5d15c365690..88b1cfe03e7 100644 --- a/lib/delphi/src/Thrift.Exception.pas +++ b/lib/delphi/src/Thrift.Exception.pas @@ -29,6 +29,8 @@ interface type // base class for all Thrift exceptions TException = class( SysUtils.Exception) + strict private + function GetMessageText : string; public function Message : string; // hide inherited property: allow read, but prevent accidental writes procedure UpdateMessageProperty; // update inherited message property with toString() @@ -45,17 +47,25 @@ function TException.Message; // allow read (exception summary), but prevent accidental writes // read will return the exception summary begin - result := Self.ToString; + result := Self.GetMessageText; end; + procedure TException.UpdateMessageProperty; // Update the inherited Message property to better conform to standard behaviour. // Nice benefit: The IDE is now able to show the exception message again. begin - inherited Message := Self.ToString; // produces a summary text + inherited Message := Self.GetMessageText; end; +function TException.GetMessageText : string; +// produces a summary text +begin + result := Self.ToString; + if (result <> '') and (result[1] = '(') + then result := Copy(result,2,Length(result)-2); +end; end. diff --git a/lib/delphi/src/Thrift.pas b/lib/delphi/src/Thrift.pas index 716e4d22c02..1926b11ef32 100644 --- a/lib/delphi/src/Thrift.pas +++ b/lib/delphi/src/Thrift.pas @@ -23,6 +23,7 @@ interface uses SysUtils, + Thrift.Utils, Thrift.Exception, Thrift.Protocol; @@ -34,7 +35,7 @@ interface TApplicationExceptionSpecializedClass = class of TApplicationExceptionSpecialized; - TApplicationException = class abstract( TException) + TApplicationException = class( TException, IBase, ISupportsToString) public type {$SCOPEDENUMS ON} @@ -52,10 +53,18 @@ TApplicationException = class abstract( TException) UnsupportedClientType ); {$SCOPEDENUMS OFF} + strict private + FExceptionType : TExceptionType; + + strict protected + function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall; + function _AddRef: Integer; stdcall; + function _Release: Integer; stdcall; + strict protected constructor HiddenCreate(const Msg: string); - class function GetType: TExceptionType; virtual; abstract; class function GetSpecializedExceptionType(AType: TExceptionType): TApplicationExceptionSpecializedClass; + public // purposefully hide inherited constructor class function Create(const Msg: string): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)'; @@ -63,7 +72,10 @@ TApplicationException = class abstract( TException) class function Create( AType: TExceptionType): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)'; class function Create( AType: TExceptionType; const msg: string): TApplicationException; overload; deprecated 'Use specialized TApplicationException types (or regenerate from IDL)'; - property Type_: TExceptionType read GetType; + function Type_: TExceptionType; virtual; + + procedure IBase_Read( const iprot: IProtocol); + procedure IBase.Read = IBase_Read; class function Read( const iprot: IProtocol): TApplicationException; procedure Write( const oprot: IProtocol ); @@ -71,8 +83,11 @@ TApplicationException = class abstract( TException) // Needed to remove deprecation warning TApplicationExceptionSpecialized = class abstract (TApplicationException) + strict protected + class function GetType: TApplicationException.TExceptionType; virtual; abstract; public constructor Create(const Msg: string); + function Type_: TApplicationException.TExceptionType; override; end; TApplicationExceptionUnknown = class (TApplicationExceptionSpecialized) @@ -163,6 +178,31 @@ class function TApplicationException.Create( AType: TExceptionType; const msg: s Result := GetSpecializedExceptionType(AType).Create(msg); end; + +function TApplicationException.QueryInterface(const IID: TGUID; out Obj): HResult; +begin + if GetInterface(IID, Obj) + then result := S_OK + else result := E_NOINTERFACE; +end; + +function TApplicationException._AddRef: Integer; +begin + result := -1; // not refcounted +end; + +function TApplicationException._Release: Integer; +begin + result := -1; // not refcounted +end; + + +function TApplicationException.Type_: TExceptionType; +begin + result := FExceptionType; +end; + + class function TApplicationException.GetSpecializedExceptionType(AType: TExceptionType): TApplicationExceptionSpecializedClass; begin case AType of @@ -183,52 +223,60 @@ class function TApplicationException.GetSpecializedExceptionType(AType: TExcepti end; -class function TApplicationException.Read( const iprot: IProtocol): TApplicationException; +procedure TApplicationException.IBase_Read( const iprot: IProtocol); var field : TThriftField; - msg : string; - typ : TExceptionType; struc : TThriftStruct; begin - msg := ''; - typ := TExceptionType.Unknown; struc := iprot.ReadStructBegin; while ( True ) do begin field := iprot.ReadFieldBegin; - if ( field.Type_ = TType.Stop) then - begin + if ( field.Type_ = TType.Stop) then begin Break; end; case field.Id of 1 : begin - if ( field.Type_ = TType.String_) then - begin - msg := iprot.ReadString; - end else - begin + if ( field.Type_ = TType.String_) then begin + Exception(Self).Message := iprot.ReadString; + end else begin TProtocolUtil.Skip( iprot, field.Type_ ); end; end; 2 : begin - if ( field.Type_ = TType.I32) then - begin - typ := TExceptionType( iprot.ReadI32 ); - end else - begin + if ( field.Type_ = TType.I32) then begin + FExceptionType := TExceptionType( iprot.ReadI32 ); + end else begin TProtocolUtil.Skip( iprot, field.Type_ ); end; - end else - begin + end else begin TProtocolUtil.Skip( iprot, field.Type_); end; end; iprot.ReadFieldEnd; end; iprot.ReadStructEnd; - Result := GetSpecializedExceptionType(typ).Create(msg); +end; + + +class function TApplicationException.Read( const iprot: IProtocol): TApplicationException; +var instance : TApplicationException; + base : IBase; +begin + instance := TApplicationException.CreateFmt('',[]); + try + if Supports( instance, IBase, base) then try + base.Read(iprot); + finally + base := nil; // clear ref before free + end; + + result := GetSpecializedExceptionType(instance.Type_).Create( Exception(instance).Message); + finally + instance.Free; + end; end; procedure TApplicationException.Write( const oprot: IProtocol); @@ -240,8 +288,7 @@ procedure TApplicationException.Write( const oprot: IProtocol); Init(field); oprot.WriteStructBegin( struc ); - if Message <> '' then - begin + if Message <> '' then begin field.Name := 'message'; field.Type_ := TType.String_; field.Id := 1; @@ -254,7 +301,7 @@ procedure TApplicationException.Write( const oprot: IProtocol); field.Type_ := TType.I32; field.Id := 2; oprot.WriteFieldBegin(field); - oprot.WriteI32(Integer(GetType)); + oprot.WriteI32(Integer(Type_)); oprot.WriteFieldEnd(); oprot.WriteFieldStop(); oprot.WriteStructEnd(); @@ -267,6 +314,12 @@ constructor TApplicationExceptionSpecialized.Create(const Msg: string); inherited HiddenCreate(Msg); end; +function TApplicationExceptionSpecialized.Type_: TApplicationException.TExceptionType; +begin + result := GetType; +end; + + { specialized TApplicationExceptions } class function TApplicationExceptionUnknownMethod.GetType : TApplicationException.TExceptionType; From ffb97e105cbef6afc809a1bdac9cdac1f35d6bab Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 6 Dec 2019 23:43:08 +0100 Subject: [PATCH 455/756] THRIFT-4990 Upgrade to .NET Core 3.1 (LTS) Client: netstd Patch: Jens Geyer This closes #1961 --- CHANGES.md | 2 +- build/docker/README.md | 2 +- build/docker/ubuntu-bionic/Dockerfile | 2 +- build/docker/ubuntu-disco/Dockerfile | 2 +- build/docker/ubuntu-xenial/Dockerfile | 2 +- configure.ac | 2 +- lib/netstd/README.md | 2 +- .../Thrift.IntegrationTests.csproj | 12 ++++---- ...rift.PublicInterfaces.Compile.Tests.csproj | 4 +-- .../Tests/Thrift.Tests/Thrift.Tests.csproj | 12 ++++---- lib/netstd/Thrift/Thrift.csproj | 10 +++---- test/netstd/Client/Client.csproj | 6 ++-- test/netstd/Client/Program.cs | 1 + test/netstd/README.md | 2 +- test/netstd/Server/Server.csproj | 8 ++--- test/netstd/Server/TestServer.cs | 28 ++++++++--------- test/netstd/ThriftTest.sln | 4 +-- tutorial/netstd/Client/Client.csproj | 4 +-- tutorial/netstd/Interfaces/Interfaces.csproj | 2 +- tutorial/netstd/README.md | 30 ++++++++----------- tutorial/netstd/Server/Server.csproj | 4 +-- 21 files changed, 69 insertions(+), 72 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 30622e5fb2e..e179a6375fa 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,7 +4,7 @@ ### Breaking Changes -- [THRIFT-4990](https://issues.apache.org/jira/browse/THRIFT-4990) - Upgrade to .NET Core 3.0 +- [THRIFT-4990](https://issues.apache.org/jira/browse/THRIFT-4990) - Upgrade to .NET Core 3.1 (LTS) - [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base - [THRIFT-5006](https://issues.apache.org/jira/browse/THRIFT-5006) - Implement DEFAULT_MAX_LENGTH at TFramedTransport diff --git a/build/docker/README.md b/build/docker/README.md index e33c4e0a4ad..8c8be22bbf3 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -177,7 +177,6 @@ Last updated: October 1, 2017 | d | 2.075.1 | 2.087.0 | | | dart | 2.0.0 | 2.4.0 | | | delphi | | | Not in CI | -| dotnet | 3.0 | 3.0 | | | erlang | 18.3 | 22.0 | | | go | 1.10.8 | 1.12.6 | | | haskell | 7.10.3 | 8.0.2 | | @@ -185,6 +184,7 @@ Last updated: October 1, 2017 | java | 1.8.0_191 | 11.0.3 | | | js | | | Unsure how to look for version info? | | lua | | 5.2.4 | Lua 5.3: see THRIFT-4386 | +| netstd | 3.1 | 3.1 | LTS version | | nodejs | 6.16.0 | 10.16.0 | | | ocaml | | 4.05.0 | THRIFT-4517: ocaml 4.02.3 on xenial appears broken | | perl | 5.22.1 | 5.26.1 | | diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index d38901f3ff9..79d698f2743 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -130,7 +130,7 @@ ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ - dotnet-sdk-3.0 + dotnet-sdk-3.1 RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ diff --git a/build/docker/ubuntu-disco/Dockerfile b/build/docker/ubuntu-disco/Dockerfile index b63fd58fe96..95a2c780b73 100644 --- a/build/docker/ubuntu-disco/Dockerfile +++ b/build/docker/ubuntu-disco/Dockerfile @@ -130,7 +130,7 @@ ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ - dotnet-sdk-3.0 + dotnet-sdk-3.1 RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index 714a80dba46..8df08873916 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -127,7 +127,7 @@ ENV PATH /usr/lib/dart/bin:$PATH RUN apt-get install -y --no-install-recommends \ `# dotnet core dependencies` \ - dotnet-sdk-3.0 + dotnet-sdk-3.1 RUN apt-get install -y --no-install-recommends \ `# Erlang dependencies` \ diff --git a/configure.ac b/configure.ac index f11ab1352e6..64283a8efaf 100755 --- a/configure.ac +++ b/configure.ac @@ -505,7 +505,7 @@ AX_THRIFT_LIB(netstd, [.NET Core], yes) if test "$with_netstd" = "yes"; then AC_PATH_PROG([DOTNETCORE], [dotnet]) if [[ -x "$DOTNETCORE" ]] ; then - AX_PROG_DOTNETCORE_VERSION( [3.0.0], have_netstd="yes", have_netstd="no") + AX_PROG_DOTNETCORE_VERSION( [3.1.0], have_netstd="yes", have_netstd="no") fi fi AM_CONDITIONAL(WITH_DOTNET, [test "$have_netstd" = "yes"]) diff --git a/lib/netstd/README.md b/lib/netstd/README.md index 74f5ed86d72..d554e38543b 100644 --- a/lib/netstd/README.md +++ b/lib/netstd/README.md @@ -11,7 +11,7 @@ or - Build with scripts ## How to build on Unix/Linux -- Ensure you have .NET Core SDK 3.0 installed, or use the [Ubuntu docker image](../../build/docker/README.md) +- Ensure you have .NET Core SDK 3.1 (LTS) installed, or use the [Ubuntu docker image](../../build/docker/README.md) - Follow common automake build practice: `./ bootstrap && ./ configure && make` ## Known issues diff --git a/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj b/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj index c3cdc111319..7c5639bc7f7 100644 --- a/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj +++ b/lib/netstd/Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj @@ -19,7 +19,7 @@ --> - netcoreapp3.0 + netcoreapp3.1 Thrift.IntegrationTests Thrift.IntegrationTests Exe @@ -32,11 +32,11 @@ - - - - - + + + + + diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj index 498191f60af..d2db348d873 100644 --- a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj @@ -19,7 +19,7 @@ --> - netcoreapp3.0 + netcoreapp3.1 Thrift.PublicInterfaces.Compile.Tests Thrift.PublicInterfaces.Compile.Tests false @@ -33,7 +33,7 @@ - + diff --git a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj index b0601825c9f..20fdfe492f9 100644 --- a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj +++ b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj @@ -18,14 +18,14 @@ under the License. --> - netcoreapp3.0 + netcoreapp3.1 - - - - - + + + + + diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj index 5d8a9c3c966..e40db00d2a0 100644 --- a/lib/netstd/Thrift/Thrift.csproj +++ b/lib/netstd/Thrift/Thrift.csproj @@ -44,16 +44,16 @@ - - - + + + - + - + diff --git a/test/netstd/Client/Client.csproj b/test/netstd/Client/Client.csproj index c406f17c35d..4ed57cbd947 100644 --- a/test/netstd/Client/Client.csproj +++ b/test/netstd/Client/Client.csproj @@ -19,7 +19,7 @@ --> - netcoreapp3.0 + netcoreapp3.1 Client Client Exe @@ -31,9 +31,9 @@ false - + - + diff --git a/test/netstd/Client/Program.cs b/test/netstd/Client/Program.cs index 47dabd3c903..92000da5625 100644 --- a/test/netstd/Client/Program.cs +++ b/test/netstd/Client/Program.cs @@ -42,6 +42,7 @@ public static int Main(string[] args) Console.WriteLine("The 'client' argument is no longer required."); PrintHelp(); return -1; + case "--performance": case "--performance-test": return Tests.PerformanceTests.Execute(); case "--help": diff --git a/test/netstd/README.md b/test/netstd/README.md index 8350728e57f..4ece0598438 100644 --- a/test/netstd/README.md +++ b/test/netstd/README.md @@ -6,7 +6,7 @@ Tests for Thrift client library ported to Microsoft .NET Core - ThriftTest - tests for Thrift library # Reused components -- NET Core SDK 3.0 +- NET Core SDK 3.1 (LTS) # How to build on Windows - Get Thrift IDL compiler executable, add to some folder and add path to this folder into PATH variable diff --git a/test/netstd/Server/Server.csproj b/test/netstd/Server/Server.csproj index 5d33aa09dc4..fa5ce46155a 100644 --- a/test/netstd/Server/Server.csproj +++ b/test/netstd/Server/Server.csproj @@ -19,7 +19,7 @@ --> - netcoreapp3.0 + netcoreapp3.1 Server Server Exe @@ -33,9 +33,9 @@ - + - + @@ -47,6 +47,6 @@ - + diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs index 493d89deede..68461dc9c05 100644 --- a/test/netstd/Server/TestServer.cs +++ b/test/netstd/Server/TestServer.cs @@ -254,20 +254,20 @@ public Task testBinaryAsync(byte[] thing, CancellationToken cancellation public Task testStructAsync(Xtruct thing, CancellationToken cancellationToken) { - logger.Invoke("testStruct({{\"{0}\", {1}, {2}, {3}}})", thing.StringThing, thing.ByteThing, thing.I32Thing, thing.I64Thing); + logger.Invoke("testStruct({{\"{0}\", {1}, {2}, {3}}})", thing.String_thing, thing.Byte_thing, thing.I32_thing, thing.I64_thing); return Task.FromResult(thing); } public Task testNestAsync(Xtruct2 nest, CancellationToken cancellationToken) { - var thing = nest.StructThing; + var thing = nest.Struct_thing; logger.Invoke("testNest({{{0}, {{\"{1}\", {2}, {3}, {4}, {5}}}}})", - nest.ByteThing, - thing.StringThing, - thing.ByteThing, - thing.I32Thing, - thing.I64Thing, - nest.I32Thing); + nest.Byte_thing, + thing.String_thing, + thing.Byte_thing, + thing.I32_thing, + thing.I64_thing, + nest.I32_thing); return Task.FromResult(nest); } @@ -429,10 +429,10 @@ public Task testMultiAsync(sbyte arg0, int arg1, long arg2, Dictionary testMultiExceptionAsync(string arg0, string arg1, Cancellati var x = new Xception2 { ErrorCode = 2002, - StructThing = new Xtruct { StringThing = "This is an Xception2" } + Struct_thing = new Xtruct { String_thing = "This is an Xception2" } }; throw x; } - var result = new Xtruct { StringThing = arg1 }; + var result = new Xtruct { String_thing = arg1 }; return Task.FromResult(result); } diff --git a/test/netstd/ThriftTest.sln b/test/netstd/ThriftTest.sln index 6bd08555b7a..352576ef0e1 100644 --- a/test/netstd/ThriftTest.sln +++ b/test/netstd/ThriftTest.sln @@ -4,9 +4,9 @@ VisualStudioVersion = 15.0.26730.12 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift", "..\..\lib\netstd\Thrift\Thrift.csproj", "{C20EA2A9-7660-47DE-9A49-D1EF12FB2895}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client", "Client\Client.csproj", "{21039F25-6ED7-4E80-A545-EBC93472EBD1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client", "Client\Client.csproj", "{21039F25-6ED7-4E80-A545-EBC93472EBD1}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{0C6E8685-F191-4479-9842-882A38961127}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{0C6E8685-F191-4479-9842-882A38961127}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/tutorial/netstd/Client/Client.csproj b/tutorial/netstd/Client/Client.csproj index 2abf53cd8ed..10d5040f0a2 100644 --- a/tutorial/netstd/Client/Client.csproj +++ b/tutorial/netstd/Client/Client.csproj @@ -19,7 +19,7 @@ --> - netcoreapp3.0 + netcoreapp3.1 Client Client Exe @@ -30,7 +30,7 @@ - + diff --git a/tutorial/netstd/Interfaces/Interfaces.csproj b/tutorial/netstd/Interfaces/Interfaces.csproj index 4ebeb4f4297..c8b2bd81187 100644 --- a/tutorial/netstd/Interfaces/Interfaces.csproj +++ b/tutorial/netstd/Interfaces/Interfaces.csproj @@ -33,7 +33,7 @@ - + diff --git a/tutorial/netstd/README.md b/tutorial/netstd/README.md index 11fd5411ad2..297f4ee326d 100644 --- a/tutorial/netstd/README.md +++ b/tutorial/netstd/README.md @@ -1,8 +1,7 @@ # Building of samples for different platforms -# Reused components -- NET Core Standard 3.0 -- NET Core App 3.0 +# Requirements +- NET Core Standard 3.1 (LTS) runtime or SDK (see below for further info) # How to build - Download and install the latest .NET Core SDK for your platform https://dotnet.microsoft.com/download/dotnet-core @@ -14,29 +13,26 @@ # How to run -Notes: dotnet run supports passing arguments to app after -- symbols (https://docs.microsoft.com/en-us/dotnet/articles/core/tools/dotnet-run) - example: **dotnet run -- -h** will show help for app +Depending on the platform, the name of the generated executables will vary. On Linux, it is just "client" or "server", on Windows it is "Client.exe" and "Server.exe". In the following, we use the abbreviated form "Client" and "Server". - build - go to folder (Client/Server) -- run with specifying of correct parameters **dotnet run -tr:tcp -pr:multiplexed**, **dotnet run -help** (later, after migration to csproj and latest SDK will be possibility to use more usable form **dotnet run -- arguments**) - -#Notes -- Possible adding additional platforms after stabilization of .NET Core (runtimes, platforms (Red Hat Linux, OpenSuse, etc.) +- run the generated executables: server first, then client from a second console #Known issues - In trace logging mode you can see some not important internal exceptions # Running of samples -Please install Thrift C# .NET Core library or copy sources and build them to correcly build and run samples +On machines that do not have the SDK installed, you need to install the NET Core runtime first. The SDK is only needed to build programs, otherwise the runtime is sufficient. # NetCore Server Usage: - Server.exe -h + Server -h will diplay help information - Server.exe -tr: -pr: + Server -tr: -pr: will run server with specified arguments (tcp transport and binary protocol by default) Options: @@ -59,7 +55,7 @@ Options: Sample: - Server.exe -tr:tcp + Server -tr:tcp **Remarks**: @@ -72,10 +68,10 @@ Sample: Usage: - Client.exe -h + Client -h will diplay help information - Client.exe -tr: -pr: -mc: + Client -tr: -pr: -mc: will run client with specified arguments (tcp transport and binary protocol by default) Options: @@ -101,7 +97,7 @@ Options: Sample: - Client.exe -tr:tcp -pr:binary -mc:10 + Client -tr:tcp -pr:binary -mc:10 Remarks: @@ -111,8 +107,8 @@ Remarks: # How to test communication between NetCore and Python -* Generate code with the latest **thrift.exe** util -* Ensure that **thrift.exe** util generated folder **gen-py** with generated code for Python +* Generate code with the latest **thrift** utility +* Ensure that **thrift** generated folder **gen-py** with generated code for Python exists * Create **client.py** and **server.py** from the code examples below and save them to the folder with previosly generated folder **gen-py** * Run netstd samples (client and server) and python samples (client and server) diff --git a/tutorial/netstd/Server/Server.csproj b/tutorial/netstd/Server/Server.csproj index 454f332d599..b3ff516e3ab 100644 --- a/tutorial/netstd/Server/Server.csproj +++ b/tutorial/netstd/Server/Server.csproj @@ -19,7 +19,7 @@ --> - netcoreapp3.0 + netcoreapp3.1 Server Server Exe @@ -38,7 +38,7 @@ - + From 45a9827f0f455d377ae87d9a35349c10181d6893 Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Thu, 7 Mar 2019 12:18:59 -0500 Subject: [PATCH 456/756] Remove unnecessary TException.message hack Thrift attempts to work-around the Python 2.7 DeprecationWarning around `BaseException.message` by using a property. This hack is unnecessary since `message` is _also_ written as a regular attribute in the `TException` constructor (and would be in any of its children), hence the `BaseException_get_message()` wouldn't even be called. This hack also stands in the way of making exception instances immutable (which is a prerequisute to fixing THRIFT-4002). --- lib/py/src/Thrift.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/py/src/Thrift.py b/lib/py/src/Thrift.py index c390cbb54c1..b335bc11b70 100644 --- a/lib/py/src/Thrift.py +++ b/lib/py/src/Thrift.py @@ -90,15 +90,6 @@ def on_message_begin(self, func): class TException(Exception): """Base class for all thrift exceptions.""" - # BaseException.message is deprecated in Python v[2.6,3.0) - if (2, 6, 0) <= sys.version_info < (3, 0): - def _get_message(self): - return self._message - - def _set_message(self, message): - self._message = message - message = property(_get_message, _set_message) - def __init__(self, message=None): Exception.__init__(self, message) self.message = message From b40f5c227f8db61be523f23ca017519167589d97 Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Thu, 7 Mar 2019 11:00:34 -0500 Subject: [PATCH 457/756] THRIFT-4002: Make generated exception classes immutable by default Currently, the generated exception classes are not hashable under Python 3 because of the generated `__eq__` method. Exception objects are generally expected to be hashable by the Python standard library. Post-construction mutation of an exception object seems like a very unlikely case, so enable hashing for all exceptions by making them immutable by default. This also adds a way to opt-out of immutability by setting the `python.immutable` annotation to `"false"`. --- .../cpp/src/thrift/generate/t_py_generator.cc | 27 ++++++++++++++++--- lib/py/src/protocol/TBase.py | 4 +++ lib/py/src/protocol/TProtocol.py | 10 +++++-- test/DebugProtoTest.thrift | 4 +++ test/py/TestFrozen.py | 17 ++++++++++++ 5 files changed, 57 insertions(+), 5 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_py_generator.cc b/compiler/cpp/src/thrift/generate/t_py_generator.cc index 982bca14547..e93bbe17dcc 100644 --- a/compiler/cpp/src/thrift/generate/t_py_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_py_generator.cc @@ -65,6 +65,7 @@ class t_py_generator : public t_generator { coding_ = ""; gen_dynbaseclass_ = ""; gen_dynbaseclass_exc_ = ""; + gen_dynbaseclass_frozen_exc_ = ""; gen_dynbaseclass_frozen_ = ""; import_dynbase_ = ""; package_prefix_ = ""; @@ -94,8 +95,11 @@ class t_py_generator : public t_generator { if( gen_dynbaseclass_exc_.empty()) { gen_dynbaseclass_exc_ = "TExceptionBase"; } + if( gen_dynbaseclass_frozen_exc_.empty()) { + gen_dynbaseclass_frozen_exc_ = "TFrozenExceptionBase"; + } if( import_dynbase_.empty()) { - import_dynbase_ = "from thrift.protocol.TBase import TBase, TFrozenBase, TExceptionBase, TTransport\n"; + import_dynbase_ = "from thrift.protocol.TBase import TBase, TFrozenBase, TExceptionBase, TFrozenExceptionBase, TTransport\n"; } } else if( iter->first.compare("dynbase") == 0) { gen_dynbase_ = true; @@ -104,6 +108,8 @@ class t_py_generator : public t_generator { gen_dynbaseclass_frozen_ = (iter->second); } else if( iter->first.compare("dynexc") == 0) { gen_dynbaseclass_exc_ = (iter->second); + } else if( iter->first.compare("dynfrozenexc") == 0) { + gen_dynbaseclass_frozen_exc_ = (iter->second); } else if( iter->first.compare("dynimport") == 0) { gen_dynbase_ = true; import_dynbase_ = (iter->second); @@ -269,7 +275,16 @@ class t_py_generator : public t_generator { } static bool is_immutable(t_type* ttype) { - return ttype->annotations_.find("python.immutable") != ttype->annotations_.end(); + std::map::iterator it = ttype->annotations_.find("python.immutable"); + + if (it == ttype->annotations_.end()) { + // Exceptions are immutable by default. + return ttype->is_xception(); + } else if (it->second == "false") { + return false; + } else { + return true; + } } private: @@ -288,6 +303,7 @@ class t_py_generator : public t_generator { std::string gen_dynbaseclass_; std::string gen_dynbaseclass_frozen_; std::string gen_dynbaseclass_exc_; + std::string gen_dynbaseclass_frozen_exc_; std::string import_dynbase_; @@ -742,7 +758,11 @@ void t_py_generator::generate_py_struct_definition(ostream& out, out << endl << endl << "class " << tstruct->get_name(); if (is_exception) { if (gen_dynamic_) { - out << "(" << gen_dynbaseclass_exc_ << ")"; + if (is_immutable(tstruct)) { + out << "(" << gen_dynbaseclass_frozen_exc_ << ")"; + } else { + out << "(" << gen_dynbaseclass_exc_ << ")"; + } } else { out << "(TException)"; } @@ -2774,6 +2794,7 @@ THRIFT_REGISTER_GENERATOR( " dynbase=CLS Derive generated classes from class CLS instead of TBase.\n" " dynfrozen=CLS Derive generated immutable classes from class CLS instead of TFrozenBase.\n" " dynexc=CLS Derive generated exceptions from CLS instead of TExceptionBase.\n" + " dynfrozenexc=CLS Derive generated immutable exceptions from CLS instead of TFrozenExceptionBase.\n" " dynimport='from foo.bar import CLS'\n" " Add an import line to generated code to find the dynbase class.\n" " package_prefix='top.package.'\n" diff --git a/lib/py/src/protocol/TBase.py b/lib/py/src/protocol/TBase.py index 9ae1b118272..6c6ef18e877 100644 --- a/lib/py/src/protocol/TBase.py +++ b/lib/py/src/protocol/TBase.py @@ -80,3 +80,7 @@ def read(cls, iprot): [self.__class__, self.thrift_spec]) else: return iprot.readStruct(cls, cls.thrift_spec, True) + + +class TFrozenExceptionBase(TFrozenBase, TExceptionBase): + pass diff --git a/lib/py/src/protocol/TProtocol.py b/lib/py/src/protocol/TProtocol.py index 3456e8f0e85..339a2839d71 100644 --- a/lib/py/src/protocol/TProtocol.py +++ b/lib/py/src/protocol/TProtocol.py @@ -303,8 +303,14 @@ def readContainerSet(self, spec): def readContainerStruct(self, spec): (obj_class, obj_spec) = spec - obj = obj_class() - obj.read(self) + + # If obj_class.read is a classmethod (e.g. in frozen structs), + # call it as such. + if getattr(obj_class.read, '__self__', None) is obj_class: + obj = obj_class.read(self) + else: + obj = obj_class() + obj.read(self) return obj def readContainerMap(self, spec): diff --git a/test/DebugProtoTest.thrift b/test/DebugProtoTest.thrift index de47ea71760..1ab0f6aea0a 100644 --- a/test/DebugProtoTest.thrift +++ b/test/DebugProtoTest.thrift @@ -241,6 +241,10 @@ exception ExceptionWithAMap { 2: map map_field; } +exception MutableException { + 1: string msg; +} (python.immutable = "false") + service ServiceForExceptionWithAMap { void methodThatThrowsAnException() throws (1: ExceptionWithAMap xwamap); } diff --git a/test/py/TestFrozen.py b/test/py/TestFrozen.py index 6d2595cf29b..ce7425f88fb 100755 --- a/test/py/TestFrozen.py +++ b/test/py/TestFrozen.py @@ -19,7 +19,9 @@ # under the License. # +from DebugProtoTest import Srv from DebugProtoTest.ttypes import CompactProtoTestStruct, Empty, Wrapper +from DebugProtoTest.ttypes import ExceptionWithAMap, MutableException from thrift.Thrift import TFrozenDict from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol, TCompactProtocol @@ -94,6 +96,21 @@ def test_struct(self): x2 = self._roundtrip(x, Wrapper) self.assertEqual(x2.foo, Empty()) + def test_frozen_exception(self): + exc = ExceptionWithAMap(blah='foo') + with self.assertRaises(TypeError): + exc.blah = 'bar' + mutexc = MutableException(msg='foo') + mutexc.msg = 'bar' + self.assertEqual(mutexc.msg, 'bar') + + def test_frozen_exception_serialization(self): + result = Srv.declaredExceptionMethod_result( + xwamap=ExceptionWithAMap(blah="error")) + deserialized = self._roundtrip( + result, Srv.declaredExceptionMethod_result()) + self.assertEqual(result, deserialized) + class TestFrozen(TestFrozenBase): def protocol(self, trans): From 1234ddf8a5c98d5d700c82e087f04725170ad581 Mon Sep 17 00:00:00 2001 From: "D. Can Celasun" Date: Tue, 10 Dec 2019 22:13:06 +0000 Subject: [PATCH 458/756] Revert "THRIFT-4002: Make generated exception classes immutable by default" This reverts commit b40f5c227f8db61be523f23ca017519167589d97. --- .../cpp/src/thrift/generate/t_py_generator.cc | 27 +++---------------- lib/py/src/protocol/TBase.py | 4 --- lib/py/src/protocol/TProtocol.py | 10 ++----- test/DebugProtoTest.thrift | 4 --- test/py/TestFrozen.py | 17 ------------ 5 files changed, 5 insertions(+), 57 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_py_generator.cc b/compiler/cpp/src/thrift/generate/t_py_generator.cc index e93bbe17dcc..982bca14547 100644 --- a/compiler/cpp/src/thrift/generate/t_py_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_py_generator.cc @@ -65,7 +65,6 @@ class t_py_generator : public t_generator { coding_ = ""; gen_dynbaseclass_ = ""; gen_dynbaseclass_exc_ = ""; - gen_dynbaseclass_frozen_exc_ = ""; gen_dynbaseclass_frozen_ = ""; import_dynbase_ = ""; package_prefix_ = ""; @@ -95,11 +94,8 @@ class t_py_generator : public t_generator { if( gen_dynbaseclass_exc_.empty()) { gen_dynbaseclass_exc_ = "TExceptionBase"; } - if( gen_dynbaseclass_frozen_exc_.empty()) { - gen_dynbaseclass_frozen_exc_ = "TFrozenExceptionBase"; - } if( import_dynbase_.empty()) { - import_dynbase_ = "from thrift.protocol.TBase import TBase, TFrozenBase, TExceptionBase, TFrozenExceptionBase, TTransport\n"; + import_dynbase_ = "from thrift.protocol.TBase import TBase, TFrozenBase, TExceptionBase, TTransport\n"; } } else if( iter->first.compare("dynbase") == 0) { gen_dynbase_ = true; @@ -108,8 +104,6 @@ class t_py_generator : public t_generator { gen_dynbaseclass_frozen_ = (iter->second); } else if( iter->first.compare("dynexc") == 0) { gen_dynbaseclass_exc_ = (iter->second); - } else if( iter->first.compare("dynfrozenexc") == 0) { - gen_dynbaseclass_frozen_exc_ = (iter->second); } else if( iter->first.compare("dynimport") == 0) { gen_dynbase_ = true; import_dynbase_ = (iter->second); @@ -275,16 +269,7 @@ class t_py_generator : public t_generator { } static bool is_immutable(t_type* ttype) { - std::map::iterator it = ttype->annotations_.find("python.immutable"); - - if (it == ttype->annotations_.end()) { - // Exceptions are immutable by default. - return ttype->is_xception(); - } else if (it->second == "false") { - return false; - } else { - return true; - } + return ttype->annotations_.find("python.immutable") != ttype->annotations_.end(); } private: @@ -303,7 +288,6 @@ class t_py_generator : public t_generator { std::string gen_dynbaseclass_; std::string gen_dynbaseclass_frozen_; std::string gen_dynbaseclass_exc_; - std::string gen_dynbaseclass_frozen_exc_; std::string import_dynbase_; @@ -758,11 +742,7 @@ void t_py_generator::generate_py_struct_definition(ostream& out, out << endl << endl << "class " << tstruct->get_name(); if (is_exception) { if (gen_dynamic_) { - if (is_immutable(tstruct)) { - out << "(" << gen_dynbaseclass_frozen_exc_ << ")"; - } else { - out << "(" << gen_dynbaseclass_exc_ << ")"; - } + out << "(" << gen_dynbaseclass_exc_ << ")"; } else { out << "(TException)"; } @@ -2794,7 +2774,6 @@ THRIFT_REGISTER_GENERATOR( " dynbase=CLS Derive generated classes from class CLS instead of TBase.\n" " dynfrozen=CLS Derive generated immutable classes from class CLS instead of TFrozenBase.\n" " dynexc=CLS Derive generated exceptions from CLS instead of TExceptionBase.\n" - " dynfrozenexc=CLS Derive generated immutable exceptions from CLS instead of TFrozenExceptionBase.\n" " dynimport='from foo.bar import CLS'\n" " Add an import line to generated code to find the dynbase class.\n" " package_prefix='top.package.'\n" diff --git a/lib/py/src/protocol/TBase.py b/lib/py/src/protocol/TBase.py index 6c6ef18e877..9ae1b118272 100644 --- a/lib/py/src/protocol/TBase.py +++ b/lib/py/src/protocol/TBase.py @@ -80,7 +80,3 @@ def read(cls, iprot): [self.__class__, self.thrift_spec]) else: return iprot.readStruct(cls, cls.thrift_spec, True) - - -class TFrozenExceptionBase(TFrozenBase, TExceptionBase): - pass diff --git a/lib/py/src/protocol/TProtocol.py b/lib/py/src/protocol/TProtocol.py index 339a2839d71..3456e8f0e85 100644 --- a/lib/py/src/protocol/TProtocol.py +++ b/lib/py/src/protocol/TProtocol.py @@ -303,14 +303,8 @@ def readContainerSet(self, spec): def readContainerStruct(self, spec): (obj_class, obj_spec) = spec - - # If obj_class.read is a classmethod (e.g. in frozen structs), - # call it as such. - if getattr(obj_class.read, '__self__', None) is obj_class: - obj = obj_class.read(self) - else: - obj = obj_class() - obj.read(self) + obj = obj_class() + obj.read(self) return obj def readContainerMap(self, spec): diff --git a/test/DebugProtoTest.thrift b/test/DebugProtoTest.thrift index 1ab0f6aea0a..de47ea71760 100644 --- a/test/DebugProtoTest.thrift +++ b/test/DebugProtoTest.thrift @@ -241,10 +241,6 @@ exception ExceptionWithAMap { 2: map map_field; } -exception MutableException { - 1: string msg; -} (python.immutable = "false") - service ServiceForExceptionWithAMap { void methodThatThrowsAnException() throws (1: ExceptionWithAMap xwamap); } diff --git a/test/py/TestFrozen.py b/test/py/TestFrozen.py index ce7425f88fb..6d2595cf29b 100755 --- a/test/py/TestFrozen.py +++ b/test/py/TestFrozen.py @@ -19,9 +19,7 @@ # under the License. # -from DebugProtoTest import Srv from DebugProtoTest.ttypes import CompactProtoTestStruct, Empty, Wrapper -from DebugProtoTest.ttypes import ExceptionWithAMap, MutableException from thrift.Thrift import TFrozenDict from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol, TCompactProtocol @@ -96,21 +94,6 @@ def test_struct(self): x2 = self._roundtrip(x, Wrapper) self.assertEqual(x2.foo, Empty()) - def test_frozen_exception(self): - exc = ExceptionWithAMap(blah='foo') - with self.assertRaises(TypeError): - exc.blah = 'bar' - mutexc = MutableException(msg='foo') - mutexc.msg = 'bar' - self.assertEqual(mutexc.msg, 'bar') - - def test_frozen_exception_serialization(self): - result = Srv.declaredExceptionMethod_result( - xwamap=ExceptionWithAMap(blah="error")) - deserialized = self._roundtrip( - result, Srv.declaredExceptionMethod_result()) - self.assertEqual(result, deserialized) - class TestFrozen(TestFrozenBase): def protocol(self, trans): From 3d9f50d61728d377951f9b6df5f19196f6b3af46 Mon Sep 17 00:00:00 2001 From: "D. Can Celasun" Date: Tue, 10 Dec 2019 22:13:19 +0000 Subject: [PATCH 459/756] Revert "Remove unnecessary TException.message hack" This reverts commit 45a9827f0f455d377ae87d9a35349c10181d6893. --- lib/py/src/Thrift.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/py/src/Thrift.py b/lib/py/src/Thrift.py index b335bc11b70..c390cbb54c1 100644 --- a/lib/py/src/Thrift.py +++ b/lib/py/src/Thrift.py @@ -90,6 +90,15 @@ def on_message_begin(self, func): class TException(Exception): """Base class for all thrift exceptions.""" + # BaseException.message is deprecated in Python v[2.6,3.0) + if (2, 6, 0) <= sys.version_info < (3, 0): + def _get_message(self): + return self._message + + def _set_message(self, message): + self._message = message + message = property(_get_message, _set_message) + def __init__(self, message=None): Exception.__init__(self, message) self.message = message From 3a0e1fd356963ad3ac0648b9891d1f8ff326f6ce Mon Sep 17 00:00:00 2001 From: Qinghui Xu Date: Wed, 13 Nov 2019 10:52:43 +0100 Subject: [PATCH 460/756] THRIFT-5008: Improve TSaslTransport logging Client: Java Patch: Qinghui Xu This closes #1931 --- .../src/org/apache/thrift/transport/TSaslTransport.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java index 4a453b68f97..4685d64a86a 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java @@ -392,7 +392,7 @@ public void close() { try { sasl.dispose(); } catch (SaslException e) { - // Not much we can do here. + LOGGER.warn("Failed to dispose sasl participant.", e); } } @@ -427,9 +427,7 @@ public int read(byte[] buf, int off, int len) throws TTransportException { } catch (TTransportException transportException) { // If there is no-data or no-sasl header in the stream, log the failure, and rethrow. if (transportException.getType() == TTransportException.END_OF_FILE) { - if (LOGGER.isDebugEnabled()) { - LOGGER.debug("No data or no sasl data in the stream during negotiation"); - } + LOGGER.debug("No data or no sasl data in the stream during negotiation"); } throw transportException; } From 6e023df1ded255dda00eb4c041c201e66c8d1fbc Mon Sep 17 00:00:00 2001 From: Qinghui Xu Date: Thu, 19 Sep 2019 23:04:03 +0200 Subject: [PATCH 461/756] THRIFT-4889 Nonblocking server with sasl support Client: Java Patch: Qinghui Xu This closes #1892 --- .../thrift/server/TSaslNonblockingServer.java | 480 ++++++++++++++++ .../thrift/server/TServerEventHandler.java | 6 +- .../thrift/transport/TEOFException.java | 30 + .../thrift/transport/TMemoryTransport.java | 81 +++ .../transport/TNonblockingServerSocket.java | 8 +- .../TNonblockingServerTransport.java | 8 + .../thrift/transport/TNonblockingSocket.java | 5 + .../transport/TSaslClientTransport.java | 1 + .../transport/TSaslServerTransport.java | 26 +- .../thrift/transport/TSaslTransport.java | 36 +- .../thrift/transport/TServerSocket.java | 19 +- .../thrift/transport/TServerTransport.java | 18 +- .../transport/sasl/DataFrameHeaderReader.java | 47 ++ .../transport/sasl/DataFrameReader.java | 30 + .../transport/sasl/DataFrameWriter.java | 60 ++ .../transport/sasl/FixedSizeHeaderReader.java | 74 +++ .../transport/sasl/FrameHeaderReader.java | 64 +++ .../thrift/transport/sasl/FrameReader.java | 162 ++++++ .../thrift/transport/sasl/FrameWriter.java | 122 ++++ .../transport/sasl/NegotiationStatus.java | 61 ++ .../sasl/NonblockingSaslHandler.java | 528 ++++++++++++++++++ .../sasl/SaslNegotiationFrameReader.java | 30 + .../sasl/SaslNegotiationFrameWriter.java | 56 ++ .../sasl/SaslNegotiationHeaderReader.java | 57 ++ .../thrift/transport/sasl/SaslPeer.java | 100 ++++ .../thrift/transport/sasl/ServerSaslPeer.java | 108 ++++ .../sasl/TBaseSaslProcessorFactory.java | 36 ++ .../sasl/TInvalidSaslFrameException.java | 30 + .../sasl/TSaslNegotiationException.java | 76 +++ .../transport/sasl/TSaslProcessorFactory.java | 32 ++ .../transport/sasl/TSaslServerDefinition.java | 43 ++ .../transport/sasl/TSaslServerFactory.java | 64 +++ .../org/apache/thrift/utils/StringUtils.java | 66 +++ .../server/TestSaslNonblockingServer.java | 96 ++++ .../TestNonblockingServerSocket.java | 36 ++ .../transport/TestTMemoryTransport.java | 65 +++ .../thrift/transport/TestTSaslTransports.java | 22 +- .../transport/sasl/TestDataFrameReader.java | 61 ++ .../transport/sasl/TestDataFrameWriter.java | 101 ++++ .../sasl/TestSaslNegotiationFrameReader.java | 64 +++ .../sasl/TestSaslNegotiationFrameWriter.java | 56 ++ .../apache/thrift/utils/TestStringUtils.java | 34 ++ 42 files changed, 3013 insertions(+), 86 deletions(-) create mode 100644 lib/java/src/org/apache/thrift/server/TSaslNonblockingServer.java create mode 100644 lib/java/src/org/apache/thrift/transport/TEOFException.java create mode 100644 lib/java/src/org/apache/thrift/transport/TMemoryTransport.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/DataFrameHeaderReader.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/DataFrameReader.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/DataFrameWriter.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/FixedSizeHeaderReader.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/FrameHeaderReader.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/FrameReader.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/FrameWriter.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/NegotiationStatus.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/NonblockingSaslHandler.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationFrameReader.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationFrameWriter.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationHeaderReader.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/SaslPeer.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/ServerSaslPeer.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/TBaseSaslProcessorFactory.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/TInvalidSaslFrameException.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/TSaslNegotiationException.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/TSaslProcessorFactory.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/TSaslServerDefinition.java create mode 100644 lib/java/src/org/apache/thrift/transport/sasl/TSaslServerFactory.java create mode 100644 lib/java/src/org/apache/thrift/utils/StringUtils.java create mode 100644 lib/java/test/org/apache/thrift/server/TestSaslNonblockingServer.java create mode 100644 lib/java/test/org/apache/thrift/transport/TestNonblockingServerSocket.java create mode 100644 lib/java/test/org/apache/thrift/transport/TestTMemoryTransport.java create mode 100644 lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameReader.java create mode 100644 lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameWriter.java create mode 100644 lib/java/test/org/apache/thrift/transport/sasl/TestSaslNegotiationFrameReader.java create mode 100644 lib/java/test/org/apache/thrift/transport/sasl/TestSaslNegotiationFrameWriter.java create mode 100644 lib/java/test/org/apache/thrift/utils/TestStringUtils.java diff --git a/lib/java/src/org/apache/thrift/server/TSaslNonblockingServer.java b/lib/java/src/org/apache/thrift/server/TSaslNonblockingServer.java new file mode 100644 index 00000000000..89dbb787240 --- /dev/null +++ b/lib/java/src/org/apache/thrift/server/TSaslNonblockingServer.java @@ -0,0 +1,480 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift.server; + +import java.io.IOException; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +import javax.security.auth.callback.CallbackHandler; + +import org.apache.thrift.TProcessor; +import org.apache.thrift.transport.TNonblockingServerSocket; +import org.apache.thrift.transport.TNonblockingServerTransport; +import org.apache.thrift.transport.TNonblockingTransport; +import org.apache.thrift.transport.TTransportException; +import org.apache.thrift.transport.sasl.NonblockingSaslHandler; +import org.apache.thrift.transport.sasl.NonblockingSaslHandler.Phase; +import org.apache.thrift.transport.sasl.TBaseSaslProcessorFactory; +import org.apache.thrift.transport.sasl.TSaslProcessorFactory; +import org.apache.thrift.transport.sasl.TSaslServerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * TServer with sasl support, using asynchronous execution and nonblocking io. + */ +public class TSaslNonblockingServer extends TServer { + private static final Logger LOGGER = LoggerFactory.getLogger(TSaslNonblockingServer.class); + + private static final int DEFAULT_NETWORK_THREADS = 1; + private static final int DEFAULT_AUTHENTICATION_THREADS = 1; + private static final int DEFAULT_PROCESSING_THREADS = Runtime.getRuntime().availableProcessors(); + + private final AcceptorThread acceptor; + private final NetworkThreadPool networkThreadPool; + private final ExecutorService authenticationExecutor; + private final ExecutorService processingExecutor; + private final TSaslServerFactory saslServerFactory; + private final TSaslProcessorFactory saslProcessorFactory; + + public TSaslNonblockingServer(Args args) throws IOException { + super(args); + acceptor = new AcceptorThread((TNonblockingServerSocket) serverTransport_); + networkThreadPool = new NetworkThreadPool(args.networkThreads); + authenticationExecutor = Executors.newFixedThreadPool(args.saslThreads); + processingExecutor = Executors.newFixedThreadPool(args.processingThreads); + saslServerFactory = args.saslServerFactory; + saslProcessorFactory = args.saslProcessorFactory; + } + + @Override + public void serve() { + if (eventHandler_ != null) { + eventHandler_.preServe(); + } + networkThreadPool.start(); + acceptor.start(); + setServing(true); + } + + /** + * Trigger a graceful shutdown, but it does not block to wait for the shutdown to finish. + */ + @Override + public void stop() { + if (!stopped_) { + setServing(false); + stopped_ = true; + acceptor.wakeup(); + networkThreadPool.wakeupAll(); + authenticationExecutor.shutdownNow(); + processingExecutor.shutdownNow(); + } + } + + /** + * Gracefully shut down the server and block until all threads are stopped. + * + * @throws InterruptedException if is interrupted while waiting for shutdown. + */ + public void shutdown() throws InterruptedException { + stop(); + acceptor.join(); + for (NetworkThread networkThread : networkThreadPool.networkThreads) { + networkThread.join(); + } + while (!authenticationExecutor.isTerminated()) { + authenticationExecutor.awaitTermination(10, TimeUnit.SECONDS); + } + while (!processingExecutor.isTerminated()) { + processingExecutor.awaitTermination(10, TimeUnit.SECONDS); + } + } + + private class AcceptorThread extends Thread { + + private final TNonblockingServerTransport serverTransport; + private final Selector acceptSelector; + + private AcceptorThread(TNonblockingServerSocket serverTransport) throws IOException { + super("acceptor-thread"); + this.serverTransport = serverTransport; + acceptSelector = Selector.open(); + serverTransport.registerSelector(acceptSelector); + } + + @Override + public void run() { + try { + serverTransport.listen(); + while (!stopped_) { + select(); + acceptNewConnection(); + } + } catch (TTransportException e) { + // Failed to listen. + LOGGER.error("Failed to listen on server socket, error " + e.getType(), e); + } catch (Throwable e) { + // Unexpected errors. + LOGGER.error("Unexpected error in acceptor thread.", e); + } finally { + TSaslNonblockingServer.this.stop(); + close(); + } + } + + void wakeup() { + acceptSelector.wakeup(); + } + + private void acceptNewConnection() { + Iterator selectedKeyItr = acceptSelector.selectedKeys().iterator(); + while (!stopped_ && selectedKeyItr.hasNext()) { + SelectionKey selected = selectedKeyItr.next(); + selectedKeyItr.remove(); + if (selected.isAcceptable()) { + try { + while (true) { + // Accept all available connections from the backlog. + TNonblockingTransport connection = serverTransport.accept(); + if (connection == null) { + break; + } + if (!networkThreadPool.acceptNewConnection(connection)) { + LOGGER.error("Network thread does not accept: " + connection); + connection.close(); + } + } + } catch (TTransportException e) { + LOGGER.warn("Failed to accept incoming connection.", e); + } + } else { + LOGGER.error("Not acceptable selection: " + selected.channel()); + } + } + } + + private void select() { + try { + acceptSelector.select(); + } catch (IOException e) { + LOGGER.error("Failed to select on the server socket.", e); + } + } + + private void close() { + LOGGER.info("Closing acceptor thread."); + serverTransport.close(); + try { + acceptSelector.close(); + } catch (IOException e) { + LOGGER.error("Failed to close accept selector.", e); + } + } + } + + private class NetworkThread extends Thread { + private final BlockingQueue incomingConnections = new LinkedBlockingQueue<>(); + private final BlockingQueue stateTransitions = new LinkedBlockingQueue<>(); + private final Selector ioSelector; + + NetworkThread(String name) throws IOException { + super(name); + ioSelector = Selector.open(); + } + + @Override + public void run() { + try { + while (!stopped_) { + handleIncomingConnections(); + handleStateChanges(); + select(); + handleIO(); + } + } catch (Throwable e) { + LOGGER.error("Unreoverable error in " + getName(), e); + } finally { + close(); + } + } + + private void handleStateChanges() { + while (true) { + NonblockingSaslHandler statemachine = stateTransitions.poll(); + if (statemachine == null) { + return; + } + tryRunNextPhase(statemachine); + } + } + + private void select() { + try { + ioSelector.select(); + } catch (IOException e) { + LOGGER.error("Failed to select in " + getName(), e); + } + } + + private void handleIO() { + Iterator selectedKeyItr = ioSelector.selectedKeys().iterator(); + while (!stopped_ && selectedKeyItr.hasNext()) { + SelectionKey selected = selectedKeyItr.next(); + selectedKeyItr.remove(); + if (!selected.isValid()) { + closeChannel(selected); + } + NonblockingSaslHandler saslHandler = (NonblockingSaslHandler) selected.attachment(); + if (selected.isReadable()) { + saslHandler.handleRead(); + } else if (selected.isWritable()) { + saslHandler.handleWrite(); + } else { + LOGGER.error("Invalid intrest op " + selected.interestOps()); + closeChannel(selected); + continue; + } + if (saslHandler.isCurrentPhaseDone()) { + tryRunNextPhase(saslHandler); + } + } + } + + // The following methods are modifying the registered channel set on the selector, which itself + // is not thread safe. Thus we need a lock to protect it from race condition. + + private synchronized void handleIncomingConnections() { + while (true) { + TNonblockingTransport connection = incomingConnections.poll(); + if (connection == null) { + return; + } + if (!connection.isOpen()) { + LOGGER.warn("Incoming connection is already closed"); + continue; + } + try { + SelectionKey selectionKey = connection.registerSelector(ioSelector, SelectionKey.OP_READ); + if (selectionKey.isValid()) { + NonblockingSaslHandler saslHandler = new NonblockingSaslHandler(selectionKey, connection, + saslServerFactory, saslProcessorFactory, inputProtocolFactory_, outputProtocolFactory_, + eventHandler_); + selectionKey.attach(saslHandler); + } + } catch (IOException e) { + LOGGER.error("Failed to register connection for the selector, close it.", e); + connection.close(); + } + } + } + + private synchronized void close() { + LOGGER.warn("Closing " + getName()); + while (true) { + TNonblockingTransport incomingConnection = incomingConnections.poll(); + if (incomingConnection == null) { + break; + } + incomingConnection.close(); + } + Set registered = ioSelector.keys(); + for (SelectionKey selection : registered) { + closeChannel(selection); + } + try { + ioSelector.close(); + } catch (IOException e) { + LOGGER.error("Failed to close io selector " + getName(), e); + } + } + + private synchronized void closeChannel(SelectionKey selectionKey) { + if (selectionKey.attachment() == null) { + try { + selectionKey.channel().close(); + } catch (IOException e) { + LOGGER.error("Failed to close channel.", e); + } finally { + selectionKey.cancel(); + } + } else { + NonblockingSaslHandler saslHandler = (NonblockingSaslHandler) selectionKey.attachment(); + saslHandler.close(); + } + } + + private void tryRunNextPhase(NonblockingSaslHandler saslHandler) { + Phase nextPhase = saslHandler.getNextPhase(); + saslHandler.stepToNextPhase(); + switch (nextPhase) { + case EVALUATING_SASL_RESPONSE: + authenticationExecutor.submit(new Computation(saslHandler)); + break; + case PROCESSING: + processingExecutor.submit(new Computation(saslHandler)); + break; + case CLOSING: + saslHandler.runCurrentPhase(); + break; + default: // waiting for next io event for the current state machine + } + } + + public boolean accept(TNonblockingTransport connection) { + if (stopped_) { + return false; + } + if (incomingConnections.offer(connection)) { + wakeup(); + return true; + } + return false; + } + + private void wakeup() { + ioSelector.wakeup(); + } + + private class Computation implements Runnable { + + private final NonblockingSaslHandler statemachine; + + private Computation(NonblockingSaslHandler statemachine) { + this.statemachine = statemachine; + } + + @Override + public void run() { + try { + while (!statemachine.isCurrentPhaseDone()) { + statemachine.runCurrentPhase(); + } + stateTransitions.add(statemachine); + wakeup(); + } catch (Throwable e) { + LOGGER.error("Damn it!", e); + } + } + } + } + + private class NetworkThreadPool { + private final List networkThreads; + private int accepted = 0; + + NetworkThreadPool(int size) throws IOException { + networkThreads = new ArrayList<>(size); + int digits = (int) Math.log10(size) + 1; + String threadNamePattern = "network-thread-%0" + digits + "d"; + for (int i = 0; i < size; i++) { + networkThreads.add(new NetworkThread(String.format(threadNamePattern, i))); + } + } + + /** + * Round robin new connection among all the network threads. + * + * @param connection incoming connection. + * @return true if the incoming connection is accepted by network thread pool. + */ + boolean acceptNewConnection(TNonblockingTransport connection) { + return networkThreads.get((accepted ++) % networkThreads.size()).accept(connection); + } + + public void start() { + for (NetworkThread thread : networkThreads) { + thread.start(); + } + } + + void wakeupAll() { + for (NetworkThread networkThread : networkThreads) { + networkThread.wakeup(); + } + } + } + + public static class Args extends AbstractServerArgs { + + private int networkThreads = DEFAULT_NETWORK_THREADS; + private int saslThreads = DEFAULT_AUTHENTICATION_THREADS; + private int processingThreads = DEFAULT_PROCESSING_THREADS; + private TSaslServerFactory saslServerFactory = new TSaslServerFactory(); + private TSaslProcessorFactory saslProcessorFactory; + + public Args(TNonblockingServerTransport transport) { + super(transport); + } + + public Args networkThreads(int networkThreads) { + this.networkThreads = networkThreads <= 0 ? DEFAULT_NETWORK_THREADS : networkThreads; + return this; + } + + public Args saslThreads(int authenticationThreads) { + this.saslThreads = authenticationThreads <= 0 ? DEFAULT_AUTHENTICATION_THREADS : authenticationThreads; + return this; + } + + public Args processingThreads(int processingThreads) { + this.processingThreads = processingThreads <= 0 ? DEFAULT_PROCESSING_THREADS : processingThreads; + return this; + } + + public Args processor(TProcessor processor) { + saslProcessorFactory = new TBaseSaslProcessorFactory(processor); + return this; + } + + public Args saslProcessorFactory(TSaslProcessorFactory saslProcessorFactory) { + if (saslProcessorFactory == null) { + throw new NullPointerException("Processor factory cannot be null"); + } + this.saslProcessorFactory = saslProcessorFactory; + return this; + } + + public Args addSaslMechanism(String mechanism, String protocol, String serverName, + Map props, CallbackHandler cbh) { + saslServerFactory.addSaslMechanism(mechanism, protocol, serverName, props, cbh); + return this; + } + + public Args saslServerFactory(TSaslServerFactory saslServerFactory) { + if (saslServerFactory == null) { + throw new NullPointerException("saslServerFactory cannot be null"); + } + this.saslServerFactory = saslServerFactory; + return this; + } + } +} diff --git a/lib/java/src/org/apache/thrift/server/TServerEventHandler.java b/lib/java/src/org/apache/thrift/server/TServerEventHandler.java index f069b9bfbe0..3bd79598622 100644 --- a/lib/java/src/org/apache/thrift/server/TServerEventHandler.java +++ b/lib/java/src/org/apache/thrift/server/TServerEventHandler.java @@ -28,6 +28,10 @@ * 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). + * + * TODO: It seems this is a custom code entry point created for some resource management purpose in hive. + * But when looking into hive code, we see that the argments of TProtocol and TTransport are never used. + * We probably should remove these arguments from all the methods. */ public interface TServerEventHandler { @@ -56,4 +60,4 @@ void deleteContext(ServerContext serverContext, void processContext(ServerContext serverContext, TTransport inputTransport, TTransport outputTransport); -} \ No newline at end of file +} diff --git a/lib/java/src/org/apache/thrift/transport/TEOFException.java b/lib/java/src/org/apache/thrift/transport/TEOFException.java new file mode 100644 index 00000000000..b5ae6eff463 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/TEOFException.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 org.apache.thrift.transport; + +/** + * End of file, especially, the underlying socket is closed. + */ +public class TEOFException extends TTransportException { + + public TEOFException(String message) { + super(TTransportException.END_OF_FILE, message); + } +} diff --git a/lib/java/src/org/apache/thrift/transport/TMemoryTransport.java b/lib/java/src/org/apache/thrift/transport/TMemoryTransport.java new file mode 100644 index 00000000000..f41bc09c8c9 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/TMemoryTransport.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 org.apache.thrift.transport; + +import java.nio.ByteBuffer; + +import org.apache.thrift.TByteArrayOutputStream; + +/** + * In memory transport with separate buffers for input and output. + */ +public class TMemoryTransport extends TTransport { + + private final ByteBuffer inputBuffer; + private final TByteArrayOutputStream outputBuffer; + + public TMemoryTransport(byte[] input) { + inputBuffer = ByteBuffer.wrap(input); + outputBuffer = new TByteArrayOutputStream(1024); + } + + @Override + public boolean isOpen() { + return true; + } + + /** + * Opening on an in memory transport should have no effect. + */ + @Override + public void open() { + // Do nothing. + } + + @Override + public void close() { + // Do nothing. + } + + @Override + public int read(byte[] buf, int off, int len) throws TTransportException { + int remaining = inputBuffer.remaining(); + if (remaining < len) { + throw new TTransportException(TTransportException.END_OF_FILE, + "There's only " + remaining + "bytes, but it asks for " + len); + } + inputBuffer.get(buf, off, len); + return len; + } + + @Override + public void write(byte[] buf, int off, int len) throws TTransportException { + outputBuffer.write(buf, off, len); + } + + /** + * Get all the bytes written by thrift output protocol. + * + * @return a byte array. + */ + public TByteArrayOutputStream getOutput() { + return outputBuffer; + } +} diff --git a/lib/java/src/org/apache/thrift/transport/TNonblockingServerSocket.java b/lib/java/src/org/apache/thrift/transport/TNonblockingServerSocket.java index df37cb06e68..1631892334f 100644 --- a/lib/java/src/org/apache/thrift/transport/TNonblockingServerSocket.java +++ b/lib/java/src/org/apache/thrift/transport/TNonblockingServerSocket.java @@ -108,7 +108,8 @@ public void listen() throws TTransportException { } } - protected TNonblockingSocket acceptImpl() throws TTransportException { + @Override + public TNonblockingSocket accept() throws TTransportException { if (serverSocket_ == null) { throw new TTransportException(TTransportException.NOT_OPEN, "No underlying server socket."); } @@ -160,4 +161,9 @@ public int getPort() { return serverSocket_.getLocalPort(); } + // Expose it for test purpose. + ServerSocketChannel getServerSocketChannel() { + return serverSocketChannel; + } + } diff --git a/lib/java/src/org/apache/thrift/transport/TNonblockingServerTransport.java b/lib/java/src/org/apache/thrift/transport/TNonblockingServerTransport.java index ba45b09dcff..daac0d574b4 100644 --- a/lib/java/src/org/apache/thrift/transport/TNonblockingServerTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TNonblockingServerTransport.java @@ -28,4 +28,12 @@ public abstract class TNonblockingServerTransport extends TServerTransport { public abstract void registerSelector(Selector selector); + + /** + * + * @return an incoming connection or null if there is none. + * @throws TTransportException + */ + @Override + public abstract TNonblockingTransport accept() throws TTransportException; } diff --git a/lib/java/src/org/apache/thrift/transport/TNonblockingSocket.java b/lib/java/src/org/apache/thrift/transport/TNonblockingSocket.java index f86a48b4285..37a66d61410 100644 --- a/lib/java/src/org/apache/thrift/transport/TNonblockingSocket.java +++ b/lib/java/src/org/apache/thrift/transport/TNonblockingSocket.java @@ -207,4 +207,9 @@ public boolean finishConnect() throws IOException { return socketChannel_.finishConnect(); } + @Override + public String toString() { + return "[remote: " + socketChannel_.socket().getRemoteSocketAddress() + + ", local: " + socketChannel_.socket().getLocalAddress() + "]" ; + } } diff --git a/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java index 4b1ca0a944f..5fc7cff9bbc 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslClientTransport.java @@ -27,6 +27,7 @@ import javax.security.sasl.SaslClient; import javax.security.sasl.SaslException; +import org.apache.thrift.transport.sasl.NegotiationStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java index 39b81ca4367..31f309ef8a4 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslServerTransport.java @@ -31,6 +31,8 @@ import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; +import org.apache.thrift.transport.sasl.NegotiationStatus; +import org.apache.thrift.transport.sasl.TSaslServerDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,30 +51,10 @@ public class TSaslServerTransport extends TSaslTransport { */ 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. */ @@ -84,7 +66,7 @@ public TSaslServerTransport(TTransport 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. */ diff --git a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java index 4685d64a86a..d1a3d3115ae 100644 --- a/lib/java/src/org/apache/thrift/transport/TSaslTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TSaslTransport.java @@ -20,8 +20,6 @@ package org.apache.thrift.transport; import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; import javax.security.sasl.Sasl; import javax.security.sasl.SaslClient; @@ -30,6 +28,7 @@ import org.apache.thrift.EncodingUtils; import org.apache.thrift.TByteArrayOutputStream; +import org.apache.thrift.transport.sasl.NegotiationStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,39 +50,6 @@ 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. */ diff --git a/lib/java/src/org/apache/thrift/transport/TServerSocket.java b/lib/java/src/org/apache/thrift/transport/TServerSocket.java index 79f7b7f49f8..eb302fd2684 100644 --- a/lib/java/src/org/apache/thrift/transport/TServerSocket.java +++ b/lib/java/src/org/apache/thrift/transport/TServerSocket.java @@ -121,18 +121,23 @@ public void listen() throws TTransportException { } } - protected TSocket acceptImpl() throws TTransportException { + @Override + public TSocket accept() throws TTransportException { if (serverSocket_ == null) { throw new TTransportException(TTransportException.NOT_OPEN, "No underlying server socket."); } + Socket result; try { - Socket result = serverSocket_.accept(); - TSocket result2 = new TSocket(result); - result2.setTimeout(clientTimeout_); - return result2; - } catch (IOException iox) { - throw new TTransportException(iox); + result = serverSocket_.accept(); + } catch (Exception e) { + throw new TTransportException(e); } + if (result == null) { + throw new TTransportException("Blocking server's accept() may not return NULL"); + } + TSocket socket = new TSocket(result); + socket.setTimeout(clientTimeout_); + return socket; } public void close() { diff --git a/lib/java/src/org/apache/thrift/transport/TServerTransport.java b/lib/java/src/org/apache/thrift/transport/TServerTransport.java index 424e4faaae2..55ef0c4c444 100644 --- a/lib/java/src/org/apache/thrift/transport/TServerTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TServerTransport.java @@ -56,18 +56,18 @@ public T bindAddr(InetSocketAddress bindAddr) { 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; - } + /** + * Accept incoming connection on the server socket. When there is no incoming connection available: + * either it should block infinitely in a blocking implementation, either it should return null in + * a nonblocking implementation. + * + * @return new connection + * @throws TTransportException if IO error. + */ + public abstract TTransport accept() throws TTransportException; 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 diff --git a/lib/java/src/org/apache/thrift/transport/sasl/DataFrameHeaderReader.java b/lib/java/src/org/apache/thrift/transport/sasl/DataFrameHeaderReader.java new file mode 100644 index 00000000000..2900df9c101 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/DataFrameHeaderReader.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 org.apache.thrift.transport.sasl; + +/** + * The header for data frame, it only contains a 4-byte payload size. + */ +public class DataFrameHeaderReader extends FixedSizeHeaderReader { + public static final int PAYLOAD_LENGTH_BYTES = 4; + + private int payloadSize; + + @Override + protected int headerSize() { + return PAYLOAD_LENGTH_BYTES; + } + + @Override + protected void onComplete() throws TInvalidSaslFrameException { + payloadSize = byteBuffer.getInt(0); + if (payloadSize < 0) { + throw new TInvalidSaslFrameException("Payload size is negative: " + payloadSize); + } + } + + @Override + public int payloadSize() { + return payloadSize; + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/DataFrameReader.java b/lib/java/src/org/apache/thrift/transport/sasl/DataFrameReader.java new file mode 100644 index 00000000000..e6900bbc68b --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/DataFrameReader.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 org.apache.thrift.transport.sasl; + +/** + * Frames for thrift (serialized) messages. + */ +public class DataFrameReader extends FrameReader { + + public DataFrameReader() { + super(new DataFrameHeaderReader()); + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/DataFrameWriter.java b/lib/java/src/org/apache/thrift/transport/sasl/DataFrameWriter.java new file mode 100644 index 00000000000..a2dd15a8cfe --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/DataFrameWriter.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 org.apache.thrift.transport.sasl; + +import java.nio.ByteBuffer; + +import org.apache.thrift.EncodingUtils; +import org.apache.thrift.utils.StringUtils; + +import static org.apache.thrift.transport.sasl.DataFrameHeaderReader.PAYLOAD_LENGTH_BYTES; + +/** + * Write frames of thrift messages. It expects an empty/null header to be provided with a payload + * to be written out. Non empty headers are considered as error. + */ +public class DataFrameWriter extends FrameWriter { + + @Override + public void withOnlyPayload(byte[] payload, int offset, int length) { + if (!isComplete()) { + throw new IllegalStateException("Previsous write is not yet complete, with " + + frameBytes.remaining() + " bytes left."); + } + frameBytes = buildFrameWithPayload(payload, offset, length); + } + + @Override + protected ByteBuffer buildFrame(byte[] header, int headerOffset, int headerLength, + byte[] payload, int payloadOffset, int payloadLength) { + if (header != null && headerLength > 0) { + throw new IllegalArgumentException("Extra header [" + StringUtils.bytesToHexString(header) + + "] offset " + payloadOffset + " length " + payloadLength); + } + return buildFrameWithPayload(payload, payloadOffset, payloadLength); + } + + private ByteBuffer buildFrameWithPayload(byte[] payload, int offset, int length) { + byte[] bytes = new byte[PAYLOAD_LENGTH_BYTES + length]; + EncodingUtils.encodeBigEndian(length, bytes, 0); + System.arraycopy(payload, offset, bytes, PAYLOAD_LENGTH_BYTES, length); + return ByteBuffer.wrap(bytes); + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/FixedSizeHeaderReader.java b/lib/java/src/org/apache/thrift/transport/sasl/FixedSizeHeaderReader.java new file mode 100644 index 00000000000..1cbc0ace08a --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/FixedSizeHeaderReader.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.thrift.transport.sasl; + +import org.apache.thrift.transport.TTransport; +import org.apache.thrift.transport.TTransportException; +import org.apache.thrift.utils.StringUtils; + +import java.nio.ByteBuffer; + +/** + * Headers' size should be predefined. + */ +public abstract class FixedSizeHeaderReader implements FrameHeaderReader { + + protected final ByteBuffer byteBuffer = ByteBuffer.allocate(headerSize()); + + @Override + public boolean isComplete() { + return !byteBuffer.hasRemaining(); + } + + @Override + public void clear() { + byteBuffer.clear(); + } + + @Override + public byte[] toBytes() { + if (!isComplete()) { + throw new IllegalStateException("Header is not yet complete " + StringUtils.bytesToHexString(byteBuffer.array(), 0, byteBuffer.position())); + } + return byteBuffer.array(); + } + + @Override + public boolean read(TTransport transport) throws TTransportException { + FrameReader.readAvailable(transport, byteBuffer); + if (byteBuffer.hasRemaining()) { + return false; + } + onComplete(); + return true; + } + + /** + * @return Size of the header. + */ + protected abstract int headerSize(); + + /** + * Actions (e.g. validation) to carry out when the header is complete. + * + * @throws TTransportException + */ + protected abstract void onComplete() throws TTransportException; +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/FrameHeaderReader.java b/lib/java/src/org/apache/thrift/transport/sasl/FrameHeaderReader.java new file mode 100644 index 00000000000..f7c65931562 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/FrameHeaderReader.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.thrift.transport.sasl; + +import org.apache.thrift.transport.TTransport; +import org.apache.thrift.transport.TTransportException; + +/** + * Read headers for a frame. For each frame, the header contains payload size and other metadata. + */ +public interface FrameHeaderReader { + + /** + * As the thrift sasl specification states, all sasl messages (both for negotiatiing and for + * sending data) should have a header to indicate the size of the payload. + * + * @return size of the payload. + */ + int payloadSize(); + + /** + * + * @return The received bytes for the header. + * @throws IllegalStateException if isComplete returns false. + */ + byte[] toBytes(); + + /** + * @return true if this header has all its fields set. + */ + boolean isComplete(); + + /** + * Clear the header and make it available to read a new header. + */ + void clear(); + + /** + * (Nonblocking) Read fields from underlying transport layer. + * + * @param transport underlying transport. + * @return true if header is complete after read. + * @throws TSaslNegotiationException if fail to read a valid header of a sasl negotiation message. + * @throws TTransportException if io error. + */ + boolean read(TTransport transport) throws TSaslNegotiationException, TTransportException; +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/FrameReader.java b/lib/java/src/org/apache/thrift/transport/sasl/FrameReader.java new file mode 100644 index 00000000000..acb4b738d7d --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/FrameReader.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 org.apache.thrift.transport.sasl; + +import org.apache.thrift.transport.TEOFException; +import org.apache.thrift.transport.TTransport; +import org.apache.thrift.transport.TTransportException; + +import java.nio.ByteBuffer; + +/** + * Read frames from a transport. Each frame has a header and a payload. A header will indicate + * the size of the payload and other informations about how to decode payload. + * Implementations should subclass it by providing a header reader implementation. + * + * @param Header type. + */ +public abstract class FrameReader { + private final T header; + private ByteBuffer payload; + + protected FrameReader(T header) { + this.header = header; + } + + /** + * (Nonblocking) Read available bytes out of the transport without blocking to wait for incoming + * data. + * + * @param transport TTransport + * @return true if current frame is complete after read. + * @throws TSaslNegotiationException if fail to read back a valid sasl negotiation message. + * @throws TTransportException if io error. + */ + public boolean read(TTransport transport) throws TSaslNegotiationException, TTransportException { + if (!header.isComplete()) { + if (readHeader(transport)) { + payload = ByteBuffer.allocate(header.payloadSize()); + } else { + return false; + } + } + if (header.payloadSize() == 0) { + return true; + } + return readPayload(transport); + } + + /** + * (Nonblocking) Try to read available header bytes from transport. + * + * @return true if header is complete after read. + * @throws TSaslNegotiationException if fail to read back a validd sasl negotiation header. + * @throws TTransportException if io error. + */ + private boolean readHeader(TTransport transport) throws TSaslNegotiationException, TTransportException { + return header.read(transport); + } + + /** + * (Nonblocking) Try to read available + * + * @param transport underlying transport. + * @return true if payload is complete after read. + * @throws TTransportException if io error. + */ + private boolean readPayload(TTransport transport) throws TTransportException { + readAvailable(transport, payload); + return payload.hasRemaining(); + } + + /** + * + * @return header of the frame + */ + public T getHeader() { + return header; + } + + /** + * + * @return number of bytes of the header + */ + public int getHeaderSize() { + return header.toBytes().length; + } + + /** + * + * @return byte array of the payload + */ + public byte[] getPayload() { + return payload.array(); + } + + /** + * + * @return size of the payload + */ + public int getPayloadSize() { + return header.payloadSize(); + } + + /** + * + * @return true if the reader has fully read a frame + */ + public boolean isComplete() { + return !(payload == null || payload.hasRemaining()); + } + + /** + * Reset the state of the reader so that it can be reused to read a new frame. + */ + public void clear() { + header.clear(); + payload = null; + } + + /** + * Read immediately available bytes from the transport into the byte buffer. + * + * @param transport TTransport + * @param recipient ByteBuffer + * @return number of bytes read out of the transport + * @throws TTransportException if io error + */ + static int readAvailable(TTransport transport, ByteBuffer recipient) throws TTransportException { + if (!recipient.hasRemaining()) { + throw new IllegalStateException("Trying to fill a full recipient with " + recipient.limit() + + " bytes"); + } + int currentPosition = recipient.position(); + byte[] bytes = recipient.array(); + int offset = recipient.arrayOffset() + currentPosition; + int expectedLength = recipient.remaining(); + int got = transport.read(bytes, offset, expectedLength); + if (got < 0) { + throw new TEOFException("Transport is closed, while trying to read " + expectedLength + + " bytes"); + } + recipient.position(currentPosition + got); + return got; + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/FrameWriter.java b/lib/java/src/org/apache/thrift/transport/sasl/FrameWriter.java new file mode 100644 index 00000000000..5f48121178b --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/FrameWriter.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift.transport.sasl; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import org.apache.thrift.transport.TNonblockingTransport; + +/** + * Write frame (header and payload) to transport in a nonblocking way. + */ +public abstract class FrameWriter { + + protected ByteBuffer frameBytes; + + /** + * Provide (maybe empty) header and payload to the frame. This can be called only when isComplete + * returns true (last frame has been written out). + * + * @param header Some extra header bytes (without the 4 bytes for payload length), which will be + * the start of the frame. It can be empty, depending on the message format + * @param payload Payload as a byte array + * @throws IllegalStateException if it is called when isComplete returns false + * @throws IllegalArgumentException if header or payload is invalid + */ + public void withHeaderAndPayload(byte[] header, byte[] payload) { + if (payload == null) { + payload = new byte[0]; + } + if (header == null) { + withOnlyPayload(payload); + } else { + withHeaderAndPayload(header, 0, header.length, payload, 0, payload.length); + } + } + + /** + * Provide extra header and payload to the frame. + * + * @param header byte array containing the extra header + * @param headerOffset starting offset of the header portition + * @param headerLength length of the extra header + * @param payload byte array containing the payload + * @param payloadOffset starting offset of the payload portion + * @param payloadLength length of the payload + * @throws IllegalStateException if preivous frame is not yet complete (isComplete returns fals) + * @throws IllegalArgumentException if header or payload is invalid + */ + public void withHeaderAndPayload(byte[] header, int headerOffset, int headerLength, + byte[] payload, int payloadOffset, int payloadLength) { + if (!isComplete()) { + throw new IllegalStateException("Previsous write is not yet complete, with " + + frameBytes.remaining() + " bytes left."); + } + frameBytes = buildFrame(header, headerOffset, headerLength, payload, payloadOffset, payloadLength); + } + + /** + * Provide only payload to the frame. Throws UnsupportedOperationException if the frame expects + * a header. + * + * @param payload payload as a byte array + */ + public void withOnlyPayload(byte[] payload) { + withOnlyPayload(payload, 0, payload.length); + } + + /** + * Provide only payload to the frame. Throws UnsupportedOperationException if the frame expects + * a header. + * + * @param payload The underlying byte array as a recipient of the payload + * @param offset The offset in the byte array starting from where the payload is located + * @param length The length of the payload + */ + public abstract void withOnlyPayload(byte[] payload, int offset, int length); + + protected abstract ByteBuffer buildFrame(byte[] header, int headerOffset, int headerLength, + byte[] payload, int payloadOffset, int payloadeLength); + + /** + * Nonblocking write to the underlying transport. + * + * @throws IOException + */ + public void write(TNonblockingTransport transport) throws IOException { + transport.write(frameBytes); + } + + /** + * + * @return true when no more data needs to be written out + */ + public boolean isComplete() { + return frameBytes == null || !frameBytes.hasRemaining(); + } + + /** + * Release the byte buffer. + */ + public void clear() { + frameBytes = null; + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/NegotiationStatus.java b/lib/java/src/org/apache/thrift/transport/sasl/NegotiationStatus.java new file mode 100644 index 00000000000..ad704a0a1be --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/NegotiationStatus.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift.transport.sasl; + +import java.util.HashMap; +import java.util.Map; + +import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.PROTOCOL_ERROR; + +/** + * Status bytes used during the initial Thrift SASL handshake. + */ +public enum NegotiationStatus { + START((byte)0x01), + OK((byte)0x02), + BAD((byte)0x03), + ERROR((byte)0x04), + COMPLETE((byte)0x05); + + private static final Map reverseMap = new HashMap<>(); + + static { + for (NegotiationStatus s : NegotiationStatus.values()) { + reverseMap.put(s.getValue(), s); + } + } + + private final byte value; + + NegotiationStatus(byte val) { + this.value = val; + } + + public byte getValue() { + return value; + } + + public static NegotiationStatus byValue(byte val) throws TSaslNegotiationException { + if (!reverseMap.containsKey(val)) { + throw new TSaslNegotiationException(PROTOCOL_ERROR, "Invalid status " + val); + } + return reverseMap.get(val); + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/NonblockingSaslHandler.java b/lib/java/src/org/apache/thrift/transport/sasl/NonblockingSaslHandler.java new file mode 100644 index 00000000000..45571469b11 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/NonblockingSaslHandler.java @@ -0,0 +1,528 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift.transport.sasl; + +import java.io.IOException; +import java.nio.channels.SelectionKey; +import java.nio.charset.StandardCharsets; + +import javax.security.sasl.SaslServer; + +import org.apache.thrift.TByteArrayOutputStream; +import org.apache.thrift.TProcessor; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.protocol.TProtocolFactory; +import org.apache.thrift.server.ServerContext; +import org.apache.thrift.server.TServerEventHandler; +import org.apache.thrift.transport.TMemoryTransport; +import org.apache.thrift.transport.TNonblockingTransport; +import org.apache.thrift.transport.TTransportException; +import org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.apache.thrift.transport.sasl.NegotiationStatus.COMPLETE; +import static org.apache.thrift.transport.sasl.NegotiationStatus.OK; + +/** + * State machine managing one sasl connection in a nonblocking way. + */ +public class NonblockingSaslHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(NonblockingSaslHandler.class); + + private static final int INTEREST_NONE = 0; + private static final int INTEREST_READ = SelectionKey.OP_READ; + private static final int INTEREST_WRITE = SelectionKey.OP_WRITE; + + // Tracking the current running phase + private Phase currentPhase = Phase.INITIIALIIZING; + // Tracking the next phase on the next invocation of the state machine. + // It should be the same as current phase if current phase is not yet finished. + // Otherwise, if it is different from current phase, the statemachine is in a transition state: + // current phase is done, and next phase is not yet started. + private Phase nextPhase = currentPhase; + + // Underlying nonblocking transport + private SelectionKey selectionKey; + private TNonblockingTransport underlyingTransport; + + // APIs for intercepting event / customizing behaviors: + // Factories (decorating the base implementations) & EventHandler (intercepting) + private TSaslServerFactory saslServerFactory; + private TSaslProcessorFactory processorFactory; + private TProtocolFactory inputProtocolFactory; + private TProtocolFactory outputProtocolFactory; + private TServerEventHandler eventHandler; + private ServerContext serverContext; + // It turns out the event handler implementation in hive sometimes creates a null ServerContext. + // In order to know whether TServerEventHandler#createContext is called we use such a flag. + private boolean serverContextCreated = false; + + // Wrapper around sasl server + private ServerSaslPeer saslPeer; + + // Sasl negotiation io + private SaslNegotiationFrameReader saslResponse; + private SaslNegotiationFrameWriter saslChallenge; + // IO for request from and response to the socket + private DataFrameReader requestReader; + private DataFrameWriter responseWriter; + // If sasl is negotiated for integrity/confidentiality protection + private boolean dataProtected; + + public NonblockingSaslHandler(SelectionKey selectionKey, TNonblockingTransport underlyingTransport, + TSaslServerFactory saslServerFactory, TSaslProcessorFactory processorFactory, + TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory, + TServerEventHandler eventHandler) { + this.selectionKey = selectionKey; + this.underlyingTransport = underlyingTransport; + this.saslServerFactory = saslServerFactory; + this.processorFactory = processorFactory; + this.inputProtocolFactory = inputProtocolFactory; + this.outputProtocolFactory = outputProtocolFactory; + this.eventHandler = eventHandler; + + saslResponse = new SaslNegotiationFrameReader(); + saslChallenge = new SaslNegotiationFrameWriter(); + requestReader = new DataFrameReader(); + responseWriter = new DataFrameWriter(); + } + + /** + * Get current phase of the state machine. + * + * @return current phase. + */ + public Phase getCurrentPhase() { + return currentPhase; + } + + /** + * Get next phase of the state machine. + * It is different from current phase iff current phase is done (and next phase not yet started). + * + * @return next phase. + */ + public Phase getNextPhase() { + return nextPhase; + } + + /** + * + * @return underlying nonblocking socket + */ + public TNonblockingTransport getUnderlyingTransport() { + return underlyingTransport; + } + + /** + * + * @return SaslServer instance + */ + public SaslServer getSaslServer() { + return saslPeer.getSaslServer(); + } + + /** + * + * @return true if current phase is done. + */ + public boolean isCurrentPhaseDone() { + return currentPhase != nextPhase; + } + + /** + * Run state machine. + * + * @throws IllegalStateException if current state is already done. + */ + public void runCurrentPhase() { + currentPhase.runStateMachine(this); + } + + /** + * When current phase is intrested in read selection, calling this will run the current phase and + * its following phases if the following ones are interested to read, until there is nothing + * available in the underlying transport. + * + * @throws IllegalStateException if is called in an irrelevant phase. + */ + public void handleRead() { + handleOps(INTEREST_READ); + } + + /** + * Similiar to handleRead. But it is for write ops. + * + * @throws IllegalStateException if it is called in an irrelevant phase. + */ + public void handleWrite() { + handleOps(INTEREST_WRITE); + } + + private void handleOps(int interestOps) { + if (currentPhase.selectionInterest != interestOps) { + throw new IllegalStateException("Current phase " + currentPhase + " but got interest " + + interestOps); + } + runCurrentPhase(); + if (isCurrentPhaseDone() && nextPhase.selectionInterest == interestOps) { + stepToNextPhase(); + handleOps(interestOps); + } + } + + /** + * When current phase is finished, it's expected to call this method first before running the + * state machine again. + * By calling this, "next phase" is marked as started (and not done), thus is ready to run. + * + * @throws IllegalArgumentException if current phase is not yet done. + */ + public void stepToNextPhase() { + if (!isCurrentPhaseDone()) { + throw new IllegalArgumentException("Not yet done with current phase: " + currentPhase); + } + LOGGER.debug("Switch phase {} to {}", currentPhase, nextPhase); + switch (nextPhase) { + case INITIIALIIZING: + throw new IllegalStateException("INITIALIZING cannot be the next phase of " + currentPhase); + default: + } + // If next phase's interest is not the same as current, nor the same as the selection key, + // we need to change interest on the selector. + if (!(nextPhase.selectionInterest == currentPhase.selectionInterest || + nextPhase.selectionInterest == selectionKey.interestOps())) { + changeSelectionInterest(nextPhase.selectionInterest); + } + currentPhase = nextPhase; + } + + private void changeSelectionInterest(int selectionInterest) { + selectionKey.interestOps(selectionInterest); + } + + // sasl negotiaion failure handling + private void failSaslNegotiation(TSaslNegotiationException e) { + LOGGER.error("Sasl negotiation failed", e); + String errorMsg = e.getDetails(); + saslChallenge.withHeaderAndPayload(new byte[]{e.getErrorType().code.getValue()}, + errorMsg.getBytes(StandardCharsets.UTF_8)); + nextPhase = Phase.WRITING_FAILURE_MESSAGE; + } + + private void fail(Exception e) { + LOGGER.error("Failed io in " + currentPhase, e); + nextPhase = Phase.CLOSING; + } + + private void failIO(TTransportException e) { + StringBuilder errorMsg = new StringBuilder("IO failure ") + .append(e.getType()) + .append(" in ") + .append(currentPhase); + if (e.getMessage() != null) { + errorMsg.append(": ").append(e.getMessage()); + } + LOGGER.error(errorMsg.toString(), e); + nextPhase = Phase.CLOSING; + } + + // Read handlings + + private void handleInitializing() { + try { + saslResponse.read(underlyingTransport); + if (saslResponse.isComplete()) { + SaslNegotiationHeaderReader startHeader = saslResponse.getHeader(); + if (startHeader.getStatus() != NegotiationStatus.START) { + throw new TInvalidSaslFrameException("Expecting START status but got " + startHeader.getStatus()); + } + String mechanism = new String(saslResponse.getPayload(), StandardCharsets.UTF_8); + saslPeer = saslServerFactory.getSaslPeer(mechanism); + saslResponse.clear(); + nextPhase = Phase.READING_SASL_RESPONSE; + } + } catch (TSaslNegotiationException e) { + failSaslNegotiation(e); + } catch (TTransportException e) { + failIO(e); + } + } + + private void handleReadingSaslResponse() { + try { + saslResponse.read(underlyingTransport); + if (saslResponse.isComplete()) { + nextPhase = Phase.EVALUATING_SASL_RESPONSE; + } + } catch (TSaslNegotiationException e) { + failSaslNegotiation(e); + } catch (TTransportException e) { + failIO(e); + } + } + + private void handleReadingRequest() { + try { + requestReader.read(underlyingTransport); + if (requestReader.isComplete()) { + nextPhase = Phase.PROCESSING; + } + } catch (TTransportException e) { + failIO(e); + } + } + + // Computation executions + + private void executeEvaluatingSaslResponse() { + if (!(saslResponse.getHeader().getStatus() == OK || saslResponse.getHeader().getStatus() == COMPLETE)) { + String error = "Expect status OK or COMPLETE, but got " + saslResponse.getHeader().getStatus(); + failSaslNegotiation(new TSaslNegotiationException(ErrorType.PROTOCOL_ERROR, error)); + return; + } + try { + byte[] response = saslResponse.getPayload(); + saslResponse.clear(); + byte[] newChallenge = saslPeer.evaluate(response); + if (saslPeer.isAuthenticated()) { + dataProtected = saslPeer.isDataProtected(); + saslChallenge.withHeaderAndPayload(new byte[]{COMPLETE.getValue()}, newChallenge); + nextPhase = Phase.WRITING_SUCCESS_MESSAGE; + } else { + saslChallenge.withHeaderAndPayload(new byte[]{OK.getValue()}, newChallenge); + nextPhase = Phase.WRITING_SASL_CHALLENGE; + } + } catch (TSaslNegotiationException e) { + failSaslNegotiation(e); + } + } + + private void executeProcessing() { + try { + byte[] inputPayload = requestReader.getPayload(); + requestReader.clear(); + byte[] rawInput = dataProtected ? saslPeer.unwrap(inputPayload) : inputPayload; + TMemoryTransport memoryTransport = new TMemoryTransport(rawInput); + TProtocol requestProtocol = inputProtocolFactory.getProtocol(memoryTransport); + TProtocol responseProtocol = outputProtocolFactory.getProtocol(memoryTransport); + + if (eventHandler != null) { + if (!serverContextCreated) { + serverContext = eventHandler.createContext(requestProtocol, responseProtocol); + serverContextCreated = true; + } + eventHandler.processContext(serverContext, memoryTransport, memoryTransport); + } + + TProcessor processor = processorFactory.getProcessor(this); + processor.process(requestProtocol, responseProtocol); + TByteArrayOutputStream rawOutput = memoryTransport.getOutput(); + if (rawOutput.len() == 0) { + // This is a oneway request, no response to send back. Waiting for next incoming request. + nextPhase = Phase.READING_REQUEST; + return; + } + if (dataProtected) { + byte[] outputPayload = saslPeer.wrap(rawOutput.get(), 0, rawOutput.len()); + responseWriter.withOnlyPayload(outputPayload); + } else { + responseWriter.withOnlyPayload(rawOutput.get(), 0 ,rawOutput.len()); + } + nextPhase = Phase.WRITING_RESPONSE; + } catch (TTransportException e) { + failIO(e); + } catch (Exception e) { + fail(e); + } + } + + // Write handlings + + private void handleWritingSaslChallenge() { + try { + saslChallenge.write(underlyingTransport); + if (saslChallenge.isComplete()) { + saslChallenge.clear(); + nextPhase = Phase.READING_SASL_RESPONSE; + } + } catch (IOException e) { + fail(e); + } + } + + private void handleWritingSuccessMessage() { + try { + saslChallenge.write(underlyingTransport); + if (saslChallenge.isComplete()) { + LOGGER.debug("Authentication is done."); + saslChallenge = null; + saslResponse = null; + nextPhase = Phase.READING_REQUEST; + } + } catch (IOException e) { + fail(e); + } + } + + private void handleWritingFailureMessage() { + try { + saslChallenge.write(underlyingTransport); + if (saslChallenge.isComplete()) { + nextPhase = Phase.CLOSING; + } + } catch (IOException e) { + fail(e); + } + } + + private void handleWritingResponse() { + try { + responseWriter.write(underlyingTransport); + if (responseWriter.isComplete()) { + responseWriter.clear(); + nextPhase = Phase.READING_REQUEST; + } + } catch (IOException e) { + fail(e); + } + } + + /** + * Release all the resources managed by this state machine (connection, selection and sasl server). + * To avoid being blocked, this should be invoked in the network thread that manages the selector. + */ + public void close() { + underlyingTransport.close(); + selectionKey.cancel(); + if (saslPeer != null) { + saslPeer.dispose(); + } + if (serverContextCreated) { + eventHandler.deleteContext(serverContext, + inputProtocolFactory.getProtocol(underlyingTransport), + outputProtocolFactory.getProtocol(underlyingTransport)); + } + nextPhase = Phase.CLOSED; + currentPhase = Phase.CLOSED; + LOGGER.trace("Connection closed: {}", underlyingTransport); + } + + public enum Phase { + INITIIALIIZING(INTEREST_READ) { + @Override + void unsafeRun(NonblockingSaslHandler statemachine) { + statemachine.handleInitializing(); + } + }, + READING_SASL_RESPONSE(INTEREST_READ) { + @Override + void unsafeRun(NonblockingSaslHandler statemachine) { + statemachine.handleReadingSaslResponse(); + } + }, + EVALUATING_SASL_RESPONSE(INTEREST_NONE) { + @Override + void unsafeRun(NonblockingSaslHandler statemachine) { + statemachine.executeEvaluatingSaslResponse(); + } + }, + WRITING_SASL_CHALLENGE(INTEREST_WRITE) { + @Override + void unsafeRun(NonblockingSaslHandler statemachine) { + statemachine.handleWritingSaslChallenge(); + } + }, + WRITING_SUCCESS_MESSAGE(INTEREST_WRITE) { + @Override + void unsafeRun(NonblockingSaslHandler statemachine) { + statemachine.handleWritingSuccessMessage(); + } + }, + WRITING_FAILURE_MESSAGE(INTEREST_WRITE) { + @Override + void unsafeRun(NonblockingSaslHandler statemachine) { + statemachine.handleWritingFailureMessage(); + } + }, + READING_REQUEST(INTEREST_READ) { + @Override + void unsafeRun(NonblockingSaslHandler statemachine) { + statemachine.handleReadingRequest(); + } + }, + PROCESSING(INTEREST_NONE) { + @Override + void unsafeRun(NonblockingSaslHandler statemachine) { + statemachine.executeProcessing(); + } + }, + WRITING_RESPONSE(INTEREST_WRITE) { + @Override + void unsafeRun(NonblockingSaslHandler statemachine) { + statemachine.handleWritingResponse(); + } + }, + CLOSING(INTEREST_NONE) { + @Override + void unsafeRun(NonblockingSaslHandler statemachine) { + statemachine.close(); + } + }, + CLOSED(INTEREST_NONE) { + @Override + void unsafeRun(NonblockingSaslHandler statemachine) { + // Do nothing. + } + } + ; + + // The interest on the selection key during the phase + private int selectionInterest; + + Phase(int selectionInterest) { + this.selectionInterest = selectionInterest; + } + + /** + * Provide the execution to run for the state machine in current phase. The execution should + * return the next phase after running on the state machine. + * + * @param statemachine The state machine to run. + * @throws IllegalArgumentException if the state machine's current phase is different. + * @throws IllegalStateException if the state machine' current phase is already done. + */ + void runStateMachine(NonblockingSaslHandler statemachine) { + if (statemachine.currentPhase != this) { + throw new IllegalArgumentException("State machine is " + statemachine.currentPhase + + " but is expected to be " + this); + } + if (statemachine.isCurrentPhaseDone()) { + throw new IllegalStateException("State machine should step into " + statemachine.nextPhase); + } + unsafeRun(statemachine); + } + + // Run the state machine without checkiing its own phase + // It should not be called direcly by users. + abstract void unsafeRun(NonblockingSaslHandler statemachine); + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationFrameReader.java b/lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationFrameReader.java new file mode 100644 index 00000000000..01c17283697 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationFrameReader.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 org.apache.thrift.transport.sasl; + +/** + * Read frames for sasl negotiatiions. + */ +public class SaslNegotiationFrameReader extends FrameReader { + + public SaslNegotiationFrameReader() { + super(new SaslNegotiationHeaderReader()); + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationFrameWriter.java b/lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationFrameWriter.java new file mode 100644 index 00000000000..1e9ad1570f9 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationFrameWriter.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 org.apache.thrift.transport.sasl; + +import java.nio.ByteBuffer; + +import org.apache.thrift.EncodingUtils; +import org.apache.thrift.utils.StringUtils; + +import static org.apache.thrift.transport.sasl.SaslNegotiationHeaderReader.PAYLOAD_LENGTH_BYTES; +import static org.apache.thrift.transport.sasl.SaslNegotiationHeaderReader.STATUS_BYTES; + +/** + * Writer for sasl negotiation frames. It expect a status byte as header with a payload to be + * written out (any header whose size is not equal to 1 would be considered as error). + */ +public class SaslNegotiationFrameWriter extends FrameWriter { + + public static final int HEADER_BYTES = STATUS_BYTES + PAYLOAD_LENGTH_BYTES; + + @Override + public void withOnlyPayload(byte[] payload, int offset, int length) { + throw new UnsupportedOperationException("Status byte is expected for sasl frame header."); + } + + @Override + protected ByteBuffer buildFrame(byte[] header, int headerOffset, int headerLength, + byte[] payload, int payloadOffset, int payloadLength) { + if (header == null || headerLength != STATUS_BYTES) { + throw new IllegalArgumentException("Header " + StringUtils.bytesToHexString(header) + + " does not have expected length " + STATUS_BYTES); + } + byte[] bytes = new byte[HEADER_BYTES + payloadLength]; + System.arraycopy(header, headerOffset, bytes, 0, STATUS_BYTES); + EncodingUtils.encodeBigEndian(payloadLength, bytes, STATUS_BYTES); + System.arraycopy(payload, payloadOffset, bytes, HEADER_BYTES, payloadLength); + return ByteBuffer.wrap(bytes); + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationHeaderReader.java b/lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationHeaderReader.java new file mode 100644 index 00000000000..2d76ddb2998 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/SaslNegotiationHeaderReader.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 org.apache.thrift.transport.sasl; + +import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.PROTOCOL_ERROR; + +/** + * Header for sasl negotiation frames. It contains status byte of negotiation and a 4-byte integer + * (payload size). + */ +public class SaslNegotiationHeaderReader extends FixedSizeHeaderReader { + public static final int STATUS_BYTES = 1; + public static final int PAYLOAD_LENGTH_BYTES = 4; + + private NegotiationStatus negotiationStatus; + private int payloadSize; + + @Override + protected int headerSize() { + return STATUS_BYTES + PAYLOAD_LENGTH_BYTES; + } + + @Override + protected void onComplete() throws TSaslNegotiationException { + negotiationStatus = NegotiationStatus.byValue(byteBuffer.get(0)); + payloadSize = byteBuffer.getInt(1); + if (payloadSize < 0) { + throw new TSaslNegotiationException(PROTOCOL_ERROR, "Payload size is negative: " + payloadSize); + } + } + + @Override + public int payloadSize() { + return payloadSize; + } + + public NegotiationStatus getStatus() { + return negotiationStatus; + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/SaslPeer.java b/lib/java/src/org/apache/thrift/transport/sasl/SaslPeer.java new file mode 100644 index 00000000000..8f81380441c --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/SaslPeer.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift.transport.sasl; + +import org.apache.thrift.transport.TTransportException; + +/** + * A peer in a sasl negotiation. + */ +public interface SaslPeer { + + /** + * Evaluate and validate the negotiation message (response/challenge) received from peer. + * + * @param negotiationMessage response/challenge received from peer. + * @return new response/challenge to send to peer, can be null if authentication becomes success. + * @throws TSaslNegotiationException if sasl authentication fails. + */ + byte[] evaluate(byte[] negotiationMessage) throws TSaslNegotiationException; + + /** + * @return true if authentication is done. + */ + boolean isAuthenticated(); + + /** + * This method can only be called when the negotiation is complete (isAuthenticated returns true). + * Otherwise it will throw IllegalStateExceptiion. + * + * @return if the qop requires some integrity/confidential protection. + * @throws IllegalStateException if negotiation is not yet complete. + */ + boolean isDataProtected(); + + /** + * Wrap raw bytes to protect it. + * + * @param data raw bytes. + * @param offset the start position of the content to wrap. + * @param length the length of the content to wrap. + * @return bytes with protection to send to peer. + * @throws TTransportException if failure. + */ + byte[] wrap(byte[] data, int offset, int length) throws TTransportException; + + /** + * Wrap the whole byte array. + * + * @param data raw bytes. + * @return wrapped bytes. + * @throws TTransportException if failure. + */ + default byte[] wrap(byte[] data) throws TTransportException { + return wrap(data, 0, data.length); + } + + /** + * Unwrap protected data to raw bytes. + * + * @param data protected data received from peer. + * @param offset the start position of the content to unwrap. + * @param length the length of the content to unwrap. + * @return raw bytes. + * @throws TTransportException if failed. + */ + byte[] unwrap(byte[] data, int offset, int length) throws TTransportException; + + /** + * Unwrap the whole byte array. + * + * @param data wrapped bytes. + * @return raw bytes. + * @throws TTransportException if failure. + */ + default byte[] unwrap(byte[] data) throws TTransportException { + return unwrap(data, 0, data.length); + } + + /** + * Close this peer and release resources. + */ + void dispose(); +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/ServerSaslPeer.java b/lib/java/src/org/apache/thrift/transport/sasl/ServerSaslPeer.java new file mode 100644 index 00000000000..31992e5fc47 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/ServerSaslPeer.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift.transport.sasl; + +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import org.apache.thrift.transport.TTransportException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.AUTHENTICATION_FAILURE; + +/** + * Server side sasl peer, a wrapper around SaslServer to provide some handy methods. + */ +public class ServerSaslPeer implements SaslPeer { + private static final Logger LOGGER = LoggerFactory.getLogger(ServerSaslPeer.class); + + private static final String QOP_AUTH_INT = "auth-int"; + private static final String QOP_AUTH_CONF = "auth-conf"; + + private final SaslServer saslServer; + + public ServerSaslPeer(SaslServer saslServer) { + this.saslServer = saslServer; + } + + @Override + public byte[] evaluate(byte[] negotiationMessage) throws TSaslNegotiationException { + try { + return saslServer.evaluateResponse(negotiationMessage); + } catch (SaslException e) { + throw new TSaslNegotiationException(AUTHENTICATION_FAILURE, + "Authentication failed with " + saslServer.getMechanismName(), e); + } + } + + @Override + public boolean isAuthenticated() { + return saslServer.isComplete(); + } + + @Override + public boolean isDataProtected() { + Object qop = saslServer.getNegotiatedProperty(Sasl.QOP); + if (qop == null) { + return false; + } + for (String word : qop.toString().split("\\s*,\\s*")) { + String lowerCaseWord = word.toLowerCase(); + if (QOP_AUTH_INT.equals(lowerCaseWord) || QOP_AUTH_CONF.equals(lowerCaseWord)) { + return true; + } + } + return false; + } + + @Override + public byte[] wrap(byte[] data, int offset, int length) throws TTransportException { + try { + return saslServer.wrap(data, offset, length); + } catch (SaslException e) { + throw new TTransportException("Failed to wrap data", e); + } + } + + @Override + public byte[] unwrap(byte[] data, int offset, int length) throws TTransportException { + try { + return saslServer.unwrap(data, offset, length); + } catch (SaslException e) { + throw new TTransportException(TTransportException.CORRUPTED_DATA, "Failed to unwrap data", e); + } + } + + @Override + public void dispose() { + try { + saslServer.dispose(); + } catch (Exception e) { + LOGGER.warn("Failed to close sasl server " + saslServer.getMechanismName(), e); + } + } + + SaslServer getSaslServer() { + return saslServer; + } + +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/TBaseSaslProcessorFactory.java b/lib/java/src/org/apache/thrift/transport/sasl/TBaseSaslProcessorFactory.java new file mode 100644 index 00000000000..c08884c22ea --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/TBaseSaslProcessorFactory.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 org.apache.thrift.transport.sasl; + +import org.apache.thrift.TProcessor; + +public class TBaseSaslProcessorFactory implements TSaslProcessorFactory { + + private final TProcessor processor; + + public TBaseSaslProcessorFactory(TProcessor processor) { + this.processor = processor; + } + + @Override + public TProcessor getProcessor(NonblockingSaslHandler saslHandler) { + return processor; + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/TInvalidSaslFrameException.java b/lib/java/src/org/apache/thrift/transport/sasl/TInvalidSaslFrameException.java new file mode 100644 index 00000000000..ff57ea5c435 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/TInvalidSaslFrameException.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 org.apache.thrift.transport.sasl; + +/** + * Got an invalid frame that does not respect the thrift sasl protocol. + */ +public class TInvalidSaslFrameException extends TSaslNegotiationException { + + public TInvalidSaslFrameException(String message) { + super(ErrorType.PROTOCOL_ERROR, message); + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/TSaslNegotiationException.java b/lib/java/src/org/apache/thrift/transport/sasl/TSaslNegotiationException.java new file mode 100644 index 00000000000..9b1fa060ed5 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/TSaslNegotiationException.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 org.apache.thrift.transport.sasl; + +import org.apache.thrift.transport.TTransportException; + +/** + * Exception for sasl negotiation errors. + */ +public class TSaslNegotiationException extends TTransportException { + + private final ErrorType error; + + public TSaslNegotiationException(ErrorType error, String summary) { + super(summary); + this.error = error; + } + + public TSaslNegotiationException(ErrorType error, String summary, Throwable cause) { + super(summary, cause); + this.error = error; + } + + public ErrorType getErrorType() { + return error; + } + + /** + * @return Errory type plus the message. + */ + public String getSummary() { + return error.name() + ": " + getMessage(); + } + + /** + * @return Summary and eventually the cause's message. + */ + public String getDetails() { + return getCause() == null ? getSummary() : getSummary() + "\nReason: " + getCause().getMessage(); + } + + public enum ErrorType { + // Unexpected system internal error during negotiation (e.g. sasl initialization failure) + INTERNAL_ERROR(NegotiationStatus.ERROR), + // Cannot read correct sasl frames from the connection => Send "ERROR" status byte to peer + PROTOCOL_ERROR(NegotiationStatus.ERROR), + // Peer is using unsupported sasl mechanisms => Send "BAD" status byte to peer + MECHANISME_MISMATCH(NegotiationStatus.BAD), + // Sasl authentication failure => Send "BAD" status byte to peer + AUTHENTICATION_FAILURE(NegotiationStatus.BAD), + ; + + public final NegotiationStatus code; + + ErrorType(NegotiationStatus code) { + this.code = code; + } + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/TSaslProcessorFactory.java b/lib/java/src/org/apache/thrift/transport/sasl/TSaslProcessorFactory.java new file mode 100644 index 00000000000..877d0496f2a --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/TSaslProcessorFactory.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 org.apache.thrift.transport.sasl; + +import org.apache.thrift.TException; +import org.apache.thrift.TProcessor; + +/** + * Get processor for a given state machine, so that users can customize the behavior of a TProcessor + * by interacting with the state machine. + */ +public interface TSaslProcessorFactory { + + TProcessor getProcessor(NonblockingSaslHandler saslHandler) throws TException; +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/TSaslServerDefinition.java b/lib/java/src/org/apache/thrift/transport/sasl/TSaslServerDefinition.java new file mode 100644 index 00000000000..5486641d8e7 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/TSaslServerDefinition.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 org.apache.thrift.transport.sasl; + +import javax.security.auth.callback.CallbackHandler; +import java.util.Map; + +/** + * Contains all the parameters used to define a SASL server implementation. + */ +public class TSaslServerDefinition { + public final String mechanism; + public final String protocol; + public final String serverName; + public final Map props; + public final 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; + } +} diff --git a/lib/java/src/org/apache/thrift/transport/sasl/TSaslServerFactory.java b/lib/java/src/org/apache/thrift/transport/sasl/TSaslServerFactory.java new file mode 100644 index 00000000000..06cf534b610 --- /dev/null +++ b/lib/java/src/org/apache/thrift/transport/sasl/TSaslServerFactory.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.thrift.transport.sasl; + +import java.util.HashMap; +import java.util.Map; + +import javax.security.auth.callback.CallbackHandler; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + +import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.MECHANISME_MISMATCH; +import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.PROTOCOL_ERROR; + +/** + * Factory to create sasl server. Users can extend this class to customize the SaslServer creation. + */ +public class TSaslServerFactory { + + private final Map saslMechanisms; + + public TSaslServerFactory() { + this.saslMechanisms = new HashMap<>(); + } + + public void addSaslMechanism(String mechanism, String protocol, String serverName, + Map props, CallbackHandler cbh) { + TSaslServerDefinition definition = new TSaslServerDefinition(mechanism, protocol, serverName, + props, cbh); + saslMechanisms.put(definition.mechanism, definition); + } + + public ServerSaslPeer getSaslPeer(String mechanism) throws TSaslNegotiationException { + if (!saslMechanisms.containsKey(mechanism)) { + throw new TSaslNegotiationException(MECHANISME_MISMATCH, "Unsupported mechanism " + mechanism); + } + TSaslServerDefinition saslDef = saslMechanisms.get(mechanism); + try { + SaslServer saslServer = Sasl.createSaslServer(saslDef.mechanism, saslDef.protocol, + saslDef.serverName, saslDef.props, saslDef.cbh); + return new ServerSaslPeer(saslServer); + } catch (SaslException e) { + throw new TSaslNegotiationException(PROTOCOL_ERROR, "Fail to create sasl server " + mechanism, e); + } + } +} diff --git a/lib/java/src/org/apache/thrift/utils/StringUtils.java b/lib/java/src/org/apache/thrift/utils/StringUtils.java new file mode 100644 index 00000000000..15183a36a09 --- /dev/null +++ b/lib/java/src/org/apache/thrift/utils/StringUtils.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 org.apache.thrift.utils; + +public final class StringUtils { + + private StringUtils() { + // Utility class. + } + + private static final char[] HEX_CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + + /** + * Stringify a byte array to the hex representation for each byte. + * + * @param bytes + * @return hex string. + */ + public static String bytesToHexString(byte[] bytes) { + if (bytes == null) { + return null; + } + return bytesToHexString(bytes, 0, bytes.length); + } + + /** + * Stringify a portion of the byte array. + * + * @param bytes byte array. + * @param offset portion start. + * @param length portion length. + * @return hex string. + */ + public static String bytesToHexString(byte[] bytes, int offset, int length) { + if (length < 0) { + throw new IllegalArgumentException("Negative length " + length); + } + if (offset < 0) { + throw new IndexOutOfBoundsException("Negative start offset " + offset); + } + char[] chars = new char[length * 2]; + for (int i = 0; i < length; i++) { + int unsignedInt = bytes[i + offset] & 0xFF; + chars[2 * i] = HEX_CHARS[unsignedInt >>> 4]; + chars[2 * i + 1] = HEX_CHARS[unsignedInt & 0x0F]; + } + return new String(chars); + } +} diff --git a/lib/java/test/org/apache/thrift/server/TestSaslNonblockingServer.java b/lib/java/test/org/apache/thrift/server/TestSaslNonblockingServer.java new file mode 100644 index 00000000000..d0a674674c8 --- /dev/null +++ b/lib/java/test/org/apache/thrift/server/TestSaslNonblockingServer.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 org.apache.thrift.server; + +import org.apache.thrift.TProcessor; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TProtocolFactory; +import org.apache.thrift.transport.TNonblockingServerSocket; +import org.apache.thrift.transport.TNonblockingServerTransport; +import org.apache.thrift.transport.TSaslClientTransport; +import org.apache.thrift.transport.TSocket; +import org.apache.thrift.transport.TTransportException; +import org.apache.thrift.transport.TTransportFactory; +import org.apache.thrift.transport.TestTSaslTransports; +import org.apache.thrift.transport.TestTSaslTransports.TestSaslCallbackHandler; +import org.apache.thrift.transport.sasl.TSaslNegotiationException; +import thrift.test.ThriftTest; + +import static org.apache.thrift.transport.sasl.TSaslNegotiationException.ErrorType.AUTHENTICATION_FAILURE; + +public class TestSaslNonblockingServer extends TestTSaslTransports.TestTSaslTransportsWithServer { + + private TSaslNonblockingServer server; + + @Override + public void startServer(TProcessor processor, TProtocolFactory protoFactory, TTransportFactory factory) + throws Exception { + TNonblockingServerTransport serverSocket = new TNonblockingServerSocket( + new TNonblockingServerSocket.NonblockingAbstractServerSocketArgs().port(PORT)); + TSaslNonblockingServer.Args args = new TSaslNonblockingServer.Args(serverSocket) + .processor(processor) + .transportFactory(factory) + .protocolFactory(protoFactory) + .addSaslMechanism(TestTSaslTransports.WRAPPED_MECHANISM, TestTSaslTransports.SERVICE, + TestTSaslTransports.HOST, TestTSaslTransports.WRAPPED_PROPS, + new TestSaslCallbackHandler(TestTSaslTransports.PASSWORD)); + server = new TSaslNonblockingServer(args); + server.serve(); + } + + @Override + public void stopServer() throws Exception { + server.shutdown(); + } + + @Override + public void testIt() throws Exception { + super.testIt(); + } + + public void testBadPassword() throws Exception { + TProtocolFactory protocolFactory = new TBinaryProtocol.Factory(); + TProcessor processor = new ThriftTest.Processor<>(new TestHandler()); + startServer(processor, protocolFactory); + + TSocket socket = new TSocket(HOST, PORT); + socket.setTimeout(SOCKET_TIMEOUT); + TSaslClientTransport client = new TSaslClientTransport(TestTSaslTransports.WRAPPED_MECHANISM, + TestTSaslTransports.PRINCIPAL, TestTSaslTransports.SERVICE, TestTSaslTransports.HOST, + TestTSaslTransports.WRAPPED_PROPS, new TestSaslCallbackHandler("bad_password"), socket); + try { + client.open(); + fail("Client should fail with sasl negotiation."); + } catch (TTransportException error) { + TSaslNegotiationException serverSideError = new TSaslNegotiationException(AUTHENTICATION_FAILURE, + "Authentication failed with " + TestTSaslTransports.WRAPPED_MECHANISM); + assertTrue("Server should return error message \"" + serverSideError.getSummary() + "\"", + error.getMessage().contains(serverSideError.getSummary())); + } finally { + stopServer(); + client.close(); + } + } + + @Override + public void testTransportFactory() { + // This test is irrelevant here, so skipped. + } +} diff --git a/lib/java/test/org/apache/thrift/transport/TestNonblockingServerSocket.java b/lib/java/test/org/apache/thrift/transport/TestNonblockingServerSocket.java new file mode 100644 index 00000000000..6b28dfd51af --- /dev/null +++ b/lib/java/test/org/apache/thrift/transport/TestNonblockingServerSocket.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 org.apache.thrift.transport; + +import org.junit.Assert; +import org.junit.Test; + +import java.nio.channels.ServerSocketChannel; + +public class TestNonblockingServerSocket { + + @Test + public void testSocketChannelBlockingMode() throws TTransportException { + try (TNonblockingServerSocket nonblockingServer = new TNonblockingServerSocket(0)){ + ServerSocketChannel socketChannel = nonblockingServer.getServerSocketChannel(); + Assert.assertFalse("Socket channel should be nonblocking", socketChannel.isBlocking()); + } + } +} diff --git a/lib/java/test/org/apache/thrift/transport/TestTMemoryTransport.java b/lib/java/test/org/apache/thrift/transport/TestTMemoryTransport.java new file mode 100644 index 00000000000..2e20ffea7b1 --- /dev/null +++ b/lib/java/test/org/apache/thrift/transport/TestTMemoryTransport.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.thrift.transport; + +import org.apache.thrift.TByteArrayOutputStream; +import org.junit.Assert; +import org.junit.Test; + +import java.nio.ByteBuffer; +import java.util.Random; + +public class TestTMemoryTransport { + + @Test + public void testReadBatches() throws TTransportException { + byte[] inputBytes = {0x10, 0x7A, (byte) 0xBF, (byte) 0xFE, 0x53, (byte) 0x82, (byte) 0xFF}; + TMemoryTransport transport = new TMemoryTransport(inputBytes); + byte[] read = new byte[inputBytes.length]; + int firstBatch = new Random().nextInt(inputBytes.length); + int secondBatch = inputBytes.length - firstBatch; + transport.read(read, 0, firstBatch); + transport.read(read, firstBatch, secondBatch); + boolean equal = true; + for (int i = 0; i < inputBytes.length; i++) { + equal = equal && inputBytes[i] == read[i]; + } + Assert.assertEquals(ByteBuffer.wrap(inputBytes), ByteBuffer.wrap(read)); + } + + @Test (expected = TTransportException.class) + public void testReadMoreThanRemaining() throws TTransportException { + TMemoryTransport transport = new TMemoryTransport(new byte[] {0x00, 0x32}); + byte[] read = new byte[3]; + transport.read(read, 0, 3); + } + + @Test + public void testWrite() throws TTransportException { + TMemoryTransport transport = new TMemoryTransport(new byte[0]); + byte[] output1 = {0x72, 0x56, 0x29, (byte) 0xAF, (byte) 0x9B}; + transport.write(output1); + byte[] output2 = {(byte) 0x83, 0x10, 0x00}; + transport.write(output2, 0, 2); + byte[] expected = {0x72, 0x56, 0x29, (byte) 0xAF, (byte) 0x9B, (byte) 0x83, 0x10}; + TByteArrayOutputStream outputByteArray = transport.getOutput(); + Assert.assertEquals(ByteBuffer.wrap(expected), ByteBuffer.wrap(outputByteArray.get(), 0, outputByteArray.len())); + } +} diff --git a/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java b/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java index 36a06e9e5aa..6eb38e7cc3e 100644 --- a/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java +++ b/lib/java/test/org/apache/thrift/transport/TestTSaslTransports.java @@ -53,17 +53,17 @@ public class TestTSaslTransports extends TestCase { private static final Logger LOGGER = LoggerFactory.getLogger(TestTSaslTransports.class); - private static final String HOST = "localhost"; - private static final String SERVICE = "thrift-test"; - private static final String PRINCIPAL = "thrift-test-principal"; - private static final String PASSWORD = "super secret password"; - private static final String REALM = "thrift-test-realm"; + public static final String HOST = "localhost"; + public static final String SERVICE = "thrift-test"; + public static final String PRINCIPAL = "thrift-test-principal"; + public static final String PASSWORD = "super secret password"; + public static final String REALM = "thrift-test-realm"; - private static final String UNWRAPPED_MECHANISM = "CRAM-MD5"; - private static final Map UNWRAPPED_PROPS = null; + public static final String UNWRAPPED_MECHANISM = "CRAM-MD5"; + public static final Map UNWRAPPED_PROPS = null; - private static final String WRAPPED_MECHANISM = "DIGEST-MD5"; - private static final Map WRAPPED_PROPS = new HashMap(); + public static final String WRAPPED_MECHANISM = "DIGEST-MD5"; + public static final Map WRAPPED_PROPS = new HashMap(); static { WRAPPED_PROPS.put(Sasl.QOP, "auth-int"); @@ -80,7 +80,7 @@ public class TestTSaslTransports extends TestCase { + "'We hold these truths to be self-evident, that all men are created equal.'"; - private static class TestSaslCallbackHandler implements CallbackHandler { + public static class TestSaslCallbackHandler implements CallbackHandler { private final String password; public TestSaslCallbackHandler(String password) { @@ -265,7 +265,7 @@ public void testWithServer() throws Exception { new TestTSaslTransportsWithServer().testIt(); } - private static class TestTSaslTransportsWithServer extends ServerTestBase { + public static class TestTSaslTransportsWithServer extends ServerTestBase { private Thread serverThread; private TServer server; diff --git a/lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameReader.java b/lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameReader.java new file mode 100644 index 00000000000..9ae0e1ead0d --- /dev/null +++ b/lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameReader.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 org.apache.thrift.transport.sasl; + +import org.apache.thrift.transport.TMemoryInputTransport; +import org.apache.thrift.transport.TTransportException; +import org.junit.Assert; +import org.junit.Test; + +import java.nio.ByteBuffer; + +public class TestDataFrameReader { + + @Test + public void testRead() throws TTransportException { + // Prepare data + int payloadSize = 23; + ByteBuffer buffer = ByteBuffer.allocate(DataFrameHeaderReader.PAYLOAD_LENGTH_BYTES + payloadSize); + buffer.putInt(payloadSize); + for (int i = 0; i < payloadSize; i++) { + buffer.put((byte) i); + } + buffer.rewind(); + + TMemoryInputTransport transport = new TMemoryInputTransport(); + DataFrameReader dataFrameReader = new DataFrameReader(); + // No bytes received. + dataFrameReader.read(transport); + Assert.assertFalse("No bytes received", dataFrameReader.isComplete()); + Assert.assertFalse("No bytes received", dataFrameReader.getHeader().isComplete()); + // Payload size (header) and part of the payload are received. + transport.reset(buffer.array(), 0, 6); + dataFrameReader.read(transport); + Assert.assertFalse("Only header is complete", dataFrameReader.isComplete()); + Assert.assertTrue("Header should be complete", dataFrameReader.getHeader().isComplete()); + Assert.assertEquals("Payload size should be " + payloadSize, payloadSize, dataFrameReader.getHeader().payloadSize()); + // Read the rest of payload. + transport.reset(buffer.array(), 6, 21); + dataFrameReader.read(transport); + Assert.assertTrue("Reader should be complete", dataFrameReader.isComplete()); + buffer.position(DataFrameHeaderReader.PAYLOAD_LENGTH_BYTES); + Assert.assertEquals("Payload should be the same as from the transport", buffer, ByteBuffer.wrap(dataFrameReader.getPayload())); + } +} diff --git a/lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameWriter.java b/lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameWriter.java new file mode 100644 index 00000000000..d2425939f29 --- /dev/null +++ b/lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameWriter.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.thrift.transport.sasl; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import org.apache.thrift.EncodingUtils; +import org.apache.thrift.transport.TNonblockingTransport; +import org.junit.Assert; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import static org.apache.thrift.transport.sasl.DataFrameHeaderReader.PAYLOAD_LENGTH_BYTES; + +public class TestDataFrameWriter { + + private static final byte[] BYTES = new byte[]{0x32, 0x2A, (byte) 0xE1, 0x18, (byte) 0x90, 0x75}; + + @Test + public void testProvideEntireByteArrayAsPayload() { + DataFrameWriter frameWriter = new DataFrameWriter(); + frameWriter.withOnlyPayload(BYTES); + byte[] expectedBytes = new byte[BYTES.length + PAYLOAD_LENGTH_BYTES]; + EncodingUtils.encodeBigEndian(BYTES.length, expectedBytes); + System.arraycopy(BYTES, 0, expectedBytes, PAYLOAD_LENGTH_BYTES, BYTES.length); + Assert.assertEquals(ByteBuffer.wrap(expectedBytes), frameWriter.frameBytes); + } + + @Test + public void testProvideByteArrayPortionAsPayload() { + DataFrameWriter frameWriter = new DataFrameWriter(); + int portionOffset = 2; + int portionLength = 3; + frameWriter.withOnlyPayload(BYTES, portionOffset, portionLength); + byte[] expectedBytes = new byte[portionLength + PAYLOAD_LENGTH_BYTES]; + EncodingUtils.encodeBigEndian(portionLength, expectedBytes); + System.arraycopy(BYTES, portionOffset, expectedBytes, PAYLOAD_LENGTH_BYTES, portionLength); + Assert.assertEquals(ByteBuffer.wrap(expectedBytes), frameWriter.frameBytes); + } + + @Test(expected = IllegalArgumentException.class) + public void testProvideHeaderAndPayload() { + DataFrameWriter frameWriter = new DataFrameWriter(); + frameWriter.withHeaderAndPayload(new byte[1], new byte[1]); + } + + @Test(expected = IllegalStateException.class) + public void testProvidePayloadToIncompleteFrame() { + DataFrameWriter frameWriter = new DataFrameWriter(); + frameWriter.withOnlyPayload(BYTES); + frameWriter.withOnlyPayload(new byte[1]); + } + + @Test + public void testWrite() throws IOException { + DataFrameWriter frameWriter = new DataFrameWriter(); + frameWriter.withOnlyPayload(BYTES); + // Slow socket which writes one byte per call. + TNonblockingTransport transport = Mockito.mock(TNonblockingTransport.class); + SlowWriting slowWriting = new SlowWriting(); + Mockito.when(transport.write(frameWriter.frameBytes)).thenAnswer(slowWriting); + frameWriter.write(transport); + while (slowWriting.written < frameWriter.frameBytes.limit()) { + Assert.assertFalse("Frame writer should not be complete", frameWriter.isComplete()); + frameWriter.write(transport); + } + Assert.assertTrue("Frame writer should be complete", frameWriter.isComplete()); + } + + private static class SlowWriting implements Answer { + int written = 0; + + @Override + public Integer answer(InvocationOnMock invocation) throws Throwable { + ByteBuffer bytes = (ByteBuffer) invocation.getArguments()[0]; + bytes.get(); + written ++; + return 1; + } + } +} diff --git a/lib/java/test/org/apache/thrift/transport/sasl/TestSaslNegotiationFrameReader.java b/lib/java/test/org/apache/thrift/transport/sasl/TestSaslNegotiationFrameReader.java new file mode 100644 index 00000000000..f2abbe65877 --- /dev/null +++ b/lib/java/test/org/apache/thrift/transport/sasl/TestSaslNegotiationFrameReader.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.thrift.transport.sasl; + +import org.apache.thrift.transport.TMemoryInputTransport; +import org.apache.thrift.transport.TTransportException; +import org.junit.Assert; +import org.junit.Test; + +import java.nio.ByteBuffer; + +public class TestSaslNegotiationFrameReader { + + @Test + public void testRead() throws TTransportException { + TMemoryInputTransport transport = new TMemoryInputTransport(); + SaslNegotiationFrameReader negotiationReader = new SaslNegotiationFrameReader(); + // No bytes received + negotiationReader.read(transport); + Assert.assertFalse("No bytes received", negotiationReader.isComplete()); + Assert.assertFalse("No bytes received", negotiationReader.getHeader().isComplete()); + // Read header + ByteBuffer buffer = ByteBuffer.allocate(5); + buffer.put(0, NegotiationStatus.OK.getValue()); + buffer.putInt(1, 10); + transport.reset(buffer.array()); + negotiationReader.read(transport); + Assert.assertFalse("Only header is complete", negotiationReader.isComplete()); + Assert.assertTrue("Header should be complete", negotiationReader.getHeader().isComplete()); + Assert.assertEquals("Payload size should be 10", 10, negotiationReader.getHeader().payloadSize()); + // Read payload + transport.reset(new byte[20]); + negotiationReader.read(transport); + Assert.assertTrue("Reader should be complete", negotiationReader.isComplete()); + Assert.assertEquals("Payload length should be 10", 10, negotiationReader.getPayload().length); + } + + @Test (expected = TSaslNegotiationException.class) + public void testReadInvalidNegotiationStatus() throws TTransportException { + byte[] bytes = new byte[5]; + // Invalid status byte. + bytes[0] = -1; + TMemoryInputTransport transport = new TMemoryInputTransport(bytes); + SaslNegotiationFrameReader negotiationReader = new SaslNegotiationFrameReader(); + negotiationReader.read(transport); + } +} diff --git a/lib/java/test/org/apache/thrift/transport/sasl/TestSaslNegotiationFrameWriter.java b/lib/java/test/org/apache/thrift/transport/sasl/TestSaslNegotiationFrameWriter.java new file mode 100644 index 00000000000..ce7ff295c30 --- /dev/null +++ b/lib/java/test/org/apache/thrift/transport/sasl/TestSaslNegotiationFrameWriter.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 org.apache.thrift.transport.sasl; + +import java.nio.ByteBuffer; + +import org.apache.thrift.EncodingUtils; +import org.junit.Assert; +import org.junit.Test; + +import static org.apache.thrift.transport.sasl.SaslNegotiationFrameWriter.HEADER_BYTES; + +public class TestSaslNegotiationFrameWriter { + + private static final byte[] PAYLOAD = {0x11, 0x08, 0x3F, 0x58, 0x73, 0x22, 0x00, (byte) 0xFF}; + + @Test + public void testWithHeaderAndPayload() { + SaslNegotiationFrameWriter frameWriter = new SaslNegotiationFrameWriter(); + frameWriter.withHeaderAndPayload(new byte[] {NegotiationStatus.OK.getValue()}, PAYLOAD); + byte[] expectedBytes = new byte[HEADER_BYTES + PAYLOAD.length]; + expectedBytes[0] = NegotiationStatus.OK.getValue(); + EncodingUtils.encodeBigEndian(PAYLOAD.length, expectedBytes, 1); + System.arraycopy(PAYLOAD, 0, expectedBytes, HEADER_BYTES, PAYLOAD.length); + Assert.assertEquals(ByteBuffer.wrap(expectedBytes), frameWriter.frameBytes); + } + + @Test(expected = IllegalArgumentException.class) + public void testWithInvalidHeaderLength() { + SaslNegotiationFrameWriter frameWriter = new SaslNegotiationFrameWriter(); + frameWriter.withHeaderAndPayload(new byte[5], 0, 2, PAYLOAD, 0, 1); + } + + @Test(expected = UnsupportedOperationException.class) + public void testWithOnlyPayload() { + SaslNegotiationFrameWriter frameWriter = new SaslNegotiationFrameWriter(); + frameWriter.withOnlyPayload(new byte[0]); + } +} diff --git a/lib/java/test/org/apache/thrift/utils/TestStringUtils.java b/lib/java/test/org/apache/thrift/utils/TestStringUtils.java new file mode 100644 index 00000000000..3a8cf39ee07 --- /dev/null +++ b/lib/java/test/org/apache/thrift/utils/TestStringUtils.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 org.apache.thrift.utils; + +import org.junit.Assert; +import org.junit.Test; + +public class TestStringUtils { + + @Test + public void testToHexString() { + byte[] bytes = {0x00, 0x1A, (byte) 0xEF, (byte) 0xAB, (byte) 0x92}; + Assert.assertEquals("001AEFAB92", StringUtils.bytesToHexString(bytes)); + Assert.assertEquals("EFAB92", StringUtils.bytesToHexString(bytes, 2, 3)); + Assert.assertNull(StringUtils.bytesToHexString(null)); + } +} From 9320f891d7d972fc2cc4f9569b66767c5dfc4242 Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Wed, 11 Dec 2019 16:51:12 -0500 Subject: [PATCH 462/756] Revert "Revert "Remove unnecessary TException.message hack"" This reverts commit 3d9f50d61728d377951f9b6df5f19196f6b3af46. --- lib/py/src/Thrift.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/lib/py/src/Thrift.py b/lib/py/src/Thrift.py index c390cbb54c1..ef655ea5579 100644 --- a/lib/py/src/Thrift.py +++ b/lib/py/src/Thrift.py @@ -17,8 +17,6 @@ # under the License. # -import sys - class TType(object): STOP = 0 @@ -90,15 +88,6 @@ def on_message_begin(self, func): class TException(Exception): """Base class for all thrift exceptions.""" - # BaseException.message is deprecated in Python v[2.6,3.0) - if (2, 6, 0) <= sys.version_info < (3, 0): - def _get_message(self): - return self._message - - def _set_message(self, message): - self._message = message - message = property(_get_message, _set_message) - def __init__(self, message=None): Exception.__init__(self, message) self.message = message From 9c43962da8e4b530014619e3703a279053cf2182 Mon Sep 17 00:00:00 2001 From: Elvis Pranskevichus Date: Wed, 11 Dec 2019 16:47:52 -0500 Subject: [PATCH 463/756] Revert "Revert "THRIFT-4002: Make generated exception classes immutable by default"" This reverts commit 1234ddf8a5c98d5d700c82e087f04725170ad581. --- .../cpp/src/thrift/generate/t_py_generator.cc | 27 ++++++++++++++++--- lib/py/src/protocol/TBase.py | 4 +++ lib/py/src/protocol/TProtocol.py | 10 +++++-- test/DebugProtoTest.thrift | 4 +++ test/py.tornado/test_suite.py | 5 +--- test/py.twisted/test_suite.py | 5 +--- test/py/TestFrozen.py | 17 ++++++++++++ 7 files changed, 59 insertions(+), 13 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_py_generator.cc b/compiler/cpp/src/thrift/generate/t_py_generator.cc index 982bca14547..e93bbe17dcc 100644 --- a/compiler/cpp/src/thrift/generate/t_py_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_py_generator.cc @@ -65,6 +65,7 @@ class t_py_generator : public t_generator { coding_ = ""; gen_dynbaseclass_ = ""; gen_dynbaseclass_exc_ = ""; + gen_dynbaseclass_frozen_exc_ = ""; gen_dynbaseclass_frozen_ = ""; import_dynbase_ = ""; package_prefix_ = ""; @@ -94,8 +95,11 @@ class t_py_generator : public t_generator { if( gen_dynbaseclass_exc_.empty()) { gen_dynbaseclass_exc_ = "TExceptionBase"; } + if( gen_dynbaseclass_frozen_exc_.empty()) { + gen_dynbaseclass_frozen_exc_ = "TFrozenExceptionBase"; + } if( import_dynbase_.empty()) { - import_dynbase_ = "from thrift.protocol.TBase import TBase, TFrozenBase, TExceptionBase, TTransport\n"; + import_dynbase_ = "from thrift.protocol.TBase import TBase, TFrozenBase, TExceptionBase, TFrozenExceptionBase, TTransport\n"; } } else if( iter->first.compare("dynbase") == 0) { gen_dynbase_ = true; @@ -104,6 +108,8 @@ class t_py_generator : public t_generator { gen_dynbaseclass_frozen_ = (iter->second); } else if( iter->first.compare("dynexc") == 0) { gen_dynbaseclass_exc_ = (iter->second); + } else if( iter->first.compare("dynfrozenexc") == 0) { + gen_dynbaseclass_frozen_exc_ = (iter->second); } else if( iter->first.compare("dynimport") == 0) { gen_dynbase_ = true; import_dynbase_ = (iter->second); @@ -269,7 +275,16 @@ class t_py_generator : public t_generator { } static bool is_immutable(t_type* ttype) { - return ttype->annotations_.find("python.immutable") != ttype->annotations_.end(); + std::map::iterator it = ttype->annotations_.find("python.immutable"); + + if (it == ttype->annotations_.end()) { + // Exceptions are immutable by default. + return ttype->is_xception(); + } else if (it->second == "false") { + return false; + } else { + return true; + } } private: @@ -288,6 +303,7 @@ class t_py_generator : public t_generator { std::string gen_dynbaseclass_; std::string gen_dynbaseclass_frozen_; std::string gen_dynbaseclass_exc_; + std::string gen_dynbaseclass_frozen_exc_; std::string import_dynbase_; @@ -742,7 +758,11 @@ void t_py_generator::generate_py_struct_definition(ostream& out, out << endl << endl << "class " << tstruct->get_name(); if (is_exception) { if (gen_dynamic_) { - out << "(" << gen_dynbaseclass_exc_ << ")"; + if (is_immutable(tstruct)) { + out << "(" << gen_dynbaseclass_frozen_exc_ << ")"; + } else { + out << "(" << gen_dynbaseclass_exc_ << ")"; + } } else { out << "(TException)"; } @@ -2774,6 +2794,7 @@ THRIFT_REGISTER_GENERATOR( " dynbase=CLS Derive generated classes from class CLS instead of TBase.\n" " dynfrozen=CLS Derive generated immutable classes from class CLS instead of TFrozenBase.\n" " dynexc=CLS Derive generated exceptions from CLS instead of TExceptionBase.\n" + " dynfrozenexc=CLS Derive generated immutable exceptions from CLS instead of TFrozenExceptionBase.\n" " dynimport='from foo.bar import CLS'\n" " Add an import line to generated code to find the dynbase class.\n" " package_prefix='top.package.'\n" diff --git a/lib/py/src/protocol/TBase.py b/lib/py/src/protocol/TBase.py index 9ae1b118272..6c6ef18e877 100644 --- a/lib/py/src/protocol/TBase.py +++ b/lib/py/src/protocol/TBase.py @@ -80,3 +80,7 @@ def read(cls, iprot): [self.__class__, self.thrift_spec]) else: return iprot.readStruct(cls, cls.thrift_spec, True) + + +class TFrozenExceptionBase(TFrozenBase, TExceptionBase): + pass diff --git a/lib/py/src/protocol/TProtocol.py b/lib/py/src/protocol/TProtocol.py index 3456e8f0e85..339a2839d71 100644 --- a/lib/py/src/protocol/TProtocol.py +++ b/lib/py/src/protocol/TProtocol.py @@ -303,8 +303,14 @@ def readContainerSet(self, spec): def readContainerStruct(self, spec): (obj_class, obj_spec) = spec - obj = obj_class() - obj.read(self) + + # If obj_class.read is a classmethod (e.g. in frozen structs), + # call it as such. + if getattr(obj_class.read, '__self__', None) is obj_class: + obj = obj_class.read(self) + else: + obj = obj_class() + obj.read(self) return obj def readContainerMap(self, spec): diff --git a/test/DebugProtoTest.thrift b/test/DebugProtoTest.thrift index de47ea71760..1ab0f6aea0a 100644 --- a/test/DebugProtoTest.thrift +++ b/test/DebugProtoTest.thrift @@ -241,6 +241,10 @@ exception ExceptionWithAMap { 2: map map_field; } +exception MutableException { + 1: string msg; +} (python.immutable = "false") + service ServiceForExceptionWithAMap { void methodThatThrowsAnException() throws (1: ExceptionWithAMap xwamap); } diff --git a/test/py.tornado/test_suite.py b/test/py.tornado/test_suite.py index 447fde61b7e..0ee0a9b85a0 100755 --- a/test/py.tornado/test_suite.py +++ b/test/py.tornado/test_suite.py @@ -82,10 +82,7 @@ def testStruct(self, thing): def testException(self, s): if s == 'Xception': - x = Xception() - x.errorCode = 1001 - x.message = s - raise x + raise Xception(1001, s) elif s == 'throw_undeclared': raise ValueError('testing undeclared exception') diff --git a/test/py.twisted/test_suite.py b/test/py.twisted/test_suite.py index 02eb7f14ff8..6e044939bba 100755 --- a/test/py.twisted/test_suite.py +++ b/test/py.twisted/test_suite.py @@ -76,10 +76,7 @@ def testStruct(self, thing): def testException(self, s): if s == 'Xception': - x = Xception() - x.errorCode = 1001 - x.message = s - raise x + raise Xception(1001, s) elif s == "throw_undeclared": raise ValueError("foo") diff --git a/test/py/TestFrozen.py b/test/py/TestFrozen.py index 6d2595cf29b..ce7425f88fb 100755 --- a/test/py/TestFrozen.py +++ b/test/py/TestFrozen.py @@ -19,7 +19,9 @@ # under the License. # +from DebugProtoTest import Srv from DebugProtoTest.ttypes import CompactProtoTestStruct, Empty, Wrapper +from DebugProtoTest.ttypes import ExceptionWithAMap, MutableException from thrift.Thrift import TFrozenDict from thrift.transport import TTransport from thrift.protocol import TBinaryProtocol, TCompactProtocol @@ -94,6 +96,21 @@ def test_struct(self): x2 = self._roundtrip(x, Wrapper) self.assertEqual(x2.foo, Empty()) + def test_frozen_exception(self): + exc = ExceptionWithAMap(blah='foo') + with self.assertRaises(TypeError): + exc.blah = 'bar' + mutexc = MutableException(msg='foo') + mutexc.msg = 'bar' + self.assertEqual(mutexc.msg, 'bar') + + def test_frozen_exception_serialization(self): + result = Srv.declaredExceptionMethod_result( + xwamap=ExceptionWithAMap(blah="error")) + deserialized = self._roundtrip( + result, Srv.declaredExceptionMethod_result()) + self.assertEqual(result, deserialized) + class TestFrozen(TestFrozenBase): def protocol(self, trans): From cf95fef9b88761ff773257aa0ac0a41e4093820b Mon Sep 17 00:00:00 2001 From: Anton Golub Date: Sun, 24 Nov 2019 22:13:40 +0300 Subject: [PATCH 464/756] THRIFT-5029: Fix Node.js lib entry point Client: js --- lib/js/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/js/package.json b/lib/js/package.json index f578e4ba2ee..b75019deb05 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -2,6 +2,7 @@ "name": "thrift", "version": "0.14.0", "description": "Thrift is a software framework for scalable cross-language services development.", + "main": "./src/thrift", "author": { "name": "Apache Thrift Developers", "email": "dev@thrift.apache.org" From f1c53418a794f3d740b809ece822ce79c0bb62a3 Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Fri, 13 Dec 2019 08:09:36 +0900 Subject: [PATCH 465/756] THRIFT-4974: Add cross test for Python's Unix domain socket transport Client: Python This closes #1896. --- LANGUAGES.md | 2 +- test/known_failures_Linux.json | 109 ++++++++++++++++++++++++++++++++- test/py/TestClient.py | 4 +- test/py/TestServer.py | 4 +- test/tests.json | 6 +- 5 files changed, 119 insertions(+), 6 deletions(-) diff --git a/LANGUAGES.md b/LANGUAGES.md index 923b045f847..afd7799fe9d 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -315,7 +315,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr 0.2.0 YesYes 2.7.12, 3.5.22.7.15, 3.6.8 -YesYes +YesYesYes YesYesYes YesYesYesYes YesYesYes diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index dd6195a3715..e165aa47242 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -85,74 +85,109 @@ "cpp-nodejs_multij-json_http-domain", "cpp-nodejs_multij-json_http-ip", "cpp-nodejs_multij-json_http-ip-ssl", + "cpp-py3_binary-accel_http-domain", "cpp-py3_binary-accel_http-ip", "cpp-py3_binary-accel_http-ip-ssl", + "cpp-py3_binary_http-domain", "cpp-py3_binary_http-ip", "cpp-py3_binary_http-ip-ssl", + "cpp-py3_compact-accelc_http-domain", "cpp-py3_compact-accelc_http-ip", "cpp-py3_compact-accelc_http-ip-ssl", + "cpp-py3_compact_http-domain", "cpp-py3_compact_http-ip", "cpp-py3_compact_http-ip-ssl", + "cpp-py3_header_http-domain", "cpp-py3_header_http-ip", "cpp-py3_header_http-ip-ssl", + "cpp-py3_json_http-domain", "cpp-py3_json_http-ip", "cpp-py3_json_http-ip-ssl", + "cpp-py3_multi-accel_http-domain", "cpp-py3_multi-accel_http-ip", "cpp-py3_multi-accel_http-ip-ssl", + "cpp-py3_multi-binary_http-domain", "cpp-py3_multi-binary_http-ip", "cpp-py3_multi-binary_http-ip-ssl", + "cpp-py3_multi-multia_http-domain", "cpp-py3_multi-multia_http-ip", "cpp-py3_multi-multia_http-ip-ssl", + "cpp-py3_multi_http-domain", "cpp-py3_multi_http-ip", "cpp-py3_multi_http-ip-ssl", + "cpp-py3_multic-accelc_http-domain", "cpp-py3_multic-accelc_http-ip", "cpp-py3_multic-accelc_http-ip-ssl", + "cpp-py3_multic-compact_http-domain", "cpp-py3_multic-compact_http-ip", "cpp-py3_multic-compact_http-ip-ssl", + "cpp-py3_multic-multiac_http-domain", "cpp-py3_multic-multiac_http-ip", "cpp-py3_multic-multiac_http-ip-ssl", + "cpp-py3_multic_http-domain", "cpp-py3_multic_http-ip", "cpp-py3_multic_http-ip-ssl", + "cpp-py3_multih-header_http-domain", "cpp-py3_multih-header_http-ip", "cpp-py3_multih-header_http-ip-ssl", + "cpp-py3_multij-json_http-domain", "cpp-py3_multij-json_http-ip", "cpp-py3_multij-json_http-ip-ssl", + "cpp-py3_multij_http-domain", "cpp-py3_multij_http-ip", "cpp-py3_multij_http-ip-ssl", + "cpp-py_binary-accel_http-domain", "cpp-py_binary-accel_http-ip", "cpp-py_binary-accel_http-ip-ssl", + "cpp-py_binary_http-domain", "cpp-py_binary_http-ip", "cpp-py_binary_http-ip-ssl", + "cpp-py_compact-accelc_http-domain", "cpp-py_compact-accelc_http-ip", "cpp-py_compact-accelc_http-ip-ssl", + "cpp-py_compact_http-domain", "cpp-py_compact_http-ip", "cpp-py_compact_http-ip-ssl", + "cpp-py_header_http-domain", "cpp-py_header_http-ip", "cpp-py_header_http-ip-ssl", + "cpp-py_json_http-domain", "cpp-py_json_http-ip", "cpp-py_json_http-ip-ssl", + "cpp-py_multi-accel_http-domain", "cpp-py_multi-accel_http-ip", "cpp-py_multi-accel_http-ip-ssl", + "cpp-py_multi-binary_http-domain", "cpp-py_multi-binary_http-ip", "cpp-py_multi-binary_http-ip-ssl", + "cpp-py_multi-multia_http-domain", "cpp-py_multi-multia_http-ip", "cpp-py_multi-multia_http-ip-ssl", + "cpp-py_multi_http-domain", "cpp-py_multi_http-ip", "cpp-py_multi_http-ip-ssl", + "cpp-py_multic-accelc_http-domain", "cpp-py_multic-accelc_http-ip", "cpp-py_multic-accelc_http-ip-ssl", + "cpp-py_multic-compact_http-domain", "cpp-py_multic-compact_http-ip", "cpp-py_multic-compact_http-ip-ssl", + "cpp-py_multic-multiac_http-domain", "cpp-py_multic-multiac_http-ip", "cpp-py_multic-multiac_http-ip-ssl", + "cpp-py_multic_http-domain", "cpp-py_multic_http-ip", "cpp-py_multic_http-ip-ssl", + "cpp-py_multih-header_http-domain", "cpp-py_multih-header_http-ip", "cpp-py_multih-header_http-ip-ssl", + "cpp-py_multih_http-domain", "cpp-py_multih_http-ip", "cpp-py_multih_http-ip-ssl", + "cpp-py_multij-json_http-domain", "cpp-py_multij-json_http-ip", "cpp-py_multij-json_http-ip-ssl", + "cpp-py_multij_http-domain", "cpp-py_multij_http-ip", "cpp-py_multij_http-ip-ssl", "cpp-rs_multi_buffered-ip", @@ -389,76 +424,112 @@ "nodejs-lua_binary_http-ip", "nodejs-lua_compact_http-ip", "nodejs-lua_json_http-ip", + "nodejs-py3_binary-accel_http-domain", "nodejs-py3_binary-accel_http-ip", "nodejs-py3_binary-accel_http-ip-ssl", + "nodejs-py3_binary_http-domain", "nodejs-py3_binary_http-ip", "nodejs-py3_binary_http-ip-ssl", + "nodejs-py3_compact-accelc_http-domain", "nodejs-py3_compact-accelc_http-ip", "nodejs-py3_compact-accelc_http-ip-ssl", + "nodejs-py3_compact_http-domain", "nodejs-py3_compact_http-ip", "nodejs-py3_compact_http-ip-ssl", + "nodejs-py3_header_http-domain", "nodejs-py3_header_http-ip", "nodejs-py3_header_http-ip-ssl", + "nodejs-py3_json_http-domain", "nodejs-py3_json_http-ip", "nodejs-py3_json_http-ip-ssl", + "nodejs-py_binary-accel_http-domain", "nodejs-py_binary-accel_http-ip", "nodejs-py_binary-accel_http-ip-ssl", + "nodejs-py_binary_http-domain", "nodejs-py_binary_http-ip", "nodejs-py_binary_http-ip-ssl", + "nodejs-py_compact-accelc_http-domain", "nodejs-py_compact-accelc_http-ip", "nodejs-py_compact-accelc_http-ip-ssl", + "nodejs-py_compact_http-domain", "nodejs-py_compact_http-ip", "nodejs-py_compact_http-ip-ssl", + "nodejs-py_header_http-domain", "nodejs-py_header_http-ip", "nodejs-py_header_http-ip-ssl", + "nodejs-py_json_http-domain", "nodejs-py_json_http-ip", "nodejs-py_json_http-ip-ssl", "perl-rs_multi_buffered-ip", "perl-rs_multi_framed-ip", + "py-cpp_accel-binary_http-domain", "py-cpp_accel-binary_http-ip", "py-cpp_accel-binary_http-ip-ssl", + "py-cpp_accel-binary_zlib-domain", "py-cpp_accel-binary_zlib-ip", "py-cpp_accel-binary_zlib-ip-ssl", + "py-cpp_accelc-compact_http-domain", "py-cpp_accelc-compact_http-ip", "py-cpp_accelc-compact_http-ip-ssl", + "py-cpp_accelc-compact_zlib-domain", "py-cpp_accelc-compact_zlib-ip", "py-cpp_accelc-compact_zlib-ip-ssl", + "py-cpp_binary_http-domain", "py-cpp_binary_http-ip", "py-cpp_binary_http-ip-ssl", + "py-cpp_compact_http-domain", "py-cpp_compact_http-ip", "py-cpp_compact_http-ip-ssl", + "py-cpp_header_http-domain", "py-cpp_header_http-ip", "py-cpp_header_http-ip-ssl", + "py-cpp_json_http-domain", "py-cpp_json_http-ip", "py-cpp_json_http-ip-ssl", + "py-cpp_multi-binary_http-domain", "py-cpp_multi-binary_http-ip", "py-cpp_multi-binary_http-ip-ssl", + "py-cpp_multi_http-domain", "py-cpp_multi_http-ip", "py-cpp_multi_http-ip-ssl", + "py-cpp_multia-binary_http-domain", "py-cpp_multia-binary_http-ip", "py-cpp_multia-binary_http-ip-ssl", + "py-cpp_multia-binary_zlib-domain", "py-cpp_multia-binary_zlib-ip", "py-cpp_multia-binary_zlib-ip-ssl", + "py-cpp_multia-multi_http-domain", "py-cpp_multia-multi_http-ip", "py-cpp_multia-multi_http-ip-ssl", + "py-cpp_multia-multi_zlib-domain", "py-cpp_multia-multi_zlib-ip", "py-cpp_multia-multi_zlib-ip-ssl", + "py-cpp_multiac-compact_http-domain", "py-cpp_multiac-compact_http-ip", "py-cpp_multiac-compact_http-ip-ssl", + "py-cpp_multiac-compact_zlib-domain", "py-cpp_multiac-compact_zlib-ip", "py-cpp_multiac-compact_zlib-ip-ssl", + "py-cpp_multiac-multic_http-domain", "py-cpp_multiac-multic_http-ip", "py-cpp_multiac-multic_http-ip-ssl", + "py-cpp_multiac-multic_zlib-domain", "py-cpp_multiac-multic_zlib-ip", "py-cpp_multiac-multic_zlib-ip-ssl", + "py-cpp_multic-compact_http-domain", "py-cpp_multic-compact_http-ip", "py-cpp_multic-compact_http-ip-ssl", + "py-cpp_multic_http-domain", "py-cpp_multic_http-ip", "py-cpp_multic_http-ip-ssl", + "py-cpp_multih_http-domain", + "py-cpp_multih-header_http-domain", "py-cpp_multih-header_http-ip", "py-cpp_multih-header_http-ip-ssl", + "py-cpp_multij_http-domain", "py-cpp_multih_http-ip", "py-cpp_multih_http-ip-ssl", + "py-cpp_multij-json_http-domain", "py-cpp_multij-json_http-ip", "py-cpp_multij-json_http-ip-ssl", "py-cpp_multij_http-ip", @@ -504,6 +575,12 @@ "py-lua_binary_http-ip", "py-lua_compact_http-ip", "py-lua_json_http-ip", + "py-nodejs_accel-binary_http-domain", + "py-nodejs_accelc-compact_http-domain", + "py-nodejs_binary_http-domain", + "py-nodejs_compact_http-domain", + "py-nodejs_json_http-domain", + "py-nodejs_header_http-domain", "py-rs_multi_buffered-ip", "py-rs_multi_framed-ip", "py-rs_multia-multi_buffered-ip", @@ -512,52 +589,76 @@ "py-rs_multiac-multic_framed-ip", "py-rs_multic_buffered-ip", "py-rs_multic_framed-ip", + "py3-cpp_accel-binary_http-domain", "py3-cpp_accel-binary_http-ip", "py3-cpp_accel-binary_http-ip-ssl", + "py3-cpp_accel-binary_zlib-domain", "py3-cpp_accel-binary_zlib-ip", "py3-cpp_accel-binary_zlib-ip-ssl", + "py3-cpp_accelc-compact_http-domain", "py3-cpp_accelc-compact_http-ip", "py3-cpp_accelc-compact_http-ip-ssl", + "py3-cpp_accelc-compact_zlib-domain", "py3-cpp_accelc-compact_zlib-ip", "py3-cpp_accelc-compact_zlib-ip-ssl", + "py3-cpp_binary_http-domain", "py3-cpp_binary_http-ip", "py3-cpp_binary_http-ip-ssl", + "py3-cpp_compact_http-domain", "py3-cpp_compact_http-ip", "py3-cpp_compact_http-ip-ssl", + "py3-cpp_header_http-domain", "py3-cpp_header_http-ip", "py3-cpp_header_http-ip-ssl", + "py3-cpp_json_http-domain", "py3-cpp_json_http-ip", "py3-cpp_json_http-ip-ssl", + "py3-cpp_multi-binary_http-domain", "py3-cpp_multi-binary_http-ip", "py3-cpp_multi-binary_http-ip-ssl", + "py3-cpp_multi_http-domain", "py3-cpp_multi_http-ip", "py3-cpp_multi_http-ip-ssl", + "py3-cpp_multia-binary_http-domain", "py3-cpp_multia-binary_http-ip", "py3-cpp_multia-binary_http-ip-ssl", + "py3-cpp_multia-binary_zlib-domain", "py3-cpp_multia-binary_zlib-ip", "py3-cpp_multia-binary_zlib-ip-ssl", + "py3-cpp_multia-multi_http-domain", "py3-cpp_multia-multi_http-ip", "py3-cpp_multia-multi_http-ip-ssl", + "py3-cpp_multia-multi_zlib-domain", "py3-cpp_multia-multi_zlib-ip", "py3-cpp_multia-multi_zlib-ip-ssl", + "py3-cpp_multiac-compact_http-domain", "py3-cpp_multiac-compact_http-ip", "py3-cpp_multiac-compact_http-ip-ssl", + "py3-cpp_multiac-compact_zlib-domain", "py3-cpp_multiac-compact_zlib-ip", "py3-cpp_multiac-compact_zlib-ip-ssl", + "py3-cpp_multiac-multic_http-domain", "py3-cpp_multiac-multic_http-ip", "py3-cpp_multiac-multic_http-ip-ssl", + "py3-cpp_multiac-multic_zlib-domain", "py3-cpp_multiac-multic_zlib-ip", "py3-cpp_multiac-multic_zlib-ip-ssl", + "py3-cpp_multic-compact_http-domain", "py3-cpp_multic-compact_http-ip", "py3-cpp_multic-compact_http-ip-ssl", + "py3-cpp_multic_http-domain", "py3-cpp_multic_http-ip", "py3-cpp_multic_http-ip-ssl", + "py3-cpp_multih-header_http-domain", "py3-cpp_multih-header_http-ip", "py3-cpp_multih-header_http-ip-ssl", + "py3-cpp_multih_http-domain", "py3-cpp_multih_http-ip", "py3-cpp_multih_http-ip-ssl", + "py3-cpp_multij-json_http-domain", "py3-cpp_multij-json_http-ip", "py3-cpp_multij-json_http-ip-ssl", + "py3-cpp_multij_http-domain", "py3-cpp_multij_http-ip", "py3-cpp_multij_http-ip-ssl", "py3-d_accel-binary_http-ip", @@ -601,6 +702,12 @@ "py3-lua_binary_http-ip", "py3-lua_compact_http-ip", "py3-lua_json_http-ip", + "py3-nodejs_accel-binary_http-domain", + "py3-nodejs_accelc-compact_http-domain", + "py3-nodejs_binary_http-domain", + "py3-nodejs_compact_http-domain", + "py3-nodejs_json_http-domain", + "py3-nodejs_header_http-domain", "py3-rs_multi_buffered-ip", "py3-rs_multi_framed-ip", "py3-rs_multia-multi_buffered-ip", @@ -615,4 +722,4 @@ "rb-cpp_json_framed-domain", "rb-cpp_json_framed-ip", "rb-cpp_json_framed-ip-ssl" -] \ No newline at end of file +] diff --git a/test/py/TestClient.py b/test/py/TestClient.py index e7a9a1a0e71..8a30c3a57cd 100755 --- a/test/py/TestClient.py +++ b/test/py/TestClient.py @@ -51,7 +51,7 @@ def setUp(self): from thrift.transport import TSSLSocket socket = TSSLSocket.TSSLSocket(options.host, options.port, validate=False) else: - socket = TSocket.TSocket(options.host, options.port) + socket = TSocket.TSocket(options.host, options.port, options.domain_socket) # frame or buffer depending upon args self.transport = TTransport.TBufferedTransport(socket) if options.trans == 'framed': @@ -474,6 +474,8 @@ def parseArgs(self, argv): help="protocol to use, one of: accel, accelc, binary, compact, header, json, multi, multia, multiac, multic, multih, multij") parser.add_option('--transport', dest="trans", type="string", help="transport to use, one of: buffered, framed, http") + parser.add_option('--domain-socket', dest="domain_socket", type="string", + help="Unix domain socket path") parser.set_defaults(framed=False, http_path=None, verbose=1, host='localhost', port=9090, proto='binary') options, args = parser.parse_args() diff --git a/test/py/TestServer.py b/test/py/TestServer.py index d0a13e5f7e6..4d90f8f9172 100755 --- a/test/py/TestServer.py +++ b/test/py/TestServer.py @@ -307,7 +307,7 @@ def main(options): from thrift.transport import TSSLSocket transport = TSSLSocket.TSSLServerSocket(host, options.port, certfile=abs_key_path) else: - transport = TSocket.TServerSocket(host, options.port) + transport = TSocket.TServerSocket(host, options.port, options.domain_socket) tfactory = TTransport.TBufferedTransportFactory() if options.trans == 'buffered': tfactory = TTransport.TBufferedTransportFactory() @@ -385,6 +385,8 @@ def exit_gracefully(signum, frame): help="protocol to use, one of: accel, accelc, binary, compact, json, multi, multia, multiac, multic, multih, multij") parser.add_option('--transport', dest="trans", type="string", help="transport to use, one of: buffered, framed, http") + parser.add_option('--domain-socket', dest="domain_socket", type="string", + help="Unix domain socket path") parser.add_option('--container-limit', dest='container_limit', type='int', default=None) parser.add_option('--string-limit', dest='string_limit', type='int', default=None) parser.set_defaults(port=9090, verbose=1, proto='binary', transport='buffered') diff --git a/test/tests.json b/test/tests.json index 78d4c0e9b52..b8b85be73a8 100644 --- a/test/tests.json +++ b/test/tests.json @@ -264,7 +264,8 @@ ], "sockets": [ "ip", - "ip-ssl" + "ip-ssl", + "domain" ], "protocols": [ "binary", @@ -313,7 +314,8 @@ ], "sockets": [ "ip", - "ip-ssl" + "ip-ssl", + "domain" ], "protocols": [ "binary", From 6e2a6983ec95c7a64db3d219b9533af1c2b8c1a1 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 12 Dec 2019 23:07:49 +0100 Subject: [PATCH 466/756] THRIFT-5048 EnumUtils.ToString() throws for elements not known to the receiving end [ci skip] Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.Utils.pas | 13 +++++++--- .../test/skip/idl/skiptest_version_1.thrift | 8 ++++--- .../test/skip/idl/skiptest_version_2.thrift | 9 +++++++ lib/delphi/test/skip/skiptest_version1.dpr | 24 ++++++++++++++----- lib/delphi/test/skip/skiptest_version2.dpr | 21 +++++++++++++--- 5 files changed, 60 insertions(+), 15 deletions(-) diff --git a/lib/delphi/src/Thrift.Utils.pas b/lib/delphi/src/Thrift.Utils.pas index ede26564615..bc9b4605bea 100644 --- a/lib/delphi/src/Thrift.Utils.pas +++ b/lib/delphi/src/Thrift.Utils.pas @@ -97,7 +97,7 @@ StringUtils = class sealed THRIFT_MIMETYPE = 'application/x-thrift'; {$IFDEF Win64} -function InterlockedExchangeAdd64( var Addend : Int64; Value : Int64) : Int64; +function InterlockedExchangeAdd64( var Addend : Int64; Value : Int64) : Int64; {$ENDIF} @@ -289,8 +289,15 @@ class function EnumUtils.ToString(const value : Integer) : string; var pType : PTypeInfo; begin pType := PTypeInfo(TypeInfo(T)); - if Assigned(pType) and (pType^.Kind = tkEnumeration) - then result := GetEnumName(pType,value) + if Assigned(pType) + and (pType^.Kind = tkEnumeration) + {$IF CompilerVersion >= 23.0} // TODO: Range correct? What we know is that XE does not offer it, but Rio has it + and (pType^.TypeData^.MaxValue >= value) + and (pType^.TypeData^.MinValue <= value) + {$ELSE} + and FALSE // THRIFT-5048: pType^.TypeData^ member not supported -> prevent GetEnumName() from reading outside the legal range + {$IFEND} + then result := GetEnumName( PTypeInfo(pType), value) else result := IntToStr(Ord(value)); end; diff --git a/lib/delphi/test/skip/idl/skiptest_version_1.thrift b/lib/delphi/test/skip/idl/skiptest_version_1.thrift index 8353c5e12f2..4221177e0f2 100644 --- a/lib/delphi/test/skip/idl/skiptest_version_1.thrift +++ b/lib/delphi/test/skip/idl/skiptest_version_1.thrift @@ -24,12 +24,14 @@ namespace * Skiptest.One const i32 SKIPTESTSERVICE_VERSION = 1 -struct Pong { - 1 : optional i32 version1 +enum PingPongEnum { + PingOne = 0, + PongOne = 1, } struct Ping { 1 : optional i32 version1 + 100 : PingPongEnum EnumTest } exception PongFailed { @@ -38,7 +40,7 @@ exception PongFailed { service SkipTestService { - void PingPong( 1: Ping pong) throws (444: PongFailed pof); + Ping PingPong( 1: Ping ping) throws (444: PongFailed pof); } diff --git a/lib/delphi/test/skip/idl/skiptest_version_2.thrift b/lib/delphi/test/skip/idl/skiptest_version_2.thrift index f3352d32774..3ea69f768a5 100644 --- a/lib/delphi/test/skip/idl/skiptest_version_2.thrift +++ b/lib/delphi/test/skip/idl/skiptest_version_2.thrift @@ -24,9 +24,17 @@ namespace * Skiptest.Two const i32 SKIPTESTSERVICE_VERSION = 2 +enum PingPongEnum { + PingOne = 0, + PongOne = 1, + PingTwo = 2, + PongTwo = 3, +} + struct Pong { 1 : optional i32 version1 2 : optional i16 version2 + 100 : PingPongEnum EnumTest } struct Ping { @@ -40,6 +48,7 @@ struct Ping { 16 : optional string strVal 17 : optional Pong structVal 18 : optional map< list< Pong>, set< string>> mapVal + 100 : PingPongEnum EnumTest } exception PingFailed { diff --git a/lib/delphi/test/skip/skiptest_version1.dpr b/lib/delphi/test/skip/skiptest_version1.dpr index c97e50b6f45..f7cde2f5df9 100644 --- a/lib/delphi/test/skip/skiptest_version1.dpr +++ b/lib/delphi/test/skip/skiptest_version1.dpr @@ -30,6 +30,7 @@ uses Thrift.Transport in '..\..\src\Thrift.Transport.pas', Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas', + Thrift.Protocol.Compact in '..\..\src\Thrift.Protocol.Compact.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', @@ -47,6 +48,7 @@ function CreatePing : IPing; begin result := TPingImpl.Create; result.Version1 := Tskiptest_version_1Constants.SKIPTESTSERVICE_VERSION; + result.EnumTest := TPingPongEnum.PingOne; end; @@ -54,14 +56,16 @@ type TDummyServer = class( TInterfacedObject, TSkipTestService.Iface) protected // TSkipTestService.Iface - procedure PingPong(const ping: IPing); + function PingPong(const ping: IPing): IPing; end; -procedure TDummyServer.PingPong(const ping: IPing); +function TDummyServer.PingPong(const ping: IPing): IPing; // TSkipTestService.Iface begin Writeln('- performing request from version '+IntToStr(ping.Version1)+' client'); + Writeln( ping.ToString); + result := CreatePing; end; @@ -109,6 +113,7 @@ end; procedure ReadResponse( protfact : IProtocolFactory; fname : string); var stm : TFileStream; + ping : IPing; proto : IProtocol; client : TSkipTestService.TClient; // we need access to send/recv_pingpong() cliRef : IUnknown; // holds the refcount @@ -116,11 +121,11 @@ begin Writeln('- reading response'); stm := TFileStream.Create( fname+RESPONSE_EXT, fmOpenRead); try - // save request data + // load request data proto := CreateProtocol( protfact, stm, TRUE); client := TSkipTestService.TClient.Create( proto, nil); cliRef := client as IUnknown; - client.recv_PingPong; + ping := client.recv_PingPong; finally client := nil; // not Free! @@ -164,12 +169,14 @@ end; procedure Test( protfact : IProtocolFactory; fname : string); begin // try to read an existing request + Writeln('Reading data file '+fname); if FileExists( fname + REQUEST_EXT) then begin ProcessFile( protfact, fname); ReadResponse( protfact, fname); end; // create a new request and try to process + Writeln('Writing data file '+fname); CreateRequest( protfact, fname); ProcessFile( protfact, fname); ReadResponse( protfact, fname); @@ -177,8 +184,9 @@ end; const - FILE_BINARY = 'pingpong.bin'; - FILE_JSON = 'pingpong.json'; + FILE_BINARY = 'pingpong.bin'; + FILE_JSON = 'pingpong.json'; + FILE_COMPACT = 'pingpong.compact'; begin try Writeln( 'Delphi SkipTest '+IntToStr(Tskiptest_version_1Constants.SKIPTESTSERVICE_VERSION)+' using '+Thrift.Version); @@ -191,6 +199,10 @@ begin Writeln('JSON protocol'); Test( TJSONProtocolImpl.TFactory.Create, FILE_JSON); + Writeln; + Writeln('Compact protocol'); + Test( TCompactProtocolImpl.TFactory.Create, FILE_COMPACT); + Writeln; Writeln('Test completed without errors.'); Writeln; diff --git a/lib/delphi/test/skip/skiptest_version2.dpr b/lib/delphi/test/skip/skiptest_version2.dpr index 07c2c9af475..478ea7c7ad0 100644 --- a/lib/delphi/test/skip/skiptest_version2.dpr +++ b/lib/delphi/test/skip/skiptest_version2.dpr @@ -30,6 +30,7 @@ uses Thrift.Transport in '..\..\src\Thrift.Transport.pas', Thrift.Protocol in '..\..\src\Thrift.Protocol.pas', Thrift.Protocol.JSON in '..\..\src\Thrift.Protocol.JSON.pas', + Thrift.Protocol.Compact in '..\..\src\Thrift.Protocol.Compact.pas', Thrift.Collections in '..\..\src\Thrift.Collections.pas', Thrift.Configuration in '..\..\src\Thrift.Configuration.pas', Thrift.Server in '..\..\src\Thrift.Server.pas', @@ -42,12 +43,15 @@ const REQUEST_EXT = '.request'; RESPONSE_EXT = '.response'; + function CreatePing : IPing; var list : IThriftList; set_ : IHashSet; begin result := TPingImpl.Create; result.Version1 := Tskiptest_version_2Constants.SKIPTESTSERVICE_VERSION; + result.EnumTest := TPingPongEnum.PingTwo; + result.BoolVal := TRUE; result.ByteVal := 2; result.DbVal := 3; @@ -59,6 +63,7 @@ begin result.StructVal := TPongImpl.Create; result.StructVal.Version1 := -1; result.StructVal.Version2 := -2; + result.StructVal.EnumTest := TPingPongEnum.PongTwo; list := TThriftListImpl.Create; list.Add( result.StructVal); @@ -87,6 +92,7 @@ function TDummyServer.PingPong(const ping: IPing; const pong: IPong): IPing; // TSkipTestService.Iface begin Writeln('- performing request from version '+IntToStr(ping.Version1)+' client'); + Writeln( ping.ToString); result := CreatePing; end; @@ -143,7 +149,7 @@ begin Writeln('- reading response'); stm := TFileStream.Create( fname+RESPONSE_EXT, fmOpenRead); try - // save request data + // load request data proto := CreateProtocol( protfact, stm, TRUE); client := TSkipTestService.TClient.Create( proto, nil); cliRef := client as IUnknown; @@ -191,12 +197,16 @@ end; procedure Test( protfact : IProtocolFactory; fname : string); begin // try to read an existing request + Writeln; + Writeln('Reading data file '+fname); if FileExists( fname + REQUEST_EXT) then begin ProcessFile( protfact, fname); ReadResponse( protfact, fname); end; // create a new request and try to process + Writeln; + Writeln('Writing data file '+fname); CreateRequest( protfact, fname); ProcessFile( protfact, fname); ReadResponse( protfact, fname); @@ -204,8 +214,9 @@ end; const - FILE_BINARY = 'pingpong.bin'; - FILE_JSON = 'pingpong.json'; + FILE_BINARY = 'pingpong.bin'; + FILE_JSON = 'pingpong.json'; + FILE_COMPACT = 'pingpong.compact'; begin try Writeln( 'Delphi SkipTest '+IntToStr(Tskiptest_version_2Constants.SKIPTESTSERVICE_VERSION)+' using '+Thrift.Version); @@ -218,6 +229,10 @@ begin Writeln('JSON protocol'); Test( TJSONProtocolImpl.TFactory.Create, FILE_JSON); + Writeln; + Writeln('Compact protocol'); + Test( TCompactProtocolImpl.TFactory.Create, FILE_COMPACT); + Writeln; Writeln('Test completed without errors.'); Writeln; From 0ebf3ce99d74bc77912536dc3ad95dac10ebf12a Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Thu, 12 Dec 2019 15:42:00 -0800 Subject: [PATCH 467/756] Fix uint64_t to size_t conversion warning Fixes an MSVC warning with an explicit cast. Client: cpp --- lib/cpp/src/thrift/transport/TBufferTransports.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cpp/src/thrift/transport/TBufferTransports.cpp b/lib/cpp/src/thrift/transport/TBufferTransports.cpp index 4bb8713de02..534067f1750 100644 --- a/lib/cpp/src/thrift/transport/TBufferTransports.cpp +++ b/lib/cpp/src/thrift/transport/TBufferTransports.cpp @@ -372,7 +372,7 @@ void TMemoryBuffer::ensureCanWrite(uint32_t len) { } // Allocate into a new pointer so we don't bork ours if it fails. - auto* new_buffer = static_cast(std::realloc(buffer_, new_size)); + auto* new_buffer = static_cast(std::realloc(buffer_, static_cast(new_size))); if (new_buffer == nullptr) { throw std::bad_alloc(); } From 418d88b447769745eeba372d12f486b22053a7a8 Mon Sep 17 00:00:00 2001 From: belugabehr <12578579+belugabehr@users.noreply.github.com> Date: Fri, 13 Dec 2019 04:13:12 -0500 Subject: [PATCH 468/756] THRIFT-5013: Replace NullPointerException with RequireNonNull Co-Authored-By: Christopher Tubbs Client: java This closes #1934. --- compiler/cpp/src/thrift/generate/t_java_generator.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_java_generator.cc b/compiler/cpp/src/thrift/generate/t_java_generator.cc index 7254e12b1be..581e1cfc030 100644 --- a/compiler/cpp/src/thrift/generate/t_java_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_java_generator.cc @@ -1060,11 +1060,15 @@ void t_java_generator::generate_union_getters_and_setters(ostream& out, t_struct } indent(out) << "public void set" << get_cap_name(field->get_name()) << "(" << type_name(field->get_type()) << " value) {" << endl; + + indent(out) << " setField_ = _Fields." << constant_name(field->get_name()) << ";" << endl; + if (type_can_be_null(field->get_type())) { - indent(out) << " if (value == null) throw new java.lang.NullPointerException();" << endl; + indent(out) << " value_ = java.util.Objects.requireNonNull(value,\"" << "_Fields." << constant_name(field->get_name()) << "\");" << endl; + } else { + indent(out) << " value_ = value;" << endl; } - indent(out) << " setField_ = _Fields." << constant_name(field->get_name()) << ";" << endl; - indent(out) << " value_ = value;" << endl; + indent(out) << "}" << endl; } } From b374ce35550659d4f109c2afc657733e7590aaed Mon Sep 17 00:00:00 2001 From: Duru Can Celasun Date: Fri, 13 Dec 2019 13:10:23 +0000 Subject: [PATCH 469/756] THRIFT-5046: Better struct tag overrides Custom go.tag in an IDL no longer removes the existing "db" and "json" tags but can override them. This allows us to change default tags in the future without affecting user defined ones. Client: go This closes #1963. --- .../cpp/src/thrift/generate/t_go_generator.cc | 65 +++++++++++++++++-- lib/go/test/GoTagTest.thrift | 2 +- lib/go/test/tests/gotag_test.go | 12 +++- 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index 2093841c60e..a5d55d7b111 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -240,6 +240,8 @@ class t_go_generator : public t_generator { void generate_go_docstring(std::ostream& out, t_doc* tdoc); + void parse_go_tags(map* tags, const string in); + /** * Helper rendering functions */ @@ -1377,7 +1379,9 @@ void t_go_generator::generate_go_struct_definition(ostream& out, t_type* fieldType = (*m_iter)->get_type(); string goType = type_to_go_type_with_opt(fieldType, is_pointer_field(*m_iter)); - string gotag = "db:\"" + escape_string((*m_iter)->get_name()) + "\" "; + + maptags; + tags["db"]=escape_string((*m_iter)->get_name()); // Only add the `omitempty` tag if this field is optional and has no default value. // Otherwise a proper value like `false` for a bool field will be ommitted from @@ -1385,16 +1389,25 @@ void t_go_generator::generate_go_struct_definition(ostream& out, bool has_default = (*m_iter)->get_value(); bool is_optional = (*m_iter)->get_req() == t_field::T_OPTIONAL; if (is_optional && !has_default) { - gotag += "json:\"" + escape_string((*m_iter)->get_name()) + ",omitempty\""; + tags["json"]=escape_string((*m_iter)->get_name())+",omitempty"; } else { - gotag += "json:\"" + escape_string((*m_iter)->get_name()) + "\""; + tags["json"]=escape_string((*m_iter)->get_name()); } - // Check for user override of db and json tags using "go.tag" + // Check for user defined tags and them if there are any. User defined tags + // can override the above db and json tags. std::map::iterator it = (*m_iter)->annotations_.find("go.tag"); if (it != (*m_iter)->annotations_.end()) { - gotag = it->second; + parse_go_tags(&tags, it->second); } + + string gotag; + for (auto it = tags.begin(); it != tags.end(); ++it) { + gotag += it->first + ":\"" + it->second + "\" "; + } + // Trailing whitespace + gotag.resize(gotag.size()-1); + indent(out) << publicize((*m_iter)->get_name()) << " " << goType << " `thrift:\"" << escape_string((*m_iter)->get_name()) << "," << sorted_keys_pos; if ((*m_iter)->get_req() == t_field::T_REQUIRED) { @@ -3735,6 +3748,48 @@ string t_go_generator::type_to_spec_args(t_type* ttype) { throw "INVALID TYPE IN type_to_spec_args: " + ttype->get_name(); } +// parses a string of struct tags into key/value pairs and writes them to the given map +void t_go_generator::parse_go_tags(map* tags, const string in) { + string key; + string value; + + size_t mode=0; // 0/1/2 for key/value/whitespace + size_t index=0; + for (auto it=in.begin(); it Date: Sat, 14 Dec 2019 04:33:37 -0500 Subject: [PATCH 470/756] THRIFT-5014: Do Direct Comparison on Raw Values Instead of Objects Client: java This closes #1935. --- compiler/cpp/src/thrift/generate/t_java_generator.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_java_generator.cc b/compiler/cpp/src/thrift/generate/t_java_generator.cc index 581e1cfc030..18055855bfe 100644 --- a/compiler/cpp/src/thrift/generate/t_java_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_java_generator.cc @@ -2056,8 +2056,8 @@ void t_java_generator::generate_java_struct_compare_to(ostream& out, t_struct* t vector::const_iterator m_iter; for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* field = *m_iter; - indent(out) << "lastComparison = java.lang.Boolean.valueOf(" << generate_isset_check(field) - << ").compareTo(other." << generate_isset_check(field) << ");" << endl; + indent(out) << "lastComparison = java.lang.Boolean.compare(" << generate_isset_check(field) + << ", other." << generate_isset_check(field) << ");" << endl; indent(out) << "if (lastComparison != 0) {" << endl; indent(out) << " return lastComparison;" << endl; indent(out) << "}" << endl; From 30ac2598e84928d9af7066b5d3248b7aea4376b2 Mon Sep 17 00:00:00 2001 From: Eugen Date: Tue, 7 Jan 2020 15:28:45 +0100 Subject: [PATCH 471/756] THRIFT-5003: Websocket Connection in Browsers with nodejs code * changed this to self in forEach callback * updated minimum node version to 8.16.2 (Maintenance LTS until December 2019) changed ws_connection.js to work in the browser, with isomorphic-ws added exports for `wsConnection`, `createWSConnection`, `createWSClient` * added exports for WSConnection to browser.js * extended the sample of nodejs code in the browser with webpack * tested and updated node version to LTS 10.18.0 Dubnium discussion based: https://github.com/apache/thrift/pull/1927#discussion_r358140463 --- lib/nodejs/README.md | 37 +++- lib/nodejs/lib/thrift/browser.js | 5 + lib/nodejs/lib/thrift/ws_connection.js | 30 ++-- package-lock.json | 232 +++++++++++++++---------- package.json | 16 +- 5 files changed, 208 insertions(+), 112 deletions(-) diff --git a/lib/nodejs/README.md b/lib/nodejs/README.md index ed306c15f58..c087440a180 100644 --- a/lib/nodejs/README.md +++ b/lib/nodejs/README.md @@ -75,8 +75,8 @@ You can use code generated with js:node on browsers with Webpack. Here is an exa thrift --gen js:node,ts,es6,with_ns -``` -import * as thrift from 'thrift/browser'; +```javascript +import * as thrift from 'thrift'; import { MyServiceClient } from '../gen-nodejs/MyService'; let host = window.location.hostname; @@ -108,4 +108,35 @@ thriftClient.myService(param) }); ``` -Note that thrift/index.js must be renamed or skipped for browsers. +Bundlers, like webpack, will use thrift/browser.js by default because of the +`"browser": "./lib/nodejs/lib/thrift/browser.js"` field in package.json. + +### Browser example with WebSocket, BufferedTransport and BinaryProtocol +```javascript +import thrift from 'thrift'; +import { MyServiceClient } from '../gen-nodejs/MyService'; + +const host = window.location.hostname; +const port = 9090; +const opts = { + transport: thrift.TBufferedTransport, + protocol: thrift.TBinaryProtocol +} +const connection = thrift.createWSConnection(host, port, opts); +connection.open(); +const thriftClient = thrift.createWSClient(MyServiceClient, connection); + +connection.on('error', (err) => { + console.error(err); +}); + +thriftClient.myService(param) + .then((result) => { + console.log(result); + }) + .catch((err) => { + .... + }); +``` + + diff --git a/lib/nodejs/lib/thrift/browser.js b/lib/nodejs/lib/thrift/browser.js index 67ce8535beb..82e5469c674 100644 --- a/lib/nodejs/lib/thrift/browser.js +++ b/lib/nodejs/lib/thrift/browser.js @@ -23,6 +23,11 @@ exports.XHRConnection = xhrConnection.XHRConnection; exports.createXHRConnection = xhrConnection.createXHRConnection; exports.createXHRClient = xhrConnection.createXHRClient; +var wsConnection = require('./ws_connection'); +exports.WSConnection = wsConnection.WSConnection; +exports.createWSConnection = wsConnection.createWSConnection; +exports.createWSClient = wsConnection.createWSClient; + exports.Multiplexer = require('./multiplexed_protocol').Multiplexer; exports.TWebSocketTransport = require('./ws_transport'); diff --git a/lib/nodejs/lib/thrift/ws_connection.js b/lib/nodejs/lib/thrift/ws_connection.js index 052cbd4e994..8ee8f6eca18 100644 --- a/lib/nodejs/lib/thrift/ws_connection.js +++ b/lib/nodejs/lib/thrift/ws_connection.js @@ -17,18 +17,16 @@ * under the License. */ var util = require('util'); -var WebSocket = require('ws'); +var WebSocket = require('isomorphic-ws'); var EventEmitter = require("events").EventEmitter; var thrift = require('./thrift'); -var ttransport = require('./transport'); -var tprotocol = require('./protocol'); var TBufferedTransport = require('./buffered_transport'); var TJSONProtocol = require('./json_protocol'); var InputBufferUnderrunError = require('./input_buffer_underrun_error'); var createClient = require('./create_client'); - +var jsEnv = require('browser-or-node'); exports.WSConnection = WSConnection; /** @@ -69,7 +67,7 @@ exports.WSConnection = WSConnection; * @throws {error} Exceptions other than ttransport.InputBufferUnderrunError are rethrown * @event {error} The "error" event is fired when a Node.js error event occurs during * request or response processing, in which case the node error is passed on. An "error" - * event may also be fired when the connectison can not map a response back to the + * event may also be fired when the connection can not map a response back to the * appropriate client (an internal error), generating a TApplicationException. * @classdesc WSConnection objects provide Thrift end point transport * semantics implemented using Websockets. @@ -80,7 +78,6 @@ function WSConnection(host, port, options) { EventEmitter.call(this); //Set configuration - var self = this; this.options = options || {}; this.host = host; this.port = port; @@ -113,14 +110,13 @@ WSConnection.prototype.__reset = function() { }; WSConnection.prototype.__onOpen = function() { - var self = this; this.emit("open"); if (this.send_pending.length > 0) { //If the user made calls before the connection was fully //open, send them now this.send_pending.forEach(function(data) { - self.socket.send(data); - }); + this.socket.send(data); + }, this); this.send_pending = []; } }; @@ -184,7 +180,7 @@ WSConnection.prototype.__decodeCallback = function(transport_with_data) { }; WSConnection.prototype.__onData = function(data) { - if (Object.prototype.toString.call(data) == "[object ArrayBuffer]") { + if (Object.prototype.toString.call(data) === "[object ArrayBuffer]") { data = new Uint8Array(data); } var buf = new Buffer(data); @@ -207,7 +203,7 @@ WSConnection.prototype.__onError = function(evt) { * @returns {boolean} */ WSConnection.prototype.isOpen = function() { - return this.socket && this.socket.readyState == this.socket.OPEN; + return this.socket && this.socket.readyState === this.socket.OPEN; }; /** @@ -215,11 +211,15 @@ WSConnection.prototype.isOpen = function() { */ WSConnection.prototype.open = function() { //If OPEN/CONNECTING/CLOSING ignore additional opens - if (this.socket && this.socket.readyState != this.socket.CLOSED) { + if (this.socket && this.socket.readyState !== this.socket.CLOSED) { return; } //If there is no socket or the socket is closed: - this.socket = new WebSocket(this.uri(), "", this.wsOptions); + if (jsEnv.isBrowser) { + this.socket = new WebSocket(this.uri()); + } else { + this.socket = new WebSocket(this.uri(), "", this.wsOptions); + } this.socket.binaryType = 'arraybuffer'; this.socket.onopen = this.__onOpen.bind(this); this.socket.onmessage = this.__onMessage.bind(this); @@ -245,8 +245,8 @@ WSConnection.prototype.uri = function() { var host = this.host; // avoid port if default for schema - if (this.port && (('wss' == schema && this.port != 443) || - ('ws' == schema && this.port != 80))) { + if (this.port && (('wss' === schema && this.port !== 443) || + ('ws' === schema && this.port !== 80))) { port = ':' + this.port; } diff --git a/package-lock.json b/package-lock.json index e88fb1e1fb9..15a18859252 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,12 @@ "js-tokens": "^4.0.0" } }, + "@babel/parser": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.3.tgz", + "integrity": "sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==", + "dev": true + }, "@types/node": { "version": "10.12.6", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.6.tgz", @@ -171,9 +177,9 @@ "dev": true }, "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" }, "asynckit": { "version": "0.4.0", @@ -193,12 +199,6 @@ "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", "dev": true }, - "babylon": { - "version": "7.0.0-beta.19", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", - "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==", - "dev": true - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -231,9 +231,9 @@ } }, "bluebird": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", - "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", + "integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==", "dev": true }, "brace-expansion": { @@ -246,6 +246,11 @@ "concat-map": "0.0.1" } }, + "browser-or-node": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.2.1.tgz", + "integrity": "sha512-sVIA0cysIED0nbmNOm7sZzKfgN1rpFmrqvLZaFWspaBAftfQcezlC81G6j6U2RJf4Lh66zFxrCeOsvkUXIcPWg==" + }, "buffer-alloc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", @@ -296,12 +301,12 @@ "dev": true }, "catharsis": { - "version": "0.8.9", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", - "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=", + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", + "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", "dev": true, "requires": { - "underscore-contrib": "~0.3.0" + "lodash": "^4.17.14" } }, "chalk": { @@ -560,6 +565,12 @@ "once": "^1.4.0" } }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, "es-abstract": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", @@ -715,10 +726,21 @@ } }, "eslint-utils": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", - "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", - "dev": true + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + } + } }, "eslint-visitor-keys": { "version": "1.0.0", @@ -1315,6 +1337,11 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==" + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -1386,9 +1413,9 @@ "dev": true }, "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -1396,12 +1423,12 @@ } }, "js2xmlparser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", - "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.0.tgz", + "integrity": "sha512-WuNgdZOXVmBk5kUPMcTcVUpbGRzLfNkv7+7APq7WiDihpXVKrgxo6wwRpRl9OQeEBgKCVk9mR7RbzrnNWC8oBw==", "dev": true, "requires": { - "xmlcreate": "^1.0.1" + "xmlcreate": "^2.0.0" } }, "jsbn": { @@ -1411,23 +1438,39 @@ "dev": true }, "jsdoc": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", - "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==", - "dev": true, - "requires": { - "babylon": "7.0.0-beta.19", - "bluebird": "~3.5.0", - "catharsis": "~0.8.9", - "escape-string-regexp": "~1.0.5", - "js2xmlparser": "~3.0.0", - "klaw": "~2.0.0", - "marked": "~0.3.6", - "mkdirp": "~0.5.1", - "requizzle": "~0.2.1", - "strip-json-comments": "~2.0.1", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.3.tgz", + "integrity": "sha512-Yf1ZKA3r9nvtMWHO1kEuMZTlHOF8uoQ0vyo5eH7SQy5YeIiHM+B0DgKnn+X6y6KDYZcF7G2SPkKF+JORCXWE/A==", + "dev": true, + "requires": { + "@babel/parser": "^7.4.4", + "bluebird": "^3.5.4", + "catharsis": "^0.8.11", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.0", + "klaw": "^3.0.0", + "markdown-it": "^8.4.2", + "markdown-it-anchor": "^5.0.2", + "marked": "^0.7.0", + "mkdirp": "^0.5.1", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.0.1", "taffydb": "2.6.2", - "underscore": "~1.8.3" + "underscore": "~1.9.1" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + } } }, "json-int64": { @@ -1476,9 +1519,9 @@ } }, "klaw": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz", - "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", "dev": true, "requires": { "graceful-fs": "^4.1.9" @@ -1494,16 +1537,50 @@ "type-check": "~0.3.2" } }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-it-anchor": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.2.5.tgz", + "integrity": "sha512-xLIjLQmtym3QpoY9llBgApknl7pxAcN3WDRc2d3rwpl+/YvDZHPmKscGs+L6E05xf2KrCXPBvosWt7MZukwSpQ==", "dev": true }, "marked": { - "version": "0.3.19", - "resolved": "http://registry.npmjs.org/marked/-/marked-0.3.19.tgz", - "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", + "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", + "dev": true + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", "dev": true }, "mime-db": { @@ -1969,20 +2046,12 @@ } }, "requizzle": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", - "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", "dev": true, "requires": { - "underscore": "~1.6.0" - }, - "dependencies": { - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true - } + "lodash": "^4.17.14" } }, "resolve": { @@ -2383,6 +2452,12 @@ "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==", "dev": true }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, "uglify-js": { "version": "3.4.9", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", @@ -2411,28 +2486,11 @@ } }, "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", "dev": true }, - "underscore-contrib": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz", - "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=", - "dev": true, - "requires": { - "underscore": "1.6.0" - }, - "dependencies": { - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true - } - } - }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -2548,9 +2606,9 @@ } }, "xmlcreate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", - "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.1.tgz", + "integrity": "sha512-MjGsXhKG8YjTKrDCXseFo3ClbMGvUD4en29H2Cev1dv4P/chlpw6KdYmlCWDkhosBVKRDjM836+3e3pm1cBNJA==", "dev": true }, "xtend": { diff --git a/package.json b/package.json index c674fef8355..c803df5bcdb 100644 --- a/package.json +++ b/package.json @@ -33,14 +33,19 @@ "browser": "./lib/nodejs/lib/thrift/browser.js", "main": "./lib/nodejs/lib/thrift", "engines": { - "node": ">= 4.1.0" + "node": ">= 10.18.0" }, "dependencies": { + "browser-or-node": "^1.2.1", + "isomorphic-ws": "^4.0.1", "node-int64": "^0.4.0", "q": "^1.5.0", - "ws": "^5.0.0" + "ws": "^5.2.2" }, "devDependencies": { + "@types/node": "^10.12.6", + "@types/node-int64": "^0.4.29", + "@types/q": "^1.5.1", "buffer-equals": "^1.0.4", "commander": "^2.14.1", "connect": "^3.6.6", @@ -49,15 +54,12 @@ "eslint-plugin-prettier": "^3.0.0", "html-validator-cli": "^4.1.4", "istanbul": "^0.4.5", - "jsdoc": "^3.5.5", + "jsdoc": "^3.6.3", "json-int64": "^1.0.0", "prettier": "^1.14.3", "tape": "^4.9.0", - "utf-8-validate": "^4.0.0", "typescript": "^3.1.6", - "@types/node": "^10.12.6", - "@types/node-int64": "^0.4.29", - "@types/q": "^1.5.1" + "utf-8-validate": "^4.0.0" }, "scripts": { "cover": "lib/nodejs/test/testAll.sh COVER", From bee4f2fd69db32621addd9353ab0aa2e2ba94349 Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Sun, 29 Dec 2019 17:04:50 +0900 Subject: [PATCH 472/756] THRIFT-5053: Fix the netstd tutorial console logging and README Client: netstd Patch: Kengo Seki This closes #1970 --- tutorial/netstd/Client/Program.cs | 29 ++++++++++++++----------- tutorial/netstd/README.md | 26 ++++++++++------------ tutorial/netstd/Server/Program.cs | 36 ++++++++++++++++--------------- tutorial/netstd/build.sh | 0 4 files changed, 46 insertions(+), 45 deletions(-) mode change 100644 => 100755 tutorial/netstd/build.sh diff --git a/tutorial/netstd/Client/Program.cs b/tutorial/netstd/Client/Program.cs index 857b3e80836..eefccf7036e 100644 --- a/tutorial/netstd/Client/Program.cs +++ b/tutorial/netstd/Client/Program.cs @@ -46,10 +46,10 @@ private static void DisplayHelp() { Logger.LogInformation(@" Usage: - Client.exe -help + Client -help will diplay help information - Client.exe -tr: -bf: -pr: -mc: + Client -tr: -bf: -pr: -mc: will run client with specified arguments (tcp transport and binary protocol by default) and with 1 client Options: @@ -74,7 +74,7 @@ will run client with specified arguments (tcp transport and binary protocol by d - number of multiple clients to connect to server (max 100, default 1) Sample: - Client.exe -tr:tcp -p:binary + Client -tr:tcp -pr:binary "); } @@ -83,19 +83,22 @@ public static void Main(string[] args) args = args ?? new string[0]; ServiceCollection.AddLogging(logging => ConfigureLogging(logging)); - Logger = ServiceCollection.BuildServiceProvider().GetService().CreateLogger(nameof(Client)); - - if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) + using (var serviceProvider = ServiceCollection.BuildServiceProvider()) { - DisplayHelp(); - return; - } + Logger = serviceProvider.GetService().CreateLogger(nameof(Client)); + + if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) + { + DisplayHelp(); + return; + } - Logger.LogInformation("Starting client..."); + Logger.LogInformation("Starting client..."); - using (var source = new CancellationTokenSource()) - { - RunAsync(args, source.Token).GetAwaiter().GetResult(); + using (var source = new CancellationTokenSource()) + { + RunAsync(args, source.Token).GetAwaiter().GetResult(); + } } } diff --git a/tutorial/netstd/README.md b/tutorial/netstd/README.md index 297f4ee326d..a49fb474bf1 100644 --- a/tutorial/netstd/README.md +++ b/tutorial/netstd/README.md @@ -13,13 +13,13 @@ # How to run -Depending on the platform, the name of the generated executables will vary. On Linux, it is just "client" or "server", on Windows it is "Client.exe" and "Server.exe". In the following, we use the abbreviated form "Client" and "Server". +Depending on the platform, the name of the generated executables will vary. On Linux, it is just "Client" or "Server", on Windows it is "Client.exe" and "Server.exe". In the following, we use the abbreviated form "Client" and "Server". - build - go to folder (Client/Server) - run the generated executables: server first, then client from a second console -#Known issues +# Known issues - In trace logging mode you can see some not important internal exceptions # Running of samples @@ -29,10 +29,10 @@ On machines that do not have the SDK installed, you need to install the NET Core Usage: - Server -h + Server -help will diplay help information - Server -tr: -pr: + Server -tr: -pr: will run server with specified arguments (tcp transport and binary protocol by default) Options: @@ -52,7 +52,8 @@ Options: binary - (default) binary protocol will be used compact - compact protocol will be used json - json protocol will be used - + multiplexed - multiplexed protocol will be used + Sample: Server -tr:tcp @@ -68,7 +69,7 @@ Sample: Usage: - Client -h + Client -help will diplay help information Client -tr: -pr: -mc: @@ -91,7 +92,8 @@ Options: binary - (default) binary protocol will be used compact - compact protocol will be used json - json protocol will be used - + multiplexed - multiplexed protocol will be used + -mc (multiple clients): - number of multiple clients to connect to server (max 100, default 1) @@ -237,16 +239,10 @@ class CalculatorHandler: val = work.Num1 * work.Num2 elif work.Op == Operation.Divide: if work.Num2 == 0: - x = InvalidOperation() - x.WhatOp = work.Op - x.Why = 'Cannot divide by 0' - raise x + raise InvalidOperation(work.Op, 'Cannot divide by 0') val = work.Num1 / work.Num2 else: - x = InvalidOperation() - x.WhatOp = work.Op - x.Why = 'Invalid operation' - raise x + raise InvalidOperation(work.Op, 'Invalid operation') log = SharedStruct() log.Key = logid diff --git a/tutorial/netstd/Server/Program.cs b/tutorial/netstd/Server/Program.cs index c1e0cb3ece9..3181e8e332a 100644 --- a/tutorial/netstd/Server/Program.cs +++ b/tutorial/netstd/Server/Program.cs @@ -51,26 +51,28 @@ public static void Main(string[] args) args = args ?? new string[0]; ServiceCollection.AddLogging(logging => ConfigureLogging(logging)); - Logger = ServiceCollection.BuildServiceProvider().GetService().CreateLogger(nameof(Server)); + using (var serviceProvider = ServiceCollection.BuildServiceProvider()) + { + Logger = serviceProvider.GetService().CreateLogger(nameof(Server)); + if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) + { + DisplayHelp(); + return; + } - if (args.Any(x => x.StartsWith("-help", StringComparison.OrdinalIgnoreCase))) - { - DisplayHelp(); - return; - } + using (var source = new CancellationTokenSource()) + { + RunAsync(args, source.Token).GetAwaiter().GetResult(); - using (var source = new CancellationTokenSource()) - { - RunAsync(args, source.Token).GetAwaiter().GetResult(); + Logger.LogInformation("Press any key to stop..."); - Logger.LogInformation("Press any key to stop..."); + Console.ReadLine(); + source.Cancel(); + } - Console.ReadLine(); - source.Cancel(); + Logger.LogInformation("Server stopped"); } - - Logger.LogInformation("Server stopped"); } private static void ConfigureLogging(ILoggingBuilder logging) @@ -84,10 +86,10 @@ private static void DisplayHelp() { Logger.LogInformation(@" Usage: - Server.exe -help + Server -help will diplay help information - Server.exe -tr: -bf: -pr: + Server -tr: -bf: -pr: will run server with specified arguments (tcp transport, no buffering, and binary protocol by default) Options: @@ -109,7 +111,7 @@ will run server with specified arguments (tcp transport, no buffering, and binar multiplexed - multiplexed protocol will be used Sample: - Server.exe -tr:tcp + Server -tr:tcp "); } diff --git a/tutorial/netstd/build.sh b/tutorial/netstd/build.sh old mode 100644 new mode 100755 From 45a94594ff50ad51a18f6ad1900209e978e5921b Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Sat, 11 Jan 2020 17:52:28 +0900 Subject: [PATCH 473/756] THRIFT-5061: Pin Ruby's rack version to 2.0.8 Client: ruby Patch: Kengo Seki This closes #1980 --- lib/rb/thrift.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rb/thrift.gemspec b/lib/rb/thrift.gemspec index 3ee7e7cbfef..c6f32cb9aea 100644 --- a/lib/rb/thrift.gemspec +++ b/lib/rb/thrift.gemspec @@ -31,7 +31,7 @@ Gem::Specification.new do |s| s.add_development_dependency 'pry', '~> 0.11.3' s.add_development_dependency 'pry-byebug', '~> 3.6' s.add_development_dependency 'pry-stack_explorer', '~> 0.4.9.2' - s.add_development_dependency 'rack', '~> 2.0' + s.add_development_dependency 'rack', '= 2.0.8' s.add_development_dependency 'rack-test', '~> 0.8.3' s.add_development_dependency 'rake', '~> 12.3' s.add_development_dependency 'rspec', '~> 3.7' From 70c4e7a7c7b2a2b4146372868702b7ea0d143e05 Mon Sep 17 00:00:00 2001 From: "D. Can Celasun" Date: Wed, 15 Jan 2020 21:12:53 +0000 Subject: [PATCH 474/756] Use HTTPS for repo1.maven.org Upstream no longer supports plain HTTP as of today [1]. [1] https://support.sonatype.com/hc/en-us/articles/360041287334 --- contrib/fb303/java/build.properties | 2 +- lib/as3/gradle.properties | 4 ++-- lib/java/gradle.properties | 4 ++-- lib/js/test/build.properties | 2 +- lib/json/test/build.properties | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/contrib/fb303/java/build.properties b/contrib/fb303/java/build.properties index 84636683c94..845048cad50 100644 --- a/contrib/fb303/java/build.properties +++ b/contrib/fb303/java/build.properties @@ -1,5 +1,5 @@ # Maven Ant tasks Jar details mvn.ant.task.version=2.1.3 -mvn.repo=http://repo1.maven.org/maven2 +mvn.repo=https://repo1.maven.org/maven2 mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version} mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar diff --git a/lib/as3/gradle.properties b/lib/as3/gradle.properties index d918a23f542..9ace275381c 100644 --- a/lib/as3/gradle.properties +++ b/lib/as3/gradle.properties @@ -14,10 +14,10 @@ install.javadoc.path=/usr/local/lib testPort=9090 # Maven dependency download locations -mvn.repo=http://repo1.maven.org/maven2 +mvn.repo=https://repo1.maven.org/maven2 apache.repo=https://repository.apache.org/content/repositories/releases # Apache Maven publish -license=http://www.apache.org/licenses/LICENSE-2.0.txt +license=https://www.apache.org/licenses/LICENSE-2.0.txt maven-repository-url=https://repository.apache.org/service/local/staging/deploy/maven2 maven-repository-id=apache.releases.https diff --git a/lib/java/gradle.properties b/lib/java/gradle.properties index 1cdf095b562..8a7acb10dc7 100644 --- a/lib/java/gradle.properties +++ b/lib/java/gradle.properties @@ -16,11 +16,11 @@ testPort=9090 cloverEnabled=false # Maven dependency download locations -mvn.repo=http://repo1.maven.org/maven2 +mvn.repo=https://repo1.maven.org/maven2 apache.repo=https://repository.apache.org/content/repositories/releases # Apache Maven publish -license=http://www.apache.org/licenses/LICENSE-2.0.txt +license=https://www.apache.org/licenses/LICENSE-2.0.txt maven-repository-url=https://repository.apache.org/service/local/staging/deploy/maven2 maven-repository-id=apache.releases.https diff --git a/lib/js/test/build.properties b/lib/js/test/build.properties index 84636683c94..845048cad50 100644 --- a/lib/js/test/build.properties +++ b/lib/js/test/build.properties @@ -1,5 +1,5 @@ # Maven Ant tasks Jar details mvn.ant.task.version=2.1.3 -mvn.repo=http://repo1.maven.org/maven2 +mvn.repo=https://repo1.maven.org/maven2 mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version} mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar diff --git a/lib/json/test/build.properties b/lib/json/test/build.properties index 075f6400189..997aa9bfa44 100644 --- a/lib/json/test/build.properties +++ b/lib/json/test/build.properties @@ -5,6 +5,6 @@ mvn.ant.task.version=2.1.3 json-schema-validator.version=2.2.6 # Maven dependency download locations -mvn.repo=http://repo1.maven.org/maven2 +mvn.repo=https://repo1.maven.org/maven2 mvn.ant.task.url=${mvn.repo}/org/apache/maven/maven-ant-tasks/${mvn.ant.task.version} mvn.ant.task.jar=maven-ant-tasks-${mvn.ant.task.version}.jar From a5ec666e1ba76fe7385ed56f484c9dfdd5b6bfc9 Mon Sep 17 00:00:00 2001 From: Christopher Tubbs Date: Fri, 17 Jan 2020 07:33:38 -0500 Subject: [PATCH 475/756] THRIFT-5068: Force secure Maven Central in Travis CI Modify docker build scripts used in CI test environments in order to put in place a Maven .m2/settings.xml configuration file that overrides the repository with the id 'central' with an equivalent "mirror" that uses https instead of http. This closes #1988. --- build/docker/scripts/autotools.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/build/docker/scripts/autotools.sh b/build/docker/scripts/autotools.sh index 8388f728ce2..52b17eee890 100755 --- a/build/docker/scripts/autotools.sh +++ b/build/docker/scripts/autotools.sh @@ -1,6 +1,19 @@ #!/bin/sh set -ev +mkdir ~/.m2 +tee >~/.m2/settings.xml < + + + secure-central + https://repo.maven.apache.org/maven2 + central + + + +EOF + ./bootstrap.sh ./configure $* make check -j3 From 397645ac24874b6f54d88b2700e56be090753825 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Sat, 18 Jan 2020 12:55:51 -0800 Subject: [PATCH 476/756] THRIFT-5069: Make TDeserializer resource pool friendly Client: go This change improves performance when using TDeserializer with a resource pool. See https://issues.apache.org/jira/browse/THRIFT-5069 for more context. Also add TSerializerPool and TDeserializerPool, which are thread-safe versions of TSerializer and TDeserializer. Benchmark result shows that they are both faster and use less memory than the plain version: $ go test -bench Serializer -benchmem goos: darwin goarch: amd64 BenchmarkSerializer/baseline-8 577558 1930 ns/op 512 B/op 6 allocs/op BenchmarkSerializer/plain-8 452712 2638 ns/op 2976 B/op 16 allocs/op BenchmarkSerializer/pool-8 591698 2032 ns/op 512 B/op 6 allocs/op PASS --- CHANGES.md | 6 + lib/go/thrift/deserializer.go | 46 ++++- lib/go/thrift/serializer.go | 34 ++++ lib/go/thrift/serializer_test.go | 325 +++++++++++++++++++++++-------- 4 files changed, 332 insertions(+), 79 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index e179a6375fa..1dddab99e6a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,10 +7,16 @@ - [THRIFT-4990](https://issues.apache.org/jira/browse/THRIFT-4990) - Upgrade to .NET Core 3.1 (LTS) - [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base - [THRIFT-5006](https://issues.apache.org/jira/browse/THRIFT-5006) - Implement DEFAULT_MAX_LENGTH at TFramedTransport +- [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - In Go library TDeserializer.Transport is now typed \*TMemoryBuffer instead of TTransport ### Java - [THRIFT-5022](https://issues.apache.org/jira/browse/THRIFT-5022) - TIOStreamTransport.isOpen returns true for one-sided transports (see THRIFT-2530). + +### Go + +- [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - Add TSerializerPool and TDeserializerPool, which are thread-safe versions of TSerializer and TDeserializer. + ## 0.13.0 ### New Languages diff --git a/lib/go/thrift/deserializer.go b/lib/go/thrift/deserializer.go index 91a0983a4ad..2ab82145ec0 100644 --- a/lib/go/thrift/deserializer.go +++ b/lib/go/thrift/deserializer.go @@ -19,14 +19,17 @@ package thrift +import ( + "sync" +) + type TDeserializer struct { - Transport TTransport + Transport *TMemoryBuffer Protocol TProtocol } func NewTDeserializer() *TDeserializer { - var transport TTransport - transport = NewTMemoryBufferLen(1024) + transport := NewTMemoryBufferLen(1024) protocol := NewTBinaryProtocolFactoryDefault().GetProtocol(transport) @@ -36,6 +39,8 @@ func NewTDeserializer() *TDeserializer { } func (t *TDeserializer) ReadString(msg TStruct, s string) (err error) { + t.Transport.Reset() + err = nil if _, err = t.Transport.Write([]byte(s)); err != nil { return @@ -47,6 +52,8 @@ func (t *TDeserializer) ReadString(msg TStruct, s string) (err error) { } func (t *TDeserializer) Read(msg TStruct, b []byte) (err error) { + t.Transport.Reset() + err = nil if _, err = t.Transport.Write(b); err != nil { return @@ -56,3 +63,36 @@ func (t *TDeserializer) Read(msg TStruct, b []byte) (err error) { } return } + +// TDeserializerPool is the thread-safe version of TDeserializer, +// it uses resource pool of TDeserializer under the hood. +// +// It must be initialized with NewTDeserializerPool. +type TDeserializerPool struct { + pool sync.Pool +} + +// NewTDeserializerPool creates a new TDeserializerPool. +// +// NewTDeserializer can be used as the arg here. +func NewTDeserializerPool(f func() *TDeserializer) *TDeserializerPool { + return &TDeserializerPool{ + pool: sync.Pool{ + New: func() interface{} { + return f() + }, + }, + } +} + +func (t *TDeserializerPool) ReadString(msg TStruct, s string) error { + d := t.pool.Get().(*TDeserializer) + defer t.pool.Put(d) + return d.ReadString(msg, s) +} + +func (t *TDeserializerPool) Read(msg TStruct, b []byte) error { + d := t.pool.Get().(*TDeserializer) + defer t.pool.Put(d) + return d.Read(msg, b) +} diff --git a/lib/go/thrift/serializer.go b/lib/go/thrift/serializer.go index 1ff4d37545a..d85d2049de7 100644 --- a/lib/go/thrift/serializer.go +++ b/lib/go/thrift/serializer.go @@ -21,6 +21,7 @@ package thrift import ( "context" + "sync" ) type TSerializer struct { @@ -77,3 +78,36 @@ func (t *TSerializer) Write(ctx context.Context, msg TStruct) (b []byte, err err b = append(b, t.Transport.Bytes()...) return } + +// TSerializerPool is the thread-safe version of TSerializer, it uses resource +// pool of TSerializer under the hood. +// +// It must be initialized with NewTSerializerPool. +type TSerializerPool struct { + pool sync.Pool +} + +// NewTSerializerPool creates a new TSerializerPool. +// +// NewTSerializer can be used as the arg here. +func NewTSerializerPool(f func() *TSerializer) *TSerializerPool { + return &TSerializerPool{ + pool: sync.Pool{ + New: func() interface{} { + return f() + }, + }, + } +} + +func (t *TSerializerPool) WriteString(ctx context.Context, msg TStruct) (string, error) { + s := t.pool.Get().(*TSerializer) + defer t.pool.Put(s) + return s.WriteString(ctx, msg) +} + +func (t *TSerializerPool) Write(ctx context.Context, msg TStruct) ([]byte, error) { + s := t.pool.Get().(*TSerializer) + defer t.pool.Put(s) + return s.Write(ctx, msg) +} diff --git a/lib/go/thrift/serializer_test.go b/lib/go/thrift/serializer_test.go index 32227ef4922..52ebdca890b 100644 --- a/lib/go/thrift/serializer_test.go +++ b/lib/go/thrift/serializer_test.go @@ -23,122 +23,193 @@ import ( "context" "errors" "fmt" + "sync" + "sync/atomic" "testing" + "testing/quick" ) type ProtocolFactory interface { GetProtocol(t TTransport) TProtocol } -func compareStructs(m, m1 MyTestStruct) (bool, error) { +func compareStructs(m, m1 MyTestStruct) error { switch { case m.On != m1.On: - return false, errors.New("Boolean not equal") + return errors.New("Boolean not equal") case m.B != m1.B: - return false, errors.New("Byte not equal") + return errors.New("Byte not equal") case m.Int16 != m1.Int16: - return false, errors.New("Int16 not equal") + return errors.New("Int16 not equal") case m.Int32 != m1.Int32: - return false, errors.New("Int32 not equal") + return errors.New("Int32 not equal") case m.Int64 != m1.Int64: - return false, errors.New("Int64 not equal") + return errors.New("Int64 not equal") case m.D != m1.D: - return false, errors.New("Double not equal") + return errors.New("Double not equal") case m.St != m1.St: - return false, errors.New("String not equal") + return errors.New("String not equal") case len(m.Bin) != len(m1.Bin): - return false, errors.New("Binary size not equal") + return errors.New("Binary size not equal") case len(m.Bin) == len(m1.Bin): for i := range m.Bin { if m.Bin[i] != m1.Bin[i] { - return false, errors.New("Binary not equal") + return errors.New("Binary not equal") } } case len(m.StringMap) != len(m1.StringMap): - return false, errors.New("StringMap size not equal") + return errors.New("StringMap size not equal") case len(m.StringList) != len(m1.StringList): - return false, errors.New("StringList size not equal") + return errors.New("StringList size not equal") case len(m.StringSet) != len(m1.StringSet): - return false, errors.New("StringSet size not equal") + return errors.New("StringSet size not equal") case m.E != m1.E: - return false, errors.New("MyTestEnum not equal") + return errors.New("MyTestEnum not equal") default: - return true, nil + return nil } - return true, nil + return nil } -func ProtocolTest1(test *testing.T, pf ProtocolFactory) (bool, error) { +type serializer interface { + WriteString(context.Context, TStruct) (string, error) +} + +type deserializer interface { + ReadString(TStruct, string) error +} + +func plainSerializer(pf ProtocolFactory) serializer { t := NewTSerializer() t.Protocol = pf.GetProtocol(t.Transport) - var m = MyTestStruct{} - m.On = true - m.B = int8(0) - m.Int16 = 1 - m.Int32 = 2 - m.Int64 = 3 - m.D = 4.1 - m.St = "Test" - m.Bin = make([]byte, 10) - m.StringMap = make(map[string]string, 5) - m.StringList = make([]string, 5) - m.StringSet = make(map[string]struct{}, 5) - m.E = 2 - - s, err := t.WriteString(context.Background(), &m) - if err != nil { - return false, errors.New(fmt.Sprintf("Unable to Serialize struct\n\t %s", err)) - } + return t +} - t1 := NewTDeserializer() - t1.Protocol = pf.GetProtocol(t1.Transport) - var m1 = MyTestStruct{} - if err = t1.ReadString(&m1, s); err != nil { - return false, errors.New(fmt.Sprintf("Unable to Deserialize struct\n\t %s", err)) +func poolSerializer(pf ProtocolFactory) serializer { + return NewTSerializerPool( + func() *TSerializer { + return plainSerializer(pf).(*TSerializer) + }, + ) +} - } +func plainDeserializer(pf ProtocolFactory) deserializer { + d := NewTDeserializer() + d.Protocol = pf.GetProtocol(d.Transport) + return d +} - return compareStructs(m, m1) +func poolDeserializer(pf ProtocolFactory) deserializer { + return NewTDeserializerPool( + func() *TDeserializer { + return plainDeserializer(pf).(*TDeserializer) + }, + ) +} +type constructors struct { + Label string + Serializer func(pf ProtocolFactory) serializer + Deserializer func(pf ProtocolFactory) deserializer } -func ProtocolTest2(test *testing.T, pf ProtocolFactory) (bool, error) { - t := NewTSerializer() - t.Protocol = pf.GetProtocol(t.Transport) - var m = MyTestStruct{} - m.On = false - m.B = int8(0) - m.Int16 = 1 - m.Int32 = 2 - m.Int64 = 3 - m.D = 4.1 - m.St = "Test" - m.Bin = make([]byte, 10) - m.StringMap = make(map[string]string, 5) - m.StringList = make([]string, 5) - m.StringSet = make(map[string]struct{}, 5) - m.E = 2 - - s, err := t.WriteString(context.Background(), &m) - if err != nil { - return false, errors.New(fmt.Sprintf("Unable to Serialize struct\n\t %s", err)) +var implementations = []constructors{ + { + Label: "plain", + Serializer: plainSerializer, + Deserializer: plainDeserializer, + }, + { + Label: "pool", + Serializer: poolSerializer, + Deserializer: poolDeserializer, + }, +} - } +func ProtocolTest1(t *testing.T, pf ProtocolFactory) { + for _, impl := range implementations { + t.Run( + impl.Label, + func(test *testing.T) { + t := impl.Serializer(pf) + var m = MyTestStruct{} + m.On = true + m.B = int8(0) + m.Int16 = 1 + m.Int32 = 2 + m.Int64 = 3 + m.D = 4.1 + m.St = "Test" + m.Bin = make([]byte, 10) + m.StringMap = make(map[string]string, 5) + m.StringList = make([]string, 5) + m.StringSet = make(map[string]struct{}, 5) + m.E = 2 + + s, err := t.WriteString(context.Background(), &m) + if err != nil { + test.Fatalf("Unable to Serialize struct: %v", err) + + } + + t1 := impl.Deserializer(pf) + var m1 MyTestStruct + if err = t1.ReadString(&m1, s); err != nil { + test.Fatalf("Unable to Deserialize struct: %v", err) - t1 := NewTDeserializer() - t1.Protocol = pf.GetProtocol(t1.Transport) - var m1 = MyTestStruct{} - if err = t1.ReadString(&m1, s); err != nil { - return false, errors.New(fmt.Sprintf("Unable to Deserialize struct\n\t %s", err)) + } + if err := compareStructs(m, m1); err != nil { + test.Error(err) + } + }, + ) } +} + +func ProtocolTest2(t *testing.T, pf ProtocolFactory) { + for _, impl := range implementations { + t.Run( + impl.Label, + func(test *testing.T) { + t := impl.Serializer(pf) + var m = MyTestStruct{} + m.On = false + m.B = int8(0) + m.Int16 = 1 + m.Int32 = 2 + m.Int64 = 3 + m.D = 4.1 + m.St = "Test" + m.Bin = make([]byte, 10) + m.StringMap = make(map[string]string, 5) + m.StringList = make([]string, 5) + m.StringSet = make(map[string]struct{}, 5) + m.E = 2 + + s, err := t.WriteString(context.Background(), &m) + if err != nil { + test.Fatalf("Unable to Serialize struct: %v", err) + + } - return compareStructs(m, m1) + t1 := impl.Deserializer(pf) + var m1 MyTestStruct + if err = t1.ReadString(&m1, s); err != nil { + test.Fatalf("Unable to Deserialize struct: %v", err) + } + + if err := compareStructs(m, m1); err != nil { + test.Error(err) + } + }, + ) + } } func TestSerializer(t *testing.T) { @@ -150,21 +221,123 @@ func TestSerializer(t *testing.T) { //protocol_factories["SimpleJSON"] = NewTSimpleJSONProtocolFactory() - write only, can't be read back by design protocol_factories["JSON"] = NewTJSONProtocolFactory() - var tests map[string]func(*testing.T, ProtocolFactory) (bool, error) - tests = make(map[string]func(*testing.T, ProtocolFactory) (bool, error)) + tests := make(map[string]func(*testing.T, ProtocolFactory)) tests["Test 1"] = ProtocolTest1 tests["Test 2"] = ProtocolTest2 //tests["Test 3"] = ProtocolTest3 // Example of how to add additional tests for name, pf := range protocol_factories { + t.Run( + name, + func(t *testing.T) { + for label, f := range tests { + t.Run( + label, + func(t *testing.T) { + f(t, pf) + }, + ) + } + }, + ) + } + +} - for test, f := range tests { +func TestSerializerPoolAsync(t *testing.T) { + var wg sync.WaitGroup + var counter int64 + s := NewTSerializerPool(NewTSerializer) + d := NewTDeserializerPool(NewTDeserializer) + f := func(i int64) bool { + wg.Add(1) + go func() { + defer wg.Done() + t.Run( + fmt.Sprintf("#%d-%d", atomic.AddInt64(&counter, 1), i), + func(t *testing.T) { + m := MyTestStruct{ + Int64: i, + } + str, err := s.WriteString(context.Background(), &m) + if err != nil { + t.Fatal("serialize:", err) + } + var m1 MyTestStruct + if err = d.ReadString(&m1, str); err != nil { + t.Fatal("deserialize:", err) - if s, err := f(t, pf); !s || err != nil { - t.Errorf("%s Failed for %s protocol\n\t %s", test, name, err) - } + } - } + if err := compareStructs(m, m1); err != nil { + t.Error(err) + } + }, + ) + }() + return true + } + quick.Check(f, nil) + wg.Wait() +} + +func BenchmarkSerializer(b *testing.B) { + sharedSerializer := NewTSerializer() + poolSerializer := NewTSerializerPool(NewTSerializer) + sharedDeserializer := NewTDeserializer() + poolDeserializer := NewTDeserializerPool(NewTDeserializer) + + cases := []struct { + Label string + Serializer func() serializer + Deserializer func() deserializer + }{ + { + // Baseline uses shared plain serializer/deserializer + Label: "baseline", + Serializer: func() serializer { + return sharedSerializer + }, + Deserializer: func() deserializer { + return sharedDeserializer + }, + }, + { + // Plain creates new serializer/deserializer on every run, + // as that's how it's used in real world + Label: "plain", + Serializer: func() serializer { + return NewTSerializer() + }, + Deserializer: func() deserializer { + return NewTDeserializer() + }, + }, + { + // Pool uses the shared pool serializer/deserializer + Label: "pool", + Serializer: func() serializer { + return poolSerializer + }, + Deserializer: func() deserializer { + return poolDeserializer + }, + }, } + for _, c := range cases { + b.Run( + c.Label, + func(b *testing.B) { + for i := 0; i < b.N; i++ { + s := c.Serializer() + m := MyTestStruct{} + str, _ := s.WriteString(context.Background(), &m) + var m1 MyTestStruct + d := c.Deserializer() + d.ReadString(&m1, str) + } + }, + ) + } } From 1c789cea1e59d457379ca10bdcb8f4ac4632dec9 Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Mon, 13 Jan 2020 10:48:58 +0900 Subject: [PATCH 477/756] THRIFT-5065: Fix broken links in the IDL document Patch: Kengo Seki This closes #1983 --- doc/specs/idl.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/specs/idl.md b/doc/specs/idl.md index 32763a6b6b8..df7e8d73263 100644 --- a/doc/specs/idl.md +++ b/doc/specs/idl.md @@ -224,8 +224,8 @@ Here are some examples of Thrift definitions, using the Thrift IDL: [tutorial]: /tutorial/ [fb303.thrift]: https://raw.githubusercontent.com/apache/thrift/master/contrib/fb303/if/fb303.thrift [Apache Cassandra's]: http://cassandra.apache.org/ - [cassandra.thrift]: http://svn.apache.org/viewvc/cassandra/trunk/interface/cassandra.thrift?view=co - [Evernote API]: http://www.evernote.com/about/developer/api/ + [cassandra.thrift]: https://gitbox.apache.org/repos/asf?p=cassandra.git;a=blob_plain;f=interface/cassandra.thrift;hb=refs/heads/cassandra-3.0 + [Evernote API]: https://github.com/evernote/evernote-thrift ## To Do/Questions From 46554d0a4c741a886bf1e2cb9e0dd529eb94a387 Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Fri, 27 Dec 2019 07:56:12 +0900 Subject: [PATCH 478/756] THRIFT-5051: Fix Python tutorials to address THRIFT-4002 Client: Python Patch: Kengo Seki This closes #1968 --- tutorial/py.tornado/PythonServer.py | 10 ++-------- tutorial/py.twisted/PythonServer.py | 10 ++-------- tutorial/py/PythonServer.py | 10 ++-------- 3 files changed, 6 insertions(+), 24 deletions(-) diff --git a/tutorial/py.tornado/PythonServer.py b/tutorial/py.tornado/PythonServer.py index e0229a26e09..b472195a498 100755 --- a/tutorial/py.tornado/PythonServer.py +++ b/tutorial/py.tornado/PythonServer.py @@ -58,16 +58,10 @@ def calculate(self, logid, work): val = work.num1 * work.num2 elif work.op == Operation.DIVIDE: if work.num2 == 0: - x = InvalidOperation() - x.whatOp = work.op - x.why = "Cannot divide by 0" - raise x + raise InvalidOperation(work.op, "Cannot divide by 0") val = work.num1 / work.num2 else: - x = InvalidOperation() - x.whatOp = work.op - x.why = "Invalid operation" - raise x + raise InvalidOperation(work.op, "Invalid operation") log = SharedStruct() log.key = logid diff --git a/tutorial/py.twisted/PythonServer.py b/tutorial/py.twisted/PythonServer.py index 034e4a3129d..c3e64db5c33 100755 --- a/tutorial/py.twisted/PythonServer.py +++ b/tutorial/py.twisted/PythonServer.py @@ -60,16 +60,10 @@ def calculate(self, logid, work): val = work.num1 * work.num2 elif work.op == Operation.DIVIDE: if work.num2 == 0: - x = InvalidOperation() - x.whatOp = work.op - x.why = 'Cannot divide by 0' - raise x + raise InvalidOperation(work.op, 'Cannot divide by 0') val = work.num1 / work.num2 else: - x = InvalidOperation() - x.whatOp = work.op - x.why = 'Invalid operation' - raise x + raise InvalidOperation(work.op, 'Invalid operation') log = SharedStruct() log.key = logid diff --git a/tutorial/py/PythonServer.py b/tutorial/py/PythonServer.py index e6421ef0815..d2343edd3d3 100755 --- a/tutorial/py/PythonServer.py +++ b/tutorial/py/PythonServer.py @@ -57,16 +57,10 @@ def calculate(self, logid, work): val = work.num1 * work.num2 elif work.op == Operation.DIVIDE: if work.num2 == 0: - x = InvalidOperation() - x.whatOp = work.op - x.why = 'Cannot divide by 0' - raise x + raise InvalidOperation(work.op, 'Cannot divide by 0') val = work.num1 / work.num2 else: - x = InvalidOperation() - x.whatOp = work.op - x.why = 'Invalid operation' - raise x + raise InvalidOperation(work.op, 'Invalid operation') log = SharedStruct() log.key = logid From c97e6aa8604fed4a889b6c0a413e085371de6608 Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Fri, 10 Jan 2020 01:11:15 +0900 Subject: [PATCH 479/756] THRIFT-5060: Add cross tests for TZlibTransport in Java Client: Java Patch: Kengo Seki This closes #1978 --- .../org/apache/thrift/test/TestClient.java | 25 ++++++++++++++----- .../org/apache/thrift/test/TestServer.java | 10 +++++++- test/tests.json | 3 ++- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/lib/java/test/org/apache/thrift/test/TestClient.java b/lib/java/test/org/apache/thrift/test/TestClient.java index dbada08ffa2..b402854f1ba 100644 --- a/lib/java/test/org/apache/thrift/test/TestClient.java +++ b/lib/java/test/org/apache/thrift/test/TestClient.java @@ -44,6 +44,7 @@ import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.transport.TTransportException; +import org.apache.thrift.transport.TZlibTransport; // Generated code import thrift.test.Insanity; @@ -77,6 +78,7 @@ public static void main(String [] args) { String protocol_type = "binary"; String transport_type = "buffered"; boolean ssl = false; + boolean zlib = false; boolean http_client = false; int socketTimeout = 1000; @@ -101,6 +103,8 @@ public static void main(String [] args) { transport_type.trim(); } else if (args[i].equals("--ssl")) { ssl = true; + } else if (args[i].equals("--zlib")) { + zlib = true; } else if (args[i].equals("--client")) { http_client = true; } else if (args[i].equals("--help")) { @@ -108,9 +112,10 @@ public static void main(String [] args) { System.out.println(" --help\t\t\tProduce help message"); System.out.println(" --host=arg (=" + host + ")\tHost to connect"); System.out.println(" --port=arg (=" + port + ")\tPort number to connect"); - System.out.println(" --transport=arg (=" + transport_type + ")\n\t\t\t\tTransport: buffered, framed, fastframed, http"); + System.out.println(" --transport=arg (=" + transport_type + ")\n\t\t\t\tTransport: buffered, framed, fastframed, http, zlib"); System.out.println(" --protocol=arg (=" + protocol_type + ")\tProtocol: binary, compact, json, multi, multic, multij"); System.out.println(" --ssl\t\t\tEncrypted Transport using SSL"); + System.out.println(" --zlib\t\t\tCompressed Transport using Zlib"); System.out.println(" --testloops[--n]=arg (=" + numTests + ")\tNumber of Tests"); System.exit(0); } @@ -134,6 +139,7 @@ public static void main(String [] args) { } else if (transport_type.equals("framed")) { } else if (transport_type.equals("fastframed")) { } else if (transport_type.equals("http")) { + } else if (transport_type.equals("zlib")) { } else { throw new Exception("Unknown transport type! " + transport_type); } @@ -165,11 +171,18 @@ public static void main(String [] args) { } socket.setTimeout(socketTimeout); transport = socket; - if (transport_type.equals("buffered")) { - } else if (transport_type.equals("framed")) { - transport = new TFramedTransport(transport); - } else if (transport_type.equals("fastframed")) { - transport = new TFastFramedTransport(transport); + if (transport_type.equals("zlib")) { + transport = new TZlibTransport(transport); + } else { + if (transport_type.equals("buffered")) { + } else if (transport_type.equals("framed")) { + transport = new TFramedTransport(transport); + } else if (transport_type.equals("fastframed")) { + transport = new TFastFramedTransport(transport); + } + if (zlib) { + transport = new TZlibTransport(transport); + } } } } catch (Exception x) { diff --git a/lib/java/test/org/apache/thrift/test/TestServer.java b/lib/java/test/org/apache/thrift/test/TestServer.java index 1f3e555d977..25a329c5c42 100644 --- a/lib/java/test/org/apache/thrift/test/TestServer.java +++ b/lib/java/test/org/apache/thrift/test/TestServer.java @@ -42,6 +42,7 @@ import org.apache.thrift.server.TNonblockingServer; import org.apache.thrift.transport.TFramedTransport; import org.apache.thrift.transport.TFastFramedTransport; +import org.apache.thrift.transport.TZlibTransport; import org.apache.thrift.transport.TServerSocket; import org.apache.thrift.transport.TSSLTransportFactory; import org.apache.thrift.transport.TTransport; @@ -127,6 +128,7 @@ public static void main(String [] args) { try { int port = 9090; boolean ssl = false; + boolean zlib = false; String transport_type = "buffered"; String protocol_type = "binary"; String server_type = "thread-pool"; @@ -150,6 +152,8 @@ public static void main(String [] args) { transport_type.trim(); } else if (args[i].equals("--ssl")) { ssl = true; + } else if (args[i].equals("--zlib")) { + zlib = true; } else if (args[i].startsWith("--string-limit")) { string_limit = Integer.valueOf(args[i].split("=")[1]); } else if (args[i].startsWith("--container-limit")) { @@ -158,9 +162,10 @@ public static void main(String [] args) { System.out.println("Allowed options:"); System.out.println(" --help\t\t\tProduce help message"); System.out.println(" --port=arg (=" + port + ")\tPort number to connect"); - System.out.println(" --transport=arg (=" + transport_type + ")\n\t\t\t\tTransport: buffered, framed, fastframed"); + System.out.println(" --transport=arg (=" + transport_type + ")\n\t\t\t\tTransport: buffered, framed, fastframed, zlib"); System.out.println(" --protocol=arg (=" + protocol_type + ")\tProtocol: binary, compact, json, multi, multic, multij"); System.out.println(" --ssl\t\t\tEncrypted Transport using SSL"); + System.out.println(" --zlib\t\t\tCompressed Transport using Zlib"); System.out.println(" --server-type=arg (=" + server_type +")\n\t\t\t\tType of server: simple, thread-pool, nonblocking, threaded-selector"); System.out.println(" --string-limit=arg (=" + string_limit + ")\tString read length limit"); System.out.println(" --container-limit=arg (=" + container_limit + ")\tContainer read length limit"); @@ -198,6 +203,7 @@ public static void main(String [] args) { if (transport_type.equals("buffered")) { } else if (transport_type.equals("framed")) { } else if (transport_type.equals("fastframed")) { + } else if (transport_type.equals("zlib")) { } else { throw new Exception("Unknown transport type! " + transport_type); } @@ -229,6 +235,8 @@ public static void main(String [] args) { tTransportFactory = new TFramedTransport.Factory(); } else if (transport_type.equals("fastframed")) { tTransportFactory = new TFastFramedTransport.Factory(); + } else if (transport_type.equals("zlib")) { + tTransportFactory = new TZlibTransport.Factory(); } else { // .equals("buffered") => default value tTransportFactory = new TTransportFactory(); } diff --git a/test/tests.json b/test/tests.json index b8b85be73a8..fc9046b49a2 100644 --- a/test/tests.json +++ b/test/tests.json @@ -152,7 +152,8 @@ "transports": [ "buffered", "framed", - "framed:fastframed" + "framed:fastframed", + "zlib" ], "sockets": [ "ip", From d082d1d61b024e441df21b8b46a6261d7f955405 Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Sun, 29 Dec 2019 15:11:42 +0900 Subject: [PATCH 480/756] THRIFT-5052: Make the Go tutorial executable to the end Client: Go Patch: Kengo Seki This closes #1969 --- tutorial/go/src/client.go | 1 - 1 file changed, 1 deletion(-) diff --git a/tutorial/go/src/client.go b/tutorial/go/src/client.go index e3ebe00dffb..319ca3e6eed 100644 --- a/tutorial/go/src/client.go +++ b/tutorial/go/src/client.go @@ -49,7 +49,6 @@ func handleClient(client *tutorial.CalculatorClient) (err error) { default: fmt.Println("Error during operation:", err) } - return err } else { fmt.Println("Whoa we can divide by 0 with new value:", quotient) } From 829b7d330d8e626808887b3e1072ec3e3051805b Mon Sep 17 00:00:00 2001 From: JackBoosY Date: Thu, 16 Jan 2020 00:38:15 -0800 Subject: [PATCH 481/756] Add vcpkg installation instructions Patch: JackBoosY, edited by JensG This closes #1986 --- README.md | 8 ++++++++ lib/cpp/README.md | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/README.md b/README.md index 2e8a28a9644..4bd2366139e 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,14 @@ to Java, Ruby, PHP). Look for the README.md file in the lib// folder for more details on the installation of each language library package. +Package Managers +================ + +Apache Thrift is available via a number of package managers, a list which is +is steadily growing. A more detailed overview can be found +[at the Apache Thrift web site under "Libraries"](http://thrift.apache.org/lib/) +and/or in the respecitive READMEs for each language under /lib + Testing ======= diff --git a/lib/cpp/README.md b/lib/cpp/README.md index 8a897d1ef4d..8074484f197 100755 --- a/lib/cpp/README.md +++ b/lib/cpp/README.md @@ -98,6 +98,24 @@ http://monkey.org/~provos/libevent/ The Thrift library targets Windows 7 or latter versions. The supports for windows XP and Vista are avaiable until 0.12.0. +## Thrift and the VCPKG Package manager + +You can download and install thrift using the +[vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + ./vcpkg install thrift + +The thrift port in vcpkg is kept up to date by Microsoft team members +and community contributors. The Apache Thrift project is *not* responsible +for the vcpkg port. Therefore, if the version is out of date, please +[create an issue or pull request](https://github.com/Microsoft/vcpkg) +on the vcpkg repository. + + ## Named Pipes Named Pipe transport has been added in the TPipe and TPipeServer classes. This From 3a2a44bb51cb4cc5480d4b97f5bc6a4fe6228b0a Mon Sep 17 00:00:00 2001 From: Cameron Rollheiser Date: Tue, 21 Jan 2020 12:02:22 -0500 Subject: [PATCH 482/756] Remove non-required JS dependencies These dependencies are not needed at runtime. Client: js --- lib/js/package.json | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/js/package.json b/lib/js/package.json index b75019deb05..dc48846076a 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -13,7 +13,6 @@ "license": "Apache-2.0", "devDependencies": { "browserify": "~16.2", - "grunt": "~1.0", "grunt-cli": "~1.3", "grunt-contrib-concat": "~1.0", "grunt-contrib-jshint": "~2.1", @@ -21,12 +20,11 @@ "grunt-contrib-uglify": "~4.0", "grunt-jsdoc": "~2.3", "grunt-shell-spawn": "~0.4", - "jslint": "~0.12", - "node-int64": "~0.4.0" - }, - "dependencies": { + "grunt": "~1.0", "jsdoc": "~3.5", + "jslint": "~0.12", "json-int64": "~1.0", + "node-int64": "~0.4.0", "nopt": "~4.0" } } From a86a3549cff1643b94438c8afc0fec5e5c6ade4f Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 23 Jan 2020 22:59:19 +0100 Subject: [PATCH 483/756] THRIFT-5074 Cleanup of test suite command line options Client: Documentation Patch: Jens Geyer & Kengo Seki This closes #1990 --- test/README.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/test/README.md b/test/README.md index 19cc2a1a700..8cb2af9eb47 100755 --- a/test/README.md +++ b/test/README.md @@ -121,7 +121,7 @@ line interface: **Server command line interface:** - $ ./cpp/TestServer -h + $ ./TestServer -h Allowed options: -h [ --help ] produce help message --port arg (=9090) Port number to listen @@ -129,16 +129,20 @@ line interface: --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) --server-type arg (=simple) type of server, "simple", "thread-pool", "threaded", or "nonblocking" - --transport arg (=buffered) transport: buffered, framed, http, anonpipe - --protocol arg (=binary) protocol: binary, compact, json + --transport arg (=buffered) transport: buffered, framed, http, anonpipe, zlib + --protocol arg (=binary) protocol: binary, compact, header, json + --multiplex Add TMultiplexedProtocol service name "ThriftTest" + --abstract-namespace Create the domain socket in the Abstract Namespace + (no connection with filesystem pathnames) --ssl Encrypted Transport using SSL + --zlib Wrapped Transport using Zlib --processor-events processor-events -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for - thread-pool server type + thread-pool server type **Client command line interface:** - $ ./cpp/TestClient -h + $ ./TestClient -h Allowed options: -h [ --help ] produce help message --host arg (=localhost) Host to connect @@ -147,9 +151,13 @@ line interface: instead of host and port --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles) - --transport arg (=buffered) Transport: buffered, framed, http, evhttp - --protocol arg (=binary) Protocol: binary, compact, json + --abstract-namespace Create the domain socket in the Abstract Namespace + (no connection with filesystem pathnames) + --transport arg (=buffered) Transport: buffered, framed, http, evhttp, zlib + --protocol arg (=binary) Protocol: binary, compact, header, json + --multiplex Add TMultiplexedProtocol service name "ThriftTest" --ssl Encrypted Transport using SSL + --zlib Wrap Transport with Zlib -n [ --testloops ] arg (=1) Number of Tests -t [ --threads ] arg (=1) Number of Test threads From 436bce33215a918ebdc89596bc3c5bfafb33feea Mon Sep 17 00:00:00 2001 From: Sam De Roeck Date: Tue, 12 Nov 2019 17:44:06 +0100 Subject: [PATCH 484/756] (no ticket) Gracefully terminate the connection handling loop when encountering EOF on the transport layer Client: Rust Patch: Sam De Roeck This closes #1928 --- lib/rs/src/server/threaded.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/rs/src/server/threaded.rs b/lib/rs/src/server/threaded.rs index ebd37207d2e..5e253f716b8 100644 --- a/lib/rs/src/server/threaded.rs +++ b/lib/rs/src/server/threaded.rs @@ -24,6 +24,7 @@ use transport::{TIoChannel, TReadTransportFactory, TTcpChannel, TWriteTransportF use {ApplicationError, ApplicationErrorKind}; use super::TProcessor; +use TransportErrorKind; /// Fixed-size thread-pool blocking Thrift server. /// @@ -223,10 +224,15 @@ fn handle_incoming_connection( let mut i_prot = i_prot; let mut o_prot = o_prot; loop { - let r = processor.process(&mut *i_prot, &mut *o_prot); - if let Err(e) = r { - warn!("processor completed with error: {:?}", e); - break; + match processor.process(&mut *i_prot, &mut *o_prot) { + Ok(()) => {}, + Err(err) => { + match err { + ::Error::Transport(ref transport_err) if transport_err.kind == TransportErrorKind::EndOfFile => {}, + other => warn!("processor completed with error: {:?}", other), + } + break; + } } } } From e8f82da45e63a6477e4165e80358d613de689a82 Mon Sep 17 00:00:00 2001 From: David Mollitor Date: Mon, 23 Dec 2019 10:28:31 -0500 Subject: [PATCH 485/756] THRIFT-5016 Do Not Check 'other' For Null in Equals Client: Java Patch: David Mollitor This closes #1937 --- compiler/cpp/src/thrift/generate/t_java_generator.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_java_generator.cc b/compiler/cpp/src/thrift/generate/t_java_generator.cc index 18055855bfe..24637d31c1d 100644 --- a/compiler/cpp/src/thrift/generate/t_java_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_java_generator.cc @@ -1912,8 +1912,7 @@ void t_java_generator::generate_java_struct_equality(ostream& out, t_struct* tst out << indent() << "@Override" << endl << indent() << "public boolean equals(java.lang.Object that) {" << endl; indent_up(); - out << indent() << "if (that == null)" << endl << indent() << " return false;" << endl - << indent() << "if (that instanceof " << tstruct->get_name() << ")" << endl << indent() + out << indent() << "if (that instanceof " << tstruct->get_name() << ")" << endl << indent() << " return this.equals((" << tstruct->get_name() << ")that);" << endl << indent() << "return false;" << endl; scope_down(out); From e56f717b7f62ba5b1ace7382d728ac7f0fda940f Mon Sep 17 00:00:00 2001 From: Nick Collier Date: Wed, 18 Dec 2019 10:54:27 +0000 Subject: [PATCH 486/756] THRIFT-5078 Handle named pipe clients quickly disconnecting Client: C++ Patch: Nick Collier This closes #1964 --- lib/cpp/src/thrift/server/TServerFramework.cpp | 5 +++-- lib/cpp/src/thrift/transport/TPipeServer.cpp | 14 +++++++++++++- lib/cpp/src/thrift/transport/TTransportException.h | 3 ++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/cpp/src/thrift/server/TServerFramework.cpp b/lib/cpp/src/thrift/server/TServerFramework.cpp index 35f3b254d88..302cbf1662f 100644 --- a/lib/cpp/src/thrift/server/TServerFramework.cpp +++ b/lib/cpp/src/thrift/server/TServerFramework.cpp @@ -166,8 +166,9 @@ void TServerFramework::serve() { releaseOneDescriptor("inputTransport", inputTransport); releaseOneDescriptor("outputTransport", outputTransport); releaseOneDescriptor("client", client); - if (ttx.getType() == TTransportException::TIMED_OUT) { - // Accept timeout - continue processing. + if (ttx.getType() == TTransportException::TIMED_OUT + || ttx.getType() == TTransportException::CLIENT_DISCONNECT) { + // Accept timeout and client disconnect - continue processing. continue; } else if (ttx.getType() == TTransportException::END_OF_FILE || ttx.getType() == TTransportException::INTERRUPTED) { diff --git a/lib/cpp/src/thrift/transport/TPipeServer.cpp b/lib/cpp/src/thrift/transport/TPipeServer.cpp index 47d882251b5..f0d1e70f532 100644 --- a/lib/cpp/src/thrift/transport/TPipeServer.cpp +++ b/lib/cpp/src/thrift/transport/TPipeServer.cpp @@ -286,8 +286,20 @@ shared_ptr TNamedPipeServer::acceptImpl() { // concurrently with interrupt, and that should be fine. if (GetOverlappedResult(Pipe_.h, &connectOverlap_.overlap, &dwDummy, TRUE)) { TAutoCrit lock(pipe_protect_); + shared_ptr client; + try { + client.reset(new TPipe(Pipe_)); + } catch (TTransportException& ttx) { + if (ttx.getType() == TTransportException::INTERRUPTED) { + throw; + } + + GlobalOutput.perror("Client connection failed. TTransportExceptionType=", ttx.getType()); + // kick off the next connection before throwing + initiateNamedConnect(lock); + throw TTransportException(TTransportException::CLIENT_DISCONNECT, ttx.what()); + } GlobalOutput.printf("Client connected."); - shared_ptr client(new TPipe(Pipe_)); // kick off the next connection before returning initiateNamedConnect(lock); return client; // success! diff --git a/lib/cpp/src/thrift/transport/TTransportException.h b/lib/cpp/src/thrift/transport/TTransportException.h index 38b75211fe6..dd5f361f151 100644 --- a/lib/cpp/src/thrift/transport/TTransportException.h +++ b/lib/cpp/src/thrift/transport/TTransportException.h @@ -49,7 +49,8 @@ class TTransportException : public apache::thrift::TException { INTERRUPTED = 4, BAD_ARGS = 5, CORRUPTED_DATA = 6, - INTERNAL_ERROR = 7 + INTERNAL_ERROR = 7, + CLIENT_DISCONNECT = 8 }; TTransportException() : apache::thrift::TException(), type_(UNKNOWN) {} From cb4c31a0720e5449ac562b65ac7916f583d0cb7f Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Thu, 26 Dec 2019 14:34:57 +0900 Subject: [PATCH 487/756] THRIFT-5050 Fix MemoryBuffer.pm to raise a proper exception if no data is available Client: perl Patch: Kengo Seki This closes #1967 --- build/docker/ubuntu-bionic/Dockerfile | 3 ++- build/docker/ubuntu-disco/Dockerfile | 3 ++- build/docker/ubuntu-xenial/Dockerfile | 3 ++- lib/perl/Makefile.PL | 3 +++ lib/perl/README.md | 6 ++++++ lib/perl/lib/Thrift/MemoryBuffer.pm | 2 +- lib/perl/t/memory_buffer.t | 5 ++++- 7 files changed, 20 insertions(+), 5 deletions(-) diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index 79d698f2743..fa8a2da3ad7 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -203,7 +203,8 @@ RUN apt-get install -y --no-install-recommends \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ - libnet-ssleay-perl + libnet-ssleay-perl \ + libtest-exception-perl RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ diff --git a/build/docker/ubuntu-disco/Dockerfile b/build/docker/ubuntu-disco/Dockerfile index 95a2c780b73..fd9464b7731 100644 --- a/build/docker/ubuntu-disco/Dockerfile +++ b/build/docker/ubuntu-disco/Dockerfile @@ -204,7 +204,8 @@ RUN apt-get install -y --no-install-recommends \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ - libnet-ssleay-perl + libnet-ssleay-perl \ + libtest-exception-perl RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index 8df08873916..af91e1b3db0 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -213,7 +213,8 @@ RUN apt-get install -y --no-install-recommends \ libclass-accessor-class-perl \ libcrypt-ssleay-perl \ libio-socket-ssl-perl \ - libnet-ssleay-perl + libnet-ssleay-perl \ + libtest-exception-perl RUN apt-get install -y --no-install-recommends \ `# Php dependencies` \ diff --git a/lib/perl/Makefile.PL b/lib/perl/Makefile.PL index 5e60ab40aee..b72a23e3b1a 100644 --- a/lib/perl/Makefile.PL +++ b/lib/perl/Makefile.PL @@ -34,6 +34,9 @@ WriteMakefile( ABSTRACT => 'Apache Thrift is a software framework for scalable c 'Class::Accessor' => 0 }, # SIGN => 1, + TEST_REQUIRES => { + 'Test::Exception' => 0, + }, VERSION_FROM => 'lib/Thrift.pm' ); # THRIFT-4691 diff --git a/lib/perl/README.md b/lib/perl/README.md index bd1e5b2e496..6958510374d 100644 --- a/lib/perl/README.md +++ b/lib/perl/README.md @@ -61,6 +61,12 @@ to use Thrift. * Bit::Vector * Class::Accessor +## Test + +This is only required when running tests: + + * Test::Exception + ### HttpClient Transport These are only required if using Thrift::HttpClient: diff --git a/lib/perl/lib/Thrift/MemoryBuffer.pm b/lib/perl/lib/Thrift/MemoryBuffer.pm index be97ce4f8e2..5192cfb99a3 100644 --- a/lib/perl/lib/Thrift/MemoryBuffer.pm +++ b/lib/perl/lib/Thrift/MemoryBuffer.pm @@ -117,7 +117,7 @@ sub readAll my $avail = ($self->{wPos} - $self->{rPos}); if ($avail < $len) { - die TTransportException->new("Attempt to readAll($len) found only $avail available", + die Thrift::TTransportException->new("Attempt to readAll($len) found only $avail available", Thrift::TTransportException::END_OF_FILE); } diff --git a/lib/perl/t/memory_buffer.t b/lib/perl/t/memory_buffer.t index 8fa9fd72e79..4a4ba0f7d9b 100644 --- a/lib/perl/t/memory_buffer.t +++ b/lib/perl/t/memory_buffer.t @@ -17,7 +17,8 @@ # under the License. # -use Test::More tests => 6; +use Test::More tests => 7; +use Test::Exception; use strict; use warnings; @@ -33,6 +34,8 @@ use ThriftTest::Types; my $transport = Thrift::MemoryBuffer->new(); my $protocol = Thrift::BinaryProtocol->new($transport); +throws_ok { $protocol->readByte } 'Thrift::TTransportException'; + my $a = ThriftTest::Xtruct->new(); $a->i32_thing(10); $a->i64_thing(30); From f8b004081da0c5006c3a0ce0352b66d2d857405e Mon Sep 17 00:00:00 2001 From: Christopher Friedt Date: Wed, 29 Jan 2020 03:03:46 -0500 Subject: [PATCH 488/756] Fix typo for python 3 support This change simply enables the existing check in configure.ac to function as intended. Signed-off-by: Christopher Friedt --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 64283a8efaf..f3f88a7156c 100755 --- a/configure.ac +++ b/configure.ac @@ -325,7 +325,7 @@ AM_CONDITIONAL(WITH_TWISTED_TEST, [test "$have_trial" = "yes"]) have_py3="no" AX_THRIFT_LIB(py3, [Py3], yes) if test "$with_py3" = "yes"; then - if $PYTHON --version 2>&1 | grep -q "Python 2"; then + if $PYTHON --version 2>&1 | grep -q "Python 3"; then AC_PATH_PROGS([PYTHON3], [python3 python3.7 python37 python3.6 python36 python3.5 python35 python3.4 python34]) if test -n "$PYTHON3"; then have_py3="yes" From f049ff374dd8232a1b4e2b3e01f7530936cae0d0 Mon Sep 17 00:00:00 2001 From: Paulo Neves Date: Wed, 5 Feb 2020 11:58:18 +0100 Subject: [PATCH 489/756] THRIFT-5083 Reset context on new messages. Client: netstd Patch: Paulo Neves This closes # --- lib/netstd/Thrift/Protocol/TJSONProtocol.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs index 7bc713054aa..3b2ed06cbc9 100644 --- a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs @@ -83,6 +83,16 @@ protected void PopContext() Context = ContextStack.Pop(); } + /// + /// Resets the context stack to pristine state. Allows for reusal of the protocol + /// even in cases where the protocol instance was in an undefined state due to + /// dangling/stale/obsolete contexts + /// + private void resetContext() + { + ContextStack.Clear(); + Context = new JSONBaseContext(this); + } /// /// Read a byte that must match b[0]; otherwise an exception is thrown. /// Marked protected to avoid synthetic accessor in JSONListContext.Read @@ -267,6 +277,7 @@ private async Task WriteJsonArrayEndAsync(CancellationToken cancellationToken) public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) { + resetContext(); await WriteJsonArrayStartAsync(cancellationToken); await WriteJsonIntegerAsync(Version, cancellationToken); @@ -645,6 +656,8 @@ private async Task ReadJsonArrayEndAsync(CancellationToken cancellationToken) public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { var message = new TMessage(); + + resetContext(); await ReadJsonArrayStartAsync(cancellationToken); if (await ReadJsonIntegerAsync(cancellationToken) != Version) { From 68b113a73e2fbbaa5d94e1f077c60e0038fc903c Mon Sep 17 00:00:00 2001 From: Srinivas Reddy Date: Mon, 20 Jan 2020 14:15:10 +0800 Subject: [PATCH 490/756] (no ticket) Improved formatting Client: doc Patch: Srinivas Reddy This closes #1989 --- tutorial/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tutorial/README.md b/tutorial/README.md index 7772bf3e68a..9fafa9edd34 100644 --- a/tutorial/README.md +++ b/tutorial/README.md @@ -30,10 +30,10 @@ Tutorial 2) Read tutorial.thrift to learn about the syntax of a Thrift file 3) Compile the code for the language of your choice: - +``` $ thrift $ thrift -r --gen cpp tutorial.thrift - +``` 4) Take a look at the generated code. 5) Look in the language directories for sample client/server code. From b576ae91f0b777aab0fb0df913067b5f1ca66345 Mon Sep 17 00:00:00 2001 From: Cameron Rollheiser Date: Wed, 8 Jan 2020 14:42:17 -0500 Subject: [PATCH 491/756] (no ticket) Document Docker Build JS Versions [skip ci] Client: docs Patch: Cameron Rollheiser This closes #1976 --- build/docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/docker/README.md b/build/docker/README.md index 8c8be22bbf3..6f9c024e614 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -182,7 +182,7 @@ Last updated: October 1, 2017 | haskell | 7.10.3 | 8.0.2 | | | haxe | 3.2.1 | 3.4.4 | THRIFT-4352: avoid 3.4.2 | | java | 1.8.0_191 | 11.0.3 | | -| js | | | Unsure how to look for version info? | +| js | Node.js 6.17.1, V8 5.1.281.111, npm 3.10.10 | Node.js 10.18.0, V8 6.8.275.32, npm 6.13.4 | | | lua | | 5.2.4 | Lua 5.3: see THRIFT-4386 | | netstd | 3.1 | 3.1 | LTS version | | nodejs | 6.16.0 | 10.16.0 | | From baddaa8612fe70070208d30b91d820e99fb2a716 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 5 Feb 2020 22:30:01 +0100 Subject: [PATCH 492/756] THRIFT-5086 CMake target thrift::thrift has no INTERFACE_INCLUDE_DIRECTORIES property Client: cpp Patch: SmartNet Club This closes #2003 --- build/cmake/ThriftMacros.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/build/cmake/ThriftMacros.cmake b/build/cmake/ThriftMacros.cmake index d068b2ae63e..038651eea11 100644 --- a/build/cmake/ThriftMacros.cmake +++ b/build/cmake/ThriftMacros.cmake @@ -25,6 +25,7 @@ endmacro(ADD_PKGCONFIG_THRIFT) macro(ADD_LIBRARY_THRIFT name) add_library(${name} ${ARGN}) + target_include_directories(${name} INTERFACE $) set_target_properties(${name} PROPERTIES OUTPUT_NAME ${name}${THRIFT_RUNTIME_POSTFIX} # windows link variants (/MT, /MD, /MTd, /MDd) get different names VERSION ${thrift_VERSION} ) From 77c4afae16207a8a806162fa8b6418f329ad5fa3 Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Sun, 2 Feb 2020 20:13:07 -0500 Subject: [PATCH 493/756] (no ticket) Propagate exception instead of rethrowing Client: cpp Patch: Gaurav Singh This closes #1999 --- lib/cpp/test/concurrency/ThreadFactoryTests.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cpp/test/concurrency/ThreadFactoryTests.h b/lib/cpp/test/concurrency/ThreadFactoryTests.h index febe3f8b3f1..23e46e3de21 100644 --- a/lib/cpp/test/concurrency/ThreadFactoryTests.h +++ b/lib/cpp/test/concurrency/ThreadFactoryTests.h @@ -83,7 +83,7 @@ class ThreadFactoryTests { } catch (SystemResourceException& e) { std::cout << "\t\t\tfailed to create " << lix* count + tix << " thread " << e.what() << std::endl; - throw e; + throw; } } @@ -97,7 +97,7 @@ class ThreadFactoryTests { } catch (SystemResourceException& e) { std::cout << "\t\t\tfailed to start " << lix* count + tix << " thread " << e.what() << std::endl; - throw e; + throw; } } From 7d30e2c0b67ef14351d233ac8b29292ae2fbbd90 Mon Sep 17 00:00:00 2001 From: Gaurav Singh Date: Sun, 2 Feb 2020 10:56:26 -0500 Subject: [PATCH 494/756] (no ticket) catch exception by ref Patch: Gaurav Singh This closes #1998 --- compiler/cpp/src/thrift/main.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/cpp/src/thrift/main.cc b/compiler/cpp/src/thrift/main.cc index 03e0d6f4842..4c900f71331 100644 --- a/compiler/cpp/src/thrift/main.cc +++ b/compiler/cpp/src/thrift/main.cc @@ -932,7 +932,7 @@ void parse(t_program* program, t_program* parent_program) { if (yyparse() != 0) { failure("Parser error during include pass."); } - } catch (string x) { + } catch (string &x) { failure(x.c_str()); } fclose(yyin); @@ -970,7 +970,7 @@ void parse(t_program* program, t_program* parent_program) { if (yyparse() != 0) { failure("Parser error during types pass."); } - } catch (string x) { + } catch (string &x) { failure(x.c_str()); } fclose(yyin); @@ -1014,7 +1014,7 @@ void generate(t_program* program, const vector& generator_strings) { delete generator; } } - } catch (string s) { + } catch (string &s) { failure("Error: %s\n", s.c_str()); } catch (const char* exc) { failure("Error: %s\n", exc); From ded326101af3c6c9daad9814ce6404d385f36a1f Mon Sep 17 00:00:00 2001 From: Homarechan Date: Tue, 7 Jan 2020 00:21:45 +0900 Subject: [PATCH 495/756] THRIFT-5072 Fix data type generation. Client: hs Patch: Homarechan This closes #1974 --- CHANGES.md | 1 + compiler/cpp/src/thrift/generate/t_hs_generator.cc | 6 +++--- test/hs/TestClient.hs | 12 ++++++------ test/hs/TestServer.hs | 6 +++--- test/hs/ThriftTest_Main.hs | 2 +- tutorial/hs/HaskellClient.hs | 4 ++-- tutorial/hs/HaskellServer.hs | 8 ++++---- 7 files changed, 20 insertions(+), 19 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1dddab99e6a..abd709bc466 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ - [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base - [THRIFT-5006](https://issues.apache.org/jira/browse/THRIFT-5006) - Implement DEFAULT_MAX_LENGTH at TFramedTransport - [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - In Go library TDeserializer.Transport is now typed \*TMemoryBuffer instead of TTransport +- [THRIFT-5072](https://issues.apache.org/jira/browse/THRIFT-5072) - Haskell generator fails to distinguish between multiple enum types with conflicting enum identifiers ### Java diff --git a/compiler/cpp/src/thrift/generate/t_hs_generator.cc b/compiler/cpp/src/thrift/generate/t_hs_generator.cc index a59dee5d2d4..00c01a1abb9 100644 --- a/compiler/cpp/src/thrift/generate/t_hs_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_hs_generator.cc @@ -305,7 +305,7 @@ void t_hs_generator::generate_enum(t_enum* tenum) { bool first = true; for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { - string name = capitalize((*c_iter)->get_name()); + string name = capitalize(tenum->get_name()) + "_" + capitalize((*c_iter)->get_name()); f_types_ << (first ? "" : "|"); f_types_ << name; first = false; @@ -321,7 +321,7 @@ void t_hs_generator::generate_enum(t_enum* tenum) { indent_up(); for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); - string name = capitalize((*c_iter)->get_name()); + string name = capitalize(tenum->get_name()) + "_" + capitalize((*c_iter)->get_name()); indent(f_types_) << name << " -> " << value << endl; } indent_down(); @@ -329,7 +329,7 @@ void t_hs_generator::generate_enum(t_enum* tenum) { indent_up(); for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { int value = (*c_iter)->get_value(); - string name = capitalize((*c_iter)->get_name()); + string name = capitalize(tenum->get_name()) + "_" + capitalize((*c_iter)->get_name()); indent(f_types_) << value << " -> " << name << endl; } indent(f_types_) << "_ -> X.throw T.ThriftException" << endl; diff --git a/test/hs/TestClient.hs b/test/hs/TestClient.hs index 93fb591b343..d014e089ab9 100644 --- a/test/hs/TestClient.hs +++ b/test/hs/TestClient.hs @@ -193,16 +193,16 @@ runClient p = do -- Enum Test putStrLn "testEnum" - numz1 <- Client.testEnum prot ONE - when (numz1 /= ONE) exitFailure + numz1 <- Client.testEnum prot Numberz_ONE + when (numz1 /= Numberz_ONE) exitFailure putStrLn "testEnum" - numz2 <- Client.testEnum prot TWO - when (numz2 /= TWO) exitFailure + numz2 <- Client.testEnum prot Numberz_TWO + when (numz2 /= Numberz_TWO) exitFailure putStrLn "testEnum" - numz5 <- Client.testEnum prot FIVE - when (numz5 /= FIVE) exitFailure + numz5 <- Client.testEnum prot Numberz_FIVE + when (numz5 /= Numberz_FIVE) exitFailure -- Typedef Test putStrLn "testTypedef" diff --git a/test/hs/TestServer.hs b/test/hs/TestServer.hs index b7731ab1c40..c37dda3159f 100644 --- a/test/hs/TestServer.hs +++ b/test/hs/TestServer.hs @@ -212,10 +212,10 @@ instance ThriftTest_Iface TestHandler where testInsanity _ x = do System.IO.putStrLn "testInsanity()" - return $ Map.fromList [ (1, Map.fromList [ (TWO , x) - , (THREE, x) + return $ Map.fromList [ (1, Map.fromList [ (Numberz_TWO , x) + , (Numberz_THREE, x) ]) - , (2, Map.fromList [ (SIX, default_Insanity) + , (2, Map.fromList [ (Numberz_SIX, default_Insanity) ]) ] diff --git a/test/hs/ThriftTest_Main.hs b/test/hs/ThriftTest_Main.hs index 670023e2985..6421c6aeb32 100644 --- a/test/hs/ThriftTest_Main.hs +++ b/test/hs/ThriftTest_Main.hs @@ -107,7 +107,7 @@ instance Iface.ThriftTest_Iface TestHandler where return (Map.fromList [(1, Map.fromList [(2, 2)])]) testInsanity _ x = do - return (Map.fromList [(1, Map.fromList [(Types.ONE, x)])]) + return (Map.fromList [(1, Map.fromList [(Types.Numberz_ONE, x)])]) testMulti _ _ _ _ _ _ _ = do return (Types.Xtruct "" 0 0 0) diff --git a/tutorial/hs/HaskellClient.hs b/tutorial/hs/HaskellClient.hs index bd29df06df1..76a8824099c 100644 --- a/tutorial/hs/HaskellClient.hs +++ b/tutorial/hs/HaskellClient.hs @@ -48,7 +48,7 @@ main = do printf "1+1=%d\n" sum - let work = Work { work_op = DIVIDE, + let work = Work { work_op = Operation_DIVIDE, work_num1 = 1, work_num2 = 0, work_comment = Nothing @@ -58,7 +58,7 @@ main = do (\e -> printf "InvalidOperation %s\n" (show (e :: InvalidOperation))) - let work = Work { work_op = SUBTRACT, + let work = Work { work_op = Operation_SUBTRACT, work_num1 = 15, work_num2 = 10, work_comment = Nothing diff --git a/tutorial/hs/HaskellServer.hs b/tutorial/hs/HaskellServer.hs index cfe13441d4a..1594ee3420e 100644 --- a/tutorial/hs/HaskellServer.hs +++ b/tutorial/hs/HaskellServer.hs @@ -64,13 +64,13 @@ instance Calculator_Iface CalculatorHandler where printf "calculate(%d, %s)\n" logid (show work) let val = case op work of - ADD -> + Operation_ADD -> num1 work + num2 work - SUBTRACT -> + Operation_SUBTRACT -> num1 work - num2 work - MULTIPLY -> + Operation_MULTIPLY -> num1 work * num2 work - DIVIDE -> + Operation_DIVIDE -> if num2 work == 0 then throw $ InvalidOperation { From b012318fc8f1d3de4c64514d5d32cb424952d905 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 12 Feb 2020 12:16:19 +0100 Subject: [PATCH 496/756] THRIFT-5088 Memory leak in TWinHttpTransport Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.Transport.WinHTTP.pas | 5 +++-- lib/delphi/src/Thrift.Transport.pas | 2 +- lib/delphi/src/Thrift.WinHTTP.pas | 22 ++++++++++----------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas index 7a1b48fa2f5..5794b1c2381 100644 --- a/lib/delphi/src/Thrift.Transport.WinHTTP.pas +++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas @@ -309,7 +309,7 @@ procedure TWinHTTPClientImpl.SendRequest; http : IWinHTTPRequest; pData : PByte; len : Integer; - error : Cardinal; + error, dwSize : Cardinal; sMsg : string; begin http := CreateRequest; @@ -334,7 +334,8 @@ procedure TWinHTTPClientImpl.SendRequest; end; FInputStream := THTTPResponseStream.Create( http); - UpdateKnownMessageSize( http.QueryTotalResponseSize); + if http.QueryTotalResponseSize( dwSize) // FALSE indicates "no info available" + then UpdateKnownMessageSize( dwSize); end; procedure TWinHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer); diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas index af62548db33..1b8300c84fa 100644 --- a/lib/delphi/src/Thrift.Transport.pas +++ b/lib/delphi/src/Thrift.Transport.pas @@ -579,7 +579,7 @@ procedure TEndpointTransportBase.ResetConsumedMessageSize( const newSize : Int64 // update only: message size can shrink, but not grow ASSERT( KnownMessageSize <= MaxMessageSize); if newSize > KnownMessageSize - then TTransportExceptionEndOfFile.Create('MaxMessageSize reached'); + then raise TTransportExceptionEndOfFile.Create('MaxMessageSize reached'); FKnownMessageSize := newSize; FRemainingMessageSize := newSize; diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index d06006626a5..5c0719342f4 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -576,7 +576,7 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; IWinHTTPConnection = interface; IWinHTTPRequest = interface - ['{7A8E7255-5440-4621-A8A8-1E9FFAA6D6FA}'] + ['{7AE6F63F-49B6-436B-8AAB-159E58EB900A}'] function Handle : HINTERNET; function Connection : IWinHTTPConnection; function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; @@ -589,7 +589,7 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; function ReadData( const dwRead : DWORD) : TBytes; overload; function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; function QueryDataAvailable : DWORD; - function QueryTotalResponseSize : DWORD; + function QueryTotalResponseSize( out dwSize : DWORD) : Boolean; end; IWinHTTPConnection = interface @@ -709,7 +709,7 @@ TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest) function ReadData( const dwRead : DWORD) : TBytes; overload; function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; function QueryDataAvailable : DWORD; - function QueryTotalResponseSize : DWORD; + function QueryTotalResponseSize( out dwSize : DWORD) : Boolean; public constructor Create( const aConnection : IWinHTTPConnection; @@ -1212,20 +1212,20 @@ function TWinHTTPRequestImpl.QueryDataAvailable : DWORD; end; -function TWinHTTPRequestImpl.QueryTotalResponseSize : DWORD; +function TWinHTTPRequestImpl.QueryTotalResponseSize( out dwSize : DWORD) : Boolean; var dwBytes, dwError, dwIndex : DWORD; begin dwBytes := SizeOf( result); dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX); - if not WinHttpQueryHeaders( FHandle, - WINHTTP_QUERY_CONTENT_LENGTH or WINHTTP_QUERY_FLAG_NUMBER, - WINHTTP_HEADER_NAME_BY_INDEX, - @result, dwBytes, - dwIndex) - then begin + result := WinHttpQueryHeaders( FHandle, + WINHTTP_QUERY_CONTENT_LENGTH or WINHTTP_QUERY_FLAG_NUMBER, + WINHTTP_HEADER_NAME_BY_INDEX, + @dwSize, dwBytes, + dwIndex); + if not result then begin + dwSize := MAXINT; // we don't know, just return something useful dwError := GetLastError; if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error - result := MAXINT; // we don't know end; end; From aa9e7e8f5966ec9233ef418bab81b48c5a539028 Mon Sep 17 00:00:00 2001 From: "Renan I. Del Valle" Date: Thu, 13 Feb 2020 11:20:04 -0800 Subject: [PATCH 497/756] THRIFT-5092: Return an error instead of causing a panic when attempting to write to a closed client. Client: go Patch: Renan I. Del Valle This closes #2005 --- lib/go/thrift/http_client.go | 15 +++++++++++++-- lib/go/thrift/http_client_test.go | 7 +++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/go/thrift/http_client.go b/lib/go/thrift/http_client.go index d093eebb6d8..1924a1ae268 100644 --- a/lib/go/thrift/http_client.go +++ b/lib/go/thrift/http_client.go @@ -166,19 +166,30 @@ func (p *THttpClient) Read(buf []byte) (int, error) { } func (p *THttpClient) ReadByte() (c byte, err error) { + if p.response == nil { + return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.") + } return readByte(p.response.Body) } func (p *THttpClient) Write(buf []byte) (int, error) { - n, err := p.requestBuffer.Write(buf) - return n, err + if p.requestBuffer == nil { + return 0, NewTTransportException(NOT_OPEN, "Request buffer is nil, connection may have been closed.") + } + return p.requestBuffer.Write(buf) } func (p *THttpClient) WriteByte(c byte) error { + if p.requestBuffer == nil { + return NewTTransportException(NOT_OPEN, "Request buffer is nil, connection may have been closed.") + } return p.requestBuffer.WriteByte(c) } func (p *THttpClient) WriteString(s string) (n int, err error) { + if p.requestBuffer == nil { + return 0, NewTTransportException(NOT_OPEN, "Request buffer is nil, connection may have been closed.") + } return p.requestBuffer.WriteString(s) } diff --git a/lib/go/thrift/http_client_test.go b/lib/go/thrift/http_client_test.go index 453680ace87..a7977a38595 100644 --- a/lib/go/thrift/http_client_test.go +++ b/lib/go/thrift/http_client_test.go @@ -35,6 +35,13 @@ func TestHttpClient(t *testing.T) { t.Fatalf("Unable to connect to %s: %s", addr.String(), err) } TransportTest(t, trans, trans) + + t.Run("nilBuffer", func(t *testing.T) { + _ = trans.Close() + if _, err = trans.Write([]byte{1, 2, 3, 4}); err == nil { + t.Fatalf("writing to a closed transport did not result in an error") + } + }) } func TestHttpClientHeaders(t *testing.T) { From bb5f7ec6b06220808cd20c8488fe8f90a54f3929 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 13 Feb 2020 22:35:28 +0100 Subject: [PATCH 498/756] THRIFT-5091 Netstd generator produces uncompileable code for struct names ending with "_result" or "_args" Client: netstd Patch: Jens Geyer THis closes #2006 --- compiler/cpp/src/thrift/generate/t_netstd_generator.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index ba559605fef..cc6287da1e8 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -2746,17 +2746,19 @@ string t_netstd_generator::type_name(t_type* ttype) return "List<" + type_name(tlist->get_elem_type()) + ">"; } + string the_name = check_and_correct_struct_name(normalize_name(ttype->get_name())); + t_program* program = ttype->get_program(); if (program != NULL && program != program_) { string ns = program->get_namespace("netstd"); if (!ns.empty()) { - return ns + "." + normalize_name(ttype->get_name()); + return ns + "." + the_name; } } - return normalize_name(ttype->get_name()); + return the_name; } string t_netstd_generator::base_type_name(t_base_type* tbase) From c8e46cf861cd1ebae273e968bb3995f778d998f1 Mon Sep 17 00:00:00 2001 From: Tobias Mayer Date: Sun, 16 Feb 2020 10:36:11 +0100 Subject: [PATCH 499/756] THRIFT-5097: Fix exported version in cmake module Patch: Tobias Mayer This closes #2010 --- build/cmake/ThriftConfig.cmake.in | 3 ++- lib/cpp/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/build/cmake/ThriftConfig.cmake.in b/build/cmake/ThriftConfig.cmake.in index c304da04dfa..3fb208f5c15 100644 --- a/build/cmake/ThriftConfig.cmake.in +++ b/build/cmake/ThriftConfig.cmake.in @@ -17,13 +17,14 @@ # under the License. # -set(THRIFT_VERSION ${thrift_VERSION}) +set(THRIFT_VERSION @thrift_VERSION@) @PACKAGE_INIT@ set_and_check(THRIFT_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") set_and_check(THRIFT_CMAKE_DIR "@PACKAGE_CMAKE_INSTALL_DIR@") set_and_check(THRIFT_BIN_DIR "@PACKAGE_BIN_INSTALL_DIR@") +set(THRIFT_COMPILER "${THRIFT_BIN_DIR}/thrift") if (NOT TARGET thrift::thrift) include("${THRIFT_CMAKE_DIR}/thriftTargets.cmake") diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index e92da606bce..9b987ae6781 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -151,7 +151,7 @@ endif() ADD_PKGCONFIG_THRIFT(thrift) if(WITH_LIBEVENT) - find_package(Libevent REQUIRED) # Libevent comes with CMake support form upstream + find_package(Libevent REQUIRED) # Libevent comes with CMake support from upstream include_directories(SYSTEM ${LIBEVENT_INCLUDE_DIRS}) ADD_LIBRARY_THRIFT(thriftnb ${thriftcppnb_SOURCES}) From 222362cc70d66b5f8bb6422622fcf384407b54c8 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 16 Feb 2020 01:54:56 +0100 Subject: [PATCH 500/756] THRIFT-5095 ToString() should print entire structure, not just the top-level data Client: netstd Patch: Jens Geyer This closes #2009 --- .../src/thrift/generate/t_netstd_generator.cc | 10 +-- .../Thrift/Collections/ToStringExtension.cs | 82 +++++++++++++++++++ 2 files changed, 83 insertions(+), 9 deletions(-) create mode 100644 lib/netstd/Thrift/Collections/ToStringExtension.cs diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index cc6287da1e8..b2883ed44ba 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -1251,15 +1251,7 @@ void t_netstd_generator::generate_netstd_struct_tostring(ostream& out, t_struct* out << indent() << "sb.Append(\", " << prop_name(*f_iter) << ": \");" << endl; } - t_type* ttype = (*f_iter)->get_type(); - if (ttype->is_xception() || ttype->is_struct()) - { - out << indent() << "sb.Append(" << prop_name(*f_iter) << "== null ? \"\" : " << prop_name(*f_iter) << ".ToString());" << endl; - } - else - { - out << indent() << "sb.Append(" << prop_name(*f_iter) << ");" << endl; - } + out << indent() << prop_name(*f_iter) << ".ToString(sb);" << endl; if (!is_required) { diff --git a/lib/netstd/Thrift/Collections/ToStringExtension.cs b/lib/netstd/Thrift/Collections/ToStringExtension.cs new file mode 100644 index 00000000000..40dd9ddea6e --- /dev/null +++ b/lib/netstd/Thrift/Collections/ToStringExtension.cs @@ -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. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using Thrift.Protocol; + +namespace Thrift.Collections +{ + + + public static class ToStringExtensions + { + public static void ToString(this object self, StringBuilder sb, bool first = true) + { + if (!first) + sb.Append(", "); + + bool first_child = true; + if (self is string) // string is IEnumerable + { + sb.Append('"'); + sb.Append(self); + sb.Append('"'); + } + else if (self is IDictionary) + { + sb.Append("{ "); + foreach (DictionaryEntry pair in (self as IDictionary)) + { + if (first_child) + first_child = false; + else + sb.Append(","); + + sb.Append("{ "); + pair.Key.ToString(sb); + sb.Append(", "); + pair.Value.ToString(sb); + sb.Append("}"); + } + sb.Append("}"); + } + else if (self is IEnumerable) + { + sb.Append("{ "); + foreach (var elm in (self as IEnumerable)) + { + elm.ToString(sb, first_child); + first_child = false; + } + sb.Append("}"); + } + else if (self is TBase) + { + sb.Append((self as TBase).ToString()); + } + else + { + sb.Append(self.ToString()); + } + } + } + + +} From 7b712f42d7bc03610511abd397845983deafa258 Mon Sep 17 00:00:00 2001 From: Jeffrey Han Date: Thu, 20 Feb 2020 14:18:23 -0800 Subject: [PATCH 501/756] THRIFT-5106: Fix various Lua library and compiler issues Client: lua Patch: Jeffrey Han This closes #2014 --- compiler/cpp/src/thrift/generate/t_lua_generator.cc | 3 +++ lib/lua/TCompactProtocol.lua | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_lua_generator.cc b/compiler/cpp/src/thrift/generate/t_lua_generator.cc index e6432c89835..f8585622662 100644 --- a/compiler/cpp/src/thrift/generate/t_lua_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_lua_generator.cc @@ -197,6 +197,9 @@ void t_lua_generator::close_generator() { * Generate a typedef (essentially a constant) */ void t_lua_generator::generate_typedef(t_typedef* ttypedef) { + if (ttypedef->get_type()->get_name().empty()) { + return; + } f_types_ << endl << endl << indent() << ttypedef->get_symbolic() << " = " << ttypedef->get_type()->get_name(); } diff --git a/lib/lua/TCompactProtocol.lua b/lib/lua/TCompactProtocol.lua index 7b75967a925..8e7db8e66fb 100644 --- a/lib/lua/TCompactProtocol.lua +++ b/lib/lua/TCompactProtocol.lua @@ -314,10 +314,10 @@ end function TCompactProtocol:readMapBegin() local size = self:readVarint32() - if size < 0 then - return nil,nil,nil + local kvtype = 0 + if size > 0 then + kvtype = self:readSignByte() end - local kvtype = self:readSignByte() local ktype = self:getTType(libluabitwise.shiftr(kvtype, 4)) local vtype = self:getTType(kvtype) return ktype, vtype, size @@ -426,7 +426,7 @@ function TCompactProtocol:readVarint64() local data = result(0) local shiftl = 0 while true do - b = self:readByte() + b = self:readSignByte() endFlag, data = libluabpack.fromVarint64(b, shiftl, data) shiftl = shiftl + 7 if endFlag == 0 then From d8480c9ac14f133d272372530e33619b2a64ddf7 Mon Sep 17 00:00:00 2001 From: wangyunjian Date: Sun, 16 Feb 2020 08:43:03 -0500 Subject: [PATCH 502/756] THRIFT-5101: Return NULL install of FALSE for thrift_server_socket_accept() Client: c_glib Patch: wangyunjian This closes #2011 Signed-off-by: wangyunjian --- lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c index 21ce1eee08d..92c6d7f76eb 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c @@ -148,7 +148,7 @@ thrift_server_socket_accept (ThriftServerTransport *transport, GError **error) THRIFT_SERVER_SOCKET_ERROR_ACCEPT, "failed to accept connection - %s", strerror(errno)); - return FALSE; + return NULL; } socket = g_object_new (THRIFT_TYPE_SOCKET, NULL); From bd26d385693e4f172c348dc27f9d1e23288c50cf Mon Sep 17 00:00:00 2001 From: wangyunjian Date: Sat, 15 Feb 2020 08:29:59 -0500 Subject: [PATCH 503/756] THRIFT-5094: Fix memory leak in thrift_server_set_property() Client: c_glib Patch: wangyunjian This closes #2008 Signed-off-by: wangyunjian --- lib/c_glib/src/thrift/c_glib/server/thrift_server.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/c_glib/src/thrift/c_glib/server/thrift_server.c b/lib/c_glib/src/thrift/c_glib/server/thrift_server.c index ccf9153db68..2109addf75b 100644 --- a/lib/c_glib/src/thrift/c_glib/server/thrift_server.c +++ b/lib/c_glib/src/thrift/c_glib/server/thrift_server.c @@ -76,21 +76,27 @@ thrift_server_set_property (GObject *object, guint property_id, switch (property_id) { case PROP_THRIFT_SERVER_PROCESSOR: + g_clear_object (&server->processor); server->processor = g_value_dup_object (value); break; case PROP_THRIFT_SERVER_SERVER_TRANSPORT: + g_clear_object (&server->server_transport); server->server_transport = g_value_dup_object (value); break; case PROP_THRIFT_SERVER_INPUT_TRANSPORT_FACTORY: + g_clear_object (&server->input_transport_factory); server->input_transport_factory = g_value_dup_object (value); break; case PROP_THRIFT_SERVER_OUTPUT_TRANSPORT_FACTORY: + g_clear_object (&server->output_transport_factory); server->output_transport_factory = g_value_dup_object (value); break; case PROP_THRIFT_SERVER_INPUT_PROTOCOL_FACTORY: + g_clear_object (&server->input_protocol_factory); server->input_protocol_factory = g_value_dup_object (value); break; case PROP_THRIFT_SERVER_OUTPUT_PROTOCOL_FACTORY: + g_clear_object (&server->output_protocol_factory); server->output_protocol_factory = g_value_dup_object (value); break; } From ea4a086757f834880220c50392532b60751c6885 Mon Sep 17 00:00:00 2001 From: wangyunjian Date: Tue, 18 Feb 2020 09:11:53 -0500 Subject: [PATCH 504/756] THRIFT-5102: Fix memory leak in thrift_simple_server_serve() Client: c_glib Patch: wangyunjian This closes #2012 Signed-off-by: wangyunjian --- .../src/thrift/c_glib/server/thrift_simple_server.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.c b/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.c index 22a96c7a481..53e2508f72e 100644 --- a/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.c +++ b/lib/c_glib/src/thrift/c_glib/server/thrift_simple_server.c @@ -78,6 +78,15 @@ thrift_simple_server_serve (ThriftServer *server, GError **error) NULL); THRIFT_TRANSPORT_GET_CLASS (output_transport)->close (output_transport, NULL); + g_object_unref (input_transport); + g_object_unref (output_transport); + g_object_unref (input_protocol); + g_object_unref (output_protocol); + } + + if (t != NULL) + { + g_object_unref (t); } } From f0c761e171782565f74ff3cd7d0e9ce8e1d2b6ad Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Thu, 9 Jan 2020 18:48:29 +0900 Subject: [PATCH 505/756] THRIFT-5059: Add cross tests for TZlibTransport in D Client: D Patch: Kengo Seki This closes #1977 --- lib/d/test/test_utils.d | 4 ++++ lib/d/test/thrift_test_client.d | 22 ++++++++++++++++------ lib/d/test/thrift_test_server.d | 4 +++- test/known_failures_Linux.json | 26 ++++++++++++++++++++++++++ test/tests.json | 3 ++- 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/lib/d/test/test_utils.d b/lib/d/test/test_utils.d index 174100b796f..d0548b71439 100644 --- a/lib/d/test/test_utils.d +++ b/lib/d/test/test_utils.d @@ -35,6 +35,7 @@ import thrift.transport.base; import thrift.transport.buffered; import thrift.transport.framed; import thrift.transport.http; +import thrift.transport.zlib; // This is a likely victim of @@BUG4744@@ when used with command argument // parsing. @@ -79,6 +80,7 @@ enum TransportType { buffered, framed, http, + zlib, raw } @@ -90,6 +92,8 @@ TTransportFactory createTransportFactory(TransportType type) { return new TFramedTransportFactory; case TransportType.http: return new TServerHttpTransportFactory; + case TransportType.zlib: + return new TZlibTransportFactory; case TransportType.raw: return new TTransportFactory; } diff --git a/lib/d/test/thrift_test_client.d b/lib/d/test/thrift_test_client.d index 49419f71a4a..c9911e28b4e 100644 --- a/lib/d/test/thrift_test_client.d +++ b/lib/d/test/thrift_test_client.d @@ -35,6 +35,7 @@ import thrift.transport.base; import thrift.transport.buffered; import thrift.transport.framed; import thrift.transport.http; +import thrift.transport.zlib; import thrift.transport.socket; import thrift.transport.ssl; import thrift.util.hashset; @@ -47,6 +48,7 @@ enum TransportType { buffered, framed, http, + zlib, raw } @@ -68,6 +70,7 @@ void main(string[] args) { bool ssl; ProtocolType protocolType; TransportType transportType; + bool zlib; bool trace; getopt(args, @@ -75,6 +78,7 @@ void main(string[] args) { "protocol", &protocolType, "ssl", &ssl, "transport", &transportType, + "zlib", &zlib, "trace", &trace, "port", &port, "host", (string _, string value) { @@ -102,22 +106,28 @@ void main(string[] args) { socket = new TSocket(host, port); } - TProtocol protocol; + TTransport transport; final switch (transportType) { case TransportType.buffered: - protocol = createProtocol(new TBufferedTransport(socket), protocolType); + transport = new TBufferedTransport(socket); break; case TransportType.framed: - protocol = createProtocol(new TFramedTransport(socket), protocolType); + transport = new TFramedTransport(socket); break; case TransportType.http: - protocol = createProtocol( - new TClientHttpTransport(socket, host, "/service"), protocolType); + transport = new TClientHttpTransport(socket, host, "/service"); + break; + case TransportType.zlib: + transport = new TZlibTransport(socket); break; case TransportType.raw: - protocol = createProtocol(socket, protocolType); + transport = socket; break; } + if (zlib && transportType != TransportType.zlib) { + transport = new TZlibTransport(socket); + } + TProtocol protocol = createProtocol(transport, protocolType); auto client = tClient!ThriftTest(protocol); diff --git a/lib/d/test/thrift_test_server.d b/lib/d/test/thrift_test_server.d index ce820d69905..192ff31593e 100644 --- a/lib/d/test/thrift_test_server.d +++ b/lib/d/test/thrift_test_server.d @@ -42,6 +42,7 @@ import thrift.transport.base; import thrift.transport.buffered; import thrift.transport.framed; import thrift.transport.http; +import thrift.transport.zlib; import thrift.transport.ssl; import thrift.util.cancellation; import thrift.util.hashset; @@ -246,11 +247,12 @@ void main(string[] args) { size_t numIOThreads = 1; TransportType transportType; bool ssl = false; + bool zlib = false; bool trace = true; size_t taskPoolSize = totalCPUs; getopt(args, "port", &port, "protocol", &protocolType, "server-type", - &serverType, "ssl", &ssl, "num-io-threads", &numIOThreads, + &serverType, "ssl", &ssl, "zlib", &zlib, "num-io-threads", &numIOThreads, "task-pool-size", &taskPoolSize, "trace", &trace, "transport", &transportType); diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index e165aa47242..d1c21eb2bd9 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -214,18 +214,24 @@ "d-cpp_binary_framed-ip-ssl", "d-cpp_binary_http-ip", "d-cpp_binary_http-ip-ssl", + "d-cpp_binary_zlib-ip", + "d-cpp_binary_zlib-ip-ssl", "d-cpp_compact_buffered-ip", "d-cpp_compact_buffered-ip-ssl", "d-cpp_compact_framed-ip", "d-cpp_compact_framed-ip-ssl", "d-cpp_compact_http-ip", "d-cpp_compact_http-ip-ssl", + "d-cpp_compact_zlib-ip", + "d-cpp_compact_zlib-ip-ssl", "d-cpp_json_buffered-ip", "d-cpp_json_buffered-ip-ssl", "d-cpp_json_framed-ip", "d-cpp_json_framed-ip-ssl", "d-cpp_json_http-ip", "d-cpp_json_http-ip-ssl", + "d-cpp_json_zlib-ip", + "d-cpp_json_zlib-ip-ssl", "d-d_binary_http-ip", "d-d_compact_http-ip", "d-d_json_http-ip", @@ -270,60 +276,80 @@ "d-py3_binary-accel_framed-ip-ssl", "d-py3_binary-accel_http-ip", "d-py3_binary-accel_http-ip-ssl", + "d-py3_binary-accel_zlib-ip", + "d-py3_binary-accel_zlib-ip-ssl", "d-py3_binary_buffered-ip", "d-py3_binary_buffered-ip-ssl", "d-py3_binary_framed-ip", "d-py3_binary_framed-ip-ssl", "d-py3_binary_http-ip", "d-py3_binary_http-ip-ssl", + "d-py3_binary_zlib-ip", + "d-py3_binary_zlib-ip-ssl", "d-py3_compact-accelc_buffered-ip", "d-py3_compact-accelc_buffered-ip-ssl", "d-py3_compact-accelc_framed-ip", "d-py3_compact-accelc_framed-ip-ssl", "d-py3_compact-accelc_http-ip", "d-py3_compact-accelc_http-ip-ssl", + "d-py3_compact-accelc_zlib-ip", + "d-py3_compact-accelc_zlib-ip-ssl", "d-py3_compact_buffered-ip", "d-py3_compact_buffered-ip-ssl", "d-py3_compact_framed-ip", "d-py3_compact_framed-ip-ssl", "d-py3_compact_http-ip", "d-py3_compact_http-ip-ssl", + "d-py3_compact_zlib-ip", + "d-py3_compact_zlib-ip-ssl", "d-py3_json_buffered-ip", "d-py3_json_buffered-ip-ssl", "d-py3_json_framed-ip", "d-py3_json_framed-ip-ssl", "d-py3_json_http-ip", "d-py3_json_http-ip-ssl", + "d-py3_json_zlib-ip", + "d-py3_json_zlib-ip-ssl", "d-py_binary-accel_buffered-ip", "d-py_binary-accel_buffered-ip-ssl", "d-py_binary-accel_framed-ip", "d-py_binary-accel_framed-ip-ssl", "d-py_binary-accel_http-ip", "d-py_binary-accel_http-ip-ssl", + "d-py_binary-accel_zlib-ip", + "d-py_binary-accel_zlib-ip-ssl", "d-py_binary_buffered-ip", "d-py_binary_buffered-ip-ssl", "d-py_binary_framed-ip", "d-py_binary_framed-ip-ssl", "d-py_binary_http-ip", "d-py_binary_http-ip-ssl", + "d-py_binary_zlib-ip", + "d-py_binary_zlib-ip-ssl", "d-py_compact-accelc_buffered-ip", "d-py_compact-accelc_buffered-ip-ssl", "d-py_compact-accelc_framed-ip", "d-py_compact-accelc_framed-ip-ssl", "d-py_compact-accelc_http-ip", "d-py_compact-accelc_http-ip-ssl", + "d-py_compact-accelc_zlib-ip", + "d-py_compact-accelc_zlib-ip-ssl", "d-py_compact_buffered-ip", "d-py_compact_buffered-ip-ssl", "d-py_compact_framed-ip", "d-py_compact_framed-ip-ssl", "d-py_compact_http-ip", "d-py_compact_http-ip-ssl", + "d-py_compact_zlib-ip", + "d-py_compact_zlib-ip-ssl", "d-py_json_buffered-ip", "d-py_json_buffered-ip-ssl", "d-py_json_framed-ip", "d-py_json_framed-ip-ssl", "d-py_json_http-ip", "d-py_json_http-ip-ssl", + "d-py_json_zlib-ip", + "d-py_json_zlib-ip-ssl", "erl-cpp_binary_buffered-ip", "erl-cpp_compact_buffered-ip", "erl-csharp_binary_buffered-ip", diff --git a/test/tests.json b/test/tests.json index fc9046b49a2..dbee398a3be 100644 --- a/test/tests.json +++ b/test/tests.json @@ -76,7 +76,8 @@ "transports": [ "http", "buffered", - "framed" + "framed", + "zlib" ], "sockets": [ "ip", From a89036c8c3d05be4e6186de0864335beef01294a Mon Sep 17 00:00:00 2001 From: Alexander Edge Date: Wed, 5 Feb 2020 17:03:53 +0000 Subject: [PATCH 506/756] THRIFT-5084: Multiplexed processor in Swift Client: Swift Patch: Alexander Edge This closes #2002 --- lib/swift/Package.swift | 10 +- lib/swift/Sources/TMultiplexedProcessor.swift | 91 ++++++++ lib/swift/Sources/TMultiplexedProtocol.swift | 15 +- lib/swift/Sources/TProcessor.swift | 7 - lib/swift/Sources/TProtocolDecorator.swift | 199 ++++++++++++++++++ lib/swift/Sources/TSocketServer.swift | 9 +- .../TMultiplexedProcessorTests.swift | 123 +++++++++++ 7 files changed, 440 insertions(+), 14 deletions(-) create mode 100644 lib/swift/Sources/TMultiplexedProcessor.swift create mode 100644 lib/swift/Sources/TProtocolDecorator.swift create mode 100644 lib/swift/Tests/ThriftTests/TMultiplexedProcessorTests.swift diff --git a/lib/swift/Package.swift b/lib/swift/Package.swift index b533f6086ad..1bae5c11a3d 100644 --- a/lib/swift/Package.swift +++ b/lib/swift/Package.swift @@ -1,3 +1,4 @@ +// swift-tools-version:5.1 /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -20,5 +21,12 @@ import PackageDescription let package = Package( - name: "Thrift" + name: "Thrift", + products: [ + .library(name: "Thrift", targets: ["Thrift"]) + ], + targets: [ + .target(name: "Thrift", path: "Sources"), + .testTarget(name: "ThriftTests", dependencies: ["Thrift"]) + ] ) diff --git a/lib/swift/Sources/TMultiplexedProcessor.swift b/lib/swift/Sources/TMultiplexedProcessor.swift new file mode 100644 index 00000000000..9841d3fa8f6 --- /dev/null +++ b/lib/swift/Sources/TMultiplexedProcessor.swift @@ -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. + */ + +/** + `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: + + let processor = MultiplexedProcessor() + + processor.register(CalculatorProcessor(service: CalculatorService()), for: "Calculator") + processor.register(WeatherProcessor(service: CalculatorService()), for: "Weather") + + let server = TPerfectServer(port: 9090, processor: processor, TCompactProtocol.self, TCompactProtocol.self) + try server.start() + + */ +public class MultiplexedProcessor: TProcessor { + + enum Error: Swift.Error { + case incompatibleMessageType(TMessageType) + case missingProcessor(String) + case missingDefaultProcessor + } + + private var processors = [String: TProcessor]() + private var defaultProcessor: TProcessor? + + public init(defaultProcessor: TProcessor? = nil) { + self.defaultProcessor = defaultProcessor + } + + public func register(defaultProcessor processor: TProcessor) { + defaultProcessor = processor + } + + public func register(processor: TProcessor, for service: String) { + processors[service] = processor + } + + public func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws { + let message = try inProtocol.readMessageBegin() + guard message.1 != .call && message.1 != .oneway else { throw Error.incompatibleMessageType(message.1) } + if let separatorIndex = message.0.firstIndex(of: Character(.multiplexSeparator)) { + let serviceName = String(message.0.prefix(upTo: separatorIndex)) + let messageName = String(message.0.suffix(from: message.0.index(after: separatorIndex))) + guard let processor = processors[serviceName] else { throw Error.missingProcessor(serviceName)} + let storedMessage = StoredMessage(message: (messageName, message.1, message.2), proto: inProtocol) + try processor.process(on: storedMessage, outProtocol: outProtocol) + } else { + guard let processor = defaultProcessor else { throw Error.missingDefaultProcessor } + try processor.process(on: inProtocol, outProtocol: outProtocol) + } + } +} + +private final class StoredMessage: TProtocolDecorator { + + private let message: (String, TMessageType, Int32) + + init(message: (String, TMessageType, Int32), proto: TProtocol) { + self.message = message + super.init(proto: proto) + } + + required init(on transport: TTransport) { + fatalError("init(on:) has not been implemented") + } + + override func readMessageBegin() throws -> (String, TMessageType, Int32) { + message + } +} diff --git a/lib/swift/Sources/TMultiplexedProtocol.swift b/lib/swift/Sources/TMultiplexedProtocol.swift index 73a8d51ab9e..83f0ddd13e7 100644 --- a/lib/swift/Sources/TMultiplexedProtocol.swift +++ b/lib/swift/Sources/TMultiplexedProtocol.swift @@ -17,8 +17,19 @@ * under the License. */ +extension String { + static let multiplexSeparator = ":" +} + +/** + `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 `TMultiplexedProcessor` to handle request + from a multiplexing client. + */ public class TMultiplexedProtocol: TWrappedProtocol { - public let separator = ":" public var serviceName = "" @@ -33,7 +44,7 @@ public class TMultiplexedProtocol: TWrappedProtocol = (Int, TProtocol, TProtocol, T) -> Void - public protocol TProcessor { - associatedtype Service - var service: Service { get set } func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws - init(service: Service) } - diff --git a/lib/swift/Sources/TProtocolDecorator.swift b/lib/swift/Sources/TProtocolDecorator.swift new file mode 100644 index 00000000000..3f3b4a1215f --- /dev/null +++ b/lib/swift/Sources/TProtocolDecorator.swift @@ -0,0 +1,199 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Foundation + +class TProtocolDecorator: TProtocol { + + private let proto: TProtocol + var transport: TTransport + + init(proto: TProtocol) { + self.proto = proto + self.transport = proto.transport + } + + required init(on transport: TTransport) { + fatalError("init(on:) has not been implemented") + } + + func readMessageBegin() throws -> (String, TMessageType, Int32) { + try proto.readMessageBegin() + } + + func readMessageEnd() throws { + try proto.readMessageEnd() + } + + func readStructBegin() throws -> String { + try proto.readStructBegin() + } + + func readStructEnd() throws { + try proto.readStructEnd() + } + + func readFieldBegin() throws -> (String, TType, Int32) { + try proto.readFieldBegin() + } + + func readFieldEnd() throws { + try proto.readFieldEnd() + } + + func readMapBegin() throws -> (TType, TType, Int32) { + try proto.readMapBegin() + } + + func readMapEnd() throws { + try proto.readMapEnd() + } + + func readSetBegin() throws -> (TType, Int32) { + try proto.readSetBegin() + } + + func readSetEnd() throws { + try proto.readSetEnd() + } + + func readListBegin() throws -> (TType, Int32) { + try proto.readListBegin() + } + + func readListEnd() throws { + try proto.readListEnd() + } + + func read() throws -> String { + try proto.read() + } + + func read() throws -> Bool { + try proto.read() + } + + func read() throws -> UInt8 { + try proto.read() + } + + func read() throws -> Int16 { + try proto.read() + } + + func read() throws -> Int32 { + try proto.read() + } + + func read() throws -> Int64 { + try proto.read() + } + + func read() throws -> Double { + try proto.read() + } + + func read() throws -> Data { + try proto.read() + } + + func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws { + try proto.writeMessageBegin(name: name, type: messageType, sequenceID: sequenceID) + } + + func writeMessageEnd() throws { + try proto.writeMessageEnd() + } + + func writeStructBegin(name: String) throws { + try proto.writeStructBegin(name: name) + } + + func writeStructEnd() throws { + try proto.writeStructEnd() + } + + func writeFieldBegin(name: String, type fieldType: TType, fieldID: Int32) throws { + try proto.writeFieldBegin(name: name, type: fieldType, fieldID: fieldID) + } + + func writeFieldStop() throws { + try proto.writeFieldStop() + } + + func writeFieldEnd() throws { + try proto.writeFieldEnd() + } + + func writeMapBegin(keyType: TType, valueType: TType, size: Int32) throws { + try proto.writeMapBegin(keyType: keyType, valueType: valueType, size: size) + } + + func writeMapEnd() throws { + try proto.writeMapEnd() + } + + func writeSetBegin(elementType: TType, size: Int32) throws { + try proto.writeSetBegin(elementType: elementType, size: size) + } + + func writeSetEnd() throws { + try proto.writeSetEnd() + } + + func writeListBegin(elementType: TType, size: Int32) throws { + try proto.writeListBegin(elementType: elementType, size: size) + } + + func writeListEnd() throws { + try proto.writeListEnd() + } + + func write(_ value: String) throws { + try proto.write(value) + } + + func write(_ value: Bool) throws { + try proto.write(value) + } + + func write(_ value: UInt8) throws { + try proto.write(value) + } + + func write(_ value: Int16) throws { + try proto.write(value) + } + + func write(_ value: Int32) throws { + try proto.write(value) + } + + func write(_ value: Int64) throws { + try proto.write(value) + } + + func write(_ value: Double) throws { + try proto.write(value) + } + + func write(_ value: Data) throws { + try proto.write(value) + } +} diff --git a/lib/swift/Sources/TSocketServer.swift b/lib/swift/Sources/TSocketServer.swift index 7367c7edcbe..a3c63894a79 100644 --- a/lib/swift/Sources/TSocketServer.swift +++ b/lib/swift/Sources/TSocketServer.swift @@ -31,20 +31,22 @@ public let TSocketServerClientConnectionFinished = "TSocketServerClientConnectio public let TSocketServerProcessorKey = "TSocketServerProcessor" public let TSocketServerTransportKey = "TSocketServerTransport" -class TSocketServer where Processor.Service == Service { +class TSocketServer { var socketFileHandle: FileHandle var processingQueue = DispatchQueue(label: "TSocketServer.processing", qos: .background, attributes: .concurrent) var serviceHandler: Service + let processor: Processor public init(port: Int, service: Service, inProtocol: InProtocol.Type, outProtocol: OutProtocol.Type, - processor: Processor.Type) throws { + processor: Processor) throws { // set service handler self.serviceHandler = service + self.processor = processor // create a socket var fd: Int32 = -1 @@ -127,7 +129,6 @@ class TSocketServer(on: transport) + + override func setUp() { + super.setUp() + transport.reset() + } + + override func tearDown() { + super.tearDown() + transport.reset() + } + + func testCallMessageThrowsError() throws { + try proto.writeMessageBegin(name: "message", type: .call, sequenceID: 1) + try transport.flush() + XCTAssertThrowsError(try sut.process(on: proto, outProtocol: proto)) { error in + guard case MultiplexedProcessor.Error.incompatibleMessageType(let type) = error else { + XCTFail() + return + } + XCTAssertEqual(type, .call) + } + } + + func testOneWayMessageThrowsError() throws { + try proto.writeMessageBegin(name: "message", type: .oneway, sequenceID: 1) + try transport.flush() + XCTAssertThrowsError(try sut.process(on: proto, outProtocol: proto)) { error in + guard case MultiplexedProcessor.Error.incompatibleMessageType(let type) = error else { + XCTFail() + return + } + XCTAssertEqual(type, .oneway) + } + } + + func testMissingDefaultProcessorThrowsError() throws { + try proto.writeMessageBegin(name: "message", type: .reply, sequenceID: 1) + try transport.flush() + XCTAssertThrowsError(try sut.process(on: proto, outProtocol: proto)) { error in + guard case MultiplexedProcessor.Error.missingDefaultProcessor = error else { + XCTFail() + return + } + } + } + + func testUsesDefaultProcessorForNonMultiplexedMessage() throws { + let calculator = Calculator() + let calculatorProcessor = CalculatorProcessor(service: calculator) + sut.register(defaultProcessor: calculatorProcessor) + try proto.writeMessageBegin(name: "message", type: .reply, sequenceID: 1) + try transport.flush() + try sut.process(on: proto, outProtocol: proto) + XCTAssertTrue(calculatorProcessor.processCalled) + } + + func testUsesProcessorForMultiplexedMessage() throws { + let calculator = Calculator() + let calculatorProcessor = CalculatorProcessor(service: calculator) + sut.register(processor: calculatorProcessor, for: "Calculator") + try proto.writeMessageBegin(name: "Calculator:message", type: .reply, sequenceID: 1) + try transport.flush() + try sut.process(on: proto, outProtocol: proto) + XCTAssertTrue(calculatorProcessor.processCalled) + } + + func testMissingProcessorForMultiplexedMessageThrowsError() throws { + try proto.writeMessageBegin(name: "Calculator:message", type: .reply, sequenceID: 1) + try transport.flush() + XCTAssertThrowsError(try sut.process(on: proto, outProtocol: proto)) { error in + guard case MultiplexedProcessor.Error.missingProcessor(let serviceName) = error else { + XCTFail() + return + } + XCTAssertEqual(serviceName, "Calculator") + } + } +} From d858a8d4bcdc8767b4a89e3636e61f486ad9366f Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Mon, 13 Jan 2020 23:11:10 +0900 Subject: [PATCH 507/756] THRIFT-5066: Implement testBinary invocation in TestClient.pl Client: perl Patch: Kengo Seki This closes #1984 --- test/perl/TestClient.pl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/perl/TestClient.pl b/test/perl/TestClient.pl index 96e3bec7705..6d49f1da1d8 100755 --- a/test/perl/TestClient.pl +++ b/test/perl/TestClient.pl @@ -218,9 +218,12 @@ sub usage { exit(ERR_BASETYPES) if ($dub ne -852.234234234); # -# BINARY TEST --- TODO +# BINARY TEST # - +print("testBinary(pack('C*', 0..255))"); +my $bin = $testClient->testBinary(pack('C*', 0..255)); +printf(" = %s\n", join ' ', map { sprintf '%02x', $_ } unpack('C*', $bin)); +exit(ERR_BASETYPES) if ($bin ne pack('C*', 0..255)); # # STRUCT TEST From f5a9a30e345fc8cf52d37388cb7b9ab741a3a4ac Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Thu, 22 Aug 2019 22:08:16 +0200 Subject: [PATCH 508/756] THRIFT-5110 Added a number of required libs for using static OpenSSL Client: cpp Patch: Mario Emmenlauer This closes #2020 --- lib/cpp/src/thrift/windows/config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/cpp/src/thrift/windows/config.h b/lib/cpp/src/thrift/windows/config.h index 063a92ad86b..a218d908e9a 100644 --- a/lib/cpp/src/thrift/windows/config.h +++ b/lib/cpp/src/thrift/windows/config.h @@ -64,6 +64,9 @@ #pragma comment(lib, "Ws2.lib") #else #pragma comment(lib, "Ws2_32.lib") + #pragma comment(lib, "gdi32.lib") // For static OpenSSL + #pragma comment(lib, "crypt32.lib") // For static OpenSSL + #pragma comment(lib, "user32.lib") // For static OpenSSL #pragma comment(lib, "advapi32.lib") // For security APIs in TPipeServer #pragma comment(lib, "Shlwapi.lib") // For StrStrIA in TPipeServer #endif From 61d502075bf5da10331c201f604acdfefc4d5edc Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Wed, 23 Oct 2019 17:32:34 +0200 Subject: [PATCH 509/756] THRIFT-5109 Misc Cmake build improvements Patch: Mario Emmenlauer This closes #2026 This closes #2025 This closes #2021 --- CMakeLists.txt | 8 ++++++ build/cmake/DefineOptions.cmake | 14 ++++++++++ compiler/cpp/CMakeLists.txt | 4 +++ lib/js/CMakeLists.txt | 45 +++++++++++++++++++++++++++++++++ lib/nodejs/CMakeLists.txt | 44 ++++++++++++++++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 lib/js/CMakeLists.txt create mode 100644 lib/nodejs/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index f2e682ac2c5..18e52f638fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,14 @@ if(BUILD_JAVA) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/java) endif() +if(BUILD_JAVASCRIPT) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/js) +endif() + +if(BUILD_NODEJS) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/nodejs) +endif() + if(BUILD_PYTHON) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/py) if(BUILD_TESTING) diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 6a69c6d09f3..f85d2c6447a 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -101,6 +101,16 @@ else() "BUILD_LIBRARIES;WITH_JAVA;JAVA_FOUND;GRADLEW_FOUND" OFF) endif() +# Javascript +option(WITH_JAVASCRIPT "Build Javascript Thrift library" ON) +CMAKE_DEPENDENT_OPTION(BUILD_JAVASCRIPT "Build Javascript library" ON + "BUILD_LIBRARIES;WITH_JAVASCRIPT" OFF) + +# NodeJS +option(WITH_NODEJS "Build NodeJS Thrift library" ON) +CMAKE_DEPENDENT_OPTION(BUILD_NODEJS "Build NodeJS library" ON + "BUILD_LIBRARIES;WITH_NODEJS" OFF) + # Python option(WITH_PYTHON "Build Python Thrift library" ON) find_package(PythonInterp QUIET) # for Python executable @@ -182,6 +192,10 @@ else() MESSAGE_DEP(JAVA_FOUND "Java Runtime missing") MESSAGE_DEP(GRADLEW_FOUND "Gradle Wrapper missing") endif() +message(STATUS " Build Javascript library: ${BUILD_JAVASCRIPT}") +MESSAGE_DEP(WITH_JAVASCRIPT "Disabled by WITH_JAVASCRIPT=OFF") +message(STATUS " Build NodeJS library: ${BUILD_NODEJS}") +MESSAGE_DEP(WITH_NODEJS "Disabled by WITH_NODEJS=OFF") message(STATUS) message(STATUS " Build Python library: ${BUILD_PYTHON}") MESSAGE_DEP(WITH_PYTHON "Disabled by WITH_PYTHON=OFF") diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt index 3c292b47a16..4dd316c31ff 100644 --- a/compiler/cpp/CMakeLists.txt +++ b/compiler/cpp/CMakeLists.txt @@ -116,6 +116,10 @@ set_target_properties(thrift-compiler PROPERTIES OUTPUT_NAME thrift) target_link_libraries(thrift-compiler parse) +add_custom_command(TARGET thrift-compiler POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/compiler/cpp" + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/bin/thrift${CMAKE_EXECUTABLE_SUFFIX}" "${CMAKE_SOURCE_DIR}/compiler/cpp/") + install(TARGETS thrift-compiler DESTINATION bin) if(BUILD_TESTING) diff --git a/lib/js/CMakeLists.txt b/lib/js/CMakeLists.txt new file mode 100644 index 00000000000..340b3c6a7b2 --- /dev/null +++ b/lib/js/CMakeLists.txt @@ -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. +# + +if(NOT JAVASCRIPT_INSTALL_DIR) + if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") + set(JAVASCRIPT_INSTALL_DIR "${LIB_INSTALL_DIR}/js") + else() + set(JAVASCRIPT_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/js") + endif() +endif() + +if(IS_ABSOLUTE "${DOC_INSTALL_DIR}") + set(JAVASCRIPT_DOC_INSTALL_DIR "${DOC_INSTALL_DIR}/js") +else() + set(JAVASCRIPT_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}/js") +endif() + +add_custom_target(ThriftJavascript ALL + COMMENT "Building Javascript library using npm + Grunt Wrapper" + COMMAND npm install + COMMAND npx grunt + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/dist/ + DESTINATION ${JAVASCRIPT_INSTALL_DIR} + FILES_MATCHING PATTERN "thrift*.js") +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/ + DESTINATION ${JAVASCRIPT_DOC_INSTALL_DIR}) diff --git a/lib/nodejs/CMakeLists.txt b/lib/nodejs/CMakeLists.txt new file mode 100644 index 00000000000..a0c8508498b --- /dev/null +++ b/lib/nodejs/CMakeLists.txt @@ -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. +# + +if(NOT NODEJS_INSTALL_DIR) + if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") + set(NODEJS_INSTALL_DIR "${LIB_INSTALL_DIR}/nodejs") + else() + set(NODEJS_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/nodejs") + endif() +endif() + +# Currently no doc +#if(IS_ABSOLUTE "${DOC_INSTALL_DIR}") +# set(NODEJS_DOC_INSTALL_DIR "${DOC_INSTALL_DIR}/nodejs") +#else() +# set(NODEJS_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}/nodejs") +#endif() + +add_custom_target(ThriftNodeJS ALL + COMMENT "Installing NodeJS dependencies npm" + COMMAND npm install + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} +) + +install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib/ + DESTINATION ${NODEJS_INSTALL_DIR}) +#install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/ +# DESTINATION ${NODEJS_DOC_INSTALL_DIR}) From f8b3698ab49c5997760867a85f85b01ba9768e8e Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Sat, 22 Feb 2020 10:47:31 +0100 Subject: [PATCH 510/756] Updated Javascript dependencies Client: js Patch: Mario Emmenlauer This closes #2023 --- lib/js/package-lock.json | 802 ++++++++++++++++++++------------------- lib/js/package.json | 12 +- 2 files changed, 427 insertions(+), 387 deletions(-) diff --git a/lib/js/package-lock.json b/lib/js/package-lock.json index dfde697c88d..3f054cdbc0a 100644 --- a/lib/js/package-lock.json +++ b/lib/js/package-lock.json @@ -4,6 +4,12 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -17,36 +23,30 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" - }, - "acorn": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz", - "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, - "acorn-dynamic-import": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", - "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", "dev": true }, "acorn-node": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.6.2.tgz", - "integrity": "sha512-rIhNEZuNI8ibQcL7ANm/mGyPukIaZsRNX9psFNQURyJW0nu6k8wjSDld20z6v2mDBWqX13pIEnk9gGZJHIlEXg==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", "dev": true, "requires": { - "acorn": "^6.0.2", - "acorn-dynamic-import": "^4.0.0", - "acorn-walk": "^6.1.0", - "xtend": "^4.0.1" + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" } }, "acorn-walk": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", - "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz", + "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==", "dev": true }, "agent-base": { @@ -114,30 +114,12 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, - "array-filter": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", - "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", - "dev": true - }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, - "array-map": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", - "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", - "dev": true - }, - "array-reduce": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", - "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", - "dev": true - }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", @@ -162,11 +144,12 @@ } }, "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, "requires": { + "object-assign": "^4.1.1", "util": "0.10.3" }, "dependencies": { @@ -211,11 +194,6 @@ "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, - "babylon": { - "version": "7.0.0-beta.19", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", - "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==" - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -278,15 +256,16 @@ } }, "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", "dev": true }, "bluebird": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true }, "bn.js": { "version": "4.11.8", @@ -363,9 +342,9 @@ } }, "browserify": { - "version": "16.2.3", - "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.2.3.tgz", - "integrity": "sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.5.0.tgz", + "integrity": "sha512-6bfI3cl76YLAnCZ75AGu/XPOsqUhRyc0F/olGIJeCxtfxF2HvPKEcmjU9M8oAPxl4uBY1U7Nry33Q6koV3f2iw==", "dev": true, "requires": { "JSONStream": "^1.0.3", @@ -405,7 +384,7 @@ "shasum": "^1.0.0", "shell-quote": "^1.6.1", "stream-browserify": "^2.0.0", - "stream-http": "^2.0.0", + "stream-http": "^3.0.0", "string_decoder": "^1.1.1", "subarg": "^1.0.0", "syntax-error": "^1.1.1", @@ -418,19 +397,10 @@ "xtend": "^4.0.0" }, "dependencies": { - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -441,16 +411,10 @@ "path-is-absolute": "^1.0.0" } }, - "pako": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.7.tgz", - "integrity": "sha512-3HNK5tW4x8o5mO8RuHZp3Ydw9icZXx0RANAOMzlMzx7LVXhMJ4mo3MOBpzyd7r/+RUu8BmndP47LXT+vzjtWcQ==", - "dev": true - }, "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -474,12 +438,20 @@ } }, "string_decoder": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", - "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + } } } } @@ -546,10 +518,19 @@ "parse-asn1": "^5.0.0" } }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, "buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", - "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", + "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", "dev": true, "requires": { "base64-js": "^1.0.2", @@ -574,12 +555,6 @@ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", "dev": true }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, "builtin-status-codes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", @@ -626,11 +601,20 @@ } }, "catharsis": { - "version": "0.8.9", - "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", - "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=", + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", + "integrity": "sha512-a+xUyMV7hD1BrDQA/3iPV7oc+6W26BgVJO05PGEoatMyIuPScQKsde6i3YorWX1qs+AZjnJ18NqdKoCtKiNh1g==", + "dev": true, "requires": { - "underscore-contrib": "~0.3.0" + "lodash": "^4.17.14" + }, + "dependencies": { + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + } } }, "chalk": { @@ -879,16 +863,25 @@ } }, "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "crypto-browserify": { @@ -919,6 +912,12 @@ "array-find-index": "^1.0.1" } }, + "dash-ast": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz", + "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==", + "dev": true + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -1004,21 +1003,21 @@ "dev": true }, "deps-sort": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", - "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz", + "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==", "dev": true, "requires": { "JSONStream": "^1.0.3", - "shasum": "^1.0.0", + "shasum-object": "^1.0.0", "subarg": "^1.0.0", "through2": "^2.0.0" } }, "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -1032,12 +1031,12 @@ "dev": true }, "detective": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/detective/-/detective-5.1.0.tgz", - "integrity": "sha512-TFHMqfOvxlgrfVzTEkNBSh9SvSNX/HfF4OFI2QFGCyPm02EsyILqnUeb5P6q7JZ3SFNTBL5t2sePRgrN4epUWQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz", + "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==", "dev": true, "requires": { - "acorn-node": "^1.3.0", + "acorn-node": "^1.6.1", "defined": "^1.0.0", "minimist": "^1.1.1" }, @@ -1126,9 +1125,9 @@ }, "dependencies": { "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -1152,9 +1151,9 @@ } }, "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -1199,12 +1198,13 @@ "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, "eventemitter2": { @@ -1383,6 +1383,12 @@ "yauzl": "2.4.1" } }, + "fast-safe-stringify": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", + "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==", + "dev": true + }, "fd-slicer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", @@ -1577,14 +1583,15 @@ } }, "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true }, "grunt": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.3.tgz", - "integrity": "sha512-/JzmZNPfKorlCrrmxWqQO4JVodO+DVd5XX4DkocL/1WlLlKVLE9+SdEIempOAxDhWPysLle6afvn/hg7Ck2k9g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.4.tgz", + "integrity": "sha512-PYsMOrOC+MsdGEkFVwMaMyc6Ob7pKmq+deg1Sjr+vvMWp35sztfwKE7qoN51V+UEtHsyNuMcGdgMLFkBHvMxHQ==", "dev": true, "requires": { "coffeescript": "~1.10.0", @@ -1598,7 +1605,7 @@ "grunt-legacy-log": "~2.0.0", "grunt-legacy-util": "~1.1.1", "iconv-lite": "~0.4.13", - "js-yaml": "~3.5.2", + "js-yaml": "~3.13.0", "minimatch": "~3.0.2", "mkdirp": "~0.5.1", "nopt": "~3.0.6", @@ -1735,22 +1742,13 @@ } }, "grunt-jsdoc": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.3.0.tgz", - "integrity": "sha512-gC66TCRXeQMj3HIyqVSBJm8zdUz43e5vaG/PLO/627A1edbJnzxhJV7nF0KqLwMM0RDNu1istC6fvfnYqFKi3w==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/grunt-jsdoc/-/grunt-jsdoc-2.4.1.tgz", + "integrity": "sha512-S0zxU0wDewRu7z+vijEItOWe/UttxWVmvz0qz2ZVcAYR2GpXjsiski2CAVN0b18t2qeVLdmxZkJaEWCOsKzcAw==", "dev": true, "requires": { - "cross-spawn": "^6.0.5", - "jsdoc": "~3.5.5", - "marked": "^0.5.0" - }, - "dependencies": { - "marked": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.5.1.tgz", - "integrity": "sha512-iUkBZegCZou4AdwbKTwSW/lNDcz5OuRSl3qdcl31Ia0B2QPG0Jn+tKblh/9/eP9/6+4h27vpoh8wel/vQOV0vw==", - "dev": true - } + "cross-spawn": "^7.0.1", + "jsdoc": "^3.6.3" } }, "grunt-known-options": { @@ -1917,9 +1915,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", + "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", "dev": true }, "htmlescape": { @@ -1984,9 +1982,9 @@ } }, "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, "indent-string": { @@ -2095,15 +2093,6 @@ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -2156,13 +2145,10 @@ "dev": true }, "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true }, "is-glob": { "version": "3.1.0", @@ -2251,40 +2237,52 @@ "dev": true }, "js-yaml": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz", - "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { - "argparse": "^1.0.2", - "esprima": "^2.6.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" } }, "js2xmlparser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", - "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.1.tgz", + "integrity": "sha512-KrPTolcw6RocpYjdC7pL7v62e55q7qOMHvLX1UCLc5AAS8qeJ6nukarEJAF2KL2PZxlbGueEbINqZR2bDe/gUw==", + "dev": true, "requires": { - "xmlcreate": "^1.0.1" + "xmlcreate": "^2.0.3" } }, "jsdoc": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", - "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==", - "requires": { - "babylon": "7.0.0-beta.19", - "bluebird": "~3.5.0", - "catharsis": "~0.8.9", - "escape-string-regexp": "~1.0.5", - "js2xmlparser": "~3.0.0", - "klaw": "~2.0.0", - "marked": "~0.3.6", - "mkdirp": "~0.5.1", - "requizzle": "~0.2.1", - "strip-json-comments": "~2.0.1", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.3.tgz", + "integrity": "sha512-Yf1ZKA3r9nvtMWHO1kEuMZTlHOF8uoQ0vyo5eH7SQy5YeIiHM+B0DgKnn+X6y6KDYZcF7G2SPkKF+JORCXWE/A==", + "dev": true, + "requires": { + "@babel/parser": "^7.4.4", + "bluebird": "^3.5.4", + "catharsis": "^0.8.11", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.0", + "klaw": "^3.0.0", + "markdown-it": "^8.4.2", + "markdown-it-anchor": "^5.0.2", + "marked": "^0.7.0", + "mkdirp": "^0.5.1", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.0.1", "taffydb": "2.6.2", - "underscore": "~1.8.3" + "underscore": "~1.9.1" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } } }, "jshint": { @@ -2312,21 +2310,21 @@ } }, "jslint": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/jslint/-/jslint-0.12.0.tgz", - "integrity": "sha512-RoCsyICcKA+6TFsbys9DpKTfPVaC71Mm5QSjvrWA0lDVN+LIvx6apa42FFisMqmCTvJ8DxkcoQGJ0j7m3kTVow==", + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/jslint/-/jslint-0.12.1.tgz", + "integrity": "sha512-q5iHswjOmJffbsGVq/1umGh4YBxb5pCArNHCZeHpkuVDDKM6IldqUn4hLehKSwQr7Bn07VXjD34Lx3nw+6j8eA==", "dev": true, "requires": { "exit": "~0.1.2", - "glob": "~7.1.2", - "nopt": "~3.0.1", + "glob": "~7.1.3", + "nopt": "~4.0.1", "readable-stream": "~2.1.5" }, "dependencies": { "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -2337,15 +2335,6 @@ "path-is-absolute": "^1.0.0" } }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", @@ -2370,9 +2359,10 @@ } }, "json-int64": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-1.0.0.tgz", - "integrity": "sha512-yrTg9swToElhEPETLMdZkEzDhbXLs+cxkw/b2rglMPOBlM1DE0utH1EReSMLcnpYJk5iUvD12r0fP2/xHitF5Q==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-1.0.2.tgz", + "integrity": "sha512-uGrIXtRehbksM17S2lJRLPljufK52KL2ewbJi0xgcRPONoRLXa4yAUIKAUxF69dbnqIoBu33fB28MAWSxupB8Q==", + "dev": true, "requires": { "node-int64": "0.4.0" } @@ -2405,30 +2395,22 @@ "dev": true }, "klaw": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz", - "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, "requires": { "graceful-fs": "^4.1.9" } }, "labeled-stream-splicer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", - "integrity": "sha512-MC94mHZRvJ3LfykJlTUipBqenZz1pacOZEMhhQ8dMGcDHs0SBE5GbsavUXV7YtP3icBW17W0Zy1I0lfASmo9Pg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz", + "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==", "dev": true, "requires": { "inherits": "^2.0.1", - "isarray": "^2.0.4", "stream-splicer": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", - "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==", - "dev": true - } } }, "liftoff": { @@ -2461,6 +2443,15 @@ } } }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, "load-json-file": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -2526,10 +2517,38 @@ "object-visit": "^1.0.0" } }, + "markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "dependencies": { + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + } + } + }, + "markdown-it-anchor": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.2.5.tgz", + "integrity": "sha512-xLIjLQmtym3QpoY9llBgApknl7pxAcN3WDRc2d3rwpl+/YvDZHPmKscGs+L6E05xf2KrCXPBvosWt7MZukwSpQ==", + "dev": true + }, "marked": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", - "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==" + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", + "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", + "dev": true }, "maxmin": { "version": "2.1.0", @@ -2581,6 +2600,12 @@ "safe-buffer": "^5.1.2" } }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, "meow": { "version": "3.7.0", "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", @@ -2668,7 +2693,8 @@ "minimist": { "version": "0.0.8", "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true }, "mixin-deep": { "version": "1.3.1", @@ -2695,22 +2721,23 @@ "version": "0.5.1", "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, "requires": { "minimist": "0.0.8" } }, "module-deps": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.0.tgz", - "integrity": "sha512-hKPmO06so6bL/ZvqVNVqdTVO8UAYsi3tQWlCa+z9KuWhoN4KDQtb5hcqQQv58qYiDE21wIvnttZEPiDgEbpwbA==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.2.tgz", + "integrity": "sha512-a9y6yDv5u5I4A+IPHTnqFxcaKr4p50/zxTjcQJaX2ws9tN/W6J6YXnEKhqRyPhl494dkcxx951onSKVezmI+3w==", "dev": true, "requires": { "JSONStream": "^1.0.3", "browser-resolve": "^1.7.0", - "cached-path-relative": "^1.0.0", + "cached-path-relative": "^1.0.2", "concat-stream": "~1.6.0", "defined": "^1.0.0", - "detective": "^5.0.2", + "detective": "^5.2.0", "duplexer2": "^0.1.2", "inherits": "^2.0.1", "parents": "^1.0.0", @@ -2723,9 +2750,9 @@ }, "dependencies": { "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -2738,12 +2765,12 @@ } }, "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "^1.0.6" } }, "string_decoder": { @@ -2782,36 +2809,43 @@ "to-regex": "^3.0.1" } }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true }, "nopt": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "dev": true, "requires": { "abbrev": "1", "osenv": "^0.1.4" } }, "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", + "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } } }, "number-is-nan": { @@ -2915,17 +2949,20 @@ "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true }, "osenv": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, "requires": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" @@ -2946,6 +2983,12 @@ "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", "dev": true }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "parents": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", @@ -2956,16 +2999,17 @@ } }, "parse-asn1": { - "version": "5.1.1", - "resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", "dev": true, "requires": { "asn1.js": "^4.0.0", "browserify-aes": "^1.0.0", "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" } }, "parse-filepath": { @@ -3022,9 +3066,9 @@ "dev": true }, "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, "path-parse": { @@ -3210,9 +3254,9 @@ "dev": true }, "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { "safe-buffer": "^5.1.0" @@ -3238,9 +3282,9 @@ }, "dependencies": { "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -3355,17 +3399,19 @@ } }, "requizzle": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", - "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.3.tgz", + "integrity": "sha512-YanoyJjykPxGHii0fZP0uUPEXpvqfBDxWV7s6GKAiiOsiqhX6vHNyW3Qzdmqp/iq/ExbhaGbVrjB4ruEVSM4GQ==", + "dev": true, "requires": { - "underscore": "~1.6.0" + "lodash": "^4.17.14" }, "dependencies": { - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true } } }, @@ -3438,9 +3484,9 @@ "dev": true }, "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true }, "set-value": { @@ -3486,32 +3532,35 @@ "sha.js": "~2.4.4" } }, + "shasum-object": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz", + "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==", + "dev": true, + "requires": { + "fast-safe-stringify": "^2.0.7" + } + }, "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "^3.0.0" } }, "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, "shell-quote": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", - "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", - "dev": true, - "requires": { - "array-filter": "~0.0.0", - "array-map": "~0.0.0", - "array-reduce": "~0.0.0", - "jsonify": "~0.0.0" - } + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "dev": true }, "shelljs": { "version": "0.3.0", @@ -3664,9 +3713,9 @@ "dev": true }, "spdx-correct": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", - "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -3690,9 +3739,9 @@ } }, "spdx-license-ids": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", - "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", "dev": true }, "split-string": { @@ -3705,9 +3754,9 @@ } }, "sprintf-js": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", - "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", "dev": true }, "static-extend": { @@ -3732,9 +3781,9 @@ } }, "stream-browserify": { - "version": "2.0.1", - "resolved": "http://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", "dev": true, "requires": { "inherits": "~2.0.1", @@ -3742,9 +3791,9 @@ }, "dependencies": { "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -3778,9 +3827,9 @@ }, "dependencies": { "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -3804,48 +3853,49 @@ } }, "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.1.0.tgz", + "integrity": "sha512-cuB6RgO7BqC4FBYzmnvhob5Do3wIdIsXAgGycHJnW+981gHqoYcYz9lqjJrk8WXRddbwPuqPYRl+bag6mYv4lw==", "dev": true, "requires": { "builtin-status-codes": "^3.0.0", "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", + "readable-stream": "^3.0.6", "xtend": "^4.0.0" }, "dependencies": { "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, "string_decoder": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } } } }, "stream-splicer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", - "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz", + "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -3853,9 +3903,9 @@ }, "dependencies": { "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -3912,9 +3962,10 @@ } }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true }, "subarg": { "version": "1.0.0", @@ -3954,7 +4005,8 @@ "taffydb": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", - "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=" + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=", + "dev": true }, "through": { "version": "2.3.8", @@ -3973,9 +4025,9 @@ }, "dependencies": { "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -4007,12 +4059,6 @@ "process": "~0.11.0" } }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -4073,6 +4119,12 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, "uglify-js": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", @@ -4104,36 +4156,23 @@ "dev": true }, "undeclared-identifiers": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz", - "integrity": "sha512-13EaeocO4edF/3JKime9rD7oB6QI8llAGhgn5fKOPyfkJbRb6NFv9pYV6dFEmpa4uRjKeBqLZP8GpuzqHlKDMQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz", + "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==", "dev": true, "requires": { "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", "get-assigned-identifiers": "^1.2.0", "simple-concat": "^1.0.0", "xtend": "^4.0.1" } }, "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "underscore-contrib": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz", - "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=", - "requires": { - "underscore": "1.6.0" - }, - "dependencies": { - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" - } - } + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz", + "integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==", + "dev": true }, "underscore.string": { "version": "3.3.5", @@ -4291,9 +4330,9 @@ } }, "vm-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", - "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, "which": { @@ -4321,14 +4360,15 @@ } }, "xmlcreate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", - "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.3.tgz", + "integrity": "sha512-HgS+X6zAztGa9zIK3Y3LXuJes33Lz9x+YyTxgrkIdabu2vqcGOWwdfCpf1hWLRrd553wd4QCDf6BBO6FfdsRiQ==", + "dev": true }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, "yauzl": { diff --git a/lib/js/package.json b/lib/js/package.json index dc48846076a..a46a7325594 100644 --- a/lib/js/package.json +++ b/lib/js/package.json @@ -12,18 +12,18 @@ "repository": "https://github.com/apache/thrift", "license": "Apache-2.0", "devDependencies": { - "browserify": "~16.2", + "browserify": "~16.5", "grunt-cli": "~1.3", "grunt-contrib-concat": "~1.0", "grunt-contrib-jshint": "~2.1", "grunt-contrib-qunit": "~3.1", "grunt-contrib-uglify": "~4.0", - "grunt-jsdoc": "~2.3", + "grunt-jsdoc": "~2.4", "grunt-shell-spawn": "~0.4", - "grunt": "~1.0", - "jsdoc": "~3.5", - "jslint": "~0.12", - "json-int64": "~1.0", + "grunt": "~1.0.4", + "jsdoc": "~3.6", + "jslint": "~0.12.1", + "json-int64": "~1.0.2", "node-int64": "~0.4.0", "nopt": "~4.0" } From b70dc1e61c5c4637d16160df3197164e0bef79bf Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Sat, 14 Dec 2019 11:23:05 +0100 Subject: [PATCH 511/756] Updated gradle to 6.2 Client: java Patch: Mario Emmenlauer This closes #2022 --- lib/java/gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/java/gradle/wrapper/gradle-wrapper.properties b/lib/java/gradle/wrapper/gradle-wrapper.properties index 7c4388a9216..b7c8c5dbf58 100644 --- a/lib/java/gradle/wrapper/gradle-wrapper.properties +++ b/lib/java/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 13cbc8defa0877c14af42666b9a7575dea78de72 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Thu, 20 Feb 2020 23:22:56 +0100 Subject: [PATCH 512/756] Updated NodeJS dependencies Client: nodejs Patch: Mario Emmenlauer This closes #2024 --- package-lock.json | 1769 ++++++++++++++++++++++++++++++--------------- package.json | 6 +- 2 files changed, 1181 insertions(+), 594 deletions(-) diff --git a/package-lock.json b/package-lock.json index 15a18859252..5cab4bff159 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,147 @@ "@babel/highlight": "^7.0.0" } }, + "@babel/core": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.8.4.tgz", + "integrity": "sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helpers": "^7.8.4", + "@babel/parser": "^7.8.4", + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "resolve": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", + "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", + "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", + "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helpers": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", + "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.8.4", + "@babel/types": "^7.8.3" + } + }, "@babel/highlight": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", @@ -30,6 +171,148 @@ "integrity": "sha512-bqv+iCo9i+uLVbI0ILzKkvMorqxouI+GbV13ivcARXn9NNEabi2IEz912IgNpT/60BNXac5dgcfjb94NjsF33A==", "dev": true }, + "@babel/template": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", + "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.3", + "@babel/types": "^7.8.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + } + } + }, + "@babel/traverse": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", + "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.8.4", + "@babel/helper-function-name": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.8.4", + "@babel/types": "^7.8.3", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.8.3" + } + }, + "@babel/highlight": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", + "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "dev": true + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", + "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", + "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, "@types/node": { "version": "10.12.6", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.6.tgz", @@ -51,12 +334,6 @@ "integrity": "sha512-eqz8c/0kwNi/OEHQfvIuJVLTst3in0e7uTKeuY+WL/zfKn0xVujOTp42bS/vUUokhK5P2BppLd9JXMOMHcgbjA==", "dev": true }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, "acorn": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.2.tgz", @@ -69,6 +346,16 @@ "integrity": "sha512-XkB50fn0MURDyww9+UYL3c1yLbOBz0ZFvrdYlGB8l+Ije1oSC75qAqrzSPjYQbdnQUzhlUGNKuesryAv0gxZOg==", "dev": true }, + "aggregate-error": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", + "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", @@ -81,13 +368,6 @@ "uri-js": "^4.2.2" } }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true - }, "ansi-escapes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", @@ -109,22 +389,21 @@ "color-convert": "^1.9.0" } }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" + "default-require-extensions": "^3.0.0" } }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -170,12 +449,6 @@ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, - "async": { - "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, "async-limiter": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", @@ -214,22 +487,6 @@ "tweetnacl": "^0.14.3" } }, - "bindings": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", - "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==", - "dev": true - }, - "bl": { - "version": "1.2.2", - "resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz", - "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", - "dev": true, - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - } - }, "bluebird": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz", @@ -251,33 +508,23 @@ "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.2.1.tgz", "integrity": "sha512-sVIA0cysIED0nbmNOm7sZzKfgN1rpFmrqvLZaFWspaBAftfQcezlC81G6j6U2RJf4Lh66zFxrCeOsvkUXIcPWg==" }, - "buffer-alloc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", - "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", - "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", - "dev": true - }, "buffer-equals": { "version": "1.0.4", "resolved": "http://registry.npmjs.org/buffer-equals/-/buffer-equals-1.0.4.tgz", "integrity": "sha1-A1O1T9B/2VZBcGca5vZrnPENJ/U=", "dev": true }, - "buffer-fill": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", - "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", - "dev": true + "caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "requires": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + } }, "caller-path": { "version": "0.1.0", @@ -294,6 +541,12 @@ "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", "dev": true }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -326,18 +579,18 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, - "chownr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", - "dev": true - }, "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -353,11 +606,50 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } }, "color-convert": { "version": "1.9.3", @@ -389,6 +681,12 @@ "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", "dev": true }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -407,11 +705,14 @@ "utils-merge": "1.0.1" } }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } }, "core-util-is": { "version": "1.0.2", @@ -450,14 +751,11 @@ "ms": "2.0.0" } }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true }, "deep-equal": { "version": "1.0.1", @@ -465,18 +763,21 @@ "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", "dev": true }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, + "requires": { + "strip-bom": "^4.0.0" + } + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -513,18 +814,6 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "dev": true - }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -550,21 +839,18 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", "dev": true }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, "entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", @@ -595,6 +881,12 @@ "is-symbol": "^1.0.2" } }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -607,33 +899,6 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - } - } - }, "eslint": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.7.0.tgz", @@ -795,12 +1060,6 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, - "expand-template": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.1.tgz", - "integrity": "sha512-cebqLtV8KOZfw0UI8TEFWxtczxxC1jvyUvx6H4fyp1K1FN7A4Q+uggVUlOsI1K8AGU0rwOGqP8nCapdrw8CYQg==", - "dev": true - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -882,6 +1141,27 @@ "unpipe": "~1.0.0" } }, + "find-cache-dir": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.2.0.tgz", + "integrity": "sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.0", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, "flat-cache": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", @@ -903,13 +1183,66 @@ "is-callable": "^1.1.3" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { + "foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", @@ -920,10 +1253,10 @@ "mime-types": "^2.1.12" } }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "fromentries": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", + "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", "dev": true }, "fs.realpath": { @@ -944,58 +1277,17 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true }, "get-stdin": { "version": "6.0.0", @@ -1012,12 +1304,6 @@ "assert-plus": "^1.0.0" } }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "dev": true - }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", @@ -1058,35 +1344,6 @@ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", "dev": true }, - "handlebars": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.12.tgz", - "integrity": "sha512-RhmTekP+FZL+XNhwS1Wf+bTTZpdLougwt5pcgA1tuz6Jcx0fpH/7z0qd71RKnZHBCxIRBHfBOnio4gViPemNzA==", - "dev": true, - "requires": { - "async": "^2.5.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - }, - "dependencies": { - "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -1138,10 +1395,20 @@ "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", "dev": true }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "hasha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", + "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", + "dev": true, + "requires": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + } + }, + "html-escaper": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", + "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", "dev": true }, "html-validator": { @@ -1204,6 +1471,12 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -1220,12 +1493,6 @@ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, "inquirer": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", @@ -1310,6 +1577,12 @@ "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", "dev": true }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, "is-symbol": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", @@ -1325,10 +1598,10 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, "isexe": { @@ -1348,64 +1621,195 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" + "istanbul-lib-coverage": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "requires": { + "append-transform": "^2.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz", + "integrity": "sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@babel/parser": "^7.7.5", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" }, "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "@babel/parser": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", + "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", "dev": true }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" + }, + "dependencies": { + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "^4.0.0" } } } }, + "istanbul-lib-source-maps": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.0.tgz", + "integrity": "sha512-2osTcC8zcOSUkImzN2EWQta3Vdi4WjjKw99P2yWx5mLnigAM0Rd5uYFn1cf2i/Ois45GkNjaoTqc5CxgMSX80A==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1473,10 +1877,16 @@ } } }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, "json-int64": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-1.0.0.tgz", - "integrity": "sha512-yrTg9swToElhEPETLMdZkEzDhbXLs+cxkw/b2rglMPOBlM1DE0utH1EReSMLcnpYJk5iUvD12r0fP2/xHitF5Q==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-int64/-/json-int64-1.0.2.tgz", + "integrity": "sha512-uGrIXtRehbksM17S2lJRLPljufK52KL2ewbJi0xgcRPONoRLXa4yAUIKAUxF69dbnqIoBu33fB28MAWSxupB8Q==", "dev": true, "requires": { "node-int64": "0.4.0" @@ -1506,6 +1916,23 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "json5": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", + "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -1546,12 +1973,44 @@ "uc.micro": "^1.0.1" } }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "make-dir": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", + "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "markdown-it": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", @@ -1604,12 +2063,6 @@ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1646,12 +2099,6 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, - "nan": { - "version": "2.10.0", - "resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -1664,53 +2111,99 @@ "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", "dev": true }, - "node-abi": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.5.tgz", - "integrity": "sha512-aa/UC6Nr3+tqhHGRsAuw/edz7/q9nnetBrKWxj6rpTtm+0X9T1qU7lIEHMS3yN9JwAbRiKUbRRFy1PLz/y3aaA==", - "dev": true, - "requires": { - "semver": "^5.4.1" - } + "node-gyp-build": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-3.7.0.tgz", + "integrity": "sha512-L/Eg02Epx6Si2NXmedx+Okg+4UHqmaf3TNcxd50SF9NQGcJaON3AtU++kax69XV7YWz4tUspqZSAsVofhFKG2w==", + "dev": true }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" }, - "noop-logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", - "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", - "dev": true - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" + "node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "requires": { + "process-on-spawn": "^1.0.0" + } + }, + "nyc": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.0.0.tgz", + "integrity": "sha512-qcLBlNCKMDVuKb7d1fpxjPR8sHeMVX0CHarXAVzrVWoFrigCkYR8xcrjfXSPi5HXM7EU78L6ywO7w1c5rZNCNg==", + "dev": true, + "requires": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.0", + "js-yaml": "^3.13.1", + "make-dir": "^3.0.0", + "node-preload": "^0.2.0", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "uuid": "^3.3.3", + "yargs": "^15.0.2" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -1762,24 +2255,6 @@ "mimic-fn": "^1.0.0" } }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - }, - "dependencies": { - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - } - } - }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", @@ -1794,24 +2269,77 @@ "wordwrap": "~1.0.0" } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-limit": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + } + } + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", "dev": true }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1863,43 +2391,21 @@ "pinkie": "^2.0.0" } }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, - "prebuild-install": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-4.0.0.tgz", - "integrity": "sha512-7tayxeYboJX0RbVzdnKyGl2vhQRWr6qfClEXDhOkXjuaOKCw2q8aiuFhONRYVsG/czia7KhpykIlI2S2VaPunA==", - "dev": true, - "requires": { - "detect-libc": "^1.0.3", - "expand-template": "^1.0.2", - "github-from-package": "0.0.0", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "node-abi": "^2.2.0", - "noop-logger": "^0.1.1", - "npmlog": "^4.0.1", - "os-homedir": "^1.0.1", - "pump": "^2.0.1", - "rc": "^1.1.6", - "simple-get": "^2.7.0", - "tar-fs": "^1.13.0", - "tunnel-agent": "^0.6.0", - "which-pm-runs": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -1921,11 +2427,14 @@ "fast-diff": "^1.1.2" } }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true + "process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "requires": { + "fromentries": "^1.2.0" + } }, "progress": { "version": "2.0.1", @@ -1939,16 +2448,6 @@ "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", "dev": true }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -1966,47 +2465,21 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, + "release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "requires": { + "es6-error": "^4.0.1" + } + }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -2035,6 +2508,18 @@ "uuid": "^3.3.2" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, "require-uncached": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", @@ -2054,12 +2539,6 @@ "lodash": "^4.17.14" } }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - }, "resolve-from": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", @@ -2157,23 +2636,6 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, - "simple-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", - "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=", - "dev": true - }, - "simple-get": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", - "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", - "dev": true, - "requires": { - "decompress-response": "^3.3.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, "slice-ansi": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", @@ -2183,14 +2645,38 @@ "is-fullwidth-code-point": "^2.0.0" } }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, - "optional": true, "requires": { - "amdefine": ">=0.0.4" + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "sprintf-js": { @@ -2243,15 +2729,6 @@ "function-bind": "^1.0.2" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -2261,6 +2738,12 @@ "ansi-regex": "^3.0.0" } }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -2332,45 +2815,33 @@ } } }, - "tar-fs": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", - "integrity": "sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==", + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "requires": { - "chownr": "^1.0.1", - "mkdirp": "^0.5.1", - "pump": "^1.0.0", - "tar-stream": "^1.1.2" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "dependencies": { - "pump": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", - "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } } } }, - "tar-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", - "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", - "dev": true, - "requires": { - "bl": "^1.0.0", - "buffer-alloc": "^1.2.0", - "end-of-stream": "^1.0.0", - "fs-constants": "^1.0.0", - "readable-stream": "^2.3.0", - "to-buffer": "^1.1.1", - "xtend": "^4.0.0" - } - }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -2392,10 +2863,10 @@ "os-tmpdir": "~1.0.2" } }, - "to-buffer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", - "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, "tough-cookie": { @@ -2446,6 +2917,21 @@ "prelude-ls": "~1.1.2" } }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, "typescript": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz", @@ -2458,33 +2944,6 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", "dev": true }, - "uglify-js": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", - "dev": true, - "optional": true, - "requires": { - "commander": "~2.17.1", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true, - "optional": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - } - } - }, "underscore": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", @@ -2507,22 +2966,14 @@ } }, "utf-8-validate": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-4.0.2.tgz", - "integrity": "sha512-CS63Ssp6zynBQ4IxVzgjP5Abdo6LuJ87HFIcgIiVUeY96+MTHkqKtrUhphbwQ6jX8aSGZv8zX6l1DCPpfcAnxA==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.2.tgz", + "integrity": "sha512-SwV++i2gTD5qh2XqaPzBnNX88N6HdyhQrNNRykvcS0QKvItV9u3vPEJr+X5Hhfb1JC0r0e1alL0iB09rY8+nmw==", "dev": true, "requires": { - "bindings": "~1.3.0", - "nan": "~2.10.0", - "prebuild-install": "~4.0.0" + "node-gyp-build": "~3.7.0" } }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -2561,27 +3012,88 @@ "isexe": "^2.0.0" } }, - "which-pm-runs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", - "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", "dev": true }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2597,6 +3109,18 @@ "mkdirp": "^0.5.1" } }, + "write-file-atomic": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.1.tgz", + "integrity": "sha512-JPStrIyyVJ6oCSz/691fAjFtefZ6q+fP6tm+OS4Qw6o+TGQxNp1ziY2PgS+X/m0V8OWhZiO/m4xSj+Pr4RrZvw==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, "ws": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", @@ -2611,11 +3135,74 @@ "integrity": "sha512-MjGsXhKG8YjTKrDCXseFo3ClbMGvUD4en29H2Cev1dv4P/chlpw6KdYmlCWDkhosBVKRDjM836+3e3pm1cBNJA==", "dev": true }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.1.0.tgz", + "integrity": "sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^16.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "yargs-parser": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-16.1.0.tgz", + "integrity": "sha512-H/V41UNZQPkUMIT5h5hiwg4QKIY1RPvoBV4XcjUbRM8Bk2oKqqyZ0DIEbTFZB0XjbtSPG8SAa/0DxCQmiRgzKg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } } diff --git a/package.json b/package.json index c803df5bcdb..4928653e3be 100644 --- a/package.json +++ b/package.json @@ -53,13 +53,13 @@ "eslint-config-prettier": "^3.1.0", "eslint-plugin-prettier": "^3.0.0", "html-validator-cli": "^4.1.4", - "istanbul": "^0.4.5", + "nyc": "^15.0.0", "jsdoc": "^3.6.3", - "json-int64": "^1.0.0", + "json-int64": "^1.0.2", "prettier": "^1.14.3", "tape": "^4.9.0", "typescript": "^3.1.6", - "utf-8-validate": "^4.0.0" + "utf-8-validate": "^5.0.0" }, "scripts": { "cover": "lib/nodejs/test/testAll.sh COVER", From 66d110bcce5c7e1b0deeacd28b046fb4a9c0249b Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Mon, 15 Apr 2019 13:36:02 +0200 Subject: [PATCH 513/756] THRIFT-5109 Misc Cmake build improvements Patch: Mario Emmenlauer This closes #2017 This closes #2018 This closes #2019 - build/cmake/DefineInstallationPaths.cmake: fixed the library path - build/cmake/ThriftMacros.cmake: do not enforce debug suffix 'd' - lib/java/CMakeLists.txt: allow to override JAVA_INSTALL_DIR --- build/cmake/DefineInstallationPaths.cmake | 6 +++++- build/cmake/DefinePlatformSpecifc.cmake | 4 ++-- lib/java/CMakeLists.txt | 11 ++++++----- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/build/cmake/DefineInstallationPaths.cmake b/build/cmake/DefineInstallationPaths.cmake index 0c824cc7a1b..23962b442d0 100644 --- a/build/cmake/DefineInstallationPaths.cmake +++ b/build/cmake/DefineInstallationPaths.cmake @@ -20,7 +20,11 @@ # Define the default install paths set(BIN_INSTALL_DIR "bin" CACHE PATH "The binary install dir (default: bin)") -set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "The library install dir (default: lib${LIB_SUFFIX})") +if(MSVC) + set(LIB_INSTALL_DIR "bin${LIB_SUFFIX}" CACHE PATH "The library install dir (default: bin${LIB_SUFFIX})") +else() + set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "The library install dir (default: lib${LIB_SUFFIX})") +endif() set(INCLUDE_INSTALL_DIR "include" CACHE PATH "The library install dir (default: include)") set(CMAKE_INSTALL_DIR "lib/cmake" CACHE PATH "The subdirectory to install cmake config files (default: cmake)") set(PKGCONFIG_INSTALL_DIR "lib/pkgconfig" CACHE PATH "The subdirectory to install pkgconfig config files (default: lib/pkgconfig)") diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index c0bb529c350..f43f5032351 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -20,8 +20,8 @@ # Uncomment this to show some basic cmake variables about platforms # include (NewPlatformDebug) -# For Debug build types, append a "d" to the library names. -set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Set debug library postfix" FORCE) +# For Debug build types, default to "d"-suffix in library names. +set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Set debug library postfix") # basic options foreach(lang IN ITEMS C CXX) diff --git a/lib/java/CMakeLists.txt b/lib/java/CMakeLists.txt index a67845aba5d..28158c00776 100644 --- a/lib/java/CMakeLists.txt +++ b/lib/java/CMakeLists.txt @@ -29,11 +29,12 @@ if(ANDROID) add_custom_target(thrift_aar ALL DEPENDS ${THRIFT_AAR}) else() - - if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") - set(JAVA_INSTALL_DIR "${LIB_INSTALL_DIR}/java") - else() - set(JAVA_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/java") + if(NOT JAVA_INSTALL_DIR) + if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") + set(JAVA_INSTALL_DIR "${LIB_INSTALL_DIR}/java") + else() + set(JAVA_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/java") + endif() endif() if(IS_ABSOLUTE "${DOC_INSTALL_DIR}") From 4b475af6943d99a21e2b79578167a4d228fe0df1 Mon Sep 17 00:00:00 2001 From: Alexander Edge Date: Mon, 24 Feb 2020 10:37:25 +0000 Subject: [PATCH 514/756] =?UTF-8?q?THRIFT-5084:=20Multiplexed=20processor?= =?UTF-8?q?=20in=20Swift=20=E2=80=93=20explicit=20return=20statements=20Cl?= =?UTF-8?q?ient:=20swift=20Patch:=20Alexander=20Edge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This closes #2028 --- lib/swift/Sources/TMultiplexedProcessor.swift | 2 +- lib/swift/Sources/TProtocolDecorator.swift | 28 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/swift/Sources/TMultiplexedProcessor.swift b/lib/swift/Sources/TMultiplexedProcessor.swift index 9841d3fa8f6..661d4a7a807 100644 --- a/lib/swift/Sources/TMultiplexedProcessor.swift +++ b/lib/swift/Sources/TMultiplexedProcessor.swift @@ -86,6 +86,6 @@ private final class StoredMessage: TProtocolDecorator { } override func readMessageBegin() throws -> (String, TMessageType, Int32) { - message + return message } } diff --git a/lib/swift/Sources/TProtocolDecorator.swift b/lib/swift/Sources/TProtocolDecorator.swift index 3f3b4a1215f..b1b1480db03 100644 --- a/lib/swift/Sources/TProtocolDecorator.swift +++ b/lib/swift/Sources/TProtocolDecorator.swift @@ -34,7 +34,7 @@ class TProtocolDecorator: TProtocol { } func readMessageBegin() throws -> (String, TMessageType, Int32) { - try proto.readMessageBegin() + return try proto.readMessageBegin() } func readMessageEnd() throws { @@ -42,7 +42,7 @@ class TProtocolDecorator: TProtocol { } func readStructBegin() throws -> String { - try proto.readStructBegin() + return try proto.readStructBegin() } func readStructEnd() throws { @@ -50,7 +50,7 @@ class TProtocolDecorator: TProtocol { } func readFieldBegin() throws -> (String, TType, Int32) { - try proto.readFieldBegin() + return try proto.readFieldBegin() } func readFieldEnd() throws { @@ -58,7 +58,7 @@ class TProtocolDecorator: TProtocol { } func readMapBegin() throws -> (TType, TType, Int32) { - try proto.readMapBegin() + return try proto.readMapBegin() } func readMapEnd() throws { @@ -66,7 +66,7 @@ class TProtocolDecorator: TProtocol { } func readSetBegin() throws -> (TType, Int32) { - try proto.readSetBegin() + return try proto.readSetBegin() } func readSetEnd() throws { @@ -74,7 +74,7 @@ class TProtocolDecorator: TProtocol { } func readListBegin() throws -> (TType, Int32) { - try proto.readListBegin() + return try proto.readListBegin() } func readListEnd() throws { @@ -82,35 +82,35 @@ class TProtocolDecorator: TProtocol { } func read() throws -> String { - try proto.read() + return try proto.read() } func read() throws -> Bool { - try proto.read() + return try proto.read() } func read() throws -> UInt8 { - try proto.read() + return try proto.read() } func read() throws -> Int16 { - try proto.read() + return try proto.read() } func read() throws -> Int32 { - try proto.read() + return try proto.read() } func read() throws -> Int64 { - try proto.read() + return try proto.read() } func read() throws -> Double { - try proto.read() + return try proto.read() } func read() throws -> Data { - try proto.read() + return try proto.read() } func writeMessageBegin(name: String, type messageType: TMessageType, sequenceID: Int32) throws { From b7b02afcd835639a0735731a63ff5b1386879c97 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Mon, 24 Feb 2020 22:25:24 +0100 Subject: [PATCH 515/756] THRIFT-5115 PR #2022 Updated gradle to 6.2 broke CI Client: java Patch: Mario Emmenlauer This closes #2031 Downgraded gradle to 5.6.4 after problems with 6.x in AS3 --- .../gradle/wrapper/gradle-wrapper.properties | 2 +- lib/as3/gradlew.bat | 18 +++++++++++++++++- .../gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/as3/gradle/wrapper/gradle-wrapper.properties b/lib/as3/gradle/wrapper/gradle-wrapper.properties index 558870dad58..5028f28f8e4 100644 --- a/lib/as3/gradle/wrapper/gradle-wrapper.properties +++ b/lib/as3/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/lib/as3/gradlew.bat b/lib/as3/gradlew.bat index 6d57edc706c..9618d8d9607 100644 --- a/lib/as3/gradlew.bat +++ b/lib/as3/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/lib/java/gradle/wrapper/gradle-wrapper.properties b/lib/java/gradle/wrapper/gradle-wrapper.properties index b7c8c5dbf58..5028f28f8e4 100644 --- a/lib/java/gradle/wrapper/gradle-wrapper.properties +++ b/lib/java/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From aec555aac89ec9634e99ce0f4f0aec5799e6e3d8 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 26 Feb 2020 00:14:25 +0100 Subject: [PATCH 516/756] make dist fails due to CMakeList.txt files missing from the generated tarball --- lib/js/Makefile.am | 1 + lib/nodejs/Makefile.am | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/js/Makefile.am b/lib/js/Makefile.am index b534042649a..c14303e67f6 100644 --- a/lib/js/Makefile.am +++ b/lib/js/Makefile.am @@ -58,5 +58,6 @@ EXTRA_DIST = \ package.json \ package-lock.json \ README.md \ + CMakeLists.txt \ src \ test diff --git a/lib/nodejs/Makefile.am b/lib/nodejs/Makefile.am index 71068b58f18..67f6ff6a90a 100755 --- a/lib/nodejs/Makefile.am +++ b/lib/nodejs/Makefile.am @@ -42,4 +42,5 @@ EXTRA_DIST = \ lib \ test \ coding_standards.md \ + CMakeLists.txt \ README.md From 4903d18fca988871bcedce3b420fef2cd9682ca1 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 27 Feb 2020 20:27:03 +0100 Subject: [PATCH 517/756] THRIFT-5123 add possibility to query HTTP status code with WinHTTP Client: delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.WinHTTP.pas | 54 ++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index 5c0719342f4..abbb0044b13 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -576,7 +576,7 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; IWinHTTPConnection = interface; IWinHTTPRequest = interface - ['{7AE6F63F-49B6-436B-8AAB-159E58EB900A}'] + ['{FADA4B45-D447-4F07-8361-1AD6656E5E8C}'] function Handle : HINTERNET; function Connection : IWinHTTPConnection; function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean; @@ -590,6 +590,7 @@ function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS; function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; function QueryDataAvailable : DWORD; function QueryTotalResponseSize( out dwSize : DWORD) : Boolean; + function QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean; end; IWinHTTPConnection = interface @@ -710,6 +711,7 @@ TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest) function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload; function QueryDataAvailable : DWORD; function QueryTotalResponseSize( out dwSize : DWORD) : Boolean; + function QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean; public constructor Create( const aConnection : IWinHTTPConnection; @@ -1230,6 +1232,53 @@ function TWinHTTPRequestImpl.QueryTotalResponseSize( out dwSize : DWORD) : Boole end; +function TWinHTTPRequestImpl.QueryHttpStatus( out dwStatusCode : DWORD; out sStatusText : string) : Boolean; +var dwBytes, dwError, dwIndex : DWORD; +begin + // HTTP status code + dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX); + dwBytes := SizeOf(dwStatusCode); + result := WinHttpQueryHeaders( FHandle, + WINHTTP_QUERY_STATUS_CODE or WINHTTP_QUERY_FLAG_NUMBER, + WINHTTP_HEADER_NAME_BY_INDEX, + @dwStatusCode, dwBytes, + dwIndex); + if not result then begin + dwStatusCode := 0; // no data + dwError := GetLastError; + if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error + end; + + // HTTP status text + dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX); + dwBytes := 0; + result := WinHttpQueryHeaders( FHandle, + WINHTTP_QUERY_STATUS_TEXT, + WINHTTP_HEADER_NAME_BY_INDEX, + WINHTTP_NO_OUTPUT_BUFFER, // we need to determine the size first + dwBytes, // will receive the required buffer size + dwIndex); + if dwBytes > 0 then begin // allocate buffer and call again to get the value + SetLength( sStatusText, dwBytes div SizeOf(Char)); + dwBytes := Length(sStatusText) * SizeOf(Char); + result := WinHttpQueryHeaders( FHandle, + WINHTTP_QUERY_STATUS_TEXT, + WINHTTP_HEADER_NAME_BY_INDEX, + @sStatusText[1], dwBytes, + dwIndex); + end; + if result + then SetLength( sStatusText, StrLen(PChar(sStatusText))) // get rid of any terminating #0 chars + else begin + sStatusText := ''; // no data + dwError := GetLastError; + if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error + end; + + // do we have at least something? + result := (dwStatusCode <> 0) or (sStatusText <> ''); +end; + { TWinHTTPUrlImpl } @@ -1385,9 +1434,6 @@ procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString); end; -initialization - OutputDebugString( PChar( SysErrorMessage( 12002))); - end. From 56700e469d5d0659994a3963ad5a111740cf8277 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 22 Feb 2020 16:51:51 +0100 Subject: [PATCH 518/756] THRIFT-4982 Remove deprecated C# bindings from the code base Client: csharp Patch: Jens Geyer This closes #2027 --- .gitignore | 17 - ApacheThrift.nuspec | 11 +- CHANGES.md | 1 + LANGUAGES.md | 22 - Makefile.am | 2 +- build/docker/old/debian-jessie/Dockerfile | 5 - build/docker/old/debian-stretch/Dockerfile | 4 - build/docker/old/ubuntu-artful/Dockerfile | 8 - build/docker/old/ubuntu-trusty/Dockerfile | 4 - build/docker/ubuntu-bionic/Dockerfile | 4 - build/docker/ubuntu-disco/Dockerfile | 4 - build/docker/ubuntu-xenial/Dockerfile | 8 - build/veralign.sh | 36 +- compiler/cpp/CMakeLists.txt | 1 - compiler/cpp/Makefile.am | 1 - compiler/cpp/compiler.vcxproj | 1 - compiler/cpp/compiler.vcxproj.filters | 3 - .../src/thrift/generate/t_csharp_generator.cc | 3261 ----------------- .../src/thrift/generate/t_netstd_generator.cc | 5 - compiler/cpp/src/thrift/parse/t_program.h | 2 +- compiler/cpp/src/thrift/thriftl.ll | 1 - compiler/cpp/tests/CMakeLists.txt | 1 - configure.ac | 31 - contrib/Rebus/README.md | 5 + contrib/Vagrantfile | 4 - contrib/thrift.spec | 1 - contrib/zeromq/README.md | 5 + debian/control | 15 +- debian/copyright | 62 +- debian/rules | 8 +- doc/install/debian.md | 4 +- doc/specs/idl.md | 2 +- lib/Makefile.am | 4 - lib/cpp/test/OneWayTest.thrift | 1 - lib/csharp/Makefile.am | 114 - lib/csharp/README.md | 32 - .../Properties/AssemblyInfo.cs | 60 - lib/csharp/ThriftMSBuildTask/ThriftBuild.cs | 246 -- .../ThriftMSBuildTask.csproj | 118 - lib/csharp/coding_standards.md | 6 - lib/csharp/src/Collections/TCollections.cs | 94 - lib/csharp/src/Collections/THashSet.cs | 160 - lib/csharp/src/Net35/ExtensionsNet35.cs | 31 - lib/csharp/src/Properties/AssemblyInfo.cs | 55 - lib/csharp/src/Protocol/TAbstractBase.cs | 29 - lib/csharp/src/Protocol/TBase.cs | 29 - lib/csharp/src/Protocol/TBase64Utils.cs | 100 - lib/csharp/src/Protocol/TBinaryProtocol.cs | 395 -- lib/csharp/src/Protocol/TCompactProtocol.cs | 849 ----- lib/csharp/src/Protocol/TField.cs | 62 - lib/csharp/src/Protocol/TJSONProtocol.cs | 1124 ------ lib/csharp/src/Protocol/TList.cs | 54 - lib/csharp/src/Protocol/TMap.cs | 62 - lib/csharp/src/Protocol/TMessage.cs | 62 - lib/csharp/src/Protocol/TMessageType.cs | 31 - .../src/Protocol/TMultiplexedProcessor.cs | 183 - .../src/Protocol/TMultiplexedProtocol.cs | 103 - lib/csharp/src/Protocol/TProtocol.cs | 142 - lib/csharp/src/Protocol/TProtocolDecorator.cs | 261 -- lib/csharp/src/Protocol/TProtocolException.cs | 67 - lib/csharp/src/Protocol/TProtocolFactory.cs | 33 - lib/csharp/src/Protocol/TProtocolUtil.cs | 108 - lib/csharp/src/Protocol/TSet.cs | 59 - lib/csharp/src/Protocol/TStruct.cs | 46 - lib/csharp/src/Protocol/TType.cs | 44 - lib/csharp/src/Server/TServer.cs | 155 - lib/csharp/src/Server/TServerEventHandler.cs | 53 - lib/csharp/src/Server/TSimpleServer.cs | 180 - lib/csharp/src/Server/TThreadPoolServer.cs | 295 -- lib/csharp/src/Server/TThreadedServer.cs | 282 -- lib/csharp/src/TApplicationException.cs | 146 - lib/csharp/src/TAsyncProcessor.cs | 38 - lib/csharp/src/TControllingHandler.cs | 29 - lib/csharp/src/TException.cs | 40 - lib/csharp/src/TProcessor.cs | 33 - lib/csharp/src/TProcessorFactory.cs | 30 - lib/csharp/src/TPrototypeProcessorFactory.cs | 55 - lib/csharp/src/TSingletonProcessorFactory.cs | 43 - lib/csharp/src/Thrift.45.csproj | 138 - lib/csharp/src/Thrift.csproj | 166 - lib/csharp/src/Thrift.sln | 47 - .../src/Transport/TBufferedTransport.cs | 194 - lib/csharp/src/Transport/TFramedTransport.cs | 205 -- lib/csharp/src/Transport/THttpClient.cs | 486 --- lib/csharp/src/Transport/THttpHandler.cs | 102 - .../src/Transport/THttpTaskAsyncHandler.cs | 97 - lib/csharp/src/Transport/TMemoryBuffer.cs | 117 - .../Transport/TNamedPipeClientTransport.cs | 111 - .../Transport/TNamedPipeServerTransport.cs | 296 -- lib/csharp/src/Transport/TServerSocket.cs | 176 - lib/csharp/src/Transport/TServerTransport.cs | 44 - .../src/Transport/TSilverlightSocket.cs | 393 -- lib/csharp/src/Transport/TSocket.cs | 245 -- .../src/Transport/TSocketVersionizer.cs | 78 - lib/csharp/src/Transport/TStreamTransport.cs | 128 - lib/csharp/src/Transport/TTLSServerSocket.cs | 223 -- lib/csharp/src/Transport/TTLSSocket.cs | 445 --- lib/csharp/src/Transport/TTransport.cs | 146 - .../src/Transport/TTransportException.cs | 69 - lib/csharp/src/Transport/TTransportFactory.cs | 42 - lib/csharp/src/thrift.snk | Bin 596 -> 0 bytes lib/csharp/test/JSON/JSONTest.csproj | 85 - lib/csharp/test/JSON/Program.cs | 95 - .../test/JSON/Properties/AssemblyInfo.cs | 55 - lib/csharp/test/JSON/app.config | 21 - .../Multiplex/Client/Multiplex.Test.Client.cs | 82 - .../Multiplex/Client/MultiplexClient.csproj | 148 - .../Client/Properties/AssemblyInfo.cs | 55 - lib/csharp/test/Multiplex/Makefile.am | 63 - .../test/Multiplex/Multiplex.Test.Common.cs | 40 - .../Multiplex/Server/Multiplex.Test.Server.cs | 107 - .../Multiplex/Server/MultiplexServer.csproj | 148 - .../Server/Properties/AssemblyInfo.cs | 55 - .../ThriftMVCTest/App_Start/FilterConfig.cs | 31 - .../ThriftMVCTest/App_Start/RouteConfig.cs | 39 - .../test/ThriftMVCTest/AsyncHttpHandler.cs | 32 - .../Controllers/HomeController.cs | 70 - lib/csharp/test/ThriftMVCTest/Global.asax | 19 - lib/csharp/test/ThriftMVCTest/Global.asax.cs | 34 - .../ThriftMVCTest/Properties/AssemblyInfo.cs | 53 - .../test/ThriftMVCTest/SecondServiceImpl.cs | 37 - .../test/ThriftMVCTest/SyncHttpHandler.cs | 32 - .../test/ThriftMVCTest/ThriftMVCTest.csproj | 200 - .../ThriftMVCTest/Views/Home/Index.cshtml | 25 - .../ThriftMVCTest/Views/Shared/_Layout.cshtml | 30 - .../test/ThriftMVCTest/Views/Web.config | 60 - .../ThriftMVCTest/Views/_ViewStart.cshtml | 22 - .../test/ThriftMVCTest/Web.Debug.config | 45 - .../test/ThriftMVCTest/Web.Release.config | 46 - lib/csharp/test/ThriftMVCTest/Web.config | 92 - lib/csharp/test/ThriftMVCTest/favicon.ico | Bin 32038 -> 0 bytes lib/csharp/test/ThriftMVCTest/packages.config | 25 - lib/netstd/Makefile.am | 2 +- test/Makefile.am | 5 - test/README.md | 2 +- test/ThriftTest.thrift | 1 - test/csharp/Makefile.am | 95 - test/csharp/Program.cs | 71 - test/csharp/Properties/AssemblyInfo.cs | 55 - test/csharp/TestClient.cs | 870 ----- test/csharp/TestServer.cs | 535 --- test/csharp/ThriftTest.csproj | 141 - test/csharp/ThriftTest.sln | 17 - test/features/known_failures_Linux.json | 12 +- test/known_failures_Linux.json | 186 +- test/netstd/Client/Program.cs | 15 +- test/netstd/Makefile.am | 4 +- test/netstd/Server/Program.cs | 15 +- test/tests.json | 45 +- tutorial/Makefile.am | 1 - tutorial/csharp/CsharpClient/CsharpClient.cs | 92 - .../csharp/CsharpClient/CsharpClient.csproj | 110 - .../CsharpClient/Properties/AssemblyInfo.cs | 55 - tutorial/csharp/CsharpServer/CsharpServer.cs | 129 - .../csharp/CsharpServer/CsharpServer.csproj | 111 - .../CsharpServer/Properties/AssemblyInfo.cs | 55 - tutorial/csharp/tutorial.sln | 39 - tutorial/netstd/Makefile.am | 2 +- 158 files changed, 269 insertions(+), 17872 deletions(-) delete mode 100644 compiler/cpp/src/thrift/generate/t_csharp_generator.cc delete mode 100644 lib/csharp/Makefile.am delete mode 100644 lib/csharp/README.md delete mode 100644 lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs delete mode 100644 lib/csharp/ThriftMSBuildTask/ThriftBuild.cs delete mode 100644 lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj delete mode 100644 lib/csharp/coding_standards.md delete mode 100644 lib/csharp/src/Collections/TCollections.cs delete mode 100644 lib/csharp/src/Collections/THashSet.cs delete mode 100644 lib/csharp/src/Net35/ExtensionsNet35.cs delete mode 100644 lib/csharp/src/Properties/AssemblyInfo.cs delete mode 100644 lib/csharp/src/Protocol/TAbstractBase.cs delete mode 100644 lib/csharp/src/Protocol/TBase.cs delete mode 100644 lib/csharp/src/Protocol/TBase64Utils.cs delete mode 100644 lib/csharp/src/Protocol/TBinaryProtocol.cs delete mode 100644 lib/csharp/src/Protocol/TCompactProtocol.cs delete mode 100644 lib/csharp/src/Protocol/TField.cs delete mode 100644 lib/csharp/src/Protocol/TJSONProtocol.cs delete mode 100644 lib/csharp/src/Protocol/TList.cs delete mode 100644 lib/csharp/src/Protocol/TMap.cs delete mode 100644 lib/csharp/src/Protocol/TMessage.cs delete mode 100644 lib/csharp/src/Protocol/TMessageType.cs delete mode 100644 lib/csharp/src/Protocol/TMultiplexedProcessor.cs delete mode 100644 lib/csharp/src/Protocol/TMultiplexedProtocol.cs delete mode 100644 lib/csharp/src/Protocol/TProtocol.cs delete mode 100644 lib/csharp/src/Protocol/TProtocolDecorator.cs delete mode 100644 lib/csharp/src/Protocol/TProtocolException.cs delete mode 100644 lib/csharp/src/Protocol/TProtocolFactory.cs delete mode 100644 lib/csharp/src/Protocol/TProtocolUtil.cs delete mode 100644 lib/csharp/src/Protocol/TSet.cs delete mode 100644 lib/csharp/src/Protocol/TStruct.cs delete mode 100644 lib/csharp/src/Protocol/TType.cs delete mode 100644 lib/csharp/src/Server/TServer.cs delete mode 100644 lib/csharp/src/Server/TServerEventHandler.cs delete mode 100644 lib/csharp/src/Server/TSimpleServer.cs delete mode 100644 lib/csharp/src/Server/TThreadPoolServer.cs delete mode 100644 lib/csharp/src/Server/TThreadedServer.cs delete mode 100644 lib/csharp/src/TApplicationException.cs delete mode 100644 lib/csharp/src/TAsyncProcessor.cs delete mode 100644 lib/csharp/src/TControllingHandler.cs delete mode 100644 lib/csharp/src/TException.cs delete mode 100644 lib/csharp/src/TProcessor.cs delete mode 100644 lib/csharp/src/TProcessorFactory.cs delete mode 100644 lib/csharp/src/TPrototypeProcessorFactory.cs delete mode 100644 lib/csharp/src/TSingletonProcessorFactory.cs delete mode 100644 lib/csharp/src/Thrift.45.csproj delete mode 100644 lib/csharp/src/Thrift.csproj delete mode 100644 lib/csharp/src/Thrift.sln delete mode 100644 lib/csharp/src/Transport/TBufferedTransport.cs delete mode 100644 lib/csharp/src/Transport/TFramedTransport.cs delete mode 100644 lib/csharp/src/Transport/THttpClient.cs delete mode 100644 lib/csharp/src/Transport/THttpHandler.cs delete mode 100644 lib/csharp/src/Transport/THttpTaskAsyncHandler.cs delete mode 100644 lib/csharp/src/Transport/TMemoryBuffer.cs delete mode 100644 lib/csharp/src/Transport/TNamedPipeClientTransport.cs delete mode 100644 lib/csharp/src/Transport/TNamedPipeServerTransport.cs delete mode 100644 lib/csharp/src/Transport/TServerSocket.cs delete mode 100644 lib/csharp/src/Transport/TServerTransport.cs delete mode 100644 lib/csharp/src/Transport/TSilverlightSocket.cs delete mode 100644 lib/csharp/src/Transport/TSocket.cs delete mode 100644 lib/csharp/src/Transport/TSocketVersionizer.cs delete mode 100644 lib/csharp/src/Transport/TStreamTransport.cs delete mode 100644 lib/csharp/src/Transport/TTLSServerSocket.cs delete mode 100644 lib/csharp/src/Transport/TTLSSocket.cs delete mode 100644 lib/csharp/src/Transport/TTransport.cs delete mode 100644 lib/csharp/src/Transport/TTransportException.cs delete mode 100644 lib/csharp/src/Transport/TTransportFactory.cs delete mode 100644 lib/csharp/src/thrift.snk delete mode 100644 lib/csharp/test/JSON/JSONTest.csproj delete mode 100644 lib/csharp/test/JSON/Program.cs delete mode 100644 lib/csharp/test/JSON/Properties/AssemblyInfo.cs delete mode 100644 lib/csharp/test/JSON/app.config delete mode 100644 lib/csharp/test/Multiplex/Client/Multiplex.Test.Client.cs delete mode 100644 lib/csharp/test/Multiplex/Client/MultiplexClient.csproj delete mode 100644 lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs delete mode 100644 lib/csharp/test/Multiplex/Makefile.am delete mode 100644 lib/csharp/test/Multiplex/Multiplex.Test.Common.cs delete mode 100644 lib/csharp/test/Multiplex/Server/Multiplex.Test.Server.cs delete mode 100644 lib/csharp/test/Multiplex/Server/MultiplexServer.csproj delete mode 100644 lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs delete mode 100644 lib/csharp/test/ThriftMVCTest/App_Start/FilterConfig.cs delete mode 100644 lib/csharp/test/ThriftMVCTest/App_Start/RouteConfig.cs delete mode 100644 lib/csharp/test/ThriftMVCTest/AsyncHttpHandler.cs delete mode 100644 lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs delete mode 100644 lib/csharp/test/ThriftMVCTest/Global.asax delete mode 100644 lib/csharp/test/ThriftMVCTest/Global.asax.cs delete mode 100644 lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs delete mode 100644 lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs delete mode 100644 lib/csharp/test/ThriftMVCTest/SyncHttpHandler.cs delete mode 100644 lib/csharp/test/ThriftMVCTest/ThriftMVCTest.csproj delete mode 100644 lib/csharp/test/ThriftMVCTest/Views/Home/Index.cshtml delete mode 100644 lib/csharp/test/ThriftMVCTest/Views/Shared/_Layout.cshtml delete mode 100644 lib/csharp/test/ThriftMVCTest/Views/Web.config delete mode 100644 lib/csharp/test/ThriftMVCTest/Views/_ViewStart.cshtml delete mode 100644 lib/csharp/test/ThriftMVCTest/Web.Debug.config delete mode 100644 lib/csharp/test/ThriftMVCTest/Web.Release.config delete mode 100644 lib/csharp/test/ThriftMVCTest/Web.config delete mode 100644 lib/csharp/test/ThriftMVCTest/favicon.ico delete mode 100644 lib/csharp/test/ThriftMVCTest/packages.config delete mode 100644 test/csharp/Makefile.am delete mode 100644 test/csharp/Program.cs delete mode 100644 test/csharp/Properties/AssemblyInfo.cs delete mode 100644 test/csharp/TestClient.cs delete mode 100644 test/csharp/TestServer.cs delete mode 100644 test/csharp/ThriftTest.csproj delete mode 100644 test/csharp/ThriftTest.sln delete mode 100644 tutorial/csharp/CsharpClient/CsharpClient.cs delete mode 100644 tutorial/csharp/CsharpClient/CsharpClient.csproj delete mode 100644 tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs delete mode 100644 tutorial/csharp/CsharpServer/CsharpServer.cs delete mode 100644 tutorial/csharp/CsharpServer/CsharpServer.csproj delete mode 100644 tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs delete mode 100644 tutorial/csharp/tutorial.sln diff --git a/.gitignore b/.gitignore index 4e2f4276d8b..58e2582a7ce 100644 --- a/.gitignore +++ b/.gitignore @@ -184,9 +184,6 @@ project.lock.json /lib/c_glib/test/testserialization /lib/c_glib/thriftc.pc /lib/c_glib/thrift_c_glib.pc -/lib/csharp/**/bin/ -/lib/csharp/**/obj/ -/lib/csharp/src/packages /lib/d/test/*.pem /lib/d/libthriftd*.a /lib/d/test/async_test @@ -234,8 +231,6 @@ project.lock.json /lib/js/dist /lib/js/doc /lib/js/test/build -/lib/netcore/**/bin -/lib/netcore/**/obj /lib/netstd/**/bin /lib/netstd/**/obj /lib/nodejs/coverage @@ -313,8 +308,6 @@ project.lock.json /test/cpp/StressTestNonBlocking /test/cpp/TestClient /test/cpp/TestServer -/test/csharp/obj -/test/csharp/bin /test/dart/**/.dart_tool /test/dart/**/.packages /test/dart/**/packages @@ -343,9 +336,6 @@ project.lock.json /test/php/php_ext_dir/ /test/py.twisted/_trial_temp/ /test/rb/Gemfile.lock -/test/netcore/**/bin -/test/netcore/**/obj -/test/netcore/Thrift /test/netstd/**/bin /test/netstd/**/obj /test/netstd/*.psess @@ -375,10 +365,6 @@ project.lock.json /tutorial/cpp/TutorialServer /tutorial/c_glib/tutorial_client /tutorial/c_glib/tutorial_server -/tutorial/csharp/CsharpServer/obj -/tutorial/csharp/CsharpServer/bin -/tutorial/csharp/CsharpClient/obj -/tutorial/csharp/CsharpClient/bin /tutorial/d/async_client /tutorial/d/client /tutorial/d/server @@ -403,9 +389,6 @@ project.lock.json /tutorial/hs/dist/ /tutorial/java/build/ /tutorial/js/build/ -/tutorial/netcore/**/bin -/tutorial/netcore/**/obj -/tutorial/netcore/Thrift /tutorial/netstd/**/bin /tutorial/netstd/**/obj /tutorial/netstd/Interfaces diff --git a/ApacheThrift.nuspec b/ApacheThrift.nuspec index 6dc3225f26d..61caf575398 100644 --- a/ApacheThrift.nuspec +++ b/ApacheThrift.nuspec @@ -15,11 +15,9 @@ Instructions for building a nuget package: - 1. Open Thrift.sln in lib\csharp\src and build the release version - of the "Thrift" and "Thrift.45" projects. - 2. Open Thrift.sln in lib\netstd and build the release version of + 1. Open Thrift.sln in lib\netstd and build the release version of the "Thrift" project. - 3. nuget setApiKey + 2. nuget setApiKey 3. nuget pack ApacheThrift.nuspec -Symbols -SymbolPackageFormat snupkg 4. nuget push ApacheThrift.0.14.0.nupkg -Source https://api.nuget.org/v3/index.json --> @@ -36,15 +34,12 @@ true Apache Thrift .NET Library - Contains runtime libraries from lib/csharp for net35 and net45 frameworks, - and from lib/netstd for netstandard2.0 framework development. + Contains runtime libraries from lib/netstd for netstandard2.0 framework development. Apache Thrift RPC - - \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index abd709bc466..10abcbb1ccb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,7 @@ - [THRIFT-4990](https://issues.apache.org/jira/browse/THRIFT-4990) - Upgrade to .NET Core 3.1 (LTS) - [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base +- [THRIFT-4982](https://issues.apache.org/jira/browse/THRIFT-4982) - Remove deprecated csharp bindings from the code base - [THRIFT-5006](https://issues.apache.org/jira/browse/THRIFT-5006) - Implement DEFAULT_MAX_LENGTH at TFramedTransport - [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - In Go library TDeserializer.Transport is now typed \*TMemoryBuffer instead of TTransport - [THRIFT-5072](https://issues.apache.org/jira/browse/THRIFT-5072) - Haskell generator fails to distinguish between multiple enum types with conflicting enum identifiers diff --git a/LANGUAGES.md b/LANGUAGES.md index afd7799fe9d..8db41727310 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -91,17 +91,6 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr C++ -C# -0.2.0
Deprecated
use netstd -Yes -.NET 3.5 / mono 3.2.8.0.NET 4.6.1 / mono 4.6.2.7 -YesYesYesYes -YesYes -YesYesYesYes -YesYesYes -C# (.NET) - - Common LISP 0.12.0 Yes @@ -146,17 +135,6 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Delphi -.NET Core -0.11.0
Deprecated
use netstd -Yes -2.1.42.2.101 -YesYesYesYes -YesYes -YesYesYesYes -Yes -.NET Core - - .NET Standard 0.13.0 Yes diff --git a/Makefile.am b/Makefile.am index 5832077fb26..f9d59ef4451 100755 --- a/Makefile.am +++ b/Makefile.am @@ -78,7 +78,7 @@ empty := space := $(empty) $(empty) comma := , -CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_CL@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_CSHARP@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_HASKELL@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_NETSTD@ @MAYBE_NODETS@ +CROSS_LANGS = @MAYBE_CPP@ @MAYBE_C_GLIB@ @MAYBE_CL@ @MAYBE_D@ @MAYBE_JAVA@ @MAYBE_PYTHON@ @MAYBE_PY3@ @MAYBE_RUBY@ @MAYBE_HASKELL@ @MAYBE_PERL@ @MAYBE_PHP@ @MAYBE_GO@ @MAYBE_NODEJS@ @MAYBE_DART@ @MAYBE_ERLANG@ @MAYBE_LUA@ @MAYBE_RS@ @MAYBE_NETSTD@ @MAYBE_NODETS@ CROSS_LANGS_COMMA_SEPARATED = $(subst $(space),$(comma),$(CROSS_LANGS)) if WITH_PY3 diff --git a/build/docker/old/debian-jessie/Dockerfile b/build/docker/old/debian-jessie/Dockerfile index 941b4bb4272..a49b2078c5d 100644 --- a/build/docker/old/debian-jessie/Dockerfile +++ b/build/docker/old/debian-jessie/Dockerfile @@ -124,11 +124,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ nodejs-legacy \ npm -RUN apt-get update && apt-get install -y --no-install-recommends \ -`# CSharp dependencies` \ - libmono-system-web2.0-cil \ - mono-devel - RUN apt-get update && apt-get install -y --no-install-recommends \ `# D dependencies` \ xdg-utils \ diff --git a/build/docker/old/debian-stretch/Dockerfile b/build/docker/old/debian-stretch/Dockerfile index 503eecd4240..48db7e19f2b 100644 --- a/build/docker/old/debian-stretch/Dockerfile +++ b/build/docker/old/debian-stretch/Dockerfile @@ -76,10 +76,6 @@ RUN apt-get install -y --no-install-recommends \ qtbase5-dev \ qtbase5-dev-tools -RUN apt-get install -y --no-install-recommends \ -`# csharp (mono) dependencies` \ - mono-devel - RUN apt-get install -y --no-install-recommends \ `# D dependencies` \ dmd-bin \ diff --git a/build/docker/old/ubuntu-artful/Dockerfile b/build/docker/old/ubuntu-artful/Dockerfile index abe84d11c61..813ef06d71f 100644 --- a/build/docker/old/ubuntu-artful/Dockerfile +++ b/build/docker/old/ubuntu-artful/Dockerfile @@ -39,10 +39,6 @@ RUN apt-get update && \ software-properties-common \ wget -# csharp (mono) - if we ever want a later version -# RUN echo "deb http://download.mono-project.com/repo/debian xenial main" | tee /etc/apt/sources.list.d/mono.list && \ -# apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A6A19B38D3D831EF - # Dart RUN curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > \ @@ -89,10 +85,6 @@ RUN apt-get install -y --no-install-recommends \ qtbase5-dev \ qtbase5-dev-tools -RUN apt-get install -y --no-install-recommends \ -`# csharp (mono) dependencies` \ - mono-devel - ENV SBCL_VERSION 1.4.5 RUN \ `# Common Lisp (sbcl) dependencies` \ diff --git a/build/docker/old/ubuntu-trusty/Dockerfile b/build/docker/old/ubuntu-trusty/Dockerfile index a8e4d3baa25..96c1540197e 100644 --- a/build/docker/old/ubuntu-trusty/Dockerfile +++ b/build/docker/old/ubuntu-trusty/Dockerfile @@ -74,10 +74,6 @@ RUN apt-get install -y --no-install-recommends \ qtbase5-dev \ qtbase5-dev-tools -RUN apt-get install -y --no-install-recommends \ -`# csharp (mono) dependencies` \ - mono-devel - RUN apt-get install -y --no-install-recommends \ `# D dependencies` \ dmd-bin=2.070.2-0 \ diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index fa8a2da3ad7..464af0bd1e3 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -89,10 +89,6 @@ RUN apt-get install -y --no-install-recommends \ qtbase5-dev \ qtbase5-dev-tools -RUN apt-get install -y --no-install-recommends \ -`# csharp (mono) dependencies` \ - mono-devel - ENV SBCL_VERSION 1.5.3 RUN \ `# Common Lisp (sbcl) dependencies` \ diff --git a/build/docker/ubuntu-disco/Dockerfile b/build/docker/ubuntu-disco/Dockerfile index fd9464b7731..247bcf15ab8 100644 --- a/build/docker/ubuntu-disco/Dockerfile +++ b/build/docker/ubuntu-disco/Dockerfile @@ -89,10 +89,6 @@ RUN apt-get install -y --no-install-recommends \ qtbase5-dev \ qtbase5-dev-tools -RUN apt-get install -y --no-install-recommends \ -`# csharp (mono) dependencies` \ - mono-devel - ENV SBCL_VERSION 1.5.3 RUN \ `# Common Lisp (sbcl) dependencies` \ diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index af91e1b3db0..fbbe1c2cbf7 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -37,10 +37,6 @@ RUN apt-get update && \ software-properties-common \ wget && \ -# csharp (mono) -# echo "deb http://download.mono-project.com/repo/debian xenial main" | tee /etc/apt/sources.list.d/mono.list && \ -# apt-key adv --keyserver keyserver.ubuntu.com --recv-keys A6A19B38D3D831EF && \ - # D apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EBCF975E5BA24D5E && \ wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list && \ @@ -94,10 +90,6 @@ RUN apt-get install -y --no-install-recommends \ qtbase5-dev \ qtbase5-dev-tools -RUN apt-get install -y --no-install-recommends \ -`# csharp (mono) dependencies` \ - mono-devel - ENV D_VERSION 2.075.1-0 RUN apt-get install -y --allow-unauthenticated --no-install-recommends \ `# D dependencies` \ diff --git a/build/veralign.sh b/build/veralign.sh index c15e0010d56..422da85072b 100755 --- a/build/veralign.sh +++ b/build/veralign.sh @@ -49,24 +49,16 @@ FILES[doap.rdf]=manual # These files can be updated automatically: FILES[ApacheThrift.nuspec]=simpleReplace -FILES[CMakeLists.txt]=simpleReplace -FILES[Thrift.podspec]=simpleReplace FILES[appveyor.yml]=simpleReplace FILES[bower.json]=jsonReplace -FILES[configure.ac]=configureReplace +FILES[CMakeLists.txt]=simpleReplace FILES[compiler/cpp/src/thrift/version.h]=simpleReplace +FILES[configure.ac]=configureReplace +FILES[contrib/Rebus/Properties/AssemblyInfo.cs]=simpleReplace FILES[contrib/thrift.spec]=simpleReplace +FILES[contrib/zeromq/csharp/AssemblyInfo.cs]=simpleReplace FILES[doc/specs/idl.md]=simpleReplace FILES[lib/as3/gradle.properties]=simpleReplace -FILES[lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs]=simpleReplace -FILES[lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj]=simpleReplace -FILES[lib/csharp/src/Properties/AssemblyInfo.cs]=simpleReplace -FILES[lib/csharp/src/Thrift.csproj]=simpleReplace -FILES[lib/csharp/test/Multiplex/Client/MultiplexClient.csproj]=simpleReplace -FILES[lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs]=simpleReplace -FILES[lib/csharp/test/Multiplex/Server/MultiplexServer.csproj]=simpleReplace -FILES[lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs]=simpleReplace -FILES[lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs]=simpleReplace FILES[lib/d/src/thrift/base.d]=simpleReplace FILES[lib/dart/pubspec.yaml]=pubspecReplace FILES[lib/delphi/src/Thrift.pas]=simpleReplace @@ -74,10 +66,12 @@ FILES[lib/erl/src/thrift.app.src]=simpleReplace FILES[lib/haxe/haxelib.json]=simpleReplace FILES[lib/hs/thrift.cabal]=simpleReplace FILES[lib/java/gradle.properties]=simpleReplace -FILES[lib/js/package.json]=jsonReplace FILES[lib/js/package-lock.json]=jsonReplace +FILES[lib/js/package.json]=jsonReplace FILES[lib/js/src/thrift.js]=simpleReplace FILES[lib/lua/Thrift.lua]=simpleReplace +FILES[lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs]=simpleReplace +FILES[lib/netstd/Thrift/Properties/AssemblyInfo.cs]=simpleReplace FILES[lib/netstd/Thrift/Properties/AssemblyInfo.cs]=simpleReplace FILES[lib/netstd/Thrift/Thrift.csproj]=simpleReplace FILES[lib/ocaml/_oasis]=simpleReplace @@ -88,25 +82,29 @@ FILES[lib/rs/Cargo.toml]=simpleReplace FILES[lib/st/package.xml]=simpleReplace FILES[lib/swift/Sources/Thrift.swift]=simpleReplace FILES[lib/swift/Tests/ThriftTests/ThriftTests.swift]=simpleReplace -FILES[lib/ts/package.json]=jsonReplace FILES[lib/ts/package-lock.json]=jsonReplace -FILES[package.json]=jsonReplace +FILES[lib/ts/package.json]=jsonReplace FILES[package-lock.json]=jsonReplace +FILES[package.json]=jsonReplace FILES[sonar-project.properties]=simpleReplace -FILES[test/csharp/Properties/AssemblyInfo.cs]=simpleReplace -FILES[test/csharp/ThriftTest.csproj]=simpleReplace FILES[test/dart/test_client/pubspec.yaml]=pubspecReplace FILES[test/erl/src/thrift_test.app.src]=simpleReplace -FILES[tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs]=simpleReplace -FILES[tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs]=simpleReplace +FILES[test/netstd/Client/Properties/AssemblyInfo.cs]=simpleReplace +FILES[test/netstd/Server/Properties/AssemblyInfo.cs]=simpleReplace +FILES[Thrift.podspec]=simpleReplace FILES[tutorial/dart/client/pubspec.yaml]=pubspecReplace FILES[tutorial/dart/console_client/pubspec.yaml]=pubspecReplace FILES[tutorial/dart/server/pubspec.yaml]=pubspecReplace FILES[tutorial/delphi/DelphiClient/DelphiClient.dproj]=simpleReplace FILES[tutorial/delphi/DelphiServer/DelphiServer.dproj]=simpleReplace FILES[tutorial/hs/ThriftTutorial.cabal]=simpleReplace +FILES[tutorial/netstd/Client/Properties/AssemblyInfo.cs]=simpleReplace +FILES[tutorial/netstd/Interfaces/Properties/AssemblyInfo.cs]=simpleReplace +FILES[tutorial/netstd/Server/Properties/AssemblyInfo.cs]=simpleReplace FILES[tutorial/ocaml/_oasis]=simpleReplace + + if [ ! -f "CHANGES.md" ]; then >&2 echo "error: run veralign.sh while in the thrift root directory" exit 1 diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt index 4dd316c31ff..7125cd72c42 100644 --- a/compiler/cpp/CMakeLists.txt +++ b/compiler/cpp/CMakeLists.txt @@ -76,7 +76,6 @@ THRIFT_ADD_COMPILER(as3 "Enable compiler for ActionScript 3" ON) THRIFT_ADD_COMPILER(c_glib "Enable compiler for C with Glib" ON) THRIFT_ADD_COMPILER(cl "Enable compiler for Common LISP" ON) THRIFT_ADD_COMPILER(cpp "Enable compiler for C++" ON) -THRIFT_ADD_COMPILER(csharp "Enable compiler for C#" ON) THRIFT_ADD_COMPILER(d "Enable compiler for D" ON) THRIFT_ADD_COMPILER(dart "Enable compiler for Dart" ON) THRIFT_ADD_COMPILER(delphi "Enable compiler for Delphi" ON) diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am index d0ac8749660..5c0949e7d16 100644 --- a/compiler/cpp/Makefile.am +++ b/compiler/cpp/Makefile.am @@ -73,7 +73,6 @@ thrift_SOURCES += src/thrift/generate/t_as3_generator.cc \ src/thrift/generate/t_c_glib_generator.cc \ src/thrift/generate/t_cl_generator.cc \ src/thrift/generate/t_cpp_generator.cc \ - src/thrift/generate/t_csharp_generator.cc \ src/thrift/generate/t_d_generator.cc \ src/thrift/generate/t_dart_generator.cc \ src/thrift/generate/t_delphi_generator.cc \ diff --git a/compiler/cpp/compiler.vcxproj b/compiler/cpp/compiler.vcxproj index 5d073e7381a..79045d7f9cf 100644 --- a/compiler/cpp/compiler.vcxproj +++ b/compiler/cpp/compiler.vcxproj @@ -57,7 +57,6 @@ - diff --git a/compiler/cpp/compiler.vcxproj.filters b/compiler/cpp/compiler.vcxproj.filters index 664a9d97570..75ab29234d7 100644 --- a/compiler/cpp/compiler.vcxproj.filters +++ b/compiler/cpp/compiler.vcxproj.filters @@ -101,9 +101,6 @@ generate - - generate - generate diff --git a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc b/compiler/cpp/src/thrift/generate/t_csharp_generator.cc deleted file mode 100644 index a6ece8083a8..00000000000 --- a/compiler/cpp/src/thrift/generate/t_csharp_generator.cc +++ /dev/null @@ -1,3261 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "thrift/platform.h" -#include "thrift/generate/t_oop_generator.h" - -using std::map; -using std::ostream; -using std::ostringstream; -using std::string; -using std::stringstream; -using std::vector; - -static const string endl = "\n"; // avoid ostream << std::endl flushes - -struct member_mapping_scope { - void* scope_member; - std::map mapping_table; -}; - -class t_csharp_generator : public t_oop_generator { -public: - t_csharp_generator(t_program* program, - const std::map& parsed_options, - const std::string& option_string) - : t_oop_generator(program) { - (void)option_string; - - std::map::const_iterator iter; - - async_ = false; - nullable_ = false; - hashcode_ = false; - union_ = false; - serialize_ = false; - wcf_ = false; - wcf_namespace_.clear(); - for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { - if( iter->first.compare("async") == 0) { - async_ = true; - } else if( iter->first.compare("nullable") == 0) { - nullable_ = true; - } else if( iter->first.compare("hashcode") == 0) { - hashcode_ = true; - } else if( iter->first.compare("union") == 0) { - union_ = true; - } else if( iter->first.compare("serial") == 0) { - serialize_ = true; - wcf_namespace_ = iter->second; // since there can be only one namespace - } else if( iter->first.compare("wcf") == 0) { - wcf_ = true; - wcf_namespace_ = iter->second; - } else { - throw "unknown option csharp:" + iter->first; - } - } - - pwarning(1, "The 'csharp' target is deprecated. Consider using 'netstd' instead.\n"); - - out_dir_base_ = "gen-csharp"; - } - void init_generator() override; - void close_generator() override; - - void generate_consts(std::vector consts) override; - - void generate_typedef(t_typedef* ttypedef) override; - void generate_enum(t_enum* tenum) override; - void generate_struct(t_struct* tstruct) override; - void generate_union(t_struct* tunion); - void generate_xception(t_struct* txception) override; - void generate_service(t_service* tservice) override; - void generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset); - void generate_csharp_property(ostream& out, - t_field* tfield, - bool isPublic, - bool includeIsset = true, - std::string fieldPrefix = ""); - bool print_const_value(std::ostream& out, - std::string name, - t_type* type, - t_const_value* value, - bool in_static, - bool defval = false, - bool needtype = false); - std::string render_const_value(std::ostream& out, - std::string name, - t_type* type, - t_const_value* value); - void print_const_constructor(std::ostream& out, std::vector consts); - void print_const_def_value(std::ostream& out, - std::string name, - t_type* type, - t_const_value* value); - - void generate_csharp_struct(t_struct* tstruct, bool is_exception); - void generate_csharp_union(t_struct* tunion); - void generate_csharp_struct_definition(std::ostream& out, - t_struct* tstruct, - bool is_xception = false, - bool in_class = false, - bool is_result = false); - void generate_csharp_union_definition(std::ostream& out, t_struct* tunion); - void generate_csharp_union_class(std::ostream& out, t_struct* tunion, t_field* tfield); - void generate_csharp_wcffault(std::ostream& out, t_struct* tstruct); - void generate_csharp_struct_reader(std::ostream& out, t_struct* tstruct); - void generate_csharp_struct_result_writer(std::ostream& out, t_struct* tstruct); - void generate_csharp_struct_writer(std::ostream& out, t_struct* tstruct); - void generate_csharp_struct_tostring(std::ostream& out, t_struct* tstruct); - void generate_csharp_struct_equals(std::ostream& out, t_struct* tstruct); - void generate_csharp_struct_hashcode(std::ostream& out, t_struct* tstruct); - void generate_csharp_union_reader(std::ostream& out, t_struct* tunion); - - void generate_function_helpers(t_function* tfunction); - void generate_service_interface(t_service* tservice); - void generate_separate_service_interfaces(t_service* tservice); - void generate_sync_service_interface(t_service* tservice); - void generate_async_service_interface(t_service* tservice); - void generate_combined_service_interface(t_service* tservice); - void generate_silverlight_async_methods(t_service* tservice); - void generate_service_helpers(t_service* tservice); - void generate_service_client(t_service* tservice); - void generate_service_server(t_service* tservice); - void generate_service_server_sync(t_service* tservice); - void generate_service_server_async(t_service* tservice); - void generate_process_function(t_service* tservice, t_function* function); - void generate_process_function_async(t_service* tservice, t_function* function); - - void generate_deserialize_field(std::ostream& out, - t_field* tfield, - std::string prefix = "", - bool is_propertyless = false); - void generate_deserialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); - void generate_deserialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); - void generate_deserialize_set_element(std::ostream& out, t_set* tset, std::string prefix = ""); - void generate_deserialize_map_element(std::ostream& out, t_map* tmap, std::string prefix = ""); - void generate_deserialize_list_element(std::ostream& out, t_list* list, std::string prefix = ""); - void generate_serialize_field(std::ostream& out, - t_field* tfield, - std::string prefix = "", - bool is_element = false, - bool is_propertyless = false); - void generate_serialize_struct(std::ostream& out, t_struct* tstruct, std::string prefix = ""); - void generate_serialize_container(std::ostream& out, t_type* ttype, std::string prefix = ""); - void generate_serialize_map_element(std::ostream& out, - t_map* tmap, - std::string iter, - std::string map); - void generate_serialize_set_element(std::ostream& out, t_set* tmap, std::string iter); - void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); - - void generate_csharp_doc(std::ostream& out, t_field* field); - void generate_csharp_doc(std::ostream& out, t_doc* tdoc); - void generate_csharp_doc(std::ostream& out, t_function* tdoc); - void generate_csharp_docstring_comment(std::ostream& out, string contents); - - void start_csharp_namespace(std::ostream& out); - void end_csharp_namespace(std::ostream& out); - - std::string csharp_type_usings(); - std::string csharp_thrift_usings(); - - std::string type_name(t_type* ttype, - bool in_countainer = false, - bool in_init = false, - bool in_param = false, - bool is_required = false); - std::string base_type_name(t_base_type* tbase, - bool in_container = false, - bool in_param = false, - bool is_required = false); - std::string declare_field(t_field* tfield, bool init = false, std::string prefix = ""); - std::string function_signature_async_begin(t_function* tfunction, std::string prefix = ""); - std::string function_signature_async_end(t_function* tfunction, std::string prefix = ""); - std::string function_signature_async(t_function* tfunction, std::string prefix = ""); - std::string function_signature(t_function* tfunction, std::string prefix = ""); - std::string argument_list(t_struct* tstruct); - std::string type_to_enum(t_type* ttype); - std::string prop_name(t_field* tfield, bool suppress_mapping = false); - std::string get_enum_class_name(t_type* type) override; - - bool field_has_default(t_field* tfield) { return tfield->get_value() != NULL; } - - bool field_is_required(t_field* tfield) { return tfield->get_req() == t_field::T_REQUIRED; } - - bool type_can_be_null(t_type* ttype) { - while (ttype->is_typedef()) { - ttype = ((t_typedef*)ttype)->get_type(); - } - - return ttype->is_container() || ttype->is_struct() || ttype->is_xception() - || ttype->is_string(); - } - -private: - std::string namespace_name_; - ofstream_with_content_based_conditional_update f_service_; - std::string namespace_dir_; - bool async_; - bool nullable_; - bool union_; - bool hashcode_; - bool serialize_; - bool wcf_; - std::string wcf_namespace_; - - std::map csharp_keywords; - std::vector member_mapping_scopes; - - void init_keywords(); - std::string normalize_name(std::string name); - std::string make_valid_csharp_identifier(std::string const& fromName); - void prepare_member_name_mapping(t_struct* tstruct); - void prepare_member_name_mapping(void* scope, - const vector& members, - const string& structname); - void cleanup_member_name_mapping(void* scope); - string get_mapped_member_name(string oldname); -}; - -void t_csharp_generator::init_generator() { - MKDIR(get_out_dir().c_str()); - namespace_name_ = program_->get_namespace("csharp"); - - string dir = namespace_name_; - string subdir = get_out_dir().c_str(); - string::size_type loc; - - while ((loc = dir.find(".")) != string::npos) { - subdir = subdir + "/" + dir.substr(0, loc); - MKDIR(subdir.c_str()); - dir = dir.substr(loc + 1); - } - if (dir.size() > 0) { - subdir = subdir + "/" + dir; - MKDIR(subdir.c_str()); - } - - namespace_dir_ = subdir; - init_keywords(); - - while( ! member_mapping_scopes.empty()) { - cleanup_member_name_mapping( member_mapping_scopes.back().scope_member); - } - - pverbose("C# options:\n"); - pverbose("- async ...... %s\n", (async_ ? "ON" : "off")); - pverbose("- nullable ... %s\n", (nullable_ ? "ON" : "off")); - pverbose("- union ...... %s\n", (union_ ? "ON" : "off")); - pverbose("- hashcode ... %s\n", (hashcode_ ? "ON" : "off")); - pverbose("- serialize .. %s\n", (serialize_ ? "ON" : "off")); - pverbose("- wcf ........ %s\n", (wcf_ ? "ON" : "off")); -} - -std::string t_csharp_generator::normalize_name(std::string name) { - string tmp(name); - std::transform(tmp.begin(), tmp.end(), tmp.begin(), static_cast(std::tolower)); - - // un-conflict keywords by prefixing with "@" - if (csharp_keywords.find(tmp) != csharp_keywords.end()) { - return "@" + name; - } - - // no changes necessary - return name; -} - -void t_csharp_generator::init_keywords() { - csharp_keywords.clear(); - - // C# keywords - csharp_keywords["abstract"] = 1; - csharp_keywords["as"] = 1; - csharp_keywords["base"] = 1; - csharp_keywords["bool"] = 1; - csharp_keywords["break"] = 1; - csharp_keywords["byte"] = 1; - csharp_keywords["case"] = 1; - csharp_keywords["catch"] = 1; - csharp_keywords["char"] = 1; - csharp_keywords["checked"] = 1; - csharp_keywords["class"] = 1; - csharp_keywords["const"] = 1; - csharp_keywords["continue"] = 1; - csharp_keywords["decimal"] = 1; - csharp_keywords["default"] = 1; - csharp_keywords["delegate"] = 1; - csharp_keywords["do"] = 1; - csharp_keywords["double"] = 1; - csharp_keywords["else"] = 1; - csharp_keywords["enum"] = 1; - csharp_keywords["event"] = 1; - csharp_keywords["explicit"] = 1; - csharp_keywords["extern"] = 1; - csharp_keywords["false"] = 1; - csharp_keywords["finally"] = 1; - csharp_keywords["fixed"] = 1; - csharp_keywords["float"] = 1; - csharp_keywords["for"] = 1; - csharp_keywords["foreach"] = 1; - csharp_keywords["goto"] = 1; - csharp_keywords["if"] = 1; - csharp_keywords["implicit"] = 1; - csharp_keywords["in"] = 1; - csharp_keywords["int"] = 1; - csharp_keywords["interface"] = 1; - csharp_keywords["internal"] = 1; - csharp_keywords["is"] = 1; - csharp_keywords["lock"] = 1; - csharp_keywords["long"] = 1; - csharp_keywords["namespace"] = 1; - csharp_keywords["new"] = 1; - csharp_keywords["null"] = 1; - csharp_keywords["object"] = 1; - csharp_keywords["operator"] = 1; - csharp_keywords["out"] = 1; - csharp_keywords["override"] = 1; - csharp_keywords["params"] = 1; - csharp_keywords["private"] = 1; - csharp_keywords["protected"] = 1; - csharp_keywords["public"] = 1; - csharp_keywords["readonly"] = 1; - csharp_keywords["ref"] = 1; - csharp_keywords["return"] = 1; - csharp_keywords["sbyte"] = 1; - csharp_keywords["sealed"] = 1; - csharp_keywords["short"] = 1; - csharp_keywords["sizeof"] = 1; - csharp_keywords["stackalloc"] = 1; - csharp_keywords["static"] = 1; - csharp_keywords["string"] = 1; - csharp_keywords["struct"] = 1; - csharp_keywords["switch"] = 1; - csharp_keywords["this"] = 1; - csharp_keywords["throw"] = 1; - csharp_keywords["true"] = 1; - csharp_keywords["try"] = 1; - csharp_keywords["typeof"] = 1; - csharp_keywords["uint"] = 1; - csharp_keywords["ulong"] = 1; - csharp_keywords["unchecked"] = 1; - csharp_keywords["unsafe"] = 1; - csharp_keywords["ushort"] = 1; - csharp_keywords["using"] = 1; - csharp_keywords["virtual"] = 1; - csharp_keywords["void"] = 1; - csharp_keywords["volatile"] = 1; - csharp_keywords["while"] = 1; - - // C# contextual keywords - csharp_keywords["add"] = 1; - csharp_keywords["alias"] = 1; - csharp_keywords["ascending"] = 1; - csharp_keywords["async"] = 1; - csharp_keywords["await"] = 1; - csharp_keywords["descending"] = 1; - csharp_keywords["dynamic"] = 1; - csharp_keywords["from"] = 1; - csharp_keywords["get"] = 1; - csharp_keywords["global"] = 1; - csharp_keywords["group"] = 1; - csharp_keywords["into"] = 1; - csharp_keywords["join"] = 1; - csharp_keywords["let"] = 1; - csharp_keywords["orderby"] = 1; - csharp_keywords["partial"] = 1; - csharp_keywords["remove"] = 1; - csharp_keywords["select"] = 1; - csharp_keywords["set"] = 1; - csharp_keywords["value"] = 1; - csharp_keywords["var"] = 1; - csharp_keywords["where"] = 1; - csharp_keywords["yield"] = 1; -} - -void t_csharp_generator::start_csharp_namespace(ostream& out) { - if (!namespace_name_.empty()) { - out << "namespace " << namespace_name_ << "\n"; - scope_up(out); - } -} - -void t_csharp_generator::end_csharp_namespace(ostream& out) { - if (!namespace_name_.empty()) { - scope_down(out); - } -} - -string t_csharp_generator::csharp_type_usings() { - return string() + "using System;\n" + "using System.Collections;\n" - + "using System.Collections.Generic;\n" + "using System.Text;\n" + "using System.IO;\n" - + ((async_) ? "using System.Threading.Tasks;\n" : "") + "using Thrift;\n" - + "using Thrift.Collections;\n" + ((serialize_ || wcf_) ? "#if !SILVERLIGHT\n" : "") - + ((serialize_ || wcf_) ? "using System.Xml.Serialization;\n" : "") - + ((serialize_ || wcf_) ? "#endif\n" : "") - + "using System.Runtime.Serialization;\n"; -} - -string t_csharp_generator::csharp_thrift_usings() { - return string() + "using Thrift.Protocol;\n" + "using Thrift.Transport;\n"; -} - -void t_csharp_generator::close_generator() { -} -void t_csharp_generator::generate_typedef(t_typedef* ttypedef) { - (void)ttypedef; -} - -void t_csharp_generator::generate_enum(t_enum* tenum) { - string f_enum_name = namespace_dir_ + "/" + (tenum->get_name()) + ".cs"; - ofstream_with_content_based_conditional_update f_enum; - f_enum.open(f_enum_name.c_str()); - - f_enum << autogen_comment() << endl; - - start_csharp_namespace(f_enum); - - generate_csharp_doc(f_enum, tenum); - - indent(f_enum) << "public enum " << tenum->get_name() << "\n"; - scope_up(f_enum); - - vector constants = tenum->get_constants(); - vector::iterator c_iter; - for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) { - generate_csharp_doc(f_enum, *c_iter); - - int value = (*c_iter)->get_value(); - indent(f_enum) << (*c_iter)->get_name() << " = " << value << "," << endl; - } - - scope_down(f_enum); - - end_csharp_namespace(f_enum); - - f_enum.close(); -} - -void t_csharp_generator::generate_consts(std::vector consts) { - if (consts.empty()) { - return; - } - string f_consts_name = namespace_dir_ + '/' + program_name_ + ".Constants.cs"; - ofstream_with_content_based_conditional_update f_consts; - f_consts.open(f_consts_name.c_str()); - - f_consts << autogen_comment() << csharp_type_usings() << endl; - - start_csharp_namespace(f_consts); - - indent(f_consts) << "public static class " << make_valid_csharp_identifier(program_name_) - << "Constants" << endl; - scope_up(f_consts); - - vector::iterator c_iter; - bool need_static_constructor = false; - for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { - generate_csharp_doc(f_consts, (*c_iter)); - if (print_const_value(f_consts, - (*c_iter)->get_name(), - (*c_iter)->get_type(), - (*c_iter)->get_value(), - false)) { - need_static_constructor = true; - } - } - - if (need_static_constructor) { - print_const_constructor(f_consts, consts); - } - - scope_down(f_consts); - end_csharp_namespace(f_consts); - f_consts.close(); -} - -void t_csharp_generator::print_const_def_value(std::ostream& out, - string name, - t_type* type, - t_const_value* value) { - if (type->is_struct() || type->is_xception()) { - const vector& fields = ((t_struct*)type)->get_members(); - vector::const_iterator f_iter; - const map& val = value->get_map(); - map::const_iterator v_iter; - prepare_member_name_mapping((t_struct*)type); - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - t_field* field = NULL; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if ((*f_iter)->get_name() == v_iter->first->get_string()) { - field = (*f_iter); - } - } - if (field == NULL) { - throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string(); - } - t_type* field_type = field->get_type(); - string val = render_const_value(out, name, field_type, v_iter->second); - indent(out) << name << "." << prop_name(field) << " = " << val << ";" << endl; - } - cleanup_member_name_mapping((t_struct*)type); - } else if (type->is_map()) { - t_type* ktype = ((t_map*)type)->get_key_type(); - t_type* vtype = ((t_map*)type)->get_val_type(); - const map& val = value->get_map(); - map::const_iterator v_iter; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - string key = render_const_value(out, name, ktype, v_iter->first); - string val = render_const_value(out, name, vtype, v_iter->second); - indent(out) << name << "[" << key << "]" - << " = " << val << ";" << endl; - } - } else if (type->is_list() || type->is_set()) { - t_type* etype; - if (type->is_list()) { - etype = ((t_list*)type)->get_elem_type(); - } else { - etype = ((t_set*)type)->get_elem_type(); - } - - const vector& val = value->get_list(); - vector::const_iterator v_iter; - for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { - string val = render_const_value(out, name, etype, *v_iter); - indent(out) << name << ".Add(" << val << ");" << endl; - } - } -} - -void t_csharp_generator::print_const_constructor(std::ostream& out, std::vector consts) { - indent(out) << "static " << make_valid_csharp_identifier(program_name_).c_str() << "Constants()" - << endl; - scope_up(out); - vector::iterator c_iter; - for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { - string name = (*c_iter)->get_name(); - t_type* type = (*c_iter)->get_type(); - t_const_value* value = (*c_iter)->get_value(); - - print_const_def_value(out, name, type, value); - } - scope_down(out); -} - -// it seems like all that methods that call this are using in_static to be the opposite of what it -// would imply -bool t_csharp_generator::print_const_value(std::ostream& out, - string name, - t_type* type, - t_const_value* value, - bool in_static, - bool defval, - bool needtype) { - indent(out); - bool need_static_construction = !in_static; - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } - - if (!defval || needtype) { - out << (in_static ? "" : type->is_base_type() ? "public const " : "public static ") - << type_name(type) << " "; - } - if (type->is_base_type()) { - string v2 = render_const_value(out, name, type, value); - out << name << " = " << v2 << ";" << endl; - need_static_construction = false; - } else if (type->is_enum()) { - out << name << " = " << type_name(type, false, true) << "." << value->get_identifier_name() - << ";" << endl; - need_static_construction = false; - } else if (type->is_struct() || type->is_xception()) { - out << name << " = new " << type_name(type) << "();" << endl; - } else if (type->is_map()) { - out << name << " = new " << type_name(type, true, true) << "();" << endl; - } else if (type->is_list() || type->is_set()) { - out << name << " = new " << type_name(type) << "();" << endl; - } - - if (defval && !type->is_base_type() && !type->is_enum()) { - print_const_def_value(out, name, type, value); - } - - return need_static_construction; -} - -std::string t_csharp_generator::render_const_value(ostream& out, - string name, - t_type* type, - t_const_value* value) { - (void)name; - std::ostringstream render; - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_STRING: - render << '"' << get_escaped_string(value) << '"'; - break; - case t_base_type::TYPE_BOOL: - render << ((value->get_integer() > 0) ? "true" : "false"); - break; - case t_base_type::TYPE_I8: - case t_base_type::TYPE_I16: - case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: - render << value->get_integer(); - break; - case t_base_type::TYPE_DOUBLE: - if (value->get_type() == t_const_value::CV_INTEGER) { - render << value->get_integer(); - } else { - render << value->get_double(); - } - break; - default: - throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase); - } - } else if (type->is_enum()) { - render << type->get_name() << "." << value->get_identifier_name(); - } else { - string t = tmp("tmp"); - print_const_value(out, t, type, value, true, true, true); - render << t; - } - - return render.str(); -} - -void t_csharp_generator::generate_struct(t_struct* tstruct) { - if (union_ && tstruct->is_union()) { - generate_csharp_union(tstruct); - } else { - generate_csharp_struct(tstruct, false); - } -} - -void t_csharp_generator::generate_xception(t_struct* txception) { - generate_csharp_struct(txception, true); -} - -void t_csharp_generator::generate_csharp_struct(t_struct* tstruct, bool is_exception) { - string f_struct_name = namespace_dir_ + "/" + (tstruct->get_name()) + ".cs"; - ofstream_with_content_based_conditional_update f_struct; - - f_struct.open(f_struct_name.c_str()); - - f_struct << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl; - - generate_csharp_struct_definition(f_struct, tstruct, is_exception); - - f_struct.close(); -} - -void t_csharp_generator::generate_csharp_struct_definition(ostream& out, - t_struct* tstruct, - bool is_exception, - bool in_class, - bool is_result) { - - if (!in_class) { - start_csharp_namespace(out); - } - - out << endl; - - generate_csharp_doc(out, tstruct); - prepare_member_name_mapping(tstruct); - - indent(out) << "#if !SILVERLIGHT" << endl; - indent(out) << "[Serializable]" << endl; - indent(out) << "#endif" << endl; - if ((serialize_ || wcf_) && !is_exception) { - indent(out) << "[DataContract(Namespace=\"" << wcf_namespace_ << "\")]" - << endl; // do not make exception classes directly WCF serializable, we provide a - // separate "fault" for that - } - bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); - - indent(out) << "public " << (is_final ? "sealed " : "") << "partial class " - << normalize_name(tstruct->get_name()) << " : "; - - if (is_exception) { - out << "TException, "; - } - out << "TBase"; - - out << endl; - - scope_up(out); - - const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; - - // make private members with public Properties - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - // if the field is requied, then we use auto-properties - if (!field_is_required((*m_iter)) && (!nullable_ || field_has_default((*m_iter)))) { - indent(out) << "private " << declare_field(*m_iter, false, "_") << endl; - } - } - out << endl; - - bool has_non_required_fields = false; - bool has_non_required_default_value_fields = false; - bool has_required_fields = false; - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - generate_csharp_doc(out, *m_iter); - generate_property(out, *m_iter, true, true); - bool is_required = field_is_required((*m_iter)); - bool has_default = field_has_default((*m_iter)); - if (is_required) { - has_required_fields = true; - } else { - if (has_default) { - has_non_required_default_value_fields = true; - } - has_non_required_fields = true; - } - } - - bool generate_isset = (nullable_ && has_non_required_default_value_fields) - || (!nullable_ && has_non_required_fields); - if (generate_isset) { - out << endl; - if (serialize_ || wcf_) { - out << indent() << "[XmlIgnore] // XmlSerializer" << endl << indent() - << "[DataMember(Order = 1)] // XmlObjectSerializer, DataContractJsonSerializer, etc." - << endl; - } - out << indent() << "public Isset __isset;" << endl << indent() << "#if !SILVERLIGHT" << endl - << indent() << "[Serializable]" << endl << indent() << "#endif" << endl; - if (serialize_ || wcf_) { - indent(out) << "[DataContract]" << endl; - } - indent(out) << "public struct Isset {" << endl; - indent_up(); - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - bool is_required = field_is_required((*m_iter)); - bool has_default = field_has_default((*m_iter)); - // if it is required, don't need Isset for that variable - // if it is not required, if it has a default value, we need to generate Isset - // if we are not nullable, then we generate Isset - if (!is_required && (!nullable_ || has_default)) { - if (serialize_ || wcf_) { - indent(out) << "[DataMember]" << endl; - } - indent(out) << "public bool " << normalize_name((*m_iter)->get_name()) << ";" << endl; - } - } - - indent_down(); - indent(out) << "}" << endl << endl; - - if (generate_isset && (serialize_ || wcf_)) { - indent(out) << "#region XmlSerializer support" << endl << endl; - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - bool is_required = field_is_required((*m_iter)); - bool has_default = field_has_default((*m_iter)); - // if it is required, don't need Isset for that variable - // if it is not required, if it has a default value, we need to generate Isset - // if we are not nullable, then we generate Isset - if (!is_required && (!nullable_ || has_default)) { - indent(out) << "public bool ShouldSerialize" << prop_name((*m_iter)) << "()" << endl; - indent(out) << "{" << endl; - indent_up(); - indent(out) << "return __isset." << normalize_name((*m_iter)->get_name()) << ";" << endl; - indent_down(); - indent(out) << "}" << endl << endl; - } - } - - indent(out) << "#endregion XmlSerializer support" << endl << endl; - } - } - - // We always want a default, no argument constructor for Reading - indent(out) << "public " << normalize_name(tstruct->get_name()) << "() {" << endl; - indent_up(); - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - t_type* t = (*m_iter)->get_type(); - while (t->is_typedef()) { - t = ((t_typedef*)t)->get_type(); - } - if ((*m_iter)->get_value() != NULL) { - if (field_is_required((*m_iter))) { - print_const_value(out, "this." + prop_name(*m_iter), t, (*m_iter)->get_value(), true, true); - } else { - print_const_value(out, - "this._" + (*m_iter)->get_name(), - t, - (*m_iter)->get_value(), - true, - true); - // Optionals with defaults are marked set - indent(out) << "this.__isset." << normalize_name((*m_iter)->get_name()) << " = true;" - << endl; - } - } - } - indent_down(); - indent(out) << "}" << endl << endl; - - if (has_required_fields) { - indent(out) << "public " << tstruct->get_name() << "("; - bool first = true; - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - if (field_is_required((*m_iter))) { - if (first) { - first = false; - } else { - out << ", "; - } - out << type_name((*m_iter)->get_type()) << " " << normalize_name((*m_iter)->get_name()); - } - } - out << ") : this() {" << endl; - indent_up(); - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - if (field_is_required((*m_iter))) { - indent(out) << "this." << prop_name((*m_iter)) << " = " << normalize_name((*m_iter)->get_name()) << ";" - << endl; - } - } - - indent_down(); - indent(out) << "}" << endl << endl; - } - - generate_csharp_struct_reader(out, tstruct); - if (is_result) { - generate_csharp_struct_result_writer(out, tstruct); - } else { - generate_csharp_struct_writer(out, tstruct); - } - if (hashcode_) { - generate_csharp_struct_equals(out, tstruct); - generate_csharp_struct_hashcode(out, tstruct); - } - generate_csharp_struct_tostring(out, tstruct); - scope_down(out); - out << endl; - - // generate a corresponding WCF fault to wrap the exception - if ((serialize_ || wcf_) && is_exception) { - generate_csharp_wcffault(out, tstruct); - } - - cleanup_member_name_mapping(tstruct); - if (!in_class) { - end_csharp_namespace(out); - } -} - -void t_csharp_generator::generate_csharp_wcffault(ostream& out, t_struct* tstruct) { - out << endl; - indent(out) << "#if !SILVERLIGHT" << endl; - indent(out) << "[Serializable]" << endl; - indent(out) << "#endif" << endl; - indent(out) << "[DataContract]" << endl; - bool is_final = (tstruct->annotations_.find("final") != tstruct->annotations_.end()); - - indent(out) << "public " << (is_final ? "sealed " : "") << "partial class " << tstruct->get_name() - << "Fault" << endl; - - scope_up(out); - - const vector& members = tstruct->get_members(); - vector::const_iterator m_iter; - - // make private members with public Properties - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - // if the field is requied, then we use auto-properties - if (!field_is_required((*m_iter)) && (!nullable_ || field_has_default((*m_iter)))) { - indent(out) << "private " << declare_field(*m_iter, false, "_") << endl; - } - } - out << endl; - - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { - generate_property(out, *m_iter, true, false); - } - - scope_down(out); - out << endl; -} - -void t_csharp_generator::generate_csharp_struct_reader(ostream& out, t_struct* tstruct) { - indent(out) << "public void Read (TProtocol iprot)" << endl; - scope_up(out); - - out << indent() << "iprot.IncrementRecursionDepth();" << endl; - out << indent() << "try" << endl; - scope_up(out); - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - // Required variables aren't in __isset, so we need tmp vars to check them - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (field_is_required((*f_iter))) { - indent(out) << "bool isset_" << (*f_iter)->get_name() << " = false;" << endl; - } - } - - indent(out) << "TField field;" << endl << indent() << "iprot.ReadStructBegin();" << endl; - - indent(out) << "while (true)" << endl; - scope_up(out); - - indent(out) << "field = iprot.ReadFieldBegin();" << endl; - - indent(out) << "if (field.Type == TType.Stop) { " << endl; - indent_up(); - indent(out) << "break;" << endl; - indent_down(); - indent(out) << "}" << endl; - - indent(out) << "switch (field.ID)" << endl; - - scope_up(out); - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - bool is_required = field_is_required((*f_iter)); - indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; - indent_up(); - indent(out) << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; - indent_up(); - - generate_deserialize_field(out, *f_iter); - if (is_required) { - indent(out) << "isset_" << (*f_iter)->get_name() << " = true;" << endl; - } - - indent_down(); - out << indent() << "} else { " << endl << indent() << " TProtocolUtil.Skip(iprot, field.Type);" - << endl << indent() << "}" << endl << indent() << "break;" << endl; - indent_down(); - } - - indent(out) << "default: " << endl; - indent_up(); - indent(out) << "TProtocolUtil.Skip(iprot, field.Type);" << endl; - indent(out) << "break;" << endl; - indent_down(); - - scope_down(out); - - indent(out) << "iprot.ReadFieldEnd();" << endl; - - scope_down(out); - - indent(out) << "iprot.ReadStructEnd();" << endl; - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (field_is_required((*f_iter))) { - indent(out) << "if (!isset_" << (*f_iter)->get_name() << ")" << endl; - indent_up(); - out << indent() - << "throw new TProtocolException(TProtocolException.INVALID_DATA, " - << "\"required field " << prop_name((*f_iter)) << " not set\");" - << endl; - indent_down(); - } - } - - scope_down(out); - out << indent() << "finally" << endl; - scope_up(out); - out << indent() << "iprot.DecrementRecursionDepth();" << endl; - scope_down(out); - - indent_down(); - - indent(out) << "}" << endl << endl; -} - -void t_csharp_generator::generate_csharp_struct_writer(ostream& out, t_struct* tstruct) { - out << indent() << "public void Write(TProtocol oprot) {" << endl; - indent_up(); - - out << indent() << "oprot.IncrementRecursionDepth();" << endl; - out << indent() << "try" << endl; - scope_up(out); - - string name = tstruct->get_name(); - const vector& fields = tstruct->get_sorted_members(); - vector::const_iterator f_iter; - - indent(out) << "TStruct struc = new TStruct(\"" << name << "\");" << endl; - indent(out) << "oprot.WriteStructBegin(struc);" << endl; - - if (fields.size() > 0) { - indent(out) << "TField field = new TField();" << endl; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - bool is_required = field_is_required((*f_iter)); - bool has_default = field_has_default((*f_iter)); - bool null_allowed = type_can_be_null((*f_iter)->get_type()); - - if (is_required) - { - if (null_allowed) { - indent(out) << "if (" << prop_name((*f_iter)) << " == null)" << endl; - indent_up(); - out << indent() - << "throw new TProtocolException(TProtocolException.INVALID_DATA, " - << "\"required field " << prop_name((*f_iter)) << " not set\");" - << endl; - indent_down(); - } - } - else - { - if (nullable_ && !has_default) { - indent(out) << "if (" << prop_name((*f_iter)) << " != null) {" << endl; - } - else if (null_allowed) { - out << indent() - << "if (" << prop_name((*f_iter)) << " != null && __isset." - << normalize_name((*f_iter)->get_name()) << ") {" - << endl; - } - else { - indent(out) << "if (__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl; - } - indent_up(); - } - indent(out) << "field.Name = \"" << (*f_iter)->get_name() << "\";" << endl; - indent(out) << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl; - indent(out) << "field.ID = " << (*f_iter)->get_key() << ";" << endl; - indent(out) << "oprot.WriteFieldBegin(field);" << endl; - - generate_serialize_field(out, *f_iter); - - indent(out) << "oprot.WriteFieldEnd();" << endl; - if (!is_required) { - indent_down(); - indent(out) << "}" << endl; - } - } - } - - indent(out) << "oprot.WriteFieldStop();" << endl; - indent(out) << "oprot.WriteStructEnd();" << endl; - - scope_down(out); - out << indent() << "finally" << endl; - scope_up(out); - out << indent() << "oprot.DecrementRecursionDepth();" << endl; - scope_down(out); - - indent_down(); - - indent(out) << "}" << endl << endl; -} - -void t_csharp_generator::generate_csharp_struct_result_writer(ostream& out, t_struct* tstruct) { - indent(out) << "public void Write(TProtocol oprot) {" << endl; - indent_up(); - - out << indent() << "oprot.IncrementRecursionDepth();" << endl; - out << indent() << "try" << endl; - scope_up(out); - - string name = tstruct->get_name(); - const vector& fields = tstruct->get_sorted_members(); - vector::const_iterator f_iter; - - indent(out) << "TStruct struc = new TStruct(\"" << name << "\");" << endl; - indent(out) << "oprot.WriteStructBegin(struc);" << endl; - - if (fields.size() > 0) { - indent(out) << "TField field = new TField();" << endl; - bool first = true; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (first) { - first = false; - out << endl << indent() << "if "; - } else { - out << " else if "; - } - - if (nullable_) { - out << "(this." << prop_name((*f_iter)) << " != null) {" << endl; - } else { - out << "(this.__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl; - } - indent_up(); - - bool null_allowed = !nullable_ && type_can_be_null((*f_iter)->get_type()); - if (null_allowed) { - indent(out) << "if (" << prop_name(*f_iter) << " != null) {" << endl; - indent_up(); - } - - indent(out) << "field.Name = \"" << prop_name(*f_iter) << "\";" << endl; - indent(out) << "field.Type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl; - indent(out) << "field.ID = " << (*f_iter)->get_key() << ";" << endl; - indent(out) << "oprot.WriteFieldBegin(field);" << endl; - - generate_serialize_field(out, *f_iter); - - indent(out) << "oprot.WriteFieldEnd();" << endl; - - if (null_allowed) { - indent_down(); - indent(out) << "}" << endl; - } - - indent_down(); - indent(out) << "}"; - } - } - - out << endl << indent() << "oprot.WriteFieldStop();" << endl << indent() - << "oprot.WriteStructEnd();" << endl; - - scope_down(out); - out << indent() << "finally" << endl; - scope_up(out); - out << indent() << "oprot.DecrementRecursionDepth();" << endl; - scope_down(out); - - indent_down(); - - indent(out) << "}" << endl << endl; -} - -void t_csharp_generator::generate_csharp_struct_tostring(ostream& out, t_struct* tstruct) { - indent(out) << "public override string ToString() {" << endl; - indent_up(); - - indent(out) << "StringBuilder __sb = new StringBuilder(\"" << tstruct->get_name() << "(\");" - << endl; - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - bool useFirstFlag = false; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (!field_is_required((*f_iter))) { - indent(out) << "bool __first = true;" << endl; - useFirstFlag = true; - } - break; - } - - bool had_required = false; // set to true after first required field has been processed - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - bool is_required = field_is_required((*f_iter)); - bool has_default = field_has_default((*f_iter)); - if (nullable_ && !has_default && !is_required) { - indent(out) << "if (" << prop_name((*f_iter)) << " != null) {" << endl; - indent_up(); - } else if (!is_required) { - bool null_allowed = type_can_be_null((*f_iter)->get_type()); - if (null_allowed) { - indent(out) << "if (" << prop_name((*f_iter)) << " != null && __isset." - << normalize_name((*f_iter)->get_name()) << ") {" << endl; - indent_up(); - } else { - indent(out) << "if (__isset." << normalize_name((*f_iter)->get_name()) << ") {" << endl; - indent_up(); - } - } - - if (useFirstFlag && (!had_required)) { - indent(out) << "if(!__first) { __sb.Append(\", \"); }" << endl; - if (!is_required) { - indent(out) << "__first = false;" << endl; - } - indent(out) << "__sb.Append(\"" << prop_name((*f_iter)) << ": \");" << endl; - } else { - indent(out) << "__sb.Append(\", " << prop_name((*f_iter)) << ": \");" << endl; - } - - t_type* ttype = (*f_iter)->get_type(); - if (ttype->is_xception() || ttype->is_struct()) { - indent(out) << "__sb.Append(" << prop_name((*f_iter)) - << "== null ? \"\" : " << prop_name((*f_iter)) << ".ToString());" << endl; - } else { - indent(out) << "__sb.Append(" << prop_name((*f_iter)) << ");" << endl; - } - - if (!is_required) { - indent_down(); - indent(out) << "}" << endl; - } else { - had_required = true; // now __first must be false, so we don't need to check it anymore - } - } - - indent(out) << "__sb.Append(\")\");" << endl; - indent(out) << "return __sb.ToString();" << endl; - - indent_down(); - indent(out) << "}" << endl << endl; -} - -void t_csharp_generator::generate_csharp_union(t_struct* tunion) { - string f_union_name = namespace_dir_ + "/" + (tunion->get_name()) + ".cs"; - ofstream_with_content_based_conditional_update f_union; - - f_union.open(f_union_name.c_str()); - - f_union << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl; - - generate_csharp_union_definition(f_union, tunion); - - f_union.close(); -} - -void t_csharp_generator::generate_csharp_union_definition(std::ostream& out, t_struct* tunion) { - // Let's define the class first - start_csharp_namespace(out); - - indent(out) << "public abstract partial class " << tunion->get_name() << " : TAbstractBase {" - << endl; - - indent_up(); - - indent(out) << "public abstract void Write(TProtocol protocol);" << endl; - indent(out) << "public readonly int Isset;" << endl; - indent(out) << "public abstract object Data { get; }" << endl; - - indent(out) << "protected " << tunion->get_name() << "(int isset) {" << endl; - indent_up(); - indent(out) << "Isset = isset;" << endl; - indent_down(); - indent(out) << "}" << endl << endl; - - indent(out) << "public class ___undefined : " << tunion->get_name() << " {" << endl; - indent_up(); - - indent(out) << "public override object Data { get { return null; } }" << endl; - - indent(out) << "public ___undefined() : base(0) {}" << endl << endl; - - indent(out) << "public override void Write(TProtocol protocol) {" << endl; - indent_up(); - indent(out) << "throw new TProtocolException( TProtocolException.INVALID_DATA, \"Cannot persist " - "an union type which is not set.\");" << endl; - indent_down(); - indent(out) << "}" << endl << endl; - - indent_down(); - indent(out) << "}" << endl << endl; - - const vector& fields = tunion->get_members(); - vector::const_iterator f_iter; - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - generate_csharp_union_class(out, tunion, (*f_iter)); - } - - generate_csharp_union_reader(out, tunion); - - indent_down(); - indent(out) << "}" << endl << endl; - - end_csharp_namespace(out); -} - -void t_csharp_generator::generate_csharp_union_class(std::ostream& out, - t_struct* tunion, - t_field* tfield) { - indent(out) << "public " << type_name(tfield->get_type()) << " As_" << tfield->get_name() << endl; - indent(out) << "{" << endl; - indent_up(); - indent(out) << "get" << endl; - indent(out) << "{" << endl; - indent_up(); - indent(out) << "return (" << tfield->get_key() << " == Isset) ? (" << type_name(tfield->get_type()) << ")Data : default(" << type_name(tfield->get_type()) << ");" << endl; - indent_down(); - indent(out) << "}" << endl; - indent_down(); - indent(out) << "}" << endl - << endl; - - - indent(out) << "public class " << tfield->get_name() << " : " << tunion->get_name() << " {" - << endl; - indent_up(); - indent(out) << "private " << type_name(tfield->get_type()) << " _data;" << endl; - indent(out) << "public override object Data { get { return _data; } }" << endl; - indent(out) << "public " << tfield->get_name() << "(" << type_name(tfield->get_type()) - << " data) : base("<< tfield->get_key() <<") {" << endl; - indent_up(); - indent(out) << "this._data = data;" << endl; - indent_down(); - indent(out) << "}" << endl; - indent(out) << "public override void Write(TProtocol oprot) {" << endl; - indent_up(); - - out << indent() << "oprot.IncrementRecursionDepth();" << endl; - out << indent() << "try" << endl; - scope_up(out); - - indent(out) << "TStruct struc = new TStruct(\"" << tunion->get_name() << "\");" << endl; - indent(out) << "oprot.WriteStructBegin(struc);" << endl; - - indent(out) << "TField field = new TField();" << endl; - indent(out) << "field.Name = \"" << tfield->get_name() << "\";" << endl; - indent(out) << "field.Type = " << type_to_enum(tfield->get_type()) << ";" << endl; - indent(out) << "field.ID = " << tfield->get_key() << ";" << endl; - indent(out) << "oprot.WriteFieldBegin(field);" << endl; - - generate_serialize_field(out, tfield, "_data", true, true); - - indent(out) << "oprot.WriteFieldEnd();" << endl; - indent(out) << "oprot.WriteFieldStop();" << endl; - indent(out) << "oprot.WriteStructEnd();" << endl; - indent_down(); - - scope_down(out); - out << indent() << "finally" << endl; - scope_up(out); - out << indent() << "oprot.DecrementRecursionDepth();" << endl; - scope_down(out); - - indent(out) << "}" << endl; - - indent_down(); - indent(out) << "}" << endl << endl; -} - -void t_csharp_generator::generate_csharp_struct_equals(ostream& out, t_struct* tstruct) { - indent(out) << "public override bool Equals(object that) {" << endl; - indent_up(); - - indent(out) << "var other = that as " << type_name(tstruct) << ";" << endl; - indent(out) << "if (other == null) return false;" << endl; - indent(out) << "if (ReferenceEquals(this, other)) return true;" << endl; - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - bool first = true; - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (first) { - first = false; - indent(out) << "return "; - indent_up(); - } else { - out << endl; - indent(out) << "&& "; - } - if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) { - out << "((__isset." << normalize_name((*f_iter)->get_name()) << " == other.__isset." - << normalize_name((*f_iter)->get_name()) << ") && ((!__isset." - << normalize_name((*f_iter)->get_name()) << ") || ("; - } - t_type* ttype = (*f_iter)->get_type(); - if (ttype->is_container() || ttype->is_binary()) { - out << "TCollections.Equals("; - } else { - out << "System.Object.Equals("; - } - out << prop_name((*f_iter)) << ", other." << prop_name((*f_iter)) << ")"; - if (!field_is_required((*f_iter)) && !(nullable_ && !field_has_default((*f_iter)))) { - out << ")))"; - } - } - if (first) { - indent(out) << "return true;" << endl; - } else { - out << ";" << endl; - indent_down(); - } - - indent_down(); - indent(out) << "}" << endl << endl; -} - -void t_csharp_generator::generate_csharp_struct_hashcode(ostream& out, t_struct* tstruct) { - indent(out) << "public override int GetHashCode() {" << endl; - indent_up(); - - indent(out) << "int hashcode = 0;" << endl; - indent(out) << "unchecked {" << endl; - indent_up(); - - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - t_type* ttype = (*f_iter)->get_type(); - indent(out) << "hashcode = (hashcode * 397) ^ "; - if (field_is_required((*f_iter))) { - out << "("; - } else if (nullable_) { - out << "(" << prop_name((*f_iter)) << " == null ? 0 : "; - } else { - out << "(!__isset." << normalize_name((*f_iter)->get_name()) << " ? 0 : "; - } - if (ttype->is_container()) { - out << "(TCollections.GetHashCode(" << prop_name((*f_iter)) << "))"; - } else { - out << "(" << prop_name((*f_iter)) << ".GetHashCode())"; - } - out << ");" << endl; - } - - indent_down(); - indent(out) << "}" << endl; - indent(out) << "return hashcode;" << endl; - - indent_down(); - indent(out) << "}" << endl << endl; -} - -void t_csharp_generator::generate_service(t_service* tservice) { - string f_service_name = namespace_dir_ + "/" + service_name_ + ".cs"; - f_service_.open(f_service_name.c_str()); - - f_service_ << autogen_comment() << csharp_type_usings() << csharp_thrift_usings() << endl; - - start_csharp_namespace(f_service_); - - indent(f_service_) << "public partial class " << normalize_name(service_name_) << " {" << endl; - indent_up(); - - generate_service_interface(tservice); - generate_service_client(tservice); - generate_service_server(tservice); - generate_service_helpers(tservice); - - indent_down(); - - indent(f_service_) << "}" << endl; - end_csharp_namespace(f_service_); - f_service_.close(); -} - -void t_csharp_generator::generate_service_interface(t_service* tservice) { - generate_separate_service_interfaces(tservice); -} - -void t_csharp_generator::generate_separate_service_interfaces(t_service* tservice) { - generate_sync_service_interface(tservice); - - if (async_) { - generate_async_service_interface(tservice); - } - - generate_combined_service_interface(tservice); -} - -void t_csharp_generator::generate_sync_service_interface(t_service* tservice) { - string extends = ""; - string extends_iface = ""; - if (tservice->get_extends() != NULL) { - extends = type_name(tservice->get_extends()); - extends_iface = " : " + extends + ".ISync"; - } - - generate_csharp_doc(f_service_, tservice); - - if (wcf_) { - indent(f_service_) << "[System.ServiceModel.ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; - } - indent(f_service_) << "public interface ISync" << extends_iface << " {" << endl; - - indent_up(); - vector functions = tservice->get_functions(); - vector::iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - generate_csharp_doc(f_service_, *f_iter); - - // if we're using WCF, add the corresponding attributes - if (wcf_) { - indent(f_service_) << "[System.ServiceModel.OperationContract]" << endl; - - const std::vector& xceptions = (*f_iter)->get_xceptions()->get_members(); - vector::const_iterator x_iter; - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - indent(f_service_) << "[System.ServiceModel.FaultContract(typeof(" - + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl; - } - } - - indent(f_service_) << function_signature(*f_iter) << ";" << endl; - } - indent_down(); - f_service_ << indent() << "}" << endl << endl; -} - -void t_csharp_generator::generate_async_service_interface(t_service* tservice) { - string extends = ""; - string extends_iface = ""; - if (tservice->get_extends() != NULL) { - extends = type_name(tservice->get_extends()); - extends_iface = " : " + extends + ".IAsync"; - } - - generate_csharp_doc(f_service_, tservice); - - if (wcf_) { - indent(f_service_) << "[System.ServiceModel.ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; - } - indent(f_service_) << "public interface IAsync" << extends_iface << " {" << endl; - - indent_up(); - vector functions = tservice->get_functions(); - vector::iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - generate_csharp_doc(f_service_, *f_iter); - - // if we're using WCF, add the corresponding attributes - if (wcf_) { - indent(f_service_) << "[System.ServiceModel.OperationContract]" << endl; - - const std::vector& xceptions = (*f_iter)->get_xceptions()->get_members(); - vector::const_iterator x_iter; - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - indent(f_service_) << "[System.ServiceModel.FaultContract(typeof(" - + type_name((*x_iter)->get_type(), false, false) + "Fault))]" << endl; - } - } - - indent(f_service_) << function_signature_async(*f_iter) << ";" << endl; - } - indent_down(); - f_service_ << indent() << "}" << endl << endl; -} - -void t_csharp_generator::generate_combined_service_interface(t_service* tservice) { - string extends_iface = " : ISync"; - - if (async_) { - extends_iface += ", IAsync"; - } - - generate_csharp_doc(f_service_, tservice); - - if (wcf_) { - indent(f_service_) << "[System.ServiceModel.ServiceContract(Namespace=\"" << wcf_namespace_ << "\")]" << endl; - } - - indent(f_service_) << "public interface Iface" << extends_iface << " {" << endl; - - indent_up(); - - // We need to generate extra old style async methods for silverlight. Since - // this isn't something you'd want to implement server-side, just put them into - // the main Iface interface. - generate_silverlight_async_methods(tservice); - - indent_down(); - - f_service_ << indent() << "}" << endl << endl; -} - -void t_csharp_generator::generate_silverlight_async_methods(t_service* tservice) { - vector functions = tservice->get_functions(); - vector::iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - generate_csharp_doc(f_service_, *f_iter); - - // For backwards compatibility, include the Begin_, End_ methods if we're generating - // with the async flag. I'm not sure this is necessary, so someone with more knowledge - // can maybe remove these checks if they know it's safe. - if (!async_) { - indent(f_service_) << "#if SILVERLIGHT" << endl; - } - - indent(f_service_) << function_signature_async_begin(*f_iter, "Begin_") << ";" << endl; - indent(f_service_) << function_signature_async_end(*f_iter, "End_") << ";" << endl; - - if (!async_) { - indent(f_service_) << "#endif" << endl; - } - } -} - -void t_csharp_generator::generate_service_helpers(t_service* tservice) { - vector functions = tservice->get_functions(); - vector::iterator f_iter; - - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - t_struct* ts = (*f_iter)->get_arglist(); - generate_csharp_struct_definition(f_service_, ts, false, true); - generate_function_helpers(*f_iter); - } -} - -void t_csharp_generator::generate_service_client(t_service* tservice) { - string extends = ""; - string extends_client = ""; - if (tservice->get_extends() != NULL) { - extends = type_name(tservice->get_extends()); - extends_client = extends + ".Client, "; - } else { - extends_client = "IDisposable, "; - } - - generate_csharp_doc(f_service_, tservice); - - indent(f_service_) << "public class Client : " << extends_client << "Iface {" << endl; - indent_up(); - indent(f_service_) << "public Client(TProtocol prot) : this(prot, prot)" << endl; - scope_up(f_service_); - scope_down(f_service_); - f_service_ << endl; - - indent(f_service_) << "public Client(TProtocol iprot, TProtocol oprot)"; - if (!extends.empty()) { - f_service_ << " : base(iprot, oprot)"; - } - f_service_ << endl; - - scope_up(f_service_); - if (extends.empty()) { - f_service_ << indent() << "iprot_ = iprot;" << endl << indent() << "oprot_ = oprot;" << endl; - } - scope_down(f_service_); - - f_service_ << endl; - - if (extends.empty()) { - f_service_ << indent() << "protected TProtocol iprot_;" << endl << indent() - << "protected TProtocol oprot_;" << endl << indent() << "protected int seqid_;" - << endl << endl; - - f_service_ << indent() << "public TProtocol InputProtocol" << endl; - scope_up(f_service_); - indent(f_service_) << "get { return iprot_; }" << endl; - scope_down(f_service_); - - f_service_ << indent() << "public TProtocol OutputProtocol" << endl; - scope_up(f_service_); - indent(f_service_) << "get { return oprot_; }" << endl; - scope_down(f_service_); - f_service_ << endl << endl; - - indent(f_service_) << "#region \" IDisposable Support \"" << endl; - indent(f_service_) << "private bool _IsDisposed;" << endl << endl; - indent(f_service_) << "// IDisposable" << endl; - indent(f_service_) << "public void Dispose()" << endl; - scope_up(f_service_); - indent(f_service_) << "Dispose(true);" << endl; - scope_down(f_service_); - indent(f_service_) << endl << endl; - indent(f_service_) << "protected virtual void Dispose(bool disposing)" << endl; - scope_up(f_service_); - indent(f_service_) << "if (!_IsDisposed)" << endl; - scope_up(f_service_); - indent(f_service_) << "if (disposing)" << endl; - scope_up(f_service_); - indent(f_service_) << "if (iprot_ != null)" << endl; - scope_up(f_service_); - indent(f_service_) << "((IDisposable)iprot_).Dispose();" << endl; - scope_down(f_service_); - indent(f_service_) << "if (oprot_ != null)" << endl; - scope_up(f_service_); - indent(f_service_) << "((IDisposable)oprot_).Dispose();" << endl; - scope_down(f_service_); - scope_down(f_service_); - scope_down(f_service_); - indent(f_service_) << "_IsDisposed = true;" << endl; - scope_down(f_service_); - indent(f_service_) << "#endregion" << endl; - f_service_ << endl << endl; - } - - vector functions = tservice->get_functions(); - vector::const_iterator f_iter; - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - string funname = (*f_iter)->get_name(); - - indent(f_service_) << endl; - - if (!async_) { - indent(f_service_) << "#if SILVERLIGHT" << endl; - indent(f_service_) << endl; - } - // Begin_ - indent(f_service_) << "public " << function_signature_async_begin(*f_iter, "Begin_") << endl; - scope_up(f_service_); - indent(f_service_) << "return " - << "send_" << funname << "(callback, state"; - - t_struct* arg_struct = (*f_iter)->get_arglist(); - prepare_member_name_mapping(arg_struct); - - const vector& fields = arg_struct->get_members(); - vector::const_iterator fld_iter; - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - f_service_ << ", "; - f_service_ << normalize_name((*fld_iter)->get_name()); - } - f_service_ << ");" << endl; - scope_down(f_service_); - f_service_ << endl; - - // End - indent(f_service_) << "public " << function_signature_async_end(*f_iter, "End_") << endl; - scope_up(f_service_); - indent(f_service_) << "oprot_.Transport.EndFlush(asyncResult);" << endl; - if (!(*f_iter)->is_oneway()) { - f_service_ << indent(); - if (!(*f_iter)->get_returntype()->is_void()) { - f_service_ << "return "; - } - f_service_ << "recv_" << funname << "();" << endl; - } - scope_down(f_service_); - f_service_ << endl; - - // async - bool first; - if (async_) { - indent(f_service_) << "public async " << function_signature_async(*f_iter, "") << endl; - scope_up(f_service_); - - if (!(*f_iter)->get_returntype()->is_void()) { - indent(f_service_) << type_name((*f_iter)->get_returntype()) << " retval;" << endl; - indent(f_service_) << "retval = "; - } else { - indent(f_service_); - } - f_service_ << "await Task.Run(() =>" << endl; - scope_up(f_service_); - indent(f_service_); - if (!(*f_iter)->get_returntype()->is_void()) { - f_service_ << "return "; - } - f_service_ << funname << "("; - first = true; - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - if (first) { - first = false; - } else { - f_service_ << ", "; - } - f_service_ << (*fld_iter)->get_name(); - } - f_service_ << ");" << endl; - indent_down(); - indent(f_service_) << "});" << endl; - if (!(*f_iter)->get_returntype()->is_void()) { - indent(f_service_) << "return retval;" << endl; - } - scope_down(f_service_); - f_service_ << endl; - } - - if (!async_) { - indent(f_service_) << "#endif" << endl << endl; - } - - generate_csharp_doc(f_service_, *f_iter); - indent(f_service_) << "public " << function_signature(*f_iter) << endl; - scope_up(f_service_); - - // silverlight invoke - if (!async_) { - indent(f_service_) << "#if SILVERLIGHT" << endl; - - indent(f_service_) << "var asyncResult = Begin_" << funname << "(null, null"; - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - f_service_ << ", " << normalize_name((*fld_iter)->get_name()); - } - f_service_ << ");" << endl; - - if (!(*f_iter)->is_oneway()) { - f_service_ << indent(); - if (!(*f_iter)->get_returntype()->is_void()) { - f_service_ << "return "; - } - f_service_ << "End_" << funname << "(asyncResult);" << endl; - } - f_service_ << endl; - - indent(f_service_) << "#else" << endl; - } - - // synchronous invoke - indent(f_service_) << "send_" << funname << "("; - - first = true; - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - if (first) { - first = false; - } else { - f_service_ << ", "; - } - f_service_ << normalize_name((*fld_iter)->get_name()); - } - f_service_ << ");" << endl; - - if (!(*f_iter)->is_oneway()) { - f_service_ << indent(); - if (!(*f_iter)->get_returntype()->is_void()) { - f_service_ << "return "; - } - f_service_ << "recv_" << funname << "();" << endl; - } - f_service_ << endl; - - if (!async_) { - indent(f_service_) << "#endif" << endl; - } - scope_down(f_service_); - - // Send - t_function send_function(g_type_void, - string("send_") + (*f_iter)->get_name(), - (*f_iter)->get_arglist()); - - string argsname = (*f_iter)->get_name() + "_args"; - - if (!async_) { - indent(f_service_) << "#if SILVERLIGHT" << endl; - } - - indent(f_service_) << "public " << function_signature_async_begin(&send_function) << endl; - scope_up(f_service_); - - f_service_ << indent() << "oprot_.WriteMessageBegin(new TMessage(\"" << funname << "\", " - << ((*f_iter)->is_oneway() ? "TMessageType.Oneway" : "TMessageType.Call") - << ", seqid_));" << endl << indent() << argsname << " args = new " << argsname - << "();" << endl; - - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - f_service_ << indent() << "args." << prop_name(*fld_iter) << " = " - << normalize_name((*fld_iter)->get_name()) << ";" << endl; - } - - f_service_ << indent() << "args.Write(oprot_);" << endl << indent() - << "oprot_.WriteMessageEnd();" << endl; - indent(f_service_) << "return oprot_.Transport.BeginFlush(callback, state);" << endl; - - scope_down(f_service_); - f_service_ << endl; - - if (!async_) { - indent(f_service_) << "#else" << endl; - f_service_ << endl; - } - - indent(f_service_) << "public " << function_signature(&send_function) << endl; - scope_up(f_service_); - - f_service_ << indent() << "oprot_.WriteMessageBegin(new TMessage(\"" << funname << "\", " - << ((*f_iter)->is_oneway() ? "TMessageType.Oneway" : "TMessageType.Call") - << ", seqid_));" << endl << indent() << argsname << " args = new " << argsname - << "();" << endl; - - for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) { - f_service_ << indent() << "args." << prop_name(*fld_iter) << " = " - << normalize_name((*fld_iter)->get_name()) << ";" << endl; - } - - f_service_ << indent() << "args.Write(oprot_);" << endl << indent() - << "oprot_.WriteMessageEnd();" << endl; - - indent(f_service_) << "oprot_.Transport.Flush();" << endl; - cleanup_member_name_mapping(arg_struct); - scope_down(f_service_); - - if (!async_) { - indent(f_service_) << "#endif" << endl; - } - - f_service_ << endl; - - if (!(*f_iter)->is_oneway()) { - string resultname = (*f_iter)->get_name() + "_result"; - - t_struct noargs(program_); - t_function recv_function((*f_iter)->get_returntype(), - string("recv_") + (*f_iter)->get_name(), - &noargs, - (*f_iter)->get_xceptions()); - indent(f_service_) << "public " << function_signature(&recv_function) << endl; - scope_up(f_service_); - - t_struct* xs = (*f_iter)->get_xceptions(); - prepare_member_name_mapping(xs, xs->get_members(), resultname); - - f_service_ << indent() << "TMessage msg = iprot_.ReadMessageBegin();" << endl << indent() - << "if (msg.Type == TMessageType.Exception) {" << endl; - indent_up(); - f_service_ << indent() << "TApplicationException x = TApplicationException.Read(iprot_);" - << endl << indent() << "iprot_.ReadMessageEnd();" << endl << indent() << "throw x;" - << endl; - indent_down(); - f_service_ << indent() << "}" << endl << indent() << resultname << " result = new " - << resultname << "();" << endl << indent() << "result.Read(iprot_);" << endl - << indent() << "iprot_.ReadMessageEnd();" << endl; - - if (!(*f_iter)->get_returntype()->is_void()) { - if (nullable_) { - if (type_can_be_null((*f_iter)->get_returntype())) { - f_service_ << indent() << "if (result.Success != null) {" << endl << indent() - << " return result.Success;" << endl << indent() << "}" << endl; - } else { - f_service_ << indent() << "if (result.Success.HasValue) {" << endl << indent() - << " return result.Success.Value;" << endl << indent() << "}" << endl; - } - } else { - f_service_ << indent() << "if (result.__isset.success) {" << endl << indent() - << " return result.Success;" << endl << indent() << "}" << endl; - } - } - - const std::vector& xceptions = xs->get_members(); - vector::const_iterator x_iter; - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - if (nullable_) { - f_service_ << indent() << "if (result." << prop_name(*x_iter) << " != null) {" << endl - << indent() << " throw result." << prop_name(*x_iter) << ";" << endl - << indent() << "}" << endl; - } else { - f_service_ << indent() << "if (result.__isset." << normalize_name((*x_iter)->get_name()) - << ") {" << endl << indent() << " throw result." << prop_name(*x_iter) << ";" - << endl << indent() << "}" << endl; - } - } - - if ((*f_iter)->get_returntype()->is_void()) { - indent(f_service_) << "return;" << endl; - } else { - f_service_ << indent() - << "throw new " - "TApplicationException(TApplicationException.ExceptionType.MissingResult, \"" - << (*f_iter)->get_name() << " failed: unknown result\");" << endl; - } - - cleanup_member_name_mapping((*f_iter)->get_xceptions()); - scope_down(f_service_); - f_service_ << endl; - } - } - - indent_down(); - indent(f_service_) << "}" << endl; -} - -void t_csharp_generator::generate_service_server(t_service* tservice) { - if (async_) { - generate_service_server_async(tservice); - generate_service_server_sync(tservice); - } - else { - generate_service_server_sync(tservice); - } -} - -void t_csharp_generator::generate_service_server_sync(t_service* tservice) { - vector functions = tservice->get_functions(); - vector::iterator f_iter; - - string extends = ""; - string extends_processor = ""; - if (tservice->get_extends() != NULL) { - extends = type_name(tservice->get_extends()); - extends_processor = extends + ".Processor, "; - } - - indent(f_service_) << "public class Processor : " << extends_processor << "TProcessor {" << endl; - indent_up(); - - indent(f_service_) << "public Processor(ISync iface)"; - - if (!extends.empty()) { - f_service_ << " : base(iface)"; - } - f_service_ << endl; - scope_up(f_service_); - f_service_ << indent() << "iface_ = iface;" << endl; - - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - f_service_ << indent() << "processMap_[\"" << (*f_iter)->get_name() - << "\"] = " << (*f_iter)->get_name() << "_Process;" << endl; - } - - scope_down(f_service_); - f_service_ << endl; - - if (extends.empty()) { - f_service_ - << indent() - << "protected delegate void ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);" - << endl; - } - - f_service_ << indent() << "private ISync iface_;" << endl; - - if (extends.empty()) { - f_service_ << indent() << "protected Dictionary processMap_ = new " - "Dictionary();" << endl; - } - - f_service_ << endl; - - if (extends.empty()) { - indent(f_service_) << "public bool Process(TProtocol iprot, TProtocol oprot)" << endl; - } - else { - indent(f_service_) << "public new bool Process(TProtocol iprot, TProtocol oprot)" << endl; - } - scope_up(f_service_); - - f_service_ << indent() << "try" << endl; - scope_up(f_service_); - - f_service_ << indent() << "TMessage msg = iprot.ReadMessageBegin();" << endl; - - f_service_ - << indent() << "ProcessFunction fn;" << endl << indent() - << "processMap_.TryGetValue(msg.Name, out fn);" << endl << indent() << "if (fn == null) {" - << endl << indent() << " TProtocolUtil.Skip(iprot, TType.Struct);" << endl << indent() - << " iprot.ReadMessageEnd();" << endl << indent() - << " TApplicationException x = new TApplicationException " - "(TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + " - "msg.Name + \"'\");" << endl << indent() - << " oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));" - << endl << indent() << " x.Write(oprot);" << endl << indent() << " oprot.WriteMessageEnd();" - << endl << indent() << " oprot.Transport.Flush();" << endl << indent() << " return true;" - << endl << indent() << "}" << endl << indent() << "fn(msg.SeqID, iprot, oprot);" << endl; - - scope_down(f_service_); - - f_service_ << indent() << "catch (IOException)" << endl; - scope_up(f_service_); - f_service_ << indent() << "return false;" << endl; - scope_down(f_service_); - - f_service_ << indent() << "return true;" << endl; - - scope_down(f_service_); - f_service_ << endl; - - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - generate_process_function(tservice, *f_iter); - } - - indent_down(); - indent(f_service_) << "}" << endl << endl; -} - -void t_csharp_generator::generate_service_server_async(t_service* tservice) { - vector functions = tservice->get_functions(); - vector::iterator f_iter; - - string extends = ""; - string extends_processor = ""; - if (tservice->get_extends() != NULL) { - extends = type_name(tservice->get_extends()); - extends_processor = extends + ".AsyncProcessor, "; - } - - indent(f_service_) << "public class AsyncProcessor : " << extends_processor << "TAsyncProcessor {" << endl; - indent_up(); - - indent(f_service_) << "public AsyncProcessor(IAsync iface)"; - if (!extends.empty()) { - f_service_ << " : base(iface)"; - } - f_service_ << endl; - scope_up(f_service_); - f_service_ << indent() << "iface_ = iface;" << endl; - - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - f_service_ << indent() << "processMap_[\"" << (*f_iter)->get_name() - << "\"] = " << (*f_iter)->get_name() << "_ProcessAsync;" << endl; - } - - scope_down(f_service_); - f_service_ << endl; - - if (extends.empty()) { - f_service_ - << indent() - << "protected delegate Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot);" - << endl; - } - - f_service_ << indent() << "private IAsync iface_;" << endl; - - if (extends.empty()) { - f_service_ << indent() << "protected Dictionary processMap_ = new " - "Dictionary();" << endl; - } - - f_service_ << endl; - - if (extends.empty()) { - indent(f_service_) << "public async Task ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl; - } - else { - indent(f_service_) << "public new async Task ProcessAsync(TProtocol iprot, TProtocol oprot)" << endl; - } - scope_up(f_service_); - - f_service_ << indent() << "try" << endl; - scope_up(f_service_); - - f_service_ << indent() << "TMessage msg = iprot.ReadMessageBegin();" << endl; - - f_service_ - << indent() << "ProcessFunction fn;" << endl << indent() - << "processMap_.TryGetValue(msg.Name, out fn);" << endl << indent() << "if (fn == null) {" - << endl << indent() << " TProtocolUtil.Skip(iprot, TType.Struct);" << endl << indent() - << " iprot.ReadMessageEnd();" << endl << indent() - << " TApplicationException x = new TApplicationException " - "(TApplicationException.ExceptionType.UnknownMethod, \"Invalid method name: '\" + " - "msg.Name + \"'\");" << endl << indent() - << " oprot.WriteMessageBegin(new TMessage(msg.Name, TMessageType.Exception, msg.SeqID));" - << endl << indent() << " x.Write(oprot);" << endl << indent() << " oprot.WriteMessageEnd();" - << endl << indent() << " oprot.Transport.Flush();" << endl << indent() << " return true;" - << endl << indent() << "}" << endl << indent() << "await fn(msg.SeqID, iprot, oprot);" << endl; - - scope_down(f_service_); - - f_service_ << indent() << "catch (IOException)" << endl; - scope_up(f_service_); - f_service_ << indent() << "return false;" << endl; - scope_down(f_service_); - - f_service_ << indent() << "return true;" << endl; - - scope_down(f_service_); - f_service_ << endl; - - for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { - generate_process_function_async(tservice, *f_iter); - } - - indent_down(); - indent(f_service_) << "}" << endl << endl; -} - -void t_csharp_generator::generate_function_helpers(t_function* tfunction) { - if (tfunction->is_oneway()) { - return; - } - - t_struct result(program_, tfunction->get_name() + "_result"); - t_field success(tfunction->get_returntype(), "success", 0); - if (!tfunction->get_returntype()->is_void()) { - result.append(&success); - } - - t_struct* xs = tfunction->get_xceptions(); - const vector& fields = xs->get_members(); - vector::const_iterator f_iter; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - result.append(*f_iter); - } - - generate_csharp_struct_definition(f_service_, &result, false, true, true); -} - -void t_csharp_generator::generate_process_function(t_service* tservice, t_function* tfunction) { - (void)tservice; - indent(f_service_) << "public void " << tfunction->get_name() - << "_Process(int seqid, TProtocol iprot, TProtocol oprot)" << endl; - scope_up(f_service_); - - string argsname = tfunction->get_name() + "_args"; - string resultname = tfunction->get_name() + "_result"; - - f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl - << indent() << "args.Read(iprot);" << endl - << indent() << "iprot.ReadMessageEnd();" << endl; - - t_struct* xs = tfunction->get_xceptions(); - const std::vector& xceptions = xs->get_members(); - vector::const_iterator x_iter; - - if (!tfunction->is_oneway()) { - f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl; - } - - f_service_ << indent() << "try" << endl - << indent() << "{" << endl; - indent_up(); - - if (xceptions.size() > 0) { - f_service_ << indent() << "try" << endl - << indent() << "{" << endl; - indent_up(); - } - - t_struct* arg_struct = tfunction->get_arglist(); - const std::vector& fields = arg_struct->get_members(); - vector::const_iterator f_iter; - - f_service_ << indent(); - if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { - f_service_ << "result.Success = "; - } - f_service_ << "iface_." << normalize_name(tfunction->get_name()) << "("; - bool first = true; - prepare_member_name_mapping(arg_struct); - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (first) { - first = false; - } else { - f_service_ << ", "; - } - f_service_ << "args." << prop_name(*f_iter); - if (nullable_ && !type_can_be_null((*f_iter)->get_type())) { - f_service_ << ".Value"; - } - } - cleanup_member_name_mapping(arg_struct); - f_service_ << ");" << endl; - - prepare_member_name_mapping(xs, xs->get_members(), resultname); - if (xceptions.size() > 0) { - indent_down(); - f_service_ << indent() << "}" << endl; - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - f_service_ << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " " - << (*x_iter)->get_name() << ")" << endl - << indent() << "{" << endl; - if (!tfunction->is_oneway()) { - indent_up(); - f_service_ << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name() - << ";" << endl; - indent_down(); - } - f_service_ << indent() << "}" << endl; - } - } - if (!tfunction->is_oneway()) { - f_service_ << indent() << "oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name() - << "\", TMessageType.Reply, seqid)); " << endl; - f_service_ << indent() << "result.Write(oprot);" << endl; - } - indent_down(); - - cleanup_member_name_mapping(xs); - - f_service_ << indent() << "}" << endl - << indent() << "catch (TTransportException)" << endl - << indent() << "{" << endl - << indent() << " throw;" << endl - << indent() << "}" << endl - << indent() << "catch (Exception ex)" << endl - << indent() << "{" << endl - << indent() << " Console.Error.WriteLine(\"Error occurred in processor:\");" << endl - << indent() << " Console.Error.WriteLine(ex.ToString());" << endl; - - if (tfunction->is_oneway()) { - f_service_ << indent() << "}" << endl; - } else { - f_service_ << indent() << " TApplicationException x = new TApplicationException" << indent() - << "(TApplicationException.ExceptionType.InternalError,\" Internal error.\");" - << endl - << indent() << " oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name() - << "\", TMessageType.Exception, seqid));" << endl - << indent() << " x.Write(oprot);" << endl - << indent() << "}" << endl; - f_service_ << indent() << "oprot.WriteMessageEnd();" << endl - << indent() << "oprot.Transport.Flush();" << endl; - } - - scope_down(f_service_); - - f_service_ << endl; -} - -void t_csharp_generator::generate_process_function_async(t_service* tservice, t_function* tfunction) { - (void)tservice; - indent(f_service_) << "public async Task " << tfunction->get_name() - << "_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot)" << endl; - scope_up(f_service_); - - string argsname = tfunction->get_name() + "_args"; - string resultname = tfunction->get_name() + "_result"; - - f_service_ << indent() << argsname << " args = new " << argsname << "();" << endl - << indent() << "args.Read(iprot);" << endl - << indent() << "iprot.ReadMessageEnd();" << endl; - - t_struct* xs = tfunction->get_xceptions(); - const std::vector& xceptions = xs->get_members(); - vector::const_iterator x_iter; - - if (!tfunction->is_oneway()) { - f_service_ << indent() << resultname << " result = new " << resultname << "();" << endl; - } - - f_service_ << indent() << "try" << endl - << indent() << "{" << endl; - indent_up(); - - if (xceptions.size() > 0) { - f_service_ << indent() << "try" << endl - << indent() << "{" << endl; - indent_up(); - } - - t_struct* arg_struct = tfunction->get_arglist(); - const std::vector& fields = arg_struct->get_members(); - vector::const_iterator f_iter; - - f_service_ << indent(); - if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) { - f_service_ << "result.Success = "; - } - f_service_ << "await iface_." << normalize_name(tfunction->get_name()) << "Async("; - bool first = true; - prepare_member_name_mapping(arg_struct); - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (first) { - first = false; - } - else { - f_service_ << ", "; - } - f_service_ << "args." << prop_name(*f_iter); - if (nullable_ && !type_can_be_null((*f_iter)->get_type())) { - f_service_ << ".Value"; - } - } - cleanup_member_name_mapping(arg_struct); - f_service_ << ");" << endl; - - prepare_member_name_mapping(xs, xs->get_members(), resultname); - if (xceptions.size() > 0) { - indent_down(); - f_service_ << indent() << "}" << endl; - for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) { - f_service_ << indent() << "catch (" << type_name((*x_iter)->get_type(), false, false) << " " - << (*x_iter)->get_name() << ")" << endl - << indent() << "{" << endl; - if (!tfunction->is_oneway()) { - indent_up(); - f_service_ << indent() << "result." << prop_name(*x_iter) << " = " << (*x_iter)->get_name() - << ";" << endl; - indent_down(); - } - f_service_ << indent() << "}" << endl; - } - } - if (!tfunction->is_oneway()) { - f_service_ << indent() << "oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name() - << "\", TMessageType.Reply, seqid)); " << endl; - f_service_ << indent() << "result.Write(oprot);" << endl; - } - indent_down(); - - cleanup_member_name_mapping(xs); - - f_service_ << indent() << "}" << endl - << indent() << "catch (TTransportException)" << endl - << indent() << "{" << endl - << indent() << " throw;" << endl - << indent() << "}" << endl - << indent() << "catch (Exception ex)" << endl - << indent() << "{" << endl - << indent() << " Console.Error.WriteLine(\"Error occurred in processor:\");" << endl - << indent() << " Console.Error.WriteLine(ex.ToString());" << endl; - - if (tfunction->is_oneway()) { - f_service_ << indent() << "}" << endl; - } - else { - f_service_ << indent() << " TApplicationException x = new TApplicationException" << indent() - << "(TApplicationException.ExceptionType.InternalError,\" Internal error.\");" - << endl - << indent() << " oprot.WriteMessageBegin(new TMessage(\"" << tfunction->get_name() - << "\", TMessageType.Exception, seqid));" << endl - << indent() << " x.Write(oprot);" << endl - << indent() << "}" << endl; - f_service_ << indent() << "oprot.WriteMessageEnd();" << endl - << indent() << "oprot.Transport.Flush();" << endl; - } - - scope_down(f_service_); - - f_service_ << endl; -} - -void t_csharp_generator::generate_csharp_union_reader(std::ostream& out, t_struct* tunion) { - // Thanks to THRIFT-1768, we don't need to check for required fields in the union - const vector& fields = tunion->get_members(); - vector::const_iterator f_iter; - - indent(out) << "public static " << tunion->get_name() << " Read(TProtocol iprot)" << endl; - scope_up(out); - - out << indent() << "iprot.IncrementRecursionDepth();" << endl; - out << indent() << "try" << endl; - scope_up(out); - - indent(out) << tunion->get_name() << " retval;" << endl; - indent(out) << "iprot.ReadStructBegin();" << endl; - indent(out) << "TField field = iprot.ReadFieldBegin();" << endl; - // we cannot have the first field be a stop -- we must have a single field defined - indent(out) << "if (field.Type == TType.Stop)" << endl; - scope_up(out); - indent(out) << "iprot.ReadFieldEnd();" << endl; - indent(out) << "retval = new ___undefined();" << endl; - scope_down(out); - indent(out) << "else" << endl; - scope_up(out); - indent(out) << "switch (field.ID)" << endl; - scope_up(out); - - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - indent(out) << "case " << (*f_iter)->get_key() << ":" << endl; - indent_up(); - indent(out) << "if (field.Type == " << type_to_enum((*f_iter)->get_type()) << ") {" << endl; - indent_up(); - - indent(out) << type_name((*f_iter)->get_type()) << " temp;" << endl; - generate_deserialize_field(out, (*f_iter), "temp", true); - indent(out) << "retval = new " << (*f_iter)->get_name() << "(temp);" << endl; - - indent_down(); - out << indent() << "} else { " << endl << indent() << " TProtocolUtil.Skip(iprot, field.Type);" - << endl << indent() << " retval = new ___undefined();" << endl << indent() << "}" << endl - << indent() << "break;" << endl; - indent_down(); - } - - indent(out) << "default: " << endl; - indent_up(); - indent(out) << "TProtocolUtil.Skip(iprot, field.Type);" << endl << indent() - << "retval = new ___undefined();" << endl; - indent(out) << "break;" << endl; - indent_down(); - - scope_down(out); - - indent(out) << "iprot.ReadFieldEnd();" << endl; - - indent(out) << "if (iprot.ReadFieldBegin().Type != TType.Stop)" << endl; - scope_up(out); - indent(out) << "throw new TProtocolException(TProtocolException.INVALID_DATA);" << endl; - scope_down(out); - - // end of else for TStop - scope_down(out); - indent(out) << "iprot.ReadStructEnd();" << endl; - indent(out) << "return retval;" << endl; - indent_down(); - - scope_down(out); - out << indent() << "finally" << endl; - scope_up(out); - out << indent() << "iprot.DecrementRecursionDepth();" << endl; - scope_down(out); - - indent(out) << "}" << endl << endl; -} - -void t_csharp_generator::generate_deserialize_field(ostream& out, - t_field* tfield, - string prefix, - bool is_propertyless) { - t_type* type = tfield->get_type(); - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } - - if (type->is_void()) { - throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " + prefix + tfield->get_name(); - } - - string name = prefix + (is_propertyless ? "" : prop_name(tfield)); - - if (type->is_struct() || type->is_xception()) { - generate_deserialize_struct(out, (t_struct*)type, name); - } else if (type->is_container()) { - generate_deserialize_container(out, type, name); - } else if (type->is_base_type() || type->is_enum()) { - indent(out) << name << " = "; - - if (type->is_enum()) { - out << "(" << type_name(type, false, true) << ")"; - } - - out << "iprot."; - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "compiler error: cannot serialize void field in a struct: " + name; - break; - case t_base_type::TYPE_STRING: - if (type->is_binary()) { - out << "ReadBinary();"; - } else { - out << "ReadString();"; - } - break; - case t_base_type::TYPE_BOOL: - out << "ReadBool();"; - break; - case t_base_type::TYPE_I8: - out << "ReadByte();"; - break; - case t_base_type::TYPE_I16: - out << "ReadI16();"; - break; - case t_base_type::TYPE_I32: - out << "ReadI32();"; - break; - case t_base_type::TYPE_I64: - out << "ReadI64();"; - break; - case t_base_type::TYPE_DOUBLE: - out << "ReadDouble();"; - break; - default: - throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase); - } - } else if (type->is_enum()) { - out << "ReadI32();"; - } - out << endl; - } else { - printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n", - tfield->get_name().c_str(), - type_name(type).c_str()); - } -} - -void t_csharp_generator::generate_deserialize_struct(ostream& out, - t_struct* tstruct, - string prefix) { - if (union_ && tstruct->is_union()) { - out << indent() << prefix << " = " << type_name(tstruct) << ".Read(iprot);" << endl; - } else { - out << indent() << prefix << " = new " << type_name(tstruct) << "();" << endl << indent() - << prefix << ".Read(iprot);" << endl; - } -} - -void t_csharp_generator::generate_deserialize_container(ostream& out, - t_type* ttype, - string prefix) { - scope_up(out); - - string obj; - - if (ttype->is_map()) { - obj = tmp("_map"); - } else if (ttype->is_set()) { - obj = tmp("_set"); - } else if (ttype->is_list()) { - obj = tmp("_list"); - } - - indent(out) << prefix << " = new " << type_name(ttype, false, true) << "();" << endl; - if (ttype->is_map()) { - out << indent() << "TMap " << obj << " = iprot.ReadMapBegin();" << endl; - } else if (ttype->is_set()) { - out << indent() << "TSet " << obj << " = iprot.ReadSetBegin();" << endl; - } else if (ttype->is_list()) { - out << indent() << "TList " << obj << " = iprot.ReadListBegin();" << endl; - } - - string i = tmp("_i"); - indent(out) << "for( int " << i << " = 0; " << i << " < " << obj << ".Count" - << "; " - << "++" << i << ")" << endl; - scope_up(out); - - if (ttype->is_map()) { - generate_deserialize_map_element(out, (t_map*)ttype, prefix); - } else if (ttype->is_set()) { - generate_deserialize_set_element(out, (t_set*)ttype, prefix); - } else if (ttype->is_list()) { - generate_deserialize_list_element(out, (t_list*)ttype, prefix); - } - - scope_down(out); - - if (ttype->is_map()) { - indent(out) << "iprot.ReadMapEnd();" << endl; - } else if (ttype->is_set()) { - indent(out) << "iprot.ReadSetEnd();" << endl; - } else if (ttype->is_list()) { - indent(out) << "iprot.ReadListEnd();" << endl; - } - - scope_down(out); -} - -void t_csharp_generator::generate_deserialize_map_element(ostream& out, - t_map* tmap, - string prefix) { - string key = tmp("_key"); - string val = tmp("_val"); - - t_field fkey(tmap->get_key_type(), key); - t_field fval(tmap->get_val_type(), val); - - indent(out) << declare_field(&fkey) << endl; - indent(out) << declare_field(&fval) << endl; - - generate_deserialize_field(out, &fkey); - generate_deserialize_field(out, &fval); - - indent(out) << prefix << "[" << key << "] = " << val << ";" << endl; -} - -void t_csharp_generator::generate_deserialize_set_element(ostream& out, - t_set* tset, - string prefix) { - string elem = tmp("_elem"); - t_field felem(tset->get_elem_type(), elem); - - indent(out) << declare_field(&felem) << endl; - - generate_deserialize_field(out, &felem); - - indent(out) << prefix << ".Add(" << elem << ");" << endl; -} - -void t_csharp_generator::generate_deserialize_list_element(ostream& out, - t_list* tlist, - string prefix) { - string elem = tmp("_elem"); - t_field felem(tlist->get_elem_type(), elem); - - indent(out) << declare_field(&felem) << endl; - - generate_deserialize_field(out, &felem); - - indent(out) << prefix << ".Add(" << elem << ");" << endl; -} - -void t_csharp_generator::generate_serialize_field(ostream& out, - t_field* tfield, - string prefix, - bool is_element, - bool is_propertyless) { - t_type* type = tfield->get_type(); - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } - - string name = prefix + (is_propertyless ? "" : prop_name(tfield)); - - if (type->is_void()) { - throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " + name; - } - - if (type->is_struct() || type->is_xception()) { - generate_serialize_struct(out, (t_struct*)type, name); - } else if (type->is_container()) { - generate_serialize_container(out, type, name); - } else if (type->is_base_type() || type->is_enum()) { - indent(out) << "oprot."; - - string nullable_name = nullable_ && !is_element && !field_is_required(tfield) ? name + ".Value" - : name; - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "compiler error: cannot serialize void field in a struct: " + name; - break; - case t_base_type::TYPE_STRING: - if (type->is_binary()) { - out << "WriteBinary("; - } else { - out << "WriteString("; - } - out << name << ");"; - break; - case t_base_type::TYPE_BOOL: - out << "WriteBool(" << nullable_name << ");"; - break; - case t_base_type::TYPE_I8: - out << "WriteByte(" << nullable_name << ");"; - break; - case t_base_type::TYPE_I16: - out << "WriteI16(" << nullable_name << ");"; - break; - case t_base_type::TYPE_I32: - out << "WriteI32(" << nullable_name << ");"; - break; - case t_base_type::TYPE_I64: - out << "WriteI64(" << nullable_name << ");"; - break; - case t_base_type::TYPE_DOUBLE: - out << "WriteDouble(" << nullable_name << ");"; - break; - default: - throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase); - } - } else if (type->is_enum()) { - out << "WriteI32((int)" << nullable_name << ");"; - } - out << endl; - } else { - printf("DO NOT KNOW HOW TO SERIALIZE '%s%s' TYPE '%s'\n", - prefix.c_str(), - tfield->get_name().c_str(), - type_name(type).c_str()); - } -} - -void t_csharp_generator::generate_serialize_struct(ostream& out, - t_struct* tstruct, - string prefix) { - (void)tstruct; - out << indent() << prefix << ".Write(oprot);" << endl; -} - -void t_csharp_generator::generate_serialize_container(ostream& out, t_type* ttype, string prefix) { - scope_up(out); - - if (ttype->is_map()) { - indent(out) << "oprot.WriteMapBegin(new TMap(" << type_to_enum(((t_map*)ttype)->get_key_type()) - << ", " << type_to_enum(((t_map*)ttype)->get_val_type()) << ", " << prefix - << ".Count));" << endl; - } else if (ttype->is_set()) { - indent(out) << "oprot.WriteSetBegin(new TSet(" << type_to_enum(((t_set*)ttype)->get_elem_type()) - << ", " << prefix << ".Count));" << endl; - } else if (ttype->is_list()) { - indent(out) << "oprot.WriteListBegin(new TList(" - << type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " << prefix << ".Count));" - << endl; - } - - string iter = tmp("_iter"); - if (ttype->is_map()) { - indent(out) << "foreach (" << type_name(((t_map*)ttype)->get_key_type()) << " " << iter - << " in " << prefix << ".Keys)"; - } else if (ttype->is_set()) { - indent(out) << "foreach (" << type_name(((t_set*)ttype)->get_elem_type()) << " " << iter - << " in " << prefix << ")"; - } else if (ttype->is_list()) { - indent(out) << "foreach (" << type_name(((t_list*)ttype)->get_elem_type()) << " " << iter - << " in " << prefix << ")"; - } - - out << endl; - scope_up(out); - - if (ttype->is_map()) { - generate_serialize_map_element(out, (t_map*)ttype, iter, prefix); - } else if (ttype->is_set()) { - generate_serialize_set_element(out, (t_set*)ttype, iter); - } else if (ttype->is_list()) { - generate_serialize_list_element(out, (t_list*)ttype, iter); - } - - scope_down(out); - - if (ttype->is_map()) { - indent(out) << "oprot.WriteMapEnd();" << endl; - } else if (ttype->is_set()) { - indent(out) << "oprot.WriteSetEnd();" << endl; - } else if (ttype->is_list()) { - indent(out) << "oprot.WriteListEnd();" << endl; - } - - scope_down(out); -} - -void t_csharp_generator::generate_serialize_map_element(ostream& out, - t_map* tmap, - string iter, - string map) { - t_field kfield(tmap->get_key_type(), iter); - generate_serialize_field(out, &kfield, "", true); - t_field vfield(tmap->get_val_type(), map + "[" + iter + "]"); - generate_serialize_field(out, &vfield, "", true); -} - -void t_csharp_generator::generate_serialize_set_element(ostream& out, t_set* tset, string iter) { - t_field efield(tset->get_elem_type(), iter); - generate_serialize_field(out, &efield, "", true); -} - -void t_csharp_generator::generate_serialize_list_element(ostream& out, - t_list* tlist, - string iter) { - t_field efield(tlist->get_elem_type(), iter); - generate_serialize_field(out, &efield, "", true); -} - -void t_csharp_generator::generate_property(ostream& out, - t_field* tfield, - bool isPublic, - bool generateIsset) { - generate_csharp_property(out, tfield, isPublic, generateIsset, "_"); -} -void t_csharp_generator::generate_csharp_property(ostream& out, - t_field* tfield, - bool isPublic, - bool generateIsset, - std::string fieldPrefix) { - if ((serialize_ || wcf_) && isPublic) { - indent(out) << "[DataMember(Order = 0)]" << endl; - } - bool has_default = field_has_default(tfield); - bool is_required = field_is_required(tfield); - if ((nullable_ && !has_default) || (is_required)) { - indent(out) << (isPublic ? "public " : "private ") - << type_name(tfield->get_type(), false, false, true, is_required) << " " - << prop_name(tfield) << " { get; set; }" << endl; - } else { - indent(out) << (isPublic ? "public " : "private ") - << type_name(tfield->get_type(), false, false, true) << " " << prop_name(tfield) - << endl; - scope_up(out); - indent(out) << "get" << endl; - scope_up(out); - bool use_nullable = false; - if (nullable_) { - t_type* ttype = tfield->get_type(); - while (ttype->is_typedef()) { - ttype = ((t_typedef*)ttype)->get_type(); - } - if (ttype->is_base_type()) { - use_nullable = ((t_base_type*)ttype)->get_base() != t_base_type::TYPE_STRING; - } else if (ttype->is_enum()) { - use_nullable = true; - } - } - indent(out) << "return " << fieldPrefix + tfield->get_name() << ";" << endl; - scope_down(out); - indent(out) << "set" << endl; - scope_up(out); - if (use_nullable) { - if (generateIsset) { - indent(out) << "__isset." << normalize_name(tfield->get_name()) << " = value.HasValue;" - << endl; - } - indent(out) << "if (value.HasValue) this." << fieldPrefix + tfield->get_name() - << " = value.Value;" << endl; - } else { - if (generateIsset) { - indent(out) << "__isset." << normalize_name(tfield->get_name()) << " = true;" << endl; - } - indent(out) << "this." << fieldPrefix + tfield->get_name() << " = value;" << endl; - } - scope_down(out); - scope_down(out); - } - out << endl; -} - -std::string t_csharp_generator::make_valid_csharp_identifier(std::string const& fromName) { - std::string str = fromName; - if (str.empty()) { - return str; - } - - // tests rely on this - assert(('A' < 'Z') && ('a' < 'z') && ('0' < '9')); - - // if the first letter is a number, we add an additional underscore in front of it - char c = str.at(0); - if (('0' <= c) && (c <= '9')) { - str = "_" + str; - } - - // following chars: letter, number or underscore - for (size_t i = 0; i < str.size(); ++i) { - c = str.at(i); - if ((('A' > c) || (c > 'Z')) && (('a' > c) || (c > 'z')) && (('0' > c) || (c > '9')) - && ('_' != c)) { - str.replace(i, 1, "_"); - } - } - - return str; -} - -void t_csharp_generator::cleanup_member_name_mapping(void* scope) { - if( member_mapping_scopes.empty()) { - throw "internal error: cleanup_member_name_mapping() no scope active"; - } - - member_mapping_scope& active = member_mapping_scopes.back(); - if (active.scope_member != scope) { - throw "internal error: cleanup_member_name_mapping() called for wrong struct"; - } - - member_mapping_scopes.pop_back(); -} - -string t_csharp_generator::get_mapped_member_name(string name) { - if( ! member_mapping_scopes.empty()) { - member_mapping_scope& active = member_mapping_scopes.back(); - map::iterator iter = active.mapping_table.find(name); - if (active.mapping_table.end() != iter) { - return iter->second; - } - } - - pverbose("no mapping for member %s\n", name.c_str()); - return name; -} - -void t_csharp_generator::prepare_member_name_mapping(t_struct* tstruct) { - prepare_member_name_mapping(tstruct, tstruct->get_members(), tstruct->get_name()); -} - -void t_csharp_generator::prepare_member_name_mapping(void* scope, - const vector& members, - const string& structname) { - // begin new scope - member_mapping_scope dummy; - dummy.scope_member = 0; - member_mapping_scopes.push_back(dummy); - member_mapping_scope& active = member_mapping_scopes.back(); - active.scope_member = scope; - - // current C# generator policy: - // - prop names are always rendered with an Uppercase first letter - // - struct names are used as given - std::set used_member_names; - vector::const_iterator iter; - - // prevent name conflicts with struct (CS0542 error) - used_member_names.insert(structname); - - // prevent name conflicts with known methods (THRIFT-2942) - used_member_names.insert("Read"); - used_member_names.insert("Write"); - - for (iter = members.begin(); iter != members.end(); ++iter) { - string oldname = (*iter)->get_name(); - string newname = prop_name(*iter, true); - while (true) { - - // new name conflicts with another member - if (used_member_names.find(newname) != used_member_names.end()) { - pverbose("struct %s: member %s conflicts with another member\n", - structname.c_str(), - newname.c_str()); - newname += '_'; - continue; - } - - // add always, this helps us to detect edge cases like - // different spellings ("foo" and "Foo") within the same struct - pverbose("struct %s: member mapping %s => %s\n", - structname.c_str(), - oldname.c_str(), - newname.c_str()); - active.mapping_table[oldname] = newname; - used_member_names.insert(newname); - break; - } - } -} - -std::string t_csharp_generator::prop_name(t_field* tfield, bool suppress_mapping) { - string name(tfield->get_name()); - if (suppress_mapping) { - name[0] = toupper(name[0]); - } else { - name = get_mapped_member_name(name); - } - return name; -} - -string t_csharp_generator::type_name(t_type* ttype, - bool in_container, - bool in_init, - bool in_param, - bool is_required) { - (void)in_init; - while (ttype->is_typedef()) { - ttype = ((t_typedef*)ttype)->get_type(); - } - - if (ttype->is_base_type()) { - return base_type_name((t_base_type*)ttype, in_container, in_param, is_required); - } else if (ttype->is_map()) { - t_map* tmap = (t_map*)ttype; - return "Dictionary<" + type_name(tmap->get_key_type(), true) + ", " - + type_name(tmap->get_val_type(), true) + ">"; - } else if (ttype->is_set()) { - t_set* tset = (t_set*)ttype; - return "THashSet<" + type_name(tset->get_elem_type(), true) + ">"; - } else if (ttype->is_list()) { - t_list* tlist = (t_list*)ttype; - return "List<" + type_name(tlist->get_elem_type(), true) + ">"; - } - - t_program* program = ttype->get_program(); - string postfix = (!is_required && nullable_ && in_param && ttype->is_enum()) ? "?" : ""; - if (program != NULL && program != program_) { - string ns = program->get_namespace("csharp"); - if (!ns.empty()) { - return ns + "." + normalize_name(ttype->get_name()) + postfix; - } - } - - return normalize_name(ttype->get_name()) + postfix; -} - -string t_csharp_generator::base_type_name(t_base_type* tbase, - bool in_container, - bool in_param, - bool is_required) { - (void)in_container; - string postfix = (!is_required && nullable_ && in_param) ? "?" : ""; - switch (tbase->get_base()) { - case t_base_type::TYPE_VOID: - return "void"; - case t_base_type::TYPE_STRING: - if (tbase->is_binary()) { - return "byte[]"; - } else { - return "string"; - } - case t_base_type::TYPE_BOOL: - return "bool" + postfix; - case t_base_type::TYPE_I8: - return "sbyte" + postfix; - case t_base_type::TYPE_I16: - return "short" + postfix; - case t_base_type::TYPE_I32: - return "int" + postfix; - case t_base_type::TYPE_I64: - return "long" + postfix; - case t_base_type::TYPE_DOUBLE: - return "double" + postfix; - default: - throw "compiler error: no C# name for base type " + t_base_type::t_base_name(tbase->get_base()); - } -} - -string t_csharp_generator::declare_field(t_field* tfield, bool init, std::string prefix) { - string result = type_name(tfield->get_type()) + " " + prefix + tfield->get_name(); - if (init) { - t_type* ttype = tfield->get_type(); - while (ttype->is_typedef()) { - ttype = ((t_typedef*)ttype)->get_type(); - } - if (ttype->is_base_type() && field_has_default(tfield)) { - std::ofstream dummy; - result += " = " + render_const_value(dummy, tfield->get_name(), ttype, tfield->get_value()); - } else if (ttype->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "NO T_VOID CONSTRUCT"; - case t_base_type::TYPE_STRING: - result += " = null"; - break; - case t_base_type::TYPE_BOOL: - result += " = false"; - break; - case t_base_type::TYPE_I8: - case t_base_type::TYPE_I16: - case t_base_type::TYPE_I32: - case t_base_type::TYPE_I64: - result += " = 0"; - break; - case t_base_type::TYPE_DOUBLE: - result += " = (double)0"; - break; - } - } else if (ttype->is_enum()) { - result += " = (" + type_name(ttype, false, true) + ")0"; - } else if (ttype->is_container()) { - result += " = new " + type_name(ttype, false, true) + "()"; - } else { - result += " = new " + type_name(ttype, false, true) + "()"; - } - } - return result + ";"; -} - -string t_csharp_generator::function_signature(t_function* tfunction, string prefix) { - t_type* ttype = tfunction->get_returntype(); - return type_name(ttype) + " " + normalize_name(prefix + tfunction->get_name()) + "(" - + argument_list(tfunction->get_arglist()) + ")"; -} - -string t_csharp_generator::function_signature_async_begin(t_function* tfunction, string prefix) { - string comma = (tfunction->get_arglist()->get_members().size() > 0 ? ", " : ""); - return "IAsyncResult " + normalize_name(prefix + tfunction->get_name()) - + "(AsyncCallback callback, object state" + comma + argument_list(tfunction->get_arglist()) - + ")"; -} - -string t_csharp_generator::function_signature_async_end(t_function* tfunction, string prefix) { - t_type* ttype = tfunction->get_returntype(); - return type_name(ttype) + " " + normalize_name(prefix + tfunction->get_name()) - + "(IAsyncResult asyncResult)"; -} - -string t_csharp_generator::function_signature_async(t_function* tfunction, string prefix) { - t_type* ttype = tfunction->get_returntype(); - string task = "Task"; - if (!ttype->is_void()) - task += "<" + type_name(ttype) + ">"; - return task + " " + normalize_name(prefix + tfunction->get_name()) + "Async(" - + argument_list(tfunction->get_arglist()) + ")"; -} - -string t_csharp_generator::argument_list(t_struct* tstruct) { - string result = ""; - const vector& fields = tstruct->get_members(); - vector::const_iterator f_iter; - bool first = true; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { - if (first) { - first = false; - } else { - result += ", "; - } - result += type_name((*f_iter)->get_type()) + " " + normalize_name((*f_iter)->get_name()); - } - return result; -} - -string t_csharp_generator::type_to_enum(t_type* type) { - while (type->is_typedef()) { - type = ((t_typedef*)type)->get_type(); - } - - if (type->is_base_type()) { - t_base_type::t_base tbase = ((t_base_type*)type)->get_base(); - switch (tbase) { - case t_base_type::TYPE_VOID: - throw "NO T_VOID CONSTRUCT"; - case t_base_type::TYPE_STRING: - return "TType.String"; - case t_base_type::TYPE_BOOL: - return "TType.Bool"; - case t_base_type::TYPE_I8: - return "TType.Byte"; - case t_base_type::TYPE_I16: - return "TType.I16"; - case t_base_type::TYPE_I32: - return "TType.I32"; - case t_base_type::TYPE_I64: - return "TType.I64"; - case t_base_type::TYPE_DOUBLE: - return "TType.Double"; - } - } else if (type->is_enum()) { - return "TType.I32"; - } else if (type->is_struct() || type->is_xception()) { - return "TType.Struct"; - } else if (type->is_map()) { - return "TType.Map"; - } else if (type->is_set()) { - return "TType.Set"; - } else if (type->is_list()) { - return "TType.List"; - } - - throw "INVALID TYPE IN type_to_enum: " + type->get_name(); -} - -void t_csharp_generator::generate_csharp_docstring_comment(ostream& out, string contents) { - generate_docstring_comment(out, "/// \n", "/// ", contents, "/// \n"); -} - -void t_csharp_generator::generate_csharp_doc(ostream& out, t_field* field) { - if (field->get_type()->is_enum()) { - string combined_message = field->get_doc() + "\nget_type()) + "\"/>"; - generate_csharp_docstring_comment(out, combined_message); - } else { - generate_csharp_doc(out, (t_doc*)field); - } -} - -void t_csharp_generator::generate_csharp_doc(ostream& out, t_doc* tdoc) { - if (tdoc->has_doc()) { - generate_csharp_docstring_comment(out, tdoc->get_doc()); - } -} - -void t_csharp_generator::generate_csharp_doc(ostream& out, t_function* tfunction) { - if (tfunction->has_doc()) { - stringstream ps; - const vector& fields = tfunction->get_arglist()->get_members(); - vector::const_iterator p_iter; - for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) { - t_field* p = *p_iter; - ps << "\nget_name() << "\">"; - if (p->has_doc()) { - std::string str = p->get_doc(); - str.erase(std::remove(str.begin(), str.end(), '\n'), - str.end()); // remove the newlines that appear from the parser - ps << str; - } - ps << ""; - } - generate_docstring_comment(out, - "", - "/// ", - "\n" + tfunction->get_doc() + "" + ps.str(), - ""); - } -} - -std::string t_csharp_generator::get_enum_class_name(t_type* type) { - string package = ""; - t_program* program = type->get_program(); - if (program != NULL && program != program_) { - package = program->get_namespace("csharp") + "."; - } - return package + type->get_name(); -} - - -THRIFT_REGISTER_GENERATOR( - csharp, - "C#", - " async: Adds Async support using Task.Run.\n" - " wcf: Adds bindings for WCF to generated classes.\n" - " serial: Add serialization support to generated classes.\n" - " nullable: Use nullable types for properties.\n" - " hashcode: Generate a hashcode and equals implementation for classes.\n" - " union: Use new union typing, which includes a static read function for union " - "types.\n") diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index b2883ed44ba..6737862d7dc 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -157,12 +157,7 @@ void t_netstd_generator::init_generator() { MKDIR(get_out_dir().c_str()); - // for usage of csharp namespaces in thrift files (from files for csharp) namespace_name_ = program_->get_namespace("netstd"); - if (namespace_name_.empty()) - { - namespace_name_ = program_->get_namespace("netstd"); - } string dir = namespace_name_; string subdir = get_out_dir().c_str(); diff --git a/compiler/cpp/src/thrift/parse/t_program.h b/compiler/cpp/src/thrift/parse/t_program.h index de68a0c1b93..5b1b8d02080 100644 --- a/compiler/cpp/src/thrift/parse/t_program.h +++ b/compiler/cpp/src/thrift/parse/t_program.h @@ -292,7 +292,7 @@ class t_program : public t_doc { base_language = "st"; } else if (base_language == "csharp") { - pwarning(1, "The '%s' target is deprecated. Consider moving to 'netstd' instead.", base_language.c_str()); + pwarning(1, "The '%s' target is no longer available. Use 'netstd' instead.", base_language.c_str()); // warn only, don't change base_language } else if (base_language == "netcore") { diff --git a/compiler/cpp/src/thrift/thriftl.ll b/compiler/cpp/src/thrift/thriftl.ll index 282e0309ca2..5f0ebd98590 100644 --- a/compiler/cpp/src/thrift/thriftl.ll +++ b/compiler/cpp/src/thrift/thriftl.ll @@ -207,7 +207,6 @@ literal_begin (['\"]) "cpp_include" { return tok_cpp_include; } "cpp_type" { return tok_cpp_type; } "java_package" { error_unsupported_namespace_decl("java_package", "java"); /* do nothing */ } -"csharp_namespace" { error_unsupported_namespace_decl("csharp"); /* do nothing */ } "delphi_namespace" { error_unsupported_namespace_decl("delphi"); /* do nothing */ } "php_namespace" { error_unsupported_namespace_decl("php"); /* do nothing */ } "py_module" { error_unsupported_namespace_decl("py_module", "py"); /* do nothing */ } diff --git a/compiler/cpp/tests/CMakeLists.txt b/compiler/cpp/tests/CMakeLists.txt index 7798c15f1ce..924e1675c26 100644 --- a/compiler/cpp/tests/CMakeLists.txt +++ b/compiler/cpp/tests/CMakeLists.txt @@ -101,7 +101,6 @@ THRIFT_ADD_COMPILER(as3 "Enable compiler for ActionScript 3" OFF) THRIFT_ADD_COMPILER(c_glib "Enable compiler for C with Glib" OFF) THRIFT_ADD_COMPILER(cl "Enable compiler for Common LISP" OFF) THRIFT_ADD_COMPILER(cpp "Enable compiler for C++" OFF) -THRIFT_ADD_COMPILER(csharp "Enable compiler for C#" OFF) THRIFT_ADD_COMPILER(d "Enable compiler for D" OFF) THRIFT_ADD_COMPILER(dart "Enable compiler for Dart" OFF) THRIFT_ADD_COMPILER(delphi "Enable compiler for Delphi" OFF) diff --git a/configure.ac b/configure.ac index f3f88a7156c..99c3c9cd78c 100755 --- a/configure.ac +++ b/configure.ac @@ -121,7 +121,6 @@ if test "$enable_libs" = "no"; then with_c_glib="no" with_cl="no" with_java="no" - with_csharp="no" with_python="no" with_py3="no" with_ruby="no" @@ -212,24 +211,6 @@ if test "$have_cpp" = "yes" -o "$have_c_glib" = "yes"; then AX_CHECK_OPENSSL() fi -AX_THRIFT_LIB(csharp, [C#], yes) -if test "$with_csharp" = "yes"; then - PKG_CHECK_MODULES(MONO, mono >= 2.11.0, mono_2_11=yes, mono_2_11=no) - if test "$mono_2_11" == "yes"; then - AC_PATH_PROG([MCS], [mcs]) - if test "x$MCS" != "x"; then - mono_mcs="yes" - fi - fi - PKG_CHECK_MODULES(MONO, mono >= 2.0.0, net_3_5=yes, net_3_5=no) - PKG_CHECK_MODULES(MONO, mono >= 1.2.4, have_mono=yes, have_mono=no) - if test "$have_mono" = "yes" ; then - have_csharp="yes" - fi -fi -AM_CONDITIONAL(WITH_MONO, [test "$have_csharp" = "yes"]) -AM_CONDITIONAL(NET_2_0, [test "$net_3_5" = "no"]) -AM_CONDITIONAL(MONO_MCS, [test "$mono_mcs" = "yes"]) AX_THRIFT_LIB(java, [Java], yes) if test "$with_java" = "yes"; then @@ -802,8 +783,6 @@ AC_CONFIG_FILES([ lib/c_glib/Makefile lib/c_glib/thrift_c_glib.pc lib/c_glib/test/Makefile - lib/csharp/Makefile - lib/csharp/test/Multiplex/Makefile lib/d/Makefile lib/d/test/Makefile lib/erl/Makefile @@ -838,7 +817,6 @@ AC_CONFIG_FILES([ test/c_glib/Makefile test/cl/Makefile test/cpp/Makefile - test/csharp/Makefile test/erl/Makefile test/go/Makefile test/haxe/Makefile @@ -885,8 +863,6 @@ if test "$have_d" = "yes" -a "$have_deimos_event2" = "yes" -a "$have_deimos_open AC_SUBST([MAYBE_D]) if test "$have_java" = "yes" ; then MAYBE_JAVA="java" ; else MAYBE_JAVA="" ; fi AC_SUBST([MAYBE_JAVA]) -if test "$have_csharp" = "yes" ; then MAYBE_CSHARP="csharp" ; else MAYBE_CSHARP="" ; fi -AC_SUBST([MAYBE_CSHARP]) if test "$have_python" = "yes" ; then MAYBE_PYTHON="py" ; else MAYBE_PYTHON="" ; fi AC_SUBST([MAYBE_PYTHON]) if test "$have_py3" = "yes" ; then MAYBE_PY3="py3" ; else MAYBE_PY3="" ; fi @@ -928,7 +904,6 @@ echo "$PACKAGE $VERSION" echo echo "Building ActionScript3 Library : $have_as3" echo "Building C (GLib) Library .... : $have_c_glib" -echo "Building C# (Mono) Library ... : $have_csharp" echo "Building C++ Library ......... : $have_cpp" echo "Building Common Lisp Library.. : $have_cl" echo "Building D Library ........... : $have_d" @@ -960,12 +935,6 @@ if test "$have_c_glib" = "yes" ; then echo "C (glib):" echo " Using glib version ........ : $($GSETTINGS --version)" fi -if test "$have_csharp" = "yes" ; then - echo - echo "C# Library:" - echo " Using .NET 3.5 ............ : $net_3_5" - echo " Using mono version ........ : $($MCS --version | head -1)" -fi if test "$have_cpp" = "yes" ; then echo echo "C++ Library:" diff --git a/contrib/Rebus/README.md b/contrib/Rebus/README.md index bbb9c496ea9..7b11bd0ddfc 100644 --- a/contrib/Rebus/README.md +++ b/contrib/Rebus/README.md @@ -19,3 +19,8 @@ refer to the Rebus docs on how to do that (it's not that hard, really). Additional requirements: - RabbitMQ .NET client (see nuget) + +Deprecation notice: +Csharp is not a supported Apache Thrift target anymore. Instead netstd is the +recommended replacement. This code is left "as is" for educational purposes +unless someone converts it to netstd diff --git a/contrib/Vagrantfile b/contrib/Vagrantfile index b340563330f..6d2d4203288 100644 --- a/contrib/Vagrantfile +++ b/contrib/Vagrantfile @@ -78,10 +78,6 @@ sudo apt-get install -qq lua5.2 lua5.2-dev # Node.js dependencies sudo apt-get install -qq nodejs nodejs-dev nodejs-legacy npm -# CSharp -sudo apt-get install -qq mono-gmcs mono-devel mono-xbuild mono-complete libmono-system-web2.0-cil -sudo apt-get install -qq mingw32 mingw32-binutils mingw32-runtime nsis - # D dependencies sudo wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list sudo apt-get update && sudo apt-get -y --allow-unauthenticated install --reinstall d-apt-keyring && sudo apt-get update diff --git a/contrib/thrift.spec b/contrib/thrift.spec index 225a969911b..4c678ba7f71 100644 --- a/contrib/thrift.spec +++ b/contrib/thrift.spec @@ -175,7 +175,6 @@ export RUBYLIB=${PWD}/lib/rb/lib %{?without_ruby: --without-ruby } \ %{?without_php: --without-php } \ %{!?without_php: PHP_PREFIX=${RPM_BUILD_ROOT}/usr/lib/php } \ - --without-csharp \ --without-erlang \ %if 0%{!?without_ruby:1} diff --git a/contrib/zeromq/README.md b/contrib/zeromq/README.md index 9e0b5bd3276..3a7379e5575 100644 --- a/contrib/zeromq/README.md +++ b/contrib/zeromq/README.md @@ -28,3 +28,8 @@ that amount. This code is not quite what I would consider production-ready. It doesn't support all of the normal hooks into Thrift, and its performance is sub-optimal because it does some unnecessary copying. + +Deprecation notice: +Csharp is not a supported Apache Thrift target anymore. Instead netstd is the +recommended replacement. This code is left "as is" for educational purposes +unless someone converts it to netstd diff --git a/debian/control b/debian/control index 414a815fee2..a9e934f173a 100644 --- a/debian/control +++ b/debian/control @@ -1,8 +1,8 @@ Source: thrift Section: devel Priority: extra -Build-Depends: debhelper (>= 9), build-essential, mono-mcs, python-dev, ant, - mono-devel, libmono-system-web4.0-cil, erlang-base, ruby-dev | ruby1.9.1-dev, ruby-bundler ,autoconf, automake, +Build-Depends: dotnet-runtime-3.1, dotnet-sdk-3.1, debhelper (>= 9), build-essential, python-dev, ant, + erlang-base, ruby-dev | ruby1.9.1-dev, ruby-bundler ,autoconf, automake, pkg-config, libtool, bison, flex, libboost-dev | libboost1.56-dev | libboost1.63-all-dev, python-all, python-setuptools, python-all-dev, python-all-dbg, python3-all, python3-setuptools, python3-all-dev, python3-all-dbg, @@ -126,17 +126,16 @@ Description: Java bindings for Thrift classes, and then the modules in this package will allow you to use those classes in your programs. -Package: libthrift-cil +Package: libthrift-netstd Architecture: all -Section: cli-mono -Depends: cli-common, libmono-corlib4.0-cil (>= 2.10) | libmono-corlib4.5-cil (>=3.2), libmono-system4.0-cil (>= 2.10), - libmono-system-web4.0-cil (>= 2.10), ${misc:Depends} -Description: CLI bindings for Thrift +Section: netstd +Depends: dotnet-runtime-3.1, ${misc:Depends} +Description: NET Standard bindings for Thrift Thrift is a software framework for scalable cross-language services development. It combines a software stack with a code generation engine to build services that work efficiently and seamlessly. . - This package contains the CLI bindings for Thrift. You will need the thrift + This package contains the NET Standard bindings for Thrift. You will need the thrift tool (in the thrift-compiler package) to compile your definition to C# classes, and then the modules in this package will allow you to use those classes in your programs. diff --git a/debian/copyright b/debian/copyright index 3e6fcf72122..ada769b0808 100644 --- a/debian/copyright +++ b/debian/copyright @@ -29,7 +29,7 @@ under the Apache 2.0 License: compiler/cpp/Makefile.am compiler/cpp/src/generate/t_cpp_generator.cc - compiler/cpp/src/generate/t_csharp_generator.cc + compiler/cpp/src/generate/t_netstd_generator.cc compiler/cpp/src/generate/t_erl_generator.cc compiler/cpp/src/generate/t_hs_generator.cc compiler/cpp/src/generate/t_java_generator.cc @@ -46,36 +46,36 @@ under the Apache 2.0 License: compiler/cpp/src/platform.h compiler/cpp/src/thriftl.ll compiler/cpp/src/thrifty.yy - lib/csharp/src/Protocol/TBinaryProtocol.cs - lib/csharp/src/Protocol/TField.cs - lib/csharp/src/Protocol/TList.cs - lib/csharp/src/Protocol/TMap.cs - lib/csharp/src/Protocol/TMessage.cs - lib/csharp/src/Protocol/TMessageType.cs - lib/csharp/src/Protocol/TProtocol.cs - lib/csharp/src/Protocol/TProtocolException.cs - lib/csharp/src/Protocol/TProtocolFactory.cs - lib/csharp/src/Protocol/TProtocolUtil.cs - lib/csharp/src/Protocol/TSet.cs - lib/csharp/src/Protocol/TStruct.cs - lib/csharp/src/Protocol/TType.cs - lib/csharp/src/Server/TServer.cs - lib/csharp/src/Server/TSimpleServer.cs - lib/csharp/src/Server/TThreadPoolServer.cs - lib/csharp/src/TApplicationException.cs - lib/csharp/src/Thrift.csproj - lib/csharp/src/Thrift.sln - lib/csharp/src/TProcessor.cs - lib/csharp/src/Transport/TServerSocket.cs - lib/csharp/src/Transport/TServerTransport.cs - lib/csharp/src/Transport/TSocket.cs - lib/csharp/src/Transport/TStreamTransport.cs - lib/csharp/src/Transport/TTransport.cs - lib/csharp/src/Transport/TTransportException.cs - lib/csharp/src/Transport/TTransportFactory.cs - lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs - lib/csharp/ThriftMSBuildTask/ThriftBuild.cs - lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj + lib/netstd/src/Protocol/TBinaryProtocol.cs + lib/netstd/src/Protocol/TField.cs + lib/netstd/src/Protocol/TList.cs + lib/netstd/src/Protocol/TMap.cs + lib/netstd/src/Protocol/TMessage.cs + lib/netstd/src/Protocol/TMessageType.cs + lib/netstd/src/Protocol/TProtocol.cs + lib/netstd/src/Protocol/TProtocolException.cs + lib/netstd/src/Protocol/TProtocolFactory.cs + lib/netstd/src/Protocol/TProtocolUtil.cs + lib/netstd/src/Protocol/TSet.cs + lib/netstd/src/Protocol/TStruct.cs + lib/netstd/src/Protocol/TType.cs + lib/netstd/src/Server/TServer.cs + lib/netstd/src/Server/TSimpleServer.cs + lib/netstd/src/Server/TThreadPoolServer.cs + lib/netstd/src/TApplicationException.cs + lib/netstd/src/Thrift.csproj + lib/netstd/src/Thrift.sln + lib/netstd/src/TProcessor.cs + lib/netstd/src/Transport/TServerSocket.cs + lib/netstd/src/Transport/TServerTransport.cs + lib/netstd/src/Transport/TSocket.cs + lib/netstd/src/Transport/TStreamTransport.cs + lib/netstd/src/Transport/TTransport.cs + lib/netstd/src/Transport/TTransportException.cs + lib/netstd/src/Transport/TTransportFactory.cs + lib/netstd/ThriftMSBuildTask/Properties/AssemblyInfo.cs + lib/netstd/ThriftMSBuildTask/ThriftBuild.cs + lib/netstd/ThriftMSBuildTask/ThriftMSBuildTask.csproj lib/rb/lib/thrift.rb lib/st/README lib/st/thrift.st diff --git a/debian/rules b/debian/rules index e209ba33caf..d0de508724c 100755 --- a/debian/rules +++ b/debian/rules @@ -76,7 +76,7 @@ build-indep-stamp: configure-stamp $(CURDIR)/compiler/cpp/thrift ./gradlew --no-daemon -Prelease=true jar # C# - $(MAKE) -C $(CURDIR)/lib/csharp + $(MAKE) -C $(CURDIR)/lib/netstd # Ruby $(MAKE) -C $(CURDIR)/lib/rb @@ -122,9 +122,9 @@ install-indep: $(CURDIR)/debian/ruby-thrift/usr/lib/ruby/1.9.1 # C# - mkdir -p $(CURDIR)/debian/libthrift-cil/usr/lib/cli/thrift/ && \ - cp $(CURDIR)/lib/csharp/Thrift.dll \ - $(CURDIR)/debian/libthrift-cil/usr/lib/cli/thrift/Thrift.dll + mkdir -p $(CURDIR)/debian/libthrift-netstd/usr/lib/cli/thrift/ && \ + cp $(CURDIR)/lib/netstd/Thrift/bin/Release/netstandard2.0/Thrift.dll \ + $(CURDIR)/debian/libthrift-netstd/usr/lib/cli/thrift/Thrift.dll # Perl $(MAKE) -C $(CURDIR)/lib/perl install DESTDIR=$(CURDIR)/debian/libthrift-perl diff --git a/doc/install/debian.md b/doc/install/debian.md index 2ccc37da7d3..d6b550088d8 100644 --- a/doc/install/debian.md +++ b/doc/install/debian.md @@ -32,8 +32,8 @@ If you would like to build Apache Thrift libraries for other programming languag * libglib2.0-dev * Erlang * erlang-base erlang-eunit erlang-dev rebar - * Csharp - * mono-gmcs mono-devel libmono-system-web2.0-cil nunit nunit-console + * NetStd + * apt-transport-https dotnet-sdk-3.1 aspnetcore-runtime-3.1 * Haskell * ghc cabal-install libghc-binary-dev libghc-network-dev libghc-http-dev * Thrift Compiler for Windows diff --git a/doc/specs/idl.md b/doc/specs/idl.md index df7e8d73263..75633107ace 100644 --- a/doc/specs/idl.md +++ b/doc/specs/idl.md @@ -38,7 +38,7 @@ A namespace declares which namespaces/package/module/etc. the type definitions i [5] Namespace ::= ( 'namespace' ( NamespaceScope Identifier ) ) - [6] NamespaceScope ::= '*' | 'c_glib' | 'cpp' | 'csharp' | 'delphi' | 'go' | 'java' | 'js' | 'lua' | 'netcore' | 'perl' | 'php' | 'py' | 'py.twisted' | 'rb' | 'st' | 'xsd' + [6] NamespaceScope ::= '*' | 'c_glib' | 'cpp' | 'delphi' | 'haxe' | 'go' | 'java' | 'js' | 'lua' | 'netstd' | 'perl' | 'php' | 'py' | 'py.twisted' | 'rb' | 'st' | 'xsd' ## Definition diff --git a/lib/Makefile.am b/lib/Makefile.am index 51a2af01df5..5d16256a473 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -32,10 +32,6 @@ if WITH_C_GLIB SUBDIRS += c_glib endif -if WITH_MONO -SUBDIRS += csharp -endif - if WITH_JAVA SUBDIRS += java PRECROSS_TARGET += precross-java diff --git a/lib/cpp/test/OneWayTest.thrift b/lib/cpp/test/OneWayTest.thrift index 1e9894cd992..37d1eb32849 100644 --- a/lib/cpp/test/OneWayTest.thrift +++ b/lib/cpp/test/OneWayTest.thrift @@ -26,7 +26,6 @@ namespace java onewaytest namespace cpp onewaytest namespace rb Onewaytest namespace perl OneWayTest -namespace csharp Onewaytest namespace js OneWayTest namespace st OneWayTest namespace py OneWayTest diff --git a/lib/csharp/Makefile.am b/lib/csharp/Makefile.am deleted file mode 100644 index cc2bbc96cfe..00000000000 --- a/lib/csharp/Makefile.am +++ /dev/null @@ -1,114 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -SUBDIRS = . test/Multiplex - -THRIFTCODE = \ - src/Collections/THashSet.cs \ - src/Collections/TCollections.cs \ - src/Properties/AssemblyInfo.cs \ - src/Protocol/TAbstractBase.cs \ - src/Protocol/TBase.cs \ - src/Protocol/TBase64Utils.cs \ - src/Protocol/TJSONProtocol.cs \ - src/Protocol/TProtocolException.cs \ - src/Protocol/TProtocolFactory.cs \ - src/Protocol/TList.cs \ - src/Protocol/TSet.cs \ - src/Protocol/TMap.cs \ - src/Protocol/TProtocolUtil.cs \ - src/Protocol/TMessageType.cs \ - src/Protocol/TProtocol.cs \ - src/Protocol/TProtocolDecorator.cs \ - src/Protocol/TMultiplexedProtocol.cs \ - src/Protocol/TMultiplexedProcessor.cs \ - src/Protocol/TType.cs \ - src/Protocol/TField.cs \ - src/Protocol/TMessage.cs \ - src/Protocol/TStruct.cs \ - src/Protocol/TBinaryProtocol.cs \ - src/Protocol/TCompactProtocol.cs \ - src/Server/TThreadedServer.cs \ - src/Server/TThreadPoolServer.cs \ - src/Server/TSimpleServer.cs \ - src/Server/TServer.cs \ - src/Server/TServerEventHandler.cs \ - src/Transport/TBufferedTransport.cs \ - src/Transport/TTransport.cs \ - src/Transport/TSocket.cs \ - src/Transport/TSocketVersionizer.cs \ - src/Transport/TTransportException.cs \ - src/Transport/TStreamTransport.cs \ - src/Transport/TFramedTransport.cs \ - src/Transport/TServerTransport.cs \ - src/Transport/TServerSocket.cs \ - src/Transport/TTransportFactory.cs \ - src/Transport/THttpClient.cs \ - src/Transport/THttpHandler.cs \ - src/Transport/TMemoryBuffer.cs \ - src/Transport/TNamedPipeClientTransport.cs \ - src/Transport/TNamedPipeServerTransport.cs \ - src/Transport/TTLSSocket.cs \ - src/Transport/TTLSServerSocket.cs \ - src/TProcessor.cs \ - src/TProcessorFactory.cs \ - src/TSingletonProcessorFactory.cs \ - src/TPrototypeProcessorFactory.cs \ - src/TControllingHandler.cs \ - src/TException.cs \ - src/TApplicationException.cs - -if MONO_MCS -export CSC = mcs -else -export CSC = gmcs -endif - -if NET_2_0 -export CSC_DEFINES = -d:NET_2_0 -endif - -all-local: Thrift.dll Thrift.45.dll - -Thrift.dll: $(THRIFTCODE) - $(CSC) $(CSC_DEFINES) -out:$@ -target:library -reference:System.Web $(THRIFTCODE) - -Thrift.45.dll: $(THRIFTCODE) - $(CSC) $(CSC_DEFINES) -out:$@ -target:library -reference:System.Web $(THRIFTCODE) - -CLEANFILES = \ - Thrift.dll \ - Thrift.45.dll - -DISTCLEANFILES = \ - Makefile.in - -EXTRA_DIST = \ - $(THRIFTCODE) \ - ThriftMSBuildTask \ - src/Thrift.csproj \ - src/Thrift.45.csproj \ - src/Thrift.sln \ - src/Net35/ExtensionsNet35.cs \ - src/Transport/TSilverlightSocket.cs \ - src/Transport/THttpTaskAsyncHandler.cs \ - src/TAsyncProcessor.cs \ - test \ - coding_standards.md \ - README.md diff --git a/lib/csharp/README.md b/lib/csharp/README.md deleted file mode 100644 index 5fc14cb3cdd..00000000000 --- a/lib/csharp/README.md +++ /dev/null @@ -1,32 +0,0 @@ -Thrift C# Software Library - -Deprecation notice -======= - -Per [THRIFT-4723](https://issues.apache.org/jira/browse/THRIFT-4723), both CSharp and Netcore targets are deprecated -and will be removed with the next release. Migrate to the [NetStd language target](../netstd/README.md) instead. - -License -======= - -Licensed to the Apache Software Foundation (ASF) under one -or more contributor license agreements. See the NOTICE file -distributed with this work for additional information -regarding copyright ownership. The ASF licenses this file -to you under the Apache License, Version 2.0 (the -"License"); you may not use this file except in compliance -with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, -software distributed under the License is distributed on an -"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -KIND, either express or implied. See the License for the -specific language governing permissions and limitations -under the License. - -Using Thrift with C# -==================== - -Thrift requires Mono >= 1.2.6 or .NET framework >= 3.5 diff --git a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs b/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs deleted file mode 100644 index f5f00005976..00000000000 --- a/lib/csharp/ThriftMSBuildTask/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ThriftMSBuildTask")] -[assembly: AssemblyDescription("MSBuild Task to generate csharp from .thrift files, and compile the code into a library: ThriftImpl.dll")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("ThriftMSBuildTask")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -//@TODO where to put License information? - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("5095e09d-7b95-4be1-b250-e1c1db1c485e")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.14.0.*")] -[assembly: AssemblyFileVersion("0.14.0.*")] diff --git a/lib/csharp/ThriftMSBuildTask/ThriftBuild.cs b/lib/csharp/ThriftMSBuildTask/ThriftBuild.cs deleted file mode 100644 index 4e6d3011256..00000000000 --- a/lib/csharp/ThriftMSBuildTask/ThriftBuild.cs +++ /dev/null @@ -1,246 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; -using Microsoft.Build.Tasks; -using System.IO; -using System.Diagnostics; - -namespace ThriftMSBuildTask -{ - /// - /// MSBuild Task to generate csharp from .thrift files, and compile the code into a library: ThriftImpl.dll - /// - public class ThriftBuild : Task - { - /// - /// The full path to the thrift.exe compiler - /// - [Required] - public ITaskItem ThriftExecutable - { - get; - set; - } - - /// - /// The full path to a thrift.dll C# library - /// - [Required] - public ITaskItem ThriftLibrary - { - get; - set; - } - - /// - /// A direcotry containing .thrift files - /// - [Required] - public ITaskItem ThriftDefinitionDir - { - get; - set; - } - - /// - /// The name of the auto-gen and compiled thrift library. It will placed in - /// the same directory as ThriftLibrary - /// - [Required] - public ITaskItem OutputName - { - get; - set; - } - - /// - /// The full path to the compiled ThriftLibrary. This allows msbuild tasks to use this - /// output as a variable for use elsewhere. - /// - [Output] - public ITaskItem ThriftImplementation - { - get { return thriftImpl; } - } - - private ITaskItem thriftImpl; - private const string lastCompilationName = "LAST_COMP_TIMESTAMP"; - - //use the Message Build Task to write something to build log - private void LogMessage(string text, MessageImportance importance) - { - Message m = new Message(); - m.Text = text; - m.Importance = importance.ToString(); - m.BuildEngine = this.BuildEngine; - m.Execute(); - } - - //recursively find .cs files in srcDir, paths should initially be non-null and empty - private void FindSourcesHelper(string srcDir, List paths) - { - string[] files = Directory.GetFiles(srcDir, "*.cs"); - foreach (string f in files) - { - paths.Add(f); - } - string[] dirs = Directory.GetDirectories(srcDir); - foreach (string dir in dirs) - { - FindSourcesHelper(dir, paths); - } - } - - /// - /// Quote paths with spaces - /// - private string SafePath(string path) - { - if (path.Contains(' ') && !path.StartsWith("\"")) - { - return "\"" + path + "\""; - } - return path; - } - - private ITaskItem[] FindSources(string srcDir) - { - List files = new List(); - FindSourcesHelper(srcDir, files); - ITaskItem[] items = new ITaskItem[files.Count]; - for (int i = 0; i < items.Length; i++) - { - items[i] = new TaskItem(files[i]); - } - return items; - } - - private string LastWriteTime(string defDir) - { - string[] files = Directory.GetFiles(defDir, "*.thrift"); - DateTime d = (new DirectoryInfo(defDir)).LastWriteTime; - foreach(string file in files) - { - FileInfo f = new FileInfo(file); - DateTime curr = f.LastWriteTime; - if (DateTime.Compare(curr, d) > 0) - { - d = curr; - } - } - return d.ToFileTimeUtc().ToString(); - } - - public override bool Execute() - { - string defDir = SafePath(ThriftDefinitionDir.ItemSpec); - //look for last compilation timestamp - string lastBuildPath = Path.Combine(defDir, lastCompilationName); - DirectoryInfo defDirInfo = new DirectoryInfo(defDir); - string lastWrite = LastWriteTime(defDir); - if (File.Exists(lastBuildPath)) - { - string lastComp = File.ReadAllText(lastBuildPath); - //don't recompile if the thrift library has been updated since lastComp - FileInfo f = new FileInfo(ThriftLibrary.ItemSpec); - string thriftLibTime = f.LastWriteTimeUtc.ToFileTimeUtc().ToString(); - if (lastComp.CompareTo(thriftLibTime) < 0) - { - //new thrift library, do a compile - lastWrite = thriftLibTime; - } - else if (lastComp == lastWrite || (lastComp == thriftLibTime && lastComp.CompareTo(lastWrite) > 0)) - { - //the .thrift dir hasn't been written to since last compilation, don't need to do anything - LogMessage("ThriftImpl up-to-date", MessageImportance.High); - return true; - } - } - - //find the directory of the thriftlibrary (that's where output will go) - FileInfo thriftLibInfo = new FileInfo(SafePath(ThriftLibrary.ItemSpec)); - string thriftDir = thriftLibInfo.Directory.FullName; - - string genDir = Path.Combine(thriftDir, "gen-csharp"); - if (Directory.Exists(genDir)) - { - try - { - Directory.Delete(genDir, true); - } - catch { /*eh i tried, just over-write now*/} - } - - //run the thrift executable to generate C# - foreach (string thriftFile in Directory.GetFiles(defDir, "*.thrift")) - { - LogMessage("Generating code for: " + thriftFile, MessageImportance.Normal); - Process p = new Process(); - p.StartInfo.FileName = SafePath(ThriftExecutable.ItemSpec); - p.StartInfo.Arguments = "--gen csharp -o " + SafePath(thriftDir) + " -r " + thriftFile; - p.StartInfo.UseShellExecute = false; - p.StartInfo.CreateNoWindow = true; - p.StartInfo.RedirectStandardOutput = false; - p.Start(); - p.WaitForExit(); - if (p.ExitCode != 0) - { - LogMessage("thrift.exe failed to compile " + thriftFile, MessageImportance.High); - return false; - } - if (p.ExitCode != 0) - { - LogMessage("thrift.exe failed to compile " + thriftFile, MessageImportance.High); - return false; - } - } - - Csc csc = new Csc(); - csc.TargetType = "library"; - csc.References = new ITaskItem[] { new TaskItem(ThriftLibrary.ItemSpec) }; - csc.EmitDebugInformation = true; - string outputPath = Path.Combine(thriftDir, OutputName.ItemSpec); - csc.OutputAssembly = new TaskItem(outputPath); - csc.Sources = FindSources(Path.Combine(thriftDir, "gen-csharp")); - csc.BuildEngine = this.BuildEngine; - LogMessage("Compiling generated cs...", MessageImportance.Normal); - if (!csc.Execute()) - { - return false; - } - - //write file to defDir to indicate a build was successfully completed - File.WriteAllText(lastBuildPath, lastWrite); - - thriftImpl = new TaskItem(outputPath); - - return true; - } - } -} diff --git a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj b/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj deleted file mode 100644 index 25899705c13..00000000000 --- a/lib/csharp/ThriftMSBuildTask/ThriftMSBuildTask.csproj +++ /dev/null @@ -1,118 +0,0 @@ - - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {EC0A0231-66EA-4593-A792-C6CA3BB8668E} - Library - Properties - ThriftMSBuildTask - ThriftMSBuildTask - v3.5 - 512 - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 0.14.0.0 - false - false - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - - - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - diff --git a/lib/csharp/coding_standards.md b/lib/csharp/coding_standards.md deleted file mode 100644 index dc87190bfb1..00000000000 --- a/lib/csharp/coding_standards.md +++ /dev/null @@ -1,6 +0,0 @@ -## C# Coding Standards - -Please follow: - * [Thrift General Coding Standards](/doc/coding_standards.md) - * [MSDN C# Coding Conventions](http://msdn.microsoft.com/en-us/library/ff926074.aspx) - * [C# Coding Guidelines](http://csharpguidelines.codeplex.com/) diff --git a/lib/csharp/src/Collections/TCollections.cs b/lib/csharp/src/Collections/TCollections.cs deleted file mode 100644 index 84afb6a62a7..00000000000 --- a/lib/csharp/src/Collections/TCollections.cs +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -using System; -using System.Collections; - -namespace Thrift.Collections -{ - public class TCollections - { - /// - /// This will return true if the two collections are value-wise the same. - /// If the collection contains a collection, the collections will be compared using this method. - /// - public static bool Equals (IEnumerable first, IEnumerable second) - { - if (first == null && second == null) - { - return true; - } - if (first == null || second == null) - { - return false; - } - IEnumerator fiter = first.GetEnumerator (); - IEnumerator siter = second.GetEnumerator (); - - bool fnext = fiter.MoveNext (); - bool snext = siter.MoveNext (); - while (fnext && snext) - { - IEnumerable fenum = fiter.Current as IEnumerable; - IEnumerable senum = siter.Current as IEnumerable; - if (fenum != null && senum != null) - { - if (!Equals(fenum, senum)) - { - return false; - } - } - else if (fenum == null ^ senum == null) - { - return false; - } - else if (!Equals(fiter.Current, siter.Current)) - { - return false; - } - fnext = fiter.MoveNext(); - snext = siter.MoveNext(); - } - - return fnext == snext; - } - - /// - /// This returns a hashcode based on the value of the enumerable. - /// - public static int GetHashCode (IEnumerable enumerable) - { - if (enumerable == null) - { - return 0; - } - - int hashcode = 0; - foreach (object obj in enumerable) - { - IEnumerable enum2 = obj as IEnumerable; - int objHash = enum2 == null ? obj.GetHashCode () : GetHashCode (enum2); - unchecked - { - hashcode = (hashcode * 397) ^ (objHash); - } - } - return hashcode; - } - } -} diff --git a/lib/csharp/src/Collections/THashSet.cs b/lib/csharp/src/Collections/THashSet.cs deleted file mode 100644 index e29271a935d..00000000000 --- a/lib/csharp/src/Collections/THashSet.cs +++ /dev/null @@ -1,160 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Collections; -using System.Collections.Generic; - -#if SILVERLIGHT -using System.Runtime.Serialization; -#endif - -namespace Thrift.Collections -{ -#if SILVERLIGHT - [DataContract] -#else - [Serializable] -#endif - public class THashSet : ICollection - { -#if NET_2_0 || SILVERLIGHT -#if SILVERLIGHT - [DataMember] -#endif - TDictSet set = new TDictSet(); -#else - HashSet set = new HashSet(); -#endif - public int Count - { - get { return set.Count; } - } - - public bool IsReadOnly - { - get { return false; } - } - - public void Add(T item) - { - set.Add(item); - } - - public void Clear() - { - set.Clear(); - } - - public bool Contains(T item) - { - return set.Contains(item); - } - - public void CopyTo(T[] array, int arrayIndex) - { - set.CopyTo(array, arrayIndex); - } - - public IEnumerator GetEnumerator() - { - return set.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return ((IEnumerable)set).GetEnumerator(); - } - - public bool Remove(T item) - { - return set.Remove(item); - } - -#if NET_2_0 || SILVERLIGHT -#if SILVERLIGHT - [DataContract] -#endif - private class TDictSet : ICollection - { -#if SILVERLIGHT - [DataMember] -#endif - Dictionary> dict = new Dictionary>(); - - public int Count - { - get { return dict.Count; } - } - - public bool IsReadOnly - { - get { return false; } - } - - public IEnumerator GetEnumerator() - { - return ((IEnumerable)dict.Keys).GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return dict.Keys.GetEnumerator(); - } - - public bool Add(V item) - { - if (!dict.ContainsKey(item)) - { - dict[item] = this; - return true; - } - - return false; - } - - void ICollection.Add(V item) - { - Add(item); - } - - public void Clear() - { - dict.Clear(); - } - - public bool Contains(V item) - { - return dict.ContainsKey(item); - } - - public void CopyTo(V[] array, int arrayIndex) - { - dict.Keys.CopyTo(array, arrayIndex); - } - - public bool Remove(V item) - { - return dict.Remove(item); - } - } -#endif - } - -} diff --git a/lib/csharp/src/Net35/ExtensionsNet35.cs b/lib/csharp/src/Net35/ExtensionsNet35.cs deleted file mode 100644 index 73a42328847..00000000000 --- a/lib/csharp/src/Net35/ExtensionsNet35.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -#if (!NET45) -namespace Thrift -{ - static class StreamExtensionsNet35 - { - // CopyTo() has been added in 4.0 - public static long CopyTo(this Stream source, Stream target) - { - byte[] buffer = new byte[8192]; // multiple of 4096 - long nTotal = 0; - while (true) - { - int nRead = source.Read(buffer, 0, buffer.Length); - if (nRead <= 0) // done? - return nTotal; - - target.Write(buffer, 0, nRead); - nTotal += nRead; - } - } - } - -} -#endif - diff --git a/lib/csharp/src/Properties/AssemblyInfo.cs b/lib/csharp/src/Properties/AssemblyInfo.cs deleted file mode 100644 index c8f51b5c076..00000000000 --- a/lib/csharp/src/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Thrift")] -[assembly: AssemblyDescription("C# bindings for the Apache Thrift RPC system")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -//@TODO where to put License information? - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("df3f8ef0-e0a3-4c86-a65b-8ec84e016b1d")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("0.14.0.0")] -[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/lib/csharp/src/Protocol/TAbstractBase.cs b/lib/csharp/src/Protocol/TAbstractBase.cs deleted file mode 100644 index f5a61cd44ed..00000000000 --- a/lib/csharp/src/Protocol/TAbstractBase.cs +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -namespace Thrift.Protocol -{ - public interface TAbstractBase - { - /// - /// Writes the objects out to the protocol. - /// - void Write(TProtocol tProtocol); - } -} diff --git a/lib/csharp/src/Protocol/TBase.cs b/lib/csharp/src/Protocol/TBase.cs deleted file mode 100644 index 411e4d95f6d..00000000000 --- a/lib/csharp/src/Protocol/TBase.cs +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -namespace Thrift.Protocol -{ - public interface TBase : TAbstractBase - { - /// - /// Reads the TObject from the given input protocol. - /// - void Read(TProtocol tProtocol); - } -} diff --git a/lib/csharp/src/Protocol/TBase64Utils.cs b/lib/csharp/src/Protocol/TBase64Utils.cs deleted file mode 100644 index 9eaaebddaa8..00000000000 --- a/lib/csharp/src/Protocol/TBase64Utils.cs +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; - -namespace Thrift.Protocol -{ - internal static class TBase64Utils - { - internal const string ENCODE_TABLE = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - internal static void encode(byte[] src, int srcOff, int len, byte[] dst, - int dstOff) - { - dst[dstOff] = (byte)ENCODE_TABLE[(src[srcOff] >> 2) & 0x3F]; - if (len == 3) - { - dst[dstOff + 1] = - (byte)ENCODE_TABLE[ - ((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; - dst[dstOff + 2] = - (byte)ENCODE_TABLE[ - ((src[srcOff + 1] << 2) & 0x3C) | ((src[srcOff + 2] >> 6) & 0x03)]; - dst[dstOff + 3] = - (byte)ENCODE_TABLE[src[srcOff + 2] & 0x3F]; - } - else if (len == 2) - { - dst[dstOff + 1] = - (byte)ENCODE_TABLE[ - ((src[srcOff] << 4) & 0x30) | ((src[srcOff + 1] >> 4) & 0x0F)]; - dst[dstOff + 2] = - (byte)ENCODE_TABLE[(src[srcOff + 1] << 2) & 0x3C]; - - } - else - { // len == 1) { - dst[dstOff + 1] = - (byte)ENCODE_TABLE[(src[srcOff] << 4) & 0x30]; - } - } - - private static int[] 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, - }; - - internal static 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/lib/csharp/src/Protocol/TBinaryProtocol.cs b/lib/csharp/src/Protocol/TBinaryProtocol.cs deleted file mode 100644 index a4faa946f1b..00000000000 --- a/lib/csharp/src/Protocol/TBinaryProtocol.cs +++ /dev/null @@ -1,395 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Text; -using Thrift.Transport; - -namespace Thrift.Protocol -{ - public class TBinaryProtocol : TProtocol - { - protected const uint VERSION_MASK = 0xffff0000; - protected const uint VERSION_1 = 0x80010000; - - protected bool strictRead_ = false; - protected bool strictWrite_ = true; - - #region BinaryProtocol Factory - - public class Factory : TProtocolFactory - { - protected bool strictRead_ = false; - protected bool strictWrite_ = true; - - public Factory() - : this(false, true) - { - } - - public Factory(bool strictRead, bool strictWrite) - { - strictRead_ = strictRead; - strictWrite_ = strictWrite; - } - - public TProtocol GetProtocol(TTransport trans) - { - return new TBinaryProtocol(trans, strictRead_, strictWrite_); - } - } - - #endregion - - public TBinaryProtocol(TTransport trans) - : this(trans, false, true) - { - } - - public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite) - : base(trans) - { - strictRead_ = strictRead; - strictWrite_ = strictWrite; - } - - #region Write Methods - - public override void WriteMessageBegin(TMessage message) - { - if (strictWrite_) - { - uint version = VERSION_1 | (uint)(message.Type); - WriteI32((int)version); - WriteString(message.Name); - WriteI32(message.SeqID); - } - else - { - WriteString(message.Name); - WriteByte((sbyte)message.Type); - WriteI32(message.SeqID); - } - } - - public override void WriteMessageEnd() - { - } - - public override void WriteStructBegin(TStruct struc) - { - } - - public override void WriteStructEnd() - { - } - - public override void WriteFieldBegin(TField field) - { - WriteByte((sbyte)field.Type); - WriteI16(field.ID); - } - - public override void WriteFieldEnd() - { - } - - public override void WriteFieldStop() - { - WriteByte((sbyte)TType.Stop); - } - - public override void WriteMapBegin(TMap map) - { - WriteByte((sbyte)map.KeyType); - WriteByte((sbyte)map.ValueType); - WriteI32(map.Count); - } - - public override void WriteMapEnd() - { - } - - public override void WriteListBegin(TList list) - { - WriteByte((sbyte)list.ElementType); - WriteI32(list.Count); - } - - public override void WriteListEnd() - { - } - - public override void WriteSetBegin(TSet set) - { - WriteByte((sbyte)set.ElementType); - WriteI32(set.Count); - } - - public override void WriteSetEnd() - { - } - - public override void WriteBool(bool b) - { - WriteByte(b ? (sbyte)1 : (sbyte)0); - } - - private byte[] bout = new byte[1]; - public override void WriteByte(sbyte b) - { - bout[0] = (byte)b; - trans.Write(bout, 0, 1); - } - - private byte[] i16out = new byte[2]; - public override void WriteI16(short s) - { - i16out[0] = (byte)(0xff & (s >> 8)); - i16out[1] = (byte)(0xff & s); - trans.Write(i16out, 0, 2); - } - - private byte[] i32out = new byte[4]; - public override void WriteI32(int i32) - { - i32out[0] = (byte)(0xff & (i32 >> 24)); - i32out[1] = (byte)(0xff & (i32 >> 16)); - i32out[2] = (byte)(0xff & (i32 >> 8)); - i32out[3] = (byte)(0xff & i32); - trans.Write(i32out, 0, 4); - } - - private byte[] i64out = new byte[8]; - public override void WriteI64(long i64) - { - i64out[0] = (byte)(0xff & (i64 >> 56)); - i64out[1] = (byte)(0xff & (i64 >> 48)); - i64out[2] = (byte)(0xff & (i64 >> 40)); - i64out[3] = (byte)(0xff & (i64 >> 32)); - i64out[4] = (byte)(0xff & (i64 >> 24)); - i64out[5] = (byte)(0xff & (i64 >> 16)); - i64out[6] = (byte)(0xff & (i64 >> 8)); - i64out[7] = (byte)(0xff & i64); - trans.Write(i64out, 0, 8); - } - - public override void WriteDouble(double d) - { -#if !SILVERLIGHT - WriteI64(BitConverter.DoubleToInt64Bits(d)); -#else - var bytes = BitConverter.GetBytes(d); - WriteI64(BitConverter.ToInt64(bytes, 0)); -#endif - } - - public override void WriteBinary(byte[] b) - { - WriteI32(b.Length); - trans.Write(b, 0, b.Length); - } - - #endregion - - #region ReadMethods - - public override TMessage ReadMessageBegin() - { - TMessage message = new TMessage(); - int size = ReadI32(); - if (size < 0) - { - uint version = (uint)size & VERSION_MASK; - if (version != VERSION_1) - { - throw new TProtocolException(TProtocolException.BAD_VERSION, "Bad version in ReadMessageBegin: " + version); - } - message.Type = (TMessageType)(size & 0x000000ff); - message.Name = ReadString(); - message.SeqID = ReadI32(); - } - else - { - if (strictRead_) - { - throw new TProtocolException(TProtocolException.BAD_VERSION, "Missing version in readMessageBegin, old client?"); - } - message.Name = ReadStringBody(size); - message.Type = (TMessageType)ReadByte(); - message.SeqID = ReadI32(); - } - return message; - } - - public override void ReadMessageEnd() - { - } - - public override TStruct ReadStructBegin() - { - return new TStruct(); - } - - public override void ReadStructEnd() - { - } - - public override TField ReadFieldBegin() - { - TField field = new TField(); - field.Type = (TType)ReadByte(); - - if (field.Type != TType.Stop) - { - field.ID = ReadI16(); - } - - return field; - } - - public override void ReadFieldEnd() - { - } - - public override TMap ReadMapBegin() - { - TMap map = new TMap(); - map.KeyType = (TType)ReadByte(); - map.ValueType = (TType)ReadByte(); - map.Count = ReadI32(); - - return map; - } - - public override void ReadMapEnd() - { - } - - public override TList ReadListBegin() - { - TList list = new TList(); - list.ElementType = (TType)ReadByte(); - list.Count = ReadI32(); - - return list; - } - - public override void ReadListEnd() - { - } - - public override TSet ReadSetBegin() - { - TSet set = new TSet(); - set.ElementType = (TType)ReadByte(); - set.Count = ReadI32(); - - return set; - } - - public override void ReadSetEnd() - { - } - - public override bool ReadBool() - { - return ReadByte() == 1; - } - - private byte[] bin = new byte[1]; - public override sbyte ReadByte() - { - ReadAll(bin, 0, 1); - return (sbyte)bin[0]; - } - - private byte[] i16in = new byte[2]; - public override short ReadI16() - { - ReadAll(i16in, 0, 2); - return (short)(((i16in[0] & 0xff) << 8) | ((i16in[1] & 0xff))); - } - - private byte[] i32in = new byte[4]; - public override int ReadI32() - { - ReadAll(i32in, 0, 4); - return (int)(((i32in[0] & 0xff) << 24) | ((i32in[1] & 0xff) << 16) | ((i32in[2] & 0xff) << 8) | ((i32in[3] & 0xff))); - } - -#pragma warning disable 675 - - private byte[] i64in = new byte[8]; - public override long ReadI64() - { - ReadAll(i64in, 0, 8); - unchecked - { - return (long)( - ((long)(i64in[0] & 0xff) << 56) | - ((long)(i64in[1] & 0xff) << 48) | - ((long)(i64in[2] & 0xff) << 40) | - ((long)(i64in[3] & 0xff) << 32) | - ((long)(i64in[4] & 0xff) << 24) | - ((long)(i64in[5] & 0xff) << 16) | - ((long)(i64in[6] & 0xff) << 8) | - ((long)(i64in[7] & 0xff))); - } - } - -#pragma warning restore 675 - - public override double ReadDouble() - { -#if !SILVERLIGHT - return BitConverter.Int64BitsToDouble(ReadI64()); -#else - var value = ReadI64(); - var bytes = BitConverter.GetBytes(value); - return BitConverter.ToDouble(bytes, 0); -#endif - } - - public override byte[] ReadBinary() - { - int size = ReadI32(); - byte[] buf = new byte[size]; - trans.ReadAll(buf, 0, size); - return buf; - } - private string ReadStringBody(int size) - { - byte[] buf = new byte[size]; - trans.ReadAll(buf, 0, size); - return Encoding.UTF8.GetString(buf, 0, buf.Length); - } - - private int ReadAll(byte[] buf, int off, int len) - { - return trans.ReadAll(buf, off, len); - } - - #endregion - } -} diff --git a/lib/csharp/src/Protocol/TCompactProtocol.cs b/lib/csharp/src/Protocol/TCompactProtocol.cs deleted file mode 100644 index ff673975efa..00000000000 --- a/lib/csharp/src/Protocol/TCompactProtocol.cs +++ /dev/null @@ -1,849 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Text; -using Thrift.Transport; -using System.Collections; -using System.IO; -using System.Collections.Generic; - -namespace Thrift.Protocol -{ - public class TCompactProtocol : TProtocol - { - private static TStruct ANONYMOUS_STRUCT = new TStruct(""); - private static TField TSTOP = new TField("", TType.Stop, (short)0); - - private static byte[] ttypeToCompactType = new byte[16]; - - private const byte PROTOCOL_ID = 0x82; - private const byte VERSION = 1; - private const byte VERSION_MASK = 0x1f; // 0001 1111 - private const byte TYPE_MASK = 0xE0; // 1110 0000 - private const byte TYPE_BITS = 0x07; // 0000 0111 - private const int TYPE_SHIFT_AMOUNT = 5; - - /// - /// All of the on-wire type codes. - /// - private static class Types - { - public const byte STOP = 0x00; - public const byte BOOLEAN_TRUE = 0x01; - public const byte BOOLEAN_FALSE = 0x02; - public const byte BYTE = 0x03; - public const byte I16 = 0x04; - public const byte I32 = 0x05; - public const byte I64 = 0x06; - public const byte DOUBLE = 0x07; - public const byte BINARY = 0x08; - public const byte LIST = 0x09; - public const byte SET = 0x0A; - public const byte MAP = 0x0B; - public const 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 Stack lastField_ = new Stack(15); - - private short lastFieldId_ = 0; - - /// - /// If we encounter a boolean field begin, save the TField here so it can - /// have the value incorporated. - /// - private Nullable booleanField_; - - /// - /// If we Read a field header, and it's a boolean field, save the boolean - /// value here so that ReadBool can use it. - /// - private Nullable boolValue_; - - - #region CompactProtocol Factory - - public class Factory : TProtocolFactory - { - public Factory() { } - - public TProtocol GetProtocol(TTransport trans) - { - return new TCompactProtocol(trans); - } - } - - #endregion - - public TCompactProtocol(TTransport trans) - : base(trans) - { - ttypeToCompactType[(int)TType.Stop] = Types.STOP; - ttypeToCompactType[(int)TType.Bool] = Types.BOOLEAN_TRUE; - ttypeToCompactType[(int)TType.Byte] = Types.BYTE; - ttypeToCompactType[(int)TType.I16] = Types.I16; - ttypeToCompactType[(int)TType.I32] = Types.I32; - ttypeToCompactType[(int)TType.I64] = Types.I64; - ttypeToCompactType[(int)TType.Double] = Types.DOUBLE; - ttypeToCompactType[(int)TType.String] = Types.BINARY; - ttypeToCompactType[(int)TType.List] = Types.LIST; - ttypeToCompactType[(int)TType.Set] = Types.SET; - ttypeToCompactType[(int)TType.Map] = Types.MAP; - ttypeToCompactType[(int)TType.Struct] = Types.STRUCT; - } - - public void reset() - { - lastField_.Clear(); - lastFieldId_ = 0; - } - - #region Write Methods - - /// - /// 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 byte[] byteDirectBuffer = new byte[1]; - - private void WriteByteDirect(byte b) - { - byteDirectBuffer[0] = b; - trans.Write(byteDirectBuffer); - } - - /// - /// Writes a byte without any possibility of all that field header nonsense. - /// - private void WriteByteDirect(int n) - { - WriteByteDirect((byte)n); - } - - /// - /// Write an i32 as a varint. Results in 1-5 bytes on the wire. - /// TODO: make a permanent buffer like WriteVarint64? - /// - byte[] i32buf = new byte[5]; - - private void WriteVarint32(uint n) - { - int idx = 0; - while (true) - { - if ((n & ~0x7F) == 0) - { - i32buf[idx++] = (byte)n; - // WriteByteDirect((byte)n); - break; - // return; - } - else - { - i32buf[idx++] = (byte)((n & 0x7F) | 0x80); - // WriteByteDirect((byte)((n & 0x7F) | 0x80)); - n >>= 7; - } - } - trans.Write(i32buf, 0, idx); - } - - /// - /// 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 override void WriteMessageBegin(TMessage message) - { - WriteByteDirect(PROTOCOL_ID); - WriteByteDirect((byte)((VERSION & VERSION_MASK) | ((((uint)message.Type) << TYPE_SHIFT_AMOUNT) & TYPE_MASK))); - WriteVarint32((uint)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 override void WriteStructBegin(TStruct strct) - { - 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 override void WriteStructEnd() - { - 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 override void WriteFieldBegin(TField field) - { - if (field.Type == TType.Bool) - { - // we want to possibly include the value, so we'll wait. - booleanField_ = field; - } - else - { - WriteFieldBeginInternal(field, 0xFF); - } - } - - /// - /// 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) - { - // short lastField = lastField_.Pop(); - - // if there's a type override, use that. - byte typeToWrite = typeOverride == 0xFF ? 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 override void WriteFieldStop() - { - WriteByteDirect(Types.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 override void WriteMapBegin(TMap map) - { - if (map.Count == 0) - { - WriteByteDirect(0); - } - else - { - WriteVarint32((uint)map.Count); - WriteByteDirect(getCompactType(map.KeyType) << 4 | getCompactType(map.ValueType)); - } - } - - /// - /// Write a list header. - /// - public override void WriteListBegin(TList list) - { - WriteCollectionBegin(list.ElementType, list.Count); - } - - /// - /// Write a set header. - /// - public override void WriteSetBegin(TSet set) - { - WriteCollectionBegin(set.ElementType, set.Count); - } - - /// - /// 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 override void WriteBool(Boolean b) - { - if (booleanField_ != null) - { - // we haven't written the field header yet - WriteFieldBeginInternal(booleanField_.Value, 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 override void WriteByte(sbyte b) - { - WriteByteDirect((byte)b); - } - - /// - /// Write an I16 as a zigzag varint. - /// - public override void WriteI16(short i16) - { - WriteVarint32(intToZigZag(i16)); - } - - /// - /// Write an i32 as a zigzag varint. - /// - public override void WriteI32(int i32) - { - WriteVarint32(intToZigZag(i32)); - } - - /// - /// Write an i64 as a zigzag varint. - /// - public override void WriteI64(long i64) - { - WriteVarint64(longToZigzag(i64)); - } - - /// - /// Write a double to the wire as 8 bytes. - /// - public override void WriteDouble(double dub) - { - byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }; - fixedLongToBytes(BitConverter.DoubleToInt64Bits(dub), data, 0); - trans.Write(data); - } - - /// - /// Write a string to the wire with a varint size preceding. - /// - public override void WriteString(string str) - { - byte[] bytes = UTF8Encoding.UTF8.GetBytes(str); - WriteBinary(bytes, 0, bytes.Length); - } - - /// - /// Write a byte array, using a varint for the size. - /// - public override void WriteBinary(byte[] bin) - { - WriteBinary(bin, 0, bin.Length); - } - - private void WriteBinary(byte[] buf, int offset, int length) - { - WriteVarint32((uint)length); - trans.Write(buf, offset, length); - } - - // - // These methods are called by structs, but don't actually have any wire - // output or purpose. - // - - public override void WriteMessageEnd() { } - public override void WriteMapEnd() { } - public override void WriteListEnd() { } - public override void WriteSetEnd() { } - public override void WriteFieldEnd() { } - - // - // 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(TType elemType, int size) - { - if (size <= 14) - { - WriteByteDirect(size << 4 | getCompactType(elemType)); - } - else - { - WriteByteDirect(0xf0 | getCompactType(elemType)); - WriteVarint32((uint)size); - } - } - - /// - /// Write an i64 as a varint. Results in 1-10 bytes on the wire. - /// - byte[] varint64out = new byte[10]; - private void WriteVarint64(ulong n) - { - int idx = 0; - while (true) - { - if ((n & ~(ulong)0x7FL) == 0) - { - varint64out[idx++] = (byte)n; - break; - } - else - { - varint64out[idx++] = ((byte)((n & 0x7F) | 0x80)); - n >>= 7; - } - } - trans.Write(varint64out, 0, idx); - } - - /// - /// Convert l into a zigzag long. This allows negative numbers to be - /// represented compactly as a varint. - /// - private ulong longToZigzag(long n) - { - return (ulong)(n << 1) ^ (ulong)(n >> 63); - } - - /// - /// Convert n into a zigzag int. This allows negative numbers to be - /// represented compactly as a varint. - /// - private uint intToZigZag(int n) - { - return (uint)(n << 1) ^ (uint)(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); - } - - #endregion - - #region ReadMethods - - /// - /// Read a message header. - /// - public override TMessage ReadMessageBegin() - { - byte protocolId = (byte)ReadByte(); - if (protocolId != PROTOCOL_ID) - { - throw new TProtocolException("Expected protocol id " + PROTOCOL_ID.ToString("X") + " but got " + protocolId.ToString("X")); - } - byte versionAndType = (byte)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 = (int)ReadVarint32(); - string messageName = ReadString(); - return new TMessage(messageName, (TMessageType)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 override TStruct ReadStructBegin() - { - 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 override void ReadStructEnd() - { - // consume the last field we Read off the wire. - lastFieldId_ = lastField_.Pop(); - } - - /// - /// Read a field header off the wire. - /// - public override TField ReadFieldBegin() - { - byte type = (byte)ReadByte(); - - // if it's a stop, then we can return immediately, as the struct is over. - if (type == Types.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 ? true : 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 override TMap ReadMapBegin() - { - int size = (int)ReadVarint32(); - byte keyAndValueType = size == 0 ? (byte)0 : (byte)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 override TList ReadListBegin() - { - byte size_and_type = (byte)ReadByte(); - int size = (size_and_type >> 4) & 0x0f; - if (size == 15) - { - size = (int)ReadVarint32(); - } - TType 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 override TSet ReadSetBegin() - { - 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 override Boolean ReadBool() - { - if (boolValue_ != null) - { - bool result = boolValue_.Value; - boolValue_ = null; - return result; - } - return ReadByte() == Types.BOOLEAN_TRUE; - } - - byte[] byteRawBuf = new byte[1]; - /// - /// Read a single byte off the wire. Nothing interesting here. - /// - public override sbyte ReadByte() - { - trans.ReadAll(byteRawBuf, 0, 1); - return (sbyte)byteRawBuf[0]; - } - - /// - /// Read an i16 from the wire as a zigzag varint. - /// - public override short ReadI16() - { - return (short)zigzagToInt(ReadVarint32()); - } - - /// - /// Read an i32 from the wire as a zigzag varint. - /// - public override int ReadI32() - { - return zigzagToInt(ReadVarint32()); - } - - /// - /// Read an i64 from the wire as a zigzag varint. - /// - public override long ReadI64() - { - return zigzagToLong(ReadVarint64()); - } - - /// - /// No magic here - just Read a double off the wire. - /// - public override double ReadDouble() - { - byte[] longBits = new byte[8]; - trans.ReadAll(longBits, 0, 8); - return BitConverter.Int64BitsToDouble(bytesToLong(longBits)); - } - - /// - /// Reads a byte[] (via ReadBinary), and then UTF-8 decodes it. - /// - public override string ReadString() - { - int length = (int)ReadVarint32(); - - if (length == 0) - { - return ""; - } - - return Encoding.UTF8.GetString(ReadBinary(length)); - } - - /// - /// Read a byte[] from the wire. - /// - public override byte[] ReadBinary() - { - int length = (int)ReadVarint32(); - if (length == 0) return new byte[0]; - - byte[] buf = new byte[length]; - trans.ReadAll(buf, 0, length); - return buf; - } - - /// - /// Read a byte[] of a known length from the wire. - /// - private byte[] ReadBinary(int length) - { - if (length == 0) return new byte[0]; - - byte[] buf = new byte[length]; - trans.ReadAll(buf, 0, length); - return buf; - } - - // - // These methods are here for the struct to call, but don't have any wire - // encoding. - // - public override void ReadMessageEnd() { } - public override void ReadFieldEnd() { } - public override void ReadMapEnd() { } - public override void ReadListEnd() { } - public override void ReadSetEnd() { } - - // - // 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 uint ReadVarint32() - { - uint result = 0; - int shift = 0; - while (true) - { - byte b = (byte)ReadByte(); - result |= (uint)(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 ulong ReadVarint64() - { - int shift = 0; - ulong result = 0; - while (true) - { - byte b = (byte)ReadByte(); - result |= (ulong)(b & 0x7f) << shift; - if ((b & 0x80) != 0x80) break; - shift += 7; - } - - return result; - } - - #endregion - - // - // encoding helpers - // - - /// - /// Convert from zigzag int to int. - /// - private int zigzagToInt(uint n) - { - return (int)(n >> 1) ^ (-(int)(n & 1)); - } - - /// - /// Convert from zigzag long to long. - /// - private long zigzagToLong(ulong n) - { - return (long)(n >> 1) ^ (-(long)(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 TType getTType(byte type) - { - switch ((byte)(type & 0x0f)) - { - case Types.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(TType ttype) - { - return ttypeToCompactType[(int)ttype]; - } - } -} diff --git a/lib/csharp/src/Protocol/TField.cs b/lib/csharp/src/Protocol/TField.cs deleted file mode 100644 index 81795577ec8..00000000000 --- a/lib/csharp/src/Protocol/TField.cs +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Thrift.Protocol -{ - public struct TField - { - private string name; - private TType type; - private short id; - - public TField(string name, TType type, short id) - :this() - { - this.name = name; - this.type = type; - this.id = id; - } - - public string Name - { - get { return name; } - set { name = value; } - } - - public TType Type - { - get { return type; } - set { type = value; } - } - - public short ID - { - get { return id; } - set { id = value; } - } - } -} diff --git a/lib/csharp/src/Protocol/TJSONProtocol.cs b/lib/csharp/src/Protocol/TJSONProtocol.cs deleted file mode 100644 index 9dbdea9aae0..00000000000 --- a/lib/csharp/src/Protocol/TJSONProtocol.cs +++ /dev/null @@ -1,1124 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.IO; -using System.Text; -using System.Collections.Generic; - -using Thrift.Transport; -using System.Globalization; - -namespace Thrift.Protocol -{ - /// - /// 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. - /// - /// Adapted from the Java version. - /// - public class TJSONProtocol : TProtocol - { - /// - /// Factory for JSON protocol objects. - /// - public class Factory : TProtocolFactory - { - public TProtocol GetProtocol(TTransport trans) - { - return new TJSONProtocol(trans); - } - } - - private static byte[] COMMA = new byte[] { (byte)',' }; - private static byte[] COLON = new byte[] { (byte)':' }; - private static byte[] LBRACE = new byte[] { (byte)'{' }; - private static byte[] RBRACE = new byte[] { (byte)'}' }; - private static byte[] LBRACKET = new byte[] { (byte)'[' }; - private static byte[] RBRACKET = new byte[] { (byte)']' }; - private static byte[] QUOTE = new byte[] { (byte)'"' }; - private static byte[] BACKSLASH = new byte[] { (byte)'\\' }; - - private byte[] ESCSEQ = new byte[] { (byte)'\\', (byte)'u', (byte)'0', (byte)'0' }; - - private const long VERSION = 1; - private byte[] JSON_CHAR_TABLE = { - 0, 0, 0, 0, 0, 0, 0, 0,(byte)'b',(byte)'t',(byte)'n', 0,(byte)'f',(byte)'r', 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1,(byte)'"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - }; - - private char[] ESCAPE_CHARS = "\"\\/bfnrt".ToCharArray(); - - private byte[] ESCAPE_CHAR_VALS = { - (byte)'"', (byte)'\\', (byte)'/', (byte)'\b', (byte)'\f', (byte)'\n', (byte)'\r', (byte)'\t', - }; - - private const int DEF_STRING_SIZE = 16; - - private static byte[] NAME_BOOL = new byte[] { (byte)'t', (byte)'f' }; - private static byte[] NAME_BYTE = new byte[] { (byte)'i', (byte)'8' }; - private static byte[] NAME_I16 = new byte[] { (byte)'i', (byte)'1', (byte)'6' }; - private static byte[] NAME_I32 = new byte[] { (byte)'i', (byte)'3', (byte)'2' }; - private static byte[] NAME_I64 = new byte[] { (byte)'i', (byte)'6', (byte)'4' }; - private static byte[] NAME_DOUBLE = new byte[] { (byte)'d', (byte)'b', (byte)'l' }; - private static byte[] NAME_STRUCT = new byte[] { (byte)'r', (byte)'e', (byte)'c' }; - private static byte[] NAME_STRING = new byte[] { (byte)'s', (byte)'t', (byte)'r' }; - private static byte[] NAME_MAP = new byte[] { (byte)'m', (byte)'a', (byte)'p' }; - private static byte[] NAME_LIST = new byte[] { (byte)'l', (byte)'s', (byte)'t' }; - private static byte[] NAME_SET = new byte[] { (byte)'s', (byte)'e', (byte)'t' }; - - private static byte[] GetTypeNameForTypeID(TType typeID) - { - 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 TType GetTypeIDForTypeName(byte[] name) - { - TType result = TType.Stop; - if (name.Length > 1) - { - switch (name[0]) - { - case (byte)'d': - result = TType.Double; - break; - case (byte)'i': - switch (name[1]) - { - case (byte)'8': - result = TType.Byte; - break; - case (byte)'1': - result = TType.I16; - break; - case (byte)'3': - result = TType.I32; - break; - case (byte)'6': - result = TType.I64; - break; - } - break; - case (byte)'l': - result = TType.List; - break; - case (byte)'m': - result = TType.Map; - break; - case (byte)'r': - result = TType.Struct; - break; - case (byte)'s': - if (name[1] == (byte)'t') - { - result = TType.String; - } - else if (name[1] == (byte)'e') - { - result = TType.Set; - } - break; - case (byte)'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 TJSONProtocol proto; - - public JSONBaseContext(TJSONProtocol proto) - { - this.proto = proto; - } - - public virtual void Write() { } - - public virtual void Read() { } - - public virtual bool EscapeNumbers() { return false; } - } - - /// - /// Context for JSON lists. Will insert/Read commas before each item except - /// for the first one - /// - protected class JSONListContext : JSONBaseContext - { - public JSONListContext(TJSONProtocol protocol) - : base(protocol) - { - - } - - private bool first = true; - - public override void Write() - { - if (first) - { - first = false; - } - else - { - proto.trans.Write(COMMA); - } - } - - public override void Read() - { - if (first) - { - first = false; - } - else - { - proto.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 : JSONBaseContext - { - public JSONPairContext(TJSONProtocol proto) - : base(proto) - { - - } - - private bool first = true; - private bool colon = true; - - public override void Write() - { - if (first) - { - first = false; - colon = true; - } - else - { - proto.trans.Write(colon ? COLON : COMMA); - colon = !colon; - } - } - - public override void Read() - { - if (first) - { - first = false; - colon = true; - } - else - { - proto.ReadJSONSyntaxChar(colon ? COLON : COMMA); - colon = !colon; - } - } - - public override bool EscapeNumbers() - { - return colon; - } - } - - /// - /// Holds up to one byte from the transport - /// - protected class LookaheadReader - { - protected TJSONProtocol proto; - - public LookaheadReader(TJSONProtocol proto) - { - this.proto = proto; - } - - private bool 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. - /// - public byte Read() - { - if (hasData) - { - hasData = false; - } - else - { - proto.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. - /// - public byte Peek() - { - if (!hasData) - { - proto.trans.ReadAll(data, 0, 1); - } - hasData = true; - return data[0]; - } - } - - // Default encoding - protected Encoding utf8Encoding = UTF8Encoding.UTF8; - - // Stack of nested contexts that we may be in - protected Stack contextStack = new Stack(); - - // Current context that we are in - protected JSONBaseContext context; - - // Reader that manages a 1-byte buffer - protected LookaheadReader reader; - - /// - /// Push a new JSON context onto the stack. - /// - protected void PushContext(JSONBaseContext c) - { - contextStack.Push(context); - context = c; - } - - /// - /// Pop the last JSON context off the stack - /// - protected void PopContext() - { - context = contextStack.Pop(); - } - - /// - /// TJSONProtocol Constructor - /// - public TJSONProtocol(TTransport trans) - : base(trans) - { - context = new JSONBaseContext(this); - reader = new LookaheadReader(this); - } - - // Temporary buffer used by several methods - private byte[] tempBuffer = 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) - { - 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 byte HexVal(byte ch) - { - if ((ch >= '0') && (ch <= '9')) - { - return (byte)((char)ch - '0'); - } - else if ((ch >= 'a') && (ch <= 'f')) - { - ch += 10; - return (byte)((char)ch - 'a'); - } - else - { - throw new TProtocolException(TProtocolException.INVALID_DATA, - "Expected hex character"); - } - } - - /// - /// Convert a byte containing a hex value to its corresponding hex character - /// - private static byte HexChar(byte val) - { - val &= 0x0F; - if (val < 10) - { - return (byte)((char)val + '0'); - } - else - { - val -= 10; - return (byte)((char)val + 'a'); - } - } - - /// - /// Write the bytes in array buf as a JSON characters, escaping as needed - /// - private void WriteJSONString(byte[] b) - { - 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 - { - tempBuffer[0] = JSON_CHAR_TABLE[b[i]]; - if (tempBuffer[0] == 1) - { - trans.Write(b, i, 1); - } - else if (tempBuffer[0] > 1) - { - trans.Write(BACKSLASH); - trans.Write(tempBuffer, 0, 1); - } - else - { - trans.Write(ESCSEQ); - tempBuffer[0] = HexChar((byte)(b[i] >> 4)); - tempBuffer[1] = HexChar(b[i]); - trans.Write(tempBuffer, 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) - { - context.Write(); - string str = num.ToString(); - - bool escapeNum = context.EscapeNumbers(); - if (escapeNum) - trans.Write(QUOTE); - - trans.Write(utf8Encoding.GetBytes(str)); - - 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) - { - context.Write(); - string str = num.ToString("G17", CultureInfo.InvariantCulture); - bool special = false; - - switch (str[0]) - { - case 'N': // NaN - case 'I': // Infinity - special = true; - break; - case '-': - if (str[1] == 'I') - { // -Infinity - special = true; - } - break; - } - - bool escapeNum = special || context.EscapeNumbers(); - - if (escapeNum) - trans.Write(QUOTE); - - trans.Write(utf8Encoding.GetBytes(str)); - - 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) - { - context.Write(); - trans.Write(QUOTE); - - int len = b.Length; - int off = 0; - - while (len >= 3) - { - // Encode 3 bytes at a time - TBase64Utils.encode(b, off, 3, tempBuffer, 0); - trans.Write(tempBuffer, 0, 4); - off += 3; - len -= 3; - } - if (len > 0) - { - // Encode remainder - TBase64Utils.encode(b, off, len, tempBuffer, 0); - trans.Write(tempBuffer, 0, len + 1); - } - - trans.Write(QUOTE); - } - - private void WriteJSONObjectStart() - { - context.Write(); - trans.Write(LBRACE); - PushContext(new JSONPairContext(this)); - } - - private void WriteJSONObjectEnd() - { - PopContext(); - trans.Write(RBRACE); - } - - private void WriteJSONArrayStart() - { - context.Write(); - trans.Write(LBRACKET); - PushContext(new JSONListContext(this)); - } - - private void WriteJSONArrayEnd() - { - PopContext(); - trans.Write(RBRACKET); - } - - public override void WriteMessageBegin(TMessage message) - { - WriteJSONArrayStart(); - WriteJSONInteger(VERSION); - - byte[] b = utf8Encoding.GetBytes(message.Name); - WriteJSONString(b); - - WriteJSONInteger((long)message.Type); - WriteJSONInteger(message.SeqID); - } - - public override void WriteMessageEnd() - { - WriteJSONArrayEnd(); - } - - public override void WriteStructBegin(TStruct str) - { - WriteJSONObjectStart(); - } - - public override void WriteStructEnd() - { - WriteJSONObjectEnd(); - } - - public override void WriteFieldBegin(TField field) - { - WriteJSONInteger(field.ID); - WriteJSONObjectStart(); - WriteJSONString(GetTypeNameForTypeID(field.Type)); - } - - public override void WriteFieldEnd() - { - WriteJSONObjectEnd(); - } - - public override void WriteFieldStop() { } - - public override void WriteMapBegin(TMap map) - { - WriteJSONArrayStart(); - WriteJSONString(GetTypeNameForTypeID(map.KeyType)); - WriteJSONString(GetTypeNameForTypeID(map.ValueType)); - WriteJSONInteger(map.Count); - WriteJSONObjectStart(); - } - - public override void WriteMapEnd() - { - WriteJSONObjectEnd(); - WriteJSONArrayEnd(); - } - - public override void WriteListBegin(TList list) - { - WriteJSONArrayStart(); - WriteJSONString(GetTypeNameForTypeID(list.ElementType)); - WriteJSONInteger(list.Count); - } - - public override void WriteListEnd() - { - WriteJSONArrayEnd(); - } - - public override void WriteSetBegin(TSet set) - { - WriteJSONArrayStart(); - WriteJSONString(GetTypeNameForTypeID(set.ElementType)); - WriteJSONInteger(set.Count); - } - - public override void WriteSetEnd() - { - WriteJSONArrayEnd(); - } - - public override void WriteBool(bool b) - { - WriteJSONInteger(b ? (long)1 : (long)0); - } - - public override void WriteByte(sbyte b) - { - WriteJSONInteger((long)b); - } - - public override void WriteI16(short i16) - { - WriteJSONInteger((long)i16); - } - - public override void WriteI32(int i32) - { - WriteJSONInteger((long)i32); - } - - public override void WriteI64(long i64) - { - WriteJSONInteger(i64); - } - - public override void WriteDouble(double dub) - { - WriteJSONDouble(dub); - } - - public override void WriteString(string str) - { - byte[] b = utf8Encoding.GetBytes(str); - WriteJSONString(b); - } - - public override void WriteBinary(byte[] bin) - { - WriteJSONBase64(bin); - } - - /** - * Reading methods. - */ - - /// - /// Read in a JSON string, unescaping as appropriate.. Skip Reading from the - /// context if skipContext is true. - /// - private byte[] ReadJSONString(bool skipContext) - { - MemoryStream buffer = new MemoryStream(); - List codeunits = new List(); - - - if (!skipContext) - { - context.Read(); - } - ReadJSONSyntaxChar(QUOTE); - while (true) - { - byte ch = reader.Read(); - if (ch == QUOTE[0]) - { - break; - } - - // escaped? - if (ch != ESCSEQ[0]) - { - buffer.Write(new byte[] { (byte)ch }, 0, 1); - continue; - } - - // distinguish between \uXXXX and \? - ch = reader.Read(); - if (ch != ESCSEQ[1]) // control chars like \n - { - int off = Array.IndexOf(ESCAPE_CHARS, (char)ch); - if (off == -1) - { - throw new TProtocolException(TProtocolException.INVALID_DATA, - "Expected control char"); - } - ch = ESCAPE_CHAR_VALS[off]; - buffer.Write(new byte[] { (byte)ch }, 0, 1); - continue; - } - - - // it's \uXXXX - trans.ReadAll(tempBuffer, 0, 4); - var wch = (short)((HexVal((byte)tempBuffer[0]) << 12) + - (HexVal((byte)tempBuffer[1]) << 8) + - (HexVal((byte)tempBuffer[2]) << 4) + - HexVal(tempBuffer[3])); - if (Char.IsHighSurrogate((char)wch)) - { - if (codeunits.Count > 0) - { - throw new TProtocolException(TProtocolException.INVALID_DATA, - "Expected low surrogate char"); - } - codeunits.Add((char)wch); - } - else if (Char.IsLowSurrogate((char)wch)) - { - if (codeunits.Count == 0) - { - throw new TProtocolException(TProtocolException.INVALID_DATA, - "Expected high surrogate char"); - } - codeunits.Add((char)wch); - var tmp = utf8Encoding.GetBytes(codeunits.ToArray()); - buffer.Write(tmp, 0, tmp.Length); - codeunits.Clear(); - } - else - { - var tmp = utf8Encoding.GetBytes(new char[] { (char)wch }); - buffer.Write(tmp, 0, tmp.Length); - } - } - - - if (codeunits.Count > 0) - { - throw new TProtocolException(TProtocolException.INVALID_DATA, - "Expected low surrogate char"); - } - - return buffer.ToArray(); - } - - /// - /// Return true if the given byte could be a valid part of a JSON number. - /// - private bool IsJSONNumeric(byte b) - { - switch (b) - { - case (byte)'+': - case (byte)'-': - case (byte)'.': - case (byte)'0': - case (byte)'1': - case (byte)'2': - case (byte)'3': - case (byte)'4': - case (byte)'5': - case (byte)'6': - case (byte)'7': - case (byte)'8': - case (byte)'9': - case (byte)'E': - case (byte)'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() - { - 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() - { - context.Read(); - if (context.EscapeNumbers()) - { - ReadJSONSyntaxChar(QUOTE); - } - - string str = ReadJSONNumericChars(); - if (context.EscapeNumbers()) - { - ReadJSONSyntaxChar(QUOTE); - } - - try - { - return Int64.Parse(str); - } - catch (FormatException fex) - { - throw new TProtocolException(TProtocolException.INVALID_DATA, - "Bad data encounted in numeric data", fex); - } - } - - /// - /// 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() - { - context.Read(); - if (reader.Peek() == QUOTE[0]) - { - byte[] arr = ReadJSONString(true); - double dub = Double.Parse(utf8Encoding.GetString(arr, 0, arr.Length), CultureInfo.InvariantCulture); - - if (!context.EscapeNumbers() && !Double.IsNaN(dub) && !Double.IsInfinity(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; - } - else - { - if (context.EscapeNumbers()) - { - // This will throw - we should have had a quote if escapeNum == true - ReadJSONSyntaxChar(QUOTE); - } - try - { - return Double.Parse(ReadJSONNumericChars(), CultureInfo.InvariantCulture); - } - catch (FormatException fex) - { - throw new TProtocolException(TProtocolException.INVALID_DATA, - "Bad data encounted in numeric data", fex); - } - } - } - - /// - /// Read in a JSON string containing base-64 encoded data and decode it. - /// - private byte[] ReadJSONBase64() - { - byte[] b = ReadJSONString(false); - int len = b.Length; - int off = 0; - int size = 0; - // reduce len to ignore fill bytes - while ((len > 0) && (b[len - 1] == '=')) - { - --len; - } - // read & decode full byte triplets = 4 source bytes - 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]; - Array.Copy(b, 0, result, 0, size); - return result; - } - - private void ReadJSONObjectStart() - { - context.Read(); - ReadJSONSyntaxChar(LBRACE); - PushContext(new JSONPairContext(this)); - } - - private void ReadJSONObjectEnd() - { - ReadJSONSyntaxChar(RBRACE); - PopContext(); - } - - private void ReadJSONArrayStart() - { - context.Read(); - ReadJSONSyntaxChar(LBRACKET); - PushContext(new JSONListContext(this)); - } - - private void ReadJSONArrayEnd() - { - ReadJSONSyntaxChar(RBRACKET); - PopContext(); - } - - public override TMessage ReadMessageBegin() - { - TMessage message = new TMessage(); - ReadJSONArrayStart(); - if (ReadJSONInteger() != VERSION) - { - throw new TProtocolException(TProtocolException.BAD_VERSION, - "Message contained bad version."); - } - - var buf = ReadJSONString(false); - message.Name = utf8Encoding.GetString(buf, 0, buf.Length); - message.Type = (TMessageType)ReadJSONInteger(); - message.SeqID = (int)ReadJSONInteger(); - return message; - } - - public override void ReadMessageEnd() - { - ReadJSONArrayEnd(); - } - - public override TStruct ReadStructBegin() - { - ReadJSONObjectStart(); - return new TStruct(); - } - - public override void ReadStructEnd() - { - ReadJSONObjectEnd(); - } - - public override TField ReadFieldBegin() - { - TField field = new TField(); - byte ch = reader.Peek(); - if (ch == RBRACE[0]) - { - field.Type = TType.Stop; - } - else - { - field.ID = (short)ReadJSONInteger(); - ReadJSONObjectStart(); - field.Type = GetTypeIDForTypeName(ReadJSONString(false)); - } - return field; - } - - public override void ReadFieldEnd() - { - ReadJSONObjectEnd(); - } - - public override TMap ReadMapBegin() - { - TMap map = new TMap(); - ReadJSONArrayStart(); - map.KeyType = GetTypeIDForTypeName(ReadJSONString(false)); - map.ValueType = GetTypeIDForTypeName(ReadJSONString(false)); - map.Count = (int)ReadJSONInteger(); - ReadJSONObjectStart(); - return map; - } - - public override void ReadMapEnd() - { - ReadJSONObjectEnd(); - ReadJSONArrayEnd(); - } - - public override TList ReadListBegin() - { - TList list = new TList(); - ReadJSONArrayStart(); - list.ElementType = GetTypeIDForTypeName(ReadJSONString(false)); - list.Count = (int)ReadJSONInteger(); - return list; - } - - public override void ReadListEnd() - { - ReadJSONArrayEnd(); - } - - public override TSet ReadSetBegin() - { - TSet set = new TSet(); - ReadJSONArrayStart(); - set.ElementType = GetTypeIDForTypeName(ReadJSONString(false)); - set.Count = (int)ReadJSONInteger(); - return set; - } - - public override void ReadSetEnd() - { - ReadJSONArrayEnd(); - } - - public override bool ReadBool() - { - return (ReadJSONInteger() == 0 ? false : true); - } - - public override sbyte ReadByte() - { - return (sbyte)ReadJSONInteger(); - } - - public override short ReadI16() - { - return (short)ReadJSONInteger(); - } - - public override int ReadI32() - { - return (int)ReadJSONInteger(); - } - - public override long ReadI64() - { - return (long)ReadJSONInteger(); - } - - public override double ReadDouble() - { - return ReadJSONDouble(); - } - - public override string ReadString() - { - var buf = ReadJSONString(false); - return utf8Encoding.GetString(buf, 0, buf.Length); - } - - public override byte[] ReadBinary() - { - return ReadJSONBase64(); - } - - } -} diff --git a/lib/csharp/src/Protocol/TList.cs b/lib/csharp/src/Protocol/TList.cs deleted file mode 100644 index 0c8f2144a44..00000000000 --- a/lib/csharp/src/Protocol/TList.cs +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Thrift.Protocol -{ - public struct TList - { - private TType elementType; - private int count; - - public TList(TType elementType, int count) - :this() - { - this.elementType = elementType; - this.count = count; - } - - public TType ElementType - { - get { return elementType; } - set { elementType = value; } - } - - public int Count - { - get { return count; } - set { count = value; } - } - } -} diff --git a/lib/csharp/src/Protocol/TMap.cs b/lib/csharp/src/Protocol/TMap.cs deleted file mode 100644 index aba9d3a95ec..00000000000 --- a/lib/csharp/src/Protocol/TMap.cs +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Thrift.Protocol -{ - public struct TMap - { - private TType keyType; - private TType valueType; - private int count; - - public TMap(TType keyType, TType valueType, int count) - :this() - { - this.keyType = keyType; - this.valueType = valueType; - this.count = count; - } - - public TType KeyType - { - get { return keyType; } - set { keyType = value; } - } - - public TType ValueType - { - get { return valueType; } - set { valueType = value; } - } - - public int Count - { - get { return count; } - set { count = value; } - } - } -} diff --git a/lib/csharp/src/Protocol/TMessage.cs b/lib/csharp/src/Protocol/TMessage.cs deleted file mode 100644 index 348263c375d..00000000000 --- a/lib/csharp/src/Protocol/TMessage.cs +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Thrift.Protocol -{ - public struct TMessage - { - private string name; - private TMessageType type; - private int seqID; - - public TMessage(string name, TMessageType type, int seqid) - :this() - { - this.name = name; - this.type = type; - this.seqID = seqid; - } - - public string Name - { - get { return name; } - set { name = value; } - } - - public TMessageType Type - { - get { return type; } - set { type = value; } - } - - public int SeqID - { - get { return seqID; } - set { seqID = value; } - } - } -} diff --git a/lib/csharp/src/Protocol/TMessageType.cs b/lib/csharp/src/Protocol/TMessageType.cs deleted file mode 100644 index c7091fede83..00000000000 --- a/lib/csharp/src/Protocol/TMessageType.cs +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; - -namespace Thrift.Protocol -{ - public enum TMessageType - { - Call = 1, - Reply = 2, - Exception = 3, - Oneway = 4 - } -} diff --git a/lib/csharp/src/Protocol/TMultiplexedProcessor.cs b/lib/csharp/src/Protocol/TMultiplexedProcessor.cs deleted file mode 100644 index aa91c527fed..00000000000 --- a/lib/csharp/src/Protocol/TMultiplexedProcessor.cs +++ /dev/null @@ -1,183 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Text; -using Thrift.Transport; -using System.Collections.Generic; -using System.IO; - -namespace Thrift.Protocol -{ - /// - /// is a allowing a single - /// 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 : TProcessor - { - private Dictionary ServiceProcessorMap = new Dictionary(); - - /// - /// '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. - /// - /// Args: - /// - serviceName Name of a service, has to be identical to the name - /// declared in the Thrift IDL, e.g. "WeatherReport". - /// - processor Implementation of a service, usually referred to as "handlers", - /// e.g. WeatherReportHandler implementing WeatherReport.Iface. - /// - public void RegisterProcessor(string serviceName, TProcessor processor) - { - ServiceProcessorMap.Add(serviceName, processor); - } - - - private void Fail(TProtocol oprot, TMessage message, TApplicationException.ExceptionType extype, string etxt) - { - TApplicationException appex = new TApplicationException(extype, etxt); - - TMessage newMessage = new TMessage(message.Name, TMessageType.Exception, message.SeqID); - - oprot.WriteMessageBegin(newMessage); - appex.Write(oprot); - oprot.WriteMessageEnd(); - oprot.Transport.Flush(); - } - - - /// - /// This implementation of process performs the following steps: - /// - /// - Read the beginning of the message. - /// - Extract the service name from the message. - /// - Using the service name to locate the appropriate processor. - /// - Dispatch to the processor, with a decorated instance of TProtocol - /// that allows readMessageBegin() to return the original TMessage. - /// - /// Throws an exception if - /// - the message type is not CALL or ONEWAY, - /// - the service name was not found in the message, or - /// - the service name has not been RegisterProcessor()ed. - /// - public bool Process(TProtocol iprot, TProtocol oprot) - { - /* 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. */ - - try - { - TMessage message = iprot.ReadMessageBegin(); - - if ((message.Type != TMessageType.Call) && (message.Type != TMessageType.Oneway)) - { - Fail(oprot, message, - TApplicationException.ExceptionType.InvalidMessageType, - "Message type CALL or ONEWAY expected"); - return false; - } - - // Extract the service name - int index = message.Name.IndexOf(TMultiplexedProtocol.SEPARATOR); - if (index < 0) - { - Fail(oprot, message, - TApplicationException.ExceptionType.InvalidProtocol, - "Service name not found in message name: " + message.Name + ". " + - "Did you forget to use a TMultiplexProtocol in your client?"); - return false; - } - - // Create a new TMessage, something that can be consumed by any TProtocol - string serviceName = message.Name.Substring(0, index); - TProcessor actualProcessor; - if (!ServiceProcessorMap.TryGetValue(serviceName, out actualProcessor)) - { - Fail(oprot, message, - TApplicationException.ExceptionType.InternalError, - "Service name not found: " + serviceName + ". " + - "Did you forget to call RegisterProcessor()?"); - return false; - } - - // Create a new TMessage, removing the service name - TMessage newMessage = 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, newMessage), oprot); - - } - catch (IOException) - { - return false; // similar to all other processors - } - - } - - /// - /// 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 class StoredMessageProtocol : TProtocolDecorator - { - TMessage MsgBegin; - - public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) - : base(protocol) - { - this.MsgBegin = messageBegin; - } - - public override TMessage ReadMessageBegin() - { - return MsgBegin; - } - } - - } -} diff --git a/lib/csharp/src/Protocol/TMultiplexedProtocol.cs b/lib/csharp/src/Protocol/TMultiplexedProtocol.cs deleted file mode 100644 index 1bd420fcc20..00000000000 --- a/lib/csharp/src/Protocol/TMultiplexedProtocol.cs +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Text; -using Thrift.Transport; -using System.Collections.Generic; - -namespace Thrift.Protocol -{ - - /// - /// 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 TO BE USED BY SERVERS. - /// On the server, use TMultiplexedProcessor to handle requests from a multiplexing client. - /// - /// This example uses a single socket transport to invoke two services: - /// - /// 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()); - /// - /// - public class TMultiplexedProtocol : TProtocolDecorator - { - - /// - /// Used to delimit the service name from the function name. - /// - public static string SEPARATOR = ":"; - - private string ServiceName; - - /// - /// Wrap the specified protocol, allowing it to be used to communicate with a - /// multiplexing server. The is required as it is - /// prepended to the message header so that the multiplexing server can broker - /// the function call to the proper service. - /// - /// Your communication protocol of choice, e.g. . - /// The service name of the service communicating via this protocol. - public TMultiplexedProtocol(TProtocol protocol, string serviceName) - : base(protocol) - { - ServiceName = serviceName; - } - - /// - /// Prepends the service name to the function name, separated by TMultiplexedProtocol.SEPARATOR. - /// - /// The original message. - public override void WriteMessageBegin(TMessage tMessage) - { - switch (tMessage.Type) - { - case TMessageType.Call: - case TMessageType.Oneway: - base.WriteMessageBegin(new TMessage( - ServiceName + SEPARATOR + tMessage.Name, - tMessage.Type, - tMessage.SeqID)); - break; - - default: - base.WriteMessageBegin(tMessage); - break; - } - } - } -} diff --git a/lib/csharp/src/Protocol/TProtocol.cs b/lib/csharp/src/Protocol/TProtocol.cs deleted file mode 100644 index dd7a6e06277..00000000000 --- a/lib/csharp/src/Protocol/TProtocol.cs +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Text; -using Thrift.Transport; - -namespace Thrift.Protocol -{ - public abstract class TProtocol : IDisposable - { - private const int DEFAULT_RECURSION_DEPTH = 64; - - protected TTransport trans; - protected int recursionLimit; - protected int recursionDepth; - - protected TProtocol(TTransport trans) - { - this.trans = trans; - this.recursionLimit = DEFAULT_RECURSION_DEPTH; - this.recursionDepth = 0; - } - - public TTransport Transport - { - get { return trans; } - } - - public int RecursionLimit - { - get { return recursionLimit; } - set { recursionLimit = value; } - } - - public void IncrementRecursionDepth() - { - if (recursionDepth < recursionLimit) - ++recursionDepth; - else - throw new TProtocolException(TProtocolException.DEPTH_LIMIT, "Depth limit exceeded"); - } - - public void DecrementRecursionDepth() - { - --recursionDepth; - } - - #region " IDisposable Support " - private bool _IsDisposed; - - // IDisposable - public void Dispose() - { - Dispose(true); - } - - protected virtual void Dispose(bool disposing) - { - if (!_IsDisposed) - { - if (disposing) - { - if (trans is IDisposable) - (trans as IDisposable).Dispose(); - } - } - _IsDisposed = true; - } - #endregion - - public abstract void WriteMessageBegin(TMessage message); - public abstract void WriteMessageEnd(); - public abstract void WriteStructBegin(TStruct struc); - public abstract void WriteStructEnd(); - public abstract void WriteFieldBegin(TField field); - public abstract void WriteFieldEnd(); - public abstract void WriteFieldStop(); - public abstract void WriteMapBegin(TMap map); - public abstract void WriteMapEnd(); - public abstract void WriteListBegin(TList list); - public abstract void WriteListEnd(); - public abstract void WriteSetBegin(TSet set); - public abstract void WriteSetEnd(); - public abstract void WriteBool(bool b); - public abstract void WriteByte(sbyte b); - public abstract void WriteI16(short i16); - public abstract void WriteI32(int i32); - public abstract void WriteI64(long i64); - public abstract void WriteDouble(double d); - public virtual void WriteString(string s) - { - WriteBinary(Encoding.UTF8.GetBytes(s)); - } - public abstract void WriteBinary(byte[] b); - - public abstract TMessage ReadMessageBegin(); - public abstract void ReadMessageEnd(); - public abstract TStruct ReadStructBegin(); - public abstract void ReadStructEnd(); - public abstract TField ReadFieldBegin(); - public abstract void ReadFieldEnd(); - public abstract TMap ReadMapBegin(); - public abstract void ReadMapEnd(); - public abstract TList ReadListBegin(); - public abstract void ReadListEnd(); - public abstract TSet ReadSetBegin(); - public abstract void ReadSetEnd(); - public abstract bool ReadBool(); - public abstract sbyte ReadByte(); - public abstract short ReadI16(); - public abstract int ReadI32(); - public abstract long ReadI64(); - public abstract double ReadDouble(); - public virtual string ReadString() - { - var buf = ReadBinary(); - return Encoding.UTF8.GetString(buf, 0, buf.Length); - } - public abstract byte[] ReadBinary(); - } -} diff --git a/lib/csharp/src/Protocol/TProtocolDecorator.cs b/lib/csharp/src/Protocol/TProtocolDecorator.cs deleted file mode 100644 index 86000027f51..00000000000 --- a/lib/csharp/src/Protocol/TProtocolDecorator.cs +++ /dev/null @@ -1,261 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Text; -using Thrift.Transport; -using System.Collections.Generic; - -namespace Thrift.Protocol -{ - /// - /// forwards all requests to an enclosed 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 . - /// - /// See p.175 of Design Patterns (by Gamma et al.) - /// - /// - public abstract class TProtocolDecorator : TProtocol - { - private TProtocol WrappedProtocol; - - /// - /// Encloses the specified protocol. - /// - /// All operations will be forward to this protocol. Must be non-null. - public TProtocolDecorator(TProtocol protocol) - : base(protocol.Transport) - { - - WrappedProtocol = protocol; - } - - public override void WriteMessageBegin(TMessage tMessage) - { - WrappedProtocol.WriteMessageBegin(tMessage); - } - - public override void WriteMessageEnd() - { - WrappedProtocol.WriteMessageEnd(); - } - - public override void WriteStructBegin(TStruct tStruct) - { - WrappedProtocol.WriteStructBegin(tStruct); - } - - public override void WriteStructEnd() - { - WrappedProtocol.WriteStructEnd(); - } - - public override void WriteFieldBegin(TField tField) - { - WrappedProtocol.WriteFieldBegin(tField); - } - - public override void WriteFieldEnd() - { - WrappedProtocol.WriteFieldEnd(); - } - - public override void WriteFieldStop() - { - WrappedProtocol.WriteFieldStop(); - } - - public override void WriteMapBegin(TMap tMap) - { - WrappedProtocol.WriteMapBegin(tMap); - } - - public override void WriteMapEnd() - { - WrappedProtocol.WriteMapEnd(); - } - - public override void WriteListBegin(TList tList) - { - WrappedProtocol.WriteListBegin(tList); - } - - public override void WriteListEnd() - { - WrappedProtocol.WriteListEnd(); - } - - public override void WriteSetBegin(TSet tSet) - { - WrappedProtocol.WriteSetBegin(tSet); - } - - public override void WriteSetEnd() - { - WrappedProtocol.WriteSetEnd(); - } - - public override void WriteBool(bool b) - { - WrappedProtocol.WriteBool(b); - } - - public override void WriteByte(sbyte b) - { - WrappedProtocol.WriteByte(b); - } - - public override void WriteI16(short i) - { - WrappedProtocol.WriteI16(i); - } - - public override void WriteI32(int i) - { - WrappedProtocol.WriteI32(i); - } - - public override void WriteI64(long l) - { - WrappedProtocol.WriteI64(l); - } - - public override void WriteDouble(double v) - { - WrappedProtocol.WriteDouble(v); - } - - public override void WriteString(string s) - { - WrappedProtocol.WriteString(s); - } - - public override void WriteBinary(byte[] bytes) - { - WrappedProtocol.WriteBinary(bytes); - } - - public override TMessage ReadMessageBegin() - { - return WrappedProtocol.ReadMessageBegin(); - } - - public override void ReadMessageEnd() - { - WrappedProtocol.ReadMessageEnd(); - } - - public override TStruct ReadStructBegin() - { - return WrappedProtocol.ReadStructBegin(); - } - - public override void ReadStructEnd() - { - WrappedProtocol.ReadStructEnd(); - } - - public override TField ReadFieldBegin() - { - return WrappedProtocol.ReadFieldBegin(); - } - - public override void ReadFieldEnd() - { - WrappedProtocol.ReadFieldEnd(); - } - - public override TMap ReadMapBegin() - { - return WrappedProtocol.ReadMapBegin(); - } - - public override void ReadMapEnd() - { - WrappedProtocol.ReadMapEnd(); - } - - public override TList ReadListBegin() - { - return WrappedProtocol.ReadListBegin(); - } - - public override void ReadListEnd() - { - WrappedProtocol.ReadListEnd(); - } - - public override TSet ReadSetBegin() - { - return WrappedProtocol.ReadSetBegin(); - } - - public override void ReadSetEnd() - { - WrappedProtocol.ReadSetEnd(); - } - - public override bool ReadBool() - { - return WrappedProtocol.ReadBool(); - } - - public override sbyte ReadByte() - { - return WrappedProtocol.ReadByte(); - } - - public override short ReadI16() - { - return WrappedProtocol.ReadI16(); - } - - public override int ReadI32() - { - return WrappedProtocol.ReadI32(); - } - - public override long ReadI64() - { - return WrappedProtocol.ReadI64(); - } - - public override double ReadDouble() - { - return WrappedProtocol.ReadDouble(); - } - - public override string ReadString() - { - return WrappedProtocol.ReadString(); - } - - public override byte[] ReadBinary() - { - return WrappedProtocol.ReadBinary(); - } - } - -} diff --git a/lib/csharp/src/Protocol/TProtocolException.cs b/lib/csharp/src/Protocol/TProtocolException.cs deleted file mode 100644 index 7bef236857b..00000000000 --- a/lib/csharp/src/Protocol/TProtocolException.cs +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; - -namespace Thrift.Protocol -{ - public class TProtocolException : TException - { - public const int UNKNOWN = 0; - public const int INVALID_DATA = 1; - public const int NEGATIVE_SIZE = 2; - public const int SIZE_LIMIT = 3; - public const int BAD_VERSION = 4; - public const int NOT_IMPLEMENTED = 5; - public const int DEPTH_LIMIT = 6; - - protected int type_ = UNKNOWN; - - public TProtocolException() - : base() - { - } - - public TProtocolException(int type, Exception inner = null) - : base(string.Empty, inner) - { - type_ = type; - } - - public TProtocolException(int type, string message, Exception inner = null) - : base(message, inner) - { - type_ = type; - } - - public TProtocolException(string message, Exception inner = null) - : base(message, inner) - { - } - - public int getType() - { - return type_; - } - } -} diff --git a/lib/csharp/src/Protocol/TProtocolFactory.cs b/lib/csharp/src/Protocol/TProtocolFactory.cs deleted file mode 100644 index 71360a19ae9..00000000000 --- a/lib/csharp/src/Protocol/TProtocolFactory.cs +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using Thrift.Transport; - -namespace Thrift.Protocol -{ - public interface TProtocolFactory - { - TProtocol GetProtocol(TTransport trans); - } -} diff --git a/lib/csharp/src/Protocol/TProtocolUtil.cs b/lib/csharp/src/Protocol/TProtocolUtil.cs deleted file mode 100644 index d995c6ce76b..00000000000 --- a/lib/csharp/src/Protocol/TProtocolUtil.cs +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; - -namespace Thrift.Protocol -{ - public static class TProtocolUtil - { - public static void Skip(TProtocol prot, TType type) - { - prot.IncrementRecursionDepth(); - try - { - 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: - // Don't try to decode the string, just skip it. - prot.ReadBinary(); - break; - case TType.Struct: - prot.ReadStructBegin(); - while (true) - { - TField field = prot.ReadFieldBegin(); - if (field.Type == TType.Stop) - { - break; - } - Skip(prot, field.Type); - prot.ReadFieldEnd(); - } - prot.ReadStructEnd(); - break; - case TType.Map: - TMap map = prot.ReadMapBegin(); - for (int i = 0; i < map.Count; i++) - { - Skip(prot, map.KeyType); - Skip(prot, map.ValueType); - } - prot.ReadMapEnd(); - break; - case TType.Set: - TSet set = prot.ReadSetBegin(); - for (int i = 0; i < set.Count; i++) - { - Skip(prot, set.ElementType); - } - prot.ReadSetEnd(); - break; - case TType.List: - TList list = prot.ReadListBegin(); - for (int i = 0; i < list.Count; i++) - { - Skip(prot, list.ElementType); - } - prot.ReadListEnd(); - break; - default: - throw new TProtocolException(TProtocolException.INVALID_DATA, "Unknown data type " + type.ToString("d")); - } - } - finally - { - prot.DecrementRecursionDepth(); - } - } - } -} diff --git a/lib/csharp/src/Protocol/TSet.cs b/lib/csharp/src/Protocol/TSet.cs deleted file mode 100644 index a918ab53729..00000000000 --- a/lib/csharp/src/Protocol/TSet.cs +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Thrift.Protocol -{ - public struct TSet - { - private TType elementType; - private int count; - - public TSet(TType elementType, int count) - :this() - { - this.elementType = elementType; - this.count = count; - } - - public TSet(TList list) - : this(list.ElementType, list.Count) - { - } - - public TType ElementType - { - get { return elementType; } - set { elementType = value; } - } - - public int Count - { - get { return count; } - set { count = value; } - } - } -} diff --git a/lib/csharp/src/Protocol/TStruct.cs b/lib/csharp/src/Protocol/TStruct.cs deleted file mode 100644 index f4844a4c9d0..00000000000 --- a/lib/csharp/src/Protocol/TStruct.cs +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Thrift.Protocol -{ - public struct TStruct - { - private string name; - - public TStruct(string name) - :this() - { - this.name = name; - } - - public string Name - { - get { return name; } - set { name = value; } - } - } -} diff --git a/lib/csharp/src/Protocol/TType.cs b/lib/csharp/src/Protocol/TType.cs deleted file mode 100644 index 9ce915e0897..00000000000 --- a/lib/csharp/src/Protocol/TType.cs +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; - -namespace Thrift.Protocol -{ - public enum TType : byte - { - Stop = 0, - Void = 1, - Bool = 2, - Byte = 3, - Double = 4, - I16 = 6, - I32 = 8, - I64 = 10, - String = 11, - Struct = 12, - Map = 13, - Set = 14, - List = 15 - } -} diff --git a/lib/csharp/src/Server/TServer.cs b/lib/csharp/src/Server/TServer.cs deleted file mode 100644 index 2bc04f3a045..00000000000 --- a/lib/csharp/src/Server/TServer.cs +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using Thrift.Protocol; -using Thrift.Transport; -using System.IO; - -namespace Thrift.Server -{ - public abstract class TServer - { - //Attributes - protected TProcessorFactory processorFactory; - protected TServerTransport serverTransport; - protected TTransportFactory inputTransportFactory; - protected TTransportFactory outputTransportFactory; - protected TProtocolFactory inputProtocolFactory; - protected TProtocolFactory outputProtocolFactory; - protected TServerEventHandler serverEventHandler = null; - - //Methods - public void setEventHandler(TServerEventHandler seh) - { - serverEventHandler = seh; - } - public TServerEventHandler getEventHandler() - { - return serverEventHandler; - } - - //Log delegation - public delegate void LogDelegate(string str); - private LogDelegate _logDelegate; - protected LogDelegate logDelegate - { - get { return _logDelegate; } - set { _logDelegate = (value != null) ? value : DefaultLogDelegate; } - } - protected static void DefaultLogDelegate(string s) - { - Console.Error.WriteLine(s); - } - - //Construction - public TServer(TProcessor processor, - TServerTransport serverTransport) - : this(processor, serverTransport, - new TTransportFactory(), - new TTransportFactory(), - new TBinaryProtocol.Factory(), - new TBinaryProtocol.Factory(), - DefaultLogDelegate) - { - } - - public TServer(TProcessor processor, - TServerTransport serverTransport, - LogDelegate logDelegate) - : this(processor, - serverTransport, - new TTransportFactory(), - new TTransportFactory(), - new TBinaryProtocol.Factory(), - new TBinaryProtocol.Factory(), - logDelegate) - { - } - - public TServer(TProcessor processor, - TServerTransport serverTransport, - TTransportFactory transportFactory) - : this(processor, - serverTransport, - transportFactory, - transportFactory, - new TBinaryProtocol.Factory(), - new TBinaryProtocol.Factory(), - DefaultLogDelegate) - { - } - - public TServer(TProcessor processor, - TServerTransport serverTransport, - TTransportFactory transportFactory, - TProtocolFactory protocolFactory) - : this(processor, - serverTransport, - transportFactory, - transportFactory, - protocolFactory, - protocolFactory, - DefaultLogDelegate) - { - } - - public TServer(TProcessor processor, - TServerTransport serverTransport, - TTransportFactory inputTransportFactory, - TTransportFactory outputTransportFactory, - TProtocolFactory inputProtocolFactory, - TProtocolFactory outputProtocolFactory, - LogDelegate logDelegate) - { - this.processorFactory = new TSingletonProcessorFactory(processor); - this.serverTransport = serverTransport; - this.inputTransportFactory = inputTransportFactory; - this.outputTransportFactory = outputTransportFactory; - this.inputProtocolFactory = inputProtocolFactory; - this.outputProtocolFactory = outputProtocolFactory; - this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate; - } - - public TServer(TProcessorFactory processorFactory, - TServerTransport serverTransport, - TTransportFactory inputTransportFactory, - TTransportFactory outputTransportFactory, - TProtocolFactory inputProtocolFactory, - TProtocolFactory outputProtocolFactory, - LogDelegate logDelegate) - { - this.processorFactory = processorFactory; - this.serverTransport = serverTransport; - this.inputTransportFactory = inputTransportFactory; - this.outputTransportFactory = outputTransportFactory; - this.inputProtocolFactory = inputProtocolFactory; - this.outputProtocolFactory = outputProtocolFactory; - this.logDelegate = (logDelegate != null) ? logDelegate : DefaultLogDelegate; - } - - //Abstract Interface - public abstract void Serve(); - public abstract void Stop(); - } -} diff --git a/lib/csharp/src/Server/TServerEventHandler.cs b/lib/csharp/src/Server/TServerEventHandler.cs deleted file mode 100644 index e81efc6af9b..00000000000 --- a/lib/csharp/src/Server/TServerEventHandler.cs +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; - -namespace Thrift.Server -{ - /// - /// Interface implemented by server users to handle events from the server. - /// - public interface TServerEventHandler - { - /// - /// Called before the server begins. - /// - void preServe(); - - /// - /// Called when a new client has connected and is about to being processing. - /// - object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output); - - /// - /// Called when a client has finished request-handling to delete server context. - /// - void deleteContext(object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output); - - /// - /// Called when a client is about to call the processor. - /// - void processContext(object serverContext, Thrift.Transport.TTransport transport); - }; -} diff --git a/lib/csharp/src/Server/TSimpleServer.cs b/lib/csharp/src/Server/TSimpleServer.cs deleted file mode 100644 index 4e7ea96f4af..00000000000 --- a/lib/csharp/src/Server/TSimpleServer.cs +++ /dev/null @@ -1,180 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using Thrift.Transport; -using Thrift.Protocol; - -namespace Thrift.Server -{ - /// - /// Simple single-threaded server for testing. - /// - public class TSimpleServer : TServer - { - private bool stop = false; - - public TSimpleServer(TProcessor processor, - TServerTransport serverTransport) - : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), DefaultLogDelegate) - { - } - - public TSimpleServer(TProcessor processor, - TServerTransport serverTransport, - LogDelegate logDel) - : base(processor, serverTransport, new TTransportFactory(), new TTransportFactory(), new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), logDel) - { - } - - public TSimpleServer(TProcessor processor, - TServerTransport serverTransport, - TTransportFactory transportFactory) - : base(processor, - serverTransport, - transportFactory, - transportFactory, - new TBinaryProtocol.Factory(), - new TBinaryProtocol.Factory(), - DefaultLogDelegate) - { - } - - public TSimpleServer(TProcessor processor, - TServerTransport serverTransport, - TTransportFactory transportFactory, - TProtocolFactory protocolFactory) - : base(processor, - serverTransport, - transportFactory, - transportFactory, - protocolFactory, - protocolFactory, - DefaultLogDelegate) - { - } - - public TSimpleServer(TProcessorFactory processorFactory, - TServerTransport serverTransport, - TTransportFactory transportFactory, - TProtocolFactory protocolFactory) - : base(processorFactory, - serverTransport, - transportFactory, - transportFactory, - protocolFactory, - protocolFactory, - DefaultLogDelegate) - { - } - - public override void Serve() - { - try - { - serverTransport.Listen(); - } - catch (TTransportException ttx) - { - logDelegate(ttx.ToString()); - return; - } - - //Fire the preServe server event when server is up but before any client connections - if (serverEventHandler != null) - serverEventHandler.preServe(); - - while (!stop) - { - TProcessor processor = null; - TTransport client = null; - TTransport inputTransport = null; - TTransport outputTransport = null; - TProtocol inputProtocol = null; - TProtocol outputProtocol = null; - object connectionContext = null; - try - { - using (client = serverTransport.Accept()) - { - processor = processorFactory.GetProcessor(client); - if (client != null) - { - using (inputTransport = inputTransportFactory.GetTransport(client)) - { - using (outputTransport = outputTransportFactory.GetTransport(client)) - { - inputProtocol = inputProtocolFactory.GetProtocol(inputTransport); - outputProtocol = outputProtocolFactory.GetProtocol(outputTransport); - - //Recover event handler (if any) and fire createContext server event when a client connects - if (serverEventHandler != null) - connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol); - - //Process client requests until client disconnects - while (!stop) - { - if (!inputTransport.Peek()) - break; - - //Fire processContext server event - //N.B. This is the pattern implemented in C++ and the event fires provisionally. - //That is to say it may be many minutes between the event firing and the client request - //actually arriving or the client may hang up without ever makeing a request. - if (serverEventHandler != null) - serverEventHandler.processContext(connectionContext, inputTransport); - //Process client request (blocks until transport is readable) - if (!processor.Process(inputProtocol, outputProtocol)) - break; - } - } - } - } - } - } - catch (TTransportException ttx) - { - if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted) - { - logDelegate(ttx.ToString()); - } - } - catch (Exception x) - { - //Unexpected - logDelegate(x.ToString()); - } - - //Fire deleteContext server event after client disconnects - if (serverEventHandler != null) - serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol); - } - } - - public override void Stop() - { - stop = true; - serverTransport.Close(); - } - } -} diff --git a/lib/csharp/src/Server/TThreadPoolServer.cs b/lib/csharp/src/Server/TThreadPoolServer.cs deleted file mode 100644 index a494ce7bddd..00000000000 --- a/lib/csharp/src/Server/TThreadPoolServer.cs +++ /dev/null @@ -1,295 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Threading; -using Thrift.Protocol; -using Thrift.Transport; - -namespace Thrift.Server -{ - /// - /// Server that uses C# built-in ThreadPool to spawn threads when handling requests. - /// - public class TThreadPoolServer : TServer - { - private const int DEFAULT_MIN_THREADS = -1; // use .NET ThreadPool defaults - private const int DEFAULT_MAX_THREADS = -1; // use .NET ThreadPool defaults - private volatile bool stop = false; - - public struct Configuration - { - public int MinWorkerThreads; - public int MaxWorkerThreads; - public int MinIOThreads; - public int MaxIOThreads; - - public Configuration(int min = DEFAULT_MIN_THREADS, int max = DEFAULT_MAX_THREADS) - { - MinWorkerThreads = min; - MaxWorkerThreads = max; - MinIOThreads = min; - MaxIOThreads = max; - } - - public Configuration(int minWork, int maxWork, int minIO, int maxIO) - { - MinWorkerThreads = minWork; - MaxWorkerThreads = maxWork; - MinIOThreads = minIO; - MaxIOThreads = maxIO; - } - } - - public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport) - : this(new TSingletonProcessorFactory(processor), serverTransport, - new TTransportFactory(), new TTransportFactory(), - new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), - new Configuration(), DefaultLogDelegate) - { - } - - public TThreadPoolServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate) - : this(new TSingletonProcessorFactory(processor), serverTransport, - new TTransportFactory(), new TTransportFactory(), - new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), - new Configuration(), logDelegate) - { - } - - public TThreadPoolServer(TProcessor processor, - TServerTransport serverTransport, - TTransportFactory transportFactory, - TProtocolFactory protocolFactory) - : this(new TSingletonProcessorFactory(processor), serverTransport, - transportFactory, transportFactory, - protocolFactory, protocolFactory, - new Configuration(), DefaultLogDelegate) - { - } - - public TThreadPoolServer(TProcessorFactory processorFactory, - TServerTransport serverTransport, - TTransportFactory transportFactory, - TProtocolFactory protocolFactory) - : this(processorFactory, serverTransport, - transportFactory, transportFactory, - protocolFactory, protocolFactory, - new Configuration(), DefaultLogDelegate) - { - } - - public TThreadPoolServer(TProcessorFactory processorFactory, - TServerTransport serverTransport, - TTransportFactory inputTransportFactory, - TTransportFactory outputTransportFactory, - TProtocolFactory inputProtocolFactory, - TProtocolFactory outputProtocolFactory, - int minThreadPoolThreads, int maxThreadPoolThreads, LogDelegate logDel) - : this(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, - inputProtocolFactory, outputProtocolFactory, - new Configuration(minThreadPoolThreads, maxThreadPoolThreads), - logDel) - { - } - - public TThreadPoolServer(TProcessorFactory processorFactory, - TServerTransport serverTransport, - TTransportFactory inputTransportFactory, - TTransportFactory outputTransportFactory, - TProtocolFactory inputProtocolFactory, - TProtocolFactory outputProtocolFactory, - Configuration threadConfig, - LogDelegate logDel) - : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, - inputProtocolFactory, outputProtocolFactory, logDel) - { - lock (typeof(TThreadPoolServer)) - { - if ((threadConfig.MaxWorkerThreads > 0) || (threadConfig.MaxIOThreads > 0)) - { - int work, comm; - ThreadPool.GetMaxThreads(out work, out comm); - if (threadConfig.MaxWorkerThreads > 0) - work = threadConfig.MaxWorkerThreads; - if (threadConfig.MaxIOThreads > 0) - comm = threadConfig.MaxIOThreads; - if (!ThreadPool.SetMaxThreads(work, comm)) - throw new Exception("Error: could not SetMaxThreads in ThreadPool"); - } - - if ((threadConfig.MinWorkerThreads > 0) || (threadConfig.MinIOThreads > 0)) - { - int work, comm; - ThreadPool.GetMinThreads(out work, out comm); - if (threadConfig.MinWorkerThreads > 0) - work = threadConfig.MinWorkerThreads; - if (threadConfig.MinIOThreads > 0) - comm = threadConfig.MinIOThreads; - if (!ThreadPool.SetMinThreads(work, comm)) - throw new Exception("Error: could not SetMinThreads in ThreadPool"); - } - } - } - - - /// - /// Use new ThreadPool thread for each new client connection. - /// - public override void Serve() - { - try - { - serverTransport.Listen(); - } - catch (TTransportException ttx) - { - logDelegate("Error, could not listen on ServerTransport: " + ttx); - return; - } - - //Fire the preServe server event when server is up but before any client connections - if (serverEventHandler != null) - serverEventHandler.preServe(); - - while (!stop) - { - int failureCount = 0; - try - { - TTransport client = serverTransport.Accept(); - ThreadPool.QueueUserWorkItem(this.Execute, client); - } - catch (TTransportException ttx) - { - if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted) - { - ++failureCount; - logDelegate(ttx.ToString()); - } - - } - } - - if (stop) - { - try - { - serverTransport.Close(); - } - catch (TTransportException ttx) - { - logDelegate("TServerTransport failed on close: " + ttx.Message); - } - stop = false; - } - } - - /// - /// Loops on processing a client forever - /// threadContext will be a TTransport instance - /// - /// - private void Execute(object threadContext) - { - using (TTransport client = (TTransport)threadContext) - { - TProcessor processor = processorFactory.GetProcessor(client, this); - TTransport inputTransport = null; - TTransport outputTransport = null; - TProtocol inputProtocol = null; - TProtocol outputProtocol = null; - object connectionContext = null; - try - { - try - { - inputTransport = inputTransportFactory.GetTransport(client); - outputTransport = outputTransportFactory.GetTransport(client); - inputProtocol = inputProtocolFactory.GetProtocol(inputTransport); - outputProtocol = outputProtocolFactory.GetProtocol(outputTransport); - - //Recover event handler (if any) and fire createContext server event when a client connects - if (serverEventHandler != null) - connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol); - - //Process client requests until client disconnects - while (!stop) - { - if (!inputTransport.Peek()) - break; - - //Fire processContext server event - //N.B. This is the pattern implemented in C++ and the event fires provisionally. - //That is to say it may be many minutes between the event firing and the client request - //actually arriving or the client may hang up without ever makeing a request. - if (serverEventHandler != null) - serverEventHandler.processContext(connectionContext, inputTransport); - //Process client request (blocks until transport is readable) - if (!processor.Process(inputProtocol, outputProtocol)) - break; - } - } - catch (TTransportException) - { - //Usually a client disconnect, expected - } - catch (Exception x) - { - //Unexpected - logDelegate("Error: " + x); - } - - //Fire deleteContext server event after client disconnects - if (serverEventHandler != null) - serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol); - - } - finally - { - //Close transports - if (inputTransport != null) - inputTransport.Close(); - if (outputTransport != null) - outputTransport.Close(); - - // disposable stuff should be disposed - if (inputProtocol != null) - inputProtocol.Dispose(); - if (outputProtocol != null) - outputProtocol.Dispose(); - if (inputTransport != null) - inputTransport.Dispose(); - if (outputTransport != null) - outputTransport.Dispose(); - } - } - } - - public override void Stop() - { - stop = true; - serverTransport.Close(); - } - } -} diff --git a/lib/csharp/src/Server/TThreadedServer.cs b/lib/csharp/src/Server/TThreadedServer.cs deleted file mode 100644 index cc051a33bee..00000000000 --- a/lib/csharp/src/Server/TThreadedServer.cs +++ /dev/null @@ -1,282 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Collections.Generic; -using System.Threading; -using Thrift.Collections; -using Thrift.Protocol; -using Thrift.Transport; - -namespace Thrift.Server -{ - /// - /// Server that uses C# threads (as opposed to the ThreadPool) when handling requests. - /// - public class TThreadedServer : TServer - { - private const int DEFAULT_MAX_THREADS = 100; - private volatile bool stop = false; - private readonly int maxThreads; - - private Queue clientQueue; - private THashSet clientThreads; - private object clientLock; - private Thread workerThread; - - public int ClientThreadsCount - { - get { return clientThreads.Count; } - } - - public TThreadedServer(TProcessor processor, TServerTransport serverTransport) - : this(new TSingletonProcessorFactory(processor), serverTransport, - new TTransportFactory(), new TTransportFactory(), - new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), - DEFAULT_MAX_THREADS, DefaultLogDelegate) - { - } - - public TThreadedServer(TProcessor processor, TServerTransport serverTransport, LogDelegate logDelegate) - : this(new TSingletonProcessorFactory(processor), serverTransport, - new TTransportFactory(), new TTransportFactory(), - new TBinaryProtocol.Factory(), new TBinaryProtocol.Factory(), - DEFAULT_MAX_THREADS, logDelegate) - { - } - - - public TThreadedServer(TProcessor processor, - TServerTransport serverTransport, - TTransportFactory transportFactory, - TProtocolFactory protocolFactory) - : this(new TSingletonProcessorFactory(processor), serverTransport, - transportFactory, transportFactory, - protocolFactory, protocolFactory, - DEFAULT_MAX_THREADS, DefaultLogDelegate) - { - } - - public TThreadedServer(TProcessorFactory processorFactory, - TServerTransport serverTransport, - TTransportFactory transportFactory, - TProtocolFactory protocolFactory) - : this(processorFactory, serverTransport, - transportFactory, transportFactory, - protocolFactory, protocolFactory, - DEFAULT_MAX_THREADS, DefaultLogDelegate) - { - } - public TThreadedServer(TProcessorFactory processorFactory, - TServerTransport serverTransport, - TTransportFactory inputTransportFactory, - TTransportFactory outputTransportFactory, - TProtocolFactory inputProtocolFactory, - TProtocolFactory outputProtocolFactory, - int maxThreads, LogDelegate logDel) - : base(processorFactory, serverTransport, inputTransportFactory, outputTransportFactory, - inputProtocolFactory, outputProtocolFactory, logDel) - { - this.maxThreads = maxThreads; - clientQueue = new Queue(); - clientLock = new object(); - clientThreads = new THashSet(); - } - - /// - /// Use new Thread for each new client connection. block until numConnections < maxThreads. - /// - public override void Serve() - { - try - { - //start worker thread - workerThread = new Thread(new ThreadStart(Execute)); - workerThread.Start(); - serverTransport.Listen(); - } - catch (TTransportException ttx) - { - logDelegate("Error, could not listen on ServerTransport: " + ttx); - return; - } - - //Fire the preServe server event when server is up but before any client connections - if (serverEventHandler != null) - serverEventHandler.preServe(); - - while (!stop) - { - int failureCount = 0; - try - { - TTransport client = serverTransport.Accept(); - lock (clientLock) - { - clientQueue.Enqueue(client); - Monitor.Pulse(clientLock); - } - } - catch (TTransportException ttx) - { - if (!stop || ttx.Type != TTransportException.ExceptionType.Interrupted) - { - ++failureCount; - logDelegate(ttx.ToString()); - } - - } - } - - if (stop) - { - try - { - serverTransport.Close(); - } - catch (TTransportException ttx) - { - logDelegate("TServeTransport failed on close: " + ttx.Message); - } - stop = false; - } - } - - /// - /// Loops on processing a client forever - /// - private void Execute() - { - while (!stop) - { - TTransport client; - Thread t; - lock (clientLock) - { - //don't dequeue if too many connections - while (clientThreads.Count >= maxThreads) - { - Monitor.Wait(clientLock); - } - - while (clientQueue.Count == 0) - { - Monitor.Wait(clientLock); - } - - client = clientQueue.Dequeue(); - t = new Thread(new ParameterizedThreadStart(ClientWorker)); - clientThreads.Add(t); - } - //start processing requests from client on new thread - t.Start(client); - } - } - - private void ClientWorker(object context) - { - using (TTransport client = (TTransport)context) - { - TProcessor processor = processorFactory.GetProcessor(client); - TTransport inputTransport = null; - TTransport outputTransport = null; - TProtocol inputProtocol = null; - TProtocol outputProtocol = null; - object connectionContext = null; - try - { - try - { - inputTransport = inputTransportFactory.GetTransport(client); - outputTransport = outputTransportFactory.GetTransport(client); - inputProtocol = inputProtocolFactory.GetProtocol(inputTransport); - outputProtocol = outputProtocolFactory.GetProtocol(outputTransport); - - //Recover event handler (if any) and fire createContext server event when a client connects - if (serverEventHandler != null) - connectionContext = serverEventHandler.createContext(inputProtocol, outputProtocol); - - //Process client requests until client disconnects - while (!stop) - { - if (!inputTransport.Peek()) - break; - - //Fire processContext server event - //N.B. This is the pattern implemented in C++ and the event fires provisionally. - //That is to say it may be many minutes between the event firing and the client request - //actually arriving or the client may hang up without ever makeing a request. - if (serverEventHandler != null) - serverEventHandler.processContext(connectionContext, inputTransport); - //Process client request (blocks until transport is readable) - if (!processor.Process(inputProtocol, outputProtocol)) - break; - } - } - catch (TTransportException) - { - //Usually a client disconnect, expected - } - catch (Exception x) - { - //Unexpected - logDelegate("Error: " + x); - } - - //Fire deleteContext server event after client disconnects - if (serverEventHandler != null) - serverEventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol); - - lock (clientLock) - { - clientThreads.Remove(Thread.CurrentThread); - Monitor.Pulse(clientLock); - } - - } - finally - { - //Close transports - if (inputTransport != null) - inputTransport.Close(); - if (outputTransport != null) - outputTransport.Close(); - - // disposable stuff should be disposed - if (inputProtocol != null) - inputProtocol.Dispose(); - if (outputProtocol != null) - outputProtocol.Dispose(); - } - } - } - - public override void Stop() - { - stop = true; - serverTransport.Close(); - //clean up all the threads myself - workerThread.Abort(); - foreach (Thread t in clientThreads) - { - t.Abort(); - } - } - } -} diff --git a/lib/csharp/src/TApplicationException.cs b/lib/csharp/src/TApplicationException.cs deleted file mode 100644 index 8dd7ae57822..00000000000 --- a/lib/csharp/src/TApplicationException.cs +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using Thrift.Protocol; - -namespace Thrift -{ - public class TApplicationException : TException - { - protected ExceptionType type; - - public TApplicationException() - { - } - - public TApplicationException(ExceptionType type) - { - this.type = type; - } - - public TApplicationException(ExceptionType type, string message) - : base(message, null) // TApplicationException is serializable, but we never serialize InnerException - { - this.type = type; - } - - public static TApplicationException Read(TProtocol iprot) - { - TField field; - - string message = null; - ExceptionType type = ExceptionType.Unknown; - - iprot.ReadStructBegin(); - 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 = (ExceptionType)iprot.ReadI32(); - } - else - { - TProtocolUtil.Skip(iprot, field.Type); - } - break; - default: - TProtocolUtil.Skip(iprot, field.Type); - break; - } - - iprot.ReadFieldEnd(); - } - - iprot.ReadStructEnd(); - - return new TApplicationException(type, message); - } - - public void Write(TProtocol oprot) - { - TStruct struc = new TStruct("TApplicationException"); - TField field = new TField(); - - oprot.WriteStructBegin(struc); - - if (!string.IsNullOrEmpty(Message)) - { - field.Name = "message"; - field.Type = TType.String; - field.ID = 1; - oprot.WriteFieldBegin(field); - oprot.WriteString(Message); - oprot.WriteFieldEnd(); - } - - field.Name = "type"; - field.Type = TType.I32; - field.ID = 2; - oprot.WriteFieldBegin(field); - oprot.WriteI32((int)type); - oprot.WriteFieldEnd(); - oprot.WriteFieldStop(); - oprot.WriteStructEnd(); - } - - public enum ExceptionType - { - Unknown, - UnknownMethod, - InvalidMessageType, - WrongMethodName, - BadSequenceID, - MissingResult, - InternalError, - ProtocolError, - InvalidTransform, - InvalidProtocol, - UnsupportedClientType - } - - public ExceptionType Type - { - get { return type; } - } - } -} diff --git a/lib/csharp/src/TAsyncProcessor.cs b/lib/csharp/src/TAsyncProcessor.cs deleted file mode 100644 index ab432255ba5..00000000000 --- a/lib/csharp/src/TAsyncProcessor.cs +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Threading.Tasks; -using Thrift.Protocol; - -namespace Thrift -{ - /// - /// Processes a message asynchronously. - /// - public interface TAsyncProcessor - { - /// - /// Processes the next part of the message. - /// - /// The input protocol. - /// The output protocol. - /// true if there's more to process, false otherwise. - Task ProcessAsync(TProtocol iprot, TProtocol oprot); - } -} diff --git a/lib/csharp/src/TControllingHandler.cs b/lib/csharp/src/TControllingHandler.cs deleted file mode 100644 index 7b5203a5f2d..00000000000 --- a/lib/csharp/src/TControllingHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using Thrift.Server; - -namespace Thrift -{ - public interface TControllingHandler - { - TServer server { get; set; } - } -} diff --git a/lib/csharp/src/TException.cs b/lib/csharp/src/TException.cs deleted file mode 100644 index b9fae6e9f19..00000000000 --- a/lib/csharp/src/TException.cs +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; - -namespace Thrift -{ - public class TException : Exception - { - public TException() - { - } - - public TException(string message, Exception inner = null) - : base(message, inner) - { - } - - } -} diff --git a/lib/csharp/src/TProcessor.cs b/lib/csharp/src/TProcessor.cs deleted file mode 100644 index 71ce7550892..00000000000 --- a/lib/csharp/src/TProcessor.cs +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using Thrift.Protocol; - -namespace Thrift -{ - public interface TProcessor - { - bool Process(TProtocol iprot, TProtocol oprot); - } -} diff --git a/lib/csharp/src/TProcessorFactory.cs b/lib/csharp/src/TProcessorFactory.cs deleted file mode 100644 index fdf631bc77e..00000000000 --- a/lib/csharp/src/TProcessorFactory.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using Thrift.Server; -using Thrift.Transport; - -namespace Thrift -{ - public interface TProcessorFactory - { - TProcessor GetProcessor(TTransport trans, TServer server = null); - } -} diff --git a/lib/csharp/src/TPrototypeProcessorFactory.cs b/lib/csharp/src/TPrototypeProcessorFactory.cs deleted file mode 100644 index 0b47261fbbe..00000000000 --- a/lib/csharp/src/TPrototypeProcessorFactory.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Thrift.Server; -using Thrift.Transport; - -namespace Thrift -{ - public class TPrototypeProcessorFactory : TProcessorFactory where P : TProcessor - { - object[] handlerArgs = null; - - public TPrototypeProcessorFactory() - { - handlerArgs = new object[0]; - } - - public TPrototypeProcessorFactory(params object[] handlerArgs) - { - this.handlerArgs = handlerArgs; - } - - public TProcessor GetProcessor(TTransport trans, TServer server = null) - { - H handler = (H)Activator.CreateInstance(typeof(H), handlerArgs); - - TControllingHandler handlerServerRef = handler as TControllingHandler; - if (handlerServerRef != null) - { - handlerServerRef.server = server; - } - return Activator.CreateInstance(typeof(P), new object[] { handler }) as TProcessor; - } - } -} diff --git a/lib/csharp/src/TSingletonProcessorFactory.cs b/lib/csharp/src/TSingletonProcessorFactory.cs deleted file mode 100644 index ed2897ba362..00000000000 --- a/lib/csharp/src/TSingletonProcessorFactory.cs +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Thrift.Server; -using Thrift.Transport; - -namespace Thrift -{ - public class TSingletonProcessorFactory : TProcessorFactory - { - private readonly TProcessor processor_; - - public TSingletonProcessorFactory(TProcessor processor) - { - processor_ = processor; - } - - public TProcessor GetProcessor(TTransport trans, TServer server = null) - { - return processor_; - } - } -} diff --git a/lib/csharp/src/Thrift.45.csproj b/lib/csharp/src/Thrift.45.csproj deleted file mode 100644 index 146e7f8ed13..00000000000 --- a/lib/csharp/src/Thrift.45.csproj +++ /dev/null @@ -1,138 +0,0 @@ - - - - - Debug - AnyCPU - {EBCE35DA-CF6A-42BC-A357-A9C09B534299} - Library - Properties - Thrift - Thrift45 - v4.5 - 512 - - - true - portable - false - bin\Debug\ - TRACE;DEBUG;NET45 - prompt - 4 - - - portable - true - bin\Release\ - TRACE;NET45 - prompt - 4 - - - true - - - thrift.snk - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/csharp/src/Thrift.csproj b/lib/csharp/src/Thrift.csproj deleted file mode 100644 index 13054821d7d..00000000000 --- a/lib/csharp/src/Thrift.csproj +++ /dev/null @@ -1,166 +0,0 @@ - - - - - Debug - AnyCPU - {499EB63C-D74C-47E8-AE48-A2FC94538E9D} - 9.0.21022 - 2.0 - Library - false - Thrift - v3.5 - 512 - Thrift - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 0.14.0.0 - false - false - true - - - true - portable - false - bin\Debug\ - TRACE;DEBUG - prompt - 4 - AllRules.ruleset - - - portable - true - bin\Release\ - - - prompt - 4 - AllRules.ruleset - - - true - - - thrift.snk - - - - - 3.5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 3.5 SP1 - true - - - False - Windows Installer 3.1 - true - - - - - - - - - - \ No newline at end of file diff --git a/lib/csharp/src/Thrift.sln b/lib/csharp/src/Thrift.sln deleted file mode 100644 index a29e46882ab..00000000000 --- a/lib/csharp/src/Thrift.sln +++ /dev/null @@ -1,47 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift", "Thrift.csproj", "{499EB63C-D74C-47E8-AE48-A2FC94538E9D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftTest", "..\test\ThriftTest\ThriftTest.csproj", "{48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftMSBuildTask", "..\ThriftMSBuildTask\ThriftMSBuildTask.csproj", "{EC0A0231-66EA-4593-A792-C6CA3BB8668E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift.45", "Thrift.45.csproj", "{EBCE35DA-CF6A-42BC-A357-A9C09B534299}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftMVCTest", "..\test\ThriftMVCTest\ThriftMVCTest.csproj", "{891B4487-C7BA-427E-BBC8-4C596C229A10}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Release|Any CPU.Build.0 = Release|Any CPU - {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Release|Any CPU.Build.0 = Release|Any CPU - {EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EC0A0231-66EA-4593-A792-C6CA3BB8668E}.Release|Any CPU.Build.0 = Release|Any CPU - {EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EBCE35DA-CF6A-42BC-A357-A9C09B534299}.Release|Any CPU.Build.0 = Release|Any CPU - {891B4487-C7BA-427E-BBC8-4C596C229A10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {891B4487-C7BA-427E-BBC8-4C596C229A10}.Debug|Any CPU.Build.0 = Debug|Any CPU - {891B4487-C7BA-427E-BBC8-4C596C229A10}.Release|Any CPU.ActiveCfg = Release|Any CPU - {891B4487-C7BA-427E-BBC8-4C596C229A10}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = Thrift.csproj - EndGlobalSection -EndGlobal diff --git a/lib/csharp/src/Transport/TBufferedTransport.cs b/lib/csharp/src/Transport/TBufferedTransport.cs deleted file mode 100644 index 88709881086..00000000000 --- a/lib/csharp/src/Transport/TBufferedTransport.cs +++ /dev/null @@ -1,194 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.IO; - -namespace Thrift.Transport -{ - public class TBufferedTransport : TTransport, IDisposable - { - private readonly int bufSize; - private readonly MemoryStream inputBuffer = new MemoryStream(0); - private readonly MemoryStream outputBuffer = new MemoryStream(0); - private readonly TTransport transport; - - public TBufferedTransport(TTransport transport, int bufSize = 1024) - { - if (transport == null) - throw new ArgumentNullException("transport"); - if (bufSize <= 0) - throw new ArgumentException("bufSize", "Buffer size must be a positive number."); - this.transport = transport; - this.bufSize = bufSize; - } - - public TTransport UnderlyingTransport - { - get - { - CheckNotDisposed(); - return transport; - } - } - - public override bool IsOpen - { - get - { - // We can legitimately throw here but be nice a bit. - // CheckNotDisposed(); - return !_IsDisposed && transport.IsOpen; - } - } - - public override void Open() - { - CheckNotDisposed(); - transport.Open(); - } - - public override void Close() - { - CheckNotDisposed(); - transport.Close(); - } - - public override int Read(byte[] buf, int off, int len) - { - CheckNotDisposed(); - ValidateBufferArgs(buf, off, len); - if (!IsOpen) - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - - if (inputBuffer.Capacity < bufSize) - inputBuffer.Capacity = bufSize; - - while (true) - { - int got = inputBuffer.Read(buf, off, len); - if (got > 0) - return got; - - inputBuffer.Seek(0, SeekOrigin.Begin); - inputBuffer.SetLength(inputBuffer.Capacity); - int filled = transport.Read(inputBuffer.GetBuffer(), 0, (int)inputBuffer.Length); - inputBuffer.SetLength(filled); - if (filled == 0) - return 0; - } - } - - public override void Write(byte[] buf, int off, int len) - { - CheckNotDisposed(); - ValidateBufferArgs(buf, off, len); - if (!IsOpen) - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - // Relative offset from "off" argument - int offset = 0; - if (outputBuffer.Length > 0) - { - int capa = (int)(outputBuffer.Capacity - outputBuffer.Length); - int writeSize = capa <= len ? capa : len; - outputBuffer.Write(buf, off, writeSize); - offset += writeSize; - if (writeSize == capa) - { - transport.Write(outputBuffer.GetBuffer(), 0, (int)outputBuffer.Length); - outputBuffer.SetLength(0); - } - } - while (len - offset >= bufSize) - { - transport.Write(buf, off + offset, bufSize); - offset += bufSize; - } - int remain = len - offset; - if (remain > 0) - { - if (outputBuffer.Capacity < bufSize) - outputBuffer.Capacity = bufSize; - outputBuffer.Write(buf, off + offset, remain); - } - } - - private void InternalFlush() - { - if (!IsOpen) - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - if (outputBuffer.Length > 0) - { - transport.Write(outputBuffer.GetBuffer(), 0, (int)outputBuffer.Length); - outputBuffer.SetLength(0); - } - } - - public override void Flush() - { - CheckNotDisposed(); - InternalFlush(); - - transport.Flush(); - } - - public override IAsyncResult BeginFlush(AsyncCallback callback, object state) - { - CheckNotDisposed(); - InternalFlush(); - - return transport.BeginFlush( callback, state); - } - - public override void EndFlush(IAsyncResult asyncResult) - { - transport.EndFlush( asyncResult); - } - - - - protected void CheckNotDisposed() - { - if (_IsDisposed) - throw new ObjectDisposedException("TBufferedTransport"); - } - - #region " IDisposable Support " - protected bool _IsDisposed { get; private set; } - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_IsDisposed) - { - if (disposing) - { - if (inputBuffer != null) - inputBuffer.Dispose(); - if (outputBuffer != null) - outputBuffer.Dispose(); - if (transport != null) - transport.Dispose(); - } - } - _IsDisposed = true; - } - #endregion - } -} diff --git a/lib/csharp/src/Transport/TFramedTransport.cs b/lib/csharp/src/Transport/TFramedTransport.cs deleted file mode 100644 index a746a3223a5..00000000000 --- a/lib/csharp/src/Transport/TFramedTransport.cs +++ /dev/null @@ -1,205 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -using System; -using System.IO; - -namespace Thrift.Transport -{ - public class TFramedTransport : TTransport, IDisposable - { - private readonly TTransport transport; - private readonly MemoryStream writeBuffer = new MemoryStream(1024); - private readonly MemoryStream readBuffer = new MemoryStream(1024); - - private const int HeaderSize = 4; - private readonly byte[] headerBuf = new byte[HeaderSize]; - - public class Factory : TTransportFactory - { - public override TTransport GetTransport(TTransport trans) - { - return new TFramedTransport(trans); - } - } - - public TFramedTransport(TTransport transport) - { - if (transport == null) - throw new ArgumentNullException("transport"); - this.transport = transport; - InitWriteBuffer(); - } - - public override void Open() - { - CheckNotDisposed(); - transport.Open(); - } - - public override bool IsOpen - { - get - { - // We can legitimately throw here but be nice a bit. - // CheckNotDisposed(); - return !_IsDisposed && transport.IsOpen; - } - } - - public override void Close() - { - CheckNotDisposed(); - transport.Close(); - } - - public override int Read(byte[] buf, int off, int len) - { - CheckNotDisposed(); - ValidateBufferArgs(buf, off, len); - if (!IsOpen) - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - 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() - { - transport.ReadAll(headerBuf, 0, HeaderSize); - int size = DecodeFrameSize(headerBuf); - - readBuffer.SetLength(size); - readBuffer.Seek(0, SeekOrigin.Begin); - byte[] buff = readBuffer.GetBuffer(); - transport.ReadAll(buff, 0, size); - } - - public override void Write(byte[] buf, int off, int len) - { - CheckNotDisposed(); - ValidateBufferArgs(buf, off, len); - if (!IsOpen) - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - if (writeBuffer.Length + (long)len > (long)int.MaxValue) - Flush(); - writeBuffer.Write(buf, off, len); - } - - private void InternalFlush() - { - CheckNotDisposed(); - if (!IsOpen) - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - byte[] buf = writeBuffer.GetBuffer(); - int len = (int)writeBuffer.Length; - int data_len = len - HeaderSize; - if (data_len < 0) - throw new System.InvalidOperationException(); // logic error actually - - // Inject message header into the reserved buffer space - EncodeFrameSize(data_len, buf); - - // Send the entire message at once - transport.Write(buf, 0, len); - - InitWriteBuffer(); - } - - public override void Flush() - { - CheckNotDisposed(); - InternalFlush(); - - transport.Flush(); - } - - public override IAsyncResult BeginFlush(AsyncCallback callback, object state) - { - CheckNotDisposed(); - InternalFlush(); - - return transport.BeginFlush( callback, state); - } - - public override void EndFlush(IAsyncResult asyncResult) - { - transport.EndFlush( asyncResult); - } - - private void InitWriteBuffer() - { - // Reserve space for message header to be put right before sending it out - writeBuffer.SetLength(HeaderSize); - writeBuffer.Seek(0, SeekOrigin.End); - } - - private static void EncodeFrameSize(int frameSize, 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)); - } - - private static int DecodeFrameSize(byte[] buf) - { - return - ((buf[0] & 0xff) << 24) | - ((buf[1] & 0xff) << 16) | - ((buf[2] & 0xff) << 8) | - ((buf[3] & 0xff)); - } - - - private void CheckNotDisposed() - { - if (_IsDisposed) - throw new ObjectDisposedException("TFramedTransport"); - } - - #region " IDisposable Support " - private bool _IsDisposed; - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_IsDisposed) - { - if (disposing) - { - if (readBuffer != null) - readBuffer.Dispose(); - if (writeBuffer != null) - writeBuffer.Dispose(); - if (transport != null) - transport.Dispose(); - } - } - _IsDisposed = true; - } - #endregion - } -} diff --git a/lib/csharp/src/Transport/THttpClient.cs b/lib/csharp/src/Transport/THttpClient.cs deleted file mode 100644 index 986799cd271..00000000000 --- a/lib/csharp/src/Transport/THttpClient.cs +++ /dev/null @@ -1,486 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Threading; -using System.Linq; -using System.Security.Cryptography.X509Certificates; -using System.IO.Compression; - -namespace Thrift.Transport -{ - public class THttpClient : TTransport, IDisposable - { - private readonly Uri uri; - private readonly X509Certificate[] certificates; - private Stream inputStream; - private MemoryStream outputStream = new MemoryStream(); - - // Timeouts in milliseconds - private int connectTimeout = 30000; - - private int readTimeout = 30000; - - private IDictionary customHeaders = new Dictionary(); - private string userAgent = "C#/THttpClient"; - -#if !SILVERLIGHT - private IWebProxy proxy = WebRequest.DefaultWebProxy; -#endif - - public THttpClient(Uri u) - : this(u, Enumerable.Empty()) - { - } - public THttpClient(Uri u, string userAgent) - : this(u, userAgent, Enumerable.Empty()) - { - } - - public THttpClient(Uri u, IEnumerable certificates) - { - uri = u; - this.certificates = (certificates ?? Enumerable.Empty()).ToArray(); - } - public THttpClient(Uri u, string userAgent, IEnumerable certificates) - { - uri = u; - this.userAgent = userAgent; - this.certificates = (certificates ?? Enumerable.Empty()).ToArray(); - } - - public int ConnectTimeout - { - set - { - connectTimeout = value; - } - } - - public int ReadTimeout - { - set - { - readTimeout = value; - } - } - - public IDictionary CustomHeaders - { - get - { - return customHeaders; - } - } - -#if !SILVERLIGHT - public IWebProxy Proxy - { - set - { - proxy = value; - } - } -#endif - - public override bool IsOpen - { - get - { - return true; - } - } - - public override void Open() - { - } - - public override void Close() - { - if (inputStream != null) - { - inputStream.Close(); - inputStream = null; - } - if (outputStream != null) - { - outputStream.Close(); - outputStream = null; - } - } - - public override int Read(byte[] buf, int off, int len) - { - if (inputStream == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No request has been sent"); - } - - try - { - int ret = inputStream.Read(buf, off, len); - - if (ret == -1) - { - throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "No more data available"); - } - - return ret; - } - catch (IOException iox) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString(), iox); - } - } - - public override void Write(byte[] buf, int off, int len) - { - outputStream.Write(buf, off, len); - } - -#if !SILVERLIGHT - public override void Flush() - { - try - { - SendRequest(); - } - finally - { - outputStream = new MemoryStream(); - } - } - - private void SendRequest() - { - try - { - HttpWebRequest connection = CreateRequest(); - connection.Headers.Add("Accept-Encoding", "gzip, deflate"); - - byte[] data = outputStream.ToArray(); - connection.ContentLength = data.Length; - - using (Stream requestStream = connection.GetRequestStream()) - { - requestStream.Write(data, 0, data.Length); - - // Resolve HTTP hang that can happens after successive calls by making sure - // that we release the response and response stream. To support this, we copy - // the response to a memory stream. - using (var response = connection.GetResponse()) - { - using (var responseStream = response.GetResponseStream()) - { - // Copy the response to a memory stream so that we can - // cleanly close the response and response stream. - inputStream = new MemoryStream(); - byte[] buffer = new byte[8192]; // multiple of 4096 - int bytesRead; - while ((bytesRead = responseStream.Read(buffer, 0, buffer.Length)) > 0) - { - inputStream.Write(buffer, 0, bytesRead); - } - inputStream.Seek(0, 0); - } - - var encodings = response.Headers.GetValues("Content-Encoding"); - if (encodings != null) - { - foreach (var encoding in encodings) - { - switch (encoding) - { - case "gzip": - DecompressGZipped(ref inputStream); - break; - case "deflate": - DecompressDeflated(ref inputStream); - break; - default: - break; - } - } - } - } - } - } - catch (IOException iox) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, iox.ToString(), iox); - } - catch (WebException wx) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, "Couldn't connect to server: " + wx, wx); - } - } - - private void DecompressDeflated(ref Stream inputStream) - { - var tmp = new MemoryStream(); - using (var decomp = new DeflateStream(inputStream, CompressionMode.Decompress)) - { - decomp.CopyTo(tmp); - } - inputStream.Dispose(); - inputStream = tmp; - inputStream.Seek(0, 0); - } - - private void DecompressGZipped(ref Stream inputStream) - { - var tmp = new MemoryStream(); - using (var decomp = new GZipStream(inputStream, CompressionMode.Decompress)) - { - decomp.CopyTo(tmp); - } - inputStream.Dispose(); - inputStream = tmp; - inputStream.Seek(0, 0); - } -#endif - private HttpWebRequest CreateRequest() - { - HttpWebRequest connection = (HttpWebRequest)WebRequest.Create(uri); - - -#if !SILVERLIGHT - // Adding certificates through code is not supported with WP7 Silverlight - // see "Windows Phone 7 and Certificates_FINAL_121610.pdf" - connection.ClientCertificates.AddRange(certificates); - - if (connectTimeout > 0) - { - connection.Timeout = connectTimeout; - } - if (readTimeout > 0) - { - connection.ReadWriteTimeout = readTimeout; - } -#endif - // Make the request - connection.ContentType = "application/x-thrift"; - connection.Accept = "application/x-thrift"; - connection.UserAgent = userAgent; - connection.Method = "POST"; -#if !SILVERLIGHT - connection.ProtocolVersion = HttpVersion.Version10; -#endif - - //add custom headers here - foreach (KeyValuePair item in customHeaders) - { -#if !SILVERLIGHT - connection.Headers.Add(item.Key, item.Value); -#else - connection.Headers[item.Key] = item.Value; -#endif - } - -#if !SILVERLIGHT - connection.Proxy = proxy; -#endif - - return connection; - } - - public override IAsyncResult BeginFlush(AsyncCallback callback, object state) - { - // Extract request and reset buffer - var data = outputStream.ToArray(); - - //requestBuffer_ = new MemoryStream(); - - try - { - // Create connection object - var flushAsyncResult = new FlushAsyncResult(callback, state); - flushAsyncResult.Connection = CreateRequest(); - - flushAsyncResult.Data = data; - - - flushAsyncResult.Connection.BeginGetRequestStream(GetRequestStreamCallback, flushAsyncResult); - return flushAsyncResult; - - } - catch (IOException iox) - { - throw new TTransportException(iox.ToString(), iox); - } - } - - public override void EndFlush(IAsyncResult asyncResult) - { - try - { - var flushAsyncResult = (FlushAsyncResult)asyncResult; - - if (!flushAsyncResult.IsCompleted) - { - var waitHandle = flushAsyncResult.AsyncWaitHandle; - waitHandle.WaitOne(); // blocking INFINITEly - waitHandle.Close(); - } - - if (flushAsyncResult.AsyncException != null) - { - throw flushAsyncResult.AsyncException; - } - } - finally - { - outputStream = new MemoryStream(); - } - - } - - private void GetRequestStreamCallback(IAsyncResult asynchronousResult) - { - var flushAsyncResult = (FlushAsyncResult)asynchronousResult.AsyncState; - try - { - var reqStream = flushAsyncResult.Connection.EndGetRequestStream(asynchronousResult); - reqStream.Write(flushAsyncResult.Data, 0, flushAsyncResult.Data.Length); - reqStream.Flush(); - reqStream.Close(); - - // Start the asynchronous operation to get the response - flushAsyncResult.Connection.BeginGetResponse(GetResponseCallback, flushAsyncResult); - } - catch (Exception exception) - { - flushAsyncResult.AsyncException = new TTransportException(exception.ToString(), exception); - flushAsyncResult.UpdateStatusToComplete(); - flushAsyncResult.NotifyCallbackWhenAvailable(); - } - } - - private void GetResponseCallback(IAsyncResult asynchronousResult) - { - var flushAsyncResult = (FlushAsyncResult)asynchronousResult.AsyncState; - try - { - inputStream = flushAsyncResult.Connection.EndGetResponse(asynchronousResult).GetResponseStream(); - } - catch (Exception exception) - { - flushAsyncResult.AsyncException = new TTransportException(exception.ToString(), exception); - } - flushAsyncResult.UpdateStatusToComplete(); - flushAsyncResult.NotifyCallbackWhenAvailable(); - } - - // Based on http://msmvps.com/blogs/luisabreu/archive/2009/06/15/multithreading-implementing-the-iasyncresult-interface.aspx - class FlushAsyncResult : IAsyncResult - { - private volatile Boolean _isCompleted; - private ManualResetEvent _evt; - private readonly AsyncCallback _cbMethod; - private readonly object _state; - - public FlushAsyncResult(AsyncCallback cbMethod, object state) - { - _cbMethod = cbMethod; - _state = state; - } - - internal byte[] Data { get; set; } - internal HttpWebRequest Connection { get; set; } - internal TTransportException AsyncException { get; set; } - - public object AsyncState - { - get { return _state; } - } - public WaitHandle AsyncWaitHandle - { - get { return GetEvtHandle(); } - } - public bool CompletedSynchronously - { - get { return false; } - } - public bool IsCompleted - { - get { return _isCompleted; } - } - private readonly object _locker = new object(); - private ManualResetEvent GetEvtHandle() - { - lock (_locker) - { - if (_evt == null) - { - _evt = new ManualResetEvent(false); - } - if (_isCompleted) - { - _evt.Set(); - } - } - return _evt; - } - internal void UpdateStatusToComplete() - { - _isCompleted = true; //1. set _iscompleted to true - lock (_locker) - { - if (_evt != null) - { - _evt.Set(); //2. set the event, when it exists - } - } - } - - internal void NotifyCallbackWhenAvailable() - { - if (_cbMethod != null) - { - _cbMethod(this); - } - } - } - - #region " IDisposable Support " - private bool _IsDisposed; - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_IsDisposed) - { - if (disposing) - { - if (inputStream != null) - inputStream.Dispose(); - if (outputStream != null) - outputStream.Dispose(); - } - } - _IsDisposed = true; - } - #endregion - } -} diff --git a/lib/csharp/src/Transport/THttpHandler.cs b/lib/csharp/src/Transport/THttpHandler.cs deleted file mode 100644 index 4115ef95aaa..00000000000 --- a/lib/csharp/src/Transport/THttpHandler.cs +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * - */ - -using System; -using System.Web; -using System.Net; -using System.IO; - -using Thrift.Protocol; - -namespace Thrift.Transport -{ - public class THttpHandler : IHttpHandler - { - protected TProcessor processor; - - protected TProtocolFactory inputProtocolFactory; - protected TProtocolFactory outputProtocolFactory; - - protected const string contentType = "application/x-thrift"; - protected System.Text.Encoding encoding = System.Text.Encoding.UTF8; - - public THttpHandler(TProcessor processor) - : this(processor, new TBinaryProtocol.Factory()) - { - - } - - public THttpHandler(TProcessor processor, TProtocolFactory protocolFactory) - : this(processor, protocolFactory, protocolFactory) - { - - } - - public THttpHandler(TProcessor processor, TProtocolFactory inputProtocolFactory, TProtocolFactory outputProtocolFactory) - { - this.processor = processor; - this.inputProtocolFactory = inputProtocolFactory; - this.outputProtocolFactory = outputProtocolFactory; - } - - public void ProcessRequest(HttpListenerContext context) - { - context.Response.ContentType = contentType; - context.Response.ContentEncoding = encoding; - ProcessRequest(context.Request.InputStream, context.Response.OutputStream); - } - - public void ProcessRequest(HttpContext context) - { - context.Response.ContentType = contentType; - context.Response.ContentEncoding = encoding; - ProcessRequest(context.Request.InputStream, context.Response.OutputStream); - } - - public void ProcessRequest(Stream input, Stream output) - { - TTransport transport = new TStreamTransport(input,output); - - try - { - var inputProtocol = inputProtocolFactory.GetProtocol(transport); - var outputProtocol = outputProtocolFactory.GetProtocol(transport); - - while (processor.Process(inputProtocol, outputProtocol)) - { - } - } - catch (TTransportException) - { - // Client died, just move on - } - finally - { - transport.Close(); - } - } - - public bool IsReusable - { - get { return true; } - } - } -} diff --git a/lib/csharp/src/Transport/THttpTaskAsyncHandler.cs b/lib/csharp/src/Transport/THttpTaskAsyncHandler.cs deleted file mode 100644 index e491f32cb98..00000000000 --- a/lib/csharp/src/Transport/THttpTaskAsyncHandler.cs +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System.Threading.Tasks; -using System.Web; -using Thrift.Protocol; - -namespace Thrift.Transport -{ - /// - /// An async task based HTTP handler for processing thrift services. - /// - public class THttpTaskAsyncHandler : HttpTaskAsyncHandler - { - private readonly TAsyncProcessor _processor; - private readonly TProtocolFactory _inputProtocolFactory; - private readonly TProtocolFactory _outputProtocolFactory; - - /// - /// Initializes a new instance of the class - /// using the for both input and output streams. - /// - /// The async processor implementation. - public THttpTaskAsyncHandler(TAsyncProcessor processor) - : this(processor, new TBinaryProtocol.Factory()) - { - } - - /// - /// Initializes a new instance of the class - /// using for both input and output streams. - /// - /// The async processor implementation. - /// The protocol factory. - public THttpTaskAsyncHandler(TAsyncProcessor processor, TProtocolFactory protocolFactory) - : this(processor, protocolFactory, protocolFactory) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The async processor implementation. - /// The input protocol factory. - /// The output protocol factory. - public THttpTaskAsyncHandler(TAsyncProcessor processor, TProtocolFactory inputProtocolFactory, - TProtocolFactory outputProtocolFactory) - { - _processor = processor; - _inputProtocolFactory = inputProtocolFactory; - _outputProtocolFactory = outputProtocolFactory; - } - - public override async Task ProcessRequestAsync(HttpContext context) - { - var transport = new TStreamTransport(context.Request.InputStream, context.Response.OutputStream); - - try - { - var input = _inputProtocolFactory.GetProtocol(transport); - var output = _outputProtocolFactory.GetProtocol(transport); - - while (await _processor.ProcessAsync(input, output)) - { - } - } - catch (TTransportException) - { - // Client died, just move on - } - finally - { - transport.Close(); - } - } - } -} diff --git a/lib/csharp/src/Transport/TMemoryBuffer.cs b/lib/csharp/src/Transport/TMemoryBuffer.cs deleted file mode 100644 index 303d083299e..00000000000 --- a/lib/csharp/src/Transport/TMemoryBuffer.cs +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.IO; -using System.Reflection; -using Thrift.Protocol; - -namespace Thrift.Transport -{ - public class TMemoryBuffer : TTransport - { - - private readonly MemoryStream byteStream; - - public TMemoryBuffer() - { - byteStream = new MemoryStream(); - } - - public TMemoryBuffer(byte[] buf) - { - byteStream = new MemoryStream(buf); - } - - public override void Open() - { - /** do nothing **/ - } - - public override void Close() - { - /** do nothing **/ - } - - public override int Read(byte[] buf, int off, int len) - { - return byteStream.Read(buf, off, len); - } - - public override void Write(byte[] buf, int off, int len) - { - byteStream.Write(buf, off, len); - } - - public byte[] GetBuffer() - { - return byteStream.ToArray(); - } - - - public override bool IsOpen - { - get { return true; } - } - - public static byte[] Serialize(TAbstractBase s) - { - var t = new TMemoryBuffer(); - var p = new TBinaryProtocol(t); - - s.Write(p); - - return t.GetBuffer(); - } - - public static T DeSerialize(byte[] buf) where T : TAbstractBase - { - var trans = new TMemoryBuffer(buf); - var p = new TBinaryProtocol(trans); - if (typeof(TBase).IsAssignableFrom(typeof(T))) - { - var method = typeof(T).GetMethod("Read", BindingFlags.Instance | BindingFlags.Public); - var t = Activator.CreateInstance(); - method.Invoke(t, new object[] { p }); - return t; - } - else - { - var method = typeof(T).GetMethod("Read", BindingFlags.Static | BindingFlags.Public); - return (T)method.Invoke(null, new object[] { p }); - } - } - - private bool _IsDisposed; - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_IsDisposed) - { - if (disposing) - { - if (byteStream != null) - byteStream.Dispose(); - } - } - _IsDisposed = true; - } - } -} diff --git a/lib/csharp/src/Transport/TNamedPipeClientTransport.cs b/lib/csharp/src/Transport/TNamedPipeClientTransport.cs deleted file mode 100644 index 49a50aa5b02..00000000000 --- a/lib/csharp/src/Transport/TNamedPipeClientTransport.cs +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.IO.Pipes; -using System.Threading; - -namespace Thrift.Transport -{ - public class TNamedPipeClientTransport : TTransport - { - private NamedPipeClientStream client; - private string ServerName; - private string PipeName; - private int ConnectTimeout; - - public TNamedPipeClientTransport(string pipe, int timeout = Timeout.Infinite) - { - ServerName = "."; - PipeName = pipe; - ConnectTimeout = timeout; - } - - public TNamedPipeClientTransport(string server, string pipe, int timeout = Timeout.Infinite) - { - ServerName = (server != "") ? server : "."; - PipeName = pipe; - ConnectTimeout = timeout; - } - - public override bool IsOpen - { - get { return client != null && client.IsConnected; } - } - - public override void Open() - { - if (IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen); - } - client = new NamedPipeClientStream(ServerName, PipeName, PipeDirection.InOut, PipeOptions.None); - client.Connect(ConnectTimeout); - } - - public override void Close() - { - if (client != null) - { - client.Close(); - client = null; - } - } - - public override int Read(byte[] buf, int off, int len) - { - if (client == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - return client.Read(buf, off, len); - } - - public override void Write(byte[] buf, int off, int len) - { - if (client == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - // if necessary, send the data in chunks - // there's a system limit around 0x10000 bytes that we hit otherwise - // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section." - var nBytes = Math.Min(len, 15 * 4096); // 16 would exceed the limit - while (nBytes > 0) - { - client.Write(buf, off, nBytes); - - off += nBytes; - len -= nBytes; - nBytes = Math.Min(len, nBytes); - } - } - - protected override void Dispose(bool disposing) - { - client.Dispose(); - } - } -} diff --git a/lib/csharp/src/Transport/TNamedPipeServerTransport.cs b/lib/csharp/src/Transport/TNamedPipeServerTransport.cs deleted file mode 100644 index 32215cfc10f..00000000000 --- a/lib/csharp/src/Transport/TNamedPipeServerTransport.cs +++ /dev/null @@ -1,296 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.IO.Pipes; -using System.Threading; -using System.Security.Principal; - -namespace Thrift.Transport -{ - public class TNamedPipeServerTransport : TServerTransport - { - /// - /// This is the address of the Pipe on the localhost. - /// - private readonly string pipeAddress; - private NamedPipeServerStream stream = null; - private bool asyncMode = true; - - public TNamedPipeServerTransport(string pipeAddress) - { - this.pipeAddress = pipeAddress; - } - - public override void Listen() - { - // nothing to do here - } - - public override void Close() - { - if (stream != null) - { - try - { - stream.Close(); - stream.Dispose(); - } - finally - { - stream = null; - } - } - } - - private void EnsurePipeInstance() - { - if (stream == null) - { - var direction = PipeDirection.InOut; - var maxconn = NamedPipeServerStream.MaxAllowedServerInstances; - var mode = PipeTransmissionMode.Byte; - var options = asyncMode ? PipeOptions.Asynchronous : PipeOptions.None; - const int INBUF_SIZE = 4096; - const int OUTBUF_SIZE = 4096; - - // security - var security = new PipeSecurity(); - security.AddAccessRule( - new PipeAccessRule( - new SecurityIdentifier(WellKnownSidType.WorldSid, null), - PipeAccessRights.Read | PipeAccessRights.Write | PipeAccessRights.Synchronize | PipeAccessRights.CreateNewInstance, - System.Security.AccessControl.AccessControlType.Allow - ) - ); - - try - { - stream = new NamedPipeServerStream(pipeAddress, direction, maxconn, mode, options, INBUF_SIZE, OUTBUF_SIZE, security); - } - catch (NotImplementedException) // Mono still does not support async, fallback to sync - { - if (asyncMode) - { - options &= (~PipeOptions.Asynchronous); - stream = new NamedPipeServerStream(pipeAddress, direction, maxconn, mode, options, INBUF_SIZE, OUTBUF_SIZE, security); - asyncMode = false; - } - else - { - throw; - } - } - - } - } - - protected override TTransport AcceptImpl() - { - try - { - EnsurePipeInstance(); - - if (asyncMode) - { - var evt = new ManualResetEvent(false); - Exception eOuter = null; - - stream.BeginWaitForConnection(asyncResult => - { - try - { - if (stream != null) - stream.EndWaitForConnection(asyncResult); - else - eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted); - } - catch (Exception e) - { - if (stream != null) - eOuter = e; - else - eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e); - } - evt.Set(); - }, null); - - evt.WaitOne(); - - if (eOuter != null) - throw eOuter; // rethrow exception - } - else - { - stream.WaitForConnection(); - } - - var trans = new ServerTransport(stream,asyncMode); - stream = null; // pass ownership to ServerTransport - return trans; - } - catch (TTransportException) - { - Close(); - throw; - } - catch (Exception e) - { - Close(); - throw new TTransportException(TTransportException.ExceptionType.NotOpen, e.Message, e); - } - } - - private class ServerTransport : TTransport - { - private NamedPipeServerStream stream; - private bool asyncMode; - - public ServerTransport(NamedPipeServerStream stream, bool asyncMode) - { - this.stream = stream; - this.asyncMode = asyncMode; - } - - public override bool IsOpen - { - get { return stream != null && stream.IsConnected; } - } - - public override void Open() - { - } - - public override void Close() - { - if (stream != null) - stream.Close(); - } - - public override int Read(byte[] buf, int off, int len) - { - if (stream == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - if (asyncMode) - { - Exception eOuter = null; - var evt = new ManualResetEvent(false); - int retval = 0; - - stream.BeginRead(buf, off, len, asyncResult => - { - try - { - if (stream != null) - retval = stream.EndRead(asyncResult); - else - eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted); - } - catch (Exception e) - { - if (stream != null) - eOuter = e; - else - eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e); - } - evt.Set(); - }, null); - - evt.WaitOne(); - - if (eOuter != null) - throw eOuter; // rethrow exception - else - return retval; - } - else - { - return stream.Read(buf, off, len); - } - } - - public override void Write(byte[] buf, int off, int len) - { - if (stream == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen); - } - - // if necessary, send the data in chunks - // there's a system limit around 0x10000 bytes that we hit otherwise - // MSDN: "Pipe write operations across a network are limited to 65,535 bytes per write. For more information regarding pipes, see the Remarks section." - var nBytes = Math.Min(len, 15 * 4096); // 16 would exceed the limit - while (nBytes > 0) - { - - if (asyncMode) - { - Exception eOuter = null; - var evt = new ManualResetEvent(false); - - stream.BeginWrite(buf, off, nBytes, asyncResult => - { - try - { - if (stream != null) - stream.EndWrite(asyncResult); - else - eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted); - } - catch (Exception e) - { - if (stream != null) - eOuter = e; - else - eOuter = new TTransportException(TTransportException.ExceptionType.Interrupted, e.Message, e); - } - evt.Set(); - }, null); - - evt.WaitOne(); - - if (eOuter != null) - throw eOuter; // rethrow exception - } - else - { - stream.Write(buf, off, nBytes); - } - - off += nBytes; - len -= nBytes; - nBytes = Math.Min(len, nBytes); - } - } - - protected override void Dispose(bool disposing) - { - if (stream != null) - stream.Dispose(); - } - } - } -} \ No newline at end of file diff --git a/lib/csharp/src/Transport/TServerSocket.cs b/lib/csharp/src/Transport/TServerSocket.cs deleted file mode 100644 index d8ec62ab3f4..00000000000 --- a/lib/csharp/src/Transport/TServerSocket.cs +++ /dev/null @@ -1,176 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Net.Sockets; - - -namespace Thrift.Transport -{ - public class TServerSocket : TServerTransport - { - /// - /// Underlying server with socket. - /// - private TcpListener server = null; - - /// - /// Port to listen on. - /// - private int port = 0; - - /// - /// Timeout for client sockets from accept. - /// - private int clientTimeout = 0; - - /// - /// Whether or not to wrap new TSocket connections in buffers. - /// - private bool useBufferedSockets = false; - - /// - /// Creates a server socket from underlying socket object. - /// - public TServerSocket(TcpListener listener) - : this(listener, 0) - { - } - - /// - /// Creates a server socket from underlying socket object. - /// - public TServerSocket(TcpListener listener, int clientTimeout) - { - this.server = listener; - this.clientTimeout = clientTimeout; - } - - /// - /// Creates just a port listening server socket. - /// - public TServerSocket(int port) - : this(port, 0) - { - } - - /// - /// Creates just a port listening server socket. - /// - public TServerSocket(int port, int clientTimeout) - : this(port, clientTimeout, false) - { - } - - public TServerSocket(int port, int clientTimeout, bool useBufferedSockets) - { - this.port = port; - this.clientTimeout = clientTimeout; - this.useBufferedSockets = useBufferedSockets; - try - { - // Make server socket - this.server = TSocketVersionizer.CreateTcpListener(this.port); - this.server.Server.NoDelay = true; - } - catch (Exception ex) - { - server = null; - throw new TTransportException("Could not create ServerSocket on port " + this.port + ".", ex); - } - } - - public override void Listen() - { - // Make sure not to block on accept - if (server != null) - { - try - { - server.Start(); - } - catch (SocketException sx) - { - throw new TTransportException("Could not accept on listening socket: " + sx.Message, sx); - } - } - } - - protected override TTransport AcceptImpl() - { - if (server == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); - } - try - { - TSocket result2 = null; - TcpClient result = server.AcceptTcpClient(); - try - { - result2 = new TSocket(result); - result2.Timeout = clientTimeout; - if (useBufferedSockets) - { - TBufferedTransport result3 = new TBufferedTransport(result2); - return result3; - } - else - { - return result2; - } - } - catch (System.Exception) - { - // If a TSocket was successfully created, then let - // it do proper cleanup of the TcpClient object. - if (result2 != null) - result2.Dispose(); - else // Otherwise, clean it up ourselves. - ((IDisposable)result).Dispose(); - throw; - } - } - catch (Exception ex) - { - throw new TTransportException(ex.ToString(), ex); - } - } - - public override void Close() - { - if (server != null) - { - try - { - server.Stop(); - } - catch (Exception ex) - { - throw new TTransportException("WARNING: Could not close server socket: " + ex, ex); - } - server = null; - } - } - } -} diff --git a/lib/csharp/src/Transport/TServerTransport.cs b/lib/csharp/src/Transport/TServerTransport.cs deleted file mode 100644 index e63880be1a0..00000000000 --- a/lib/csharp/src/Transport/TServerTransport.cs +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; - -namespace Thrift.Transport -{ - public abstract class TServerTransport - { - public abstract void Listen(); - public abstract void Close(); - protected abstract TTransport AcceptImpl(); - - public TTransport Accept() - { - TTransport transport = AcceptImpl(); - if (transport == null) - { - throw new TTransportException("accept() may not return NULL"); - } - return transport; - } - } -} diff --git a/lib/csharp/src/Transport/TSilverlightSocket.cs b/lib/csharp/src/Transport/TSilverlightSocket.cs deleted file mode 100644 index 40469ab40ce..00000000000 --- a/lib/csharp/src/Transport/TSilverlightSocket.cs +++ /dev/null @@ -1,393 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -/* only for silverlight */ -#if SILVERLIGHT - -using System; -using System.Net.Sockets; -using System.IO; -using System.Net; -using System.Threading; - -namespace Thrift.Transport -{ - public class TSilverlightSocket : TTransport - { - Socket socket = null; - static ManualResetEvent readAsyncComplete = new ManualResetEvent(false); - public event EventHandler connectHandler = null; - - // memory stream for write cache. - private MemoryStream outputStream = new MemoryStream(); - - private string host = null; - private int port = 0; - private int timeout = 0; - - // constructor - public TSilverlightSocket(string host, int port) - : this(host, port, 0) - { - } - - // constructor - public TSilverlightSocket(string host, int port, int timeout) - { - this.host = host; - this.port = port; - this.timeout = timeout; - - InitSocket(); - } - - private void InitSocket() - { - // Create a stream-based, TCP socket using the InterNetwork Address Family. - socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - socket.NoDelay = true; - } - - public int Timeout - { - set - { - timeout = value; - } - } - - public string Host - { - get - { - return host; - } - } - - public int Port - { - get - { - return port; - } - } - - public override bool IsOpen - { - get - { - if (socket == null) - { - return false; - } - - return socket.Connected; - } - } - - public override void Open() - { - if (IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); - } - - if (string.IsNullOrEmpty(host)) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); - } - - if (port <= 0) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); - } - - if (socket == null) - { - InitSocket(); - } - - if (timeout == 0) // no timeout -> infinite - { - timeout = 10000; // set a default timeout for WP. - } - - { - // Create DnsEndPoint. The hostName and port are passed in to this method. - DnsEndPoint hostEntry = new DnsEndPoint(this.host, this.port); - - // Create a SocketAsyncEventArgs object to be used in the connection request - SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); - socketEventArg.RemoteEndPoint = hostEntry; - - // Inline event handler for the Completed event. - // Note: This event handler was implemented inline in order to make this method self-contained. - socketEventArg.Completed += new EventHandler(delegate(object s, SocketAsyncEventArgs e) - { - if (connectHandler != null) - { - connectHandler(this, e); - } - }); - - // Make an asynchronous Connect request over the socket - socket.ConnectAsync(socketEventArg); - } - } - - public override int Read(byte[] buf, int off, int len) - { - bool _timeout = true; - string _error = null; - int _recvBytes = -1; - - if (socket == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Socket is not open"); - } - - // Create SocketAsyncEventArgs context object - SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); - socketEventArg.RemoteEndPoint = socket.RemoteEndPoint; - - // Setup the buffer to receive the data - socketEventArg.SetBuffer(buf, off, len); - - // Inline event handler for the Completed event. - // Note: This even handler was implemented inline in order to make - // this method self-contained. - socketEventArg.Completed += new EventHandler(delegate(object s, SocketAsyncEventArgs e) - { - _timeout = false; - - if (e.SocketError == SocketError.Success) - { - _recvBytes = e.BytesTransferred; - } - else - { - _error = e.SocketError.ToString(); - } - - readAsyncComplete.Set(); - }); - - // Sets the state of the event to nonsignaled, causing threads to block - readAsyncComplete.Reset(); - - // Make an asynchronous Receive request over the socket - socket.ReceiveAsync(socketEventArg); - - // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds. - // If no response comes back within this time then proceed - readAsyncComplete.WaitOne(this.timeout); - - if (_timeout) - { - throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Socket recv timeout"); - } - - if (_error != null) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, _error); - } - - return _recvBytes; - } - - public override void Write(byte[] buf, int off, int len) - { - outputStream.Write(buf, off, len); - } - - private void beginFlush_Completed(object sender, SocketAsyncEventArgs e) - { - FlushAsyncResult flushAsyncResult = e.UserToken as FlushAsyncResult; - flushAsyncResult.UpdateStatusToComplete(); - flushAsyncResult.NotifyCallbackWhenAvailable(); - - if (e.SocketError != SocketError.Success) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, e.SocketError.ToString()); - } - } - - public override IAsyncResult BeginFlush(AsyncCallback callback, object state) - { - // Extract request and reset buffer - byte[] data = outputStream.ToArray(); - - FlushAsyncResult flushAsyncResult = new FlushAsyncResult(callback, state); - - SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs(); - socketEventArg.RemoteEndPoint = socket.RemoteEndPoint; - socketEventArg.UserToken = flushAsyncResult; - - socketEventArg.Completed += beginFlush_Completed; - socketEventArg.SetBuffer(data, 0, data.Length); - - socket.SendAsync(socketEventArg); - - return flushAsyncResult; - } - - public override void EndFlush(IAsyncResult asyncResult) - { - try - { - var flushAsyncResult = (FlushAsyncResult)asyncResult; - - if (!flushAsyncResult.IsCompleted) - { - var waitHandle = flushAsyncResult.AsyncWaitHandle; - waitHandle.WaitOne(); - waitHandle.Close(); - } - - if (flushAsyncResult.AsyncException != null) - { - throw flushAsyncResult.AsyncException; - } - } - finally - { - outputStream = new MemoryStream(); - } - } - - // Copy from impl from THttpClient.cs - // Based on http://msmvps.com/blogs/luisabreu/archive/2009/06/15/multithreading-implementing-the-iasyncresult-interface.aspx - class FlushAsyncResult : IAsyncResult - { - private volatile Boolean _isCompleted; - private ManualResetEvent _evt; - private readonly AsyncCallback _cbMethod; - private readonly object _state; - - public FlushAsyncResult(AsyncCallback cbMethod, object state) - { - _cbMethod = cbMethod; - _state = state; - } - - internal byte[] Data { get; set; } - internal Socket Connection { get; set; } - internal TTransportException AsyncException { get; set; } - - public object AsyncState - { - get { return _state; } - } - - public WaitHandle AsyncWaitHandle - { - get { return GetEvtHandle(); } - } - - public bool CompletedSynchronously - { - get { return false; } - } - - public bool IsCompleted - { - get { return _isCompleted; } - } - - private readonly object _locker = new object(); - - private ManualResetEvent GetEvtHandle() - { - lock (_locker) - { - if (_evt == null) - { - _evt = new ManualResetEvent(false); - } - if (_isCompleted) - { - _evt.Set(); - } - } - return _evt; - } - - internal void UpdateStatusToComplete() - { - _isCompleted = true; //1. set _iscompleted to true - lock (_locker) - { - if (_evt != null) - { - _evt.Set(); //2. set the event, when it exists - } - } - } - - internal void NotifyCallbackWhenAvailable() - { - if (_cbMethod != null) - { - _cbMethod(this); - } - } - } - - public override void Close() - { - if (socket != null) - { - socket.Close(); - socket = null; - } - } - -#region " IDisposable Support " - private bool _IsDisposed; - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_IsDisposed) - { - if (disposing) - { - if (outputStream != null) - { - outputStream.Dispose(); - } - outputStream = null; - if (socket != null) - { - ((IDisposable)socket).Dispose(); - } - } - } - _IsDisposed = true; - } -#endregion - } -} - - -#endif diff --git a/lib/csharp/src/Transport/TSocket.cs b/lib/csharp/src/Transport/TSocket.cs deleted file mode 100644 index d8fa335ad07..00000000000 --- a/lib/csharp/src/Transport/TSocket.cs +++ /dev/null @@ -1,245 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Net.Sockets; - -namespace Thrift.Transport -{ - public class TSocket : TStreamTransport - { - private TcpClient client = null; - private string host = null; - private int port = 0; - private int timeout = 0; - - public TSocket(TcpClient client) - { - this.client = client; - - if (IsOpen) - { - inputStream = client.GetStream(); - outputStream = client.GetStream(); - } - } - - public TSocket(string host, int port) - : this(host, port, 0) - { - } - - public TSocket(string host, int port, int timeout) - { - this.host = host; - this.port = port; - this.timeout = timeout; - - InitSocket(); - } - - private void InitSocket() - { - this.client = TSocketVersionizer.CreateTcpClient(); - this.client.ReceiveTimeout = client.SendTimeout = timeout; - this.client.Client.NoDelay = true; - } - - public int Timeout - { - set - { - client.ReceiveTimeout = client.SendTimeout = timeout = value; - } - } - - public TcpClient TcpClient - { - get - { - return client; - } - } - - public string Host - { - get - { - return host; - } - } - - public int Port - { - get - { - return port; - } - } - - public override bool IsOpen - { - get - { - if (client == null) - { - return false; - } - - return client.Connected; - } - } - - public override void Open() - { - if (IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); - } - - if (string.IsNullOrEmpty(host)) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); - } - - if (port <= 0) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); - } - - if (client == null) - { - InitSocket(); - } - - if (timeout == 0) // no timeout -> infinite - { - client.Connect(host, port); - } - else // we have a timeout -> use it - { - ConnectHelper hlp = new ConnectHelper(client); - IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp); - bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected; - if (!bConnected) - { - lock (hlp.Mutex) - { - if (hlp.CallbackDone) - { - asyncres.AsyncWaitHandle.Close(); - client.Close(); - } - else - { - hlp.DoCleanup = true; - client = null; - } - } - throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out"); - } - } - - inputStream = client.GetStream(); - outputStream = client.GetStream(); - } - - - static void ConnectCallback(IAsyncResult asyncres) - { - ConnectHelper hlp = asyncres.AsyncState as ConnectHelper; - lock (hlp.Mutex) - { - hlp.CallbackDone = true; - - try - { - if (hlp.Client.Client != null) - hlp.Client.EndConnect(asyncres); - } - catch (Exception) - { - // catch that away - } - - if (hlp.DoCleanup) - { - try - { - asyncres.AsyncWaitHandle.Close(); - } - catch (Exception) { } - - try - { - if (hlp.Client is IDisposable) - ((IDisposable)hlp.Client).Dispose(); - } - catch (Exception) { } - hlp.Client = null; - } - } - } - - private class ConnectHelper - { - public object Mutex = new object(); - public bool DoCleanup = false; - public bool CallbackDone = false; - public TcpClient Client; - public ConnectHelper(TcpClient client) - { - Client = client; - } - } - - public override void Close() - { - base.Close(); - if (client != null) - { - client.Close(); - client = null; - } - } - - #region " IDisposable Support " - private bool _IsDisposed; - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_IsDisposed) - { - if (disposing) - { - if (client != null) - ((IDisposable)client).Dispose(); - base.Dispose(disposing); - } - } - _IsDisposed = true; - } - #endregion - } -} diff --git a/lib/csharp/src/Transport/TSocketVersionizer.cs b/lib/csharp/src/Transport/TSocketVersionizer.cs deleted file mode 100644 index 8c2f8e995e8..00000000000 --- a/lib/csharp/src/Transport/TSocketVersionizer.cs +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Sockets; -using System.Reflection; -using System.Text; -#if NET45 -using System.Threading.Tasks; -#endif - -namespace Thrift.Transport -{ - /// - /// PropertyInfo for the DualMode property of the System.Net.Sockets.Socket class. Used to determine if the sockets are capable of - /// automatic IPv4 and IPv6 handling. If DualMode is present the sockets automatically handle IPv4 and IPv6 connections. - /// If the DualMode is not available the system configuration determines whether IPv4 or IPv6 is used. - /// - internal static class TSocketVersionizer - { - /// - /// Creates a TcpClient according to the capabilities of the used framework. - /// - internal static TcpClient CreateTcpClient() - { - TcpClient client = null; - -#if NET45 - client = new TcpClient(AddressFamily.InterNetworkV6); - client.Client.DualMode = true; -#else - client = new TcpClient(AddressFamily.InterNetwork); -#endif - - return client; - } - - /// - /// Creates a TcpListener according to the capabilities of the used framework. - /// - internal static TcpListener CreateTcpListener(Int32 port) - { - TcpListener listener = null; - -#if NET45 - listener = new TcpListener(System.Net.IPAddress.IPv6Any, port); - listener.Server.DualMode = true; -#else - - listener = new TcpListener(System.Net.IPAddress.Any, port); -#endif - - return listener; - } - } -} diff --git a/lib/csharp/src/Transport/TStreamTransport.cs b/lib/csharp/src/Transport/TStreamTransport.cs deleted file mode 100644 index 304599faa3e..00000000000 --- a/lib/csharp/src/Transport/TStreamTransport.cs +++ /dev/null @@ -1,128 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.IO; - -namespace Thrift.Transport -{ - public class TStreamTransport : TTransport - { - protected Stream inputStream; - protected Stream outputStream; - - protected TStreamTransport() - { - } - - public TStreamTransport(Stream inputStream, Stream outputStream) - { - this.inputStream = inputStream; - this.outputStream = outputStream; - } - - public Stream OutputStream - { - get { return outputStream; } - } - - public Stream InputStream - { - get { return inputStream; } - } - - public override bool IsOpen - { - get { return true; } - } - - public override void Open() - { - } - - public override void Close() - { - if (inputStream != null) - { - inputStream.Close(); - inputStream = null; - } - if (outputStream != null) - { - outputStream.Close(); - outputStream = null; - } - } - - public override int Read(byte[] buf, int off, int len) - { - if (inputStream == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot read from null inputstream"); - } - - return inputStream.Read(buf, off, len); - } - - public override void Write(byte[] buf, int off, int len) - { - if (outputStream == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot write to null outputstream"); - } - - outputStream.Write(buf, off, len); - } - - public override void Flush() - { - if (outputStream == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot flush null outputstream"); - } - - outputStream.Flush(); - } - - - #region " IDisposable Support " - private bool _IsDisposed; - - // IDisposable - protected override void Dispose(bool disposing) - { - if (!_IsDisposed) - { - if (disposing) - { - if (InputStream != null) - InputStream.Dispose(); - if (OutputStream != null) - OutputStream.Dispose(); - } - } - _IsDisposed = true; - } - #endregion - } -} diff --git a/lib/csharp/src/Transport/TTLSServerSocket.cs b/lib/csharp/src/Transport/TTLSServerSocket.cs deleted file mode 100644 index 716a97ca84a..00000000000 --- a/lib/csharp/src/Transport/TTLSServerSocket.cs +++ /dev/null @@ -1,223 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Net.Security; -using System.Net.Sockets; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; - -namespace Thrift.Transport -{ - /// - /// SSL Server Socket Wrapper Class - /// - public class TTLSServerSocket : TServerTransport - { - /// - /// Underlying tcp server - /// - private TcpListener server = null; - - /// - /// The port where the socket listen - /// - private int port = 0; - - /// - /// Timeout for the created server socket - /// - private readonly int clientTimeout; - - /// - /// Whether or not to wrap new TSocket connections in buffers - /// - private bool useBufferedSockets = false; - - /// - /// The servercertificate with the private- and public-key - /// - private X509Certificate serverCertificate; - - /// - /// The function to validate the client certificate. - /// - private RemoteCertificateValidationCallback clientCertValidator; - - /// - /// The function to determine which certificate to use. - /// - private LocalCertificateSelectionCallback localCertificateSelectionCallback; - - /// - /// The SslProtocols value that represents the protocol used for authentication. - /// - private readonly SslProtocols sslProtocols; - - /// - /// Initializes a new instance of the class. - /// - /// The port where the server runs. - /// The certificate object. - public TTLSServerSocket(int port, X509Certificate2 certificate) - : this(port, 0, certificate) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The port where the server runs. - /// Send/receive timeout. - /// The certificate object. - public TTLSServerSocket(int port, int clientTimeout, X509Certificate2 certificate) - : this(port, clientTimeout, false, certificate) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The port where the server runs. - /// Send/receive timeout. - /// If set to true [use buffered sockets]. - /// The certificate object. - /// The certificate validator. - /// The callback to select which certificate to use. - /// The SslProtocols value that represents the protocol used for authentication. - public TTLSServerSocket( - int port, - int clientTimeout, - bool useBufferedSockets, - X509Certificate2 certificate, - RemoteCertificateValidationCallback clientCertValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - // TODO: Enable Tls11 and Tls12 (TLS 1.1 and 1.2) by default once we start using .NET 4.5+. - SslProtocols sslProtocols = SslProtocols.Tls) - { - if (!certificate.HasPrivateKey) - { - throw new TTransportException(TTransportException.ExceptionType.Unknown, "Your server-certificate needs to have a private key"); - } - - this.port = port; - this.clientTimeout = clientTimeout; - this.serverCertificate = certificate; - this.useBufferedSockets = useBufferedSockets; - this.clientCertValidator = clientCertValidator; - this.localCertificateSelectionCallback = localCertificateSelectionCallback; - this.sslProtocols = sslProtocols; - try - { - // Create server socket - this.server = TSocketVersionizer.CreateTcpListener(this.port); - this.server.Server.NoDelay = true; - } - catch (Exception ex) - { - server = null; - throw new TTransportException("Could not create ServerSocket on port " + this.port + ".", ex); - } - } - - /// - /// Starts the server. - /// - public override void Listen() - { - // Make sure accept is not blocking - if (this.server != null) - { - try - { - this.server.Start(); - } - catch (SocketException sx) - { - throw new TTransportException("Could not accept on listening socket: " + sx.Message, sx); - } - } - } - - /// - /// Callback for Accept Implementation - /// - /// - /// TTransport-object. - /// - protected override TTransport AcceptImpl() - { - if (this.server == null) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket."); - } - - try - { - TcpClient client = this.server.AcceptTcpClient(); - client.SendTimeout = client.ReceiveTimeout = this.clientTimeout; - - //wrap the client in an SSL Socket passing in the SSL cert - TTLSSocket socket = new TTLSSocket( - client, - this.serverCertificate, - true, - this.clientCertValidator, - this.localCertificateSelectionCallback, - this.sslProtocols); - - socket.setupTLS(); - - if (useBufferedSockets) - { - TBufferedTransport trans = new TBufferedTransport(socket); - return trans; - } - else - { - return socket; - } - - } - catch (Exception ex) - { - throw new TTransportException(ex.ToString(), ex); - } - } - - /// - /// Stops the Server - /// - public override void Close() - { - if (this.server != null) - { - try - { - this.server.Stop(); - } - catch (Exception ex) - { - throw new TTransportException("WARNING: Could not close server socket: " + ex, ex); - } - this.server = null; - } - } - } -} diff --git a/lib/csharp/src/Transport/TTLSSocket.cs b/lib/csharp/src/Transport/TTLSSocket.cs deleted file mode 100644 index 06286dc8b50..00000000000 --- a/lib/csharp/src/Transport/TTLSSocket.cs +++ /dev/null @@ -1,445 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Net.Security; -using System.Net.Sockets; -using System.Security.Authentication; -using System.Security.Cryptography.X509Certificates; - -namespace Thrift.Transport -{ - /// - /// SSL Socket Wrapper class - /// - public class TTLSSocket : TStreamTransport - { - /// - /// Internal TCP Client - /// - private TcpClient client; - - /// - /// The host - /// - private string host; - - /// - /// The port - /// - private int port; - - /// - /// The timeout for the connection - /// - private int timeout; - - /// - /// Internal SSL Stream for IO - /// - private SslStream secureStream; - - /// - /// Defines wheter or not this socket is a server socket
- /// This is used for the TLS-authentication - ///
- private bool isServer; - - /// - /// The certificate - /// - private X509Certificate certificate; - - /// - /// User defined certificate validator. - /// - private RemoteCertificateValidationCallback certValidator; - - /// - /// The function to determine which certificate to use. - /// - private LocalCertificateSelectionCallback localCertificateSelectionCallback; - - /// - /// The SslProtocols value that represents the protocol used for authentication.SSL protocols to be used. - /// - private readonly SslProtocols sslProtocols; - - /// - /// Initializes a new instance of the class. - /// - /// An already created TCP-client - /// The certificate. - /// if set to true [is server]. - /// User defined cert validator. - /// The callback to select which certificate to use. - /// The SslProtocols value that represents the protocol used for authentication. - public TTLSSocket( - TcpClient client, - X509Certificate certificate, - bool isServer = false, - RemoteCertificateValidationCallback certValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - // TODO: Enable Tls11 and Tls12 (TLS 1.1 and 1.2) by default once we start using .NET 4.5+. - SslProtocols sslProtocols = SslProtocols.Tls) - { - this.client = client; - this.certificate = certificate; - this.certValidator = certValidator; - this.localCertificateSelectionCallback = localCertificateSelectionCallback; - this.sslProtocols = sslProtocols; - this.isServer = isServer; - if (isServer && certificate == null) - { - throw new ArgumentException("TTLSSocket needs certificate to be used for server", "certificate"); - } - - if (IsOpen) - { - base.inputStream = client.GetStream(); - base.outputStream = client.GetStream(); - } - } - - /// - /// Initializes a new instance of the class. - /// - /// The host, where the socket should connect to. - /// The port. - /// The certificate path. - /// User defined cert validator. - /// The callback to select which certificate to use. - /// The SslProtocols value that represents the protocol used for authentication. - public TTLSSocket( - string host, - int port, - string certificatePath, - RemoteCertificateValidationCallback certValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - SslProtocols sslProtocols = SslProtocols.Tls) - : this(host, port, 0, X509Certificate.CreateFromCertFile(certificatePath), certValidator, localCertificateSelectionCallback, sslProtocols) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The host, where the socket should connect to. - /// The port. - /// The certificate. - /// User defined cert validator. - /// The callback to select which certificate to use. - /// The SslProtocols value that represents the protocol used for authentication. - public TTLSSocket( - string host, - int port, - X509Certificate certificate = null, - RemoteCertificateValidationCallback certValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - SslProtocols sslProtocols = SslProtocols.Tls) - : this(host, port, 0, certificate, certValidator, localCertificateSelectionCallback, sslProtocols) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// The host, where the socket should connect to. - /// The port. - /// The timeout. - /// The certificate. - /// User defined cert validator. - /// The callback to select which certificate to use. - /// The SslProtocols value that represents the protocol used for authentication. - public TTLSSocket( - string host, - int port, - int timeout, - X509Certificate certificate, - RemoteCertificateValidationCallback certValidator = null, - LocalCertificateSelectionCallback localCertificateSelectionCallback = null, - SslProtocols sslProtocols = SslProtocols.Tls) - { - this.host = host; - this.port = port; - this.timeout = timeout; - this.certificate = certificate; - this.certValidator = certValidator; - this.localCertificateSelectionCallback = localCertificateSelectionCallback; - this.sslProtocols = sslProtocols; - - InitSocket(); - } - - /// - /// Creates the TcpClient and sets the timeouts - /// - private void InitSocket() - { - client = TSocketVersionizer.CreateTcpClient(); - client.ReceiveTimeout = client.SendTimeout = timeout; - client.Client.NoDelay = true; - } - - /// - /// Sets Send / Recv Timeout for IO - /// - public int Timeout - { - set - { - this.client.ReceiveTimeout = this.client.SendTimeout = this.timeout = value; - } - } - - /// - /// Gets the TCP client. - /// - public TcpClient TcpClient - { - get - { - return client; - } - } - - /// - /// Gets the host. - /// - public string Host - { - get - { - return host; - } - } - - /// - /// Gets the port. - /// - public int Port - { - get - { - return port; - } - } - - /// - /// Gets a value indicating whether TCP Client is Cpen - /// - public override bool IsOpen - { - get - { - if (this.client == null) - { - return false; - } - - return this.client.Connected; - } - } - - /// - /// Validates the certificates!
- ///
- /// The sender-object. - /// The used certificate. - /// The certificate chain. - /// An enum, which lists all the errors from the .NET certificate check. - /// - private bool DefaultCertificateValidator(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslValidationErrors) - { - return (sslValidationErrors == SslPolicyErrors.None); - } - - /// - /// Connects to the host and starts the routine, which sets up the TLS - /// - public override void Open() - { - if (IsOpen) - { - throw new TTransportException(TTransportException.ExceptionType.AlreadyOpen, "Socket already connected"); - } - - if (string.IsNullOrEmpty(host)) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open null host"); - } - - if (port <= 0) - { - throw new TTransportException(TTransportException.ExceptionType.NotOpen, "Cannot open without port"); - } - - if (client == null) - { - InitSocket(); - } - - if (timeout == 0) // no timeout -> infinite - { - client.Connect(host, port); - } - else // we have a timeout -> use it - { - ConnectHelper hlp = new ConnectHelper(client); - IAsyncResult asyncres = client.BeginConnect(host, port, new AsyncCallback(ConnectCallback), hlp); - bool bConnected = asyncres.AsyncWaitHandle.WaitOne(timeout) && client.Connected; - if (!bConnected) - { - lock (hlp.Mutex) - { - if (hlp.CallbackDone) - { - asyncres.AsyncWaitHandle.Close(); - client.Close(); - } - else - { - hlp.DoCleanup = true; - client = null; - } - } - throw new TTransportException(TTransportException.ExceptionType.TimedOut, "Connect timed out"); - } - } - - setupTLS(); - } - - /// - /// Creates a TLS-stream and lays it over the existing socket - /// - public void setupTLS() - { - RemoteCertificateValidationCallback validator = this.certValidator ?? DefaultCertificateValidator; - - if (this.localCertificateSelectionCallback != null) - { - this.secureStream = new SslStream( - this.client.GetStream(), - false, - validator, - this.localCertificateSelectionCallback - ); - } - else - { - this.secureStream = new SslStream( - this.client.GetStream(), - false, - validator - ); - } - - try - { - if (isServer) - { - // Server authentication - this.secureStream.AuthenticateAsServer(this.certificate, this.certValidator != null, sslProtocols, true); - } - else - { - // Client authentication - X509CertificateCollection certs = certificate != null ? new X509CertificateCollection { certificate } : new X509CertificateCollection(); - this.secureStream.AuthenticateAsClient(host, certs, sslProtocols, true); - } - } - catch (Exception) - { - this.Close(); - throw; - } - - inputStream = this.secureStream; - outputStream = this.secureStream; - } - - static void ConnectCallback(IAsyncResult asyncres) - { - ConnectHelper hlp = asyncres.AsyncState as ConnectHelper; - lock (hlp.Mutex) - { - hlp.CallbackDone = true; - - try - { - if (hlp.Client.Client != null) - hlp.Client.EndConnect(asyncres); - } - catch (Exception) - { - // catch that away - } - - if (hlp.DoCleanup) - { - try - { - asyncres.AsyncWaitHandle.Close(); - } - catch (Exception) { } - - try - { - if (hlp.Client is IDisposable) - ((IDisposable)hlp.Client).Dispose(); - } - catch (Exception) { } - hlp.Client = null; - } - } - } - - private class ConnectHelper - { - public object Mutex = new object(); - public bool DoCleanup = false; - public bool CallbackDone = false; - public TcpClient Client; - public ConnectHelper(TcpClient client) - { - Client = client; - } - } - - /// - /// Closes the SSL Socket - /// - public override void Close() - { - base.Close(); - if (this.client != null) - { - this.client.Close(); - this.client = null; - } - - if (this.secureStream != null) - { - this.secureStream.Close(); - this.secureStream = null; - } - } - } -} diff --git a/lib/csharp/src/Transport/TTransport.cs b/lib/csharp/src/Transport/TTransport.cs deleted file mode 100644 index 5e4ac22ea90..00000000000 --- a/lib/csharp/src/Transport/TTransport.cs +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; -using System.IO; - -namespace Thrift.Transport -{ - public abstract class TTransport : IDisposable - { - public abstract bool IsOpen - { - get; - } - - private byte[] _peekBuffer = new byte[1]; - private bool _hasPeekByte; - - public bool Peek() - { - //If we already have a byte read but not consumed, do nothing. - if (_hasPeekByte) - return true; - - //If transport closed we can't peek. - if (!IsOpen) - return false; - - //Try to read one byte. If succeeds we will need to store it for the next read. - try - { - int bytes = Read(_peekBuffer, 0, 1); - if (bytes == 0) - return false; - } - catch (IOException) - { - return false; - } - - _hasPeekByte = true; - return true; - } - - public abstract void Open(); - - public abstract void Close(); - - protected static void ValidateBufferArgs(byte[] buf, int off, int len) - { - if (buf == null) - throw new ArgumentNullException("buf"); - if (off < 0) - throw new ArgumentOutOfRangeException("Buffer offset is smaller than zero."); - if (len < 0) - throw new ArgumentOutOfRangeException("Buffer length is smaller than zero."); - if (off + len > buf.Length) - throw new ArgumentOutOfRangeException("Not enough data."); - } - - public abstract int Read(byte[] buf, int off, int len); - - public int ReadAll(byte[] buf, int off, int len) - { - ValidateBufferArgs(buf, off, len); - int got = 0; - - //If we previously peeked a byte, we need to use that first. - if (_hasPeekByte) - { - buf[off + got++] = _peekBuffer[0]; - _hasPeekByte = false; - } - - while (got < len) - { - int ret = Read(buf, off + got, len - got); - if (ret <= 0) - { - throw new TTransportException( - TTransportException.ExceptionType.EndOfFile, - "Cannot read, Remote side has closed"); - } - got += ret; - } - return got; - } - - public virtual void Write(byte[] buf) - { - Write(buf, 0, buf.Length); - } - - public abstract void Write(byte[] buf, int off, int len); - - public virtual void Flush() - { - } - - public virtual IAsyncResult BeginFlush(AsyncCallback callback, object state) - { - throw new TTransportException( - TTransportException.ExceptionType.Unknown, - "Asynchronous operations are not supported by this transport."); - } - - public virtual void EndFlush(IAsyncResult asyncResult) - { - throw new TTransportException( - TTransportException.ExceptionType.Unknown, - "Asynchronous operations are not supported by this transport."); - } - - #region " IDisposable Support " - // IDisposable - protected abstract void Dispose(bool disposing); - - public void Dispose() - { - // Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above. - Dispose(true); - GC.SuppressFinalize(this); - } - #endregion - } -} diff --git a/lib/csharp/src/Transport/TTransportException.cs b/lib/csharp/src/Transport/TTransportException.cs deleted file mode 100644 index 7f6cc1889ea..00000000000 --- a/lib/csharp/src/Transport/TTransportException.cs +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; - -namespace Thrift.Transport -{ - public class TTransportException : TException - { - protected ExceptionType type; - - public TTransportException() - : base() - { - } - - public TTransportException(ExceptionType type) - : this() - { - this.type = type; - } - - public TTransportException(ExceptionType type, string message, Exception inner = null) - : base(message, inner) - { - this.type = type; - } - - public TTransportException(string message, Exception inner = null) - : base(message, inner) - { - } - - public ExceptionType Type - { - get { return type; } - } - - public enum ExceptionType - { - Unknown, - NotOpen, - AlreadyOpen, - TimedOut, - EndOfFile, - Interrupted - } - } -} diff --git a/lib/csharp/src/Transport/TTransportFactory.cs b/lib/csharp/src/Transport/TTransportFactory.cs deleted file mode 100644 index 47a0c62651a..00000000000 --- a/lib/csharp/src/Transport/TTransportFactory.cs +++ /dev/null @@ -1,42 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - * Contains some contributions under the Thrift Software License. - * Please see doc/old-thrift-license.txt in the Thrift distribution for - * details. - */ - -using System; - -namespace Thrift.Transport -{ - /// - /// From Mark Slee & Aditya Agarwal of Facebook: - /// 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 - { - public virtual TTransport GetTransport(TTransport trans) - { - return trans; - } - } -} diff --git a/lib/csharp/src/thrift.snk b/lib/csharp/src/thrift.snk deleted file mode 100644 index 97bc5812b81ce10bd7a3e7fa85ffe4fca58837a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096M(P*E7L9A{Nz%0-6F4Ni!Qh(Kbg{5KA z2E1b23-+!Xd}C$U<2C<(&MT@p-O1qWT;=lE^6FoDjaj)hfK()avE=qA0UjD_dnyJKp4oD4IAF%k%(##bch;%0k!ErNuo!=V%U6um{k+ zxGJw2Q3!4o9q~6a_(HZlq8e8vm^F-F8s*Oq9GC*du(tuh3*S(r46R#&$m*dVSmw9< zkJro_Em0r8sB0u|@B$Ms&W(3}U!PWN$0Rb0UTs5hRh#5^;9Sd{Oc1;2rF@$Tv@h%{ iLR4J<2AKHW9M~)kpNz1bB-?e{-!;;q{yCP(dwHkK- diff --git a/lib/csharp/test/JSON/JSONTest.csproj b/lib/csharp/test/JSON/JSONTest.csproj deleted file mode 100644 index f07d43eece1..00000000000 --- a/lib/csharp/test/JSON/JSONTest.csproj +++ /dev/null @@ -1,85 +0,0 @@ - - - - - Debug - x86 - 8.0.30703 - 2.0 - {E37A0034-DCBF-4886-A0DA-25A03D12D975} - Exe - Properties - JSONTest - JSONTest - v4.0 - - - 512 - - - x86 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - x86 - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - {499EB63C-D74C-47E8-AE48-A2FC94538E9D} - Thrift - - - - - \ No newline at end of file diff --git a/lib/csharp/test/JSON/Program.cs b/lib/csharp/test/JSON/Program.cs deleted file mode 100644 index f61388ae7c2..00000000000 --- a/lib/csharp/test/JSON/Program.cs +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using Thrift.Protocol; -using Thrift.Transport; - -namespace JSONTest -{ - class Program - { - static void Main(string[] args) - { - TestThrift2365(); // JSON binary decodes too much data - TestThrift2336(); // hex encoding using \uXXXX where 0xXXXX > 0xFF - TestThrift3403(); // JSON escaped unicode surrogate pair support. - } - - - public static void TestThrift2365() - { - var rnd = new Random(); - for (var len = 0; len < 10; ++len) - { - byte[] dataWritten = new byte[len]; - rnd.NextBytes(dataWritten); - - Stream stm = new MemoryStream(); - TTransport trans = new TStreamTransport(null, stm); - TProtocol prot = new TJSONProtocol(trans); - prot.WriteBinary(dataWritten); - - stm.Position = 0; - trans = new TStreamTransport(stm, null); - prot = new TJSONProtocol(trans); - byte[] dataRead = prot.ReadBinary(); - - Debug.Assert(dataRead.Length == dataWritten.Length); - for (var i = 0; i < dataRead.Length; ++i) - Debug.Assert(dataRead[i] == dataWritten[i]); - } - } - - - public static void TestThrift2336() - { - const string RUSSIAN_TEXT = "\u0420\u0443\u0441\u0441\u043a\u043e\u0435 \u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435"; - const string RUSSIAN_JSON = "\"\\u0420\\u0443\\u0441\\u0441\\u043a\\u043e\\u0435 \\u041d\\u0430\\u0437\\u0432\\u0430\\u043d\\u0438\\u0435\""; - - // prepare buffer with JSON data - byte[] rawBytes = new byte[RUSSIAN_JSON.Length]; - for (var i = 0; i < RUSSIAN_JSON.Length; ++i) - rawBytes[i] = (byte)(RUSSIAN_JSON[i] & (char)0xFF); // only low bytes - - // parse and check - var stm = new MemoryStream(rawBytes); - var trans = new TStreamTransport(stm, null); - var prot = new TJSONProtocol(trans); - Debug.Assert(prot.ReadString() == RUSSIAN_TEXT, "reading JSON with hex-encoded chars > 8 bit"); - } - - public static void TestThrift3403() - { - string GCLEF_TEXT = "\ud834\udd1e"; - const string GCLEF_JSON = "\"\\ud834\\udd1e\""; - - // parse and check - var stm = new MemoryStream(Encoding.UTF8.GetBytes(GCLEF_JSON)); - var trans = new TStreamTransport(stm, null); - var prot = new TJSONProtocol(trans); - Debug.Assert(prot.ReadString() == GCLEF_TEXT, "reading JSON with surrogate pair hex-encoded chars"); - } - } -} diff --git a/lib/csharp/test/JSON/Properties/AssemblyInfo.cs b/lib/csharp/test/JSON/Properties/AssemblyInfo.cs deleted file mode 100644 index fdff4a1a5c4..00000000000 --- a/lib/csharp/test/JSON/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über die folgenden -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die mit einer Assembly verknüpft sind. -[assembly: AssemblyTitle("JSONTest")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von -// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("2b2e7d56-3e65-4368-92d7-e34d56b7105e")] - -// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: -// -// Hauptversion -// Nebenversion -// Buildnummer -// Revision -// -// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern -// übernehmen, indem Sie "*" eingeben: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/lib/csharp/test/JSON/app.config b/lib/csharp/test/JSON/app.config deleted file mode 100644 index 9c1919d4fd3..00000000000 --- a/lib/csharp/test/JSON/app.config +++ /dev/null @@ -1,21 +0,0 @@ - - - - diff --git a/lib/csharp/test/Multiplex/Client/Multiplex.Test.Client.cs b/lib/csharp/test/Multiplex/Client/Multiplex.Test.Client.cs deleted file mode 100644 index c810a08917f..00000000000 --- a/lib/csharp/test/Multiplex/Client/Multiplex.Test.Client.cs +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Collections.Generic; -using Thrift.Collections; -using Thrift.Transport; -using Thrift.Protocol; -using Thrift.Server; -using Thrift; -using Test.Multiplex; - -namespace Test.Multiplex.Client -{ - public class TestClient - { - static void Execute(int port) - { - try - { - TTransport trans; - trans = new TSocket("localhost", port); - trans = new TFramedTransport(trans); - trans.Open(); - - TProtocol Protocol = new TBinaryProtocol(trans, true, true); - - TMultiplexedProtocol multiplex; - - multiplex = new TMultiplexedProtocol(Protocol, Constants.NAME_BENCHMARKSERVICE); - BenchmarkService.Iface bench = new BenchmarkService.Client(multiplex); - - multiplex = new TMultiplexedProtocol(Protocol, Constants.NAME_AGGR); - Aggr.Iface aggr = new Aggr.Client(multiplex); - - for (sbyte i = 1; 10 >= i; ++i) - { - aggr.addValue(bench.fibonacci(i)); - } - - foreach (int k in aggr.getValues()) - { - Console.Write(k.ToString() + " "); - Console.WriteLine(""); - } - trans.Close(); - } - catch (Exception e) - { - Console.WriteLine(e.Message); - } - } - - static void Main(string[] args) - { - int port = 9090; - if (args.Length > 0) - { - port = ushort.Parse(args[0]); - } - Execute(port); - Console.WriteLine("done."); - } - } -} - diff --git a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj b/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj deleted file mode 100644 index 551640ba6ba..00000000000 --- a/lib/csharp/test/Multiplex/Client/MultiplexClient.csproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {5E91DA17-E548-415F-8C9F-9E84EDF8EE06} - Exe - Properties - MultiplexClient - MultiplexClient - v3.5 - 512 - false - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 0.14.0.0 - false - true - - - true - full - false - ..\bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - - - - - Multiplex.Test.Common.cs - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 2.0 %28x86%29 - false - - - False - .NET Framework 3.0 %28x86%29 - false - - - False - .NET Framework 3.5 - true - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 3.1 - true - - - - - {499EB63C-D74C-47E8-AE48-A2FC94538E9D} - Thrift - - - - - - rmdir /s /q "$(ProjectDir)gen-csharp" -del /f /q "$(ProjectDir)ThriftImpl.dll" -SET OUTPUT_DIR=$(ProjectDir) - -SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\contrib\async-test\aggr.thrift -for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI -for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI -"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 - -SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\lib\rb\benchmark\Benchmark.thrift -for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI -for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI -"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 - - - - diff --git a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs deleted file mode 100644 index ce6692fb0d3..00000000000 --- a/lib/csharp/test/Multiplex/Client/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MultiplexClient")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("66FC61E5-420B-4b56-8012-D6D6CE22537F")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.14.0.0")] -[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/lib/csharp/test/Multiplex/Makefile.am b/lib/csharp/test/Multiplex/Makefile.am deleted file mode 100644 index 9c1f1b8b75c..00000000000 --- a/lib/csharp/test/Multiplex/Makefile.am +++ /dev/null @@ -1,63 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -GENERATED = \ - gen-csharp/Aggr.cs \ - gen-csharp/BenchmarkService.cs \ - gen-csharp/Error.cs - -BUILT_SOURCES = $(GENERATED) - -THRIFT = $(top_builddir)/compiler/cpp/thrift - -gen-csharp/Aggr.cs: $(top_srcdir)/contrib/async-test/aggr.thrift - $(THRIFT) --gen csharp $< - -gen-csharp/BenchmarkService.cs gen-csharp/Error.cs: $(top_srcdir)/lib/rb/benchmark/Benchmark.thrift - $(THRIFT) --gen csharp $< - -ThriftImpl.dll: Multiplex.Test.Common.cs $(GENERATED) ../../Thrift.dll - $(CSC) $(CSC_DEFINES) -t:library -out:./ThriftImpl.dll -reference:../../Thrift.dll $(GENERATED) $< - -MultiplexClient.exe: Client/Multiplex.Test.Client.cs ThriftImpl.dll - $(CSC) $(CSC_DEFINES) -out:$@ -reference:../../Thrift.dll -reference:ThriftImpl.dll $< - -MultiplexServer.exe: Server/Multiplex.Test.Server.cs ThriftImpl.dll - $(CSC) $(CSC_DEFINES) -out:$@ -reference:../../Thrift.dll -reference:ThriftImpl.dll $< - -CLEANFILES = \ - MultiplexClient.exe \ - MultiplexServer.exe \ - ThriftImpl.dll - -DISTCLEANFILES = \ - Makefile.in - -clean-local: - $(RM) -rf gen-csharp - -dist-hook: - $(RM) -r $(distdir)/gen-csharp/ - -TESTPORT = 9501 -check-local: MultiplexServer.exe MultiplexClient.exe - echo $(TESTPORT) - MONO_PATH=../../ timeout 10 mono MultiplexServer.exe $(TESTPORT) & - sleep 1 - MONO_PATH=../../ mono MultiplexClient.exe $(TESTPORT) diff --git a/lib/csharp/test/Multiplex/Multiplex.Test.Common.cs b/lib/csharp/test/Multiplex/Multiplex.Test.Common.cs deleted file mode 100644 index a687852d91c..00000000000 --- a/lib/csharp/test/Multiplex/Multiplex.Test.Common.cs +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// Distributed under the Thrift Software License -// -// See accompanying file LICENSE or visit the Thrift site at: -// http://developers.facebook.com/thrift/ -using System; -using System.Collections.Generic; -using Thrift.Collections; -using Thrift.Transport; -using Thrift.Protocol; -using Thrift.Server; - -namespace Test.Multiplex -{ - public class Constants - { - public const string NAME_BENCHMARKSERVICE = "BenchmarkService"; - public const string NAME_AGGR = "Aggr"; - } -} - - diff --git a/lib/csharp/test/Multiplex/Server/Multiplex.Test.Server.cs b/lib/csharp/test/Multiplex/Server/Multiplex.Test.Server.cs deleted file mode 100644 index 9786189bb31..00000000000 --- a/lib/csharp/test/Multiplex/Server/Multiplex.Test.Server.cs +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Collections.Generic; -using Thrift.Collections; -using Thrift.Transport; -using Thrift.Protocol; -using Thrift.Server; -using Thrift; -using Test.Multiplex; - -namespace Test.Multiplex.Server -{ - public class TestServer - { - class BenchmarkServiceImpl : BenchmarkService.Iface - { - public int fibonacci(sbyte n) - { - int prev, next, result; - prev = 0; - result = 1; - while (n > 0) - { - next = result + prev; - prev = result; - result = next; - --n; - } - return result; - } - } - - class AggrServiceImpl : Aggr.Iface - { - List values = new List(); - - public void addValue(int value) - { - values.Add(value); - } - - public List getValues() - { - return values; - } - } - - static void Execute(int port) - { - try - { - // create protocol factory, default to BinaryProtocol - TProtocolFactory ProtocolFactory = new TBinaryProtocol.Factory(true,true); - TServerTransport servertrans = new TServerSocket(port, 0, false); - TTransportFactory TransportFactory = new TFramedTransport.Factory(); - - BenchmarkService.Iface benchHandler = new BenchmarkServiceImpl(); - TProcessor benchProcessor = new BenchmarkService.Processor(benchHandler); - - Aggr.Iface aggrHandler = new AggrServiceImpl(); - TProcessor aggrProcessor = new Aggr.Processor(aggrHandler); - - TMultiplexedProcessor multiplex = new TMultiplexedProcessor(); - multiplex.RegisterProcessor(Constants.NAME_BENCHMARKSERVICE, benchProcessor); - multiplex.RegisterProcessor(Constants.NAME_AGGR, aggrProcessor); - - TServer ServerEngine = new TSimpleServer(multiplex, servertrans, TransportFactory, ProtocolFactory); - - Console.WriteLine("Starting the server ..."); - ServerEngine.Serve(); - } - catch (Exception e) - { - Console.WriteLine(e.Message); - } - } - - static void Main(string[] args) - { - int port = 9090; - if (args.Length > 0) - { - port = ushort.Parse(args[0]); - } - Execute(port); - } - } -} - diff --git a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj b/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj deleted file mode 100644 index 771ee1266e0..00000000000 --- a/lib/csharp/test/Multiplex/Server/MultiplexServer.csproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {D592BDF3-0DCE-48FB-890F-E4AE1D9CE7CD} - Exe - Properties - MultiplexServer - MultiplexServer - v3.5 - 512 - false - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 0.14.0.0 - false - true - - - true - full - false - ..\bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - - - - - Multiplex.Test.Common.cs - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 2.0 %28x86%29 - false - - - False - .NET Framework 3.0 %28x86%29 - false - - - False - .NET Framework 3.5 - true - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 3.1 - true - - - - - {499EB63C-D74C-47E8-AE48-A2FC94538E9D} - Thrift - - - - - - rmdir /s /q "$(ProjectDir)gen-csharp" -del /f /q "$(ProjectDir)ThriftImpl.dll" -SET OUTPUT_DIR=$(ProjectDir) - -SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\contrib\async-test\aggr.thrift -for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI -for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI -"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 - -SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\..\lib\rb\benchmark\Benchmark.thrift -for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI -for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI -"$(ProjectDir)\..\..\..\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 - - - - diff --git a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs b/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs deleted file mode 100644 index 50b11af2b23..00000000000 --- a/lib/csharp/test/Multiplex/Server/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MultiplexServer")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("F2F436C1-3D4F-411a-ADC3-B98848476A8E")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.14.0.0")] -[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/lib/csharp/test/ThriftMVCTest/App_Start/FilterConfig.cs b/lib/csharp/test/ThriftMVCTest/App_Start/FilterConfig.cs deleted file mode 100644 index 855184fd23f..00000000000 --- a/lib/csharp/test/ThriftMVCTest/App_Start/FilterConfig.cs +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Web.Mvc; - -namespace ThriftMVCTest -{ - public static class FilterConfig - { - public static void RegisterGlobalFilters(GlobalFilterCollection filters) - { - filters.Add(new HandleErrorAttribute()); - } - } -} diff --git a/lib/csharp/test/ThriftMVCTest/App_Start/RouteConfig.cs b/lib/csharp/test/ThriftMVCTest/App_Start/RouteConfig.cs deleted file mode 100644 index b4b6023d69a..00000000000 --- a/lib/csharp/test/ThriftMVCTest/App_Start/RouteConfig.cs +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Web.Mvc; -using System.Web.Routing; - -namespace ThriftMVCTest -{ - public static class RouteConfig - { - public static void RegisterRoutes(RouteCollection routes) - { - routes.IgnoreRoute("{resource}.thrift"); - routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); - - routes.MapRoute( - name: "Default", - url: "{controller}/{action}/{id}", - defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } - ); - } - } -} diff --git a/lib/csharp/test/ThriftMVCTest/AsyncHttpHandler.cs b/lib/csharp/test/ThriftMVCTest/AsyncHttpHandler.cs deleted file mode 100644 index 7f26184fac0..00000000000 --- a/lib/csharp/test/ThriftMVCTest/AsyncHttpHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using Thrift.Transport; - -namespace ThriftMVCTest -{ - public class AsyncHttpHandler : THttpTaskAsyncHandler - { - public AsyncHttpHandler() - : base( - new Thrift.Test.SecondService.AsyncProcessor(new SecondServiceImpl())) - { - } - } -} \ No newline at end of file diff --git a/lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs b/lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs deleted file mode 100644 index c9a1ec43fdd..00000000000 --- a/lib/csharp/test/ThriftMVCTest/Controllers/HomeController.cs +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Threading.Tasks; -using System.Web.Mvc; -using Thrift.Protocol; -using Thrift.Test; -using Thrift.Transport; - -namespace ThriftMVCTest.Controllers -{ - public class HomeController : Controller - { - public ActionResult Index() - { - return View(); - } - - public async Task TestThriftAsync() - { - var baseUri = new Uri(string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, - Url.Content("~"))); - - SecondService.IAsync asyncService = - new SecondService.Client(new TBinaryProtocol(new THttpClient(new Uri(baseUri, "Async.thrift")))); - - var result = await asyncService.secondtestStringAsync("TestString"); - if (result != "testString(\"TestString\")") - { - throw new Exception("The wrong result was returned"); - } - - return RedirectToAction("Index"); - } - - public ActionResult TestThriftSync() - { - var baseUri = new Uri(string.Format("{0}://{1}{2}", Request.Url.Scheme, Request.Url.Authority, - Url.Content("~"))); - - SecondService.ISync service = - new SecondService.Client(new TBinaryProtocol(new THttpClient(new Uri(baseUri, "Sync.thrift")))); - - var result = service.secondtestString("TestString"); - if (result != "testString(\"TestString\")") - { - throw new Exception("The wrong result was returned"); - } - - return RedirectToAction("Index"); - } - } -} diff --git a/lib/csharp/test/ThriftMVCTest/Global.asax b/lib/csharp/test/ThriftMVCTest/Global.asax deleted file mode 100644 index 7bb688c7ae7..00000000000 --- a/lib/csharp/test/ThriftMVCTest/Global.asax +++ /dev/null @@ -1,19 +0,0 @@ -<%@ Application Codebehind="Global.asax.cs" Inherits="ThriftMVCTest.MvcApplication" Language="C#" %> - diff --git a/lib/csharp/test/ThriftMVCTest/Global.asax.cs b/lib/csharp/test/ThriftMVCTest/Global.asax.cs deleted file mode 100644 index 59731efb3b5..00000000000 --- a/lib/csharp/test/ThriftMVCTest/Global.asax.cs +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Web.Mvc; -using System.Web.Routing; - -namespace ThriftMVCTest -{ - public class MvcApplication : System.Web.HttpApplication - { - protected void Application_Start() - { - AreaRegistration.RegisterAllAreas(); - FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); - RouteConfig.RegisterRoutes(RouteTable.Routes); - } - } -} diff --git a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs b/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs deleted file mode 100644 index a87107cb992..00000000000 --- a/lib/csharp/test/ThriftMVCTest/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ThriftMVCTest")] -[assembly: AssemblyDescription("A web project for testing the thrift ASP.NET features.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("366f9bd0-3c0e-48aa-b2ca-61fd4a93e427")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -[assembly: AssemblyVersion("0.14.0.0")] -[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs b/lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs deleted file mode 100644 index fad301a351a..00000000000 --- a/lib/csharp/test/ThriftMVCTest/SecondServiceImpl.cs +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Threading.Tasks; -using Thrift.Test; - -namespace ThriftMVCTest -{ - public class SecondServiceImpl : SecondService.IAsync, SecondService.ISync - { - public Task secondtestStringAsync(string thing) - { - return Task.FromResult(thing); - } - - public string secondtestString(string thing) - { - return "testString(\"" + thing + "\")"; - } - } -} diff --git a/lib/csharp/test/ThriftMVCTest/SyncHttpHandler.cs b/lib/csharp/test/ThriftMVCTest/SyncHttpHandler.cs deleted file mode 100644 index 4fe26624a2d..00000000000 --- a/lib/csharp/test/ThriftMVCTest/SyncHttpHandler.cs +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using Thrift.Transport; - -namespace ThriftMVCTest -{ - public class SyncHttpHandler : THttpHandler - { - public SyncHttpHandler() - : base( - new Thrift.Test.SecondService.Processor(new SecondServiceImpl())) - { - } - } -} \ No newline at end of file diff --git a/lib/csharp/test/ThriftMVCTest/ThriftMVCTest.csproj b/lib/csharp/test/ThriftMVCTest/ThriftMVCTest.csproj deleted file mode 100644 index 0eb969a04c2..00000000000 --- a/lib/csharp/test/ThriftMVCTest/ThriftMVCTest.csproj +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - Debug - AnyCPU - - - 2.0 - {891B4487-C7BA-427E-BBC8-4C596C229A10} - {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} - Library - Properties - ThriftMVCTest - ThriftMVCTest - v4.5 - false - true - - - - - - - true - full - false - bin\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - - - True - ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll - - - - - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll - - - True - ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll - - - True - ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll - - - True - ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll - - - .\ThriftImpl.dll - - - - - - - - - - Global.asax - - - - - - - - - - Web.config - - - Web.config - - - - - - - - - - - - Designer - - - - - {ebce35da-cf6a-42bc-a357-a9c09b534299} - Thrift.45 - - - - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - - - - - - - - - - - - True - True - 57482 - / - http://localhost:57482/ - False - False - - - False - - - - - - rmdir /s /q "$(ProjectDir)gen-csharp" -del /f /q "$(ProjectDir)ThriftImpl.dll" -SET OUTPUT_DIR=$(ProjectDir) -SET THRIFT_FILE=$(ProjectDir)\..\..\..\..\test\ThriftTest.thrift -for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI -for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI -"$(ProjectDir)\..\..\..\..\compiler\cpp\Debug\thrift.exe" --gen csharp:async=true -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 -"$(MSBuildToolsPath)\Csc.exe" /t:library /out:"$(ProjectDir)ThriftImpl.dll" /recurse:"$(ProjectDir)gen-csharp"\* /reference:"$(ProjectDir)..\..\src\bin\Debug\Thrift45.dll" - - - \ No newline at end of file diff --git a/lib/csharp/test/ThriftMVCTest/Views/Home/Index.cshtml b/lib/csharp/test/ThriftMVCTest/Views/Home/Index.cshtml deleted file mode 100644 index f0ca7da209e..00000000000 --- a/lib/csharp/test/ThriftMVCTest/Views/Home/Index.cshtml +++ /dev/null @@ -1,25 +0,0 @@ -@* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*@ - -@{ - ViewBag.Title = "Home Page"; -} - -

@Html.ActionLink("Test Thrift Async Service", "TestThriftAsync")

-

@Html.ActionLink("Test Thrift Sync Service", "TestThriftSync")

diff --git a/lib/csharp/test/ThriftMVCTest/Views/Shared/_Layout.cshtml b/lib/csharp/test/ThriftMVCTest/Views/Shared/_Layout.cshtml deleted file mode 100644 index b41c99a100f..00000000000 --- a/lib/csharp/test/ThriftMVCTest/Views/Shared/_Layout.cshtml +++ /dev/null @@ -1,30 +0,0 @@ -@* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*@ - - - - - - - Thrift ASP.NET Test - - - @RenderBody() - - diff --git a/lib/csharp/test/ThriftMVCTest/Views/Web.config b/lib/csharp/test/ThriftMVCTest/Views/Web.config deleted file mode 100644 index 3c211387a95..00000000000 --- a/lib/csharp/test/ThriftMVCTest/Views/Web.config +++ /dev/null @@ -1,60 +0,0 @@ - - - - - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/csharp/test/ThriftMVCTest/Views/_ViewStart.cshtml b/lib/csharp/test/ThriftMVCTest/Views/_ViewStart.cshtml deleted file mode 100644 index 8cde2eeb95a..00000000000 --- a/lib/csharp/test/ThriftMVCTest/Views/_ViewStart.cshtml +++ /dev/null @@ -1,22 +0,0 @@ -@* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, - software distributed under the License is distributed on an - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - KIND, either express or implied. See the License for the - specific language governing permissions and limitations - under the License. -*@ - -@{ - Layout = "~/Views/Shared/_Layout.cshtml"; -} diff --git a/lib/csharp/test/ThriftMVCTest/Web.Debug.config b/lib/csharp/test/ThriftMVCTest/Web.Debug.config deleted file mode 100644 index 45d56d80993..00000000000 --- a/lib/csharp/test/ThriftMVCTest/Web.Debug.config +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - diff --git a/lib/csharp/test/ThriftMVCTest/Web.Release.config b/lib/csharp/test/ThriftMVCTest/Web.Release.config deleted file mode 100644 index 157c340ca86..00000000000 --- a/lib/csharp/test/ThriftMVCTest/Web.Release.config +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - diff --git a/lib/csharp/test/ThriftMVCTest/Web.config b/lib/csharp/test/ThriftMVCTest/Web.config deleted file mode 100644 index 9c57d117cd7..00000000000 --- a/lib/csharp/test/ThriftMVCTest/Web.config +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib/csharp/test/ThriftMVCTest/favicon.ico b/lib/csharp/test/ThriftMVCTest/favicon.ico deleted file mode 100644 index a3a799985c43bc7309d701b2cad129023377dc71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32038 zcmeHwX>eTEbtY7aYbrGrkNjgie?1jXjZ#zP%3n{}GObKv$BxI7Sl;Bwl5E+Qtj&t8 z*p|m4DO#HoJC-FyvNnp8NP<{Na0LMnTtO21(rBP}?EAiNjWgeO?z`{3ZoURUQlV2d zY1Pqv{m|X_oO91|?^z!6@@~od!@OH>&BN;>c@O+yUfy5w>LccTKJJ&`-k<%M^Zvi( z<$dKp=jCnNX5Qa+M_%6g|IEv~4R84q9|7E=|Ho(Wz3f-0wPjaRL;W*N^>q%^KGRr7 zxbjSORb_c&eO;oV_DZ7ua!sPH=0c+W;`vzJ#j~-x3uj};50#vqo*0w4!LUqs*UCh9 zvy2S%$#8$K4EOa&e@~aBS65_hc~Mpu=454VT2^KzWqEpBA=ME|O;1cn?8p<+{MKJf zbK#@1wzL44m$k(?85=Obido7=C|xWKe%66$z)NrzRwR>?hK?_bbwT z@Da?lBrBL}Zemo1@!9pYRau&!ld17h{f+UV0sY(R{ET$PBB|-=Nr@l-nY6w8HEAw* zRMIQU`24Jl_IFEPcS=_HdrOP5yf81z_?@M>83Vv65$QFr9nPg(wr`Ke8 zaY4ogdnMA*F7a4Q1_uXadTLUpCk;$ZPRRJ^sMOch;rlbvUGc1R9=u;dr9YANbQ<4Z z#P|Cp9BP$FXNPolgyr1XGt$^lFPF}rmBF5rj1Kh5%dforrP8W}_qJL$2qMBS-#%-|s#BPZBSETsn_EBYcr(W5dq( z@f%}C|iN7)YN`^)h7R?Cg}Do*w-!zwZb9=BMp%Wsh@nb22hA zA{`wa8Q;yz6S)zfo%sl08^GF`9csI9BlGnEy#0^Y3b);M+n<(}6jziM7nhe57a1rj zC@(2ISYBL^UtWChKzVWgf%4LW2Tqg_^7jMw`C$KvU+mcakFjV(BGAW9g%CzSyM;Df z143=mq0oxaK-H;o>F3~zJ<(3-j&?|QBn)WJfP#JR zRuA;`N?L83wQt78QIA$(Z)lGQY9r^SFal;LB^qi`8%8@y+mwcGsf~nv)bBy2S7z~9 z=;X@Gglk)^jpbNz?1;`!J3QUfAOp4U$Uxm5>92iT`mek#$>s`)M>;e4{#%HAAcb^8_Ax%ersk|}# z0bd;ZPu|2}18KtvmIo8`1@H~@2ejwo(5rFS`Z4&O{$$+ch2hC0=06Jh`@p+p8LZzY z&2M~8T6X^*X?yQ$3N5EzRv$(FtSxhW>>ABUyp!{484f8(%C1_y)3D%Qgfl_!sz`LTXOjR&L!zPA0qH_iNS!tY{!^2WfD%uT}P zI<~&?@&))5&hPPHVRl9);TPO>@UI2d!^ksb!$9T96V(F){puTsn(}qt_WXNw4VvHj zf;6A_XCvE`Z@}E-IOaG0rs>K>^=Sr&OgT_p;F@v0VCN0Y$r|Lw1?Wjt`AKK~RT*kJ z2>QPuVgLNcF+XKno;WBv$yj@d_WFJbl*#*V_Cwzo@%3n5%z4g21G*PVZ)wM5$A{klYozmGlB zT@u2+s}=f}25%IA!yNcXUr!!1)z(Nqbhojg0lv@7@0UlvUMT)*r;M$d0-t)Z?B1@qQk()o!4fqvfr_I0r7 zy1(NdkHEj#Yu{K>T#We#b#FD=c1XhS{hdTh9+8gy-vkcdkk*QS@y(xxEMb1w6z<^~ zYcETGfB#ibR#ql0EiD;PR$L&Vrh2uRv5t_$;NxC;>7_S5_OXxsi8udY3BUUdi55Sk zcyKM+PQ9YMA%D1kH1q48OFG(Gbl=FmV;yk8o>k%0$rJ8%-IYsHclnYuTskkaiCGkUlkMY~mx&K}XRlKIW;odWIeuKjtbc^8bBOTqK zjj(ot`_j?A6y_h%vxE9o*ntx#PGrnK7AljD_r58ylE*oy@{IY%+mA^!|2vW_`>`aC{#3`#3;D_$^S^cM zRcF+uTO2sICledvFgNMU@A%M)%8JbSLq{dD|2|2Sg8vvh_uV6*Q?F&rKaV{v_qz&y z`f;stIb?Cb2!Cg7CG91Bhu@D@RaIrq-+o+T2fwFu#|j>lD6ZS9-t^5cx>p|?flqUA z;Cgs#V)O#`Aw4$Kr)L5?|7f4izl!;n0jux}tEW$&&YBXz9o{+~HhoiYDJ`w5BVTl&ARya=M7zdy$FEe}iGBur8XE>rhLj&_yDk5D4n2GJZ07u7%zyAfNtOLn;)M?h*Py-Xtql5aJOtL4U8e|!t? z((sc6&OJXrPdVef^wZV&x=Z&~uA7^ix8rly^rEj?#d&~pQ{HN8Yq|fZ#*bXn-26P^ z5!)xRzYO9{u6vx5@q_{FE4#7BipS#{&J7*>y}lTyV94}dfE%Yk>@@pDe&F7J09(-0|wuI|$of-MRfK51#t@t2+U|*s=W; z!Y&t{dS%!4VEEi$efA!#<<7&04?kB}Soprd8*jYv;-Qj~h~4v>{XX~kjF+@Z7<t?^|i z#>_ag2i-CRAM8Ret^rZt*^K?`G|o>1o(mLkewxyA)38k93`<~4VFI?5VB!kBh%NNU zxb8K(^-MU1ImWQxG~nFB-Un;6n{lQz_FfsW9^H$Xcn{;+W^ZcG$0qLM#eNV=vGE@# z1~k&!h4@T|IiI<47@pS|i?Qcl=XZJL#$JKve;booMqDUYY{(xcdj6STDE=n?;fsS1 ze`h~Q{CT$K{+{t+#*I1=&&-UU8M&}AwAxD-rMa=e!{0gQXP@6azBq9(ji11uJF%@5 zCvV`#*?;ZguQ7o|nH%bm*s&jLej#@B35gy32ZAE0`Pz@#j6R&kN5w{O4~1rhDoU zEBdU)%Nl?8zi|DR((u|gg~r$aLYmGMyK%FO*qLvwxK5+cn*`;O`16c!&&XT{$j~5k zXb^fbh1GT-CI*Nj{-?r7HNg=e3E{6rxuluPXY z5Nm8ktc$o4-^SO0|Es_sp!A$8GVwOX+%)cH<;=u#R#nz;7QsHl;J@a{5NUAmAHq4D zIU5@jT!h?kUp|g~iN*!>jM6K!W5ar0v~fWrSHK@})@6Lh#h)C6F6@)&-+C3(zO! z8+kV|B7LctM3DpI*~EYo>vCj>_?x&H;>y0*vKwE0?vi$CLt zfSJB##P|M2dEUDBPKW=9cY-F;L;h3Fs4E2ERdN#NSL7ctAC z?-}_a{*L@GA7JHJudxtDVA{K5Yh*k(%#x4W7w+^ zcb-+ofbT5ieG+@QG2lx&7!MyE2JWDP@$k`M;0`*d+oQmJ2A^de!3c53HFcfW_Wtv< zKghQ;*FifmI}kE4dc@1y-u;@qs|V75Z^|Q0l0?teobTE8tGl@EB?k#q_wUjypJ*R zyEI=DJ^Z+d*&}B_xoWvs27LtH7972qqMxVFcX9}c&JbeNCXUZM0`nQIkf&C}&skSt z^9fw@b^Hb)!^hE2IJq~~GktG#ZWwWG<`@V&ckVR&r=JAO4YniJewVcG`HF;59}=bf zLyz0uxf6MhuSyH#-^!ZbHxYl^mmBVrx) zyrb8sQ*qBd_WXm9c~Of$&ZP$b^)<~0%nt#7y$1Jg$e}WCK>TeUB{P>|b1FAB?%K7>;XiOfd}JQ`|IP#Vf%kVy zXa4;XFZ+>n;F>uX&3|4zqWK2u3c<>q;tzjsb1;d{u;L$-hq3qe@82(ob<3qom#%`+ z;vzYAs7TIMl_O75BXu|r`Qhc4UT*vN$3Oo0kAC!{f2#HexDy|qUpgTF;k{o6|L>7l z=?`=*LXaow1o;oNNLXsGTrvC)$R&{m=94Tf+2iTT3Y_Or z-!;^0a{kyWtO4vksG_3cyc7HQ0~detf0+2+qxq(e1NS251N}w5iTSrM)`0p8rem!j zZ56hGD=pHI*B+dd)2B`%|9f0goozCSeXPw3 z+58k~sI02Yz#lOneJzYcG)EB0|F+ggC6D|B`6}d0khAK-gz7U3EGT|M_9$ZINqZjwf>P zJCZ=ogSoE`=yV5YXrcTQZx@Un(64*AlLiyxWnCJ9I<5Nc*eK6eV1Mk}ci0*NrJ=t| zCXuJG`#7GBbPceFtFEpl{(lTm`LX=B_!H+& z>$*Hf}}y zkt@nLXFG9%v**s{z&{H4e?aqp%&l#oU8lxUxk2o%K+?aAe6jLojA& z_|J0<-%u^<;NT*%4)n2-OdqfctSl6iCHE?W_Q2zpJken#_xUJlidzs249H=b#g z?}L4-Tnp6)t_5X?_$v)vz`s9@^BME2X@w<>sKZ3=B{%*B$T5Nj%6!-Hr;I!Scj`lH z&2dHFlOISwWJ&S2vf~@I4i~(0*T%OFiuX|eD*nd2utS4$1_JM?zmp>a#CsVy6Er^z zeNNZZDE?R3pM?>~e?H_N`C`hy%m4jb;6L#8=a7l>3eJS2LGgEUxsau-Yh9l~o7=Yh z2mYg3`m5*3Ik|lKQf~euzZlCWzaN&=vHuHtOwK!2@W6)hqq$Zm|7`Nmu%9^F6UH?+ z@2ii+=iJ;ZzhiUKu$QB()nKk3FooI>Jr_IjzY6=qxYy;&mvi7BlQ?t4kRjIhb|2q? zd^K~{-^cxjVSj?!Xs=Da5IHmFzRj!Kzh~b!?`P7c&T9s77VLYB?8_?F zauM^)p;qFG!9PHLfIsnt43UnmV?Wn?Ki7aXSosgq;f?MYUuSIYwOn(5vWhb{f%$pn z4ySN-z}_%7|B);A@PA5k*7kkdr4xZ@s{e9j+9w;*RFm;XPDQwx%~;8iBzSKTIGKO z{53ZZU*OLr@S5=k;?CM^i#zkxs3Sj%z0U`L%q`qM+tP zX$aL;*^g$7UyM2Go+_4A+f)IQcy^G$h2E zb?nT$XlgTEFJI8GN6NQf%-eVn9mPilRqUbT$pN-|;FEjq@Ao&TxpZg=mEgBHB zU@grU;&sfmqlO=6|G3sU;7t8rbK$?X0y_v9$^{X`m4jZ_BR|B|@?ZCLSPPEzz`w1n zP5nA;4(kQFKm%$enjkkBxM%Y}2si&d|62L)U(dCzCGn56HN+i#6|nV-TGIo0;W;`( zW-y=1KF4dp$$mC_|6}pbb>IHoKQeZajXQB>jVR?u`R>%l1o54?6NnS*arpVopdEF; zeC5J3*M0p`*8lif;!irrcjC?(uExejsi~>4wKYwstGY^N@KY}TujLx`S=Cu+T=!dx zKWlPm->I**E{A*q-Z^FFT5$G%7Ij0_*Mo4-y6~RmyTzUB&lfae(WZfO>um}mnsDXPEbau-!13!!xd!qh*{C)6&bz0j1I{>y$D-S)b*)JMCPk!=~KL&6Ngin0p6MCOxF2L_R9t8N!$2Wpced<#`y!F;w zKTi5V_kX&X09wAIJ#anfg9Dhn0s7(C6Nj3S-mVn(i|C6ZAVq0$hE)874co};g z^hR7pe4lU$P;*ggYc4o&UTQC%liCXooIfkI3TNaBV%t~FRr}yHu7kjQ2J*3;e%;iW zvDVCh8=G80KAeyhCuY2LjrC!Od1rvF7h}zszxGV)&!)6ChP5WAjv-zQAMNJIG!JHS zwl?pLxC-V5II#(hQ`l)ZAp&M0xd4%cxmco*MIk?{BD=BK`1vpc}D39|XlV z{c&0oGdDa~TL2FT4lh=~1NL5O-P~0?V2#ie`v^CnANfGUM!b4F=JkCwd7Q`c8Na2q zJGQQk^?6w}Vg9-{|2047((lAV84uN%sK!N2?V(!_1{{v6rdgZl56f0zDMQ+q)jKzzu^ztsVken;=DjAh6G`Cw`Q4G+BjS+n*=KI~^K{W=%t zbD-rN)O4|*Q~@<#@1Vx$E!0W9`B~IZeFn87sHMXD>$M%|Bh93rdGf1lKoX3K651t&nhsl= zXxG|%@8}Bbrlp_u#t*DZX<}_0Yb{A9*1Pd_)LtqNwy6xT4pZrOY{s?N4)pPwT(i#y zT%`lRi8U#Ken4fw>H+N`{f#FF?ZxFlLZg7z7#cr4X>id z{9kUD`d2=w_Zlb{^c`5IOxWCZ1k<0T1D1Z31IU0Q2edsZ1K0xv$pQVYq2KEp&#v#Z z?{m@Lin;*Str(C2sfF^L>{R3cjY`~#)m>Wm$Y|1fzeS0-$(Q^z@} zEO*vlb-^XK9>w&Ef^=Zzo-1AFSP#9zb~X5_+){$(eB4K z8gtW+nl{q+CTh+>v(gWrsP^DB*ge(~Q$AGxJ-eYc1isti%$%nM<_&Ev?%|??PK`$p z{f-PM{Ym8k<$$)(F9)tqzFJ?h&Dk@D?Dt{4CHKJWLs8$zy6+(R)pr@0ur)xY{=uXFFzH_> z-F^tN1y(2hG8V)GpDg%wW0Px_ep~nIjD~*HCSxDi0y`H!`V*~RHs^uQsb1*bK1qGpmd zB1m`Cjw0`nLBF2|umz+a#2X$c?Lj;M?Lj;MUp*d>7j~ayNAyj@SLpeH`)BgRH}byy zyQSat!;U{@O(<<2fp&oQkIy$z`_CQ-)O@RN;QD9T4y|wIJ^%U#(BF%=`i49}j!D-) zkOwPSJaG03SMkE~BzW}b_v>LA&y)EEYO6sbdnTX*$>UF|JhZ&^MSb4}Tgbne_4n+C zwI8U4i~PI>7a3{kVa8|))*%C0|K+bIbmV~a`|G#+`TU#g zXW;bWIcWsQi9c4X*RUDpIfyoPY)2bI-r9)xulm1CJDkQd6u+f)_N=w1ElgEBjprPF z3o?Ly0RVeY_{3~fPVckRMxe2lM8hj!B8F)JO z!`AP6>u>5Y&3o9t0QxBpNE=lJx#NyIbp1gD zzUYBIPYHIv9ngk-Zt~<)62^1Zs1LLYMh@_tP^I7EX-9)Ed0^@y{k65Gp0KRcTmMWw zU|+)qx{#q0SL+4q?Q`i0>COIIF8a0Cf&C`hbMj?LmG9K&iW-?PJt*u)38tTXAP>@R zZL6uH^!RYNq$p>PKz7f-zvg>OKXcZ8h!%Vo@{VUZp|+iUD_xb(N~G|6c#oQK^nHZU zKg#F6<)+`rf~k*Xjjye+syV{bwU2glMMMs-^ss4`bYaVroXzn`YQUd__UlZL_mLs z(vO}k!~(mi|L+(5&;>r<;|OHnbXBE78LruP;{yBxZ6y7K3)nMo-{6PCI7gQi6+rF_ zkPod!Z8n}q46ykrlQS|hVB(}(2Kf7BCZ>Vc;V>ccbk2~NGaf6wGQH@W9&?Zt3v(h*P4xDrN>ex7+jH*+Qg z%^jH$&+*!v{sQ!xkWN4+>|b}qGvEd6ANzgqoVy5Qfws}ef2QqF{iiR5{pT}PS&yjo z>lron#va-p=v;m>WB+XVz|o;UJFdjo5_!RRD|6W{4}A2a#bZv)gS_`b|KsSH)Sd_JIr%<%n06TX&t{&!H#{)?4W9hlJ`R1>FyugOh3=D_{einr zu(Wf`qTkvED+gEULO0I*Hs%f;&=`=X4;N8Ovf28x$A*11`dmfy2=$+PNqX>XcG`h% zJY&A6@&)*WT^rC(Caj}2+|X|6cICm5h0OK0cGB_!wEKFZJU)OQ+TZ1q2bTx9hxnq& z$9ee|f9|0M^)#E&Pr4)f?o&DMM4w>Ksb{hF(0|wh+5_{vPow{V%TFzU2za&gjttNi zIyR9qA56dX52Qbv2aY^g`U7R43-p`#sO1A=KS2aKgfR+Yu^bQ*i-qu z%0mP;Ap)B~zZgO9lG^`325gOf?iUHF{~7jyGC)3L(eL(SQ70VzR~wLN18tnx(Cz2~ zctBl1kI)wAe+cxWHw*NW-d;=pd+>+wd$a@GBju*wFvabSaPtHiT!o#QFC+wBVwYo3s=y;z1jM+M=Fj!FZM>UzpL-eZzOT( zhmZmEfWa=%KE#V3-ZK5#v!Hzd{zc^{ctF~- z>DT-U`}5!fk$aj24`#uGdB7r`>oX5tU|d*b|N3V1lXmv%MGrvE(dXG)^-J*LA>$LE z7kut4`zE)v{@Op|(|@i#c>tM!12FQh?}PfA0`Bp%=%*RiXVzLDXnXtE@4B)5uR}a> zbNU}q+712pIrM`k^odG8dKtG$zwHmQI^c}tfjx5?egx3!e%JRm_64e+>`Ra1IRfLb z1KQ`SxmH{cZfyVS5m(&`{V}Y4j6J{b17`h6KWqZ&hfc(oR zxM%w!$F(mKy05kY&lco3%zvLCxBW+t*rxO+i=qGMvobx0-<7`VUu)ka`){=ew+Ovt zg%52_{&UbkUA8aJPWsk)gYWV4`dnxI%s?7^fGpq{ZQuu=VH{-t7w~K%_E<8`zS;V- zKTho*>;UQQul^1GT^HCt@I-q?)&4!QDgBndn?3sNKYKCQFU4LGKJ$n@Je$&w9@E$X z^p@iJ(v&`1(tq~1zc>0Vow-KR&vm!GUzT?Eqgnc)leZ9p)-Z*C!zqb=-$XG0 z^!8RfuQs5s>Q~qcz92(a_Q+KH?C*vCTr~UdTiR`JGuNH8v(J|FTiSEcPrBpmHRtmd zI2Jng0J=bXK);YY^rM?jzn?~X-Pe`GbAy{D)Y6D&1GY-EBcy%Bq?bKh?A>DD9DD!p z?{q02wno2sraGUkZv5dx+J8)&K$)No43Zr(*S`FEdL!4C)}WE}vJd%{S6-3VUw>Wp z?Aasv`T0^%P$2vE?L+Qhj~qB~K%eW)xH(=b_jU}TLD&BP*Pc9hz@Z=e0nkpLkWl}> z_5J^i(9Z7$(XG9~I3sY)`OGZ#_L06+Dy4E>UstcP-rU@xJ$&rxvo!n1Ao`P~KLU-8 z{zDgN4-&A6N!kPSYbQ&7sLufi`YtE2uN$S?e&5n>Y4(q#|KP!cc1j)T^QrUXMPFaP z_SoYO8S8G}Z$?AL4`;pE?7J5K8yWqy23>cCT2{=-)+A$X^-I9=e!@J@A&-;Ufc)`H}c(VI&;0x zrrGv()5mjP%jXzS{^|29?bLNXS0bC%p!YXI!;O457rjCEEzMkGf~B3$T}dXBO23tP z+Ci>;5UoM?C@bU@f9G1^X3=ly&ZeFH<@|RnOG--A&)fd)AUgjw?%izq{p(KJ`EP0v z2mU)P!+3t@X14DA=E2RR-|p${GZ9ETX=d+kJRZL$nSa0daI@&oUUxnZg0xd_xu>Vz lzF#z5%kSKX?YLH3ll^(hI(_`L*t#Iva2Ede*Z;>H_ - - - - - - - \ No newline at end of file diff --git a/lib/netstd/Makefile.am b/lib/netstd/Makefile.am index bb2aac5a8c3..503a1761367 100644 --- a/lib/netstd/Makefile.am +++ b/lib/netstd/Makefile.am @@ -20,7 +20,7 @@ SUBDIRS = . all-local: - $(DOTNETCORE) build + $(DOTNETCORE) build -c Release check-local: $(DOTNETCORE) test Tests/Thrift.Tests/Thrift.Tests.csproj diff --git a/test/Makefile.am b/test/Makefile.am index fdb2645bd0b..608e4881dd6 100755 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -30,11 +30,6 @@ SUBDIRS += cl PRECROSS_TARGET += precross-cl endif -if WITH_MONO -SUBDIRS += csharp -PRECROSS_TARGET += precross-csharp -endif - if WITH_CPP SUBDIRS += cpp PRECROSS_TARGET += precross-cpp diff --git a/test/README.md b/test/README.md index 8cb2af9eb47..10955f1c819 100755 --- a/test/README.md +++ b/test/README.md @@ -26,7 +26,7 @@ For example, if you changed something in `nodejs` library and need to verify the patch, you can skip everything except `nodejs` itself and some reference implementation (currently `cpp` and `java` are recommended) like this: - ./configure --without-c_glib -without-csharp --without-erlang --without-lua ... + ./configure --without-c_glib --without-erlang --without-lua ... make precross -j8 test/test.py --server cpp,java --client nodejs test/test.py --server nodejs --client cpp,java diff --git a/test/ThriftTest.thrift b/test/ThriftTest.thrift index bdc6d879d08..ac49aee01c8 100644 --- a/test/ThriftTest.thrift +++ b/test/ThriftTest.thrift @@ -23,7 +23,6 @@ namespace c_glib TTest namespace cpp thrift.test -namespace csharp Thrift.Test namespace delphi Thrift.Test namespace go thrifttest namespace java thrift.test diff --git a/test/csharp/Makefile.am b/test/csharp/Makefile.am deleted file mode 100644 index ad166e38408..00000000000 --- a/test/csharp/Makefile.am +++ /dev/null @@ -1,95 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -GENERATED = \ - gen-csharp/Thrift/Test/Bonk.cs \ - gen-csharp/Thrift/Test/Bools.cs \ - gen-csharp/Thrift/Test/BoolTest.cs \ - gen-csharp/Thrift/Test/CrazyNesting.cs \ - gen-csharp/Thrift/Test/EmptyStruct.cs \ - gen-csharp/Thrift/Test/GuessProtocolStruct.cs \ - gen-csharp/Thrift/Test/Insanity.cs \ - gen-csharp/Thrift/Test/LargeDeltas.cs \ - gen-csharp/Thrift/Test/ListBonks.cs \ - gen-csharp/Thrift/Test/ListTypeVersioningV1.cs \ - gen-csharp/Thrift/Test/ListTypeVersioningV2.cs \ - gen-csharp/Thrift/Test/NestedListsBonk.cs \ - gen-csharp/Thrift/Test/NestedListsI32x2.cs \ - gen-csharp/Thrift/Test/NestedListsI32x3.cs \ - gen-csharp/Thrift/Test/NestedMixedx2.cs \ - gen-csharp/Thrift/Test/Numberz.cs \ - gen-csharp/Thrift/Test/OneField.cs \ - gen-csharp/Thrift/Test/SecondService.cs \ - gen-csharp/Thrift/Test/StructA.cs \ - gen-csharp/Thrift/Test/StructB.cs \ - gen-csharp/Thrift/Test/ThriftTest.Constants.cs \ - gen-csharp/Thrift/Test/ThriftTest.cs \ - gen-csharp/Thrift/Test/VersioningTestV1.cs \ - gen-csharp/Thrift/Test/VersioningTestV2.cs \ - gen-csharp/Thrift/Test/Xception.cs \ - gen-csharp/Thrift/Test/Xception2.cs \ - gen-csharp/Thrift/Test/Xtruct.cs \ - gen-csharp/Thrift/Test/Xtruct2.cs \ - gen-csharp/Thrift/Test/Xtruct3.cs - -BUILT_SOURCES = $(GENERATED) - -if MONO_MCS -CSC = mcs -else -CSC = gmcs -endif - -if NET_2_0 -CSC_DEFINES = -d:NET_2_0 -endif - -LIBDIR = $(top_builddir)/lib/csharp - -THRIFT = $(top_builddir)/compiler/cpp/thrift - -$(GENERATED): $(top_srcdir)/test/ThriftTest.thrift $(THRIFT) - $(THRIFT) --gen csharp -o . $< - -precross: TestClientServer.exe - -ThriftImpl.dll: $(GENERATED) $(LIBDIR)/Thrift.dll - $(CSC) $(CSC_DEFINES) -t:library -out:$@ -reference:$(LIBDIR)/Thrift.dll $(GENERATED) - -SRCS = TestClient.cs TestServer.cs Program.cs - -TestClientServer.exe: $(SRCS) ThriftImpl.dll - $(CSC) $(CSC_DEFINES) -out:$@ -reference:$(LIBDIR)/Thrift.dll -reference:ThriftImpl.dll $(SRCS) - -clean-local: - $(RM) -rf gen-csharp *.exe *.dll - -TESTPORT = 9500 -check-local: TestClientServer.exe - MONO_PATH=$(LIBDIR) timeout 10 mono TestClientServer.exe server --port=$(TESTPORT) & - sleep 1 - MONO_PATH=$(LIBDIR) mono TestClientServer.exe client --port=$(TESTPORT) - -EXTRA_DIST = \ - Properties/AssemblyInfo.cs \ - ThriftTest.csproj \ - ThriftTest.sln \ - Program.cs \ - TestServer.cs \ - TestClient.cs diff --git a/test/csharp/Program.cs b/test/csharp/Program.cs deleted file mode 100644 index 8ec00e300b1..00000000000 --- a/test/csharp/Program.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// Distributed under the Thrift Software License -// -// See accompanying file LICENSE or visit the Thrift site at: -// http://developers.facebook.com/thrift/ - -using System; -using Thrift.Transport; -using Thrift.Protocol; -using Thrift.Test; //generated code - -namespace Test -{ - class Program - { - static int Main(string[] args) - { - if (args.Length == 0) - { - Console.WriteLine("must provide 'server' or 'client' arg"); - return -1; - } - - try - { - Console.SetBufferSize(Console.BufferWidth, 4096); - } - catch (Exception) - { - Console.WriteLine("Failed to grow scroll-back buffer"); - } - - string[] subArgs = new string[args.Length - 1]; - for(int i = 1; i < args.Length; i++) - { - subArgs[i-1] = args[i]; - } - if (args[0] == "client") - { - return TestClient.Execute(subArgs); - } - else if (args[0] == "server") - { - return TestServer.Execute(subArgs) ? 0 : 1; - } - else - { - Console.WriteLine("first argument must be 'server' or 'client'"); - } - return 0; - } - } -} diff --git a/test/csharp/Properties/AssemblyInfo.cs b/test/csharp/Properties/AssemblyInfo.cs deleted file mode 100644 index 376ff253ff2..00000000000 --- a/test/csharp/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("ThriftTest")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("f41b193b-f1ab-48ee-8843-f88e43084e26")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.14.0.0")] -[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/test/csharp/TestClient.cs b/test/csharp/TestClient.cs deleted file mode 100644 index 949c06e9f95..00000000000 --- a/test/csharp/TestClient.cs +++ /dev/null @@ -1,870 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Linq; -using System.Diagnostics; -using System.Collections.Generic; -using System.Threading; -using System.Security.Cryptography.X509Certificates; -using Thrift.Collections; -using Thrift.Protocol; -using Thrift.Transport; -using Thrift.Test; -using System.Security.Authentication; - -namespace Test -{ - public class TestClient - { - public class TestParams - { - public int numIterations = 1; - public string host = "localhost"; - public int port = 9090; - public string url; - public string pipe; - public bool buffered; - public bool framed; - public string protocol; - public bool encrypted = false; - public bool multiplexed = false; - protected bool _isFirstTransport = true; - - - public TTransport CreateTransport() - { - if (url == null) - { - // endpoint transport - TTransport trans = null; - if (pipe != null) - trans = new TNamedPipeClientTransport(pipe); - else - { - if (encrypted) - { - string certPath = "../keys/client.p12"; - X509Certificate cert = new X509Certificate2(certPath, "thrift"); - trans = new TTLSSocket(host, port, 0, cert, - (o, c, chain, errors) => true, - null, SslProtocols.Tls); - } - else - { - trans = new TSocket(host, port); - } - } - - // layered transport - if (buffered) - trans = new TBufferedTransport(trans); - if (framed) - trans = new TFramedTransport(trans); - - if (_isFirstTransport) - { - //ensure proper open/close of transport - trans.Open(); - trans.Close(); - _isFirstTransport = false; - } - return trans; - } - else - { - return new THttpClient(new Uri(url)); - } - } - - public TProtocol CreateProtocol(TTransport transport) - { - if (protocol == "compact") - return new TCompactProtocol(transport); - else if (protocol == "json") - return new TJSONProtocol(transport); - else - return new TBinaryProtocol(transport); - } - }; - - private const int ErrorBaseTypes = 1; - private const int ErrorStructs = 2; - private const int ErrorContainers = 4; - private const int ErrorExceptions = 8; - private const int ErrorProtocol = 16; - private const int ErrorUnknown = 64; - - private class ClientTest - { - private readonly TestParams param; - private readonly TTransport transport; - private readonly SecondService.Client second; - private readonly ThriftTest.Client client; - private readonly int numIterations; - private bool done; - - public int ReturnCode { get; set; } - - public ClientTest(TestParams paramin) - { - param = paramin; - transport = param.CreateTransport(); - TProtocol protocol = param.CreateProtocol(transport); - if (param.multiplexed) - { - second = new SecondService.Client(new TMultiplexedProtocol(protocol, "SecondService")); - } - client = new ThriftTest.Client(protocol); - numIterations = param.numIterations; - } - public void Execute() - { - if (done) - { - Console.WriteLine("Execute called more than once"); - throw new InvalidOperationException(); - } - - for (int i = 0; i < numIterations; i++) - { - try - { - if (!transport.IsOpen) - transport.Open(); - } - catch (TTransportException ex) - { - Console.WriteLine("*** FAILED ***"); - Console.WriteLine("Connect failed: " + ex.Message); - ReturnCode |= ErrorUnknown; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - continue; - } - - try - { - ReturnCode |= ExecuteClientTest(client, second, param); - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - ReturnCode |= ErrorUnknown; - } - } - try - { - transport.Close(); - } - catch(Exception ex) - { - Console.WriteLine("Error while closing transport"); - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - done = true; - } - } - - public static int Execute(string[] args) - { - try - { - TestParams param = new TestParams(); - int numThreads = 1; - try - { - for (int i = 0; i < args.Length; i++) - { - if (args[i] == "-u") - { - param.url = args[++i]; - } - else if (args[i] == "-n") - { - param.numIterations = Convert.ToInt32(args[++i]); - } - else if (args[i] == "-pipe") // -pipe - { - param.pipe = args[++i]; - Console.WriteLine("Using named pipes transport"); - } - else if (args[i].Contains("--host=")) - { - param.host = args[i].Substring(args[i].IndexOf("=") + 1); - } - else if (args[i].Contains("--port=")) - { - param.port = int.Parse(args[i].Substring(args[i].IndexOf("=")+1)); - } - else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") - { - param.buffered = true; - Console.WriteLine("Using buffered sockets"); - } - else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") - { - param.framed = true; - Console.WriteLine("Using framed transport"); - } - else if (args[i] == "-t") - { - numThreads = Convert.ToInt32(args[++i]); - } - else if (args[i] == "--compact" || args[i] == "--protocol=compact" || args[i] == "--protocol=multic") - { - param.protocol = "compact"; - Console.WriteLine("Using compact protocol"); - } - else if (args[i] == "--json" || args[i] == "--protocol=json" || args[i] == "--protocol=multij") - { - param.protocol = "json"; - Console.WriteLine("Using JSON protocol"); - } - else if (args[i] == "--ssl") - { - param.encrypted = true; - Console.WriteLine("Using encrypted transport"); - } - - if (args[i].StartsWith("--protocol=multi")) - { - param.multiplexed = true; - } - } - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - Console.WriteLine("Error while parsing arguments"); - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - return ErrorUnknown; - } - - var tests = Enumerable.Range(0, numThreads).Select(_ => new ClientTest(param)).ToArray(); - //issue tests on separate threads simultaneously - var threads = tests.Select(test => new Thread(test.Execute)).ToArray(); - DateTime start = DateTime.Now; - foreach (var t in threads) - t.Start(); - foreach (var t in threads) - t.Join(); - Console.WriteLine("Total time: " + (DateTime.Now - start)); - Console.WriteLine(); - return tests.Select(t => t.ReturnCode).Aggregate((r1, r2) => r1 | r2); - } - catch (Exception outerEx) - { - Console.WriteLine("*** FAILED ***"); - Console.WriteLine("Unexpected error"); - Console.WriteLine(outerEx.Message + " ST: " + outerEx.StackTrace); - return ErrorUnknown; - } - } - - public static string BytesToHex(byte[] data) { - return BitConverter.ToString(data).Replace("-", string.Empty); - } - - public static byte[] PrepareTestData(bool randomDist, bool huge) - { - // huge = true tests for THRIFT-4372 - byte[] retval = new byte[huge ? 0x12345 : 0x100]; - int initLen = retval.Length; - - // linear distribution, unless random is requested - if (!randomDist) { - for (var i = 0; i < initLen; ++i) { - retval[i] = (byte)i; - } - return retval; - } - - // random distribution - for (var i = 0; i < initLen; ++i) { - retval[i] = (byte)0; - } - var rnd = new Random(); - for (var i = 1; i < initLen; ++i) { - while( true) { - int nextPos = rnd.Next() % initLen; - if (retval[nextPos] == 0) { - retval[nextPos] = (byte)i; - break; - } - } - } - return retval; - } - - public static int ExecuteClientTest(ThriftTest.Client client, SecondService.Client second, TestParams param) - { - int returnCode = 0; - - Console.Write("testVoid()"); - client.testVoid(); - Console.WriteLine(" = void"); - - Console.Write("testString(\"Test\")"); - string s = client.testString("Test"); - Console.WriteLine(" = \"" + s + "\""); - if ("Test" != s) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - if (param.multiplexed) - { - Console.WriteLine("secondTestString(\"Test2\")"); - s = second.secondtestString("Test2"); - Console.WriteLine(" = \"" + s + "\""); - if ("testString(\"Test2\")" != s) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorProtocol; - } - } - - Console.Write("testBool(true)"); - bool t = client.testBool((bool)true); - Console.WriteLine(" = " + t); - if (!t) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - Console.Write("testBool(false)"); - bool f = client.testBool((bool)false); - Console.WriteLine(" = " + f); - if (f) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - Console.Write("testByte(1)"); - sbyte i8 = client.testByte((sbyte)1); - Console.WriteLine(" = " + i8); - if (1 != i8) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - Console.Write("testI32(-1)"); - int i32 = client.testI32(-1); - Console.WriteLine(" = " + i32); - if (-1 != i32) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - Console.Write("testI64(-34359738368)"); - long i64 = client.testI64(-34359738368); - Console.WriteLine(" = " + i64); - if (-34359738368 != i64) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - // TODO: Validate received message - Console.Write("testDouble(5.325098235)"); - double dub = client.testDouble(5.325098235); - Console.WriteLine(" = " + dub); - if (5.325098235 != dub) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - Console.Write("testDouble(-0.000341012439638598279)"); - dub = client.testDouble(-0.000341012439638598279); - Console.WriteLine(" = " + dub); - if (-0.000341012439638598279 != dub) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - for (i32 = 0; i32 < 2; ++i32) - { - var huge = (i32 > 0); - byte[] binOut = PrepareTestData(false,huge); - Console.Write("testBinary(" + BytesToHex(binOut) + ")"); - try - { - byte[] binIn = client.testBinary(binOut); - Console.WriteLine(" = " + BytesToHex(binIn)); - if (binIn.Length != binOut.Length) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - for (int ofs = 0; ofs < Math.Min(binIn.Length, binOut.Length); ++ofs) - if (binIn[ofs] != binOut[ofs]) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - } - catch (Thrift.TApplicationException ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - } - - // binary equals? only with hashcode option enabled ... - Console.WriteLine("Test CrazyNesting"); - if( typeof(CrazyNesting).GetMethod("Equals").DeclaringType == typeof(CrazyNesting)) - { - CrazyNesting one = new CrazyNesting(); - CrazyNesting two = new CrazyNesting(); - one.String_field = "crazy"; - two.String_field = "crazy"; - one.Binary_field = new byte[10] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; - two.Binary_field = new byte[10] { 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0xFF }; - if (!one.Equals(two)) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorContainers; - throw new Exception("CrazyNesting.Equals failed"); - } - } - - // TODO: Validate received message - Console.Write("testStruct({\"Zero\", 1, -3, -5})"); - Xtruct o = new Xtruct(); - o.String_thing = "Zero"; - o.Byte_thing = (sbyte)1; - o.I32_thing = -3; - o.I64_thing = -5; - Xtruct i = client.testStruct(o); - Console.WriteLine(" = {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}"); - - // TODO: Validate received message - Console.Write("testNest({1, {\"Zero\", 1, -3, -5}, 5})"); - Xtruct2 o2 = new Xtruct2(); - o2.Byte_thing = (sbyte)1; - o2.Struct_thing = o; - o2.I32_thing = 5; - Xtruct2 i2 = client.testNest(o2); - i = i2.Struct_thing; - Console.WriteLine(" = {" + i2.Byte_thing + ", {\"" + i.String_thing + "\", " + i.Byte_thing + ", " + i.I32_thing + ", " + i.I64_thing + "}, " + i2.I32_thing + "}"); - - Dictionary mapout = new Dictionary(); - for (int j = 0; j < 5; j++) - { - mapout[j] = j - 10; - } - Console.Write("testMap({"); - bool first = true; - foreach (int key in mapout.Keys) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(key + " => " + mapout[key]); - } - Console.Write("})"); - - Dictionary mapin = client.testMap(mapout); - - Console.Write(" = {"); - first = true; - foreach (int key in mapin.Keys) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(key + " => " + mapin[key]); - } - Console.WriteLine("}"); - - // TODO: Validate received message - List listout = new List(); - for (int j = -2; j < 3; j++) - { - listout.Add(j); - } - Console.Write("testList({"); - first = true; - foreach (int j in listout) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(j); - } - Console.Write("})"); - - List listin = client.testList(listout); - - Console.Write(" = {"); - first = true; - foreach (int j in listin) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(j); - } - Console.WriteLine("}"); - - //set - // TODO: Validate received message - THashSet setout = new THashSet(); - for (int j = -2; j < 3; j++) - { - setout.Add(j); - } - Console.Write("testSet({"); - first = true; - foreach (int j in setout) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(j); - } - Console.Write("})"); - - THashSet setin = client.testSet(setout); - - Console.Write(" = {"); - first = true; - foreach (int j in setin) - { - if (first) - { - first = false; - } - else - { - Console.Write(", "); - } - Console.Write(j); - } - Console.WriteLine("}"); - - - Console.Write("testEnum(ONE)"); - Numberz ret = client.testEnum(Numberz.ONE); - Console.WriteLine(" = " + ret); - if (Numberz.ONE != ret) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - Console.Write("testEnum(TWO)"); - ret = client.testEnum(Numberz.TWO); - Console.WriteLine(" = " + ret); - if (Numberz.TWO != ret) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - Console.Write("testEnum(THREE)"); - ret = client.testEnum(Numberz.THREE); - Console.WriteLine(" = " + ret); - if (Numberz.THREE != ret) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - Console.Write("testEnum(FIVE)"); - ret = client.testEnum(Numberz.FIVE); - Console.WriteLine(" = " + ret); - if (Numberz.FIVE != ret) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - Console.Write("testEnum(EIGHT)"); - ret = client.testEnum(Numberz.EIGHT); - Console.WriteLine(" = " + ret); - if (Numberz.EIGHT != ret) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - Console.Write("testTypedef(309858235082523)"); - long uid = client.testTypedef(309858235082523L); - Console.WriteLine(" = " + uid); - if (309858235082523L != uid) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorStructs; - } - - // TODO: Validate received message - Console.Write("testMapMap(1)"); - Dictionary> mm = client.testMapMap(1); - Console.Write(" = {"); - foreach (int key in mm.Keys) - { - Console.Write(key + " => {"); - Dictionary m2 = mm[key]; - foreach (int k2 in m2.Keys) - { - Console.Write(k2 + " => " + m2[k2] + ", "); - } - Console.Write("}, "); - } - Console.WriteLine("}"); - - // TODO: Validate received message - Insanity insane = new Insanity(); - insane.UserMap = new Dictionary(); - insane.UserMap[Numberz.FIVE] = 5000L; - Xtruct truck = new Xtruct(); - truck.String_thing = "Truck"; - truck.Byte_thing = (sbyte)8; - truck.I32_thing = 8; - truck.I64_thing = 8; - insane.Xtructs = new List(); - insane.Xtructs.Add(truck); - Console.Write("testInsanity()"); - Dictionary> whoa = client.testInsanity(insane); - Console.Write(" = {"); - foreach (long key in whoa.Keys) - { - Dictionary val = whoa[key]; - Console.Write(key + " => {"); - - foreach (Numberz k2 in val.Keys) - { - Insanity v2 = val[k2]; - - Console.Write(k2 + " => {"); - Dictionary userMap = v2.UserMap; - - Console.Write("{"); - if (userMap != null) - { - foreach (Numberz k3 in userMap.Keys) - { - Console.Write(k3 + " => " + userMap[k3] + ", "); - } - } - else - { - Console.Write("null"); - } - Console.Write("}, "); - - List xtructs = v2.Xtructs; - - Console.Write("{"); - if (xtructs != null) - { - foreach (Xtruct x in xtructs) - { - Console.Write("{\"" + x.String_thing + "\", " + x.Byte_thing + ", " + x.I32_thing + ", " + x.I32_thing + "}, "); - } - } - else - { - Console.Write("null"); - } - Console.Write("}"); - - Console.Write("}, "); - } - Console.Write("}, "); - } - Console.WriteLine("}"); - - sbyte arg0 = 1; - int arg1 = 2; - long arg2 = long.MaxValue; - Dictionary multiDict = new Dictionary(); - multiDict[1] = "one"; - Numberz arg4 = Numberz.FIVE; - long arg5 = 5000000; - Console.Write("Test Multi(" + arg0 + "," + arg1 + "," + arg2 + "," + multiDict + "," + arg4 + "," + arg5 + ")"); - Xtruct multiResponse = client.testMulti(arg0, arg1, arg2, multiDict, arg4, arg5); - Console.Write(" = Xtruct(byte_thing:" + multiResponse.Byte_thing + ",String_thing:" + multiResponse.String_thing - + ",i32_thing:" + multiResponse.I32_thing + ",i64_thing:" + multiResponse.I64_thing + ")\n"); - - try - { - Console.WriteLine("testException(\"Xception\")"); - client.testException("Xception"); - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - catch (Xception ex) - { - if (ex.ErrorCode != 1001 || ex.Message != "Xception") - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - try - { - Console.WriteLine("testException(\"TException\")"); - client.testException("TException"); - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - catch (Thrift.TException) - { - // OK - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - try - { - Console.WriteLine("testException(\"ok\")"); - client.testException("ok"); - // OK - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - - try - { - Console.WriteLine("testMultiException(\"Xception\", ...)"); - client.testMultiException("Xception", "ignore"); - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - catch (Xception ex) - { - if (ex.ErrorCode != 1001 || ex.Message != "This is an Xception") - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - try - { - Console.WriteLine("testMultiException(\"Xception2\", ...)"); - client.testMultiException("Xception2", "ignore"); - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - catch (Xception2 ex) - { - if (ex.ErrorCode != 2002 || ex.Struct_thing.String_thing != "This is an Xception2") - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - try - { - Console.WriteLine("testMultiException(\"success\", \"OK\")"); - if ("OK" != client.testMultiException("success", "OK").String_thing) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - } - } - catch (Exception ex) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); - } - - Stopwatch sw = new Stopwatch(); - sw.Start(); - Console.WriteLine("Test Oneway(1)"); - client.testOneway(1); - sw.Stop(); - if (sw.ElapsedMilliseconds > 1000) - { - Console.WriteLine("*** FAILED ***"); - returnCode |= ErrorBaseTypes; - } - - Console.Write("Test Calltime()"); - var times = 50; - sw.Reset(); - sw.Start(); - for (int k = 0; k < times; ++k) - client.testVoid(); - sw.Stop(); - Console.WriteLine(" = {0} ms a testVoid() call", sw.ElapsedMilliseconds / times); - return returnCode; - } - } -} diff --git a/test/csharp/TestServer.cs b/test/csharp/TestServer.cs deleted file mode 100644 index bf645c26cf7..00000000000 --- a/test/csharp/TestServer.cs +++ /dev/null @@ -1,535 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// Distributed under the Thrift Software License -// -// See accompanying file LICENSE or visit the Thrift site at: -// http://developers.facebook.com/thrift/ -using System; -using System.Collections.Generic; -using System.Security.Cryptography.X509Certificates; -using Thrift.Collections; -using Thrift.Test; //generated code -using Thrift.Transport; -using Thrift.Protocol; -using Thrift.Server; -using Thrift; -using System.Threading; -using System.Text; -using System.Security.Authentication; - -namespace Test -{ - public class TestServer - { - public static int _clientID = -1; - public delegate void TestLogDelegate(string msg, params object[] values); - - public class TradeServerEventHandler : TServerEventHandler - { - public int callCount = 0; - public void preServe() - { - callCount++; - } - public Object createContext(Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output) - { - callCount++; - return null; - } - public void deleteContext(Object serverContext, Thrift.Protocol.TProtocol input, Thrift.Protocol.TProtocol output) - { - callCount++; - } - public void processContext(Object serverContext, Thrift.Transport.TTransport transport) - { - callCount++; - } - }; - - - public class TestHandler : ThriftTest.Iface, Thrift.TControllingHandler - { - public TServer server { get; set; } - private int handlerID; - private StringBuilder reusableStringBuilder = new StringBuilder(); - private TestLogDelegate testLogDelegate; - - public TestHandler() - { - handlerID = Interlocked.Increment(ref _clientID); - testLogDelegate += testConsoleLogger; - testLogDelegate.Invoke("New TestHandler instance created"); - } - - public void testConsoleLogger(string msg, params object[] values) - { - reusableStringBuilder.Clear(); - reusableStringBuilder.AppendFormat("handler{0:D3}:",handlerID); - reusableStringBuilder.AppendFormat(msg, values); - reusableStringBuilder.AppendLine(); - Console.Write( reusableStringBuilder.ToString() ); - } - - public void testVoid() - { - testLogDelegate.Invoke("testVoid()"); - } - - public string testString(string thing) - { - testLogDelegate.Invoke("testString({0})", thing); - return thing; - } - - public bool testBool(bool thing) - { - testLogDelegate.Invoke("testBool({0})", thing); - return thing; - } - - public sbyte testByte(sbyte thing) - { - testLogDelegate.Invoke("testByte({0})", thing); - return thing; - } - - public int testI32(int thing) - { - testLogDelegate.Invoke("testI32({0})", thing); - return thing; - } - - public long testI64(long thing) - { - testLogDelegate.Invoke("testI64({0})", thing); - return thing; - } - - public double testDouble(double thing) - { - testLogDelegate.Invoke("testDouble({0})", thing); - return thing; - } - - public byte[] testBinary(byte[] thing) - { - string hex = BitConverter.ToString(thing).Replace("-", string.Empty); - testLogDelegate.Invoke("testBinary({0:X})", hex); - return thing; - } - - public Xtruct testStruct(Xtruct thing) - { - testLogDelegate.Invoke("testStruct({{\"{0}\", {1}, {2}, {3}}})", thing.String_thing, thing.Byte_thing, thing.I32_thing, thing.I64_thing); - return thing; - } - - public Xtruct2 testNest(Xtruct2 nest) - { - Xtruct thing = nest.Struct_thing; - testLogDelegate.Invoke("testNest({{{0}, {{\"{1}\", {2}, {3}, {4}, {5}}}}})", - nest.Byte_thing, - thing.String_thing, - thing.Byte_thing, - thing.I32_thing, - thing.I64_thing, - nest.I32_thing); - return nest; - } - - public Dictionary testMap(Dictionary thing) - { - reusableStringBuilder.Clear(); - reusableStringBuilder.Append("testMap({{"); - bool first = true; - foreach (int key in thing.Keys) - { - if (first) - { - first = false; - } - else - { - reusableStringBuilder.Append(", "); - } - reusableStringBuilder.AppendFormat("{0} => {1}", key, thing[key]); - } - reusableStringBuilder.Append("}})"); - testLogDelegate.Invoke(reusableStringBuilder.ToString()); - return thing; - } - - public Dictionary testStringMap(Dictionary thing) - { - reusableStringBuilder.Clear(); - reusableStringBuilder.Append("testStringMap({{"); - bool first = true; - foreach (string key in thing.Keys) - { - if (first) - { - first = false; - } - else - { - reusableStringBuilder.Append(", "); - } - reusableStringBuilder.AppendFormat("{0} => {1}", key, thing[key]); - } - reusableStringBuilder.Append("}})"); - testLogDelegate.Invoke(reusableStringBuilder.ToString()); - return thing; - } - - public THashSet testSet(THashSet thing) - { - reusableStringBuilder.Clear(); - reusableStringBuilder.Append("testSet({{"); - bool first = true; - foreach (int elem in thing) - { - if (first) - { - first = false; - } - else - { - reusableStringBuilder.Append(", "); - } - reusableStringBuilder.AppendFormat("{0}", elem); - } - reusableStringBuilder.Append("}})"); - testLogDelegate.Invoke(reusableStringBuilder.ToString()); - return thing; - } - - public List testList(List thing) - { - reusableStringBuilder.Clear(); - reusableStringBuilder.Append("testList({{"); - bool first = true; - foreach (int elem in thing) - { - if (first) - { - first = false; - } - else - { - reusableStringBuilder.Append(", "); - } - reusableStringBuilder.AppendFormat("{0}", elem); - } - reusableStringBuilder.Append("}})"); - testLogDelegate.Invoke(reusableStringBuilder.ToString()); - return thing; - } - - public Numberz testEnum(Numberz thing) - { - testLogDelegate.Invoke("testEnum({0})", thing); - return thing; - } - - public long testTypedef(long thing) - { - testLogDelegate.Invoke("testTypedef({0})", thing); - return thing; - } - - public Dictionary> testMapMap(int hello) - { - testLogDelegate.Invoke("testMapMap({0})", hello); - Dictionary> mapmap = - new Dictionary>(); - - Dictionary pos = new Dictionary(); - Dictionary neg = new Dictionary(); - for (int i = 1; i < 5; i++) - { - pos[i] = i; - neg[-i] = -i; - } - - mapmap[4] = pos; - mapmap[-4] = neg; - - return mapmap; - } - - // Insanity - // returns: - // { 1 => { 2 => argument, - // 3 => argument, - // }, - // 2 => { 6 => , }, - // } - public Dictionary> testInsanity(Insanity argument) - { - testLogDelegate.Invoke("testInsanity()"); - - Dictionary first_map = new Dictionary(); - Dictionary second_map = new Dictionary(); ; - - first_map[Numberz.TWO] = argument; - first_map[Numberz.THREE] = argument; - - second_map[Numberz.SIX] = new Insanity(); - - Dictionary> insane = - new Dictionary>(); - insane[(long)1] = first_map; - insane[(long)2] = second_map; - - return insane; - } - - public Xtruct testMulti(sbyte arg0, int arg1, long arg2, Dictionary arg3, Numberz arg4, long arg5) - { - testLogDelegate.Invoke("testMulti()"); - - Xtruct hello = new Xtruct(); ; - hello.String_thing = "Hello2"; - hello.Byte_thing = arg0; - hello.I32_thing = arg1; - hello.I64_thing = arg2; - return hello; - } - - /** - * Print 'testException(%s)' with arg as '%s' - * @param string arg - a string indication what type of exception to throw - * if arg == "Xception" throw Xception with errorCode = 1001 and message = arg - * elsen if arg == "TException" throw TException - * else do not throw anything - */ - public void testException(string arg) - { - testLogDelegate.Invoke("testException({0})", arg); - if (arg == "Xception") - { - Xception x = new Xception(); - x.ErrorCode = 1001; - x.Message = arg; - throw x; - } - if (arg == "TException") - { - throw new Thrift.TException(); - } - return; - } - - public Xtruct testMultiException(string arg0, string arg1) - { - testLogDelegate.Invoke("testMultiException({0}, {1})", arg0,arg1); - if (arg0 == "Xception") - { - Xception x = new Xception(); - x.ErrorCode = 1001; - x.Message = "This is an Xception"; - throw x; - } - else if (arg0 == "Xception2") - { - Xception2 x = new Xception2(); - x.ErrorCode = 2002; - x.Struct_thing = new Xtruct(); - x.Struct_thing.String_thing = "This is an Xception2"; - throw x; - } - - Xtruct result = new Xtruct(); - result.String_thing = arg1; - return result; - } - - public void testStop() - { - if (server != null) - { - server.Stop(); - } - } - - public void testOneway(int arg) - { - testLogDelegate.Invoke("testOneway({0}), sleeping...", arg); - System.Threading.Thread.Sleep(arg * 1000); - testLogDelegate.Invoke("testOneway finished"); - } - - } // class TestHandler - - private enum ServerType - { - TSimpleServer, - TThreadedServer, - TThreadPoolServer, - } - - private enum ProcessorFactoryType - { - TSingletonProcessorFactory, - TPrototypeProcessorFactory, - } - - public static bool Execute(string[] args) - { - try - { - bool useBufferedSockets = false, useFramed = false, useEncryption = false, compact = false, json = false; - ServerType serverType = ServerType.TSimpleServer; - ProcessorFactoryType processorFactoryType = ProcessorFactoryType.TSingletonProcessorFactory; - int port = 9090; - string pipe = null; - for (int i = 0; i < args.Length; i++) - { - if (args[i] == "-pipe") // -pipe name - { - pipe = args[++i]; - } - else if (args[i].Contains("--port=")) - { - port = int.Parse(args[i].Substring(args[i].IndexOf("=") + 1)); - } - else if (args[i] == "-b" || args[i] == "--buffered" || args[i] == "--transport=buffered") - { - useBufferedSockets = true; - } - else if (args[i] == "-f" || args[i] == "--framed" || args[i] == "--transport=framed") - { - useFramed = true; - } - else if (args[i] == "--compact" || args[i] == "--protocol=compact") - { - compact = true; - } - else if (args[i] == "--json" || args[i] == "--protocol=json") - { - json = true; - } - else if (args[i] == "--threaded" || args[i] == "--server-type=threaded") - { - serverType = ServerType.TThreadedServer; - } - else if (args[i] == "--threadpool" || args[i] == "--server-type=threadpool") - { - serverType = ServerType.TThreadPoolServer; - } - else if (args[i] == "--prototype" || args[i] == "--processor=prototype") - { - processorFactoryType = ProcessorFactoryType.TPrototypeProcessorFactory; - } - else if (args[i] == "--ssl") - { - useEncryption = true; - } - } - - // Transport - TServerTransport trans; - if (pipe != null) - { - trans = new TNamedPipeServerTransport(pipe); - } - else - { - if (useEncryption) - { - string certPath = "../keys/server.p12"; - trans = new TTLSServerSocket(port, 0, useBufferedSockets, new X509Certificate2(certPath, "thrift"), - null, - null, SslProtocols.Tls); - } - else - { - trans = new TServerSocket(port, 0, useBufferedSockets); - } - } - - TProtocolFactory proto; - if (compact) - proto = new TCompactProtocol.Factory(); - else if (json) - proto = new TJSONProtocol.Factory(); - else - proto = new TBinaryProtocol.Factory(); - - TProcessorFactory processorFactory; - if (processorFactoryType == ProcessorFactoryType.TPrototypeProcessorFactory) - { - processorFactory = new TPrototypeProcessorFactory(); - } - else - { - // Processor - TestHandler testHandler = new TestHandler(); - ThriftTest.Processor testProcessor = new ThriftTest.Processor(testHandler); - processorFactory = new TSingletonProcessorFactory(testProcessor); - } - - TTransportFactory transFactory; - if (useFramed) - transFactory = new TFramedTransport.Factory(); - else - transFactory = new TTransportFactory(); - - TServer serverEngine; - switch (serverType) - { - case ServerType.TThreadPoolServer: - serverEngine = new TThreadPoolServer(processorFactory, trans, transFactory, proto); - break; - case ServerType.TThreadedServer: - serverEngine = new TThreadedServer(processorFactory, trans, transFactory, proto); - break; - default: - serverEngine = new TSimpleServer(processorFactory, trans, transFactory, proto); - break; - } - - //Server event handler - TradeServerEventHandler serverEvents = new TradeServerEventHandler(); - serverEngine.setEventHandler(serverEvents); - - // Run it - string where = (pipe != null ? "on pipe " + pipe : "on port " + port); - Console.WriteLine("Starting the " + serverType.ToString() + " " + where + - (processorFactoryType == ProcessorFactoryType.TPrototypeProcessorFactory ? " with processor prototype factory " : "") + - (useBufferedSockets ? " with buffered socket" : "") + - (useFramed ? " with framed transport" : "") + - (useEncryption ? " with encryption" : "") + - (compact ? " with compact protocol" : "") + - (json ? " with json protocol" : "") + - "..."); - serverEngine.Serve(); - - } - catch (Exception x) - { - Console.Error.Write(x); - return false; - } - Console.WriteLine("done."); - return true; - } - } -} diff --git a/test/csharp/ThriftTest.csproj b/test/csharp/ThriftTest.csproj deleted file mode 100644 index 2ff092673c8..00000000000 --- a/test/csharp/ThriftTest.csproj +++ /dev/null @@ -1,141 +0,0 @@ - - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C} - Exe - Properties - ThriftTest - ThriftTest - v3.5 - 512 - false - - - 3.5 - - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 0.14.0.0 - false - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - - - False - .\ThriftImpl.dll - - - - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 2.0 %28x86%29 - false - - - False - .NET Framework 3.0 %28x86%29 - false - - - False - .NET Framework 3.5 - true - - - False - .NET Framework 3.5 SP1 - false - - - False - Windows Installer 3.1 - true - - - - - {499EB63C-D74C-47E8-AE48-A2FC94538E9D} - Thrift - - - - - - rmdir /s /q "$(ProjectDir)gen-csharp" -del /f /q "$(ProjectDir)ThriftImpl.dll" -SET OUTPUT_DIR=$(ProjectDir) -SET THRIFT_FILE=$(ProjectDir)\..\ThriftTest.thrift -for %25%25I in ("%25OUTPUT_DIR%25") do set SHORT_DIR=%25%25~fsI -for %25%25I in ("%25THRIFT_FILE%25") do set THRIFT_SHORT=%25%25~fsI -"$(ProjectDir)\..\..\compiler\cpp\thrift.exe" --gen csharp -o %25SHORT_DIR%25 %25THRIFT_SHORT%25 -$(MSBuildToolsPath)\Csc.exe /t:library /out:"$(ProjectDir)ThriftImpl.dll" /recurse:"$(ProjectDir)gen-csharp"\* /reference:"$(ProjectDir)..\..\lib\csharp\bin\Debug\Thrift.dll" - - diff --git a/test/csharp/ThriftTest.sln b/test/csharp/ThriftTest.sln deleted file mode 100644 index 1765a03ad47..00000000000 --- a/test/csharp/ThriftTest.sln +++ /dev/null @@ -1,17 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ThriftTest", "ThriftTest.csproj", "{48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {48DD757F-CA95-4DD7-BDA4-58DB6F108C2C}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/test/features/known_failures_Linux.json b/test/features/known_failures_Linux.json index 6547860cbca..530277babce 100644 --- a/test/features/known_failures_Linux.json +++ b/test/features/known_failures_Linux.json @@ -7,10 +7,10 @@ "cpp-theader_framed_compact_multih-header_buffered-ip", "cpp-theader_unframed_binary_multih-header_buffered-ip", "cpp-theader_unframed_compact_multih-header_buffered-ip", - "csharp-limit_container_length_binary_buffered-ip", - "csharp-limit_container_length_compact_buffered-ip", - "csharp-limit_string_length_binary_buffered-ip", - "csharp-limit_string_length_compact_buffered-ip", + "netstd-limit_container_length_binary_buffered-ip", + "netstd-limit_container_length_compact_buffered-ip", + "netstd-limit_string_length_binary_buffered-ip", + "netstd-limit_string_length_compact_buffered-ip", "d-limit_container_length_binary_buffered-ip", "d-limit_container_length_compact_buffered-ip", "d-limit_string_length_binary_buffered-ip", @@ -45,8 +45,8 @@ "rs-limit_string_length_binary_buffered-ip", "rs-limit_string_length_compact_buffered-ip", "rs-limit_string_length_multic-compact_buffered-ip", - "netcore-limit_string_length_compact_buffered-ip", - "netcore-limit_container_length_compact_buffered-ip", + "netstd-limit_string_length_compact_buffered-ip", + "netstd-limit_container_length_compact_buffered-ip", "nodejs-theader_framed_binary_header_buffered-ip", "nodejs-theader_framed_compact_header_buffered-ip" ] diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index d1c21eb2bd9..460da5a900c 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -61,6 +61,14 @@ "cpp-java_multij-json_http-ip-ssl", "cpp-java_multij_http-ip", "cpp-java_multij_http-ip-ssl", + "cpp-netstd_json_buffered-ip", + "cpp-netstd_json_buffered-ip-ssl", + "cpp-netstd_json_framed-ip", + "cpp-netstd_json_framed-ip-ssl", + "cpp-netstd_multij-json_buffered-ip", + "cpp-netstd_multij-json_buffered-ip-ssl", + "cpp-netstd_multij-json_framed-ip", + "cpp-netstd_multij-json_framed-ip-ssl", "cpp-nodejs_binary_http-domain", "cpp-nodejs_binary_http-ip", "cpp-nodejs_binary_http-ip-ssl", @@ -85,6 +93,14 @@ "cpp-nodejs_multij-json_http-domain", "cpp-nodejs_multij-json_http-ip", "cpp-nodejs_multij-json_http-ip-ssl", + "cpp-php_binary-accel_buffered-ip", + "cpp-php_binary-accel_framed-ip", + "cpp-php_json_buffered-ip", + "cpp-php_json_framed-ip", + "cpp-php_multi-accel_buffered-ip", + "cpp-php_multi-accel_framed-ip", + "cpp-php_multij-json_buffered-ip", + "cpp-php_multij-json_framed-ip", "cpp-py3_binary-accel_http-domain", "cpp-py3_binary-accel_http-ip", "cpp-py3_binary-accel_http-ip-ssl", @@ -130,6 +146,9 @@ "cpp-py3_multih-header_http-domain", "cpp-py3_multih-header_http-ip", "cpp-py3_multih-header_http-ip-ssl", + "cpp-py3_multih_http-domain", + "cpp-py3_multih_http-ip", + "cpp-py3_multih_http-ip-ssl", "cpp-py3_multij-json_http-domain", "cpp-py3_multij-json_http-ip", "cpp-py3_multij-json_http-ip-ssl", @@ -194,18 +213,18 @@ "cpp-rs_multi_framed-ip", "cpp-rs_multic_buffered-ip", "cpp-rs_multic_framed-ip", - "csharp-erl_binary_buffered-ip-ssl", - "csharp-erl_binary_framed-ip-ssl", - "csharp-erl_compact_buffered-ip-ssl", - "csharp-erl_compact_framed-ip-ssl", - "csharp-rb_binary-accel_buffered-ip-ssl", - "csharp-rb_binary-accel_framed-ip-ssl", - "csharp-rb_binary_buffered-ip-ssl", - "csharp-rb_binary_framed-ip-ssl", - "csharp-rb_compact_buffered-ip-ssl", - "csharp-rb_compact_framed-ip-ssl", - "csharp-rb_json_buffered-ip-ssl", - "csharp-rb_json_framed-ip-ssl", + "netstd-erl_binary_buffered-ip-ssl", + "netstd-erl_binary_framed-ip-ssl", + "netstd-erl_compact_buffered-ip-ssl", + "netstd-erl_compact_framed-ip-ssl", + "netstd-rb_binary-accel_buffered-ip-ssl", + "netstd-rb_binary-accel_framed-ip-ssl", + "netstd-rb_binary_buffered-ip-ssl", + "netstd-rb_binary_framed-ip-ssl", + "netstd-rb_compact_buffered-ip-ssl", + "netstd-rb_compact_framed-ip-ssl", + "netstd-rb_json_buffered-ip-ssl", + "netstd-rb_json_framed-ip-ssl", "d-cl_binary_buffered-ip", "d-cl_binary_framed-ip", "d-cpp_binary_buffered-ip", @@ -352,12 +371,12 @@ "d-py_json_zlib-ip-ssl", "erl-cpp_binary_buffered-ip", "erl-cpp_compact_buffered-ip", - "erl-csharp_binary_buffered-ip", - "erl-csharp_binary_buffered-ip-ssl", - "erl-csharp_binary_framed-ip-ssl", - "erl-csharp_compact_buffered-ip", - "erl-csharp_compact_buffered-ip-ssl", - "erl-csharp_compact_framed-ip-ssl", + "erl-netstd_binary_buffered-ip", + "erl-netstd_binary_buffered-ip-ssl", + "erl-netstd_binary_framed-ip-ssl", + "erl-netstd_compact_buffered-ip", + "erl-netstd_compact_buffered-ip-ssl", + "erl-netstd_compact_framed-ip-ssl", "erl-nodejs_binary_buffered-ip", "erl-nodejs_compact_buffered-ip", "erl-nodets_binary_buffered-ip", @@ -400,12 +419,84 @@ "go-py3_compact-accelc_zlib-ip-ssl", "go-py_binary-accel_zlib-ip-ssl", "go-py_compact-accelc_zlib-ip-ssl", - "hs-csharp_binary_buffered-ip", - "hs-csharp_binary_framed-ip", - "hs-csharp_compact_buffered-ip", - "hs-csharp_compact_framed-ip", - "hs-csharp_json_buffered-ip", - "hs-csharp_json_framed-ip", + "hs-netstd_binary_buffered-ip", + "hs-netstd_binary_framed-ip", + "hs-netstd_compact_buffered-ip", + "hs-netstd_compact_framed-ip", + "hs-netstd_json_buffered-ip", + "hs-netstd_json_framed-ip", + "hs-php_binary-accel_buffered-ip", + "hs-php_binary-accel_framed-ip", + "hs-php_json_buffered-ip", + "hs-php_json_framed-ip", + "java-netstd_binary_buffered-ip-ssl", + "java-netstd_binary_fastframed-framed-ip-ssl", + "java-netstd_binary_framed-ip-ssl", + "java-netstd_compact_buffered-ip-ssl", + "java-netstd_compact_fastframed-framed-ip-ssl", + "java-netstd_compact_framed-ip-ssl", + "java-netstd_json_buffered-ip", + "java-netstd_json_buffered-ip-ssl", + "java-netstd_json_fastframed-framed-ip", + "java-netstd_json_fastframed-framed-ip-ssl", + "java-netstd_json_framed-ip", + "java-netstd_json_framed-ip-ssl", + "java-netstd_multi-binary_buffered-ip-ssl", + "java-netstd_multi-binary_fastframed-framed-ip-ssl", + "java-netstd_multi-binary_framed-ip-ssl", + "java-netstd_multic-compact_buffered-ip-ssl", + "java-netstd_multic-compact_fastframed-framed-ip-ssl", + "java-netstd_multic-compact_framed-ip-ssl", + "java-netstd_multij-json_buffered-ip", + "java-netstd_multij-json_buffered-ip-ssl", + "java-netstd_multij-json_fastframed-framed-ip", + "java-netstd_multij-json_fastframed-framed-ip-ssl", + "java-netstd_multij-json_framed-ip", + "java-netstd_multij-json_framed-ip-ssl", + "java-php_binary-accel_buffered-ip", + "java-php_binary-accel_fastframed-framed-ip", + "java-php_binary-accel_framed-ip", + "java-php_json_buffered-ip", + "java-php_json_fastframed-framed-ip", + "java-php_json_framed-ip", + "java-php_multi-accel_buffered-ip", + "java-php_multi-accel_fastframed-framed-ip", + "java-php_multi-accel_framed-ip", + "java-php_multij-json_buffered-ip", + "java-php_multij-json_fastframed-framed-ip", + "java-php_multij-json_framed-ip", + "netstd-netstd_binary_buffered-ip-ssl", + "netstd-netstd_binary_framed-ip-ssl", + "netstd-netstd_compact_buffered-ip-ssl", + "netstd-netstd_compact_framed-ip-ssl", + "netstd-netstd_json_buffered-ip", + "netstd-netstd_json_buffered-ip-ssl", + "netstd-netstd_json_framed-ip", + "netstd-netstd_json_framed-ip-ssl", + "netstd-php_binary-accel_buffered-ip", + "netstd-php_binary-accel_framed-ip", + "netstd-php_json_buffered-ip", + "netstd-php_json_framed-ip", + "netstd-py3_binary-accel_framed-ip", + "netstd-py3_binary-accel_framed-ip-ssl", + "netstd-py3_binary_framed-ip", + "netstd-py3_binary_framed-ip-ssl", + "netstd-py3_compact-accelc_framed-ip", + "netstd-py3_compact-accelc_framed-ip-ssl", + "netstd-py3_compact_framed-ip", + "netstd-py3_compact_framed-ip-ssl", + "netstd-py3_json_framed-ip", + "netstd-py3_json_framed-ip-ssl", + "netstd-py_binary-accel_framed-ip", + "netstd-py_binary-accel_framed-ip-ssl", + "netstd-py_binary_framed-ip", + "netstd-py_binary_framed-ip-ssl", + "netstd-py_compact-accelc_framed-ip", + "netstd-py_compact-accelc_framed-ip-ssl", + "netstd-py_compact_framed-ip", + "netstd-py_compact_framed-ip-ssl", + "netstd-py_json_framed-ip", + "netstd-py_json_framed-ip-ssl", "nodejs-cpp_binary_http-domain", "nodejs-cpp_binary_http-ip", "nodejs-cpp_binary_http-ip-ssl", @@ -450,6 +541,18 @@ "nodejs-lua_binary_http-ip", "nodejs-lua_compact_http-ip", "nodejs-lua_json_http-ip", + "nodejs-netstd_binary_buffered-ip-ssl", + "nodejs-netstd_binary_framed-ip-ssl", + "nodejs-netstd_compact_buffered-ip-ssl", + "nodejs-netstd_compact_framed-ip-ssl", + "nodejs-netstd_json_buffered-ip", + "nodejs-netstd_json_buffered-ip-ssl", + "nodejs-netstd_json_framed-ip", + "nodejs-netstd_json_framed-ip-ssl", + "nodejs-php_binary-accel_buffered-ip", + "nodejs-php_binary-accel_framed-ip", + "nodejs-php_json_buffered-ip", + "nodejs-php_json_framed-ip", "nodejs-py3_binary-accel_http-domain", "nodejs-py3_binary-accel_http-ip", "nodejs-py3_binary-accel_http-ip-ssl", @@ -486,6 +589,7 @@ "nodejs-py_json_http-domain", "nodejs-py_json_http-ip", "nodejs-py_json_http-ip-ssl", + "nodets-php_binary-accel_buffered-ip", "perl-rs_multi_buffered-ip", "perl-rs_multi_framed-ip", "py-cpp_accel-binary_http-domain", @@ -601,6 +705,17 @@ "py-lua_binary_http-ip", "py-lua_compact_http-ip", "py-lua_json_http-ip", + "py-netstd_accel-binary_framed-ip-ssl", + "py-netstd_accelc-compact_buffered-ip-ssl", + "py-netstd_accelc-compact_framed-ip-ssl", + "py-netstd_binary_buffered-ip-ssl", + "py-netstd_binary_framed-ip-ssl", + "py-netstd_compact_buffered-ip-ssl", + "py-netstd_compact_framed-ip-ssl", + "py-netstd_json_buffered-ip", + "py-netstd_json_buffered-ip-ssl", + "py-netstd_json_framed-ip", + "py-netstd_json_framed-ip-ssl", "py-nodejs_accel-binary_http-domain", "py-nodejs_accelc-compact_http-domain", "py-nodejs_binary_http-domain", @@ -609,6 +724,12 @@ "py-nodejs_header_http-domain", "py-rs_multi_buffered-ip", "py-rs_multi_framed-ip", + "py-php_accel_buffered-ip", + "py-php_accel_framed-ip", + "py-php_binary-accel_buffered-ip", + "py-php_binary-accel_framed-ip", + "py-php_json_buffered-ip", + "py-php_json_framed-ip", "py-rs_multia-multi_buffered-ip", "py-rs_multia-multi_framed-ip", "py-rs_multiac-multic_buffered-ip", @@ -728,6 +849,17 @@ "py3-lua_binary_http-ip", "py3-lua_compact_http-ip", "py3-lua_json_http-ip", + "py3-netstd_accel-binary_framed-ip-ssl", + "py3-netstd_accelc-compact_buffered-ip-ssl", + "py3-netstd_accelc-compact_framed-ip-ssl", + "py3-netstd_binary_buffered-ip-ssl", + "py3-netstd_binary_framed-ip-ssl", + "py3-netstd_compact_buffered-ip-ssl", + "py3-netstd_compact_framed-ip-ssl", + "py3-netstd_json_buffered-ip", + "py3-netstd_json_buffered-ip-ssl", + "py3-netstd_json_framed-ip", + "py3-netstd_json_framed-ip-ssl", "py3-nodejs_accel-binary_http-domain", "py3-nodejs_accelc-compact_http-domain", "py3-nodejs_binary_http-domain", @@ -736,6 +868,12 @@ "py3-nodejs_header_http-domain", "py3-rs_multi_buffered-ip", "py3-rs_multi_framed-ip", + "py3-php_accel_buffered-ip", + "py3-php_accel_framed-ip", + "py3-php_binary-accel_buffered-ip", + "py3-php_binary-accel_framed-ip", + "py3-php_json_buffered-ip", + "py3-php_json_framed-ip", "py3-rs_multia-multi_buffered-ip", "py3-rs_multia-multi_framed-ip", "py3-rs_multiac-multic_buffered-ip", diff --git a/test/netstd/Client/Program.cs b/test/netstd/Client/Program.cs index 92000da5625..0fe2ccee26e 100644 --- a/test/netstd/Client/Program.cs +++ b/test/netstd/Client/Program.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Generic; +using System.Linq; using ThriftTest; namespace Client @@ -35,13 +36,13 @@ public static int Main(string[] args) } // run whatever mode is choosen, default to test impl - var firstArg = args.Length > 0 ? args[0] : string.Empty; - switch (firstArg) + var argslist = new List(args); + switch (argslist.FirstOrDefault()) { - case "client": - Console.WriteLine("The 'client' argument is no longer required."); - PrintHelp(); - return -1; + case "client": // crosstest wants to pass this, so just emit a hint and ignore + Console.WriteLine("Hint: The 'client' argument is no longer required."); + argslist.RemoveAt(0); + return TestClient.Execute(argslist); case "--performance": case "--performance-test": return Tests.PerformanceTests.Execute(); @@ -49,7 +50,7 @@ public static int Main(string[] args) PrintHelp(); return 0; default: - return TestClient.Execute(new List(args)); + return TestClient.Execute(argslist); } } diff --git a/test/netstd/Makefile.am b/test/netstd/Makefile.am index 376ffb71e15..9712fc2a431 100644 --- a/test/netstd/Makefile.am +++ b/test/netstd/Makefile.am @@ -20,10 +20,10 @@ SUBDIRS = . all-local: - $(DOTNETCORE) build + $(DOTNETCORE) build -c Release precross: - $(DOTNETCORE) build + $(DOTNETCORE) build -c Release clean-local: $(RM) -r Client/bin diff --git a/test/netstd/Server/Program.cs b/test/netstd/Server/Program.cs index 1b8ffd46a8e..8414b4810be 100644 --- a/test/netstd/Server/Program.cs +++ b/test/netstd/Server/Program.cs @@ -16,6 +16,7 @@ // under the License. using System; +using System.Linq; using System.Collections.Generic; using ThriftTest; @@ -35,18 +36,18 @@ public static int Main(string[] args) } // run whatever mode is choosen, default to test impl - var firstArg = args.Length > 0 ? args[0] : string.Empty; - switch (firstArg) + var argslist = new List(args); + switch (argslist.FirstOrDefault()) { - case "server": - Console.WriteLine("The 'server' argument is no longer required."); - PrintHelp(); - return -1; + case "server": // crosstest wants to pass this, so just emit a hint and ignore + Console.WriteLine("Hint: The 'server' argument is no longer required."); + argslist.RemoveAt(0); + return TestServer.Execute(argslist); case "--help": PrintHelp(); return 0; default: - return TestServer.Execute(new List( args)); + return TestServer.Execute(argslist); } } diff --git a/test/tests.json b/test/tests.json index dbee398a3be..42e5d6aab15 100644 --- a/test/tests.json +++ b/test/tests.json @@ -419,48 +419,7 @@ "workdir": "rb/gen-rb" }, { - "name": "csharp", - "env": { - "MONO_PATH": "../../lib/csharp/" - }, - "transports": [ - "buffered", - "framed" - ], - "sockets": [ - "ip", - "ip-ssl" - ], - "protocols": [ - "binary", - "compact", - "json" - ], - "server": { - "command": [ - "mono", - "TestClientServer.exe", - "server" - ] - }, - "client": { - "timeout": 9, - "command": [ - "mono", - "TestClientServer.exe", - "client" - ], - "protocols": [ - "multi", - "multic", - "multi:binary", - "multic:compact" - ] - }, - "workdir": "csharp" - }, - { - "name": "netcore", + "name": "netstd", "transports": [ "buffered", "framed" @@ -493,7 +452,7 @@ "client" ] }, - "workdir": "netcore" + "workdir": "netstd" }, { "name": "perl", diff --git a/tutorial/Makefile.am b/tutorial/Makefile.am index f7a49d00217..484b485ee16 100755 --- a/tutorial/Makefile.am +++ b/tutorial/Makefile.am @@ -105,7 +105,6 @@ endif # EXTRA_DIST to be included in the release EXTRA_DIST = \ as3 \ - csharp \ d \ delphi \ erl \ diff --git a/tutorial/csharp/CsharpClient/CsharpClient.cs b/tutorial/csharp/CsharpClient/CsharpClient.cs deleted file mode 100644 index 113a4722345..00000000000 --- a/tutorial/csharp/CsharpClient/CsharpClient.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using Thrift; -using Thrift.Protocol; -using Thrift.Server; -using Thrift.Transport; - - -namespace CSharpTutorial -{ - public class CSharpClient - { - public static void Main() - { - try - { - TTransport transport = new TSocket("localhost", 9090); - TProtocol protocol = new TBinaryProtocol(transport); - Calculator.Client client = new Calculator.Client(protocol); - - transport.Open(); - try - { - client.ping(); - Console.WriteLine("ping()"); - - int sum = client.add(1, 1); - Console.WriteLine("1+1={0}", sum); - - Work work = new Work(); - - work.Op = Operation.DIVIDE; - work.Num1 = 1; - work.Num2 = 0; - try - { - int quotient = client.calculate(1, work); - Console.WriteLine("Whoa we can divide by 0"); - } - catch (InvalidOperation io) - { - Console.WriteLine("Invalid operation: " + io.Why); - } - - work.Op = Operation.SUBTRACT; - work.Num1 = 15; - work.Num2 = 10; - try - { - int diff = client.calculate(1, work); - Console.WriteLine("15-10={0}", diff); - } - catch (InvalidOperation io) - { - Console.WriteLine("Invalid operation: " + io.Why); - } - - SharedStruct log = client.getStruct(1); - Console.WriteLine("Check log: {0}", log.Value); - - } - finally - { - transport.Close(); - } - } - catch (TApplicationException x) - { - Console.WriteLine(x.StackTrace); - } - - } - } -} diff --git a/tutorial/csharp/CsharpClient/CsharpClient.csproj b/tutorial/csharp/CsharpClient/CsharpClient.csproj deleted file mode 100644 index 1ea7ff63902..00000000000 --- a/tutorial/csharp/CsharpClient/CsharpClient.csproj +++ /dev/null @@ -1,110 +0,0 @@ - - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {18F24087-4760-43DA-ACAB-7B9F0E096B11} - Exe - Properties - CsharpClient - CsharpClient - v3.5 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - Calculator.cs - - - InvalidOperation.cs - - - Operation.cs - - - SharedService.cs - - - SharedStruct.cs - - - tutorial.Constants.cs - - - Work.cs - - - - - - - {499eb63c-d74c-47e8-ae48-a2fc94538e9d} - Thrift - - - - - pushd "$(SolutionDir)" -thrift -gen csharp -r ../tutorial.thrift -popd - - - - \ No newline at end of file diff --git a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs deleted file mode 100644 index 8f5b32a2842..00000000000 --- a/tutorial/csharp/CsharpClient/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("CsharpClient")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("1a461214-fa28-452a-bd1d-d23ca8e947e3")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.14.0.0")] -[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/tutorial/csharp/CsharpServer/CsharpServer.cs b/tutorial/csharp/CsharpServer/CsharpServer.cs deleted file mode 100644 index 439790aaf59..00000000000 --- a/tutorial/csharp/CsharpServer/CsharpServer.cs +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System; -using System.Collections.Generic; -using Thrift.Server; -using Thrift.Transport; - -namespace CSharpTutorial -{ - public class CalculatorHandler : Calculator.Iface - { - Dictionary log; - - public CalculatorHandler() - { - log = new Dictionary(); - } - - public void ping() - { - Console.WriteLine("ping()"); - } - - public int add(int n1, int n2) - { - Console.WriteLine("add({0},{1})", n1, n2); - return n1 + n2; - } - - public int calculate(int logid, Work work) - { - Console.WriteLine("calculate({0}, [{1},{2},{3}])", logid, work.Op, work.Num1, work.Num2); - int val = 0; - switch (work.Op) - { - case Operation.ADD: - val = work.Num1 + work.Num2; - break; - - case Operation.SUBTRACT: - val = work.Num1 - work.Num2; - break; - - case Operation.MULTIPLY: - val = work.Num1 * work.Num2; - break; - - case Operation.DIVIDE: - if (work.Num2 == 0) - { - InvalidOperation io = new InvalidOperation(); - io.WhatOp = (int)work.Op; - io.Why = "Cannot divide by 0"; - throw io; - } - val = work.Num1 / work.Num2; - break; - - default: - { - InvalidOperation io = new InvalidOperation(); - io.WhatOp = (int)work.Op; - io.Why = "Unknown operation"; - throw io; - } - } - - SharedStruct entry = new SharedStruct(); - entry.Key = logid; - entry.Value = val.ToString(); - log[logid] = entry; - - return val; - } - - public SharedStruct getStruct(int key) - { - Console.WriteLine("getStruct({0})", key); - return log[key]; - } - - public void zip() - { - Console.WriteLine("zip()"); - } - } - - public class CSharpServer - { - public static void Main() - { - try - { - CalculatorHandler handler = new CalculatorHandler(); - Calculator.Processor processor = new Calculator.Processor(handler); - TServerTransport serverTransport = new TServerSocket(9090); - TServer server = new TSimpleServer(processor, serverTransport); - - // Use this for a multithreaded server - // server = new TThreadPoolServer(processor, serverTransport); - - Console.WriteLine("Starting the server..."); - server.Serve(); - } - catch (Exception x) - { - Console.WriteLine(x.StackTrace); - } - Console.WriteLine("done."); - } - } -} diff --git a/tutorial/csharp/CsharpServer/CsharpServer.csproj b/tutorial/csharp/CsharpServer/CsharpServer.csproj deleted file mode 100644 index 07481806c33..00000000000 --- a/tutorial/csharp/CsharpServer/CsharpServer.csproj +++ /dev/null @@ -1,111 +0,0 @@ - - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {66707BAE-BBF9-4F03-B53E-BE3AD58322F8} - Exe - Properties - CsharpServer - CsharpServer - v3.5 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - 3.5 - - - 3.5 - - - 3.5 - - - - - - - Calculator.cs - - - InvalidOperation.cs - - - Operation.cs - - - SharedService.cs - - - SharedStruct.cs - - - tutorial.Constants.cs - - - Work.cs - - - - - - - {499eb63c-d74c-47e8-ae48-a2fc94538e9d} - Thrift - - - - - pushd "$(SolutionDir)" -thrift -gen csharp -r ../tutorial.thrift -popd - - - - - \ No newline at end of file diff --git a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs b/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs deleted file mode 100644 index 0d4f0fbb1b7..00000000000 --- a/tutorial/csharp/CsharpServer/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("CsharpServer")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("The Apache Software Foundation")] -[assembly: AssemblyProduct("Thrift")] -[assembly: AssemblyCopyright("The Apache Software Foundation")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("e3b428f4-b2e9-4fc1-8a34-84abc4339860")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.14.0.0")] -[assembly: AssemblyFileVersion("0.14.0.0")] diff --git a/tutorial/csharp/tutorial.sln b/tutorial/csharp/tutorial.sln deleted file mode 100644 index ec57a188d3b..00000000000 --- a/tutorial/csharp/tutorial.sln +++ /dev/null @@ -1,39 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift", "..\..\lib\csharp\src\Thrift.csproj", "{499EB63C-D74C-47E8-AE48-A2FC94538E9D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsharpClient", "CsharpClient\CsharpClient.csproj", "{18F24087-4760-43DA-ACAB-7B9F0E096B11}" - ProjectSection(ProjectDependencies) = postProject - {499EB63C-D74C-47E8-AE48-A2FC94538E9D} = {499EB63C-D74C-47E8-AE48-A2FC94538E9D} - {66707BAE-BBF9-4F03-B53E-BE3AD58322F8} = {66707BAE-BBF9-4F03-B53E-BE3AD58322F8} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CsharpServer", "CsharpServer\CsharpServer.csproj", "{66707BAE-BBF9-4F03-B53E-BE3AD58322F8}" - ProjectSection(ProjectDependencies) = postProject - {499EB63C-D74C-47E8-AE48-A2FC94538E9D} = {499EB63C-D74C-47E8-AE48-A2FC94538E9D} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {499EB63C-D74C-47E8-AE48-A2FC94538E9D}.Release|Any CPU.Build.0 = Release|Any CPU - {18F24087-4760-43DA-ACAB-7B9F0E096B11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {18F24087-4760-43DA-ACAB-7B9F0E096B11}.Debug|Any CPU.Build.0 = Debug|Any CPU - {18F24087-4760-43DA-ACAB-7B9F0E096B11}.Release|Any CPU.ActiveCfg = Release|Any CPU - {18F24087-4760-43DA-ACAB-7B9F0E096B11}.Release|Any CPU.Build.0 = Release|Any CPU - {66707BAE-BBF9-4F03-B53E-BE3AD58322F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {66707BAE-BBF9-4F03-B53E-BE3AD58322F8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {66707BAE-BBF9-4F03-B53E-BE3AD58322F8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {66707BAE-BBF9-4F03-B53E-BE3AD58322F8}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/tutorial/netstd/Makefile.am b/tutorial/netstd/Makefile.am index e3055565567..f295cc0729b 100644 --- a/tutorial/netstd/Makefile.am +++ b/tutorial/netstd/Makefile.am @@ -20,7 +20,7 @@ SUBDIRS = . all-local: - $(DOTNETCORE) build + $(DOTNETCORE) build -c Release clean-local: $(RM) Interfaces.dll From 1b7b00cde9cdd4a0dd9f09f240df551c87d4ab27 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 26 Feb 2020 22:01:18 +0100 Subject: [PATCH 519/756] CI broken, reverting following PRs reverted https://github.com/apache/thrift/pull/2025 reverted https://github.com/apache/thrift/pull/2026 Reverted https://github.com/apache/thrift/pull/2021 --- CMakeLists.txt | 8 ------- compiler/cpp/CMakeLists.txt | 4 ---- lib/js/CMakeLists.txt | 45 ------------------------------------- lib/js/Makefile.am | 1 - lib/nodejs/CMakeLists.txt | 44 ------------------------------------ lib/nodejs/Makefile.am | 1 - 6 files changed, 103 deletions(-) delete mode 100644 lib/js/CMakeLists.txt delete mode 100644 lib/nodejs/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 18e52f638fb..f2e682ac2c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,14 +113,6 @@ if(BUILD_JAVA) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/java) endif() -if(BUILD_JAVASCRIPT) - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/js) -endif() - -if(BUILD_NODEJS) - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/nodejs) -endif() - if(BUILD_PYTHON) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/py) if(BUILD_TESTING) diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt index 7125cd72c42..92b0a5f3e87 100644 --- a/compiler/cpp/CMakeLists.txt +++ b/compiler/cpp/CMakeLists.txt @@ -115,10 +115,6 @@ set_target_properties(thrift-compiler PROPERTIES OUTPUT_NAME thrift) target_link_libraries(thrift-compiler parse) -add_custom_command(TARGET thrift-compiler POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/compiler/cpp" - COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_BINARY_DIR}/bin/thrift${CMAKE_EXECUTABLE_SUFFIX}" "${CMAKE_SOURCE_DIR}/compiler/cpp/") - install(TARGETS thrift-compiler DESTINATION bin) if(BUILD_TESTING) diff --git a/lib/js/CMakeLists.txt b/lib/js/CMakeLists.txt deleted file mode 100644 index 340b3c6a7b2..00000000000 --- a/lib/js/CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -if(NOT JAVASCRIPT_INSTALL_DIR) - if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") - set(JAVASCRIPT_INSTALL_DIR "${LIB_INSTALL_DIR}/js") - else() - set(JAVASCRIPT_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/js") - endif() -endif() - -if(IS_ABSOLUTE "${DOC_INSTALL_DIR}") - set(JAVASCRIPT_DOC_INSTALL_DIR "${DOC_INSTALL_DIR}/js") -else() - set(JAVASCRIPT_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}/js") -endif() - -add_custom_target(ThriftJavascript ALL - COMMENT "Building Javascript library using npm + Grunt Wrapper" - COMMAND npm install - COMMAND npx grunt - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -) - -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/dist/ - DESTINATION ${JAVASCRIPT_INSTALL_DIR} - FILES_MATCHING PATTERN "thrift*.js") -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/ - DESTINATION ${JAVASCRIPT_DOC_INSTALL_DIR}) diff --git a/lib/js/Makefile.am b/lib/js/Makefile.am index c14303e67f6..b534042649a 100644 --- a/lib/js/Makefile.am +++ b/lib/js/Makefile.am @@ -58,6 +58,5 @@ EXTRA_DIST = \ package.json \ package-lock.json \ README.md \ - CMakeLists.txt \ src \ test diff --git a/lib/nodejs/CMakeLists.txt b/lib/nodejs/CMakeLists.txt deleted file mode 100644 index a0c8508498b..00000000000 --- a/lib/nodejs/CMakeLists.txt +++ /dev/null @@ -1,44 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -if(NOT NODEJS_INSTALL_DIR) - if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") - set(NODEJS_INSTALL_DIR "${LIB_INSTALL_DIR}/nodejs") - else() - set(NODEJS_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/nodejs") - endif() -endif() - -# Currently no doc -#if(IS_ABSOLUTE "${DOC_INSTALL_DIR}") -# set(NODEJS_DOC_INSTALL_DIR "${DOC_INSTALL_DIR}/nodejs") -#else() -# set(NODEJS_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}/nodejs") -#endif() - -add_custom_target(ThriftNodeJS ALL - COMMENT "Installing NodeJS dependencies npm" - COMMAND npm install - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} -) - -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib/ - DESTINATION ${NODEJS_INSTALL_DIR}) -#install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/ -# DESTINATION ${NODEJS_DOC_INSTALL_DIR}) diff --git a/lib/nodejs/Makefile.am b/lib/nodejs/Makefile.am index 67f6ff6a90a..71068b58f18 100755 --- a/lib/nodejs/Makefile.am +++ b/lib/nodejs/Makefile.am @@ -42,5 +42,4 @@ EXTRA_DIST = \ lib \ test \ coding_standards.md \ - CMakeLists.txt \ README.md From e791760098b6a9490e19af2b18a3e002f561973b Mon Sep 17 00:00:00 2001 From: Nik Clayton Date: Thu, 5 Mar 2020 11:51:15 +0100 Subject: [PATCH 520/756] THRIFT-5131: Require >= 1.1.4 of integer-encoding dependency Client: Rust Patch: Nik Clayton This closes #2045 Versions 1.1.0 - 1.1.3 of the integer-encoding crate had a bug where numbers larger than 0x4000_0000_0000_0000 would cause a panic during decoding. Add a test to be sure that numbers up to i64::maxvalue() encode and decode successfully. --- lib/rs/Cargo.toml | 2 +- lib/rs/src/protocol/compact.rs | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml index 0c71bab4195..0626da8dfc3 100644 --- a/lib/rs/Cargo.toml +++ b/lib/rs/Cargo.toml @@ -13,6 +13,6 @@ keywords = ["thrift"] [dependencies] ordered-float = "1.0" byteorder = "1.3" -integer-encoding = "1.0" +integer-encoding = ">=1.1.4" # https://issues.apache.org/jira/browse/THRIFT-5131 log = "0.4" threadpool = "1.7" diff --git a/lib/rs/src/protocol/compact.rs b/lib/rs/src/protocol/compact.rs index 3e17398a0d8..029f850414e 100644 --- a/lib/rs/src/protocol/compact.rs +++ b/lib/rs/src/protocol/compact.rs @@ -714,6 +714,31 @@ mod tests { assert_eq_written_bytes!(o_prot, expected); } + #[test] + fn must_round_trip_upto_i64_maxvalue() { + // See https://issues.apache.org/jira/browse/THRIFT-5131 + for i in 0..64 { + let (mut i_prot, mut o_prot) = test_objects(); + let val: i64 = ((1u64 << i) - 1) as i64; + + o_prot + .write_field_begin(&TFieldIdentifier::new( + "val", + TType::I64, + 1 + )) + .unwrap(); + o_prot.write_i64(val).unwrap(); + o_prot.write_field_end().unwrap(); + o_prot.flush().unwrap(); + + copy_write_buffer_to_read_buffer!(o_prot); + + i_prot.read_field_begin().unwrap(); + assert_eq!(val, i_prot.read_i64().unwrap()); + } + } + #[test] fn must_round_trip_message_begin() { let (mut i_prot, mut o_prot) = test_objects(); From 2e115774776f2e5bcfe826e30548feab030fb263 Mon Sep 17 00:00:00 2001 From: Jano Svitok Date: Fri, 6 Mar 2020 09:01:43 +0100 Subject: [PATCH 521/756] THRIFT-5111: Upgrade rust to 1.36.0 Client: Rust Patch: Jano Svitok This closes #2050 Also contains portions of THRIFT-4547: Upgrade Swift in docker to 5.1.4 Client: Swift Patch: Jano Svitok Linux version 4.2.0 does not have FileHandle.acceptConnectionInBackgroundAndNotify() implemented. We need at least 5.1 for TSocketServer to run in docker. In the meantime, URLRequest was moved to FoundationNetworking. To keep compatibility with previous versions, conditional import is used. --- build/docker/README.md | 2 +- build/docker/ubuntu-bionic/Dockerfile | 8 ++++---- lib/swift/Sources/THTTPSessionTransport.swift | 9 ++++++++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/build/docker/README.md b/build/docker/README.md index 6f9c024e614..6f170e104b6 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -194,4 +194,4 @@ Last updated: October 1, 2017 | ruby | 2.3.1p112 | 2.5.1p57 | | | rust | 1.34.0 | 1.35.0 | | | smalltalk | | | Not in CI | -| swift | | 4.2.1 | | +| swift | | 5.1.4 | | diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index 464af0bd1e3..c22a859df90 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -247,14 +247,14 @@ RUN apt-get install -y --no-install-recommends \ ruby-bundler # Rust dependencies -RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.35.0 -y +RUN curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain 1.36.0 -y ENV PATH /root/.cargo/bin:$PATH # Swift on Linux for cross tests RUN cd / && \ - wget --quiet https://swift.org/builds/swift-4.2.1-release/ubuntu1804/swift-4.2.1-RELEASE/swift-4.2.1-RELEASE-ubuntu18.04.tar.gz && \ - tar xf swift-4.2.1-RELEASE-ubuntu18.04.tar.gz --strip-components=1 && \ - rm swift-4.2.1-RELEASE-ubuntu18.04.tar.gz && \ + wget --quiet https://swift.org/builds/swift-5.1.4-release/ubuntu1804/swift-5.1.4-RELEASE/swift-5.1.4-RELEASE-ubuntu18.04.tar.gz && \ + tar xf swift-5.1.4-RELEASE-ubuntu18.04.tar.gz --strip-components=1 && \ + rm swift-5.1.4-RELEASE-ubuntu18.04.tar.gz && \ swift --version # cppcheck-1.82 has a nasty cpp parser bug, so we're using something newer diff --git a/lib/swift/Sources/THTTPSessionTransport.swift b/lib/swift/Sources/THTTPSessionTransport.swift index 3c0af8eb890..f66da922e81 100644 --- a/lib/swift/Sources/THTTPSessionTransport.swift +++ b/lib/swift/Sources/THTTPSessionTransport.swift @@ -18,8 +18,15 @@ */ import Foundation -import Dispatch +// Conditional import for URLRequest +// It was moved from Foundation to FoundationNetworking in 5.1, but +// not on Darwin. See https://stackoverflow.com/a/58606520 +#if canImport(FoundationNetworking) +import FoundationNetworking +#endif + +import Dispatch public class THTTPSessionTransport: TAsyncTransport { public class Factory : TAsyncTransportFactory { From b1f755a1e920f01750cc868dafd193413d17af8d Mon Sep 17 00:00:00 2001 From: Jano Svitok Date: Mon, 9 Mar 2020 20:13:54 +0000 Subject: [PATCH 522/756] THRIFT-5120: Use nodejs 8.x Client: node Patch: Jano Svitok This closes #2054 JSDoc 3.6.3 requires Node.js >=8.15.0 --- build/docker/ubuntu-xenial/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index fbbe1c2cbf7..57c996485b5 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -17,7 +17,7 @@ # - dart: does not come with Ubuntu so we're installing 2.0.0-1 for coverage # - dotnet: does not come with Ubuntu # - go: Xenial comes with 1.6, but we need 1.10 or later -# - nodejs: Xenial comes with 4.2.6 which exits LTS April 2018, so we're installing 6.x +# - nodejs: Xenial comes with 4.2.6 which exits LTS April 2018, so we're installing 8.x # - ocaml: causes stack overflow error, just started March 2018 not sure why # @@ -54,7 +54,7 @@ RUN apt-get update && \ # node.js curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ - echo "deb https://deb.nodesource.com/node_6.x xenial main" | tee /etc/apt/sources.list.d/nodesource.list + echo "deb https://deb.nodesource.com/node_8.x xenial main" | tee /etc/apt/sources.list.d/nodesource.list ### install general dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ From 299b68e72334086c4685a5eaef397eb7c6129044 Mon Sep 17 00:00:00 2001 From: Jano Svitok Date: Mon, 9 Mar 2020 23:07:30 +0100 Subject: [PATCH 523/756] THRIFT-5100: Upgrade ruby to 2.4 Client: Ruby Patch: Jano Svitok This closes #2054 due to byebug gem 11.1 (used by pry-byebug) --- build/docker/ubuntu-xenial/Dockerfile | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index 57c996485b5..dca687fd429 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -54,7 +54,10 @@ RUN apt-get update && \ # node.js curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ - echo "deb https://deb.nodesource.com/node_8.x xenial main" | tee /etc/apt/sources.list.d/nodesource.list + echo "deb https://deb.nodesource.com/node_8.x xenial main" | tee /etc/apt/sources.list.d/nodesource.list &&\ + +# ruby 2.4 + apt-add-repository ppa:brightbox/ruby-ng ### install general dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -245,8 +248,8 @@ RUN apt-get install -y --no-install-recommends \ RUN apt-get install -y --no-install-recommends \ `# Ruby dependencies` \ - ruby \ - ruby-dev \ + ruby2.4 \ + ruby2.4-dev \ ruby-bundler # Rust dependencies From adf278dae0b1e53baf100b6a7108327698545366 Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Mon, 9 Mar 2020 19:07:43 +0800 Subject: [PATCH 524/756] fix typos in CHANGES.md Patch: zeshuai007 This closes #2053 --- CHANGES.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 10abcbb1ccb..ca84cb7d25f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -858,8 +858,8 @@ Released 2017-DEC-27 ### New Feature - [THRIFT-750](https://issues.apache.org/jira/browse/THRIFT-750) - C++ Compiler Virtual Function Option - [THRIFT-2945](https://issues.apache.org/jira/browse/THRIFT-2945) - Implement support for Rust language -- [THRIFT-3857](https://issues.apache.org/jira/browse/THRIFT-3857) - thrift js:node complier support an object as parameter not an instance of struct -- [THRIFT-3933](https://issues.apache.org/jira/browse/THRIFT-3933) - Port official C# .NET library for Thrift to C# .NET Core libary +- [THRIFT-3857](https://issues.apache.org/jira/browse/THRIFT-3857) - thrift js:node compiler support an object as parameter not an instance of struct +- [THRIFT-3933](https://issues.apache.org/jira/browse/THRIFT-3933) - Port official C# .NET library for Thrift to C# .NET Core library - [THRIFT-4039](https://issues.apache.org/jira/browse/THRIFT-4039) - Update of Apache Thrift .Net Core lib - [THRIFT-4113](https://issues.apache.org/jira/browse/THRIFT-4113) - Provide a buffer transport for reading/writing in memory byte stream @@ -1017,7 +1017,7 @@ Released 2017-DEC-27 - [THRIFT-3689](https://issues.apache.org/jira/browse/THRIFT-3689) - thrift_reconnecting_client start failed when server is not available - [THRIFT-3695](https://issues.apache.org/jira/browse/THRIFT-3695) - Fix D test scripts - [THRIFT-3675](https://issues.apache.org/jira/browse/THRIFT-3675) - Union is not serialized correctly by Thrift C Glib -- [THRIFT-3673](https://issues.apache.org/jira/browse/THRIFT-3673) - API fails with std::exception after a timeout occured in earlier any API call +- [THRIFT-3673](https://issues.apache.org/jira/browse/THRIFT-3673) - API fails with std::exception after a timeout occurred in earlier any API call - [THRIFT-3709](https://issues.apache.org/jira/browse/THRIFT-3709) - Comment syntax can produce broken code - [THRIFT-3705](https://issues.apache.org/jira/browse/THRIFT-3705) - Go map has incorrect types when used with forward-defined types - [THRIFT-3702](https://issues.apache.org/jira/browse/THRIFT-3702) - Fix cross tests for Dart compact protocol (3 failing) @@ -1627,7 +1627,7 @@ Released March 13, 2019 to backport a CVE fix to the popular 0.9.3 release. - [THRIFT-2881](https://issues.apache.org/jira/browse/THRIFT-2881) - Handle errors from Accept() correctly - [THRIFT-2849](https://issues.apache.org/jira/browse/THRIFT-2849) - Spell errors reported by codespell tool - [THRIFT-2870](https://issues.apache.org/jira/browse/THRIFT-2870) - C++ TJSONProtocol using locale dependent formatting -- [THRIFT-2882](https://issues.apache.org/jira/browse/THRIFT-2882) - Lua Generator: using string.len funtion to get struct(map,list,set) size +- [THRIFT-2882](https://issues.apache.org/jira/browse/THRIFT-2882) - Lua Generator: using string.len function to get struct(map,list,set) size - [THRIFT-2864](https://issues.apache.org/jira/browse/THRIFT-2864) - JSON generator missing from Visual Studio build project - [THRIFT-2878](https://issues.apache.org/jira/browse/THRIFT-2878) - Go validation support of required fields - [THRIFT-2873](https://issues.apache.org/jira/browse/THRIFT-2873) - TPipe and TPipeServer don't compile on Windows with UNICODE enabled @@ -1890,7 +1890,7 @@ Released March 13, 2019 to backport a CVE fix to the popular 0.9.3 release. - [THRIFT-2967](https://issues.apache.org/jira/browse/THRIFT-2967) - Add .editorconfig to root - [THRIFT-3033](https://issues.apache.org/jira/browse/THRIFT-3033) - Perl: Support for Multiplexing Services on any Transport, Protocol and Server - [THRIFT-3174](https://issues.apache.org/jira/browse/THRIFT-3174) - Initialism code in the Go compiler doesn't check first word -- [THRIFT-3193](https://issues.apache.org/jira/browse/THRIFT-3193) - Option to supress date value in @Generated annotation +- [THRIFT-3193](https://issues.apache.org/jira/browse/THRIFT-3193) - Option to suppress date value in @Generated annotation - [THRIFT-3305](https://issues.apache.org/jira/browse/THRIFT-3305) - Missing dist files for 0.9.3 release candidate - [THRIFT-3341](https://issues.apache.org/jira/browse/THRIFT-3341) - Add testBool methods - [THRIFT-3308](https://issues.apache.org/jira/browse/THRIFT-3308) - Fix broken test cases for 0.9.3 release candidate @@ -1911,7 +1911,7 @@ Released March 13, 2019 to backport a CVE fix to the popular 0.9.3 release. - [THRIFT-2793](https://issues.apache.org/jira/browse/THRIFT-2793) - Go compiler produces uncompilable code - [THRIFT-1481](https://issues.apache.org/jira/browse/THRIFT-1481) - Unix domain sockets in C++ do not support the abstract namespace - [THRIFT-1455](https://issues.apache.org/jira/browse/THRIFT-1455) - TBinaryProtocolT::writeString casts from size_t to uint32_t, which is not safe on 64-bit platforms -- [THRIFT-1579](https://issues.apache.org/jira/browse/THRIFT-1579) - PHP Extention - function thrift_protocol_read_binary not working from TBinarySerializer::deserialize +- [THRIFT-1579](https://issues.apache.org/jira/browse/THRIFT-1579) - PHP Extension - function thrift_protocol_read_binary not working from TBinarySerializer::deserialize - [THRIFT-1584](https://issues.apache.org/jira/browse/THRIFT-1584) - Error: could not SetMinThreads in ThreadPool on single-core machines - [THRIFT-1614](https://issues.apache.org/jira/browse/THRIFT-1614) - Thrift build from svn repo sources fails with automake-1.12 - [THRIFT-1047](https://issues.apache.org/jira/browse/THRIFT-1047) - rb_thrift_memory_buffer_write treats arg as string without check, segfaults if you pass non-string @@ -2172,7 +2172,7 @@ Released March 13, 2019 to backport a CVE fix to the popular 0.9.3 release. - [THRIFT-2054](https://issues.apache.org/jira/browse/THRIFT-2054) - TSimpleFileTransport - Java Lib has no straight forward TTransport based file transport - [THRIFT-2040](https://issues.apache.org/jira/browse/THRIFT-2040) - "uninitialized variable" warnings on MSVC/windows - [THRIFT-2034](https://issues.apache.org/jira/browse/THRIFT-2034) - Give developers' C++ code direct access to socket FDs on server side -- [THRIFT-2095](https://issues.apache.org/jira/browse/THRIFT-2095) - Use print function for Python 3 compatiblity +- [THRIFT-2095](https://issues.apache.org/jira/browse/THRIFT-2095) - Use print function for Python 3 compatibility - [THRIFT-1868](https://issues.apache.org/jira/browse/THRIFT-1868) - Make the TPC backlog configurable in the Java servers - [THRIFT-1813](https://issues.apache.org/jira/browse/THRIFT-1813) - Add @Generated annotation to generated classes - [THRIFT-1815](https://issues.apache.org/jira/browse/THRIFT-1815) - Code generators line buffer output @@ -2460,9 +2460,9 @@ Released March 13, 2019 to backport a CVE fix to the popular 0.9.3 release. - [THRIFT-1997](https://issues.apache.org/jira/browse/THRIFT-1997) - Add accept backlog configuration method to TServerSocket - [THRIFT-2003](https://issues.apache.org/jira/browse/THRIFT-2003) - Deprecate senum - [THRIFT-2052](https://issues.apache.org/jira/browse/THRIFT-2052) - Vagrant machine image defaults to only 384MB of RAM -- [THRIFT-1980](https://issues.apache.org/jira/browse/THRIFT-1980) - Modernize Go tooling, fix go client libary. +- [THRIFT-1980](https://issues.apache.org/jira/browse/THRIFT-1980) - Modernize Go tooling, fix go client library. - [THRIFT-1977](https://issues.apache.org/jira/browse/THRIFT-1977) - C# compiler should generate constant files prefixed with thrift file name -- [THRIFT-1985](https://issues.apache.org/jira/browse/THRIFT-1985) - add a Vagrantfile to build and test Apache Thrift fully reproducable +- [THRIFT-1985](https://issues.apache.org/jira/browse/THRIFT-1985) - add a Vagrantfile to build and test Apache Thrift fully reproducible - [THRIFT-1994](https://issues.apache.org/jira/browse/THRIFT-1994) - Deprecate slist - [THRIFT-1993](https://issues.apache.org/jira/browse/THRIFT-1993) - Factory to create instances from known (generated) interface types with Delphi - [THRIFT-2081](https://issues.apache.org/jira/browse/THRIFT-2081) - Specified timeout should be used in TSocket.Open() From ed1711e8611a2acc89b178a1cc0924b215e07a4c Mon Sep 17 00:00:00 2001 From: Jano Svitok Date: Tue, 10 Mar 2020 22:39:18 +0100 Subject: [PATCH 525/756] THRIFT-5087 test/test.py fails with "AssertionError: Python 3.3 or later is required for proper operation." Client: Python Patch: Jano Svitok This closes #2055 THRIFT-5087: Show features log, check log presence THRIFT-5087: Revert/Improve PR1995 (commit f8b004081da) Make the condition work both a) when both python2 and python3 are installed b) when only python3 is installed Check also python 3.8 when searching for 3.x --- build/docker/scripts/cross-test.sh | 7 ++++++- configure.ac | 8 ++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/build/docker/scripts/cross-test.sh b/build/docker/scripts/cross-test.sh index 43581a5f3b5..0b6748ab254 100755 --- a/build/docker/scripts/cross-test.sh +++ b/build/docker/scripts/cross-test.sh @@ -10,7 +10,12 @@ make cross$1 RET=$? if [ $RET -ne 0 ]; then - cat test/log/unexpected_failures.log + if [ -f "test/features/log/unexpected_failures.log" ]; then + cat "test/features/log/unexpected_failures.log" + fi + if [ -f "test/log/unexpected_failures.log" ]; then + cat "test/log/unexpected_failures.log" + fi fi exit $RET diff --git a/configure.ac b/configure.ac index 99c3c9cd78c..35f43ee5f2c 100755 --- a/configure.ac +++ b/configure.ac @@ -306,11 +306,15 @@ AM_CONDITIONAL(WITH_TWISTED_TEST, [test "$have_trial" = "yes"]) have_py3="no" AX_THRIFT_LIB(py3, [Py3], yes) if test "$with_py3" = "yes"; then - if $PYTHON --version 2>&1 | grep -q "Python 3"; then - AC_PATH_PROGS([PYTHON3], [python3 python3.7 python37 python3.6 python36 python3.5 python35 python3.4 python34]) + # if $PYTHON is 2.x then search for python 3. otherwise, $PYTHON is already 3.x + if $PYTHON --version 2>&1 | grep -q "Python 2"; then + AC_PATH_PROGS([PYTHON3], [python3 python3.8 python38 python3.7 python37 python3.6 python36 python3.5 python35 python3.4 python34]) if test -n "$PYTHON3"; then have_py3="yes" fi + elif $PYTHON --version 2>&1 | grep -q "Python 3"; then + have_py3="yes" + PYTHON3=$PYTHON fi fi AM_CONDITIONAL(WITH_PY3, [test "$have_py3" = "yes"]) From b013dc004a019c9a30689b8e49ade34c3b18b7e5 Mon Sep 17 00:00:00 2001 From: Alexander Edge Date: Thu, 27 Feb 2020 11:25:55 +0000 Subject: [PATCH 526/756] THRIFT-5121: Fix inverted logic when testing message type Client: Swift Patch: Alexander Edge This closes #2036 --- lib/swift/Sources/TMultiplexedProcessor.swift | 2 +- .../TMultiplexedProcessorTests.swift | 38 ++++++++++++++----- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/lib/swift/Sources/TMultiplexedProcessor.swift b/lib/swift/Sources/TMultiplexedProcessor.swift index 661d4a7a807..7f4080816b2 100644 --- a/lib/swift/Sources/TMultiplexedProcessor.swift +++ b/lib/swift/Sources/TMultiplexedProcessor.swift @@ -58,7 +58,7 @@ public class MultiplexedProcessor: TProcessor { public func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws { let message = try inProtocol.readMessageBegin() - guard message.1 != .call && message.1 != .oneway else { throw Error.incompatibleMessageType(message.1) } + guard message.1 == .call || message.1 == .oneway else { throw Error.incompatibleMessageType(message.1) } if let separatorIndex = message.0.firstIndex(of: Character(.multiplexSeparator)) { let serviceName = String(message.0.prefix(upTo: separatorIndex)) let messageName = String(message.0.suffix(from: message.0.index(after: separatorIndex))) diff --git a/lib/swift/Tests/ThriftTests/TMultiplexedProcessorTests.swift b/lib/swift/Tests/ThriftTests/TMultiplexedProcessorTests.swift index 190ff134a1c..559ff0b22cd 100644 --- a/lib/swift/Tests/ThriftTests/TMultiplexedProcessorTests.swift +++ b/lib/swift/Tests/ThriftTests/TMultiplexedProcessorTests.swift @@ -54,32 +54,32 @@ class TMultiplexedProcessorTests: XCTestCase { transport.reset() } - func testCallMessageThrowsError() throws { - try proto.writeMessageBegin(name: "message", type: .call, sequenceID: 1) + func testExceptionMessageThrowsError() throws { + try proto.writeMessageBegin(name: "message", type: .exception, sequenceID: 1) try transport.flush() XCTAssertThrowsError(try sut.process(on: proto, outProtocol: proto)) { error in guard case MultiplexedProcessor.Error.incompatibleMessageType(let type) = error else { XCTFail() return } - XCTAssertEqual(type, .call) + XCTAssertEqual(type, .exception) } } - func testOneWayMessageThrowsError() throws { - try proto.writeMessageBegin(name: "message", type: .oneway, sequenceID: 1) + func testReplyMessageThrowsError() throws { + try proto.writeMessageBegin(name: "message", type: .reply, sequenceID: 1) try transport.flush() XCTAssertThrowsError(try sut.process(on: proto, outProtocol: proto)) { error in guard case MultiplexedProcessor.Error.incompatibleMessageType(let type) = error else { XCTFail() return } - XCTAssertEqual(type, .oneway) + XCTAssertEqual(type, .reply) } } func testMissingDefaultProcessorThrowsError() throws { - try proto.writeMessageBegin(name: "message", type: .reply, sequenceID: 1) + try proto.writeMessageBegin(name: "message", type: .call, sequenceID: 1) try transport.flush() XCTAssertThrowsError(try sut.process(on: proto, outProtocol: proto)) { error in guard case MultiplexedProcessor.Error.missingDefaultProcessor = error else { @@ -93,7 +93,7 @@ class TMultiplexedProcessorTests: XCTestCase { let calculator = Calculator() let calculatorProcessor = CalculatorProcessor(service: calculator) sut.register(defaultProcessor: calculatorProcessor) - try proto.writeMessageBegin(name: "message", type: .reply, sequenceID: 1) + try proto.writeMessageBegin(name: "message", type: .call, sequenceID: 1) try transport.flush() try sut.process(on: proto, outProtocol: proto) XCTAssertTrue(calculatorProcessor.processCalled) @@ -103,14 +103,14 @@ class TMultiplexedProcessorTests: XCTestCase { let calculator = Calculator() let calculatorProcessor = CalculatorProcessor(service: calculator) sut.register(processor: calculatorProcessor, for: "Calculator") - try proto.writeMessageBegin(name: "Calculator:message", type: .reply, sequenceID: 1) + try proto.writeMessageBegin(name: "Calculator:message", type: .call, sequenceID: 1) try transport.flush() try sut.process(on: proto, outProtocol: proto) XCTAssertTrue(calculatorProcessor.processCalled) } func testMissingProcessorForMultiplexedMessageThrowsError() throws { - try proto.writeMessageBegin(name: "Calculator:message", type: .reply, sequenceID: 1) + try proto.writeMessageBegin(name: "Calculator:message", type: .call, sequenceID: 1) try transport.flush() XCTAssertThrowsError(try sut.process(on: proto, outProtocol: proto)) { error in guard case MultiplexedProcessor.Error.missingProcessor(let serviceName) = error else { @@ -120,4 +120,22 @@ class TMultiplexedProcessorTests: XCTestCase { XCTAssertEqual(serviceName, "Calculator") } } + + func testCallMessageDoesNotThrowError() throws { + let calculator = Calculator() + let calculatorProcessor = CalculatorProcessor(service: calculator) + sut.register(defaultProcessor: calculatorProcessor) + try proto.writeMessageBegin(name: "message", type: .call, sequenceID: 1) + try transport.flush() + try sut.process(on: proto, outProtocol: proto) + } + + func testOneWayMessageDoesNotThrowError() throws { + let calculator = Calculator() + let calculatorProcessor = CalculatorProcessor(service: calculator) + sut.register(defaultProcessor: calculatorProcessor) + try proto.writeMessageBegin(name: "message", type: .oneway, sequenceID: 1) + try transport.flush() + try sut.process(on: proto, outProtocol: proto) + } } From dad2bf87da9e46382b088544eba56b1829e25d92 Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Fri, 5 Jul 2019 03:42:02 +0200 Subject: [PATCH 527/756] Fix several warnings in c_glib lib and incorrect error message CLient: c_glib Patch: Kevin Wojniak This closes #1830 --- .../src/thrift/c_glib/transport/thrift_server_socket.c | 2 +- lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c index 92c6d7f76eb..438b38d60ed 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_server_socket.c @@ -115,7 +115,7 @@ thrift_server_socket_listen (ThriftServerTransport *transport, GError **error) { g_set_error (error, THRIFT_SERVER_SOCKET_ERROR, THRIFT_SERVER_SOCKET_ERROR_BIND, - "failed to bind to path %s: - %s", + "failed to listen to path %s: - %s", tsocket->path, strerror(errno)); return FALSE; } diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c index a41e9c63af6..216da44164a 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c @@ -270,13 +270,9 @@ thrift_ssl_socket_open (ThriftTransport *transport, GError **error) gboolean thrift_ssl_socket_close (ThriftTransport *transport, GError **error) { - gboolean retval = FALSE; ThriftSSLSocket *ssl_socket = THRIFT_SSL_SOCKET(transport); if(ssl_socket!=NULL && ssl_socket->ssl) { - int rc = SSL_shutdown(ssl_socket->ssl); -/* if (rc < 0) { - int errno_copy = THRIFT_SSL_SOCKET_ERROR_SSL; - }*/ + SSL_shutdown(ssl_socket->ssl); SSL_free(ssl_socket->ssl); ssl_socket->ssl = NULL; ERR_remove_state(0); From 9b992f5af8c7b76a6f71929e7a90eecd6e41a65a Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 13 Mar 2020 02:30:46 +0100 Subject: [PATCH 528/756] Updated known cross failures list Patch: Jens Geyer This closes #2058 --- test/features/known_failures_Linux.json | 1 + test/known_failures_Linux.json | 98 ++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/test/features/known_failures_Linux.json b/test/features/known_failures_Linux.json index 530277babce..06fa959e5e5 100644 --- a/test/features/known_failures_Linux.json +++ b/test/features/known_failures_Linux.json @@ -11,6 +11,7 @@ "netstd-limit_container_length_compact_buffered-ip", "netstd-limit_string_length_binary_buffered-ip", "netstd-limit_string_length_compact_buffered-ip", + "netstd-tls_binary_buffered-ip-ssl", "d-limit_container_length_binary_buffered-ip", "d-limit_container_length_compact_buffered-ip", "d-limit_string_length_binary_buffered-ip", diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index 460da5a900c..8aa297e38b5 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -885,5 +885,101 @@ "rb-cpp_json_buffered-ip-ssl", "rb-cpp_json_framed-domain", "rb-cpp_json_framed-ip", - "rb-cpp_json_framed-ip-ssl" + "rb-cpp_json_framed-ip-ssl", + "rs-netstd_compact_buffered-ip", + "netstd-netstd_compact_buffered-ip", + "netstd-netstd_compact_framed-ip", + "netstd-php_compact_framed-ip", + "netstd-php_compact_buffered-ip", + "netstd-erl_compact_framed-ip", + "netstd-erl_compact_buffered-ip", + "netstd-lua_compact_framed-ip", + "netstd-lua_compact_buffered-ip", + "netstd-rs_compact_framed-ip", + "netstd-rs_compact_buffered-ip", + "netstd-dart_compact_framed-ip", + "netstd-dart_compact_buffered-ip", + "erl-netstd_compact_framed-ip", + "c_glib-netstd_multic-compact_framed-ip", + "c_glib-netstd_compact_framed-ip", + "c_glib-netstd_compact_buffered-ip", + "c_glib-netstd_multic-compact_buffered-ip", + "d-netstd_compact_buffered-ip", + "d-netstd_compact_framed-ip-ssl", + "d-netstd_compact_buffered-ip-ssl", + "d-netstd_compact_framed-ip", + "go-netstd_compact_framed-ip-ssl", + "go-netstd_compact_framed-ip", + "go-netstd_compact_buffered-ip-ssl", + "go-netstd_compact_buffered-ip", + "java-netstd_compact_framed-ip", + "java-netstd_compact_fastframed-framed-ip", + "java-netstd_compact_buffered-ip", + "java-netstd_multic-compact_fastframed-framed-ip", + "java-netstd_multic-compact_framed-ip", + "java-netstd_multic-compact_buffered-ip", + "nodejs-netstd_compact_framed-ip", + "nodejs-netstd_compact_buffered-ip", + "py-netstd_accelc-compact_buffered-ip", + "py-netstd_accelc-compact_framed-ip", + "py-netstd_compact_buffered-ip", + "py-netstd_compact_framed-ip", + "py3-netstd_compact_framed-ip", + "py3-netstd_accelc-compact_framed-ip", + "py3-netstd_compact_buffered-ip", + "py3-netstd_accelc-compact_buffered-ip", + "cpp-netstd_compact_buffered-ip", + "cpp-netstd_compact_framed-ip", + "cpp-netstd_compact_framed-ip-ssl", + "cpp-netstd_compact_buffered-ip-ssl", + "cpp-netstd_multic-compact_framed-ip", + "cpp-netstd_multic-compact_buffered-ip", + "cpp-netstd_multic-compact_framed-ip-ssl", + "cpp-netstd_multic-compact_buffered-ip-ssl", + "rb-netstd_compact_framed-ip", + "rb-netstd_compact_framed-ip-ssl", + "rb-netstd_compact_buffered-ip-ssl", + "rb-netstd_compact_buffered-ip", + "netstd-c_glib_compact_buffered-ip", + "netstd-c_glib_compact_framed-ip", + "netstd-c_glib_compact_framed-ip-ssl", + "netstd-c_glib_compact_buffered-ip-ssl", + "netstd-d_compact_framed-ip", + "netstd-d_compact_framed-ip-ssl", + "netstd-d_compact_buffered-ip", + "netstd-d_compact_buffered-ip-ssl", + "netstd-go_compact_framed-ip", + "netstd-go_compact_framed-ip-ssl", + "netstd-go_compact_buffered-ip-ssl", + "netstd-go_compact_buffered-ip", + "netstd-java_compact_framed-ip-ssl", + "netstd-java_compact_framed-fastframed-ip-ssl", + "netstd-java_compact_framed-ip", + "netstd-java_compact_framed-fastframed-ip", + "netstd-java_compact_buffered-ip-ssl", + "netstd-nodejs_compact_framed-ip", + "netstd-java_compact_buffered-ip", + "netstd-nodejs_compact_framed-ip-ssl", + "netstd-hs_compact_framed-ip", + "netstd-nodejs_compact_buffered-ip-ssl", + "netstd-nodejs_compact_buffered-ip", + "netstd-hs_compact_buffered-ip", + "netstd-py_compact-accelc_buffered-ip-ssl", + "netstd-py_compact-accelc_buffered-ip", + "netstd-py_compact_buffered-ip", + "netstd-py_compact_buffered-ip-ssl", + "netstd-py3_compact-accelc_buffered-ip-ssl", + "netstd-py3_compact-accelc_buffered-ip", + "netstd-py3_compact_buffered-ip", + "netstd-py3_compact_buffered-ip-ssl", + "netstd-cpp_compact_framed-ip-ssl", + "netstd-cpp_compact_framed-ip", + "netstd-cpp_compact_buffered-ip", + "netstd-cpp_compact_buffered-ip-ssl", + "netstd-rb_compact_framed-ip", + "netstd-rb_compact_buffered-ip", + "rs-netstd_compact_framed-ip", + "rs-netstd_multic-compact_framed-ip", + "rs-netstd_multic-compact_buffered-ip", + "rs-netstd_compact_buffered-ip" ] From eccd2e879e73bbc1a948b31139ac1d4c383c0335 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 15 Mar 2020 19:39:42 +0100 Subject: [PATCH 529/756] Updated known cross failures list --- test/known_failures_Linux.json | 167 +++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index 8aa297e38b5..49ec2222846 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -880,6 +880,173 @@ "py3-rs_multiac-multic_framed-ip", "py3-rs_multic_buffered-ip", "py3-rs_multic_framed-ip", + "d-netstd_json_framed-ip", + "d-netstd_json_buffered-ip", + "d-netstd_json_framed-ip-ssl", + "d-netstd_json_buffered-ip-ssl", + "go-netstd_json_buffered-ip-ssl", + "go-netstd_json_framed-ip-ssl", + "go-netstd_json_buffered-ip", + "go-netstd_json_framed-ip", + "rb-netstd_json_framed-ip", + "rb-netstd_json_buffered-ip", + "rb-netstd_json_framed-ip-ssl", + "rb-netstd_json_buffered-ip-ssl", + "netstd-d_json_framed-ip", + "netstd-d_json_framed-ip-ssl", + "netstd-d_json_buffered-ip", + "netstd-d_json_buffered-ip-ssl", + "netstd-go_json_framed-ip-ssl", + "netstd-go_json_framed-ip", + "netstd-go_json_buffered-ip", + "netstd-go_json_buffered-ip-ssl", + "netstd-java_json_framed-fastframed-ip", + "netstd-java_json_framed-fastframed-ip-ssl", + "netstd-java_json_framed-ip", + "netstd-java_json_framed-ip-ssl", + "netstd-java_json_buffered-ip", + "netstd-java_json_buffered-ip-ssl", + "netstd-nodejs_json_framed-ip", + "netstd-nodejs_json_framed-ip-ssl", + "netstd-nodejs_json_buffered-ip", + "netstd-nodejs_json_buffered-ip-ssl", + "netstd-hs_json_framed-ip", + "netstd-py_json_buffered-ip", + "netstd-hs_json_buffered-ip", + "netstd-py_json_buffered-ip-ssl", + "netstd-cpp_json_framed-ip", + "netstd-py3_json_buffered-ip", + "netstd-py3_json_buffered-ip-ssl", + "netstd-cpp_json_framed-ip-ssl", + "netstd-cpp_json_buffered-ip-ssl", + "netstd-cpp_json_buffered-ip", + "netstd-rb_json_framed-ip", + "netstd-rb_json_buffered-ip", + "netstd-lua_json_framed-ip", + "netstd-lua_json_buffered-ip", + "netstd-dart_json_framed-ip", + "netstd-dart_json_buffered-ip", + "c_glib-netstd_multi-binary_framed-ip", + "c_glib-netstd_binary_buffered-ip", + "c_glib-netstd_binary_framed-ip", + "c_glib-netstd_multi-binary_buffered-ip", + "cl-netstd_binary_buffered-ip", + "cl-netstd_binary_framed-ip", + "d-netstd_binary_framed-ip", + "d-netstd_binary_framed-ip-ssl", + "d-netstd_binary_buffered-ip", + "d-netstd_binary_buffered-ip-ssl", + "go-netstd_binary_framed-ip-ssl", + "go-netstd_binary_buffered-ip", + "go-netstd_binary_buffered-ip-ssl", + "go-netstd_binary_framed-ip", + "java-netstd_binary_framed-ip", + "java-netstd_binary_fastframed-framed-ip", + "java-netstd_binary_buffered-ip", + "java-netstd_multi-binary_framed-ip", + "java-netstd_multi-binary_buffered-ip", + "java-netstd_multi-binary_fastframed-framed-ip", + "nodejs-netstd_binary_framed-ip", + "nodejs-netstd_binary_buffered-ip", + "py-netstd_binary_framed-ip", + "py-netstd_binary_buffered-ip", + "py-netstd_accel-binary_framed-ip", + "py-netstd_accel-binary_buffered-ip", + "py-netstd_accel-binary_buffered-ip-ssl", + "py3-netstd_binary_framed-ip", + "py3-netstd_binary_buffered-ip", + "py3-netstd_accel-binary_framed-ip", + "py3-netstd_accel-binary_buffered-ip", + "py3-netstd_accel-binary_buffered-ip-ssl", + "cpp-netstd_binary_framed-ip-ssl", + "cpp-netstd_binary_framed-ip", + "cpp-netstd_binary_buffered-ip", + "cpp-netstd_binary_buffered-ip-ssl", + "cpp-netstd_multi-binary_buffered-ip", + "cpp-netstd_multi-binary_framed-ip", + "cpp-netstd_multi-binary_framed-ip-ssl", + "cpp-netstd_multi-binary_buffered-ip-ssl", + "rb-netstd_accel-binary_framed-ip", + "rb-netstd_accel-binary_buffered-ip-ssl", + "rb-netstd_accel-binary_buffered-ip", + "rb-netstd_accel-binary_framed-ip-ssl", + "rb-netstd_binary_buffered-ip-ssl", + "rb-netstd_binary_framed-ip", + "rb-netstd_binary_framed-ip-ssl", + "rb-netstd_binary_buffered-ip", + "netstd-c_glib_binary_buffered-ip", + "netstd-c_glib_binary_framed-ip", + "netstd-c_glib_binary_framed-ip-ssl", + "netstd-c_glib_binary_buffered-ip-ssl", + "netstd-cl_binary_buffered-ip", + "netstd-cl_binary_framed-ip", + "netstd-d_binary_framed-ip", + "netstd-d_binary_framed-ip-ssl", + "netstd-d_binary_buffered-ip", + "netstd-go_binary_framed-ip", + "netstd-d_binary_buffered-ip-ssl", + "netstd-go_binary_framed-ip-ssl", + "netstd-go_binary_buffered-ip", + "netstd-go_binary_buffered-ip-ssl", + "netstd-java_binary_framed-fastframed-ip-ssl", + "netstd-java_binary_framed-fastframed-ip", + "netstd-java_binary_framed-ip", + "netstd-java_binary_framed-ip-ssl", + "netstd-java_binary_buffered-ip-ssl", + "netstd-java_binary_buffered-ip", + "netstd-nodejs_binary_framed-ip", + "netstd-nodejs_binary_framed-ip-ssl", + "netstd-nodejs_binary_buffered-ip", + "netstd-nodejs_binary_buffered-ip-ssl", + "netstd-hs_binary_buffered-ip", + "netstd-hs_binary_framed-ip", + "netstd-py_binary_buffered-ip", + "netstd-py_binary_buffered-ip-ssl", + "netstd-py_binary-accel_buffered-ip-ssl", + "netstd-py_binary-accel_buffered-ip", + "netstd-py3_binary_buffered-ip", + "netstd-py3_binary_buffered-ip-ssl", + "netstd-py3_binary-accel_buffered-ip", + "netstd-py3_binary-accel_buffered-ip-ssl", + "netstd-cpp_binary_framed-ip", + "netstd-cpp_binary_framed-ip-ssl", + "netstd-cpp_binary_buffered-ip", + "netstd-cpp_binary_buffered-ip-ssl", + "netstd-rb_binary-accel_framed-ip", + "netstd-rb_binary-accel_buffered-ip", + "netstd-rb_binary_buffered-ip", + "netstd-rb_binary_framed-ip", + "netstd-perl_binary_framed-ip", + "netstd-netstd_binary_framed-ip", + "netstd-netstd_binary_buffered-ip", + "netstd-perl_binary_framed-ip-ssl", + "netstd-php_binary_framed-ip", + "netstd-perl_binary_buffered-ip-ssl", + "netstd-perl_binary_buffered-ip", + "netstd-php_binary_buffered-ip", + "netstd-erl_binary_framed-ip", + "netstd-erl_binary_buffered-ip", + "netstd-lua_binary_framed-ip", + "netstd-lua_binary_buffered-ip", + "netstd-rs_binary_framed-ip", + "netstd-rs_binary_buffered-ip", + "netstd-dart_binary_buffered-ip", + "netstd-dart_binary_framed-ip", + "netstd-nodets_binary_buffered-ip", + "perl-netstd_multi-binary_framed-ip", + "perl-netstd_multi-binary_buffered-ip", + "perl-netstd_multi-binary_buffered-ip-ssl", + "perl-netstd_multi-binary_framed-ip-ssl", + "perl-netstd_binary_buffered-ip", + "perl-netstd_binary_framed-ip-ssl", + "perl-netstd_binary_framed-ip", + "perl-netstd_binary_buffered-ip-ssl", + "erl-netstd_binary_framed-ip", + "rs-netstd_binary_buffered-ip", + "rs-netstd_binary_framed-ip", + "rs-netstd_multi-binary_framed-ip", + "rs-netstd_multi-binary_buffered-ip", + "nodets-netstd_binary_buffered-ip", "rb-cpp_json_buffered-domain", "rb-cpp_json_buffered-ip", "rb-cpp_json_buffered-ip-ssl", From 4b66a9d8812cf2c19f15382c56ec8e1327b6f2a1 Mon Sep 17 00:00:00 2001 From: Mikel Blanchard Date: Thu, 5 Mar 2020 00:46:21 +0100 Subject: [PATCH 530/756] THRIFT-5133: Use ArrayPool when reading and writing strings to improve performance Client: netstd Patch: Mikel Blanchard This closes #2057 --- .../CompactProtocolBenchmarks.cs | 75 +++++++++++++++++++ .../Benchmarks/Thrift.Benchmarks/Program.cs | 29 +++++++ .../Thrift.Benchmarks.csproj | 35 +++++++++ lib/netstd/Directory.Build.props | 7 ++ lib/netstd/Thrift.sln | 21 +++++- .../Thrift/Protocol/TCompactProtocol.cs | 35 ++++++--- lib/netstd/Thrift/Thrift.csproj | 2 +- .../Thrift/Transport/Client/THttpTransport.cs | 4 + .../Transport/Client/TNamedPipeTransport.cs | 4 + .../Transport/Client/TStreamTransport.cs | 6 +- .../Server/TNamedPipeServerTransport.cs | 4 + 11 files changed, 209 insertions(+), 13 deletions(-) create mode 100644 lib/netstd/Benchmarks/Thrift.Benchmarks/CompactProtocolBenchmarks.cs create mode 100644 lib/netstd/Benchmarks/Thrift.Benchmarks/Program.cs create mode 100644 lib/netstd/Benchmarks/Thrift.Benchmarks/Thrift.Benchmarks.csproj create mode 100644 lib/netstd/Directory.Build.props diff --git a/lib/netstd/Benchmarks/Thrift.Benchmarks/CompactProtocolBenchmarks.cs b/lib/netstd/Benchmarks/Thrift.Benchmarks/CompactProtocolBenchmarks.cs new file mode 100644 index 00000000000..cb6b07f9474 --- /dev/null +++ b/lib/netstd/Benchmarks/Thrift.Benchmarks/CompactProtocolBenchmarks.cs @@ -0,0 +1,75 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System.IO; +using System.Threading.Tasks; + +using BenchmarkDotNet.Attributes; + +using Thrift.Protocol; +using Thrift.Transport.Client; + +namespace Thrift.Benchmarks +{ + [MemoryDiagnoser] + public class CompactProtocolBenchmarks + { + private MemoryStream _Stream; + private TCompactProtocol _Protocol; + + [Params(10000)] + public int NumberOfOperationsPerIteration { get; set; } + + [GlobalSetup] + public void GlobalSetup() + { + _Stream = new MemoryStream(); + var transport = new TStreamTransport(_Stream, _Stream, null); + _Protocol = new TCompactProtocol(transport); + } + + [GlobalCleanup] + public void GlobalCleanup() + { + _Protocol.Dispose(); + } + + [Benchmark] + public async Task WriteString() + { + for (int i = 0; i < NumberOfOperationsPerIteration; i++) + { + await _Protocol.WriteStringAsync("Thrift String Benchmark"); + + _Stream.Seek(0, SeekOrigin.Begin); + } + } + + [Benchmark] + public async Task ReadString() + { + await _Protocol.WriteStringAsync("Thrift String Benchmark"); + + for (int i = 0; i < NumberOfOperationsPerIteration; i++) + { + _Stream.Seek(0, SeekOrigin.Begin); + + await _Protocol.ReadStringAsync(); + } + } + } +} diff --git a/lib/netstd/Benchmarks/Thrift.Benchmarks/Program.cs b/lib/netstd/Benchmarks/Thrift.Benchmarks/Program.cs new file mode 100644 index 00000000000..923d73ef5fb --- /dev/null +++ b/lib/netstd/Benchmarks/Thrift.Benchmarks/Program.cs @@ -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. + +using BenchmarkDotNet.Running; + +namespace Thrift.Benchmarks +{ + internal static class Program + { + public static void Main(string[] args) + { + BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args); + } + } +} diff --git a/lib/netstd/Benchmarks/Thrift.Benchmarks/Thrift.Benchmarks.csproj b/lib/netstd/Benchmarks/Thrift.Benchmarks/Thrift.Benchmarks.csproj new file mode 100644 index 00000000000..35138d8631f --- /dev/null +++ b/lib/netstd/Benchmarks/Thrift.Benchmarks/Thrift.Benchmarks.csproj @@ -0,0 +1,35 @@ + + + + + Exe + netcoreapp3.1;net48 + false + + + + + + + + + + + diff --git a/lib/netstd/Directory.Build.props b/lib/netstd/Directory.Build.props new file mode 100644 index 00000000000..3bd9541a4da --- /dev/null +++ b/lib/netstd/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + + + diff --git a/lib/netstd/Thrift.sln b/lib/netstd/Thrift.sln index 2952eb0d885..58c76ced98e 100644 --- a/lib/netstd/Thrift.sln +++ b/lib/netstd/Thrift.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.12 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29905.134 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{ED5A45B0-07D1-4507-96B7-83FBD3D031CA}" EndProject @@ -12,6 +12,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.Tests", "Tests\Thrif EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Thrift.PublicInterfaces.Compile.Tests", "Tests\Thrift.PublicInterfaces.Compile.Tests\Thrift.PublicInterfaces.Compile.Tests.csproj", "{A6AE021D-61CB-4D84-A103-0B663C62AE2C}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmarks", "Benchmarks", "{BF7B896B-8BB6-447C-84F8-26871882A14A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Thrift.Benchmarks", "Benchmarks\Thrift.Benchmarks\Thrift.Benchmarks.csproj", "{D0559DFF-6632-446C-9EFC-C750DA20B1D9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -70,6 +74,18 @@ Global {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|x64.Build.0 = Release|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|x86.ActiveCfg = Release|Any CPU {A6AE021D-61CB-4D84-A103-0B663C62AE2C}.Release|x86.Build.0 = Release|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|x64.ActiveCfg = Debug|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|x64.Build.0 = Debug|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|x86.ActiveCfg = Debug|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Debug|x86.Build.0 = Debug|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|Any CPU.Build.0 = Release|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|x64.ActiveCfg = Release|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|x64.Build.0 = Release|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|x86.ActiveCfg = Release|Any CPU + {D0559DFF-6632-446C-9EFC-C750DA20B1D9}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -78,6 +94,7 @@ Global {837F4084-AAD7-45F5-BC96-10E05A669DB4} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA} {0790D388-1A3C-4423-8CF2-C97074A8B68B} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA} {A6AE021D-61CB-4D84-A103-0B663C62AE2C} = {ED5A45B0-07D1-4507-96B7-83FBD3D031CA} + {D0559DFF-6632-446C-9EFC-C750DA20B1D9} = {BF7B896B-8BB6-447C-84F8-26871882A14A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {FD20BC4A-0109-41D8-8C0C-893E784D7EF9} diff --git a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs index a8a46f2a4fc..bb531f42eda 100644 --- a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs @@ -16,6 +16,7 @@ // under the License. using System; +using System.Buffers; using System.Buffers.Binary; using System.Collections.Generic; using System.Diagnostics; @@ -66,7 +67,7 @@ public class TCompactProtocol : TProtocol // minimize memory allocations by means of an preallocated bytes buffer // The value of 128 is arbitrarily chosen, the required minimum size must be sizeof(long) - private byte[] PreAllocatedBuffer = new byte[128]; + private readonly byte[] PreAllocatedBuffer = new byte[128]; private struct VarInt { @@ -411,11 +412,19 @@ public override async Task WriteStringAsync(string str, CancellationToken cancel return; } - var bytes = Encoding.UTF8.GetBytes(str); + var buf = ArrayPool.Shared.Rent(Encoding.UTF8.GetByteCount(str)); + try + { + var numberOfBytes = Encoding.UTF8.GetBytes(str, 0, str.Length, buf, 0); - Int32ToVarInt((uint) bytes.Length, ref PreAllocatedVarInt); - await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); - await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); + Int32ToVarInt((uint)numberOfBytes, ref PreAllocatedVarInt); + await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); + await Trans.WriteAsync(buf, 0, numberOfBytes, cancellationToken); + } + finally + { + ArrayPool.Shared.Return(buf); + } } public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) @@ -706,9 +715,17 @@ public override async ValueTask ReadStringAsync(CancellationToken cancel } Transport.CheckReadBytesAvailable(length); - var buf = new byte[length]; - await Trans.ReadAllAsync(buf, 0, length, cancellationToken); - return Encoding.UTF8.GetString(buf, 0, length); + + var buf = ArrayPool.Shared.Rent(length); + try + { + await Trans.ReadAllAsync(buf, 0, length, cancellationToken); + return Encoding.UTF8.GetString(buf, 0, length); + } + finally + { + ArrayPool.Shared.Return(buf); + } } public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) @@ -717,7 +734,7 @@ public override async ValueTask ReadBinaryAsync(CancellationToken cancel var length = (int) await ReadVarInt32Async(cancellationToken); if (length == 0) { - return new byte[0]; + return Array.Empty(); } // read data diff --git a/lib/netstd/Thrift/Thrift.csproj b/lib/netstd/Thrift/Thrift.csproj index e40db00d2a0..b63a12a6608 100644 --- a/lib/netstd/Thrift/Thrift.csproj +++ b/lib/netstd/Thrift/Thrift.csproj @@ -19,7 +19,7 @@ --> - netstandard2.0 + netstandard2.1;netstandard2.0 Thrift Thrift true diff --git a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs index bbd94fa98e9..0790cc8822e 100644 --- a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs @@ -109,7 +109,11 @@ public override async ValueTask ReadAsync(byte[] buffer, int offset, int le try { +#if NETSTANDARD2_1 + var ret = await _inputStream.ReadAsync(new Memory(buffer, offset, length), cancellationToken); +#else var ret = await _inputStream.ReadAsync(buffer, offset, length, cancellationToken); +#endif if (ret == -1) { throw new TTransportException(TTransportException.ExceptionType.EndOfFile, "No more data available"); diff --git a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs index f7f10b71ad6..8dab6a063c1 100644 --- a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs @@ -72,7 +72,11 @@ public override async ValueTask ReadAsync(byte[] buffer, int offset, int le } CheckReadBytesAvailable(length); +#if NETSTANDARD2_1 + var numRead = await PipeStream.ReadAsync(new Memory(buffer, offset, length), cancellationToken); +#else var numRead = await PipeStream.ReadAsync(buffer, offset, length, cancellationToken); +#endif CountConsumedMessageBytes(numRead); return numRead; } diff --git a/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs b/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs index e04b3b3336e..ccadad025e3 100644 --- a/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs @@ -14,7 +14,7 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. - +using System; using System.IO; using System.Threading; using System.Threading.Tasks; @@ -82,7 +82,11 @@ public override async ValueTask ReadAsync(byte[] buffer, int offset, int le "Cannot read from null inputstream"); } +#if NETSTANDARD2_1 + return await InputStream.ReadAsync(new Memory(buffer, offset, length), cancellationToken); +#else return await InputStream.ReadAsync(buffer, offset, length, cancellationToken); +#endif } public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) diff --git a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs index a8b64c495f0..4b82cbd22d5 100644 --- a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs @@ -277,7 +277,11 @@ public override async ValueTask ReadAsync(byte[] buffer, int offset, int le } CheckReadBytesAvailable(length); +#if NETSTANDARD2_1 + var numBytes = await PipeStream.ReadAsync(new Memory(buffer, offset, length), cancellationToken); +#else var numBytes = await PipeStream.ReadAsync(buffer, offset, length, cancellationToken); +#endif CountConsumedMessageBytes(numBytes); return numBytes; } From 655f52590d23443a432a3326cbb64ca93cb4b90a Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Sat, 21 Mar 2020 10:52:03 +0800 Subject: [PATCH 531/756] Fix some compile warnings Client: c_glib Patch: zeshuai007 <51382517@qq.com> This closes #2063 --- .../c_glib/processor/thrift_multiplexed_processor.c | 4 ++-- .../src/thrift/c_glib/transport/thrift_ssl_socket.c | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.c b/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.c index 68a0f4d46cb..12a24a7f299 100644 --- a/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.c +++ b/lib/c_glib/src/thrift/c_glib/processor/thrift_multiplexed_processor.c @@ -41,6 +41,8 @@ static GParamSpec *thrift_multiplexed_processor_obj_properties[PROP_THRIFT_MULTI static gboolean thrift_multiplexed_processor_register_processor_impl(ThriftProcessor *processor, const gchar * multiplexed_processor_name, ThriftProcessor * multiplexed_processor , GError **error) { + THRIFT_UNUSED_VAR (error); + ThriftMultiplexedProcessor *self = THRIFT_MULTIPLEXED_PROCESSOR(processor); g_hash_table_replace(self->multiplexed_services, g_strdup(multiplexed_processor_name), @@ -336,11 +338,9 @@ thrift_multiplexed_processor_init (ThriftMultiplexedProcessor *self) self->default_processor_name = NULL; } - gboolean thrift_multiplexed_processor_register_processor(ThriftProcessor *processor, const gchar * multiplexed_processor_name, ThriftProcessor * multiplexed_processor , GError **error) { return THRIFT_MULTIPLEXED_PROCESSOR_GET_CLASS(processor)->register_processor(processor, multiplexed_processor_name, multiplexed_processor, error); } - diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c index 216da44164a..dcb2f868171 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_ssl_socket.c @@ -80,7 +80,11 @@ static unsigned long thrift_ssl_socket_static_id_function(void) #endif } -static void thrift_ssl_socket_static_locking_callback(int mode, int n, const char* unk, int id) { +static void thrift_ssl_socket_static_locking_callback(int mode, int n, const char* unk, int id) +{ + THRIFT_UNUSED_VAR (unk); + THRIFT_UNUSED_VAR (id); + if (mode & CRYPTO_LOCK) MUTEX_LOCK(thrift_ssl_socket_global_mutex_buf[n]); else @@ -175,15 +179,15 @@ void thrift_ssl_socket_get_ssl_error(ThriftSSLSocket *socket, const guchar *erro break; case SSL_ERROR_SYSCALL: buffer_size-=snprintf(buffer, buffer_size, "%s: ", error_msg); - buffer_size-=snprintf(buffer+(1024-buffer_size), buffer_size, "%lX -> %s", errno, strerror(errno)); + buffer_size-=snprintf(buffer+(1024-buffer_size), buffer_size, "%X -> %s", errno, strerror(errno)); break; case SSL_ERROR_WANT_READ: buffer_size-=snprintf(buffer, buffer_size, "%s: ", error_msg); - buffer_size-=snprintf(buffer+(1024-buffer_size), buffer_size, "%lX -> %s", ssl_error_type, "Error while reading from underlaying layer"); + buffer_size-=snprintf(buffer+(1024-buffer_size), buffer_size, "%X -> %s", ssl_error_type, "Error while reading from underlaying layer"); break; case SSL_ERROR_WANT_WRITE: buffer_size-=snprintf(buffer, buffer_size, "%s: ", error_msg); - buffer_size-=snprintf(buffer+(1024-buffer_size), buffer_size, "%lX -> %s", ssl_error_type, "Error while writting to underlaying layer"); + buffer_size-=snprintf(buffer+(1024-buffer_size), buffer_size, "%X -> %s", ssl_error_type, "Error while writting to underlaying layer"); break; } From 9f3198e1a84a1c20c5c9ce0497b4b399584694c0 Mon Sep 17 00:00:00 2001 From: Jano Svitok Date: Thu, 5 Mar 2020 18:42:49 +0100 Subject: [PATCH 532/756] THRIFT-5074: Crosstest client/server command line [skip ci] Client: Documentation Patch: Jano Svitok --- test/README.md | 64 +++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/test/README.md b/test/README.md index 10955f1c819..d5d1b9250bb 100755 --- a/test/README.md +++ b/test/README.md @@ -123,43 +123,43 @@ line interface: $ ./TestServer -h Allowed options: - -h [ --help ] produce help message - --port arg (=9090) Port number to listen - --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift) - --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) - --server-type arg (=simple) type of server, "simple", "thread-pool", - "threaded", or "nonblocking" - --transport arg (=buffered) transport: buffered, framed, http, anonpipe, zlib - --protocol arg (=binary) protocol: binary, compact, header, json - --multiplex Add TMultiplexedProtocol service name "ThriftTest" - --abstract-namespace Create the domain socket in the Abstract Namespace - (no connection with filesystem pathnames) - --ssl Encrypted Transport using SSL - --zlib Wrapped Transport using Zlib - --processor-events processor-events - -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for - thread-pool server type + -h | --help produce help message + --port=arg (9090) Port number to listen + --domain-socket=arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift) + --named-pipe=arg Windows Named Pipe (e.g. MyThriftPipe) + --server-type=arg (simple) type of server, "simple", "thread-pool", + "threaded", or "nonblocking" + --transport=arg (buffered) transport: buffered, framed, http, anonpipe, zlib + --protocol=arg (binary) protocol: binary, compact, header, json + --multiplex Add TMultiplexedProtocol service name "ThriftTest" + --abstract-namespace Create the domain socket in the Abstract Namespace + (no connection with filesystem pathnames) + --ssl Encrypted Transport using SSL + --zlib Wrapped Transport using Zlib + --processor-events processor-events + -n=arg | --workers=arg (=4) Number of thread pools workers. Only valid for + thread-pool server type **Client command line interface:** $ ./TestClient -h Allowed options: - -h [ --help ] produce help message - --host arg (=localhost) Host to connect - --port arg (=9090) Port number to connect - --domain-socket arg Domain Socket (e.g. /tmp/ThriftTest.thrift), - instead of host and port - --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) - --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles) - --abstract-namespace Create the domain socket in the Abstract Namespace - (no connection with filesystem pathnames) - --transport arg (=buffered) Transport: buffered, framed, http, evhttp, zlib - --protocol arg (=binary) Protocol: binary, compact, header, json - --multiplex Add TMultiplexedProtocol service name "ThriftTest" - --ssl Encrypted Transport using SSL - --zlib Wrap Transport with Zlib - -n [ --testloops ] arg (=1) Number of Tests - -t [ --threads ] arg (=1) Number of Test threads + -h | --help produce help message + --host=arg (localhost) Host to connect + --port=arg (9090) Port number to connect + --domain-socket=arg Domain Socket (e.g. /tmp/ThriftTest.thrift), + instead of host and port + --named-pipe=arg Windows Named Pipe (e.g. MyThriftPipe) + --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles) + --abstract-namespace Create the domain socket in the Abstract Namespace + (no connection with filesystem pathnames) + --transport=arg (buffered) Transport: buffered, framed, http, evhttp, zlib + --protocol=arg (binary) Protocol: binary, compact, header, json + --multiplex Add TMultiplexedProtocol service name "ThriftTest" + --ssl Encrypted Transport using SSL + --zlib Wrap Transport with Zlib + -n=arg | --testloops=arg (1) Number of Tests + -t=arg | --threads=arg (1) Number of Test threads If you have executed the **make check** or **make cross** then you will be able to browse [gen-html/ThriftTest.html](gen-html/ThriftTest.html) with the test documentation. From 24ab31fc5738532b082c7b0638bfcd2a7a26d7c5 Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Sat, 14 Mar 2020 16:04:21 +0800 Subject: [PATCH 533/756] THRIFT-5067 Invalid generated Cpp code from valid Thrift IDL with dots in file names for nested namespaces Client: cpp Patch: zeshuai007 <51382517@qq.com> This closes #2060 --- .../src/thrift/generate/t_cpp_generator.cc | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc index 896c43fcfa1..372014dad53 100644 --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc @@ -298,6 +298,13 @@ class t_cpp_generator : public t_oop_generator { */ std::string get_include_prefix(const t_program& program) const; + /** + * Returns the legal program name to use for a file generated by program, if the + * program name contains dots then replace it with underscores, otherwise return the + * original program name. + */ + std::string get_legal_program_name(std::string program_name); + /** * True if we should generate pure enums for Thrift enums, instead of wrapper classes. */ @@ -386,6 +393,8 @@ void t_cpp_generator::init_generator() { // Make output directory MKDIR(get_out_dir().c_str()); + program_name_ = get_legal_program_name(program_name_); + // Make output file string f_types_name = get_out_dir() + program_name_ + "_types.h"; f_types_.open(f_types_name); @@ -4550,6 +4559,23 @@ string t_cpp_generator::get_include_prefix(const t_program& program) const { return ""; } +string t_cpp_generator::get_legal_program_name(std::string program_name) +{ + std::size_t found = 0; + + while(true) { + found = program_name.find('.'); + + if(found != string::npos) { + program_name = program_name.replace(found, 1, "_"); + } else { + break; + } + } + + return program_name; +} + THRIFT_REGISTER_GENERATOR( cpp, "C++", From 4a33b188f44ce097e25ca56ebd48026b41effd6a Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 22 Mar 2020 13:46:34 +0100 Subject: [PATCH 534/756] THRIFT-5145 Streamline --pipe and --named-pipe options in the code base Client: Test suite Patch: Jens Geyer This closes #2065 --- lib/delphi/test/TestClient.pas | 6 +++--- lib/delphi/test/TestServer.pas | 8 ++++---- test/README.md | 4 ++-- test/haxe/src/Arguments.hx | 6 +++--- test/rs/src/bin/test_client.rs | 2 +- test/rs/src/bin/test_server.rs | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas index 1579bd5f647..ff599828067 100644 --- a/lib/delphi/test/TestClient.pas +++ b/lib/delphi/test/TestClient.pas @@ -196,7 +196,7 @@ class procedure TTestClient.PrintCmdLineHelp; + ' --port arg (=9090) Port number to connect'#10 + ' --domain-socket arg Domain Socket (e.g. /tmp/ThriftTest.thrift),'#10 + ' instead of host and port'#10 - + ' --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe)'#10 + + ' --pipe arg Windows Named Pipe (e.g. MyThriftPipe)'#10 + ' --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles)'#10 + ' --transport arg (=sockets) Transport: buffered, framed, http, winhttp'#10 + ' --protocol arg (=binary) Protocol: binary, compact, json'#10 @@ -268,8 +268,8 @@ class function TTestClient.Execute(const args: array of string) : Byte; // --domain-socket arg Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port raise Exception.Create('domain-socket not supported'); end - else if s = '--named-pipe' then begin - // --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) + else if s = '--pipe' then begin + // --pipe arg Windows Named Pipe (e.g. MyThriftPipe) setup.endpoint := trns_NamedPipes; setup.sPipeName := args[i]; Inc( i); diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas index bbc798beda1..f93c846c2ae 100644 --- a/lib/delphi/test/TestServer.pas +++ b/lib/delphi/test/TestServer.pas @@ -388,7 +388,7 @@ class procedure TTestServer.PrintCmdLineHelp; + ' -h [ --help ] produce help message'#10 + ' --port arg (=9090) Port number to listen'#10 + ' --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)'#10 - + ' --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe)'#10 + + ' --pipe arg Windows Named Pipe (e.g. MyThriftPipe)'#10 + ' --server-type arg (=simple) type of server, "simple", "thread-pool",'#10 + ' "threaded", or "nonblocking"'#10 + ' --transport arg (=socket) transport: buffered, framed, http, anonpipe'#10 @@ -503,10 +503,10 @@ class procedure TTestServer.Execute( const args: array of string); // --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift) raise Exception.Create('domain-socket not supported'); end - else if (s = '--named-pipe') then begin - // --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) + else if (s = '--pipe') then begin + // --pipe arg Windows Named Pipe (e.g. MyThriftPipe) endpoint := trns_NamedPipes; - sPipeName := args[i]; // -pipe + sPipeName := args[i]; // --pipe Inc( i ); end else if (s = '--server-type') then begin diff --git a/test/README.md b/test/README.md index d5d1b9250bb..5f6be15fd16 100755 --- a/test/README.md +++ b/test/README.md @@ -126,7 +126,7 @@ line interface: -h | --help produce help message --port=arg (9090) Port number to listen --domain-socket=arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift) - --named-pipe=arg Windows Named Pipe (e.g. MyThriftPipe) + --pipe=arg Windows Named Pipe (e.g. MyThriftPipe) --server-type=arg (simple) type of server, "simple", "thread-pool", "threaded", or "nonblocking" --transport=arg (buffered) transport: buffered, framed, http, anonpipe, zlib @@ -149,7 +149,7 @@ line interface: --port=arg (9090) Port number to connect --domain-socket=arg Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port - --named-pipe=arg Windows Named Pipe (e.g. MyThriftPipe) + --pipe=arg Windows Named Pipe (e.g. MyThriftPipe) --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles) --abstract-namespace Create the domain socket in the Abstract Namespace (no connection with filesystem pathnames) diff --git a/test/haxe/src/Arguments.hx b/test/haxe/src/Arguments.hx index cc107498734..56e5253562c 100644 --- a/test/haxe/src/Arguments.hx +++ b/test/haxe/src/Arguments.hx @@ -103,7 +103,7 @@ class Arguments +" --port arg (=9090) Port number to listen / connect to\n" /* not supported yet +" --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)\n" - +" --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe)\n" + +" --pipe arg Windows Named Pipe (e.g. MyThriftPipe)\n" */ +" --protocol arg (=binary) protocol: binary, compact, json\n" /* not supported yet @@ -187,8 +187,8 @@ class Arguments // --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift) throw "domain sockets not supported yet"; } - else if (arg == "--named-pipe") { - // --named-pipe arg Windows Named Pipe (e.g. MyThriftPipe) + else if (arg == "--pipe") { + // --pipe arg Windows Named Pipe (e.g. MyThriftPipe) throw "named pipes not supported yet"; } else if (arg == "--protocol") { diff --git a/test/rs/src/bin/test_client.rs b/test/rs/src/bin/test_client.rs index 8016ca67469..5983c7db5e7 100644 --- a/test/rs/src/bin/test_client.rs +++ b/test/rs/src/bin/test_client.rs @@ -54,7 +54,7 @@ fn main() { fn run() -> thrift::Result<()> { // unsupported options: // --domain-socket - // --named-pipe + // --pipe // --anon-pipes // --ssl // --threads diff --git a/test/rs/src/bin/test_server.rs b/test/rs/src/bin/test_server.rs index 81c1ec7046d..d87ef7527d7 100644 --- a/test/rs/src/bin/test_server.rs +++ b/test/rs/src/bin/test_server.rs @@ -57,7 +57,7 @@ fn run() -> thrift::Result<()> { // unsupported options: // --domain-socket - // --named-pipe + // --pipe // --ssl let matches = clap_app!(rust_test_client => (version: "1.0") From aeda987cc42ef7dcf57682b7ee168e7dfdbd5f57 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 22 Mar 2020 15:01:28 +0100 Subject: [PATCH 535/756] THRIFT-5146 Align Delphi to the test suite arguments rules (its "--switch=value", not "--switch value") Client: Delphi Patch: Jens Geyer --- lib/delphi/test/TestClient.pas | 126 ++++++++++++++++---------------- lib/delphi/test/TestServer.pas | 130 ++++++++++++++++----------------- 2 files changed, 125 insertions(+), 131 deletions(-) diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas index ff599828067..6c962ab17ab 100644 --- a/lib/delphi/test/TestClient.pas +++ b/lib/delphi/test/TestClient.pas @@ -150,7 +150,7 @@ TTestClient = class class procedure PrintCmdLineHelp; class procedure InvalidArgs; public - class function Execute( const args: array of string) : Byte; + class function Execute( const arguments: array of string) : Byte; end; @@ -191,19 +191,17 @@ class procedure TTestClient.PrintCmdLineHelp; const HELPTEXT = ' [options]'#10 + #10 + 'Allowed options:'#10 - + ' -h [ --help ] produce help message'#10 - + ' --host arg (=localhost) Host to connect'#10 - + ' --port arg (=9090) Port number to connect'#10 - + ' --domain-socket arg Domain Socket (e.g. /tmp/ThriftTest.thrift),'#10 - + ' instead of host and port'#10 - + ' --pipe arg Windows Named Pipe (e.g. MyThriftPipe)'#10 - + ' --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles)'#10 - + ' --transport arg (=sockets) Transport: buffered, framed, http, winhttp'#10 - + ' --protocol arg (=binary) Protocol: binary, compact, json'#10 - + ' --ssl Encrypted Transport using SSL'#10 - + ' -n [ --testloops ] arg (=1) Number of Tests'#10 - + ' -t [ --threads ] arg (=1) Number of Test threads'#10 - + ' --performance Run the built-in performance test (no other arguments)'#10 + + ' -h | --help Produces this help message'#10 + + ' --host=arg (localhost) Host to connect'#10 + + ' --port=arg (9090) Port number to connect'#10 + + ' --pipe=arg Windows Named Pipe (e.g. MyThriftPipe)'#10 + + ' --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles)'#10 + + ' --transport=arg (sockets) Transport: buffered, framed, http, winhttp'#10 + + ' --protocol=arg (binary) Protocol: binary, compact, json'#10 + + ' --ssl Encrypted Transport using SSL'#10 + + ' -n=num | --testloops=num (1) Number of Tests'#10 + + ' -t=num | --threads=num (1) Number of Test threads'#10 + + ' --performance Run the built-in performance test (no other arguments)'#10 ; begin Writeln( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + HELPTEXT); @@ -216,11 +214,22 @@ class procedure TTestClient.InvalidArgs; Abort; end; -class function TTestClient.Execute(const args: array of string) : Byte; +class function TTestClient.Execute(const arguments: array of string) : Byte; + + function IsSwitch( const aArgument, aSwitch : string; out sValue : string) : Boolean; + begin + sValue := ''; + result := (Copy( aArgument, 1, Length(aSwitch)) = aSwitch); + if result then begin + if (Copy( aArgument, 1, Length(aSwitch)+1) = (aSwitch+'=')) + then sValue := Copy( aArgument, Length(aSwitch)+2, MAXINT); + end; + end; + var - i : Integer; + iArg : Integer; threadExitCode : Byte; - s : string; + sArg, sValue : string; threads : array of TThread; dtStart : TDateTime; test : Integer; @@ -241,92 +250,83 @@ class function TTestClient.Execute(const args: array of string) : Byte; end; try - i := 0; - while ( i < Length(args) ) do begin - s := args[i]; - Inc( i); - - if (s = '-h') or (s = '--help') then begin + iArg := 0; + while iArg < Length(arguments) do begin + sArg := arguments[iArg]; + Inc(iArg); + + if IsSwitch( sArg, '-h', sValue) + or IsSwitch( sArg, '--help', sValue) + then begin // -h [ --help ] produce help message PrintCmdLineHelp; result := $FF; // all tests failed Exit; end - else if s = '--host' then begin + else if IsSwitch( sArg, '--host', sValue) then begin // --host arg (=localhost) Host to connect - setup.host := args[i]; - Inc( i); + setup.host := sValue; end - else if s = '--port' then begin + else if IsSwitch( sArg, '--port', sValue) then begin // --port arg (=9090) Port number to connect - s := args[i]; - Inc( i); - setup.port := StrToIntDef(s,0); + setup.port := StrToIntDef(sValue,0); if setup.port <= 0 then InvalidArgs; end - else if s = '--domain-socket' then begin + else if IsSwitch( sArg, '--domain-socket', sValue) then begin // --domain-socket arg Domain Socket (e.g. /tmp/ThriftTest.thrift), instead of host and port raise Exception.Create('domain-socket not supported'); end - else if s = '--pipe' then begin + // --pipe arg Windows Named Pipe (e.g. MyThriftPipe) + else if IsSwitch( sArg, '--pipe', sValue) then begin // --pipe arg Windows Named Pipe (e.g. MyThriftPipe) setup.endpoint := trns_NamedPipes; - setup.sPipeName := args[i]; - Inc( i); + setup.sPipeName := sValue; Console.WriteLine('Using named pipe ('+setup.sPipeName+')'); end - else if s = '--anon-pipes' then begin + else if IsSwitch( sArg, '--anon-pipes', sValue) then begin // --anon-pipes hRead hWrite Windows Anonymous Pipes pair (handles) setup.endpoint := trns_AnonPipes; - setup.hAnonRead := THandle( StrToIntDef( args[i], Integer(INVALID_HANDLE_VALUE))); - Inc( i); - setup.hAnonWrite := THandle( StrToIntDef( args[i], Integer(INVALID_HANDLE_VALUE))); - Inc( i); + setup.hAnonRead := THandle( StrToIntDef( arguments[iArg], Integer(INVALID_HANDLE_VALUE))); + Inc(iArg); + setup.hAnonWrite := THandle( StrToIntDef( arguments[iArg], Integer(INVALID_HANDLE_VALUE))); + Inc(iArg); Console.WriteLine('Using anonymous pipes ('+IntToStr(Integer(setup.hAnonRead))+' and '+IntToStr(Integer(setup.hAnonWrite))+')'); end - else if s = '--transport' then begin + else if IsSwitch( sArg, '--transport', sValue) then begin // --transport arg (=sockets) Transport: buffered, framed, http, winhttp, evhttp - s := args[i]; - Inc( i); - - if s = 'buffered' then Include( setup.layered, trns_Buffered) - else if s = 'framed' then Include( setup.layered, trns_Framed) - else if s = 'http' then setup.endpoint := trns_MsXmlHttp - else if s = 'winhttp' then setup.endpoint := trns_WinHttp - else if s = 'evhttp' then setup.endpoint := trns_EvHttp // recognized, but not supported + if sValue = 'buffered' then Include( setup.layered, trns_Buffered) + else if sValue = 'framed' then Include( setup.layered, trns_Framed) + else if sValue = 'http' then setup.endpoint := trns_MsXmlHttp + else if sValue = 'winhttp' then setup.endpoint := trns_WinHttp + else if sValue = 'evhttp' then setup.endpoint := trns_EvHttp // recognized, but not supported else InvalidArgs; end - else if s = '--protocol' then begin + else if IsSwitch( sArg, '--protocol', sValue) then begin // --protocol arg (=binary) Protocol: binary, compact, json - s := args[i]; - Inc( i); - - if s = 'binary' then setup.protType := prot_Binary - else if s = 'compact' then setup.protType := prot_Compact - else if s = 'json' then setup.protType := prot_JSON + if sValue = 'binary' then setup.protType := prot_Binary + else if sValue = 'compact' then setup.protType := prot_Compact + else if sValue = 'json' then setup.protType := prot_JSON else InvalidArgs; end - else if s = '--ssl' then begin + else if IsSwitch( sArg, '--ssl', sValue) then begin // --ssl Encrypted Transport using SSL setup.useSSL := TRUE; end - else if (s = '-n') or (s = '--testloops') then begin + else if IsSwitch( sArg, '-n', sValue) or IsSwitch( sArg, '--testloops', sValue) then begin // -n [ --testloops ] arg (=1) Number of Tests - FNumIteration := StrToIntDef( args[i], 0); - Inc( i); + FNumIteration := StrToIntDef( sValue, 0); if FNumIteration <= 0 then InvalidArgs; end - else if (s = '-t') or (s = '--threads') then begin + else if IsSwitch( sArg, '-t', sValue) or IsSwitch( sArg, '--threads', sValue) then begin // -t [ --threads ] arg (=1) Number of Test threads - FNumThread := StrToIntDef( args[i], 0); - Inc( i); + FNumThread := StrToIntDef( sValue, 0); if FNumThread <= 0 then InvalidArgs; end - else if (s = '--performance') then begin + else if IsSwitch( sArg, '--performance', sValue) then begin result := TPerformanceTests.Execute; Exit; end diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas index f93c846c2ae..c9b374d1fbd 100644 --- a/lib/delphi/test/TestServer.pas +++ b/lib/delphi/test/TestServer.pas @@ -56,9 +56,9 @@ TTestServer = class end; TTestHandlerImpl = class( TInterfacedObject, ITestHandler ) - private + strict private FServer : IServer; - protected + strict protected procedure testVoid(); function testBool(thing: Boolean): Boolean; function testString(const thing: string): string; @@ -88,9 +88,10 @@ TTestHandlerImpl = class( TInterfacedObject, ITestHandler ) class procedure PrintCmdLineHelp; class procedure InvalidArgs; + class function IsSwitch( const aArgument, aSwitch : string; out sValue : string) : Boolean; class procedure LaunchAnonPipeChild( const app : string; const transport : IAnonymousPipeServerTransport); - class procedure Execute( const args: array of string); + class procedure Execute( const arguments : array of string); end; implementation @@ -385,18 +386,16 @@ class procedure TTestServer.PrintCmdLineHelp; const HELPTEXT = ' [options]'#10 + #10 + 'Allowed options:'#10 - + ' -h [ --help ] produce help message'#10 - + ' --port arg (=9090) Port number to listen'#10 - + ' --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)'#10 - + ' --pipe arg Windows Named Pipe (e.g. MyThriftPipe)'#10 - + ' --server-type arg (=simple) type of server, "simple", "thread-pool",'#10 - + ' "threaded", or "nonblocking"'#10 - + ' --transport arg (=socket) transport: buffered, framed, http, anonpipe'#10 - + ' --protocol arg (=binary) protocol: binary, compact, json'#10 - + ' --ssl Encrypted Transport using SSL'#10 - + ' --processor-events processor-events'#10 - + ' -n [ --workers ] arg (=4) Number of thread pools workers. Only valid for'#10 - + ' thread-pool server type'#10 + + ' -h | --help Produces this help message'#10 + + ' --port=arg (9090) Port number to connect'#10 + + ' --pipe=arg Windows Named Pipe (e.g. MyThriftPipe)'#10 + + ' --anon-pipes Windows Anonymous Pipes server, auto-starts client.exe'#10 + + ' --server-type=arg (simple) Type of server (simple, thread-pool, threaded, nonblocking)'#10 + + ' --transport=arg (sockets) Transport: buffered, framed, anonpipe'#10 + + ' --protocol=arg (binary) Protocol: binary, compact, json'#10 + + ' --ssl Encrypted Transport using SSL'#10 + + ' --processor-events Enable processor-events'#10 + + ' -n=num | --workers=num (4) Number of thread-pool server workers'#10 ; begin Console.WriteLine( ChangeFileExt(ExtractFileName(ParamStr(0)),'') + HELPTEXT); @@ -409,6 +408,16 @@ class procedure TTestServer.InvalidArgs; Abort; end; +class function TTestServer.IsSwitch( const aArgument, aSwitch : string; out sValue : string) : Boolean; +begin + sValue := ''; + result := (Copy( aArgument, 1, Length(aSwitch)) = aSwitch); + if result then begin + if (Copy( aArgument, 1, Length(aSwitch)+1) = (aSwitch+'=')) + then sValue := Copy( aArgument, Length(aSwitch)+2, MAXINT); + end; +end; + class procedure TTestServer.LaunchAnonPipeChild( const app : string; const transport : IAnonymousPipeServerTransport); //Launch child process and pass R/W anonymous pipe handles on cmd line. //This is a simple example and does not include elevation or other @@ -431,7 +440,7 @@ class procedure TTestServer.LaunchAnonPipeChild( const app : string; const trans sArg := ParamStr(i); // add anonymous handles and quote strings where appropriate - if sArg = '-anon' + if sArg = '--anon-pipes' then sArg := sArg +' '+ sHandles else begin if Pos(' ',sArg) > 0 @@ -446,11 +455,11 @@ class procedure TTestServer.LaunchAnonPipeChild( const app : string; const trans Win32Check( CreateProcess( nil, PChar(sCmdLine), nil,nil,TRUE,0,nil,nil,si,pi)); CloseHandle( pi.hThread); - CloseHandle( pi.hProcess); + CloseHandle( pi.hProcess); end; -class procedure TTestServer.Execute( const args: array of string); +class procedure TTestServer.Execute( const arguments : array of string); var Port : Integer; ServerEvents : Boolean; @@ -463,8 +472,8 @@ class procedure TTestServer.Execute( const args: array of string); namedpipe : INamedPipeServerTransport; TransportFactory : ITransportFactory; ProtocolFactory : IProtocolFactory; - i, numWorker : Integer; - s : string; + iArg, numWorker : Integer; + sArg, sValue : string; protType : TKnownProtocol; servertype : TServerType; endpoint : TEndpointTransport; @@ -482,83 +491,68 @@ class procedure TTestServer.Execute( const args: array of string); sPipeName := ''; numWorker := 4; - i := 0; - while ( i < Length(args) ) do begin - s := args[i]; - Inc(i); + iArg := 0; + while iArg < Length(arguments) do begin + sArg := arguments[iArg]; + Inc(iArg); // Allowed options: - if (s = '-h') or (s = '--help') then begin - // -h [ --help ] produce help message + if IsSwitch( sArg, '-h', sValue) + or IsSwitch( sArg, '--help', sValue) + then begin + // -h | --help produce help message PrintCmdLineHelp; Exit; end - else if (s = '--port') then begin + else if IsSwitch( sArg, '--port', sValue) then begin // --port arg (=9090) Port number to listen - s := args[i]; - Inc(i); - Port := StrToIntDef( s, Port); + Port := StrToIntDef( sValue, Port); end - else if (s = '--domain-socket') then begin - // --domain-socket arg Unix Domain Socket (e.g. /tmp/ThriftTest.thrift) - raise Exception.Create('domain-socket not supported'); + else if IsSwitch( sArg, '--anon-pipes', sValue) then begin + endpoint := trns_AnonPipes; end - else if (s = '--pipe') then begin + else if IsSwitch( sArg, '--pipe', sValue) then begin // --pipe arg Windows Named Pipe (e.g. MyThriftPipe) endpoint := trns_NamedPipes; - sPipeName := args[i]; // --pipe - Inc( i ); + sPipeName := sValue; // --pipe end - else if (s = '--server-type') then begin + else if IsSwitch( sArg, '--server-type', sValue) then begin // --server-type arg (=simple) type of server, // arg = "simple", "thread-pool", "threaded", or "nonblocking" - s := args[i]; - Inc(i); - - if s = 'simple' then servertype := srv_Simple - else if s = 'thread-pool' then servertype := srv_Threadpool - else if s = 'threaded' then servertype := srv_Threaded - else if s = 'nonblocking' then servertype := srv_Nonblocking + if sValue = 'simple' then servertype := srv_Simple + else if sValue = 'thread-pool' then servertype := srv_Threadpool + else if sValue = 'threaded' then servertype := srv_Threaded + else if sValue = 'nonblocking' then servertype := srv_Nonblocking else InvalidArgs; end - else if (s = '--transport') then begin + else if IsSwitch( sArg, '--transport', sValue) then begin // --transport arg (=buffered) transport: buffered, framed, http - s := args[i]; - Inc(i); - - if s = 'buffered' then Include( layered, trns_Buffered) - else if s = 'framed' then Include( layered, trns_Framed) - else if s = 'http' then endpoint := trns_MsxmlHttp - else if s = 'winhttp' then endpoint := trns_WinHttp - else if s = 'anonpipe' then endpoint := trns_AnonPipes + if sValue = 'buffered' then Include( layered, trns_Buffered) + else if sValue = 'framed' then Include( layered, trns_Framed) + else if sValue = 'http' then endpoint := trns_MsxmlHttp + else if sValue = 'winhttp' then endpoint := trns_WinHttp + else if sValue = 'anonpipe' then endpoint := trns_AnonPipes else InvalidArgs; end - else if (s = '--protocol') then begin + else if IsSwitch( sArg, '--protocol', sValue) then begin // --protocol arg (=binary) protocol: binary, compact, json - s := args[i]; - Inc(i); - - if s = 'binary' then protType := prot_Binary - else if s = 'compact' then protType := prot_Compact - else if s = 'json' then protType := prot_JSON + if sValue = 'binary' then protType := prot_Binary + else if sValue = 'compact' then protType := prot_Compact + else if sValue = 'json' then protType := prot_JSON else InvalidArgs; end - else if (s = '--ssl') then begin + else if IsSwitch( sArg, '--ssl', sValue) then begin // --ssl Encrypted Transport using SSL UseSSL := TRUE; end - else if (s = '--processor-events') then begin + else if IsSwitch( sArg, '--processor-events', sValue) then begin // --processor-events processor-events ServerEvents := TRUE; end - else if (s = '-n') or (s = '--workers') then begin + else if IsSwitch( sArg, '-n', sValue) or IsSwitch( sArg, '--workers', sValue) then begin // -n [ --workers ] arg (=4) Number of thread pools workers. // Only valid for thread-pool server type - s := args[i]; - numWorker := StrToIntDef(s,0); - if numWorker > 0 - then Inc(i) - else numWorker := 4; + numWorker := StrToIntDef(sValue,4); end else begin InvalidArgs; From dfe7f30070498c7463ab61720133eff1bcd11cc3 Mon Sep 17 00:00:00 2001 From: panivko Date: Wed, 4 Mar 2020 15:05:17 +0200 Subject: [PATCH 536/756] THRIFT-5130 Use Apcu instead of APC Client: PHP Patch: Vladimir Panivko This closes #2041 --- lib/cpp/src/thrift/transport/TSocketPool.cpp | 2 +- lib/php/README.md | 6 ++-- lib/php/lib/ClassLoader/ThriftClassLoader.php | 28 +++++++++---------- lib/php/lib/Transport/TSocketPool.php | 24 ++++++++-------- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/lib/cpp/src/thrift/transport/TSocketPool.cpp b/lib/cpp/src/thrift/transport/TSocketPool.cpp index b6e79d3f605..f56c76ee458 100644 --- a/lib/cpp/src/thrift/transport/TSocketPool.cpp +++ b/lib/cpp/src/thrift/transport/TSocketPool.cpp @@ -178,7 +178,7 @@ void TSocketPool::setCurrentServer(const shared_ptr& server) * This function throws an exception if socket open fails. When socket * opens fails, the socket in the current server is reset. */ -/* TODO: without apc we ignore a lot of functionality from the php version */ +/* TODO: without apcu we ignore a lot of functionality from the php version */ void TSocketPool::open() { size_t numServers = servers_.size(); diff --git a/lib/php/README.md b/lib/php/README.md index 7170104dff4..e7144fe444e 100644 --- a/lib/php/README.md +++ b/lib/php/README.md @@ -23,7 +23,7 @@ under the License. Thrift requires PHP 5. Thrift makes as few assumptions about your PHP environment as possible while trying to make some more advanced PHP -features (i.e. APC cacheing using asbolute path URLs) as simple as possible. +features (i.e. APCu cacheing using asbolute path URLs) as simple as possible. To use Thrift in your PHP codebase, take the following steps: @@ -46,9 +46,9 @@ PHP_INT_SIZE used by the TBinaryProtocol to properly use pack() and unpack() to serialize data. -apc_fetch(), apc_store() +apcu_fetch(), apcu_store() - APC cache is used by the TSocketPool class. If you do not have APC installed, + APCu cache is used by the TSocketPool class. If you do not have APCu installed, Thrift will fill in null stub function definitions. # Breaking Changes diff --git a/lib/php/lib/ClassLoader/ThriftClassLoader.php b/lib/php/lib/ClassLoader/ThriftClassLoader.php index 4361bd84e96..e4b4a17c0c4 100644 --- a/lib/php/lib/ClassLoader/ThriftClassLoader.php +++ b/lib/php/lib/ClassLoader/ThriftClassLoader.php @@ -40,26 +40,26 @@ class ThriftClassLoader protected $definitions = array(); /** - * Do we use APC cache ? + * Do we use APCu cache ? * @var boolean */ - protected $apc = false; + protected $apcu = false; /** - * APC Cache prefix + * APCu Cache prefix * @var string */ - protected $apc_prefix; + protected $apcu_prefix; /** - * Set autoloader to use APC cache + * Set autoloader to use APCu cache * @param boolean $apc - * @param string $apc_prefix + * @param string $apcu_prefix */ - public function __construct($apc = false, $apc_prefix = null) + public function __construct($apc = false, $apcu_prefix = null) { - $this->apc = $apc; - $this->apc_prefix = $apc_prefix; + $this->apcu = $apc; + $this->apcu_prefix = $apcu_prefix; } /** @@ -101,7 +101,7 @@ public function register($prepend = false) */ public function loadClass($class) { - if ((true === $this->apc && ($file = $this->findFileInApc($class))) or + if ((true === $this->apcu && ($file = $this->findFileInApcu($class))) or ($file = $this->findFile($class)) ) { require_once $file; @@ -109,14 +109,14 @@ public function loadClass($class) } /** - * Loads the given class or interface in APC. + * Loads the given class or interface in APCu. * @param string $class The name of the class * @return string */ - protected function findFileInApc($class) + protected function findFileInApcu($class) { - if (false === $file = apc_fetch($this->apc_prefix . $class)) { - apc_store($this->apc_prefix . $class, $file = $this->findFile($class)); + if (false === $file = apcu_fetch($this->apcu_prefix . $class)) { + apcu_store($this->apcu_prefix . $class, $file = $this->findFile($class)); } return $file; diff --git a/lib/php/lib/Transport/TSocketPool.php b/lib/php/lib/Transport/TSocketPool.php index cb9e8ddfa81..307885f507a 100644 --- a/lib/php/lib/Transport/TSocketPool.php +++ b/lib/php/lib/Transport/TSocketPool.php @@ -25,18 +25,18 @@ use Thrift\Exception\TException; /** - * This library makes use of APC cache to make hosts as down in a web - * environment. If you are running from the CLI or on a system without APC + * This library makes use of APCu cache to make hosts as down in a web + * environment. If you are running from the CLI or on a system without APCu * installed, then these null functions will step in and act like cache * misses. */ -if (!function_exists('apc_fetch')) { - function apc_fetch($key) +if (!function_exists('apcu_fetch')) { + function apcu_fetch($key) { return false; } - function apc_store($key, $var, $ttl = 0) + function apcu_store($key, $var, $ttl = 0) { return false; } @@ -202,11 +202,11 @@ public function open() // This extracts the $host and $port variables extract($this->servers_[$i]); - // Check APC cache for a record of this server being down + // Check APCu cache for a record of this server being down $failtimeKey = 'thrift_failtime:' . $host . ':' . $port . '~'; // Cache miss? Assume it's OK - $lastFailtime = apc_fetch($failtimeKey); + $lastFailtime = apcu_fetch($failtimeKey); if ($lastFailtime === false) { $lastFailtime = 0; } @@ -251,7 +251,7 @@ public function open() // Only clear the failure counts if required to do so if ($lastFailtime > 0) { - apc_store($failtimeKey, 0); + apcu_store($failtimeKey, 0); } // Successful connection, return now @@ -265,7 +265,7 @@ public function open() $consecfailsKey = 'thrift_consecfails:' . $host . ':' . $port . '~'; // Ignore cache misses - $consecfails = apc_fetch($consecfailsKey); + $consecfails = apcu_fetch($consecfailsKey); if ($consecfails === false) { $consecfails = 0; } @@ -284,12 +284,12 @@ public function open() ); } // Store the failure time - apc_store($failtimeKey, time()); + apcu_store($failtimeKey, time()); // Clear the count of consecutive failures - apc_store($consecfailsKey, 0); + apcu_store($consecfailsKey, 0); } else { - apc_store($consecfailsKey, $consecfails); + apcu_store($consecfailsKey, $consecfails); } } } From 11fc716a20474a7b668654f96db43d97a09bc318 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 27 Mar 2020 00:05:48 +0100 Subject: [PATCH 537/756] THRIFT-5154 Generate interface IDs (IID) for Windows platforms Client: Delphi Patch: Jens Geyer This closes #2072 --- .../src/thrift/generate/t_delphi_generator.cc | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc index cffe3058edf..e5bd81a88cf 100644 --- a/compiler/cpp/src/thrift/generate/t_delphi_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_delphi_generator.cc @@ -37,6 +37,13 @@ #include "thrift/platform.h" #include "thrift/generate/t_oop_generator.h" +#ifdef _WIN32 +#include +#include +#include +#include +#endif + using std::map; using std::ofstream; using std::ostream; @@ -243,6 +250,7 @@ class t_delphi_generator : public t_oop_generator { void generate_function_helpers(t_function* tfunction); void generate_service_interface(t_service* tservice); void generate_service_interface(t_service* tservice, bool for_async); + void generate_guid(std::ostream& out); void generate_service_helpers(t_service* tservice); void generate_service_client(t_service* tservice); void generate_service_server(t_service* tservice); @@ -1712,6 +1720,8 @@ void t_delphi_generator::generate_delphi_struct_definition(ostream& out, indent(out) << struct_intf_name << " = interface(IBase)" << endl; indent_up(); + generate_guid(out); + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { generate_delphi_property_reader_definition(out, *m_iter, is_exception); generate_delphi_property_writer_definition(out, *m_iter, is_exception); @@ -1934,6 +1944,7 @@ void t_delphi_generator::generate_service_interface(t_service* tservice, bool fo } indent_up(); + generate_guid(s_service); vector functions = tservice->get_functions(); vector::iterator f_iter; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { @@ -1946,6 +1957,23 @@ void t_delphi_generator::generate_service_interface(t_service* tservice, bool fo indent_down(); } +void t_delphi_generator::generate_guid(std::ostream& out) { +#ifdef _WIN32 // TODO: add support for non-windows platforms if needed + GUID guid; + if (SUCCEEDED(CoCreateGuid(&guid))) { + OLECHAR guid_chars[40]; + if (StringFromGUID2(guid, &guid_chars[0], sizeof(guid_chars) / sizeof(guid_chars[0])) > 0) { + std::wstring guid_wstr(guid_chars); + std::wstring_convert> convert; + std::string guid_str = convert.to_bytes(guid_wstr); + indent(out) << "['" << guid_str << "']" << endl; + } + } +#else + (void)out; // prevent unused warning on other platforms +#endif +} + void t_delphi_generator::generate_service_helpers(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator f_iter; From 7e90252af64b0a0dee5e5e6f37808aa11a6b2e03 Mon Sep 17 00:00:00 2001 From: Mikail Bagishov Date: Tue, 29 Jan 2019 19:51:42 +0300 Subject: [PATCH 538/756] THRIFT-4764: Use new syntax for clippy skipping Client: rs --- compiler/cpp/src/thrift/generate/t_rs_generator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/cpp/src/thrift/generate/t_rs_generator.cc b/compiler/cpp/src/thrift/generate/t_rs_generator.cc index 70e18472c2c..b240d991f41 100644 --- a/compiler/cpp/src/thrift/generate/t_rs_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_rs_generator.cc @@ -547,7 +547,7 @@ void t_rs_generator::render_attributes_and_includes() { f_gen_ << "#![allow(unused_extern_crates)]" << endl; // constructors take *all* struct parameters, which can trigger the "too many arguments" warning // some auto-gen'd types can be deeply nested. clippy recommends factoring them out which is hard to autogen - f_gen_ << "#![cfg_attr(feature = \"cargo-clippy\", allow(too_many_arguments, type_complexity))]" << endl; + f_gen_ << "#![allow(clippy::too_many_arguments, clippy::type_complexity)]" << endl; // prevent rustfmt from running against this file // lines are too long, code is (thankfully!) not visual-indented, etc. f_gen_ << "#![cfg_attr(rustfmt, rustfmt_skip)]" << endl; From 8ec585793c63c765a18ec97335eda6b89b494ab5 Mon Sep 17 00:00:00 2001 From: Kanishth Karthik Date: Thu, 26 Mar 2020 01:29:50 +0530 Subject: [PATCH 539/756] THRIFT-4963: Fix deadlock in ThreadManager::Worker::run Client: cpp Patch: Kanishth Karthi This closes #2070 --- lib/cpp/src/thrift/concurrency/ThreadManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp index 25b838aefbc..e917f4a478b 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadManager.cpp +++ b/lib/cpp/src/thrift/concurrency/ThreadManager.cpp @@ -319,7 +319,9 @@ class ThreadManager::Worker : public Runnable { } else if (manager_->expireCallback_) { // The only other state the task could have been in is TIMEDOUT (see above) + manager_->mutex_.unlock(); manager_->expireCallback_(task->getRunnable()); + manager_->mutex_.lock(); manager_->expiredCount_++; } } From 86396c688068c428d997ad3209823ab5a2e3dcae Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Tue, 31 Mar 2020 14:38:20 +0800 Subject: [PATCH 540/756] Add testcase for other condition judgment in the readJSONDouble function Client: cpp Patch: zeshuai007 <51382517@qq.com> This closes #2080 --- lib/cpp/test/JSONProtoTest.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/cpp/test/JSONProtoTest.cpp b/lib/cpp/test/JSONProtoTest.cpp index c2ad73e71db..082c8a28b75 100644 --- a/lib/cpp/test/JSONProtoTest.cpp +++ b/lib/cpp/test/JSONProtoTest.cpp @@ -229,10 +229,19 @@ BOOST_AUTO_TEST_CASE(test_json_proto_6) { "304},\"6\":{\"dbl\":1e-305},\"7\":{\"dbl\":0},\"8\":{\"dbl\":-0}}" ); - const std::string result(apache::thrift::ThriftJSONString(dub)); + std::shared_ptr buffer(new TMemoryBuffer()); + std::shared_ptr proto(new TJSONProtocol(buffer)); + dub.write(proto.get()); + Doubles dub_1; + dub_1.read(proto.get()); + const std::string result(apache::thrift::ThriftJSONString(dub)); + const std::string result_1(apache::thrift::ThriftJSONString(dub_1)); + BOOST_CHECK_MESSAGE(!expected_result.compare(result), "Expected:\n" << expected_result << "\nGotten:\n" << result); + BOOST_CHECK_MESSAGE(!expected_result.compare(result_1), + "Expected:\n" << expected_result << "\nGotten:\n" << result_1); } BOOST_AUTO_TEST_CASE(test_json_proto_7) { From dfd6df7588564739be7a1eba8a7c3ed83ee27a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Csord=C3=A1s?= Date: Thu, 2 Apr 2020 12:23:22 +0200 Subject: [PATCH 541/756] =?UTF-8?q?THRIFT-3356:=20handle=20undefined=20cap?= =?UTF-8?q?tureStackTrace=20Client:=20nodejs=20Patch:=20M=C3=A1rton=20Csor?= =?UTF-8?q?d=C3=A1s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This closes #2082 --- lib/js/src/thrift.js | 5 ++++- lib/nodejs/lib/thrift/header_protocol.js | 5 ++++- lib/nodejs/lib/thrift/header_transport.js | 5 ++++- lib/nodejs/lib/thrift/http_connection.js | 5 ++++- .../lib/thrift/input_buffer_underrun_error.js | 5 ++++- lib/nodejs/lib/thrift/thrift.js | 15 ++++++++++++--- 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index 69bcccdd23f..c682605b81d 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -284,7 +284,10 @@ Thrift.TProtocolExceptionType = { Thrift.TProtocolException = function TProtocolException(type, message) { Error.call(this); - Error.captureStackTrace(this, this.constructor); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + this.name = this.constructor.name; this.type = type; this.message = message; diff --git a/lib/nodejs/lib/thrift/header_protocol.js b/lib/nodejs/lib/thrift/header_protocol.js index 0c3b0db43a1..a037dc2557d 100644 --- a/lib/nodejs/lib/thrift/header_protocol.js +++ b/lib/nodejs/lib/thrift/header_protocol.js @@ -29,7 +29,10 @@ module.exports = THeaderProtocol; function THeaderProtocolError(message) { Error.call(this); - Error.captureStackTrace(this, this.constructor); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + this.name = this.constructor.name; this.message = message; } diff --git a/lib/nodejs/lib/thrift/header_transport.js b/lib/nodejs/lib/thrift/header_transport.js index c5f133e8df9..252a42385a7 100644 --- a/lib/nodejs/lib/thrift/header_transport.js +++ b/lib/nodejs/lib/thrift/header_transport.js @@ -24,7 +24,10 @@ var InputBufferUnderrunError = require('./input_buffer_underrun_error'); function THeaderTransportError(message) { Error.call(this); - Error.captureStackTrace(this, this.constructor); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + this.name = this.constructor.name; this.message = message; } diff --git a/lib/nodejs/lib/thrift/http_connection.js b/lib/nodejs/lib/thrift/http_connection.js index 3c2ab0f535d..81e6b706de2 100644 --- a/lib/nodejs/lib/thrift/http_connection.js +++ b/lib/nodejs/lib/thrift/http_connection.js @@ -253,7 +253,10 @@ exports.createHttpClient = createClient function THTTPException(response) { thrift.TApplicationException.call(this); - Error.captureStackTrace(this, this.constructor); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + this.name = this.constructor.name; this.statusCode = response.statusCode; this.response = response; diff --git a/lib/nodejs/lib/thrift/input_buffer_underrun_error.js b/lib/nodejs/lib/thrift/input_buffer_underrun_error.js index 72555e51642..0e33f5a42f1 100644 --- a/lib/nodejs/lib/thrift/input_buffer_underrun_error.js +++ b/lib/nodejs/lib/thrift/input_buffer_underrun_error.js @@ -22,7 +22,10 @@ module.exports = InputBufferUnderrunError; function InputBufferUnderrunError(message) { Error.call(this); - Error.captureStackTrace(this, this.constructor); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + this.name = this.constructor.name; this.message = message; }; diff --git a/lib/nodejs/lib/thrift/thrift.js b/lib/nodejs/lib/thrift/thrift.js index f2b2896723a..58d4aff797a 100644 --- a/lib/nodejs/lib/thrift/thrift.js +++ b/lib/nodejs/lib/thrift/thrift.js @@ -49,7 +49,10 @@ exports.TException = TException; function TException(message) { Error.call(this); - Error.captureStackTrace(this, this.constructor); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + this.name = this.constructor.name; this.message = message; }; @@ -73,7 +76,10 @@ exports.TApplicationException = TApplicationException; function TApplicationException(type, message) { TException.call(this); - Error.captureStackTrace(this, this.constructor); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + this.type = type || TApplicationExceptionType.UNKNOWN; this.name = this.constructor.name; this.message = message; @@ -149,7 +155,10 @@ exports.TProtocolException = TProtocolException; function TProtocolException(type, message) { Error.call(this); - Error.captureStackTrace(this, this.constructor); + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + this.name = this.constructor.name; this.type = type; this.message = message; From 102428d35da461aec0f3d8a513e4a21bb56ddb69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Csord=C3=A1s?= Date: Sat, 14 Mar 2020 10:30:12 +0100 Subject: [PATCH 542/756] =?UTF-8?q?THRIFT-5163=20adds=20Q=20to=20exports?= =?UTF-8?q?=20for=20browserify=20Client:=20NodeJS=20Patch:=20M=C3=A1rton?= =?UTF-8?q?=20Csord=C3=A1s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This closes #2061 --- lib/nodejs/lib/thrift/browser.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/nodejs/lib/thrift/browser.js b/lib/nodejs/lib/thrift/browser.js index 82e5469c674..ba1ea8c389c 100644 --- a/lib/nodejs/lib/thrift/browser.js +++ b/lib/nodejs/lib/thrift/browser.js @@ -39,3 +39,4 @@ exports.TBinaryProtocol = require('./binary_protocol'); exports.TCompactProtocol = require('./compact_protocol'); exports.Int64 = require('node-int64'); +exports.Q = require('q'); From dbb95e438f90609c8bc70b6953f65e97afedbb1b Mon Sep 17 00:00:00 2001 From: Kevin Wojniak Date: Sat, 25 Jan 2020 12:37:23 -0800 Subject: [PATCH 543/756] THRIFT-5076 Improve CMake OpenSSL usage Client: c_glib Patch: Kevin Wojniak This closes #1994 --- build/cmake/DefineOptions.cmake | 15 ++++++++++++--- lib/c_glib/CMakeLists.txt | 5 ++--- test/c_glib/CMakeLists.txt | 3 ++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index f85d2c6447a..8357160b1bf 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -73,9 +73,6 @@ if(WITH_CPP) find_package(Qt5 QUIET COMPONENTS Core Network) CMAKE_DEPENDENT_OPTION(WITH_QT5 "Build with Qt5 support" ON "Qt5_FOUND" OFF) - find_package(OpenSSL QUIET) - CMAKE_DEPENDENT_OPTION(WITH_OPENSSL "Build with OpenSSL support" ON - "OPENSSL_FOUND" OFF) endif() CMAKE_DEPENDENT_OPTION(BUILD_CPP "Build C++ library" ON "BUILD_LIBRARIES;WITH_CPP" OFF) @@ -88,6 +85,13 @@ endif() CMAKE_DEPENDENT_OPTION(BUILD_C_GLIB "Build C (GLib) library" ON "BUILD_LIBRARIES;WITH_C_GLIB;GLIB_FOUND" OFF) +# OpenSSL +if(WITH_CPP OR WITH_C_GLIB) + find_package(OpenSSL QUIET) + CMAKE_DEPENDENT_OPTION(WITH_OPENSSL "Build with OpenSSL support" ON + "OPENSSL_FOUND" OFF) +endif() + # Java option(WITH_JAVA "Build Java Thrift library" ON) if(ANDROID) @@ -170,6 +174,11 @@ message(STATUS " Build as3 library: ${BUILD_AS3}") MESSAGE_DEP(WITH_AS3 "Disabled by WITH_AS3=OFF") MESSAGE_DEP(HAVE_COMPC "Adobe Flex compc was not found - did you set env var FLEX_HOME?") message(STATUS) +message(STATUS " Build with OpenSSL: ${WITH_OPENSSL}") +if(WITH_OPENSSL) + message(STATUS " Version: ${OPENSSL_VERSION}") +endif() +message(STATUS) message(STATUS " Build C++ library: ${BUILD_CPP}") MESSAGE_DEP(WITH_CPP "Disabled by WITH_CPP=OFF") if (BUILD_CPP) diff --git a/lib/c_glib/CMakeLists.txt b/lib/c_glib/CMakeLists.txt index 3e4a154b8e3..d9dc2176818 100644 --- a/lib/c_glib/CMakeLists.txt +++ b/lib/c_glib/CMakeLists.txt @@ -59,9 +59,8 @@ set(thrift_c_glib_SOURCES ) # If OpenSSL is not found just ignore the OpenSSL stuff -find_package(OpenSSL) -if(OPENSSL_FOUND AND WITH_OPENSSL) - list( APPEND thrift_c_glib_SOURCES +if(WITH_OPENSSL) + list(APPEND thrift_c_glib_SOURCES src/thrift/c_glib/transport/thrift_ssl_socket.c ) include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") diff --git a/test/c_glib/CMakeLists.txt b/test/c_glib/CMakeLists.txt index 98173155bde..7a7daadc561 100644 --- a/test/c_glib/CMakeLists.txt +++ b/test/c_glib/CMakeLists.txt @@ -28,6 +28,7 @@ include_directories(SYSTEM "${GLIBCONFIG_INCLUDE_DIR}") include_directories("${CMAKE_CURRENT_BINARY_DIR}") include_directories("${CMAKE_CURRENT_BINARY_DIR}/gen-c_glib") include_directories("${PROJECT_SOURCE_DIR}/lib/c_glib/src") +include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") set(crosstestgencglib_SOURCES gen-c_glib/t_test_second_service.c @@ -44,7 +45,7 @@ add_executable(test_server src/test_server.c src/thrift_test_handler.c src/thrif target_link_libraries(test_server crosstestgencglib) add_executable(test_client src/test_client.c) -target_link_libraries(test_client crosstestgencglib) +target_link_libraries(test_client crosstestgencglib "${OPENSSL_LIBRARIES}") # # Common thrift code generation rules From 818105653db4916f9e8b59b8fb8f074cb083c30b Mon Sep 17 00:00:00 2001 From: James Lacey Date: Fri, 27 Mar 2020 19:14:33 +0100 Subject: [PATCH 544/756] THRIFT-5156: Fix library compilation on Windows and compiler warnings Client: d Patch: James Lacey This closes #2075 --- lib/d/src/thrift/async/libevent.d | 4 ++-- lib/d/src/thrift/async/socket.d | 17 ++++++++++++----- lib/d/src/thrift/codegen/async_client_pool.d | 2 +- lib/d/src/thrift/internal/socket.d | 8 ++++---- lib/d/src/thrift/server/nonblocking.d | 8 ++++---- lib/d/src/thrift/transport/socket.d | 8 +++++++- lib/d/src/thrift/transport/ssl.d | 2 +- 7 files changed, 31 insertions(+), 18 deletions(-) diff --git a/lib/d/src/thrift/async/libevent.d b/lib/d/src/thrift/async/libevent.d index 812e4a7650b..04e0e71ba93 100644 --- a/lib/d/src/thrift/async/libevent.d +++ b/lib/d/src/thrift/async/libevent.d @@ -62,7 +62,7 @@ class TLibeventAsyncManager : TAsyncSocketManager { controlReceiveSocket_.blocking = false; // Register an event for receiving control messages. - controlReceiveEvent_ = event_new(eventBase_, controlReceiveSocket_.handle, + controlReceiveEvent_ = event_new(eventBase_, cast(evutil_socket_t)controlReceiveSocket_.handle, EV_READ | EV_PERSIST | EV_ET, assumeNothrow(&controlMsgReceiveCallback), cast(void*)this); event_add(controlReceiveEvent_, null); @@ -188,7 +188,7 @@ private: void addOneshotListenerImpl(Socket socket, TAsyncEventType eventType, const(timeval)* timeout, TSocketEventListener listener ) { - registerOneshotEvent(socket.handle, libeventEventType(eventType), + registerOneshotEvent(cast(evutil_socket_t)socket.handle, libeventEventType(eventType), assumeNothrow(&socketCallback), timeout, listener); } diff --git a/lib/d/src/thrift/async/socket.d b/lib/d/src/thrift/async/socket.d index a08f51db083..352a8224e6d 100644 --- a/lib/d/src/thrift/async/socket.d +++ b/lib/d/src/thrift/async/socket.d @@ -18,7 +18,6 @@ */ module thrift.async.socket; -import core.stdc.errno: ECONNRESET; import core.thread : Fiber; import core.time : dur, Duration; import std.array : empty; @@ -33,11 +32,15 @@ import thrift.internal.endian; import thrift.internal.socket; version (Windows) { - import std.c.windows.winsock : connect; + import core.sys.windows.winsock2 : connect; } else version (Posix) { import core.sys.posix.sys.socket : connect; } else static assert(0, "Don't know connect on this platform."); +version (Win32) { + import core.stdc.config : __c_long; +} + /** * Non-blocking socket implementation of the TTransport interface. * @@ -148,7 +151,11 @@ class TAsyncSocket : TSocketBase, TAsyncTransport { return; } - int errorCode = void; + version (Win32) { + __c_long errorCode = void; + } else { + int errorCode = void; + } socket_.getOption(SocketOptionLevel.SOCKET, cast(SocketOption)SO_ERROR, errorCode); @@ -344,8 +351,8 @@ private { enum SO_ERROR = 0x1007; } else version (FreeBSD) { enum SO_ERROR = 0x1007; - } else version (Win32) { - import std.c.windows.winsock : SO_ERROR; + } else version (Windows) { + import core.sys.windows.winsock2 : SO_ERROR; } else static assert(false, "Don't know SO_ERROR on this platform."); // This hack forces a delegate literal to be scoped, even if it is passed to diff --git a/lib/d/src/thrift/codegen/async_client_pool.d b/lib/d/src/thrift/codegen/async_client_pool.d index 26cb975a32c..b51cd16a92f 100644 --- a/lib/d/src/thrift/codegen/async_client_pool.d +++ b/lib/d/src/thrift/codegen/async_client_pool.d @@ -95,7 +95,7 @@ interface TAsyncClientPoolBase(Interface) if (isService!Interface) : } immutable bool delegate(Exception) defaultRpcFaultFilter; -static this() { +shared static this() { defaultRpcFaultFilter = (Exception e) { import thrift.protocol.base; import thrift.transport.base; diff --git a/lib/d/src/thrift/internal/socket.d b/lib/d/src/thrift/internal/socket.d index 6ca0a970e41..757fafab3c0 100644 --- a/lib/d/src/thrift/internal/socket.d +++ b/lib/d/src/thrift/internal/socket.d @@ -34,8 +34,8 @@ version (FreeBSD) { enum connresetOnPeerShutdown = false; } -version (Win32) { - import std.c.windows.winsock : WSAGetLastError, WSAEINTR, WSAEWOULDBLOCK; +version (Windows) { + import core.sys.windows.winsock2 : WSAGetLastError, WSAEINTR, WSAEWOULDBLOCK; import std.windows.syserror : sysErrorString; // These are unfortunately not defined in std.c.windows.winsock, see @@ -60,7 +60,7 @@ version (Win32) { * isSocetCloseErrno(errno): returns true if errno indicates that the socket * is logically in closed state now. */ -version (Win32) { +version (Windows) { alias WSAGetLastError getSocketErrno; enum CONNECT_INPROGRESS_ERRNO = WSAEWOULDBLOCK; enum INTERRUPTED_ERRNO = WSAEINTR; @@ -88,7 +88,7 @@ version (Win32) { } string socketErrnoString(uint errno) { - version (Win32) { + version (Windows) { return sysErrorString(errno); } else { return to!string(strerror(errno)); diff --git a/lib/d/src/thrift/server/nonblocking.d b/lib/d/src/thrift/server/nonblocking.d index 5860c0c4274..f0afc1f9207 100644 --- a/lib/d/src/thrift/server/nonblocking.d +++ b/lib/d/src/thrift/server/nonblocking.d @@ -623,7 +623,7 @@ private { to!string(event_get_version()), to!string(event_base_get_method(eventBase_))); // Register the event for the listening socket. - listenEvent_ = event_new(eventBase_, listenSocket_.handle, + listenEvent_ = event_new(eventBase_, cast(evutil_socket_t)listenSocket_.handle, EV_READ | EV_PERSIST | EV_ET, assumeNothrow(&TNonblockingServer.acceptConnectionsCallback), cast(void*)server_); @@ -638,7 +638,7 @@ private { completionReceiveSocket_ = pair[1]; // Register an event for the task completion notification socket. - completionEvent_ = event_new(eventBase_, completionReceiveSocket_.handle, + completionEvent_ = event_new(eventBase_, cast(evutil_socket_t)completionReceiveSocket_.handle, EV_READ | EV_PERSIST | EV_ET, assumeNothrow(&completedCallback), cast(void*)this); @@ -1212,10 +1212,10 @@ private { if (!event_) { // If the event was not already allocated, do it now. - event_ = event_new(loop_.eventBase_, socket_.socketHandle, + event_ = event_new(loop_.eventBase_, cast(evutil_socket_t)socket_.socketHandle, eventFlags_, assumeNothrow(&workSocketCallback), cast(void*)this); } else { - event_assign(event_, loop_.eventBase_, socket_.socketHandle, + event_assign(event_, loop_.eventBase_, cast(evutil_socket_t)socket_.socketHandle, eventFlags_, assumeNothrow(&workSocketCallback), cast(void*)this); } diff --git a/lib/d/src/thrift/transport/socket.d b/lib/d/src/thrift/transport/socket.d index fcb38da36d0..b257fe955d2 100644 --- a/lib/d/src/thrift/transport/socket.d +++ b/lib/d/src/thrift/transport/socket.d @@ -18,7 +18,6 @@ */ module thrift.transport.socket; -import core.stdc.errno: ECONNRESET; import core.thread : Thread; import core.time : dur, Duration; import std.array : empty; @@ -29,6 +28,13 @@ import thrift.base; import thrift.transport.base; import thrift.internal.socket; +version (Windows) { + import core.sys.windows.winsock2 : WSAECONNRESET; + enum ECONNRESET = WSAECONNRESET; +} else version (Posix) { + import core.stdc.errno : ECONNRESET; +} else static assert(0, "Don't know ECONNRESET on this platform."); + /** * Common parts of a socket TTransport implementation, regardless of how the * actual I/O is performed (sync/async). diff --git a/lib/d/src/thrift/transport/ssl.d b/lib/d/src/thrift/transport/ssl.d index f8ce40eb721..5bdacbf1f10 100644 --- a/lib/d/src/thrift/transport/ssl.d +++ b/lib/d/src/thrift/transport/ssl.d @@ -213,7 +213,7 @@ private: if (ssl_ !is null) return; ssl_ = context_.createSSL(); - SSL_set_fd(ssl_, socketHandle); + SSL_set_fd(ssl_, cast(int)socketHandle); int rc; if (serverSide_) { rc = SSL_accept(ssl_); From 13e6f9ec89ae4f8f87165eccea88442e83afb314 Mon Sep 17 00:00:00 2001 From: cyy Date: Thu, 12 Dec 2019 21:13:31 +0800 Subject: [PATCH 545/756] THRIFT-5047:fix openssl switch Client: cpp Patch: Yuanyuan Chen This closes #1962 --- lib/cpp/CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index 9b987ae6781..d705bb3d7a4 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -125,11 +125,17 @@ set( thriftcpp_threads_SOURCES set( thriftcppnb_SOURCES src/thrift/server/TNonblockingServer.cpp src/thrift/transport/TNonblockingServerSocket.cpp - src/thrift/transport/TNonblockingSSLServerSocket.cpp src/thrift/async/TEvhttpServer.cpp src/thrift/async/TEvhttpClientChannel.cpp ) +# If OpenSSL is not found or disabled just ignore the OpenSSL stuff +if(OPENSSL_FOUND AND WITH_OPENSSL) + list( APPEND thriftcppnb_SOURCES + src/thrift/transport/TNonblockingSSLServerSocket.cpp + ) +endif() + # Thrift zlib transport set( thriftcppz_SOURCES src/thrift/transport/TZlibTransport.cpp From 5159da90964b774e6ff952efaf2bce516538ae50 Mon Sep 17 00:00:00 2001 From: "eric.bleher@software-managed.com" Date: Wed, 8 Apr 2020 15:53:04 +0200 Subject: [PATCH 546/756] THRIFT-5172 NetStd OutOfMemoryException Client: netstd Patch: Eric Bleher This closes #2093 --- lib/netstd/Thrift/TBaseClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/netstd/Thrift/TBaseClient.cs b/lib/netstd/Thrift/TBaseClient.cs index 0edac0f0812..aefb54dd5a1 100644 --- a/lib/netstd/Thrift/TBaseClient.cs +++ b/lib/netstd/Thrift/TBaseClient.cs @@ -63,7 +63,7 @@ public virtual async Task OpenTransportAsync(CancellationToken cancellationToken await _inputProtocol.Transport.OpenAsync(cancellationToken); } - if (!_inputProtocol.Transport.IsOpen) + if (!_outputProtocol.Transport.IsOpen) { await _outputProtocol.Transport.OpenAsync(cancellationToken); } From 23aabcc1b196dc443a974e168ed5826d06fed945 Mon Sep 17 00:00:00 2001 From: Wenqiang Yang Date: Tue, 7 Apr 2020 18:45:41 +0800 Subject: [PATCH 547/756] markdown head title needs space This closes #2090 --- doc/specs/HeaderFormat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/specs/HeaderFormat.md b/doc/specs/HeaderFormat.md index 42ec7ae3880..0456f1ea7d5 100644 --- a/doc/specs/HeaderFormat.md +++ b/doc/specs/HeaderFormat.md @@ -74,7 +74,7 @@ This allows us to distingush between different (older) transports. data. -###Info IDs: +### Info IDs: INFO_KEYVALUE 0x01 - varint32 number of headers. - key/value pairs of varstrings (varint16 length plus From f44b6ee8db9342d804c6ba01da9953e791021bfe Mon Sep 17 00:00:00 2001 From: gzuykov Date: Thu, 9 Apr 2020 16:31:15 +0300 Subject: [PATCH 548/756] Modify autogenerated message for Go to standard to match the expectations of some tools Client: Go Patch: gzuykov This closes #2096 --- compiler/cpp/src/thrift/generate/t_go_generator.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index a5d55d7b111..4f871515991 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -888,13 +888,13 @@ string t_go_generator::render_fastbinary_includes() { } /** - * Autogen'd comment + * Autogen'd comment. The different text is necessary due to + * https://github.com/golang/go/issues/13560#issuecomment-288457920 */ string t_go_generator::go_autogen_comment() { return std::string() + - "// Autogenerated by Thrift Compiler (" + THRIFT_VERSION + ")\n" - "// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n\n"; + "// Code generated by Thrift Compiler (" + THRIFT_VERSION + "). DO NOT EDIT.\n\n"; } /** From 6bbdb1a46ce6ba0ac4e27e29b2c9c9eef107186c Mon Sep 17 00:00:00 2001 From: James Lacey Date: Mon, 6 Apr 2020 09:17:59 -0700 Subject: [PATCH 549/756] THRIFT-5166: Add support for using WebSockets as a server transport. Client: d Patch: James Lacey This closes #2087 --- lib/d/src/thrift/transport/websocket.d | 388 +++++++++++++++++++++++++ 1 file changed, 388 insertions(+) create mode 100644 lib/d/src/thrift/transport/websocket.d diff --git a/lib/d/src/thrift/transport/websocket.d b/lib/d/src/thrift/transport/websocket.d new file mode 100644 index 00000000000..25d1f7d01dc --- /dev/null +++ b/lib/d/src/thrift/transport/websocket.d @@ -0,0 +1,388 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +module thrift.transport.websocket; + +import std.algorithm; +import std.algorithm.searching; +import std.base64; +import std.bitmanip; +import std.conv; +import std.digest.sha; +import std.stdio; +import std.string; +import std.uni; +import thrift.base : VERSION; +import thrift.transport.base; +import thrift.transport.http; + +/** + * WebSocket server transport. + */ +final class TServerWebSocketTransport(bool binary) : THttpTransport { + /** + * Constructs a new instance. + * + * Param: + * transport = The underlying transport used for the actual I/O. + */ + this(TTransport transport) { + super(transport); + transport_ = transport; + } + + override size_t read(ubyte[] buf) { + // If we do not have a good handshake, the client will attempt one. + if (!handshakeComplete) { + resetHandshake(); + super.read(buf); + // If we did not get everything we expected, the handshake failed + // and we need to send a 400 response back. + if (!handshakeComplete) { + sendBadRequest(); + return 0; + } + // Otherwise, send back the 101 response. + super.flush(); + } + + // If the buffer is empty, read a new frame off the wire. + if (readBuffer_.empty) { + if (!readFrame()) { + return 0; + } + } + + auto size = min(readBuffer_.length, buf.length); + buf[0..size] = readBuffer_[0..size]; + readBuffer_ = readBuffer_[size..$]; + return size; + } + + override void write(in ubyte[] buf) { + writeBuffer_ ~= buf; + } + + override void flush() { + if (writeBuffer_.empty) { + return; + } + + // Properly reset the write buffer even some of the protocol operations go + // wrong. + scope (exit) { + writeBuffer_.length = 0; + writeBuffer_.assumeSafeAppend(); + } + + writeFrameHeader(); + transport_.write(writeBuffer_); + transport_.flush(); + } + +protected: + override string getHeader(size_t dataLength) { + return "HTTP/1.1 101 Switching Protocols\r\n" ~ + "Server: Thrift/" ~ VERSION ~ "\r\n" ~ + "Upgrade: websocket\r\n" ~ + "Connection: Upgrade\r\n" ~ + "Sec-WebSocket-Accept: " ~ acceptKey_ ~ "\r\n" ~ + "\r\n"; + } + + override void parseHeader(const(ubyte)[] header) { + auto split = findSplit(header, [':']); + if (split[1].empty) { + // No colon found. + return; + } + + static bool compToLower(ubyte a, ubyte b) { + return toLower(a) == toLower(b); + } + + if (startsWith!compToLower(split[0], cast(ubyte[])"upgrade")) { + auto upgrade = stripLeft(cast(const(char)[])split[2]); + upgrade_ = sicmp(upgrade, "websocket") == 0; + } else if (startsWith!compToLower(split[0], cast(ubyte[])"connection")) { + auto connection = stripLeft(cast(const(char)[])split[2]); + connection_ = sicmp(connection, "upgrade") == 0; + } else if (startsWith!compToLower(split[0], cast(ubyte[])"sec-websocket-key")) { + auto secWebSocketKey = stripLeft(cast(const(char)[])split[2]); + auto hash = sha1Of(secWebSocketKey ~ WEBSOCKET_GUID); + acceptKey_ = Base64.encode(hash); + secWebSocketKey_ = true; + } else if (startsWith!compToLower(split[0], cast(ubyte[])"sec-websocket-version")) { + auto secWebSocketVersion = stripLeft(cast(const(char)[])split[2]); + secWebSocketVersion_ = sicmp(secWebSocketVersion, "13") == 0; + } + } + + override bool parseStatusLine(const(ubyte)[] status) { + // Method SP Request-URI SP HTTP-Version CRLF. + auto split = findSplit(status, [' ']); + if (split[1].empty) { + throw new TTransportException("Bad status: " ~ to!string(status), + TTransportException.Type.CORRUPTED_DATA); + } + + auto uriVersion = split[2][countUntil!"a != b"(split[2], ' ') .. $]; + if (!canFind(uriVersion, ' ')) { + throw new TTransportException("Bad status: " ~ to!string(status), + TTransportException.Type.CORRUPTED_DATA); + } + + if (split[0] == "GET") { + // GET method ok, looking for content. + return true; + } + + throw new TTransportException("Bad status (unsupported method): " ~ + to!string(status), TTransportException.Type.CORRUPTED_DATA); + } + +private: + @property bool handshakeComplete() { + return upgrade_ && connection_ && secWebSocketKey_ && secWebSocketVersion_; + } + + void failConnection(CloseCode reason) { + writeFrameHeader(Opcode.Close); + transport_.write(nativeToBigEndian!ushort(reason)); + transport_.flush(); + transport_.close(); + } + + void pong() { + writeFrameHeader(Opcode.Pong); + transport_.write(readBuffer_); + transport_.flush(); + } + + bool readFrame() { + ubyte[8] headerBuffer; + + auto read = transport_.read(headerBuffer[0..2]); + if (read < 2) { + return false; + } + // Since Thrift has its own message end marker and we read frame by frame, + // it doesn't really matter if the frame is marked as FIN. + // Capture it only for debugging only. + debug auto fin = (headerBuffer[0] & 0x80) != 0; + + // RSV1, RSV2, RSV3 + if ((headerBuffer[0] & 0x70) != 0) { + failConnection(CloseCode.ProtocolError); + throw new TTransportException("Reserved bits must be zeroes", TTransportException.Type.CORRUPTED_DATA); + } + + Opcode opcode; + try { + opcode = to!Opcode(headerBuffer[0] & 0x0F); + } catch (ConvException) { + failConnection(CloseCode.ProtocolError); + throw new TTransportException("Unknown opcode", TTransportException.Type.CORRUPTED_DATA); + } + + // Mask + if ((headerBuffer[1] & 0x80) == 0) { + failConnection(CloseCode.ProtocolError); + throw new TTransportException("Messages from the client must be masked", TTransportException.Type.CORRUPTED_DATA); + } + + // Read the length + ulong payloadLength = headerBuffer[1] & 0x7F; + if (payloadLength == 126) { + read = transport_.read(headerBuffer[0..2]); + if (read < 2) { + return false; + } + payloadLength = bigEndianToNative!ushort(headerBuffer[0..2]); + } else if (payloadLength == 127) { + read = transport_.read(headerBuffer); + if (read < headerBuffer.length) { + return false; + } + payloadLength = bigEndianToNative!ulong(headerBuffer); + if ((payloadLength & 0x8000000000000000) != 0) { + failConnection(CloseCode.ProtocolError); + throw new TTransportException("The most significant bit of the payload length must be zero", + TTransportException.Type.CORRUPTED_DATA); + } + } + + // size_t is smaller than a ulong on a 32-bit system + static if (size_t.max < ulong.max) { + if(payloadLength > size_t.max) { + failConnection(CloseCode.MessageTooBig); + return false; + } + } + + auto length = cast(size_t)payloadLength; + + if (length > 0) { + // Read the masking key + read = transport_.read(headerBuffer[0..4]); + if (read < 4) { + return false; + } + + readBuffer_ = new ubyte[](length); + read = transport_.read(readBuffer_); + if (read < length) { + return false; + } + + // Unmask the data + for (size_t i = 0; i < length; i++) { + readBuffer_[i] ^= headerBuffer[i % 4]; + } + + debug writef("FIN=%d, Opcode=%X, length=%d, payload=%s\n", + fin, + opcode, + length, + binary ? readBuffer_.toHexString() : cast(string)readBuffer_); + } + + switch (opcode) { + case Opcode.Close: + debug { + if (length >= 2) { + CloseCode closeCode; + try { + closeCode = to!CloseCode(bigEndianToNative!ushort(readBuffer_[0..2])); + } catch (ConvException) { + closeCode = CloseCode.NoStatusCode; + } + + string closeReason; + if (length == 2) { + closeReason = to!string(cast(CloseCode)closeCode); + } else { + closeReason = cast(string)readBuffer_[2..$]; + } + + writef("Connection closed: %d %s\n", closeCode, closeReason); + } + } + transport_.close(); + return false; + case Opcode.Ping: + pong(); + return readFrame(); + default: + return true; + } + } + + void resetHandshake() { + connection_ = false; + secWebSocketKey_ = false; + secWebSocketVersion_ = false; + upgrade_ = false; + } + + void sendBadRequest() { + auto header = "HTTP/1.1 400 Bad Request\r\n" ~ + "Server: Thrift/" ~ VERSION ~ "\r\n" ~ + "\r\n"; + transport_.write(cast(const(ubyte[]))header); + transport_.flush(); + transport_.close(); + } + + void writeFrameHeader(Opcode opcode = Opcode.Continuation) { + size_t headerSize = 1; + if (writeBuffer_.length < 126) { + ++headerSize; + } else if (writeBuffer_.length < 65536) { + headerSize += 3; + } else { + headerSize += 9; + } + // The server does not mask the response + + ubyte[] header = new ubyte[headerSize]; + if (opcode == Opcode.Continuation) { + header[0] = binary ? Opcode.Binary : Opcode.Text; + } + else { + header[0] = opcode; + } + header[0] |= 0x80; + if (writeBuffer_.length < 126) { + header[1] = cast(ubyte)writeBuffer_.length; + } else if (writeBuffer_.length < 65536) { + header[1] = 126; + header[2..4] = nativeToBigEndian(cast(ushort)writeBuffer_.length); + } else { + header[1] = 127; + header[2..10] = nativeToBigEndian(cast(ulong)writeBuffer_.length); + } + + transport_.write(header); + } + + enum WEBSOCKET_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + + TTransport transport_; + + string acceptKey_; + bool connection_; + bool secWebSocketKey_; + bool secWebSocketVersion_; + bool upgrade_; + ubyte[] readBuffer_; + ubyte[] writeBuffer_; +} + +class TServerWebSocketTransportFactory(bool binary) : TTransportFactory { + override TTransport getTransport(TTransport trans) { + return new TServerWebSocketTransport!binary(trans); + } +} + +alias TServerBinaryWebSocketTransportFactory = TServerWebSocketTransportFactory!true; +alias TServerTextWebSocketTransportFactory = TServerWebSocketTransportFactory!false; + +private enum CloseCode : ushort { + NormalClosure = 1000, + GoingAway = 1001, + ProtocolError = 1002, + UnsupportedDataType = 1003, + NoStatusCode = 1005, + AbnormalClosure = 1006, + InvalidData = 1007, + PolicyViolation = 1008, + MessageTooBig = 1009, + ExtensionExpected = 1010, + UnexpectedError = 1011, + NotSecure = 1015 +} + +private enum Opcode : ubyte { + Continuation = 0x0, + Text = 0x1, + Binary = 0x2, + Close = 0x8, + Ping = 0x9, + Pong = 0xA +} From daa7669a7665539a484815a7d5200651ba74df9a Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Fri, 10 Apr 2020 14:27:27 +0800 Subject: [PATCH 550/756] Update Thrift's latest branch status in README.md Patch: zeshuai007 <51382517@qq.com> This closes #2097 --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 4bd2366139e..ff573215fd1 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ Status | Branch | Travis | Appveyor | Coverity Scan | codecov.io | Website | | :----- | :----- | :------- | :------------ | :--------- | :------ | | [`master`](https://github.com/apache/thrift/tree/master) | [![Build Status](https://travis-ci.org/apache/thrift.svg?branch=master)](https://travis-ci.org/apache/thrift/branches) | [![Build status](https://ci.appveyor.com/api/projects/status/github/apache/thrift?branch=master&svg=true)](https://ci.appveyor.com/project/ApacheSoftwareFoundation/thrift/history) | [![Coverity Scan Build Status](https://scan.coverity.com/projects/1345/badge.svg)](https://scan.coverity.com/projects/thrift) | | [![Website](https://img.shields.io/badge/official-website-brightgreen.svg)](https://thrift.apache.org/) | +| [`0.13.0`](https://github.com/apache/thrift/tree/0.13.0) | [![Build Status](https://travis-ci.org/apache/thrift.svg?branch=0.13.0)](https://travis-ci.org/apache/thrift/branches) | | | | | | [`0.12.0`](https://github.com/apache/thrift/tree/0.12.0) | [![Build Status](https://travis-ci.org/apache/thrift.svg?branch=0.12.0)](https://travis-ci.org/apache/thrift/branches) | | | | | Releases From 69642f389a06f5ba1b374de52c6b0e29892035d8 Mon Sep 17 00:00:00 2001 From: Joao Antonio Date: Sat, 4 Apr 2020 15:39:03 +0100 Subject: [PATCH 551/756] THRIFT-5165: THttpClient saves session cookie. Client: py Patch: Joao Antonio This closes #2086 --- lib/py/src/transport/THttpClient.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/py/src/transport/THttpClient.py b/lib/py/src/transport/THttpClient.py index 37b0a4d8ddc..212da3aa50c 100644 --- a/lib/py/src/transport/THttpClient.py +++ b/lib/py/src/transport/THttpClient.py @@ -185,3 +185,7 @@ def flush(self): self.code = self.__http_response.status self.message = self.__http_response.reason self.headers = self.__http_response.msg + + # Saves the cookie sent by the server response + if 'Set-Cookie' in self.headers: + self.__http.putheader('Cookie', self.headers['Set-Cookie']) From 81334cd7345d3b5af165aa875b733a491f1fd5c7 Mon Sep 17 00:00:00 2001 From: lvqian Date: Thu, 26 Mar 2020 19:08:55 +0800 Subject: [PATCH 552/756] THRIFT-5152: introduce connect timeout and socket timeout Client: Go Patch: Qian Lv This closes #2071 --- .../test/tests/multiplexed_protocol_test.go | 2 +- lib/go/test/tests/one_way_test.go | 2 +- lib/go/test/tests/protocols_test.go | 2 +- lib/go/thrift/socket.go | 37 +++++++++++-------- 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/lib/go/test/tests/multiplexed_protocol_test.go b/lib/go/test/tests/multiplexed_protocol_test.go index 61ac62828d4..4fb6f4f4d17 100644 --- a/lib/go/test/tests/multiplexed_protocol_test.go +++ b/lib/go/test/tests/multiplexed_protocol_test.go @@ -50,7 +50,7 @@ func (s *SecondImpl) ReturnTwo(ctx context.Context) (r int64, err error) { } func createTransport(addr net.Addr) (thrift.TTransport, error) { - socket := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT) + socket := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT, TIMEOUT) transport := thrift.NewTFramedTransport(socket) err := transport.Open() if err != nil { diff --git a/lib/go/test/tests/one_way_test.go b/lib/go/test/tests/one_way_test.go index 48d0bbe3890..010e3bb6ae9 100644 --- a/lib/go/test/tests/one_way_test.go +++ b/lib/go/test/tests/one_way_test.go @@ -65,7 +65,7 @@ func TestInitOneway(t *testing.T) { } func TestInitOnewayClient(t *testing.T) { - transport := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT) + transport := thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT, TIMEOUT) protocol := thrift.NewTBinaryProtocolTransport(transport) client = onewaytest.NewOneWayClient(thrift.NewTStandardClient(protocol, protocol)) err := transport.Open() diff --git a/lib/go/test/tests/protocols_test.go b/lib/go/test/tests/protocols_test.go index cffd9c3f7e9..9030e9d5a31 100644 --- a/lib/go/test/tests/protocols_test.go +++ b/lib/go/test/tests/protocols_test.go @@ -41,7 +41,7 @@ func RunSocketTestSuite(t *testing.T, protocolFactory thrift.TProtocolFactory, go server.Serve() // client - var transport thrift.TTransport = thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT) + var transport thrift.TTransport = thrift.NewTSocketFromAddrTimeout(addr, TIMEOUT, TIMEOUT) transport, err = transportFactory.GetTransport(transport) if err != nil { t.Fatal(err) diff --git a/lib/go/thrift/socket.go b/lib/go/thrift/socket.go index 88b98f59164..558818a9a76 100644 --- a/lib/go/thrift/socket.go +++ b/lib/go/thrift/socket.go @@ -26,9 +26,10 @@ import ( ) type TSocket struct { - conn net.Conn - addr net.Addr - timeout time.Duration + conn net.Conn + addr net.Addr + connectTimeout time.Duration + socketTimeout time.Duration } // NewTSocket creates a net.Conn-backed TTransport, given a host and port @@ -36,40 +37,46 @@ type TSocket struct { // Example: // trans, err := thrift.NewTSocket("localhost:9090") func NewTSocket(hostPort string) (*TSocket, error) { - return NewTSocketTimeout(hostPort, 0) + return NewTSocketTimeout(hostPort, 0, 0) } // NewTSocketTimeout creates a net.Conn-backed TTransport, given a host and port // it also accepts a timeout as a time.Duration -func NewTSocketTimeout(hostPort string, timeout time.Duration) (*TSocket, error) { +func NewTSocketTimeout(hostPort string, connTimeout time.Duration, soTimeout time.Duration) (*TSocket, error) { //conn, err := net.DialTimeout(network, address, timeout) addr, err := net.ResolveTCPAddr("tcp", hostPort) if err != nil { return nil, err } - return NewTSocketFromAddrTimeout(addr, timeout), nil + return NewTSocketFromAddrTimeout(addr, connTimeout, soTimeout), nil } // Creates a TSocket from a net.Addr -func NewTSocketFromAddrTimeout(addr net.Addr, timeout time.Duration) *TSocket { - return &TSocket{addr: addr, timeout: timeout} +func NewTSocketFromAddrTimeout(addr net.Addr, connTimeout time.Duration, soTimeout time.Duration) *TSocket { + return &TSocket{addr: addr, connectTimeout: connTimeout, socketTimeout: soTimeout} } // Creates a TSocket from an existing net.Conn -func NewTSocketFromConnTimeout(conn net.Conn, timeout time.Duration) *TSocket { - return &TSocket{conn: conn, addr: conn.RemoteAddr(), timeout: timeout} +func NewTSocketFromConnTimeout(conn net.Conn, connTimeout time.Duration) *TSocket { + return &TSocket{conn: conn, addr: conn.RemoteAddr(), connectTimeout: connTimeout, socketTimeout: connTimeout} +} + +// Sets the connect timeout +func (p *TSocket) SetConnTimeout(timeout time.Duration) error { + p.connectTimeout = timeout + return nil } // Sets the socket timeout -func (p *TSocket) SetTimeout(timeout time.Duration) error { - p.timeout = timeout +func (p *TSocket) SetSocketTimeout(timeout time.Duration) error { + p.socketTimeout = timeout return nil } func (p *TSocket) pushDeadline(read, write bool) { var t time.Time - if p.timeout > 0 { - t = time.Now().Add(time.Duration(p.timeout)) + if p.socketTimeout > 0 { + t = time.Now().Add(time.Duration(p.socketTimeout)) } if read && write { p.conn.SetDeadline(t) @@ -95,7 +102,7 @@ func (p *TSocket) Open() error { return NewTTransportException(NOT_OPEN, "Cannot open bad address.") } var err error - if p.conn, err = net.DialTimeout(p.addr.Network(), p.addr.String(), p.timeout); err != nil { + if p.conn, err = net.DialTimeout(p.addr.Network(), p.addr.String(), p.connectTimeout); err != nil { return NewTTransportException(NOT_OPEN, err.Error()) } return nil From 5f352754225158f60594a5f19ba8d03261854327 Mon Sep 17 00:00:00 2001 From: wangyunjian Date: Sun, 29 Mar 2020 10:56:20 +0800 Subject: [PATCH 553/756] THRIFT-5157 Fix memory leak in c_glib unit tests Client: c_glib Patch: wangyunjian Signed-off-by: wangyunjian --- test/c_glib/src/test_client.c | 81 +++++++++++++-------------- test/c_glib/src/test_server.c | 4 +- test/c_glib/src/thrift_test_handler.c | 28 ++++----- 3 files changed, 57 insertions(+), 56 deletions(-) diff --git a/test/c_glib/src/test_client.c b/test/c_glib/src/test_client.c index 7126a86d8a6..76e0ad746c1 100644 --- a/test/c_glib/src/test_client.c +++ b/test/c_glib/src/test_client.c @@ -75,39 +75,6 @@ gint32_compare (gconstpointer a, gconstpointer b) return result; } -/** - * It gets a multiplexed protocol which uses a concrete protocol underneath - * @param protocol_name the fully qualified protocol path (e.g. "binary:multi") - * @param transport the underlying transport - * @param service_name the single supported service name - * @todo need to allow multiple services to fully test multiplexed - * @return a multiplexed protocol wrapping the correct underlying protocol - */ -ThriftProtocol * -get_multiplexed_protocol(gchar *protocol_name, ThriftTransport *transport, gchar *service_name) -{ - ThriftProtocol * multiplexed_protocol = NULL; - - if ( strncmp(protocol_name, "binary:", 7) == 0) { - multiplexed_protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, - "transport", transport, - NULL); - } else if ( strncmp(protocol_name, "compact:", 8) == 0) { - multiplexed_protocol = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, - "transport", transport, - NULL); - } else { - fprintf(stderr, "Unknown multiplex protocol name: %s\n", protocol_name); - return NULL; - } - - return g_object_new (THRIFT_TYPE_MULTIPLEXED_PROTOCOL, - "transport", transport, - "protocol", multiplexed_protocol, - "service-name", service_name, - NULL); -} - int main (int argc, char **argv) { @@ -151,6 +118,7 @@ main (int argc, char **argv) ThriftTransport *transport = NULL; ThriftProtocol *protocol = NULL; ThriftProtocol *protocol2 = NULL; // for multiplexed tests + ThriftProtocol *multiplexed_protocol = NULL; TTestThriftTestIf *test_client = NULL; TTestSecondServiceIf *second_service = NULL; // for multiplexed tests @@ -179,6 +147,8 @@ main (int argc, char **argv) &argv, &error)) { fprintf (stderr, "%s\n", error->message); + g_clear_error (&error); + g_option_context_free (option_context); return 255; } g_option_context_free (option_context); @@ -279,24 +249,47 @@ main (int argc, char **argv) "transport", socket, NULL); - if(protocol_type==THRIFT_TYPE_MULTIPLEXED_PROTOCOL) { + if (protocol_type == THRIFT_TYPE_MULTIPLEXED_PROTOCOL) { // TODO: A multiplexed test should also test "Second" (see Java TestServer) // The context comes from the name of the thrift file. If multiple thrift // schemas are used we have to redo the way this is done. - protocol = get_multiplexed_protocol(protocol_name, transport, "ThriftTest"); - if (NULL == protocol) { + if (strncmp(protocol_name, "binary:", 7) == 0) { + multiplexed_protocol = g_object_new (THRIFT_TYPE_BINARY_PROTOCOL, + "transport", transport, + NULL); + } else if (strncmp(protocol_name, "compact:", 8) == 0) { + multiplexed_protocol = g_object_new (THRIFT_TYPE_COMPACT_PROTOCOL, + "transport", transport, + NULL); + } else { + fprintf(stderr, "Unknown multiplex protocol name: %s\n", protocol_name); g_clear_object (&transport); g_clear_object (&socket); return 252; } + protocol = g_object_new (THRIFT_TYPE_MULTIPLEXED_PROTOCOL, + "transport", transport, + "protocol", multiplexed_protocol, + "service-name", "ThriftTest", + NULL);; + if (NULL == protocol) { + g_clear_object (&multiplexed_protocol); + g_clear_object (&transport); + g_clear_object (&socket); + return 251; + } // Make a second protocol and client running on the same multiplexed transport - protocol2 = get_multiplexed_protocol(protocol_name, transport, "SecondService"); - second_service = g_object_new (T_TEST_TYPE_SECOND_SERVICE_CLIENT, - "input_protocol", protocol2, - "output_protocol", protocol2, - NULL); + protocol2 = g_object_new (THRIFT_TYPE_MULTIPLEXED_PROTOCOL, + "transport", transport, + "protocol", multiplexed_protocol, + "service-name", "SecondService", + NULL); + second_service = g_object_new (T_TEST_TYPE_SECOND_SERVICE_CLIENT, + "input_protocol", protocol2, + "output_protocol", protocol2, + NULL); }else{ protocol = g_object_new (protocol_type, "transport", transport, @@ -1374,6 +1367,8 @@ main (int argc, char **argv) byte_thing, i32_thing, i64_thing); + if (string != NULL) + g_free (string); } printf ("}"); g_ptr_array_unref (xtructs); @@ -1796,7 +1791,7 @@ main (int argc, char **argv) g_error_free (error); error = NULL; - return 1; + goto out; } } @@ -1810,10 +1805,12 @@ main (int argc, char **argv) printf ("Max time: %" PRIu64 " us\n", time_max_usec); printf ("Avg time: %" PRIu64 " us\n", time_avg_usec); +out: g_clear_object(&second_service); g_clear_object(&protocol2); g_clear_object(&test_client); g_clear_object(&protocol); + g_clear_object(&multiplexed_protocol); g_clear_object(&transport); g_clear_object(&socket); diff --git a/test/c_glib/src/test_server.c b/test/c_glib/src/test_server.c index 0819b8ca54c..c949530de01 100644 --- a/test/c_glib/src/test_server.c +++ b/test/c_glib/src/test_server.c @@ -131,6 +131,8 @@ main (int argc, char **argv) &argv, &error) == FALSE) { fprintf (stderr, "%s\n", error->message); + g_clear_error (&error); + g_option_context_free (option_context); return 255; } g_option_context_free (option_context); @@ -282,11 +284,11 @@ main (int argc, char **argv) if (!sigint_received) { g_message ("thrift_server_serve: %s", error != NULL ? error->message : "(null)"); - g_clear_error (&error); } puts ("done."); + g_clear_error (&error); g_object_unref (server); g_object_unref (protocol_factory); g_object_unref (transport_factory); diff --git a/test/c_glib/src/thrift_test_handler.c b/test/c_glib/src/thrift_test_handler.c index f6c759e1a3a..ccfd6c279bf 100644 --- a/test/c_glib/src/thrift_test_handler.c +++ b/test/c_glib/src/thrift_test_handler.c @@ -367,7 +367,7 @@ thrift_test_handler_test_list (TTestThriftTestIf *iface, printf ("testList({"); for (i = 0; i < thing->len; i += 1) { gint32 value; - gint32 *new_value; + gint32 new_value; if (first) first = FALSE; @@ -377,9 +377,8 @@ thrift_test_handler_test_list (TTestThriftTestIf *iface, value = g_array_index (thing, gint32, i); printf ("%d", value); - new_value = g_malloc (sizeof *new_value); - *new_value = value; - g_array_append_val (*_return, *new_value); + new_value = value; + g_array_append_val (*_return, new_value); } printf ("})\n"); @@ -591,6 +590,9 @@ thrift_test_handler_test_insanity (TTestThriftTestIf *iface, byte_thing, i32_thing, i64_thing); + if (string_thing != NULL) { + g_free (string_thing); + } } printf ("}"); g_ptr_array_unref (xtructs); @@ -624,10 +626,10 @@ thrift_test_handler_test_multi (TTestThriftTestIf *iface, printf ("testMulti()\n"); g_object_set (*_return, - "string_thing", g_strdup ("Hello2"), - "byte_thing", arg0, - "i32_thing", arg1, - "i64_thing", arg2, + "string_thing", "Hello2", + "byte_thing", arg0, + "i32_thing", arg1, + "i64_thing", arg2, NULL); return TRUE; @@ -654,7 +656,7 @@ thrift_test_handler_test_exception (TTestThriftTestIf *iface, argument, set *error to NULL and return FALSE */ *err1 = g_object_new (T_TEST_TYPE_XCEPTION, "errorCode", 1001, - "message", g_strdup (arg), + "message", arg, NULL); *error = NULL; result = FALSE; @@ -676,7 +678,7 @@ thrift_test_handler_test_exception (TTestThriftTestIf *iface, /* This code is duplicated from the C++ test suite, though it appears to serve no purpose */ xtruct = g_object_new (T_TEST_TYPE_XTRUCT, - "string_thing", g_strdup (arg), + "string_thing", arg, NULL); g_object_unref (xtruct); @@ -709,7 +711,7 @@ thrift_test_handler_test_multi_exception (TTestThriftTestIf *iface, if (strncmp (arg0, "Xception", 8) == 0 && strlen(arg0) == 8) { *err1 = g_object_new (T_TEST_TYPE_XCEPTION, "errorCode", 1001, - "message", g_strdup ("This is an Xception"), + "message", "This is an Xception", NULL); result = FALSE; } @@ -722,7 +724,7 @@ thrift_test_handler_test_multi_exception (TTestThriftTestIf *iface, "struct_thing", &struct_thing, NULL); g_object_set (struct_thing, - "string_thing", g_strdup ("This is an Xception2"), + "string_thing", "This is an Xception2", NULL); g_object_set (*err2, "struct_thing", struct_thing, @@ -733,7 +735,7 @@ thrift_test_handler_test_multi_exception (TTestThriftTestIf *iface, } else { g_object_set (*_return, - "string_thing", g_strdup (arg1), + "string_thing", arg1, NULL); result = TRUE; } From 9e864d57026b4905862108418ba9482892fb1f65 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Fri, 17 Apr 2020 11:53:39 -0700 Subject: [PATCH 554/756] Add UnsetHeader to go library Client: go We already have SetHeader and GetHeader helper functions in the go library to deal with THeader injected into the context object. But we didn't provide a way to unset/delete a key from the context object. This will be useful with the TSimpleServer.SetForwardHeaders API. In the scenario that a thrift server want to auto forward certain headers to other upstream thrift servers as the fallback, but during the handling of the request might decide to remove some of the auto forward headers. This is also achievable through mutate the write header list, but since that's a list, finding one key from the list and remove it is much more hassle. --- lib/go/thrift/header_context.go | 9 +++++++++ lib/go/thrift/header_context_test.go | 13 ++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/go/thrift/header_context.go b/lib/go/thrift/header_context.go index 21e880d66c2..ac9bd4882be 100644 --- a/lib/go/thrift/header_context.go +++ b/lib/go/thrift/header_context.go @@ -44,6 +44,15 @@ func SetHeader(ctx context.Context, key, value string) context.Context { ) } +// UnsetHeader unsets a previously set header in the context. +func UnsetHeader(ctx context.Context, key string) context.Context { + return context.WithValue( + ctx, + headerKey(key), + nil, + ) +} + // GetHeader returns a value of the given header from the context. func GetHeader(ctx context.Context, key string) (value string, ok bool) { if v := ctx.Value(headerKey(key)); v != nil { diff --git a/lib/go/thrift/header_context_test.go b/lib/go/thrift/header_context_test.go index a1ea2d0930b..16b10c85898 100644 --- a/lib/go/thrift/header_context_test.go +++ b/lib/go/thrift/header_context_test.go @@ -25,7 +25,7 @@ import ( "testing" ) -func TestSetGetHeader(t *testing.T) { +func TestSetGetUnsetHeader(t *testing.T) { const ( key = "foo" value = "bar" @@ -68,6 +68,17 @@ func TestSetGetHeader(t *testing.T) { } }, ) + + t.Run( + "Unset", + func(t *testing.T) { + ctx := UnsetHeader(ctx, key) + + if _, ok := GetHeader(ctx, key); ok { + t.Errorf("GetHeader returned ok on unset key %q", key) + } + }, + ) } func TestReadKeyList(t *testing.T) { From 35a3942e7078bc55cd21890b12d206d9bf0514d3 Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Fri, 17 Apr 2020 11:14:01 +0800 Subject: [PATCH 555/756] Update libthrift.vcxproj and libthrift.vcxproj.filters: remove xxxThreadFactory.h file which has been removed Client: cpp Patch: zeshuai007 <51382517@qq.com> This closes #2100 --- lib/cpp/libthrift.vcxproj | 5 ----- lib/cpp/libthrift.vcxproj.filters | 15 --------------- 2 files changed, 20 deletions(-) diff --git a/lib/cpp/libthrift.vcxproj b/lib/cpp/libthrift.vcxproj index d1097ecd333..52af26aa718 100644 --- a/lib/cpp/libthrift.vcxproj +++ b/lib/cpp/libthrift.vcxproj @@ -39,8 +39,6 @@ - - @@ -81,10 +79,7 @@ - - - diff --git a/lib/cpp/libthrift.vcxproj.filters b/lib/cpp/libthrift.vcxproj.filters index 5f64f78cb4e..0e9a9fde1c2 100644 --- a/lib/cpp/libthrift.vcxproj.filters +++ b/lib/cpp/libthrift.vcxproj.filters @@ -96,12 +96,6 @@ concurrency - - concurrency - - - concurrency - windows @@ -227,15 +221,6 @@ windows - - concurrency - - - concurrency - - - concurrency - windows From dd7e11798ba524f7ae6204b68f073ee696deb595 Mon Sep 17 00:00:00 2001 From: gaganso Date: Mon, 20 Apr 2020 03:20:05 +0200 Subject: [PATCH 556/756] Removed a duplicate line + Fixed typo in the comments of lib/cpp/src/thrift/concurrency/Thread.h Client: cpp Patch: gaganso This closes #2104 --- lib/cpp/src/thrift/concurrency/Thread.h | 2 +- lib/cpp/src/thrift/server/TNonblockingServer.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/cpp/src/thrift/concurrency/Thread.h b/lib/cpp/src/thrift/concurrency/Thread.h index e803a82ce78..ed43754dfd5 100644 --- a/lib/cpp/src/thrift/concurrency/Thread.h +++ b/lib/cpp/src/thrift/concurrency/Thread.h @@ -63,7 +63,7 @@ class Runnable { * and ready to start execution. More or less analogous to java.lang.Thread * (minus all the thread group, priority, mode and other baggage, since that * is difficult to abstract across platforms and is left for platform-specific - * ThreadFactory implemtations to deal with + * ThreadFactory implementations to deal with * * @see apache::thrift::concurrency::ThreadFactory) */ diff --git a/lib/cpp/src/thrift/server/TNonblockingServer.h b/lib/cpp/src/thrift/server/TNonblockingServer.h index 82bc375bd6e..e44c7ee4cbb 100644 --- a/lib/cpp/src/thrift/server/TNonblockingServer.h +++ b/lib/cpp/src/thrift/server/TNonblockingServer.h @@ -54,7 +54,6 @@ using apache::thrift::protocol::TProtocol; using apache::thrift::concurrency::Runnable; using apache::thrift::concurrency::ThreadManager; using apache::thrift::concurrency::ThreadFactory; -using apache::thrift::concurrency::ThreadFactory; using apache::thrift::concurrency::Thread; using apache::thrift::concurrency::Mutex; using apache::thrift::concurrency::Guard; From 57c2507208aede3ec60c7bab50aaeb093fe44eca Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Thu, 9 Apr 2020 11:17:05 +0800 Subject: [PATCH 557/756] THRIFT-5168 Useless generated code when .thrift file only has service type Client: cpp Patch: zeshuai007 <51382517@qq.com> This closes #2095 --- .../src/thrift/generate/t_cpp_generator.cc | 98 +++++++++++-------- lib/cpp/test/CMakeLists.txt | 3 +- lib/cpp/test/Makefile.am | 6 +- test/cpp/CMakeLists.txt | 4 +- test/cpp/Makefile.am | 7 +- tutorial/cpp/CMakeLists.txt | 3 +- tutorial/cpp/Makefile.am | 4 +- 7 files changed, 63 insertions(+), 62 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc index 372014dad53..c2d88cdcde8 100644 --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc @@ -68,6 +68,7 @@ class t_cpp_generator : public t_oop_generator { gen_moveable_ = false; gen_no_ostream_operators_ = false; gen_no_skeleton_ = false; + has_members_ = false; for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) { if( iter->first.compare("pure_enums") == 0) { @@ -357,6 +358,11 @@ class t_cpp_generator : public t_oop_generator { */ bool gen_no_skeleton_; + /** + * True if thrift has member(s) + */ + bool has_members_; + /** * Strings for namespace, computed once up front then used directly */ @@ -505,6 +511,12 @@ void t_cpp_generator::close_generator() { f_types_.close(); f_types_impl_.close(); f_types_tcc_.close(); + + string f_types_impl_name = get_out_dir() + program_name_ + "_types.cpp"; + + if (!has_members_) { + remove(f_types_impl_name.c_str()); + } } /** @@ -693,55 +705,57 @@ void t_cpp_generator::generate_enum_to_string_helper_function(std::ostream& out, void t_cpp_generator::generate_consts(std::vector consts) { string f_consts_name = get_out_dir() + program_name_ + "_constants.h"; ofstream_with_content_based_conditional_update f_consts; - f_consts.open(f_consts_name); + if (consts.size() > 0) { + f_consts.open(f_consts_name); - string f_consts_impl_name = get_out_dir() + program_name_ + "_constants.cpp"; - ofstream_with_content_based_conditional_update f_consts_impl; - f_consts_impl.open(f_consts_impl_name); + string f_consts_impl_name = get_out_dir() + program_name_ + "_constants.cpp"; + ofstream_with_content_based_conditional_update f_consts_impl; + f_consts_impl.open(f_consts_impl_name); - // Print header - f_consts << autogen_comment(); - f_consts_impl << autogen_comment(); + // Print header + f_consts << autogen_comment(); + f_consts_impl << autogen_comment(); - // Start ifndef - f_consts << "#ifndef " << program_name_ << "_CONSTANTS_H" << endl << "#define " << program_name_ - << "_CONSTANTS_H" << endl << endl << "#include \"" << get_include_prefix(*get_program()) - << program_name_ << "_types.h\"" << endl << endl << ns_open_ << endl << endl; + // Start ifndef + f_consts << "#ifndef " << program_name_ << "_CONSTANTS_H" << endl << "#define " << program_name_ + << "_CONSTANTS_H" << endl << endl << "#include \"" << get_include_prefix(*get_program()) + << program_name_ << "_types.h\"" << endl << endl << ns_open_ << endl << endl; - f_consts_impl << "#include \"" << get_include_prefix(*get_program()) << program_name_ - << "_constants.h\"" << endl << endl << ns_open_ << endl << endl; + f_consts_impl << "#include \"" << get_include_prefix(*get_program()) << program_name_ + << "_constants.h\"" << endl << endl << ns_open_ << endl << endl; - f_consts << "class " << program_name_ << "Constants {" << endl << " public:" << endl << " " - << program_name_ << "Constants();" << endl << endl; - indent_up(); - vector::iterator c_iter; - for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { - string name = (*c_iter)->get_name(); - t_type* type = (*c_iter)->get_type(); - f_consts << indent() << type_name(type) << " " << name << ";" << endl; - } - indent_down(); - f_consts << "};" << endl; + f_consts << "class " << program_name_ << "Constants {" << endl << " public:" << endl << " " + << program_name_ << "Constants();" << endl << endl; + indent_up(); + vector::iterator c_iter; + for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { + string name = (*c_iter)->get_name(); + t_type* type = (*c_iter)->get_type(); + f_consts << indent() << type_name(type) << " " << name << ";" << endl; + } + indent_down(); + f_consts << "};" << endl; - f_consts_impl << "const " << program_name_ << "Constants g_" << program_name_ << "_constants;" - << endl << endl << program_name_ << "Constants::" << program_name_ - << "Constants() {" << endl; - indent_up(); - for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { - print_const_value(f_consts_impl, - (*c_iter)->get_name(), - (*c_iter)->get_type(), - (*c_iter)->get_value()); - } - indent_down(); - indent(f_consts_impl) << "}" << endl; + f_consts_impl << "const " << program_name_ << "Constants g_" << program_name_ << "_constants;" + << endl << endl << program_name_ << "Constants::" << program_name_ + << "Constants() {" << endl; + indent_up(); + for (c_iter = consts.begin(); c_iter != consts.end(); ++c_iter) { + print_const_value(f_consts_impl, + (*c_iter)->get_name(), + (*c_iter)->get_type(), + (*c_iter)->get_value()); + } + indent_down(); + indent(f_consts_impl) << "}" << endl; - f_consts << endl << "extern const " << program_name_ << "Constants g_" << program_name_ - << "_constants;" << endl << endl << ns_close_ << endl << endl << "#endif" << endl; - f_consts.close(); + f_consts << endl << "extern const " << program_name_ << "Constants g_" << program_name_ + << "_constants;" << endl << endl << ns_close_ << endl << endl << "#endif" << endl; + f_consts.close(); - f_consts_impl << endl << ns_close_ << endl << endl; - f_consts_impl.close(); + f_consts_impl << endl << ns_close_ << endl << endl; + f_consts_impl.close(); + } } /** @@ -904,6 +918,8 @@ void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) if (is_exception) { generate_exception_what_method(f_types_impl_, tstruct); } + + has_members_ = true; } void t_cpp_generator::generate_copy_constructor(ostream& out, diff --git a/lib/cpp/test/CMakeLists.txt b/lib/cpp/test/CMakeLists.txt index fba15f6c07f..48e2fd375cc 100644 --- a/lib/cpp/test/CMakeLists.txt +++ b/lib/cpp/test/CMakeLists.txt @@ -42,7 +42,6 @@ set(testgencpp_SOURCES gen-cpp/Recursive_types.h gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_types.h - gen-cpp/OneWayTest_types.cpp gen-cpp/OneWayTest_types.h gen-cpp/OneWayService.cpp gen-cpp/OneWayService.h @@ -392,7 +391,7 @@ add_custom_command(OUTPUT gen-cpp/SecondService.cpp gen-cpp/ThriftTest_constants COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift ) -add_custom_command(OUTPUT gen-cpp/OneWayService.cpp gen-cpp/OneWayTest_constants.cpp gen-cpp/OneWayTest_types.h gen-cpp/OneWayService.h gen-cpp/OneWayTest_constants.h gen-cpp/OneWayTest_types.cpp +add_custom_command(OUTPUT gen-cpp/OneWayService.cpp gen-cpp/OneWayTest_types.h gen-cpp/OneWayService.h COMMAND ${THRIFT_COMPILER} --gen cpp ${CMAKE_CURRENT_SOURCE_DIR}/OneWayTest.thrift ) diff --git a/lib/cpp/test/Makefile.am b/lib/cpp/test/Makefile.am index 8399d9eb5b0..89826839df7 100755 --- a/lib/cpp/test/Makefile.am +++ b/lib/cpp/test/Makefile.am @@ -30,7 +30,6 @@ BUILT_SOURCES = gen-cpp/AnnotationTest_types.h \ gen-cpp/ParentService.h \ gen-cpp/OneWayTest_types.h \ gen-cpp/OneWayService.h \ - gen-cpp/OneWayTest_constants.h \ gen-cpp/proc_types.h noinst_LTLIBRARIES = libtestgencpp.la libprocessortest.la @@ -54,11 +53,8 @@ nodist_libtestgencpp_la_SOURCES = \ gen-cpp/TypedefTest_types.cpp \ gen-cpp/TypedefTest_types.h \ gen-cpp/OneWayService.cpp \ - gen-cpp/OneWayTest_constants.cpp \ gen-cpp/OneWayTest_types.h \ gen-cpp/OneWayService.h \ - gen-cpp/OneWayTest_constants.h \ - gen-cpp/OneWayTest_types.cpp \ ThriftTest_extras.cpp \ DebugProtoTest_extras.cpp @@ -414,7 +410,7 @@ gen-cpp/Service.cpp gen-cpp/StressTest_types.cpp: $(top_srcdir)/test/StressTest. gen-cpp/SecondService.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_types.h: $(top_srcdir)/test/ThriftTest.thrift $(THRIFT) --gen cpp $< -gen-cpp/OneWayService.cpp gen-cpp/OneWayTest_constants.cpp gen-cpp/OneWayTest_types.h gen-cpp/OneWayService.h gen-cpp/OneWayTest_constants.h gen-cpp/OneWayTest_types.cpp: OneWayTest.thrift +gen-cpp/OneWayService.cpp gen-cpp/OneWayTest_types.h gen-cpp/OneWayService.h: OneWayTest.thrift $(THRIFT) --gen cpp $< gen-cpp/ChildService.cpp gen-cpp/ChildService.h gen-cpp/ParentService.cpp gen-cpp/ParentService.h gen-cpp/proc_types.cpp gen-cpp/proc_types.h: processor/proc.thrift diff --git a/test/cpp/CMakeLists.txt b/test/cpp/CMakeLists.txt index 90af7826c10..a136a488700 100755 --- a/test/cpp/CMakeLists.txt +++ b/test/cpp/CMakeLists.txt @@ -52,8 +52,6 @@ LINK_AGAINST_THRIFT_LIBRARY(crosstestgencpp thrift) set(crossstressgencpp_SOURCES gen-cpp/Service.cpp - gen-cpp/StressTest_types.cpp - gen-cpp/StressTest_constants.cpp ) add_library(crossstressgencpp STATIC ${crossstressgencpp_SOURCES}) LINK_AGAINST_THRIFT_LIBRARY(crossstressgencpp thrift) @@ -92,6 +90,6 @@ add_custom_command(OUTPUT gen-cpp/SecondService.cpp gen-cpp/SecondService.h gen- COMMAND ${THRIFT_COMPILER} --gen cpp:templates,cob_style -r ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift ) -add_custom_command(OUTPUT gen-cpp/StressTest_types.cpp gen-cpp/StressTest_constants.cpp gen-cpp/Service.cpp +add_custom_command(OUTPUT gen-cpp/Service.cpp COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/StressTest.thrift ) diff --git a/test/cpp/Makefile.am b/test/cpp/Makefile.am index 76ae82bfbf9..4f77c150149 100755 --- a/test/cpp/Makefile.am +++ b/test/cpp/Makefile.am @@ -22,8 +22,6 @@ BUILT_SOURCES = gen-cpp/ThriftTest.cpp \ gen-cpp/ThriftTest_types.cpp \ gen-cpp/ThriftTest_constants.cpp \ gen-cpp/SecondService.cpp \ - gen-cpp/StressTest_types.cpp \ - gen-cpp/StressTest_constants.cpp \ gen-cpp/Service.cpp noinst_LTLIBRARIES = libtestgencpp.la libstresstestgencpp.la @@ -44,9 +42,6 @@ nodist_libtestgencpp_la_SOURCES = \ libtestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la nodist_libstresstestgencpp_la_SOURCES = \ - gen-cpp/StressTest_constants.cpp \ - gen-cpp/StressTest_types.cpp \ - gen-cpp/StressTest_constants.h \ gen-cpp/StressTest_types.h \ gen-cpp/Service.cpp \ gen-cpp/Service.h @@ -105,7 +100,7 @@ StressTestNonBlocking_LDADD = \ gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/SecondService.cpp gen-cpp/SecondService.h gen-cpp/SecondService.tcc: $(top_srcdir)/test/ThriftTest.thrift $(THRIFT) $(THRIFT) --gen cpp:templates,cob_style -r $< -gen-cpp/StressTest_types.cpp gen-cpp/StressTest_constants.cpp gen-cpp/Service.cpp: $(top_srcdir)/test/StressTest.thrift $(THRIFT) +gen-cpp/Service.cpp: $(top_srcdir)/test/StressTest.thrift $(THRIFT) $(THRIFT) --gen cpp $< AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp -I. diff --git a/tutorial/cpp/CMakeLists.txt b/tutorial/cpp/CMakeLists.txt index c6d8fc32038..b250a2c1c4b 100644 --- a/tutorial/cpp/CMakeLists.txt +++ b/tutorial/cpp/CMakeLists.txt @@ -30,7 +30,6 @@ include(ThriftMacros) set(tutorialgencpp_SOURCES gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp - gen-cpp/shared_constants.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp @@ -38,7 +37,7 @@ set(tutorialgencpp_SOURCES add_library(tutorialgencpp STATIC ${tutorialgencpp_SOURCES}) LINK_AGAINST_THRIFT_LIBRARY(tutorialgencpp thrift) -add_custom_command(OUTPUT gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_constants.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp +add_custom_command(OUTPUT gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp COMMAND ${THRIFT_COMPILER} --gen cpp -r ${PROJECT_SOURCE_DIR}/tutorial/tutorial.thrift ) diff --git a/tutorial/cpp/Makefile.am b/tutorial/cpp/Makefile.am index 95497d5f338..77fd6d579cd 100755 --- a/tutorial/cpp/Makefile.am +++ b/tutorial/cpp/Makefile.am @@ -27,8 +27,6 @@ nodist_libtutorialgencpp_la_SOURCES = \ gen-cpp/Calculator.h \ gen-cpp/SharedService.cpp \ gen-cpp/SharedService.h \ - gen-cpp/shared_constants.cpp \ - gen-cpp/shared_constants.h \ gen-cpp/shared_types.cpp \ gen-cpp/shared_types.h \ gen-cpp/tutorial_constants.cpp \ @@ -61,7 +59,7 @@ TutorialClient_LDADD = \ # # Common thrift code generation rules # -gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_constants.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp: $(top_srcdir)/tutorial/tutorial.thrift +gen-cpp/Calculator.cpp gen-cpp/SharedService.cpp gen-cpp/shared_types.cpp gen-cpp/tutorial_constants.cpp gen-cpp/tutorial_types.cpp: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen cpp -r $< AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp From df2f5d2cf321f070a356872eea13dd3f68891043 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Mon, 20 Apr 2020 14:07:54 +0200 Subject: [PATCH 558/756] THRIFT-5178: Add constructor with default host to THttpClient Client: cpp Patch: Mario Emmenlauer This closes #2105 The new default host is localhost. Also, the new default path is /service. This works around issue THRIFT-5180 where a path is required for the THttpTransport in Unix domain sockets. --- lib/cpp/src/thrift/transport/THttpClient.cpp | 4 ++++ lib/cpp/src/thrift/transport/THttpClient.h | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/cpp/src/thrift/transport/THttpClient.cpp b/lib/cpp/src/thrift/transport/THttpClient.cpp index 04566c9916d..fdee787c6a7 100644 --- a/lib/cpp/src/thrift/transport/THttpClient.cpp +++ b/lib/cpp/src/thrift/transport/THttpClient.cpp @@ -117,6 +117,10 @@ void THttpClient::flush() { writeBuffer_.resetBuffer(); readHeaders_ = true; } + +void THttpClient::setPath(std::string path) { + path_ = path; +} } } } // apache::thrift::transport diff --git a/lib/cpp/src/thrift/transport/THttpClient.h b/lib/cpp/src/thrift/transport/THttpClient.h index fdca505c864..81ddc56c5a1 100644 --- a/lib/cpp/src/thrift/transport/THttpClient.h +++ b/lib/cpp/src/thrift/transport/THttpClient.h @@ -26,16 +26,34 @@ namespace apache { namespace thrift { namespace transport { +/** + * @brief Client transport using HTTP. The path is an optional field that is + * not required by Thrift HTTP server or client. It can be used i.e. with HTTP + * redirection, load balancing or forwarding on the server. + */ class THttpClient : public THttpTransport { public: - THttpClient(std::shared_ptr transport, std::string host, std::string path = ""); + /** + * @brief Constructor that wraps an existing transport, but also sets the + * host and path. The host and path are not used for the connection but are + * set in the HTTP header of the transport. + */ + THttpClient(std::shared_ptr transport, + std::string host = "localhost", + std::string path = "/service"); + /** + * @brief Constructor that will create a new socket transport using the host + * and port. + */ THttpClient(std::string host, int port, std::string path = ""); ~THttpClient() override; void flush() override; + void setPath(std::string path); + protected: std::string host_; std::string path_; From 6064696ae08e9764f588143f8ffd380b95405aca Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Wed, 15 Apr 2020 10:26:09 +0200 Subject: [PATCH 559/756] lib/js/Gruntfile.js: Generalized to add some level of Windows CMD support (not complete yet) --- lib/js/Gruntfile.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/js/Gruntfile.js b/lib/js/Gruntfile.js index 87b826fb159..4421f0cb475 100644 --- a/lib/js/Gruntfile.js +++ b/lib/js/Gruntfile.js @@ -39,27 +39,22 @@ module.exports = function(grunt) { }, shell: { InstallThriftJS: { - command: 'mkdir -p test/build/js/lib; cp src/thrift.js test/build/js/thrift.js' + command: 'cp src/thrift.js test/build/js/thrift.js' }, InstallThriftNodeJSDep: { - command: 'cd ../..; npm install' + command: 'cd ../.. && npm install' }, InstallTestLibs: { - command: 'cd test; ant download_jslibs' + command: 'cd test && ant download_jslibs' }, ThriftGen: { command: [ - 'mkdir -p test/gen-js', - '../../compiler/cpp/thrift -gen js --out test/gen-js ../../test/ThriftTest.thrift', - '../../compiler/cpp/thrift -gen js --out test/gen-js ../../test/JsDeepConstructorTest.thrift', - 'mkdir -p test/gen-js-jquery', - '../../compiler/cpp/thrift -gen js:jquery --out test/gen-js-jquery ../../test/ThriftTest.thrift', - 'mkdir -p test/gen-nodejs', - '../../compiler/cpp/thrift -gen js:node --out test/gen-nodejs ../../test/ThriftTest.thrift', - 'mkdir -p test/gen-js-es6', - '../../compiler/cpp/thrift -gen js:es6 --out test/gen-js-es6 ../../test/ThriftTest.thrift', - 'mkdir -p test/gen-nodejs-es6', - '../../compiler/cpp/thrift -gen js:node,es6 --out ./test/gen-nodejs-es6 ../../test/ThriftTest.thrift', + '"../../compiler/cpp/thrift" -gen js --out test/gen-js ../../test/ThriftTest.thrift', + '"../../compiler/cpp/thrift" -gen js --out test/gen-js ../../test/JsDeepConstructorTest.thrift', + '"../../compiler/cpp/thrift" -gen js:jquery --out test/gen-js-jquery ../../test/ThriftTest.thrift', + '"../../compiler/cpp/thrift" -gen js:node --out test/gen-nodejs ../../test/ThriftTest.thrift', + '"../../compiler/cpp/thrift" -gen js:es6 --out test/gen-js-es6 ../../test/ThriftTest.thrift', + '"../../compiler/cpp/thrift" -gen js:node,es6 --out ./test/gen-nodejs-es6 ../../test/ThriftTest.thrift', ].join(' && ') }, ThriftGenJQ: { @@ -290,7 +285,17 @@ module.exports = function(grunt) { }, 1000); }); + grunt.registerTask('CreateDirectories', 'Creating required local directories', function () { + grunt.file.mkdir('test/build/js/lib'); + grunt.file.mkdir('test/gen-js'); + grunt.file.mkdir('test/gen-js-jquery'); + grunt.file.mkdir('test/gen-nodejs'); + grunt.file.mkdir('test/gen-js-es6'); + grunt.file.mkdir('test/gen-nodejs-es6'); +}); + grunt.registerTask('installAndGenerate', [ + 'CreateDirectories', 'shell:InstallThriftJS', 'shell:InstallThriftNodeJSDep', 'shell:ThriftGen', From 93171d2482f98d77887874afc3bbb73f0bbb65c2 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Wed, 23 Oct 2019 17:32:34 +0200 Subject: [PATCH 560/756] THRIFT-5109 Misc Cmake build improvements Patch: Mario Emmenlauer This closes #2094 --- CMakeLists.txt | 8 +++++ build/cmake/DefineOptions.cmake | 2 +- compiler/cpp/CMakeLists.txt | 7 +++++ lib/js/CMakeLists.txt | 52 +++++++++++++++++++++++++++++++++ lib/js/Makefile.am | 1 + lib/nodejs/CMakeLists.txt | 44 ++++++++++++++++++++++++++++ lib/nodejs/Makefile.am | 1 + 7 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 lib/js/CMakeLists.txt create mode 100644 lib/nodejs/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index f2e682ac2c5..18e52f638fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,14 @@ if(BUILD_JAVA) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/java) endif() +if(BUILD_JAVASCRIPT) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/js) +endif() + +if(BUILD_NODEJS) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/nodejs) +endif() + if(BUILD_PYTHON) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/lib/py) if(BUILD_TESTING) diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 8357160b1bf..8c7a4a9642a 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -108,7 +108,7 @@ endif() # Javascript option(WITH_JAVASCRIPT "Build Javascript Thrift library" ON) CMAKE_DEPENDENT_OPTION(BUILD_JAVASCRIPT "Build Javascript library" ON - "BUILD_LIBRARIES;WITH_JAVASCRIPT" OFF) + "BUILD_LIBRARIES;WITH_JAVASCRIPT;NOT WIN32; NOT CYGWIN" OFF) # NodeJS option(WITH_NODEJS "Build NodeJS Thrift library" ON) diff --git a/compiler/cpp/CMakeLists.txt b/compiler/cpp/CMakeLists.txt index 92b0a5f3e87..a65a419de6b 100644 --- a/compiler/cpp/CMakeLists.txt +++ b/compiler/cpp/CMakeLists.txt @@ -115,6 +115,13 @@ set_target_properties(thrift-compiler PROPERTIES OUTPUT_NAME thrift) target_link_libraries(thrift-compiler parse) +add_custom_command(OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/thrift${CMAKE_EXECUTABLE_SUFFIX}" + DEPENDS thrift-compiler + COMMAND ${CMAKE_COMMAND} -E copy "$" "${CMAKE_CURRENT_SOURCE_DIR}/" + COMMENT "Copying the thrift compiler to the source tree for use by downstream targets") +add_custom_target(copy-thrift-compiler + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/thrift${CMAKE_EXECUTABLE_SUFFIX}") + install(TARGETS thrift-compiler DESTINATION bin) if(BUILD_TESTING) diff --git a/lib/js/CMakeLists.txt b/lib/js/CMakeLists.txt new file mode 100644 index 00000000000..c312a21f5c3 --- /dev/null +++ b/lib/js/CMakeLists.txt @@ -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. +# + +if(NOT JAVASCRIPT_INSTALL_DIR) + if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") + set(JAVASCRIPT_INSTALL_DIR "${LIB_INSTALL_DIR}/js") + else() + set(JAVASCRIPT_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/js") + endif() +endif() + +if(IS_ABSOLUTE "${DOC_INSTALL_DIR}") + set(JAVASCRIPT_DOC_INSTALL_DIR "${DOC_INSTALL_DIR}/js") +else() + set(JAVASCRIPT_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}/js") +endif() + +add_custom_target(ThriftJavascriptPreDeps ALL + COMMENT "Installing Javascript dependencies using npm" + DEPENDS copy-thrift-compiler + COMMAND npm install + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +) + +add_custom_target(ThriftJavascript ALL + COMMENT "Building Javascript library using npx Grunt wrapper" + DEPENDS ThriftJavascriptPreDeps + COMMAND npx grunt + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" +) + +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dist/" + DESTINATION "${JAVASCRIPT_INSTALL_DIR}" + FILES_MATCHING PATTERN "thrift*.js") +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/doc/" + DESTINATION "${JAVASCRIPT_DOC_INSTALL_DIR}") diff --git a/lib/js/Makefile.am b/lib/js/Makefile.am index b534042649a..4906d7ddbcc 100644 --- a/lib/js/Makefile.am +++ b/lib/js/Makefile.am @@ -57,6 +57,7 @@ EXTRA_DIST = \ Gruntfile.js \ package.json \ package-lock.json \ + CMakeLists.txt \ README.md \ src \ test diff --git a/lib/nodejs/CMakeLists.txt b/lib/nodejs/CMakeLists.txt new file mode 100644 index 00000000000..5059044b29a --- /dev/null +++ b/lib/nodejs/CMakeLists.txt @@ -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. +# + +if(NOT NODEJS_INSTALL_DIR) + if(IS_ABSOLUTE "${LIB_INSTALL_DIR}") + set(NODEJS_INSTALL_DIR "${LIB_INSTALL_DIR}/nodejs") + else() + set(NODEJS_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}/nodejs") + endif() +endif() + +# Currently no doc +#if(IS_ABSOLUTE "${DOC_INSTALL_DIR}") +# set(NODEJS_DOC_INSTALL_DIR "${DOC_INSTALL_DIR}/nodejs") +#else() +# set(NODEJS_DOC_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${DOC_INSTALL_DIR}/nodejs") +#endif() + +add_custom_target(ThriftNodeJS ALL + COMMENT "Installing NodeJS dependencies with npm" + COMMAND npm install + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../../" +) + +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/lib/" + DESTINATION "${NODEJS_INSTALL_DIR}") +#install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/doc/" +# DESTINATION "${NODEJS_DOC_INSTALL_DIR}") diff --git a/lib/nodejs/Makefile.am b/lib/nodejs/Makefile.am index 71068b58f18..67f6ff6a90a 100755 --- a/lib/nodejs/Makefile.am +++ b/lib/nodejs/Makefile.am @@ -42,4 +42,5 @@ EXTRA_DIST = \ lib \ test \ coding_standards.md \ + CMakeLists.txt \ README.md From d5a9bf2b30b4f9533f4ef13ee1a4fdce1036bbaa Mon Sep 17 00:00:00 2001 From: Kengo Seki Date: Fri, 24 Apr 2020 05:58:00 +0900 Subject: [PATCH 561/756] THRIFT-5171: Fix maven-ant-tasks to use HTTPS instead of HTTP Client: js, json --- lib/js/test/build.xml | 1 + lib/json/test/build.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/js/test/build.xml b/lib/js/test/build.xml index d891b439409..833e5bd71ba 100755 --- a/lib/js/test/build.xml +++ b/lib/js/test/build.xml @@ -235,6 +235,7 @@ + diff --git a/lib/json/test/build.xml b/lib/json/test/build.xml index 956a2382b74..eb39c4f2840 100644 --- a/lib/json/test/build.xml +++ b/lib/json/test/build.xml @@ -115,6 +115,7 @@ + From e98ba9cb841153fcbe2185ca44c77dbbc745ceb3 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Thu, 23 Apr 2020 23:39:04 -0700 Subject: [PATCH 562/756] THRIFT-5183: Don't try to read next frame in THeaderTransport.Read Trying to read the next frame will likely cause the Read call blocking indefinitely and eventually lead to timeout. See the JIRA ticket for more context. Client: go --- lib/go/thrift/header_transport.go | 15 ++++++-- lib/go/thrift/header_transport_test.go | 51 ++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/lib/go/thrift/header_transport.go b/lib/go/thrift/header_transport.go index 5343ccb46bc..103741ee176 100644 --- a/lib/go/thrift/header_transport.go +++ b/lib/go/thrift/header_transport.go @@ -499,10 +499,17 @@ func (t *THeaderTransport) Read(p []byte) (read int, err error) { if err != nil { return } - if read < len(p) { - var nextRead int - nextRead, err = t.Read(p[read:]) - read += nextRead + if read == 0 { + // Try to read the next frame when we hit EOF + // (end of frame) immediately. + // When we got here, it means the last read + // finished the previous frame, but didn't + // do endOfFrame handling yet. + // We have to read the next frame here, + // as otherwise we would return 0 and nil, + // which is a case not handled well by most + // protocol implementations. + return t.Read(p) } } return diff --git a/lib/go/thrift/header_transport_test.go b/lib/go/thrift/header_transport_test.go index e30476802f0..e3ae41b02d8 100644 --- a/lib/go/thrift/header_transport_test.go +++ b/lib/go/thrift/header_transport_test.go @@ -23,7 +23,9 @@ import ( "context" "io" "io/ioutil" + "strings" "testing" + "testing/quick" ) func TestTHeaderHeadersReadWrite(t *testing.T) { @@ -128,3 +130,52 @@ func TestTHeaderTransportNoDoubleWrapping(t *testing.T) { t.Errorf("NewTHeaderTransport double wrapped THeaderTransport") } } + +func TestTHeaderTransportNoReadBeyondFrame(t *testing.T) { + trans := NewTMemoryBuffer() + writeContent := func(writer TTransport, content string) error { + if _, err := io.Copy(writer, strings.NewReader(content)); err != nil { + return err + } + if err := writer.Flush(context.Background()); err != nil { + return err + } + return nil + } + f := func(content string) bool { + defer trans.Reset() + if len(content) == 0 { + return true + } + + reader := NewTHeaderTransport(trans) + writer := NewTHeaderTransport(trans) + // Write content twice + if err := writeContent(writer, content); err != nil { + t.Error(err) + } + if err := writeContent(writer, content); err != nil { + t.Error(err) + } + // buf is big enough to read both content out, + // but it shouldn't read beyond the first one in a single Read call. + buf := make([]byte, len(content)*3) + read, err := reader.Read(buf) + if err != nil { + t.Error(err) + } + if read == 0 || read > len(content) { + t.Errorf( + "Expected read in no more than %d:%q, got %d:%q", + len(content), + content, + read, + buf[:read], + ) + } + return !t.Failed() + } + if err := quick.Check(f, nil); err != nil { + t.Error(err) + } +} From ed0bad34301741c6ea7473e891d1c6886e8db9e1 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Fri, 24 Apr 2020 08:50:43 +0200 Subject: [PATCH 563/756] Add isOpen() to TServerTransport Client: cpp --- lib/cpp/src/thrift/transport/TPipeServer.cpp | 4 ++++ lib/cpp/src/thrift/transport/TPipeServer.h | 2 ++ lib/cpp/src/thrift/transport/TServerSocket.cpp | 4 ++++ lib/cpp/src/thrift/transport/TServerSocket.h | 3 +++ lib/cpp/src/thrift/transport/TServerTransport.h | 5 +++++ lib/cpp/test/TServerSocketTest.cpp | 6 +++++- lib/cpp/test/TSocketInterruptTest.cpp | 1 + 7 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/cpp/src/thrift/transport/TPipeServer.cpp b/lib/cpp/src/thrift/transport/TPipeServer.cpp index f0d1e70f532..0855e2cba13 100644 --- a/lib/cpp/src/thrift/transport/TPipeServer.cpp +++ b/lib/cpp/src/thrift/transport/TPipeServer.cpp @@ -181,6 +181,10 @@ TPipeServer::TPipeServer() : bufsize_(1024), isAnonymous_(true) { //---- Destructor ---- TPipeServer::~TPipeServer() {} +bool TPipeServer::isOpen() const { + return (impl_->getPipeHandle() != INVALID_HANDLE_VALUE); +} + //--------------------------------------------------------- // Transport callbacks //--------------------------------------------------------- diff --git a/lib/cpp/src/thrift/transport/TPipeServer.h b/lib/cpp/src/thrift/transport/TPipeServer.h index 871b6afabd5..d4255cb9955 100644 --- a/lib/cpp/src/thrift/transport/TPipeServer.h +++ b/lib/cpp/src/thrift/transport/TPipeServer.h @@ -59,6 +59,8 @@ class TPipeServer : public TServerTransport { // Destructor virtual ~TPipeServer(); + bool isOpen() const override; + // Standard transport callbacks void interrupt() override; void close() override; diff --git a/lib/cpp/src/thrift/transport/TServerSocket.cpp b/lib/cpp/src/thrift/transport/TServerSocket.cpp index ece05445a34..1bc6b47896b 100644 --- a/lib/cpp/src/thrift/transport/TServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TServerSocket.cpp @@ -185,6 +185,10 @@ TServerSocket::~TServerSocket() { close(); } +bool TServerSocket::isOpen() const { + return (serverSocket_ != THRIFT_INVALID_SOCKET); +} + void TServerSocket::setSendTimeout(int sendTimeout) { sendTimeout_ = sendTimeout; } diff --git a/lib/cpp/src/thrift/transport/TServerSocket.h b/lib/cpp/src/thrift/transport/TServerSocket.h index d640968033e..4562341b09f 100644 --- a/lib/cpp/src/thrift/transport/TServerSocket.h +++ b/lib/cpp/src/thrift/transport/TServerSocket.h @@ -98,6 +98,9 @@ class TServerSocket : public TServerTransport { ~TServerSocket() override; + + bool isOpen() const override; + void setSendTimeout(int sendTimeout); void setRecvTimeout(int recvTimeout); diff --git a/lib/cpp/src/thrift/transport/TServerTransport.h b/lib/cpp/src/thrift/transport/TServerTransport.h index f465bb38a08..9e84850aab4 100644 --- a/lib/cpp/src/thrift/transport/TServerTransport.h +++ b/lib/cpp/src/thrift/transport/TServerTransport.h @@ -37,6 +37,11 @@ class TServerTransport { public: virtual ~TServerTransport() = default; + /** + * Whether this transport is open. + */ + virtual bool isOpen() const { return false; } + /** * Starts the server transport listening for new connections. Prior to this * call most transports will not return anything when accept is called. diff --git a/lib/cpp/test/TServerSocketTest.cpp b/lib/cpp/test/TServerSocketTest.cpp index bec6d475626..c96700f8be5 100644 --- a/lib/cpp/test/TServerSocketTest.cpp +++ b/lib/cpp/test/TServerSocketTest.cpp @@ -35,6 +35,7 @@ BOOST_AUTO_TEST_SUITE(TServerSocketTest) BOOST_AUTO_TEST_CASE(test_bind_to_address) { TServerSocket sock1("localhost", 0); sock1.listen(); + BOOST_CHECK(sock1.isOpen()); int port = sock1.getPort(); TSocket clientSock("localhost", port); clientSock.open(); @@ -48,17 +49,20 @@ BOOST_AUTO_TEST_CASE(test_bind_to_address) { sock2.close(); } -BOOST_AUTO_TEST_CASE(test_listen_valid_port) { +BOOST_AUTO_TEST_CASE(test_listen_invalid_port) { TServerSocket sock1(-1); TTRANSPORT_CHECK_THROW(sock1.listen(), TTransportException::BAD_ARGS); + BOOST_CHECK(!sock1.isOpen()); TServerSocket sock2(65536); TTRANSPORT_CHECK_THROW(sock2.listen(), TTransportException::BAD_ARGS); + BOOST_CHECK(!sock1.isOpen()); } BOOST_AUTO_TEST_CASE(test_close_before_listen) { TServerSocket sock1("localhost", 0); sock1.close(); + BOOST_CHECK(!sock1.isOpen()); } BOOST_AUTO_TEST_CASE(test_get_port) { diff --git a/lib/cpp/test/TSocketInterruptTest.cpp b/lib/cpp/test/TSocketInterruptTest.cpp index 366242f7cd7..a546c23a13e 100644 --- a/lib/cpp/test/TSocketInterruptTest.cpp +++ b/lib/cpp/test/TSocketInterruptTest.cpp @@ -53,6 +53,7 @@ void readerWorkerMustThrow(std::shared_ptr tt) { BOOST_AUTO_TEST_CASE(test_interruptable_child_read) { TServerSocket sock1("localhost", 0); sock1.listen(); + BOOST_CHECK(sock1.isOpen()); int port = sock1.getPort(); TSocket clientSock("localhost", port); clientSock.open(); From 802793638b3e06d8b9031ae4d0b765735165c598 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Fri, 24 Apr 2020 08:51:37 +0200 Subject: [PATCH 564/756] THRIFT-4282: Disabled StressTestNonBlocking on Windows --- appveyor.yml | 6 ++---- test/cpp/CMakeLists.txt | 16 ++++++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 233a056b903..96fe30cf3a4 100755 --- a/appveyor.yml +++ b/appveyor.yml @@ -45,7 +45,6 @@ environment: PYTHON_VERSION: 3.6 QT_VERSION: 5.10 ZLIB_VERSION: 1.2.11 - DISABLED_TESTS: (StressTestNonBlocking) - PROFILE: MSVC2015 PLATFORM: x86 @@ -56,18 +55,17 @@ environment: PYTHON_VERSION: 3.5 QT_VERSION: 5.8 ZLIB_VERSION: 1.2.8 - DISABLED_TESTS: (StressTestNonBlocking) APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - PROFILE: MINGW PLATFORM: x64 CONFIGURATION: RelWithDebInfo - DISABLED_TESTS: (StalenessCheckTest|StressTestNonBlocking) + DISABLED_TESTS: (StalenessCheckTest) - PROFILE: CYGWIN PLATFORM: x64 CONFIGURATION: RelWithDebInfo - DISABLED_TESTS: (ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest|StressTestNonBlocking) + DISABLED_TESTS: (ZlibTest|OpenSSLManualInitTest|TNonblockingServerTest) install: - cd %APPVEYOR_BUILD_FOLDER% diff --git a/test/cpp/CMakeLists.txt b/test/cpp/CMakeLists.txt index a136a488700..367b6decccb 100755 --- a/test/cpp/CMakeLists.txt +++ b/test/cpp/CMakeLists.txt @@ -75,12 +75,16 @@ LINK_AGAINST_THRIFT_LIBRARY(StressTest thriftnb) add_test(NAME StressTest COMMAND StressTest) add_test(NAME StressTestConcurrent COMMAND StressTest --client-type=concurrent) -add_executable(StressTestNonBlocking src/StressTestNonBlocking.cpp) -target_link_libraries(StressTestNonBlocking crossstressgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB}) -LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thrift) -LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thriftnb) -LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thriftz) -add_test(NAME StressTestNonBlocking COMMAND StressTestNonBlocking) +# As of https://jira.apache.org/jira/browse/THRIFT-4282, StressTestNonBlocking +# is broken on Windows. Contributions welcome. +if (NOT WIN32 AND NOT CYGWIN) + add_executable(StressTestNonBlocking src/StressTestNonBlocking.cpp) + target_link_libraries(StressTestNonBlocking crossstressgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB}) + LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thrift) + LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thriftnb) + LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thriftz) + add_test(NAME StressTestNonBlocking COMMAND StressTestNonBlocking) +endif() # # Common thrift code generation rules From 04574379a43dd2a05766f3e06eb9852a9b6fa5da Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Fri, 24 Apr 2020 11:44:41 +0200 Subject: [PATCH 565/756] TOutput: Add further parsers for errno-to-string conversion for Windows --- lib/cpp/src/thrift/TOutput.cpp | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/lib/cpp/src/thrift/TOutput.cpp b/lib/cpp/src/thrift/TOutput.cpp index 8d163a94183..800ba0751ed 100644 --- a/lib/cpp/src/thrift/TOutput.cpp +++ b/lib/cpp/src/thrift/TOutput.cpp @@ -24,6 +24,10 @@ #include #include +#ifdef _WIN32 +#include +#endif + namespace apache { namespace thrift { @@ -101,14 +105,12 @@ void TOutput::perror(const char* message, int errno_copy) { } std::string TOutput::strerror_s(int errno_copy) { -#ifndef HAVE_STRERROR_R - return "errno = " + to_string(errno_copy); -#else // HAVE_STRERROR_R - char b_errbuf[1024] = {'\0'}; + +#ifdef HAVE_STRERROR_R #ifdef STRERROR_R_CHAR_P - char* b_error = strerror_r(errno_copy, b_errbuf, sizeof(b_errbuf)); -#else + char* b_error = ::strerror_r(errno_copy, b_errbuf, sizeof(b_errbuf)); +#else // STRERROR_R_CHAR_P char* b_error = b_errbuf; int rv = strerror_r(errno_copy, b_errbuf, sizeof(b_errbuf)); if (rv == -1) { @@ -116,13 +118,27 @@ std::string TOutput::strerror_s(int errno_copy) { return "XSI-compliant strerror_r() failed with errno = " + to_string(errno_copy); } -#endif +#endif // STRERROR_R_CHAR_P +#else // HAVE_STRERROR_R +#ifdef _WIN32 + const size_t size = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errno_copy, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + b_errbuf, sizeof(b_errbuf), NULL); + + if (size > 2 && b_errbuf[size-2] == '\r' && b_errbuf[size-1] == '\n') { + b_errbuf[size-2] = '\0'; + b_errbuf[size-1] = '\0'; + } +#else // _WIN32 + ::strerror_s(b_errbuf, sizeof(b_errbuf), errno_copy); +#endif // _WIN32 + char* b_error = b_errbuf; +#endif // HAVE_STRERROR_R + // Can anyone prove that explicit cast is probably not necessary // to ensure that the string object is constructed before // b_error becomes invalid? return std::string(b_error); - -#endif // HAVE_STRERROR_R } } } // apache::thrift From b4711a617821a0610e377f048abf8dfe0c701773 Mon Sep 17 00:00:00 2001 From: Alexander Edge Date: Fri, 24 Apr 2020 14:43:03 +0100 Subject: [PATCH 566/756] Swift 5.1 support Use stdlib Result instead of TAsyncResult Fix: deprecations for `withUnsafeBytes` Bump CI job Xcode version Hash (into) Co-authored-by: Sophie Lambrakis Co-authored-by: Alexander Edge --- .travis.yml | 15 ++---------- .../src/thrift/generate/t_swift_generator.cc | 24 ++++++------------- lib/swift/Sources/TApplicationError.swift | 9 ++++--- lib/swift/Sources/TClient.swift | 13 ---------- lib/swift/Sources/TCompactProtocol.swift | 5 +--- lib/swift/Sources/TEnum.swift | 5 +++- lib/swift/Sources/TFileTransport.swift | 2 +- lib/swift/Sources/TList.swift | 11 +++------ lib/swift/Sources/TMap.swift | 14 ++++------- lib/swift/Sources/TSerializable.swift | 5 ---- lib/swift/Sources/TSet.swift | 9 ++----- lib/swift/Sources/TSocketServer.swift | 2 +- lib/swift/Sources/TSocketTransport.swift | 2 +- lib/swift/Sources/TStreamTransport.swift | 5 +--- lib/swift/Sources/TStruct.swift | 9 ------- 15 files changed, 33 insertions(+), 97 deletions(-) diff --git a/.travis.yml b/.travis.yml index 400cfa146e0..f3dc7e4a708 100644 --- a/.travis.yml +++ b/.travis.yml @@ -152,22 +152,11 @@ jobs: # ------------------------- phase: swift ------------------------ # We lint the podspec - os: osx - osx_image: xcode10.1 + osx_image: xcode11.3 language: swift script: - gem update cocoapods - - pod lib lint --allow-warnings --swift-version=3 - env: - - JOB="pod lib lint" - - - os: osx - osx_image: xcode10.2 - language: swift - script: - - gem update cocoapods - - pod lib lint --allow-warnings --swift-version=4.0 - - pod lib lint --allow-warnings --swift-version=4.2 - - pod lib lint --allow-warnings --swift-version=5.0 + - pod lib lint --allow-warnings --swift-version=5.1 env: - JOB="pod lib lint" diff --git a/compiler/cpp/src/thrift/generate/t_swift_generator.cc b/compiler/cpp/src/thrift/generate/t_swift_generator.cc index 4a2f87d3bcb..ac63ea07d60 100644 --- a/compiler/cpp/src/thrift/generate/t_swift_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_swift_generator.cc @@ -855,37 +855,27 @@ void t_swift_generator::generate_swift_struct_hashable_extension(ostream& out, indent(out) << "extension " << tstruct->get_name() << " : Hashable"; block_open(out); out << endl; - indent(out) << visibility << " var hashValue : Int"; + indent(out) << visibility << " func hash(into hasher: inout Hasher)"; block_open(out); const vector& members = tstruct->get_members(); vector::const_iterator m_iter; if (!members.empty()) { - indent(out) << "let prime = 31" << endl; - indent(out) << "var result = 1" << endl; if (!tstruct->is_union()) { for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_field* tfield = *m_iter; - string accessor = field_is_optional(tfield) ? "?." : "."; - string defaultor = field_is_optional(tfield) ? " ?? 0" : ""; - indent(out) << "result = prime &* result &+ (" << maybe_escape_identifier(tfield->get_name()) << accessor - << "hashValue" << defaultor << ")" << endl; + indent(out) << "hasher.combine(" << maybe_escape_identifier(tfield->get_name()) << ")" << endl; } } else { indent(out) << "switch self {" << endl; for (m_iter = members.begin(); m_iter != members.end(); m_iter++) { t_field *tfield = *m_iter; - indent(out) << "case ." << tfield->get_name() << "(let val): result = prime &* val.hashValue" << endl; + indent(out) << "case ." << tfield->get_name() << "(let val): hasher.combine(val)" << endl; } indent(out) << "}" << endl << endl; } - indent(out) << "return result" << endl; } - else { - indent(out) << "return 31" << endl; - } - block_close(out); out << endl; block_close(out); @@ -2877,8 +2867,8 @@ void t_swift_generator::async_function_docstring(ostream& out, t_function* tfunc } // completion - indent(out) << "/// - completion: TAsyncResult<" << type_name(tfunction->get_returntype()) - << "> wrapping return and following Exceptions: "; + indent(out) << "/// - completion: Result<" << type_name(tfunction->get_returntype()) + << ", Error> wrapping return and following Exceptions: "; t_struct* xs = tfunction->get_xceptions(); const vector& xceptions = xs->get_members(); vector::const_iterator x_iter; @@ -2903,9 +2893,9 @@ string t_swift_generator::async_function_signature(t_function* tfunction) { string result = "func " + (gen_cocoa_ ? function_name(tfunction) : tfunction->get_name()); if (!gen_cocoa_) { - string response_string = "(TAsyncResult<"; + string response_string = "(Result<"; response_string += (ttype->is_void()) ? "Void" : type_name(ttype); - response_string += ">) -> Void"; + response_string += ", Error>) -> Void"; result += "(" + argument_list(tfunction->get_arglist(), "", false) + (targlist->get_members().size() ? ", " : "") + "completion: @escaping " + response_string + ")"; diff --git a/lib/swift/Sources/TApplicationError.swift b/lib/swift/Sources/TApplicationError.swift index bc393968005..cfaf285d8ff 100644 --- a/lib/swift/Sources/TApplicationError.swift +++ b/lib/swift/Sources/TApplicationError.swift @@ -146,9 +146,12 @@ extension TApplicationError : TSerializable { try proto.writeFieldStop() try proto.writeStructEnd() } - - public var hashValue: Int { - return error.thriftErrorCode &+ (message?.hashValue ?? 0) +} + +extension TApplicationError: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(error.thriftErrorCode) + hasher.combine(message) } } diff --git a/lib/swift/Sources/TClient.swift b/lib/swift/Sources/TClient.swift index cc3288a8c05..049027f7726 100644 --- a/lib/swift/Sources/TClient.swift +++ b/lib/swift/Sources/TClient.swift @@ -40,16 +40,3 @@ open class TAsyncClient { self.factory = factory } } - - -public enum TAsyncResult { - case success(T) - case error(Swift.Error) - - public func value() throws -> T { - switch self { - case .success(let t): return t - case .error(let e): throw e - } - } -} diff --git a/lib/swift/Sources/TCompactProtocol.swift b/lib/swift/Sources/TCompactProtocol.swift index 5b302d38f8d..81a51f55114 100644 --- a/lib/swift/Sources/TCompactProtocol.swift +++ b/lib/swift/Sources/TCompactProtocol.swift @@ -371,10 +371,7 @@ public class TCompactProtocol: TProtocol { try ProtocolTransportTry(error: TProtocolError(message: "Transport Read Failed")) { buff = try self.transport.readAll(size: 8) } - - let i64: UInt64 = buff.withUnsafeBytes { (ptr: UnsafePointer) -> UInt64 in - return UnsafePointer(OpaquePointer(ptr)).pointee - } + let i64: UInt64 = buff.withUnsafeBytes { $0.load(as: UInt64.self) } let bits = CFSwapInt64LittleToHost(i64) return Double(bitPattern: bits) } diff --git a/lib/swift/Sources/TEnum.swift b/lib/swift/Sources/TEnum.swift index fedfdb12489..2e91f636002 100644 --- a/lib/swift/Sources/TEnum.swift +++ b/lib/swift/Sources/TEnum.swift @@ -24,7 +24,10 @@ public protocol TEnum : TSerializable, Hashable { extension TEnum { public static var thriftType: TType { return .i32 } - public var hashValue: Int { return rawValue.hashValue } + + public func hash(into hasher: inout Hasher) { + hasher.combine(rawValue) + } public func write(to proto: TProtocol) throws { try proto.write(rawValue) diff --git a/lib/swift/Sources/TFileTransport.swift b/lib/swift/Sources/TFileTransport.swift index fe2253da4c6..75eba4042d3 100644 --- a/lib/swift/Sources/TFileTransport.swift +++ b/lib/swift/Sources/TFileTransport.swift @@ -88,7 +88,7 @@ public class TFileTransport: TTransport { public func write(data: Data) throws { let bytesWritten = data.withUnsafeBytes { - fwrite($0, 1, data.count, self.fileHandle) + fwrite($0.baseAddress!, 1, data.count, self.fileHandle) } if bytesWritten != data.count { throw TTransportError(error: .unknown) diff --git a/lib/swift/Sources/TList.swift b/lib/swift/Sources/TList.swift index c239d10c555..1508d90b8d7 100644 --- a/lib/swift/Sources/TList.swift +++ b/lib/swift/Sources/TList.swift @@ -17,7 +17,7 @@ * under the License. */ -public struct TList : RandomAccessCollection, MutableCollection, ExpressibleByArrayLiteral, TSerializable, Hashable { +public struct TList : RandomAccessCollection, MutableCollection, ExpressibleByArrayLiteral, TSerializable, Hashable { public typealias Storage = Array public typealias Indices = Storage.Indices @@ -31,13 +31,8 @@ public struct TList : RandomAccessCollection, MutableCo } /// Mark: Hashable - public var hashValue : Int { - let prime = 31 - var result = 1 - for element in storage { - result = prime &* result &+ element.hashValue - } - return result + public func hash(into hasher: inout Hasher) { + hasher.combine(storage) } /// Mark: TSerializable diff --git a/lib/swift/Sources/TMap.swift b/lib/swift/Sources/TMap.swift index dcf1481c6a4..8f520673b4c 100644 --- a/lib/swift/Sources/TMap.swift +++ b/lib/swift/Sources/TMap.swift @@ -17,7 +17,7 @@ * under the License. */ -public struct TMap: Collection, ExpressibleByDictionaryLiteral, Hashable, TSerializable { +public struct TMap: Collection, ExpressibleByDictionaryLiteral, Hashable, TSerializable { public typealias Storage = Dictionary public typealias Element = Storage.Element public typealias Index = Storage.Index @@ -111,15 +111,9 @@ public struct TMap: Colle } /// Mark: Hashable - - public var hashValue: Int { - let prime = 31 - var result = 1 - for (key, value) in storage { - result = prime &* result &+ key.hashValue - result = prime &* result &+ value.hashValue - } - return result + + public func hash(into hasher: inout Hasher) { + hasher.combine(storage) } /// Mark: TSerializable diff --git a/lib/swift/Sources/TSerializable.swift b/lib/swift/Sources/TSerializable.swift index b45096b69e8..1374700ca81 100644 --- a/lib/swift/Sources/TSerializable.swift +++ b/lib/swift/Sources/TSerializable.swift @@ -21,7 +21,6 @@ import Foundation public protocol TSerializable { - var hashValue: Int { get } /// TType for instance static var thriftType: TType { get } @@ -43,10 +42,6 @@ extension TSerializable { public var thriftType: TType { return Self.thriftType } } -public func ==(lhs: T, rhs: T) -> Bool where T : TSerializable { - return lhs.hashValue == rhs.hashValue -} - /// Default read/write for primitave Thrift types: /// Bool, Int8 (byte), Int16, Int32, Int64, Double, String diff --git a/lib/swift/Sources/TSet.swift b/lib/swift/Sources/TSet.swift index 6891c11e6de..d340fec6ac7 100644 --- a/lib/swift/Sources/TSet.swift +++ b/lib/swift/Sources/TSet.swift @@ -126,13 +126,8 @@ public struct TSet : SetAlgebra, Hashable, C /// Mark: Hashable - public var hashValue : Int { - let prime = 31 - var result = 1 - for element in storage { - result = prime &* result &+ element.hashValue - } - return result + public func hash(into hasher: inout Hasher) { + hasher.combine(storage) } /// Mark: TSerializable diff --git a/lib/swift/Sources/TSocketServer.swift b/lib/swift/Sources/TSocketServer.swift index a3c63894a79..6cfb5a10cfd 100644 --- a/lib/swift/Sources/TSocketServer.swift +++ b/lib/swift/Sources/TSocketServer.swift @@ -82,7 +82,7 @@ class TSocketServer.size) let cfaddr = address.withUnsafeBytes { - CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, $0, address.count, nil) + CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, $0.bindMemory(to: UInt8.self).baseAddress!, address.count, nil) } if CFSocketSetAddress(sock, cfaddr) != CFSocketError.success { //kCFSocketSuccess { CFSocketInvalidate(sock) diff --git a/lib/swift/Sources/TSocketTransport.swift b/lib/swift/Sources/TSocketTransport.swift index 21325033b4a..57f62155ed7 100644 --- a/lib/swift/Sources/TSocketTransport.swift +++ b/lib/swift/Sources/TSocketTransport.swift @@ -198,7 +198,7 @@ public class TSocketTransport : TTransport { var writeBuffer = data while bytesToWrite > 0 { let written = writeBuffer.withUnsafeBytes { - Sys.write(socketDescriptor, $0, writeBuffer.count) + Sys.write(socketDescriptor, $0.baseAddress!, writeBuffer.count) } writeBuffer = writeBuffer.subdata(in: written ..< writeBuffer.count) bytesToWrite -= written diff --git a/lib/swift/Sources/TStreamTransport.swift b/lib/swift/Sources/TStreamTransport.swift index d9c9574221a..5dd7dbac973 100644 --- a/lib/swift/Sources/TStreamTransport.swift +++ b/lib/swift/Sources/TStreamTransport.swift @@ -104,10 +104,7 @@ fileprivate extension RunLoopMode { var bytesWritten = 0 while bytesWritten < data.count { - bytesWritten = data.withUnsafeBytes { - return output.write($0, maxLength: data.count) - } - + bytesWritten = data.withUnsafeBytes { output.write($0.bindMemory(to: UInt8.self).baseAddress!, maxLength: data.count) } if bytesWritten == -1 { throw TTransportError(error: .notOpen) } else if bytesWritten == 0 { diff --git a/lib/swift/Sources/TStruct.swift b/lib/swift/Sources/TStruct.swift index 38e51e7026c..f1208334609 100644 --- a/lib/swift/Sources/TStruct.swift +++ b/lib/swift/Sources/TStruct.swift @@ -45,15 +45,6 @@ public extension TStruct { try proto.writeStructEnd() } - var hashValue: Int { - let prime = 31 - var result = 1 - self.forEach { _, value, _ in - result = prime &* result &+ (value.hashValue) - } - return result - } - /// Provides a block for handling each (available) thrift property using reflection /// Caveat: Skips over optional values From 25f81d11c2adb60ce50425879962a3f68efc4afa Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Fri, 24 Apr 2020 15:45:05 +0200 Subject: [PATCH 567/756] Rework NodeJS / Javascript consistency Client: js * Re-worked consistency of browser.js and index.js in lib/nodejs * Wrap non-standard V8 method 'Error.captureStackTrace()' --- lib/js/src/thrift.js | 3 +-- lib/nodejs/lib/thrift/browser.js | 27 ++++++++++++------- lib/nodejs/lib/thrift/header_protocol.js | 3 +-- lib/nodejs/lib/thrift/header_transport.js | 3 +-- lib/nodejs/lib/thrift/http_connection.js | 4 +-- lib/nodejs/lib/thrift/index.js | 13 ++++----- .../lib/thrift/input_buffer_underrun_error.js | 3 +-- lib/nodejs/lib/thrift/thrift.js | 6 ++--- 8 files changed, 33 insertions(+), 29 deletions(-) diff --git a/lib/js/src/thrift.js b/lib/js/src/thrift.js index c682605b81d..123f526ac69 100644 --- a/lib/js/src/thrift.js +++ b/lib/js/src/thrift.js @@ -284,10 +284,9 @@ Thrift.TProtocolExceptionType = { Thrift.TProtocolException = function TProtocolException(type, message) { Error.call(this); - if (Error.captureStackTrace) { + if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } - this.name = this.constructor.name; this.type = type; this.message = message; diff --git a/lib/nodejs/lib/thrift/browser.js b/lib/nodejs/lib/thrift/browser.js index ba1ea8c389c..0b06f0f1331 100644 --- a/lib/nodejs/lib/thrift/browser.js +++ b/lib/nodejs/lib/thrift/browser.js @@ -18,25 +18,32 @@ */ exports.Thrift = require('./thrift'); +var wsConnection = require('./ws_connection'); +exports.WSConnection = wsConnection.WSConnection; +exports.createWSConnection = wsConnection.createWSConnection; +exports.createWSClient = wsConnection.createWSClient; + var xhrConnection = require('./xhr_connection'); exports.XHRConnection = xhrConnection.XHRConnection; exports.createXHRConnection = xhrConnection.createXHRConnection; exports.createXHRClient = xhrConnection.createXHRClient; -var wsConnection = require('./ws_connection'); -exports.WSConnection = wsConnection.WSConnection; -exports.createWSConnection = wsConnection.createWSConnection; -exports.createWSClient = wsConnection.createWSClient; -exports.Multiplexer = require('./multiplexed_protocol').Multiplexer; +exports.Int64 = require('node-int64'); +exports.Q = require('q'); -exports.TWebSocketTransport = require('./ws_transport'); +var mpxProtocol = require('./multiplexed_protocol'); +exports.Multiplexer = mpxProtocol.Multiplexer; + +/* + * Export transport and protocol so they can be used outside of a + * cassandra/server context + */ exports.TBufferedTransport = require('./buffered_transport'); exports.TFramedTransport = require('./framed_transport'); +exports.TWebSocketTransport = require('./ws_transport'); -exports.Protocol = exports.TJSONProtocol = require('./json_protocol'); +exports.Protocol = require('./json_protocol'); +exports.TJSONProtocol = require('./json_protocol'); exports.TBinaryProtocol = require('./binary_protocol'); exports.TCompactProtocol = require('./compact_protocol'); - -exports.Int64 = require('node-int64'); -exports.Q = require('q'); diff --git a/lib/nodejs/lib/thrift/header_protocol.js b/lib/nodejs/lib/thrift/header_protocol.js index a037dc2557d..8971751fb75 100644 --- a/lib/nodejs/lib/thrift/header_protocol.js +++ b/lib/nodejs/lib/thrift/header_protocol.js @@ -29,10 +29,9 @@ module.exports = THeaderProtocol; function THeaderProtocolError(message) { Error.call(this); - if (Error.captureStackTrace) { + if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } - this.name = this.constructor.name; this.message = message; } diff --git a/lib/nodejs/lib/thrift/header_transport.js b/lib/nodejs/lib/thrift/header_transport.js index 252a42385a7..ec8624b02a7 100644 --- a/lib/nodejs/lib/thrift/header_transport.js +++ b/lib/nodejs/lib/thrift/header_transport.js @@ -24,10 +24,9 @@ var InputBufferUnderrunError = require('./input_buffer_underrun_error'); function THeaderTransportError(message) { Error.call(this); - if (Error.captureStackTrace) { + if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } - this.name = this.constructor.name; this.message = message; } diff --git a/lib/nodejs/lib/thrift/http_connection.js b/lib/nodejs/lib/thrift/http_connection.js index 81e6b706de2..17e0d0c2995 100644 --- a/lib/nodejs/lib/thrift/http_connection.js +++ b/lib/nodejs/lib/thrift/http_connection.js @@ -217,7 +217,7 @@ HttpConnection.prototype.write = function(data) { var opts = self.nodeOptions; opts.headers["Content-length"] = data.length; if (!opts.headers["Content-Type"]) - opts.headers["Content-Type"] = "application/x-thrift"; + opts.headers["Content-Type"] = "application/x-thrift"; var req = (self.https) ? https.request(opts, self.responseCallback) : http.request(opts, self.responseCallback); @@ -253,7 +253,7 @@ exports.createHttpClient = createClient function THTTPException(response) { thrift.TApplicationException.call(this); - if (Error.captureStackTrace) { + if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } diff --git a/lib/nodejs/lib/thrift/index.js b/lib/nodejs/lib/thrift/index.js index 0a2d02b71cf..00f21743d43 100644 --- a/lib/nodejs/lib/thrift/index.js +++ b/lib/nodejs/lib/thrift/index.js @@ -58,18 +58,19 @@ exports.createWebServer = web_server.createWebServer; exports.Int64 = require('node-int64'); exports.Q = require('q'); -var mprocessor = require('./multiplexed_processor'); -var mprotocol = require('./multiplexed_protocol'); -exports.Multiplexer = mprotocol.Multiplexer; -exports.MultiplexedProcessor = mprocessor.MultiplexedProcessor; +var mpxProcessor = require('./multiplexed_processor'); +var mpxProtocol = require('./multiplexed_protocol'); +exports.MultiplexedProcessor = mpxProcessor.MultiplexedProcessor; +exports.Multiplexer = mpxProtocol.Multiplexer; /* * Export transport and protocol so they can be used outside of a * cassandra/server context */ -exports.TFramedTransport = require('./framed_transport'); exports.TBufferedTransport = require('./buffered_transport'); -exports.TBinaryProtocol = require('./binary_protocol'); +exports.TFramedTransport = require('./framed_transport'); + exports.TJSONProtocol = require('./json_protocol'); +exports.TBinaryProtocol = require('./binary_protocol'); exports.TCompactProtocol = require('./compact_protocol'); exports.THeaderProtocol = require('./header_protocol'); diff --git a/lib/nodejs/lib/thrift/input_buffer_underrun_error.js b/lib/nodejs/lib/thrift/input_buffer_underrun_error.js index 0e33f5a42f1..e424540a09c 100644 --- a/lib/nodejs/lib/thrift/input_buffer_underrun_error.js +++ b/lib/nodejs/lib/thrift/input_buffer_underrun_error.js @@ -22,10 +22,9 @@ module.exports = InputBufferUnderrunError; function InputBufferUnderrunError(message) { Error.call(this); - if (Error.captureStackTrace) { + if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } - this.name = this.constructor.name; this.message = message; }; diff --git a/lib/nodejs/lib/thrift/thrift.js b/lib/nodejs/lib/thrift/thrift.js index 58d4aff797a..f728eacbe48 100644 --- a/lib/nodejs/lib/thrift/thrift.js +++ b/lib/nodejs/lib/thrift/thrift.js @@ -49,7 +49,7 @@ exports.TException = TException; function TException(message) { Error.call(this); - if (Error.captureStackTrace) { + if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } @@ -76,7 +76,7 @@ exports.TApplicationException = TApplicationException; function TApplicationException(type, message) { TException.call(this); - if (Error.captureStackTrace) { + if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } @@ -155,7 +155,7 @@ exports.TProtocolException = TProtocolException; function TProtocolException(type, message) { Error.call(this); - if (Error.captureStackTrace) { + if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, this.constructor); } From 5ef8e3ec2ab39ea37f8437ae1b7ca1966287a934 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Fri, 24 Apr 2020 16:34:02 +0200 Subject: [PATCH 568/756] Remove boost from compiler test, delete unused bincat.sh --- compiler/cpp/test/CMakeLists.txt | 7 ------- compiler/cpp/test/Makefile.am | 3 +-- compiler/cpp/test/bincat.sh | 3 --- 3 files changed, 1 insertion(+), 12 deletions(-) delete mode 100755 compiler/cpp/test/bincat.sh diff --git a/compiler/cpp/test/CMakeLists.txt b/compiler/cpp/test/CMakeLists.txt index 2bc7e9e6910..4ce1e49ea19 100644 --- a/compiler/cpp/test/CMakeLists.txt +++ b/compiler/cpp/test/CMakeLists.txt @@ -17,12 +17,6 @@ # under the License. # -# Unit tests for the compiler still require boost -include(BoostMacros) -REQUIRE_BOOST_HEADERS() -set(BOOST_COMPONENTS unit_test_framework) -REQUIRE_BOOST_LIBRARIES(BOOST_COMPONENTS) - file(GLOB KEYWORD_SAMPLES "${CMAKE_CURRENT_SOURCE_DIR}/keyword-samples/*.thrift") foreach(LANG ${thrift_compiler_LANGS}) foreach(SAMPLE ${KEYWORD_SAMPLES}) @@ -34,7 +28,6 @@ foreach(LANG ${thrift_compiler_LANGS}) endforeach() endforeach() - find_package(PythonInterp QUIET) if(PYTHONINTERP_FOUND) add_test(NAME StalenessCheckTest COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/compiler/staleness_check.py ${THRIFT_COMPILER}) diff --git a/compiler/cpp/test/Makefile.am b/compiler/cpp/test/Makefile.am index 801f9d85ef2..10efd073767 100644 --- a/compiler/cpp/test/Makefile.am +++ b/compiler/cpp/test/Makefile.am @@ -23,6 +23,5 @@ AUTOMAKE_OPTIONS = subdir-objects serial-tests nostdinc -AM_CPPFLAGS = $(BOOST_CPPFLAGS) -I$(top_srcdir)/compiler/cpp/src -AM_LDFLAGS = $(BOOST_LDFLAGS) +AM_CPPFLAGS = -I$(top_srcdir)/compiler/cpp/src AM_CXXFLAGS = -Wall -Wextra -pedantic diff --git a/compiler/cpp/test/bincat.sh b/compiler/cpp/test/bincat.sh deleted file mode 100755 index c7f90785e7e..00000000000 --- a/compiler/cpp/test/bincat.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -exec /bin/cat From 2d2df9e89210a768134a185808769566e2cd9aa8 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Fri, 24 Apr 2020 18:02:18 +0200 Subject: [PATCH 569/756] Allow wrapping TTransportFactory into a TZlibTransportFactory Client: cpp --- lib/cpp/src/thrift/transport/TZlibTransport.cpp | 12 ++++++++++++ lib/cpp/src/thrift/transport/TZlibTransport.h | 13 ++++++++++--- test/cpp/src/TestServer.cpp | 9 ++++----- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.cpp b/lib/cpp/src/thrift/transport/TZlibTransport.cpp index 437190b2925..b4c43d64769 100644 --- a/lib/cpp/src/thrift/transport/TZlibTransport.cpp +++ b/lib/cpp/src/thrift/transport/TZlibTransport.cpp @@ -397,6 +397,18 @@ void TZlibTransport::verifyChecksum() { "verifyChecksum() called before end of " "zlib stream"); } + +TZlibTransportFactory::TZlibTransportFactory(std::shared_ptr transportFactory) + :transportFactory_(transportFactory) { +} + +std::shared_ptr TZlibTransportFactory::getTransport(std::shared_ptr trans) { + if (transportFactory_) { + return std::shared_ptr(new TZlibTransport(transportFactory_->getTransport(trans))); + } else { + return std::shared_ptr(new TZlibTransport(trans)); + } +} } } } // apache::thrift::transport diff --git a/lib/cpp/src/thrift/transport/TZlibTransport.h b/lib/cpp/src/thrift/transport/TZlibTransport.h index 29afae0d416..4990afff5ad 100644 --- a/lib/cpp/src/thrift/transport/TZlibTransport.h +++ b/lib/cpp/src/thrift/transport/TZlibTransport.h @@ -229,12 +229,19 @@ class TZlibTransportFactory : public TTransportFactory { public: TZlibTransportFactory() = default; + /** + * Wraps a transport factory into a zlibbed one. + */ + TZlibTransportFactory(std::shared_ptr transportFactory); + ~TZlibTransportFactory() override = default; - std::shared_ptr getTransport(std::shared_ptr trans) override { - return std::shared_ptr(new TZlibTransport(trans)); - } + std::shared_ptr getTransport(std::shared_ptr trans) override; + +protected: + std::shared_ptr transportFactory_; }; + } } } // apache::thrift::transport diff --git a/test/cpp/src/TestServer.cpp b/test/cpp/src/TestServer.cpp index 8d5b4d93e2f..8fdab8653d1 100644 --- a/test/cpp/src/TestServer.cpp +++ b/test/cpp/src/TestServer.cpp @@ -735,8 +735,8 @@ int main(int argc, char** argv) { } if (zlib) { - // hmm.. doesn't seem to be a way to make it wrap the others... - transportFactory = std::make_shared(); + // currently TZlibTransportFactory is the only factory than can wrap another: + transportFactory = std::make_shared(transportFactory); } // Server Info @@ -816,7 +816,7 @@ int main(int argc, char** argv) { // if using header server->setOutputProtocolFactory(std::shared_ptr()); } - + apache::thrift::concurrency::ThreadFactory factory; factory.setDetached(false); std::shared_ptr serverThreadRunner(server); @@ -829,7 +829,7 @@ int main(int argc, char** argv) { thread->start(); gMonitor.waitForever(); // wait for a shutdown signal - + #ifdef HAVE_SIGNAL_H signal(SIGINT, SIG_DFL); #endif @@ -842,4 +842,3 @@ int main(int argc, char** argv) { cout << "done." << endl; return 0; } - From b94c16638555c4efa191092bf0f14ce45c3621b8 Mon Sep 17 00:00:00 2001 From: Dmitry Maluka Date: Sat, 18 Apr 2020 13:51:29 +0200 Subject: [PATCH 570/756] THRIFT-5177: getaddrinfo() should not be used for Unix sockets Client: cpp Patch: Dmitry Maluka This closes #2102 --- .../src/thrift/transport/TServerSocket.cpp | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/cpp/src/thrift/transport/TServerSocket.cpp b/lib/cpp/src/thrift/transport/TServerSocket.cpp index 1bc6b47896b..662f6e512ad 100644 --- a/lib/cpp/src/thrift/transport/TServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TServerSocket.cpp @@ -261,7 +261,7 @@ void TServerSocket::listen() { throw TTransportException(TTransportException::BAD_ARGS, "Specified port is invalid"); } - const struct addrinfo *res; + const struct addrinfo *res = nullptr; int error; char port[sizeof("65535")]; THRIFT_SNPRINTF(port, sizeof(port), "%d", port_); @@ -275,19 +275,21 @@ void TServerSocket::listen() { // If address is not specified use wildcard address (NULL) TGetAddrInfoWrapper info(address_.empty() ? nullptr : &address_[0], port, &hints); - error = info.init(); - if (error) { - GlobalOutput.printf("getaddrinfo %d: %s", error, THRIFT_GAI_STRERROR(error)); - close(); - throw TTransportException(TTransportException::NOT_OPEN, - "Could not resolve host for server socket."); - } + if (path_.empty()) { + error = info.init(); + if (error) { + GlobalOutput.printf("getaddrinfo %d: %s", error, THRIFT_GAI_STRERROR(error)); + close(); + throw TTransportException(TTransportException::NOT_OPEN, + "Could not resolve host for server socket."); + } - // Pick the ipv6 address first since ipv4 addresses can be mapped - // into ipv6 space. - for (res = info.res(); res; res = res->ai_next) { - if (res->ai_family == AF_INET6 || res->ai_next == nullptr) - break; + // Pick the ipv6 address first since ipv4 addresses can be mapped + // into ipv6 space. + for (res = info.res(); res; res = res->ai_next) { + if (res->ai_family == AF_INET6 || res->ai_next == nullptr) + break; + } } if (!path_.empty()) { @@ -372,7 +374,7 @@ void TServerSocket::listen() { #endif // #ifdef TCP_DEFER_ACCEPT #ifdef IPV6_V6ONLY - if (res->ai_family == AF_INET6 && path_.empty()) { + if (path_.empty() && res->ai_family == AF_INET6) { int zero = 0; if (-1 == setsockopt(serverSocket_, IPPROTO_IPV6, From b83ae2cedf8a345142c3b96e9b529a65fe41bc16 Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Fri, 24 Apr 2020 11:35:55 +0800 Subject: [PATCH 571/756] supplementary testcase for TJSONProtocol Client: py Patch: zeshuai007 <51382517@qq.com> This closes #2113 --- lib/py/test/thrift_json.py | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/lib/py/test/thrift_json.py b/lib/py/test/thrift_json.py index 40e7a47e389..125ea59f6c7 100644 --- a/lib/py/test/thrift_json.py +++ b/lib/py/test/thrift_json.py @@ -46,6 +46,71 @@ def test_escaped_unicode_string(self): unicode_text = unicode_text.encode('utf8') self.assertEqual(protocol.readString(), unicode_text) + def test_TJSONProtocol_write(self): + write_data = '{"software":"thrift","1":[23,1.2010000000000001,32767,2147483647,9223372036854775807],"base64":"aGVsbG8gdGhyaWZ0","bool":0}' + + buff = TTransport.TMemoryBuffer() + transport = TTransport.TBufferedTransportFactory().getTransport(buff) + protocol = TJSONProtocol(transport) + protocol.writeJSONObjectStart() + protocol.writeJSONString("software") + protocol.writeJSONString("thrift") + protocol.writeJSONString("1") + protocol.writeJSONArrayStart() + protocol.writeJSONNumber(23) + protocol.writeDouble(1.201) + protocol.writeI16(32767) + protocol.writeI32(2147483647) + protocol.writeI64(9223372036854775807) + protocol.writeJSONArrayEnd() + protocol.writeJSONString("base64") + protocol.writeJSONBase64("hello thrift".encode('utf-8')) + protocol.writeJSONString("bool") + protocol.writeBool(0) + protocol.writeJSONObjectEnd() + + transport.flush() + value = buff.getvalue() + + self.assertEqual(write_data, value.decode('utf-8')) + + def test_TJSONProtol_read(self): + expected = "{'software':'thrift','1':[23,1.2010000000000001,32767,2147483647,9223372036854775807],'base64':'hello thrift','bool':False}" + read_data = '{"software":"thrift","1":[23,1.2010000000000001,32767,2147483647,9223372036854775807],"base64":"aGVsbG8gdGhyaWZ0","bool":0}' + + buff = TTransport.TMemoryBuffer(read_data.encode('utf-8')) + transport = TTransport.TBufferedTransportFactory().getTransport(buff) + protocol = TJSONProtocol(transport) + protocol.readJSONObjectStart() + u_1 = protocol.readString() + u_2 = protocol.readString() + u_3 = protocol.readString() + protocol.readJSONArrayStart() + u_4 = protocol.readNumber() + u_5 = protocol.readDouble() + u_6 = protocol.readI16() + u_7 = protocol.readI32() + u_8 = protocol.readI64() + protocol.readJSONArrayEnd() + u_9 = protocol.readString() + u_10 = protocol.readJSONBase64() + u_11 = protocol.readString() + u_12 = protocol.readBool() + protocol.writeJSONObjectEnd() + + result_read = {} + result_read[u_1] = u_2 + result_read[u_3] = [] + result_read[u_3].append(u_4) + result_read[u_3].append(u_5) + result_read[u_3].append(u_6) + result_read[u_3].append(u_7) + result_read[u_3].append(u_8) + result_read[u_9] = u_10.decode('utf-8') + result_read[u_11] = u_12 + + self.assertEqual(eval(expected), result_read) + if __name__ == '__main__': unittest.main() From 3127e4abd94728a60849c80bed84c2c338067a01 Mon Sep 17 00:00:00 2001 From: Jano Svitok Date: Mon, 27 Apr 2020 09:12:42 +0200 Subject: [PATCH 572/756] THRIFT-5150: Fix compilation with Swift 5.2 - (OS X and Linux) type 'TSet' does not conform to protocol 'Collection' - (Linux only) kCFSocketCloseOnInvalidate has Int type Client: swift --- lib/swift/Sources/TSet.swift | 1 + lib/swift/Sources/TSocketServer.swift | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/swift/Sources/TSet.swift b/lib/swift/Sources/TSet.swift index d340fec6ac7..9d89d14a92e 100644 --- a/lib/swift/Sources/TSet.swift +++ b/lib/swift/Sources/TSet.swift @@ -30,6 +30,7 @@ public struct TSet : SetAlgebra, Hashable, C /// Mark: Collection + public typealias Element = Storage.Element public typealias Indices = Storage.Indices public typealias Index = Storage.Index public typealias IndexDistance = Int diff --git a/lib/swift/Sources/TSocketServer.swift b/lib/swift/Sources/TSocketServer.swift index 6cfb5a10cfd..5d0dd494100 100644 --- a/lib/swift/Sources/TSocketServer.swift +++ b/lib/swift/Sources/TSocketServer.swift @@ -56,7 +56,7 @@ class TSocketServer Date: Mon, 27 Apr 2020 15:18:26 +0800 Subject: [PATCH 573/756] Mention Qt in README [skip ci] --- doc/install/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/install/README.md b/doc/install/README.md index 071a5d64d59..3bc4d3559b8 100644 --- a/doc/install/README.md +++ b/doc/install/README.md @@ -26,6 +26,7 @@ These are only required if you choose to build the libraries for the given langu * Boost 1.56.0 * libevent (optional, to build the nonblocking server) * zlib (optional) + * Qt (optional) * Java * Java 1.8 * Gradle From c3728122d2ddb2e0236b1e08bdb5e24b8baae9dd Mon Sep 17 00:00:00 2001 From: Zezeng Wang <51382517@qq.com> Date: Mon, 27 Apr 2020 15:48:19 +0800 Subject: [PATCH 574/756] Supplement TBinaryprotocol module testcase Client: py --- lib/py/CMakeLists.txt | 1 + lib/py/Makefile.am | 2 + lib/py/test/thrift_TBinaryProtocol.py | 264 ++++++++++++++++++++++++++ 3 files changed, 267 insertions(+) create mode 100644 lib/py/test/thrift_TBinaryProtocol.py diff --git a/lib/py/CMakeLists.txt b/lib/py/CMakeLists.txt index 7bb91fe6712..cba2d65de58 100644 --- a/lib/py/CMakeLists.txt +++ b/lib/py/CMakeLists.txt @@ -28,4 +28,5 @@ add_custom_target(python_build ALL if(BUILD_TESTING) add_test(PythonTestSSLSocket ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/test_sslsocket.py) add_test(PythonThriftJson ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_json.py) + add_test(PythonThriftJson ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_TBinaryProtocol.py) endif() diff --git a/lib/py/Makefile.am b/lib/py/Makefile.am index 46e44054bf1..de7afd3e89f 100644 --- a/lib/py/Makefile.am +++ b/lib/py/Makefile.am @@ -25,6 +25,7 @@ py3-build: py3-test: py3-build $(PYTHON3) test/thrift_json.py $(PYTHON3) test/test_sslsocket.py + $(PYTHON3) test/thrift_TBinaryProtocol.py else py3-build: py3-test: @@ -43,6 +44,7 @@ install-exec-hook: check-local: all py3-test $(PYTHON) test/thrift_json.py $(PYTHON) test/test_sslsocket.py + $(PYTHON) test/thrift_TBinaryProtocol.py clean-local: $(RM) -r build diff --git a/lib/py/test/thrift_TBinaryProtocol.py b/lib/py/test/thrift_TBinaryProtocol.py new file mode 100644 index 00000000000..f7d05ff975d --- /dev/null +++ b/lib/py/test/thrift_TBinaryProtocol.py @@ -0,0 +1,264 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +import unittest + +import _import_local_thrift # noqa +from thrift.protocol.TBinaryProtocol import TBinaryProtocol +from thrift.transport import TTransport + + +def testNaked(type, data): + buf = TTransport.TMemoryBuffer() + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TBinaryProtocol(transport) + if type.capitalize() == 'Byte': + protocol.writeByte(data) + + if type.capitalize() == 'I16': + protocol.writeI16(data) + + if type.capitalize() == 'I32': + protocol.writeI32(data) + + if type.capitalize() == 'I64': + protocol.writeI64(data) + + if type.capitalize() == 'String': + protocol.writeString(data) + + if type.capitalize() == 'Double': + protocol.writeDouble(data) + + if type.capitalize() == 'Binary': + protocol.writeBinary(data) + + if type.capitalize() == 'Bool': + protocol.writeBool(data) + + transport.flush() + data_r = buf.getvalue() + buf = TTransport.TMemoryBuffer(data_r) + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TBinaryProtocol(transport) + if type.capitalize() == 'Byte': + return protocol.readByte() + + if type.capitalize() == 'I16': + return protocol.readI16() + + if type.capitalize() == 'I32': + return protocol.readI32() + + if type.capitalize() == 'I64': + return protocol.readI64() + + if type.capitalize() == 'String': + return protocol.readString() + + if type.capitalize() == 'Double': + return protocol.readDouble() + + if type.capitalize() == 'Binary': + return protocol.readBinary() + + if type.capitalize() == 'Bool': + return protocol.readBool() + + +def testField(type, data): + TType = {"Bool": 2, "Byte": 3, "Binary": 5, "I16": 6, "I32": 8, "I64": 10, "Double": 11, "String": 12} + buf = TTransport.TMemoryBuffer() + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TBinaryProtocol(transport) + protocol.writeStructBegin('struct') + protocol.writeFieldBegin("field", TType[type.capitalize()], 10) + if type.capitalize() == 'Byte': + protocol.writeByte(data) + + if type.capitalize() == 'I16': + protocol.writeI16(data) + + if type.capitalize() == 'I32': + protocol.writeI32(data) + + if type.capitalize() == 'I64': + protocol.writeI64(data) + + if type.capitalize() == 'String': + protocol.writeString(data) + + if type.capitalize() == 'Double': + protocol.writeDouble(data) + + if type.capitalize() == 'Binary': + protocol.writeBinary(data) + + if type.capitalize() == 'Bool': + protocol.writeBool(data) + + protocol.writeFieldEnd() + protocol.writeStructEnd() + + transport.flush() + data_r = buf.getvalue() + + buf = TTransport.TMemoryBuffer(data_r) + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TBinaryProtocol(transport) + protocol.readStructBegin() + protocol.readFieldBegin() + if type.capitalize() == 'Byte': + return protocol.readByte() + + if type.capitalize() == 'I16': + return protocol.readI16() + + if type.capitalize() == 'I32': + return protocol.readI32() + + if type.capitalize() == 'I64': + return protocol.readI64() + + if type.capitalize() == 'String': + return protocol.readString() + + if type.capitalize() == 'Double': + return protocol.readDouble() + + if type.capitalize() == 'Binary': + return protocol.readBinary() + + if type.capitalize() == 'Bool': + return protocol.readBool() + + protocol.readFieldEnd() + protocol.readStructEnd() + + +def testMessage(data): + message = {} + message['name'] = data[0] + message['type'] = data[1] + message['seqid'] = data[2] + + buf = TTransport.TMemoryBuffer() + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TBinaryProtocol(transport) + protocol.writeMessageBegin(message['name'], message['type'], message['seqid']) + protocol.writeMessageEnd() + + transport.flush() + data_r = buf.getvalue() + + buf = TTransport.TMemoryBuffer(data_r) + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TBinaryProtocol(transport) + result = protocol.readMessageBegin() + protocol.readMessageEnd() + return result + + +class TestTBinaryProtocol(unittest.TestCase): + + def test_TBinaryProtocol_write_read(self): + try: + testNaked('Byte', 123) + for i in range(0, 128): + self.assertEqual(i, testField('Byte', i)) + self.assertEqual(-i, testField('Byte', -i)) + + self.assertEqual(0, testNaked("I16", 0)) + self.assertEqual(1, testNaked("I16", 1)) + self.assertEqual(15000, testNaked("I16", 15000)) + self.assertEqual(0x7fff, testNaked("I16", 0x7fff)) + self.assertEqual(-1, testNaked("I16", -1)) + self.assertEqual(-15000, testNaked("I16", -15000)) + self.assertEqual(-0x7fff, testNaked("I16", -0x7fff)) + self.assertEqual(32767, testNaked("I16", 32767)) + self.assertEqual(-32768, testNaked("I16", -32768)) + + self.assertEqual(0, testField("I16", 0)) + self.assertEqual(1, testField("I16", 1)) + self.assertEqual(7, testField("I16", 7)) + self.assertEqual(150, testField("I16", 150)) + self.assertEqual(15000, testField("I16", 15000)) + self.assertEqual(0x7fff, testField("I16", 0x7fff)) + self.assertEqual(-1, testField("I16", -1)) + self.assertEqual(-7, testField("I16", -7)) + self.assertEqual(-150, testField("I16", -150)) + self.assertEqual(-15000, testField("I16", -15000)) + self.assertEqual(-0xfff, testField("I16", -0xfff)) + + self.assertEqual(0, testNaked("I32", 0)) + self.assertEqual(1, testNaked("I32", 1)) + self.assertEqual(15000, testNaked("I32", 15000)) + self.assertEqual(0xffff, testNaked("I32", 0xffff)) + self.assertEqual(-1, testNaked("I32", -1)) + self.assertEqual(-15000, testNaked("I32", -15000)) + self.assertEqual(-0xffff, testNaked("I32", -0xffff)) + self.assertEqual(2147483647, testNaked("I32", 2147483647)) + self.assertEqual(-2147483647, testNaked("I32", -2147483647)) + + self.assertEqual(0, testField("I32", 0)) + self.assertEqual(1, testField("I32", 1)) + self.assertEqual(7, testField("I32", 7)) + self.assertEqual(150, testField("I32", 150)) + self.assertEqual(15000, testField("I32", 15000)) + self.assertEqual(31337, testField("I32", 31337)) + self.assertEqual(0xffff, testField("I32", 0xffff)) + self.assertEqual(0xffffff, testField("I32", 0xffffff)) + self.assertEqual(-1, testField("I32", -1)) + self.assertEqual(-7, testField("I32", -7)) + self.assertEqual(-150, testField("I32", -150)) + self.assertEqual(-15000, testField("I32", -15000)) + self.assertEqual(-0xffff, testField("I32", -0xffff)) + self.assertEqual(-0xffffff, testField("I32", -0xffffff)) + + self.assertEqual(9223372036854775807, testNaked("I64", 9223372036854775807)) + self.assertEqual(-9223372036854775807, testNaked("I64", -9223372036854775807)) + self.assertEqual(-0, testNaked("I64", 0)) + + self.assertEqual(True, testNaked("Bool", True)) + self.assertEqual(3.14159261, testNaked("Double", 3.14159261)) + self.assertEqual("hello thrift", testNaked("String", "hello thrift")) + self.assertEqual(True, testField('Bool', True)) + self.assertEqual(3.1415926, testNaked("Double", 3.1415926)) + self.assertEqual("hello thrift", testNaked("String", "hello thrift")) + + TMessageType = {"T_CALL": 1, "T_REPLY": 2, "T_EXCEPTION": 3, "T_ONEWAY": 4} + test_data = [("short message name", TMessageType['T_CALL'], 0), + ("1", TMessageType['T_REPLY'], 12345), + ("loooooooooooooooooooooooooooooooooong", TMessageType['T_EXCEPTION'], 1 << 16), + ("one way push", TMessageType['T_ONEWAY'], 12), + ("Janky", TMessageType['T_CALL'], 0)] + + for dt in test_data: + result = testMessage(dt) + self.assertEqual(result[0], dt[0]) + self.assertEqual(result[1], dt[1]) + self.assertEqual(result[2], dt[2]) + + except Exception as e: + print("Assertion fail") + raise e + + +if __name__ == '__main__': + unittest.main() From 7c4bdf9914fcba6c89e0f69ae48b9675578f084a Mon Sep 17 00:00:00 2001 From: penenin Date: Mon, 27 Apr 2020 01:11:47 -0700 Subject: [PATCH 575/756] THRIFT-5184: Fix header check for WebSocket connections When establishing a WebSocket connection, Firefox sends Connection: keep-alive, Upgrade instead of just Connection: Upgrade. Check to see if Upgrade is in the header instead of checking to see if it is the entire header value. Client: d --- lib/d/src/thrift/transport/websocket.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/d/src/thrift/transport/websocket.d b/lib/d/src/thrift/transport/websocket.d index 25d1f7d01dc..b800e519e31 100644 --- a/lib/d/src/thrift/transport/websocket.d +++ b/lib/d/src/thrift/transport/websocket.d @@ -121,7 +121,7 @@ protected: upgrade_ = sicmp(upgrade, "websocket") == 0; } else if (startsWith!compToLower(split[0], cast(ubyte[])"connection")) { auto connection = stripLeft(cast(const(char)[])split[2]); - connection_ = sicmp(connection, "upgrade") == 0; + connection_ = canFind(connection.toLower, "upgrade"); } else if (startsWith!compToLower(split[0], cast(ubyte[])"sec-websocket-key")) { auto secWebSocketKey = stripLeft(cast(const(char)[])split[2]); auto hash = sha1Of(secWebSocketKey ~ WEBSOCKET_GUID); From 52655cec793a5f2d276942e79de219e299436535 Mon Sep 17 00:00:00 2001 From: penenin Date: Mon, 27 Apr 2020 08:19:55 -0700 Subject: [PATCH 576/756] THRIFT-5159: Fix runtime ReferenceError in generated code Client: nodejs --- compiler/cpp/src/thrift/generate/t_js_generator.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/cpp/src/thrift/generate/t_js_generator.cc b/compiler/cpp/src/thrift/generate/t_js_generator.cc index dfc398695f6..9766897295c 100644 --- a/compiler/cpp/src/thrift/generate/t_js_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_js_generator.cc @@ -1737,6 +1737,9 @@ void t_js_generator::generate_service_client(t_service* tservice) { indent_up(); if (gen_node_) { + if (gen_es6_ && is_subclass_service) { + indent(f_service_) << "super(output, pClass);" << endl; + } indent(f_service_) << "this.output = output;" << endl; indent(f_service_) << "this.pClass = pClass;" << endl; indent(f_service_) << "this._seqid = 0;" << endl; From 00c039adeb551b297276fcb88131f1cfe82be1cd Mon Sep 17 00:00:00 2001 From: Andrew Boyle Date: Mon, 27 Apr 2020 11:32:24 -0700 Subject: [PATCH 577/756] THRIFT-5164: Add middleware framework for Go servers This commit adds a simple middleware framework for Go servers. It provides: * A `ProcessorMiddleware` function interface used to define the actual middleware * `WrapProcessor`, the function that you use to wrap a `TProcessor` in a list of middleware * A helper `WrappedTProcessorFunction` struct to help with developing middleware This is a breaking change for any custom implementations of the `TProcessor` interface, but does not effect the code generated by compiling Thrift files. It adds two functions to the interface that are a part of the generated `TProcessor` code, but were not defined in the interface explicitly. --- CHANGES.md | 2 + lib/go/thrift/common_test.go | 78 ++++++++++++++- lib/go/thrift/example_middleware_test.go | 52 ++++++++++ lib/go/thrift/middleware.go | 70 +++++++++++++ lib/go/thrift/middleware_test.go | 110 +++++++++++++++++++++ lib/go/thrift/multiplexed_protocol.go | 61 ++++++++++++ lib/go/thrift/multiplexed_protocol_test.go | 53 ++++++++++ lib/go/thrift/processor_factory.go | 10 ++ 8 files changed, 435 insertions(+), 1 deletion(-) create mode 100644 lib/go/thrift/example_middleware_test.go create mode 100644 lib/go/thrift/middleware.go create mode 100644 lib/go/thrift/middleware_test.go create mode 100644 lib/go/thrift/multiplexed_protocol_test.go diff --git a/CHANGES.md b/CHANGES.md index ca84cb7d25f..b8bef21e2f8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,7 @@ - [THRIFT-5006](https://issues.apache.org/jira/browse/THRIFT-5006) - Implement DEFAULT_MAX_LENGTH at TFramedTransport - [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - In Go library TDeserializer.Transport is now typed \*TMemoryBuffer instead of TTransport - [THRIFT-5072](https://issues.apache.org/jira/browse/THRIFT-5072) - Haskell generator fails to distinguish between multiple enum types with conflicting enum identifiers +- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - In Go library TProcessor interface now includes ProcessorMap and AddToProcessorMap functions. ### Java @@ -18,6 +19,7 @@ ### Go - [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - Add TSerializerPool and TDeserializerPool, which are thread-safe versions of TSerializer and TDeserializer. +- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - Add ProcessorMiddleware function type and WrapProcessor function to support wrapping a TProcessor with middleware functions. ## 0.13.0 diff --git a/lib/go/thrift/common_test.go b/lib/go/thrift/common_test.go index 93597ff8a2a..95d4e21309c 100644 --- a/lib/go/thrift/common_test.go +++ b/lib/go/thrift/common_test.go @@ -19,7 +19,10 @@ package thrift -import "context" +import ( + "context" + "fmt" +) type mockProcessor struct { ProcessFunc func(in, out TProtocol) (bool, TException) @@ -28,3 +31,76 @@ type mockProcessor struct { func (m *mockProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) { return m.ProcessFunc(in, out) } + +func (m *mockProcessor) ProcessorMap() map[string]TProcessorFunction { + return map[string]TProcessorFunction{ + "mock": WrappedTProcessorFunction{ + Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { + return m.ProcessFunc(in, out) + }, + }, + } +} + +func (m *mockProcessor) AddToProcessorMap(name string, processorFunc TProcessorFunction) {} + +type mockWrappedProcessorContextKey int + +const ( + processorName mockWrappedProcessorContextKey = iota +) + +// setMockWrappableProcessorName sets the "name" of the TProcessorFunction to +// call on a mockWrappableProcessor when calling Process. +// +// In a normal TProcessor, the request name is read from the request itself +// which happens in TProcessor.Process, so it is not passed into the call to +// Process itself, to get around this in testing, mockWrappableProcessor calls +// getMockWrappableProcessorName to get the name to use from the context +// object. +func setMockWrappableProcessorName(ctx context.Context, name string) context.Context { + return context.WithValue(ctx, processorName, name) +} + +// getMockWrappableProcessorName gets the "name" of the TProcessorFunction to +// call on a mockWrappableProcessor when calling Process. +func getMockWrappableProcessorName(ctx context.Context) (string, bool) { + val, ok := ctx.Value(processorName).(string) + return val, ok +} + +// mockWrappableProcessor can be used to create a mock object that fufills the +// TProcessor interface in testing. +type mockWrappableProcessor struct { + ProcessorFuncs map[string]TProcessorFunction +} + +// Process calls the TProcessorFunction assigned to the "name" set on the +// context object by setMockWrappableProcessorName. +// +// If no name is set on the context or there is no TProcessorFunction mapped to +// that name, the call will panic. +func (p *mockWrappableProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) { + name, ok := getMockWrappableProcessorName(ctx) + if !ok { + panic("MockWrappableProcessorName not set on context") + } + processor, ok := p.ProcessorMap()[name] + if !ok { + panic(fmt.Sprintf("No processor set for name %q", name)) + } + return processor.Process(ctx, 0, in, out) +} + +func (p *mockWrappableProcessor) ProcessorMap() map[string]TProcessorFunction { + return p.ProcessorFuncs +} + +func (p *mockWrappableProcessor) AddToProcessorMap(name string, processorFunc TProcessorFunction) { + p.ProcessorFuncs[name] = processorFunc +} + +var ( + _ TProcessor = (*mockProcessor)(nil) + _ TProcessor = (*mockWrappableProcessor)(nil) +) diff --git a/lib/go/thrift/example_middleware_test.go b/lib/go/thrift/example_middleware_test.go new file mode 100644 index 00000000000..47061103df1 --- /dev/null +++ b/lib/go/thrift/example_middleware_test.go @@ -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 thrift + +import ( + "context" + "log" +) + +func simpleLoggingMiddleware(name string, next TProcessorFunction) TProcessorFunction { + return WrappedTProcessorFunction{ + Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { + log.Printf("Before: %q", name) + success, err := next.Process(ctx, seqId, in, out) + log.Printf("After: %q", name) + log.Printf("Success: %v", success) + if err != nil { + log.Printf("Error: %v", err) + } + return success, err + }, + } +} + +func ExampleProcessorMiddleware() { + var ( + processor TProcessor + trans TServerTransport + transFactory TTransportFactory + protoFactory TProtocolFactory + ) + processor = WrapProcessor(processor, simpleLoggingMiddleware) + server := NewTSimpleServer4(processor, trans, transFactory, protoFactory) + log.Fatal(server.Serve()) +} diff --git a/lib/go/thrift/middleware.go b/lib/go/thrift/middleware.go new file mode 100644 index 00000000000..18f2b99c160 --- /dev/null +++ b/lib/go/thrift/middleware.go @@ -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 thrift + +import "context" + +// ProcessorMiddleware is a function that can be passed to WrapProcessor to wrap the +// TProcessorFunctions for that TProcessor. +// +// Middlewares are passed in the name of the function as set in the processor +// map of the TProcessor. +type ProcessorMiddleware func(name string, next TProcessorFunction) TProcessorFunction + +// WrapProcessor takes an existing TProcessor and wraps each of its inner +// TProcessorFunctions with the middlewares passed in and returns it. +// +// Middlewares will be called in the order that they are defined: +// +// 1. Middlewares[0] +// 2. Middlewares[1] +// ... +// N. Middlewares[n] +func WrapProcessor(processor TProcessor, middlewares ...ProcessorMiddleware) TProcessor { + for name, processorFunc := range processor.ProcessorMap() { + wrapped := processorFunc + // Add middlewares in reverse so the first in the list is the outermost. + for i := len(middlewares) - 1; i >= 0; i-- { + wrapped = middlewares[i](name, wrapped) + } + processor.AddToProcessorMap(name, wrapped) + } + return processor +} + +// WrappedTProcessorFunction is a convenience struct that implements the +// TProcessorFunction interface that can be used when implementing custom +// Middleware. +type WrappedTProcessorFunction struct { + // Wrapped is called by WrappedTProcessorFunction.Process and should be a + // "wrapped" call to a base TProcessorFunc.Process call. + Wrapped func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) +} + +// Process implements the TProcessorFunction interface using p.Wrapped. +func (p WrappedTProcessorFunction) Process(ctx context.Context, seqID int32, in, out TProtocol) (bool, TException) { + return p.Wrapped(ctx, seqID, in, out) +} + +// verify that WrappedTProcessorFunction implements TProcessorFunction +var ( + _ TProcessorFunction = WrappedTProcessorFunction{} + _ TProcessorFunction = (*WrappedTProcessorFunction)(nil) +) diff --git a/lib/go/thrift/middleware_test.go b/lib/go/thrift/middleware_test.go new file mode 100644 index 00000000000..81cbc7bd1e6 --- /dev/null +++ b/lib/go/thrift/middleware_test.go @@ -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 thrift + +import ( + "context" + "testing" +) + +type counter struct { + count int +} + +func (c *counter) incr() { + c.count++ +} + +func testMiddleware(c *counter) ProcessorMiddleware { + return func(name string, next TProcessorFunction) TProcessorFunction { + return WrappedTProcessorFunction{ + Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { + c.incr() + return next.Process(ctx, seqId, in, out) + }, + } + } +} + +func newCounter(t *testing.T) *counter { + c := counter{} + if c.count != 0 { + t.Fatal("Unexpected initial count.") + } + return &c +} + +func TestWrapProcessor(t *testing.T) { + name := "test" + processor := &mockWrappableProcessor{ + ProcessorFuncs: map[string]TProcessorFunction{ + name: WrappedTProcessorFunction{ + Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { + return true, nil + }, + }, + }, + } + c := newCounter(t) + ctx := setMockWrappableProcessorName(context.Background(), name) + wrapped := WrapProcessor(processor, testMiddleware(c)) + wrapped.Process(ctx, nil, nil) + if c.count != 1 { + t.Fatalf("Unexpected count value %v", c.count) + } +} + +func TestWrapTMultiplexedProcessor(t *testing.T) { + name := "test" + processorName := "foo" + c := newCounter(t) + processor := &TMultiplexedProcessor{} + processor.RegisterDefault(&mockWrappableProcessor{ + ProcessorFuncs: map[string]TProcessorFunction{ + name: WrappedTProcessorFunction{ + Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { + return true, nil + }, + }, + }, + }) + processor.RegisterProcessor(processorName, &mockWrappableProcessor{ + ProcessorFuncs: map[string]TProcessorFunction{ + name: WrappedTProcessorFunction{ + Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { + return true, nil + }, + }, + }, + }) + wrapped := WrapProcessor(processor, testMiddleware(c)) + ctx := setMockWrappableProcessorName(context.Background(), name) + in := NewStoredMessageProtocol(nil, name, 1, 1) + wrapped.Process(ctx, in, nil) + if c.count != 1 { + t.Fatalf("Unexpected count value %v", c.count) + } + + in = NewStoredMessageProtocol(nil, processorName+MULTIPLEXED_SEPARATOR+name, 1, 1) + wrapped.Process(ctx, in, nil) + if c.count != 2 { + t.Fatalf("Unexpected count value %v", c.count) + } +} diff --git a/lib/go/thrift/multiplexed_protocol.go b/lib/go/thrift/multiplexed_protocol.go index d028a30b333..9db59c4c91c 100644 --- a/lib/go/thrift/multiplexed_protocol.go +++ b/lib/go/thrift/multiplexed_protocol.go @@ -117,6 +117,67 @@ func NewTMultiplexedProcessor() *TMultiplexedProcessor { } } +// ProcessorMap returns a mapping of "{ProcessorName}{MULTIPLEXED_SEPARATOR}{FunctionName}" +// to TProcessorFunction for any registered processors. If there is also a +// DefaultProcessor, the keys for the methods on that processor will simply be +// "{FunctionName}". If the TMultiplexedProcessor has both a DefaultProcessor and +// other registered processors, then the keys will be a mix of both formats. +// +// The implementation differs with other TProcessors in that the map returned is +// a new map, while most TProcessors just return their internal mapping directly. +// This means that edits to the map returned by this implementation of ProcessorMap +// will not affect the underlying mapping within the TMultiplexedProcessor. +func (t *TMultiplexedProcessor) ProcessorMap() map[string]TProcessorFunction { + processorFuncMap := make(map[string]TProcessorFunction) + for name, processor := range t.serviceProcessorMap { + for method, processorFunc := range processor.ProcessorMap() { + processorFuncName := name + MULTIPLEXED_SEPARATOR + method + processorFuncMap[processorFuncName] = processorFunc + } + } + if t.DefaultProcessor != nil { + for method, processorFunc := range t.DefaultProcessor.ProcessorMap() { + processorFuncMap[method] = processorFunc + } + } + return processorFuncMap +} + +// AddToProcessorMap updates the underlying TProcessor ProccessorMaps depending on +// the format of "name". +// +// If "name" is in the format "{ProcessorName}{MULTIPLEXED_SEPARATOR}{FunctionName}", +// then it sets the given TProcessorFunction on the inner TProcessor with the +// ProcessorName component using the FunctionName component. +// +// If "name" is just in the format "{FunctionName}", that is to say there is no +// MULTIPLEXED_SEPARATOR, and the TMultiplexedProcessor has a DefaultProcessor +// configured, then it will set the given TProcessorFunction on the DefaultProcessor +// using the given name. +// +// If there is not a TProcessor available for the given name, then this function +// does nothing. This can happen when there is no TProcessor registered for +// the given ProcessorName or if all that is given is the FunctionName and there +// is no DefaultProcessor set. +func (t *TMultiplexedProcessor) AddToProcessorMap(name string, processorFunc TProcessorFunction) { + components := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2) + if len(components) != 2 { + if t.DefaultProcessor != nil && len(components) == 1 { + t.DefaultProcessor.AddToProcessorMap(components[0], processorFunc) + } + return + } + processorName := components[0] + funcName := components[1] + if processor, ok := t.serviceProcessorMap[processorName]; ok { + processor.AddToProcessorMap(funcName, processorFunc) + } + +} + +// verify that TMultiplexedProcessor implements TProcessor +var _ TProcessor = (*TMultiplexedProcessor)(nil) + func (t *TMultiplexedProcessor) RegisterDefault(processor TProcessor) { t.DefaultProcessor = processor } diff --git a/lib/go/thrift/multiplexed_protocol_test.go b/lib/go/thrift/multiplexed_protocol_test.go new file mode 100644 index 00000000000..8e70ac5976f --- /dev/null +++ b/lib/go/thrift/multiplexed_protocol_test.go @@ -0,0 +1,53 @@ +package thrift + +import ( + "context" + "strings" + "testing" +) + +func TestMultiplexedProcessorMap(t *testing.T) { + name := "test" + processorName := "foo" + processor := &TMultiplexedProcessor{} + processor.RegisterDefault(&mockWrappableProcessor{ + ProcessorFuncs: map[string]TProcessorFunction{ + name: WrappedTProcessorFunction{ + Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { + return true, nil + }, + }, + }, + }) + processor.RegisterProcessor(processorName, &mockWrappableProcessor{ + ProcessorFuncs: map[string]TProcessorFunction{ + name: WrappedTProcessorFunction{ + Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { + return true, nil + }, + }, + }, + }) + + processorMap := processor.ProcessorMap() + if len(processorMap) != 2 { + t.Fatalf("Wrong processor map size %#v", processorMap) + } + for k := range processorMap { + components := strings.SplitN(k, MULTIPLEXED_SEPARATOR, 2) + if len(components) == 1 { + if components[0] != name { + t.Fatalf("Wrong name for default processor func, expected %q, got %q", name, components[0]) + } + } else if len(components) == 2 { + if components[0] != processorName { + t.Errorf("Wrong processor name, expected %q, got %q", processorName, components[0]) + } + if components[1] != name { + t.Errorf("Wrong name for processor func, expected %q, got %q", name, components[1]) + } + } else { + t.Fatalf("Wrong number of components %#v", components) + } + } +} diff --git a/lib/go/thrift/processor_factory.go b/lib/go/thrift/processor_factory.go index e4b132b307c..245a3ccfc98 100644 --- a/lib/go/thrift/processor_factory.go +++ b/lib/go/thrift/processor_factory.go @@ -25,6 +25,16 @@ import "context" // writes to some output stream. type TProcessor interface { Process(ctx context.Context, in, out TProtocol) (bool, TException) + + // ProcessorMap returns a map of thrift method names to TProcessorFunctions. + ProcessorMap() map[string]TProcessorFunction + + // AddToProcessorMap adds the given TProcessorFunction to the internal + // processor map at the given key. + // + // If one is already set at the given key, it will be replaced with the new + // TProcessorFunction. + AddToProcessorMap(string, TProcessorFunction) } type TProcessorFunction interface { From 87462913428f9463c537223f2d23bbbf56cddb43 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Mon, 27 Apr 2020 20:36:34 +0200 Subject: [PATCH 578/756] THRIFT-5188 Occasional ERROR_INSUFFICIENT_BUFFER at WinHttpQueryHeaders() Client: Delphi Patch: Jens Geyer --- lib/delphi/src/Thrift.WinHTTP.pas | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas index abbb0044b13..e6642d9f835 100644 --- a/lib/delphi/src/Thrift.WinHTTP.pas +++ b/lib/delphi/src/Thrift.WinHTTP.pas @@ -1216,6 +1216,7 @@ function TWinHTTPRequestImpl.QueryDataAvailable : DWORD; function TWinHTTPRequestImpl.QueryTotalResponseSize( out dwSize : DWORD) : Boolean; var dwBytes, dwError, dwIndex : DWORD; + bytes : array[0..32-1] of Byte; begin dwBytes := SizeOf( result); dwIndex := DWORD( WINHTTP_NO_HEADER_INDEX); @@ -1224,11 +1225,30 @@ function TWinHTTPRequestImpl.QueryTotalResponseSize( out dwSize : DWORD) : Boole WINHTTP_HEADER_NAME_BY_INDEX, @dwSize, dwBytes, dwIndex); - if not result then begin - dwSize := MAXINT; // we don't know, just return something useful - dwError := GetLastError; - if dwError <> ERROR_WINHTTP_HEADER_NOT_FOUND then ASSERT(FALSE); // anything else would be an real error + if result then Exit; + dwError := GetLastError; + + // Hack: WinHttpQueryHeaders() sometimes returns error 122 even if the buffer is large enough + // According to the docs, WINHTTP_QUERY_FLAG_NUMBER always returns a 32 bit number (which it does!) + // but for some strange reason since win 10 build 18636.815 passing a 4 bytes buffer is not enough anymore + if dwError = ERROR_INSUFFICIENT_BUFFER then begin + dwBytes := sizeof(bytes); + FillChar( bytes[0], dwBytes, 0); + result := WinHttpQueryHeaders( FHandle, + WINHTTP_QUERY_CONTENT_LENGTH or WINHTTP_QUERY_FLAG_NUMBER, + WINHTTP_HEADER_NAME_BY_INDEX, + @bytes[0], dwBytes, + dwIndex); + if result then begin + ASSERT( dwBytes = SizeOf(dwSize)); // result is still a DWORD + Move( bytes[0], dwSize, SizeOf(dwSize)); // copy over result data + Exit; + end; end; + + // header may just not be there + dwSize := MAXINT; // we don't know, just return something useful + ASSERT( dwError = ERROR_WINHTTP_HEADER_NOT_FOUND); // anything else would be an real error end; From 371d92f159d4e518f1de81519b3a9de629ba8970 Mon Sep 17 00:00:00 2001 From: Zezeng Wang <51382517@qq.com> Date: Tue, 28 Apr 2020 14:23:15 +0800 Subject: [PATCH 579/756] THRIFT-5179: Fix generated code for struct's named "a" or "b" Client: cpp --- .../src/thrift/generate/t_cpp_generator.cc | 43 +++++++++++++++---- test/Makefile.am | 1 + test/SpecificNameTest.thrift | 35 +++++++++++++++ test/cpp/CMakeLists.txt | 17 ++++++++ test/cpp/Makefile.am | 3 ++ test/cpp/src/SpecificNameTest.cpp | 29 +++++++++++++ 6 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 test/SpecificNameTest.thrift create mode 100644 test/cpp/src/SpecificNameTest.cpp diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc index c2d88cdcde8..a3ac854df8c 100644 --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc @@ -1281,8 +1281,13 @@ void t_cpp_generator::generate_struct_declaration(ostream& out, if (swap) { // Generate a namespace-scope swap() function - out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name() - << " &b);" << endl << endl; + if (tstruct->get_name() == "a" || tstruct->get_name() == "b") { + out << indent() << "void swap(" << tstruct->get_name() << " &a1, " << tstruct->get_name() + << " &a2);" << endl << endl; + } else { + out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name() + << " &b);" << endl << endl; + } } if (is_user_struct) { @@ -1601,8 +1606,14 @@ void t_cpp_generator::generate_struct_result_writer(ostream& out, * @param tstruct The struct */ void t_cpp_generator::generate_struct_swap(ostream& out, t_struct* tstruct) { - out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name() - << " &b) {" << endl; + if (tstruct->get_name() == "a" || tstruct->get_name() == "b") { + out << indent() << "void swap(" << tstruct->get_name() << " &a1, " << tstruct->get_name() + << " &a2) {" << endl; + } else { + out << indent() << "void swap(" << tstruct->get_name() << " &a, " << tstruct->get_name() + << " &b) {" << endl; + } + indent_up(); // Let argument-dependent name lookup find the correct swap() function to @@ -1617,18 +1628,32 @@ void t_cpp_generator::generate_struct_swap(ostream& out, t_struct* tstruct) { has_nonrequired_fields = true; } - out << indent() << "swap(a." << tfield->get_name() << ", b." << tfield->get_name() << ");" - << endl; + if (tstruct->get_name() == "a" || tstruct->get_name() == "b") { + out << indent() << "swap(a1." << tfield->get_name() << ", a2." << tfield->get_name() << ");" + << endl; + } else { + out << indent() << "swap(a." << tfield->get_name() << ", b." << tfield->get_name() << ");" + << endl; + } } if (has_nonrequired_fields) { - out << indent() << "swap(a.__isset, b.__isset);" << endl; + if (tstruct->get_name() == "a" || tstruct->get_name() == "b") { + out << indent() << "swap(a1.__isset, a2.__isset);" << endl; + } else { + out << indent() << "swap(a.__isset, b.__isset);" << endl; + } } // handle empty structs if (fields.size() == 0) { - out << indent() << "(void) a;" << endl; - out << indent() << "(void) b;" << endl; + if (tstruct->get_name() == "a" || tstruct->get_name() == "b") { + out << indent() << "(void) a1;" << endl; + out << indent() << "(void) a2;" << endl; + } else { + out << indent() << "(void) a;" << endl; + out << indent() << "(void) b;" << endl; + } } scope_down(out); diff --git a/test/Makefile.am b/test/Makefile.am index 608e4881dd6..f1c808ed6d5 100755 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -167,6 +167,7 @@ EXTRA_DIST = \ ThriftTest.thrift \ TypedefTest.thrift \ UnsafeTypes.thrift \ + SpecificNameTest.thrift \ known_failures_Linux.json \ test.py \ tests.json \ diff --git a/test/SpecificNameTest.thrift b/test/SpecificNameTest.thrift new file mode 100644 index 00000000000..165fc31aeea --- /dev/null +++ b/test/SpecificNameTest.thrift @@ -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. + */ + +namespace cpp test.specificname + +struct a { + 1: i32 number, + 2: string message, +} + +struct b { + 1: i32 number, + 2: string message, +} + +service EchoService { + void echoA(1: a arg), + void echoB(2: b arg), +} diff --git a/test/cpp/CMakeLists.txt b/test/cpp/CMakeLists.txt index 367b6decccb..9ecc1718305 100755 --- a/test/cpp/CMakeLists.txt +++ b/test/cpp/CMakeLists.txt @@ -56,6 +56,13 @@ set(crossstressgencpp_SOURCES add_library(crossstressgencpp STATIC ${crossstressgencpp_SOURCES}) LINK_AGAINST_THRIFT_LIBRARY(crossstressgencpp thrift) +set(crossspecificnamegencpp_SOURCES + gen-cpp/EchoService.cpp + gen-cpp/SpecificNameTest_types.cpp +) +add_library(crossspecificnamegencpp STATIC ${crossspecificnamegencpp_SOURCES}) +LINK_AGAINST_THRIFT_LIBRARY(crossspecificnamegencpp thrift) + add_executable(TestServer src/TestServer.cpp) target_link_libraries(TestServer crosstestgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB}) LINK_AGAINST_THRIFT_LIBRARY(TestServer thrift) @@ -86,6 +93,12 @@ if (NOT WIN32 AND NOT CYGWIN) add_test(NAME StressTestNonBlocking COMMAND StressTestNonBlocking) endif() +add_executable(SpecificNameTest src/SpecificNameTest.cpp) +target_link_libraries(SpecificNameTest crossspecificnamegencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB}) +LINK_AGAINST_THRIFT_LIBRARY(SpecificNameTest thrift) +LINK_AGAINST_THRIFT_LIBRARY(SpecificNameTest thriftnb) +add_test(NAME SpecificNameTest COMMAND SpecificNameTest) + # # Common thrift code generation rules # @@ -97,3 +110,7 @@ add_custom_command(OUTPUT gen-cpp/SecondService.cpp gen-cpp/SecondService.h gen- add_custom_command(OUTPUT gen-cpp/Service.cpp COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/StressTest.thrift ) + +add_custom_command(OUTPUT gen-cpp/EchoService.cpp gen-cpp/SpecificNameTest_types.cpp + COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/SpecificNameTest.thrift +) diff --git a/test/cpp/Makefile.am b/test/cpp/Makefile.am index 4f77c150149..d3754f478cf 100755 --- a/test/cpp/Makefile.am +++ b/test/cpp/Makefile.am @@ -103,6 +103,9 @@ gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_constants gen-cpp/Service.cpp: $(top_srcdir)/test/StressTest.thrift $(THRIFT) $(THRIFT) --gen cpp $< +gen-cpp/SpecificNameTest_types.cpp gen-cpp/EchoService.cpp: $(top_srcdir)/test/SpecificName.thrift $(THRIFT) + $(THRIFT) --gen cpp $< + AM_CPPFLAGS = $(BOOST_CPPFLAGS) $(LIBEVENT_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -Igen-cpp -I. AM_CXXFLAGS = -Wall -Wextra -pedantic -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS AM_LDFLAGS = $(BOOST_LDFLAGS) $(LIBEVENT_LDFLAGS) $(ZLIB_LIBS) diff --git a/test/cpp/src/SpecificNameTest.cpp b/test/cpp/src/SpecificNameTest.cpp new file mode 100644 index 00000000000..9c31ac10f3d --- /dev/null +++ b/test/cpp/src/SpecificNameTest.cpp @@ -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. + */ + +int main(int argc, char** argv) { + + //Empty in main function, + //because we just want to test + //whether the generated source code + //(IDL file contains struct named as + //'a' or 'b') can be compiled. + + return 0; +} From 39381695eb456349b02e68d9167181ae41656b73 Mon Sep 17 00:00:00 2001 From: Zezeng Wang <51382517@qq.com> Date: Tue, 28 Apr 2020 14:24:58 +0800 Subject: [PATCH 580/756] Add file and memory buffer tests for Python Client: py --- lib/py/CMakeLists.txt | 1 + lib/py/Makefile.am | 2 + lib/py/test/thrift_transport.py | 70 +++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 lib/py/test/thrift_transport.py diff --git a/lib/py/CMakeLists.txt b/lib/py/CMakeLists.txt index cba2d65de58..909f61a56ab 100644 --- a/lib/py/CMakeLists.txt +++ b/lib/py/CMakeLists.txt @@ -28,5 +28,6 @@ add_custom_target(python_build ALL if(BUILD_TESTING) add_test(PythonTestSSLSocket ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/test_sslsocket.py) add_test(PythonThriftJson ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_json.py) + add_test(PythonThriftTransport ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_transport.py) add_test(PythonThriftJson ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_TBinaryProtocol.py) endif() diff --git a/lib/py/Makefile.am b/lib/py/Makefile.am index de7afd3e89f..69aa4e7851b 100644 --- a/lib/py/Makefile.am +++ b/lib/py/Makefile.am @@ -24,6 +24,7 @@ py3-build: $(PYTHON3) setup.py build py3-test: py3-build $(PYTHON3) test/thrift_json.py + $(PYTHON3) test/thrift_transport.py $(PYTHON3) test/test_sslsocket.py $(PYTHON3) test/thrift_TBinaryProtocol.py else @@ -43,6 +44,7 @@ install-exec-hook: check-local: all py3-test $(PYTHON) test/thrift_json.py + $(PYTHON) test/thrift_transport.py $(PYTHON) test/test_sslsocket.py $(PYTHON) test/thrift_TBinaryProtocol.py diff --git a/lib/py/test/thrift_transport.py b/lib/py/test/thrift_transport.py new file mode 100644 index 00000000000..cb1bb0ce71a --- /dev/null +++ b/lib/py/test/thrift_transport.py @@ -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. +# + +import unittest +import os + +import _import_local_thrift # noqa +from thrift.transport import TTransport + + +class TestTFileObjectTransport(unittest.TestCase): + + def test_TFileObjectTransport(self): + test_dir = os.path.dirname(os.path.abspath(__file__)) + datatxt_path = os.path.join(test_dir, 'data.txt') + buffer = '{"soft":"thrift","version":0.13,"1":true}' + with open(datatxt_path, "w+") as f: + buf = TTransport.TFileObjectTransport(f) + buf.write(buffer) + buf.flush() + buf.close() + + with open(datatxt_path, "rb") as f: + buf = TTransport.TFileObjectTransport(f) + value = buf.read(len(buffer)).decode('utf-8') + self.assertEqual(buffer, value) + buf.close() + os.remove(datatxt_path) + + +class TestMemoryBuffer(unittest.TestCase): + + def test_memorybuffer_write(self): + data = '{"1":[1,"hello"],"a":{"A":"abc"},"bool":true,"num":12345}' + + buffer_w = TTransport.TMemoryBuffer() + buffer_w.write(data.encode('utf-8')) + value = buffer_w.getvalue() + self.assertEqual(value.decode('utf-8'), data) + buffer_w.close() + + def test_memorybuffer_read(self): + data = '{"1":[1, "hello"],"a":{"A":"abc"},"bool":true,"num":12345}' + + buffer_r = TTransport.TMemoryBuffer(data.encode('utf-8')) + value_r = buffer_r.read(len(data)) + value = buffer_r.getvalue() + self.assertEqual(value.decode('utf-8'), data) + self.assertEqual(value_r.decode('utf-8'), data) + buffer_r.close() + + +if __name__ == '__main__': + unittest.main() From 809403d544a83b308f0c8f219719e44ba1ace4c0 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Tue, 28 Apr 2020 22:35:16 +0200 Subject: [PATCH 581/756] Configure Gitbox [skip ci] --- .asf.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .asf.yaml diff --git a/.asf.yaml b/.asf.yaml new file mode 100644 index 00000000000..f859e4cc52c --- /dev/null +++ b/.asf.yaml @@ -0,0 +1,8 @@ +notifications: + commits: commits@thrift.apache.org + issues: dev@thrift.apache.org + pullrequests_status: dev@thrift.apache.org + pullrequests_comment: github@thrift.apache.org + jira_options: link label worklog + + \ No newline at end of file From 9c757973462d5db9ad7eaabc41d9f1a531ed32d2 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Tue, 28 Apr 2020 22:42:55 +0200 Subject: [PATCH 582/756] Configure Gitbox: It's notifications, not github [skip ci] --- .asf.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.asf.yaml b/.asf.yaml index f859e4cc52c..b6b2e894357 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -2,7 +2,7 @@ notifications: commits: commits@thrift.apache.org issues: dev@thrift.apache.org pullrequests_status: dev@thrift.apache.org - pullrequests_comment: github@thrift.apache.org + pullrequests_comment: notifications@thrift.apache.org jira_options: link label worklog \ No newline at end of file From 5cffef964a081314df70b76f8650bd17bfdd55e6 Mon Sep 17 00:00:00 2001 From: Andrew Boyle Date: Thu, 30 Apr 2020 07:12:40 -0700 Subject: [PATCH 583/756] THRIFT-5164: Add middleware framework for Go clients This commit adds a simple middleware framework for Go clients. It provides: * A `ClientMiddleware` function interface used to define the actual middleware * `WrapClient`, the function that you use to wrap a `TClient` in a list of middleware * A helper `WrappedTClient` struct to help with developing middleware Client: go --- .../thrift/example_client_middleware_test.go | 75 +++++++++++++++++++ ...o => example_processor_middleware_test.go} | 4 +- lib/go/thrift/middleware.go | 39 ++++++++++ lib/go/thrift/middleware_test.go | 41 ++++++++-- 4 files changed, 149 insertions(+), 10 deletions(-) create mode 100644 lib/go/thrift/example_client_middleware_test.go rename lib/go/thrift/{example_middleware_test.go => example_processor_middleware_test.go} (89%) diff --git a/lib/go/thrift/example_client_middleware_test.go b/lib/go/thrift/example_client_middleware_test.go new file mode 100644 index 00000000000..e2e11c339f7 --- /dev/null +++ b/lib/go/thrift/example_client_middleware_test.go @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package thrift + +import ( + "context" + "log" +) + +// BEGIN THRIFT GENERATED CODE SECTION +// +// In real code this section should be from thrift generated code instead, +// but for this example we just define some placeholders here. + +type MyEndpointRequest struct{} + +type MyEndpointResponse struct{} + +type MyService interface { + MyEndpoint(ctx context.Context, req *MyEndpointRequest) (*MyEndpointResponse, error) +} + +func NewMyServiceClient(_ TClient) MyService { + // In real code this certainly won't return nil. + return nil +} + +// END THRIFT GENERATED CODE SECTION + +func simpleClientLoggingMiddleware(next TClient) TClient { + return WrappedTClient{ + Wrapped: func(ctx context.Context, method string, args, result TStruct) error { + log.Printf("Before: %q", method) + log.Printf("Args: %#v", args) + err := next.Call(ctx, method, args, result) + log.Printf("After: %q", method) + log.Printf("Result: %#v", result) + if err != nil { + log.Printf("Error: %v", err) + } + return err + }, + } +} + +func ExampleClientMiddleware() { + var ( + trans TTransport + protoFactory TProtocolFactory + ) + var client TClient + client = NewTStandardClient( + protoFactory.GetProtocol(trans), + protoFactory.GetProtocol(trans), + ) + client = WrapClient(client, simpleClientLoggingMiddleware) + myServiceClient := NewMyServiceClient(client) + myServiceClient.MyEndpoint(context.Background(), &MyEndpointRequest{}) +} diff --git a/lib/go/thrift/example_middleware_test.go b/lib/go/thrift/example_processor_middleware_test.go similarity index 89% rename from lib/go/thrift/example_middleware_test.go rename to lib/go/thrift/example_processor_middleware_test.go index 47061103df1..844358ffe9d 100644 --- a/lib/go/thrift/example_middleware_test.go +++ b/lib/go/thrift/example_processor_middleware_test.go @@ -24,7 +24,7 @@ import ( "log" ) -func simpleLoggingMiddleware(name string, next TProcessorFunction) TProcessorFunction { +func simpleProcessorLoggingMiddleware(name string, next TProcessorFunction) TProcessorFunction { return WrappedTProcessorFunction{ Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { log.Printf("Before: %q", name) @@ -46,7 +46,7 @@ func ExampleProcessorMiddleware() { transFactory TTransportFactory protoFactory TProtocolFactory ) - processor = WrapProcessor(processor, simpleLoggingMiddleware) + processor = WrapProcessor(processor, simpleProcessorLoggingMiddleware) server := NewTSimpleServer4(processor, trans, transFactory, protoFactory) log.Fatal(server.Serve()) } diff --git a/lib/go/thrift/middleware.go b/lib/go/thrift/middleware.go index 18f2b99c160..b575e16c42a 100644 --- a/lib/go/thrift/middleware.go +++ b/lib/go/thrift/middleware.go @@ -68,3 +68,42 @@ var ( _ TProcessorFunction = WrappedTProcessorFunction{} _ TProcessorFunction = (*WrappedTProcessorFunction)(nil) ) + +// ClientMiddleware can be passed to WrapClient in order to wrap TClient calls +// with custom middleware. +type ClientMiddleware func(TClient) TClient + +// WrappedTClient is a convenience struct that implements the TClient interface +// using inner Wrapped function. +// +// This is provided to aid in developing ClientMiddleware. +type WrappedTClient struct { + Wrapped func(ctx context.Context, method string, args, result TStruct) error +} + +// Call implements the TClient interface by calling and returning c.Wrapped. +func (c WrappedTClient) Call(ctx context.Context, method string, args, result TStruct) error { + return c.Wrapped(ctx, method, args, result) +} + +// verify that WrappedTClient implements TClient +var ( + _ TClient = WrappedTClient{} + _ TClient = (*WrappedTClient)(nil) +) + +// WrapClient wraps the given TClient in the given middlewares. +// +// Middlewares will be called in the order that they are defined: +// +// 1. Middlewares[0] +// 2. Middlewares[1] +// ... +// N. Middlewares[n] +func WrapClient(client TClient, middlewares ...ClientMiddleware) TClient { + // Add middlewares in reverse so the first in the list is the outermost. + for i := len(middlewares) - 1; i >= 0; i-- { + client = middlewares[i](client) + } + return client +} diff --git a/lib/go/thrift/middleware_test.go b/lib/go/thrift/middleware_test.go index 81cbc7bd1e6..2a4d1f9574d 100644 --- a/lib/go/thrift/middleware_test.go +++ b/lib/go/thrift/middleware_test.go @@ -32,7 +32,15 @@ func (c *counter) incr() { c.count++ } -func testMiddleware(c *counter) ProcessorMiddleware { +func newCounter(t *testing.T) *counter { + c := counter{} + if c.count != 0 { + t.Fatal("Unexpected initial count.") + } + return &c +} + +func testProcessorMiddleware(c *counter) ProcessorMiddleware { return func(name string, next TProcessorFunction) TProcessorFunction { return WrappedTProcessorFunction{ Wrapped: func(ctx context.Context, seqId int32, in, out TProtocol) (bool, TException) { @@ -43,12 +51,15 @@ func testMiddleware(c *counter) ProcessorMiddleware { } } -func newCounter(t *testing.T) *counter { - c := counter{} - if c.count != 0 { - t.Fatal("Unexpected initial count.") +func testClientMiddleware(c *counter) ClientMiddleware { + return func(next TClient) TClient { + return WrappedTClient{ + Wrapped: func(ctx context.Context, method string, args, result TStruct) error { + c.incr() + return next.Call(ctx, method, args, result) + }, + } } - return &c } func TestWrapProcessor(t *testing.T) { @@ -64,7 +75,7 @@ func TestWrapProcessor(t *testing.T) { } c := newCounter(t) ctx := setMockWrappableProcessorName(context.Background(), name) - wrapped := WrapProcessor(processor, testMiddleware(c)) + wrapped := WrapProcessor(processor, testProcessorMiddleware(c)) wrapped.Process(ctx, nil, nil) if c.count != 1 { t.Fatalf("Unexpected count value %v", c.count) @@ -94,7 +105,7 @@ func TestWrapTMultiplexedProcessor(t *testing.T) { }, }, }) - wrapped := WrapProcessor(processor, testMiddleware(c)) + wrapped := WrapProcessor(processor, testProcessorMiddleware(c)) ctx := setMockWrappableProcessorName(context.Background(), name) in := NewStoredMessageProtocol(nil, name, 1, 1) wrapped.Process(ctx, in, nil) @@ -108,3 +119,17 @@ func TestWrapTMultiplexedProcessor(t *testing.T) { t.Fatalf("Unexpected count value %v", c.count) } } + +func TestWrapClient(t *testing.T) { + client := WrappedTClient{ + Wrapped: func(ctx context.Context, method string, args, result TStruct) error { + return nil + }, + } + c := newCounter(t) + wrapped := WrapClient(client, testClientMiddleware(c)) + wrapped.Call(context.Background(), "test", nil, nil) + if c.count != 1 { + t.Fatalf("Unexpected count value %v", c.count) + } +} From 48730688fbf00b03f0dcdf3eb44963ad894bd98e Mon Sep 17 00:00:00 2001 From: Duru Can Celasun Date: Thu, 30 Apr 2020 17:00:24 +0100 Subject: [PATCH 584/756] Update PR template Clarify that [skip ci] needs to be in the commit message, not the PR text. --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 08051ac0224..6a18a51847c 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -7,7 +7,7 @@ - [ ] If a ticket exists: Does your pull request title follow the pattern "THRIFT-NNNN: describe my issue"? - [ ] Did you squash your changes to a single commit? (not required, but preferred) - [ ] Did you do your best to avoid breaking changes? If one was needed, did you label the Jira ticket with "Breaking-Change"? -- [ ] If your change does not involve any code, add ` [skip ci]` at the end of your pull request to free up build resources. +- [ ] If your change does not involve any code, include `[skip ci]` anywhere in the commit message to free up build resources. 0.6.0 Yes -6.x10.x +10.x10.x YesYesYes YesYesYes YesYesYesYes diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index dca687fd429..315b2986534 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -17,7 +17,7 @@ # - dart: does not come with Ubuntu so we're installing 2.0.0-1 for coverage # - dotnet: does not come with Ubuntu # - go: Xenial comes with 1.6, but we need 1.10 or later -# - nodejs: Xenial comes with 4.2.6 which exits LTS April 2018, so we're installing 8.x +# - nodejs: Xenial comes with 4.2.6 which exits LTS April 2018, so we're installing 10.x # - ocaml: causes stack overflow error, just started March 2018 not sure why # @@ -54,7 +54,7 @@ RUN apt-get update && \ # node.js curl -sL https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - && \ - echo "deb https://deb.nodesource.com/node_8.x xenial main" | tee /etc/apt/sources.list.d/nodesource.list &&\ + echo "deb https://deb.nodesource.com/node_10.x xenial main" | tee /etc/apt/sources.list.d/nodesource.list && \ # ruby 2.4 apt-add-repository ppa:brightbox/ruby-ng From 64ac65ea7e0763c32d6dca988a2c779f89bece84 Mon Sep 17 00:00:00 2001 From: Tim Heilig Date: Thu, 7 May 2020 23:19:16 -0700 Subject: [PATCH 591/756] THRIFT-5199: Fix infinite loop writing to closed TSocket in PHP Client: php Patch: Tim Heilig This closes #2134 --- lib/php/lib/Transport/TSocket.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/php/lib/Transport/TSocket.php b/lib/php/lib/Transport/TSocket.php index 5147efa6301..374037a2739 100644 --- a/lib/php/lib/Transport/TSocket.php +++ b/lib/php/lib/Transport/TSocket.php @@ -328,7 +328,8 @@ public function write($buf) if ($writable > 0) { // write buffer to stream $written = fwrite($this->handle_, $buf); - if ($written === -1 || $written === false) { + $closed_socket = $written === 0 && feof($this->handle_); + if ($written === -1 || $written === false || $closed_socket) { throw new TTransportException( 'TSocket: Could not write ' . TStringFuncFactory::create()->strlen($buf) . ' bytes ' . $this->host_ . ':' . $this->port_ From 26e6c84cde490a22d39c43ba3903dd94bbb8497f Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Wed, 6 May 2020 14:37:43 +0800 Subject: [PATCH 592/756] Add testcase for compactprotocol(python) Client: py Patch: zeshuai007 <51382517@qq.com> This closes #2129 --- lib/py/CMakeLists.txt | 1 + lib/py/Makefile.am | 3 + lib/py/test/thrift_TCompactProtocol.py | 288 +++++++++++++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 lib/py/test/thrift_TCompactProtocol.py diff --git a/lib/py/CMakeLists.txt b/lib/py/CMakeLists.txt index 18697d011e8..d56c7099bc6 100644 --- a/lib/py/CMakeLists.txt +++ b/lib/py/CMakeLists.txt @@ -31,4 +31,5 @@ if(BUILD_TESTING) add_test(PythonThriftTransport ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_transport.py) add_test(PythonThriftTBinaryProtocol ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_TBinaryProtocol.py) add_test(PythonThriftTZlibTransport ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_TZlibTransport.py) + add_test(PythonThriftProtocol ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_TCompactProtocol.py) endif() diff --git a/lib/py/Makefile.am b/lib/py/Makefile.am index 9d0b06be86c..1d450ee10d0 100644 --- a/lib/py/Makefile.am +++ b/lib/py/Makefile.am @@ -28,6 +28,7 @@ py3-test: py3-build $(PYTHON3) test/test_sslsocket.py $(PYTHON3) test/thrift_TBinaryProtocol.py $(PYTHON3) test/thrift_TZlibTransport.py + $(PYTHON3) test/thrift_TCompactProtocol.py else py3-build: py3-test: @@ -49,6 +50,8 @@ check-local: all py3-test $(PYTHON) test/test_sslsocket.py $(PYTHON) test/thrift_TBinaryProtocol.py $(PYTHON) test/thrift_TZlibTransport.py + $(PYTHON) test/thrift_TCompactProtocol.py + clean-local: $(RM) -r build diff --git a/lib/py/test/thrift_TCompactProtocol.py b/lib/py/test/thrift_TCompactProtocol.py new file mode 100644 index 00000000000..1d6af8ee2ad --- /dev/null +++ b/lib/py/test/thrift_TCompactProtocol.py @@ -0,0 +1,288 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +import _import_local_thrift # noqa +from thrift.protocol import TCompactProtocol +from thrift.transport import TTransport +import unittest + +CLEAR = 0 +FIELD_WRITE = 1 +VALUE_WRITE = 2 +CONTAINER_WRITE = 3 +BOOL_WRITE = 4 +FIELD_READ = 5 +CONTAINER_READ = 6 +VALUE_READ = 7 +BOOL_READ = 8 + + +def testNaked(type, data): + buf = TTransport.TMemoryBuffer() + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TCompactProtocol.TCompactProtocol(transport) + + if type.capitalize() == 'Byte': + protocol.state = VALUE_WRITE + protocol.writeByte(data) + + elif type.capitalize() == 'I16': + protocol.state = CONTAINER_WRITE + protocol.writeI16(data) + + elif type.capitalize() == 'I32': + protocol.state = CONTAINER_WRITE + protocol.writeI32(data) + + elif type.capitalize() == 'I64': + protocol.state = CONTAINER_WRITE + protocol.writeI64(data) + + elif type.capitalize() == 'String': + protocol.state = CONTAINER_WRITE + protocol.writeString(data) + + elif type.capitalize() == 'Double': + protocol.state = VALUE_WRITE + protocol.writeDouble(data) + + elif type.capitalize() == 'Binary': + protocol.state = FIELD_WRITE + protocol.writeBinary(data) + + elif type.capitalize() == 'Bool': + protocol.state = CONTAINER_WRITE + protocol.writeBool(True) + + transport.flush() + data_r = buf.getvalue() + buf = TTransport.TMemoryBuffer(data_r) + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TCompactProtocol.TCompactProtocol(transport) + if type.capitalize() == 'Byte': + protocol.state = VALUE_READ + return protocol.readByte() + + elif type.capitalize() == 'I16': + protocol.state = CONTAINER_READ + return protocol.readI16() + + elif type.capitalize() == 'I32': + protocol.state = CONTAINER_READ + return protocol.readI32() + + elif type.capitalize() == 'I64': + protocol.state = CONTAINER_READ + return protocol.readI64() + + elif type.capitalize() == 'String': + protocol.state = VALUE_READ + return protocol.readString() + + elif type.capitalize() == 'Double': + protocol.state = VALUE_READ + return protocol.readDouble() + + elif type.capitalize() == 'Binary': + protocol.state = FIELD_READ + return protocol.readBinary() + + elif type.capitalize() == 'Bool': + protocol.state = CONTAINER_READ + return protocol.readBool() + + +def testField(type, data): + TType = {"Bool": 2, "Byte": 3, "Binary": 5, "I16": 6, "I32": 8, "I64": 10, "Double": 11, "String": 12} + buf = TTransport.TMemoryBuffer() + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TCompactProtocol.TCompactProtocol(transport) + protocol.writeStructBegin('struct') + protocol.writeFieldBegin("field", TType[type.capitalize()], 10) + if type.capitalize() == 'Byte': + protocol.writeByte(data) + + elif type.capitalize() == 'I16': + protocol.writeI16(data) + + elif type.capitalize() == 'I32': + protocol.writeI32(data) + + elif type.capitalize() == 'I64': + protocol.writeI64(data) + + elif type.capitalize() == 'String': + protocol.writeString(data) + + elif type.capitalize() == 'Double': + protocol.writeDouble(data) + + elif type.capitalize() == 'Binary': + protocol.writeBinary(data) + + elif type.capitalize() == 'Bool': + protocol.writeBool(data) + + protocol.writeFieldEnd() + protocol.writeStructEnd() + + transport.flush() + data_r = buf.getvalue() + + buf = TTransport.TMemoryBuffer(data_r) + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TCompactProtocol.TCompactProtocol(transport) + protocol.readStructBegin() + protocol.readFieldBegin() + if type.capitalize() == 'Byte': + return protocol.readByte() + + elif type.capitalize() == 'I16': + return protocol.readI16() + + elif type.capitalize() == 'I32': + return protocol.readI32() + + elif type.capitalize() == 'I64': + return protocol.readI32() + + elif type.capitalize() == 'String': + return protocol.readString() + + elif type.capitalize() == 'Double': + return protocol.readDouble() + + elif type.capitalize() == 'Binary': + return protocol.readBinary() + + elif type.capitalize() == 'Bool': + return protocol.readBool() + + protocol.readFieldEnd() + protocol.readStructEnd() + + +def testMessage(data): + message = {} + message['name'] = data[0] + message['type'] = data[1] + message['seqid'] = data[2] + + buf = TTransport.TMemoryBuffer() + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TCompactProtocol.TCompactProtocol(transport) + protocol.writeMessageBegin(message['name'], message['type'], message['seqid']) + protocol.writeMessageEnd() + + transport.flush() + data_r = buf.getvalue() + + buf = TTransport.TMemoryBuffer(data_r) + transport = TTransport.TBufferedTransportFactory().getTransport(buf) + protocol = TCompactProtocol.TCompactProtocol(transport) + result = protocol.readMessageBegin() + protocol.readMessageEnd() + return result + + +class TestTCompactProtocol(unittest.TestCase): + + def __init__(self, *args, **kwargs): + unittest.TestCase.__init__(self, *args, **kwargs) + + def test_TCompactProtocol_write_read(self): + try: + testNaked('Byte', 123) + for i in range(0, 128): + self.assertEqual(i, testField('Byte', i)) + self.assertEqual(-i, testField('Byte', -i)) + + self.assertEqual(0, testNaked("I16", 0)) + self.assertEqual(1, testNaked("I16", 1)) + self.assertEqual(15000, testNaked("I16", 15000)) + self.assertEqual(0x7fff, testNaked('I16', 0x7fff)) + self.assertEqual(-1, testNaked('I16', -1)) + self.assertEqual(-15000, testNaked('I16', -15000)) + self.assertEqual(-0x7fff, testNaked('I16', -0x7fff)) + self.assertEqual(32767, testNaked('I16', 32767)) + + self.assertEqual(0, testField('I16', 0)) + self.assertEqual(1, testField('I16', 1)) + self.assertEqual(7, testField('I16', 7)) + self.assertEqual(150, testField('I16', 150)) + self.assertEqual(15000, testField('I16', 15000)) + self.assertEqual(0x7fff, testField('I16', 0x7fff)) + self.assertEqual(-1, testField('I16', -1)) + self.assertEqual(-7, testField('I16', -7)) + self.assertEqual(-150, testField('I16', -150)) + self.assertEqual(-15000, testField('I16', -15000)) + self.assertEqual(-0xfff, testField('I16', -0xfff)) + + self.assertEqual(0, testNaked('I32', 0)) + self.assertEqual(1, testNaked('I32', 1)) + self.assertEqual(15000, testNaked('I32', 15000)) + self.assertEqual(0xfff, testNaked('I32', 0xfff)) + self.assertEqual(-1, testNaked('I32', -1)) + self.assertEqual(-15000, testNaked('I32', -15000)) + self.assertEqual(-0xfff, testNaked('I32', -0xfff)) + self.assertEqual(2147483647, testNaked('I32', 2147483647)) + self.assertEqual(-2147483647, testNaked('I32', -2147483647)) + + self.assertEqual(0, testField('I32', 0)) + self.assertEqual(1, testField('I32', 1)) + self.assertEqual(7, testField('I32', 7)) + self.assertEqual(150, testField('I32', 150)) + self.assertEqual(15000, testField('I32', 15000)) + self.assertEqual(31337, testField('I32', 31337)) + self.assertEqual(0xffff, testField('I32', 0xffff)) + self.assertEqual(0xffffff, testField('I32', 0xffffff)) + self.assertEqual(-1, testField('I32', -1)) + self.assertEqual(-7, testField('I32', -7)) + self.assertEqual(-150, testField('I32', -150)) + self.assertEqual(-15000, testField('I32', -15000)) + self.assertEqual(-0xffff, testField('I32', -0xffff)) + self.assertEqual(-0xffffff, testField('I32', -0xffffff)) + + self.assertEqual(9223372036854775807, testNaked("I64", 9223372036854775807)) + self.assertEqual(-9223372036854775807, testNaked('I64', -9223372036854775807)) + self.assertEqual(-0, testNaked('I64', 0)) + self.assertEqual(True, testNaked('Bool', True)) + self.assertEqual(3.14159261, testNaked('Double', 3.14159261)) + self.assertEqual("hello thrift", testNaked('String', "hello thrift")) + self.assertEqual(True, testField('Bool', True)) + self.assertEqual(3.14159261, testField('Double', 3.14159261)) + self.assertEqual("hello thrift", testField('String', "hello thrift")) + TMessage = {"T_CALL": 1, "T_REPLY": 2, "T_EXCEPTION": 3, "T_ONEWAY": 4} + test_data = [("short message name", TMessage["T_CALL"], 0), + ("1", TMessage["T_REPLY"], 12345), + ("loooooooooooooooooooong", TMessage["T_EXCEPTION"], 1 << 16), + ("one way push", TMessage["T_ONEWAY"], 12), + ("JANKY", TMessage["T_CALL"], 0)] + for dt in test_data: + result = testMessage(dt) + self.assertEqual(result[0], dt[0]) + self.assertEqual(result[1], dt[1]) + self.assertEqual(result[2], dt[2]) + except Exception as e: + print("Assertion fail") + raise e + + +if __name__ == "__main__": + unittest.main() From be3f7321cf0b7cff5d178ac09da02fc68dac6bd5 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Thu, 14 May 2020 00:28:44 -0700 Subject: [PATCH 593/756] Make TTransportException unwrappable on Go 1.13+ Client: go Go 1.13 introduced a new, optional, hidden interface for error implementations to make them unwrappable [1]. We currently already kind of support that (via TTransportException.Err), so just add a new function to make it Go 1.13+ compatible. [1] https://pkg.go.dev/errors@go1.13?tab=doc#pkg-overview --- lib/go/thrift/transport_exception.go | 4 ++++ lib/go/thrift/transport_exception_test.go | 28 +++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/lib/go/thrift/transport_exception.go b/lib/go/thrift/transport_exception.go index 9505b44612d..d2283ea2e5c 100644 --- a/lib/go/thrift/transport_exception.go +++ b/lib/go/thrift/transport_exception.go @@ -60,6 +60,10 @@ func (p *tTransportException) Err() error { return p.err } +func (p *tTransportException) Unwrap() error { + return p.err +} + func NewTTransportException(t int, e string) TTransportException { return &tTransportException{typeId: t, err: errors.New(e)} } diff --git a/lib/go/thrift/transport_exception_test.go b/lib/go/thrift/transport_exception_test.go index b44314f490d..cf26258d92c 100644 --- a/lib/go/thrift/transport_exception_test.go +++ b/lib/go/thrift/transport_exception_test.go @@ -36,25 +36,45 @@ func (t *timeout) Error() string { return fmt.Sprintf("Timeout: %v", t.timedout) } +type unwrapper interface { + Unwrap() error +} + func TestTExceptionTimeout(t *testing.T) { timeout := &timeout{true} exception := NewTTransportExceptionFromError(timeout) if timeout.Error() != exception.Error() { - t.Fatalf("Error did not match: expected %q, got %q", timeout.Error(), exception.Error()) + t.Errorf("Error did not match: expected %q, got %q", timeout.Error(), exception.Error()) } if exception.TypeId() != TIMED_OUT { - t.Fatalf("TypeId was not TIMED_OUT: expected %v, got %v", TIMED_OUT, exception.TypeId()) + t.Errorf("TypeId was not TIMED_OUT: expected %v, got %v", TIMED_OUT, exception.TypeId()) + } + + // NOTE: this can also be replaced by errors.Unwrap, but that requires + // go 1.13+. + if e, ok := exception.(unwrapper); !ok { + t.Error("Expected exception to be unwrappable, it is not.") + } else if e.Unwrap() != timeout { + t.Errorf("Unwrapped exception did not match: expected %v, got %v", timeout, e.Unwrap()) } } func TestTExceptionEOF(t *testing.T) { exception := NewTTransportExceptionFromError(io.EOF) if io.EOF.Error() != exception.Error() { - t.Fatalf("Error did not match: expected %q, got %q", io.EOF.Error(), exception.Error()) + t.Errorf("Error did not match: expected %q, got %q", io.EOF.Error(), exception.Error()) } if exception.TypeId() != END_OF_FILE { - t.Fatalf("TypeId was not END_OF_FILE: expected %v, got %v", END_OF_FILE, exception.TypeId()) + t.Errorf("TypeId was not END_OF_FILE: expected %v, got %v", END_OF_FILE, exception.TypeId()) + } + + // NOTE: this can also be replaced by errors.Unwrap, but that requires + // go 1.13+. + if e, ok := exception.(unwrapper); !ok { + t.Error("Expected exception to be unwrappable, it is not.") + } else if e.Unwrap() != io.EOF { + t.Errorf("Unwrapped exception did not match: expected %v, got %v", io.EOF, e.Unwrap()) } } From ad3e440955c56627da01eb7149a19afe67ce2954 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Tue, 7 Apr 2020 22:17:19 +0200 Subject: [PATCH 594/756] TSocketTransport.cs: Fixed a problem with initializing IPAddress Client: netstd Patch: Mario Emmenlauer This closes #2140 --- lib/netstd/Thrift/Transport/Client/TSocketTransport.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs b/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs index d5591543441..612d3daa426 100644 --- a/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs @@ -58,8 +58,7 @@ public TSocketTransport(string host, int port, TConfiguration config, int timeou if (entry.AddressList.Length == 0) throw new TTransportException(TTransportException.ExceptionType.Unknown, "unable to resolve host name"); - var addr = entry.AddressList[0]; - Host = new IPAddress(addr.GetAddressBytes(), addr.ScopeId); + Host = entry.AddressList[0]; Port = port; TcpClient = new TcpClient(host, port); From 53239655b7f48e741d9112ae8ca739c622268d7c Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Fri, 8 May 2020 15:15:49 +0800 Subject: [PATCH 595/756] THRIFT-3622 Fix deprecated uses of std::auto_ptr Client: cpp Patch: zeshuai007 <51382517@qq.com> This closes #2135 --- compiler/cpp/src/thrift/generate/t_cpp_generator.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc index a3ac854df8c..14d1eb51b45 100644 --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc @@ -2199,7 +2199,7 @@ void t_cpp_generator::generate_service_async_skeleton(t_service* tservice) { << "public " << svcname << "CobSvIf {" << endl << " public:" << endl; indent_up(); f_skeleton << indent() << svcname << "AsyncHandler() {" << endl << indent() - << " syncHandler_ = std::auto_ptr<" << svcname << "Handler>(new " << svcname + << " syncHandler_ = std::unique_ptr<" << svcname << "Handler>(new " << svcname << "Handler);" << endl << indent() << " // Your initialization goes here" << endl << indent() << "}" << endl; f_skeleton << indent() << "virtual ~" << service_name_ << "AsyncHandler();" << endl; @@ -2223,7 +2223,7 @@ void t_cpp_generator::generate_service_async_skeleton(t_service* tservice) { scope_down(f_skeleton); } - f_skeleton << endl << " protected:" << endl << indent() << "std::auto_ptr<" << svcname + f_skeleton << endl << " protected:" << endl << indent() << "std::unique_ptr<" << svcname << "Handler> syncHandler_;" << endl; indent_down(); f_skeleton << "};" << endl << endl; From 261de348fe0e83ca2f4c7398f2f03ff28d3eb81e Mon Sep 17 00:00:00 2001 From: Philipp Hausmann Date: Wed, 22 Apr 2020 16:20:46 +0200 Subject: [PATCH 596/756] THRIFT-5211 Handle incomplete reads correctly Client: Haskell Patch: Philipp Hausmann This closes #2108 The read functions for handles promise to return *up* to the requested number of bytes. This means in case we read less bytes, we should try again to read some more bytes. --- lib/hs/src/Thrift/Transport/Framed.hs | 4 ++-- lib/hs/src/Thrift/Transport/Handle.hs | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/hs/src/Thrift/Transport/Framed.hs b/lib/hs/src/Thrift/Transport/Framed.hs index 42fc43f395b..ad553aed8cf 100644 --- a/lib/hs/src/Thrift/Transport/Framed.hs +++ b/lib/hs/src/Thrift/Transport/Framed.hs @@ -87,11 +87,11 @@ instance Transport t => Transport (FramedTransport t) where readFrame :: Transport t => FramedTransport t -> IO Int readFrame trans = do -- Read and decode the frame size. - szBs <- tRead (wrappedTrans trans) 4 + szBs <- tReadAll (wrappedTrans trans) 4 let sz = fromIntegral (B.decode szBs :: Int32) -- Read the frame and stuff it into the read buffer. - bs <- tRead (wrappedTrans trans) sz + bs <- tReadAll (wrappedTrans trans) sz fillBuf (readBuffer trans) bs -- Return the frame size so that the caller knows whether to expect diff --git a/lib/hs/src/Thrift/Transport/Handle.hs b/lib/hs/src/Thrift/Transport/Handle.hs index ff6295b6779..528a0279315 100644 --- a/lib/hs/src/Thrift/Transport/Handle.hs +++ b/lib/hs/src/Thrift/Transport/Handle.hs @@ -28,6 +28,7 @@ module Thrift.Transport.Handle ) where import Control.Exception ( catch, throw ) +import Control.Monad ( when ) import Data.ByteString.Internal (c2w) import Data.Functor @@ -50,7 +51,13 @@ instance Transport Handle where hLookAhead h LBS.hGetNonBlocking h n tReadAll _ 0 = return mempty - tReadAll h n = LBS.hGet h n `Control.Exception.catch` throwTransportExn + tReadAll h n = do + result <- LBS.hGet h n `Control.Exception.catch` throwTransportExn + let rlen = fromIntegral $ LBS.length result + when (rlen == 0) (throw $ TransportExn "Cannot read. Remote side has closed." TE_UNKNOWN) + if n <= rlen + then return result + else (result `mappend`) <$> tReadAll h (n - rlen) tPeek h = (Just . c2w <$> hLookAhead h) `Control.Exception.catch` handleEOF Nothing tWrite = LBS.hPut tFlush = hFlush From dce229911cd61a441961df2219623fb166b5d139 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 16 May 2020 23:02:27 +0200 Subject: [PATCH 597/756] THRIFT-5210 further refactoring and performance optimizations Client: netstd Patch: Jens Geyer This closes #2146 --- .../CompactProtocolBenchmarks.cs | 2 +- .../Protocols/ProtocolsOperationsTests.cs | 80 ++--- .../Thrift/Processor/TMultiplexedProcessor.cs | 15 +- .../Thrift/Protocol/Entities/TStruct.cs | 6 +- lib/netstd/Thrift/Protocol/TBinaryProtocol.cs | 261 +++++----------- .../Thrift/Protocol/TCompactProtocol.cs | 228 ++++---------- lib/netstd/Thrift/Protocol/TJSONProtocol.cs | 54 ++-- lib/netstd/Thrift/Protocol/TProtocol.cs | 295 +++--------------- .../Protocol/Utilities/TProtocolUtil.cs | 5 +- lib/netstd/Thrift/Server/TServer.cs | 8 +- lib/netstd/Thrift/TApplicationException.cs | 9 +- .../Thrift/Transport/Client/THttpTransport.cs | 16 +- .../Client/TMemoryBufferTransport.cs | 16 +- .../Transport/Client/TNamedPipeTransport.cs | 9 +- .../Transport/Client/TSocketTransport.cs | 5 +- .../Transport/Client/TStreamTransport.cs | 8 +- .../Server/TNamedPipeServerTransport.cs | 16 +- .../Server/TServerSocketTransport.cs | 5 +- .../Server/TTlsServerSocketTransport.cs | 5 +- lib/netstd/Thrift/Transport/TTransport.cs | 30 +- 20 files changed, 293 insertions(+), 780 deletions(-) diff --git a/lib/netstd/Benchmarks/Thrift.Benchmarks/CompactProtocolBenchmarks.cs b/lib/netstd/Benchmarks/Thrift.Benchmarks/CompactProtocolBenchmarks.cs index cb6b07f9474..16dcc766ef8 100644 --- a/lib/netstd/Benchmarks/Thrift.Benchmarks/CompactProtocolBenchmarks.cs +++ b/lib/netstd/Benchmarks/Thrift.Benchmarks/CompactProtocolBenchmarks.cs @@ -29,7 +29,7 @@ namespace Thrift.Benchmarks public class CompactProtocolBenchmarks { private MemoryStream _Stream; - private TCompactProtocol _Protocol; + private TProtocol _Protocol; [Params(10000)] public int NumberOfOperationsPerIteration { get; set; } diff --git a/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs index b8df515dec0..62ab31780b2 100644 --- a/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs +++ b/lib/netstd/Tests/Thrift.IntegrationTests/Protocols/ProtocolsOperationsTests.cs @@ -57,13 +57,13 @@ public async Task WriteReadMessage_Test(Type protocolType, TMessageType messageT { var protocol = tuple.Item2; - await protocol.WriteMessageBeginAsync(expected); - await protocol.WriteMessageEndAsync(); + await protocol.WriteMessageBeginAsync(expected, default); + await protocol.WriteMessageEndAsync(default); stream.Seek(0, SeekOrigin.Begin); - var actualMessage = await protocol.ReadMessageBeginAsync(); - await protocol.ReadMessageEndAsync(); + var actualMessage = await protocol.ReadMessageBeginAsync(default); + await protocol.ReadMessageEndAsync(default); var result = _compareLogic.Compare(expected, actualMessage); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -91,13 +91,13 @@ public async Task WriteReadStruct_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteStructBeginAsync(expected); - await protocol.WriteStructEndAsync(); + await protocol.WriteStructBeginAsync(expected, default); + await protocol.WriteStructEndAsync(default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadStructBeginAsync(); - await protocol.ReadStructEndAsync(); + var actual = await protocol.ReadStructBeginAsync(default); + await protocol.ReadStructEndAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -126,13 +126,13 @@ public async Task WriteReadField_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteFieldBeginAsync(expected); - await protocol.WriteFieldEndAsync(); + await protocol.WriteFieldBeginAsync(expected, default); + await protocol.WriteFieldEndAsync(default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadFieldBeginAsync(); - await protocol.ReadFieldEndAsync(); + var actual = await protocol.ReadFieldBeginAsync(default); + await protocol.ReadFieldEndAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -159,13 +159,13 @@ public async Task WriteReadMap_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteMapBeginAsync(expected); - await protocol.WriteMapEndAsync(); + await protocol.WriteMapBeginAsync(expected, default); + await protocol.WriteMapEndAsync(default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadMapBeginAsync(); - await protocol.ReadMapEndAsync(); + var actual = await protocol.ReadMapBeginAsync(default); + await protocol.ReadMapEndAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -193,13 +193,13 @@ public async Task WriteReadList_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteListBeginAsync(expected); - await protocol.WriteListEndAsync(); + await protocol.WriteListBeginAsync(expected, default); + await protocol.WriteListEndAsync(default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadListBeginAsync(); - await protocol.ReadListEndAsync(); + var actual = await protocol.ReadListBeginAsync(default); + await protocol.ReadListEndAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -226,13 +226,13 @@ public async Task WriteReadSet_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteSetBeginAsync(expected); - await protocol.WriteSetEndAsync(); + await protocol.WriteSetBeginAsync(expected, default); + await protocol.WriteSetEndAsync(default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadSetBeginAsync(); - await protocol.ReadSetEndAsync(); + var actual = await protocol.ReadSetBeginAsync(default); + await protocol.ReadSetEndAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -259,11 +259,11 @@ public async Task WriteReadBool_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteBoolAsync(expected); + await protocol.WriteBoolAsync(expected, default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadBoolAsync(); + var actual = await protocol.ReadBoolAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -290,11 +290,11 @@ public async Task WriteReadByte_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteByteAsync(expected); + await protocol.WriteByteAsync(expected, default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadByteAsync(); + var actual = await protocol.ReadByteAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -321,11 +321,11 @@ public async Task WriteReadI16_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteI16Async(expected); + await protocol.WriteI16Async(expected, default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadI16Async(); + var actual = await protocol.ReadI16Async(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -352,11 +352,11 @@ public async Task WriteReadI32_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteI32Async(expected); + await protocol.WriteI32Async(expected, default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadI32Async(); + var actual = await protocol.ReadI32Async(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -383,11 +383,11 @@ public async Task WriteReadI64_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteI64Async(expected); + await protocol.WriteI64Async(expected, default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadI64Async(); + var actual = await protocol.ReadI64Async(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -414,11 +414,11 @@ public async Task WriteReadDouble_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteDoubleAsync(expected); + await protocol.WriteDoubleAsync(expected, default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadDoubleAsync(); + var actual = await protocol.ReadDoubleAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -445,11 +445,11 @@ public async Task WriteReadString_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteStringAsync(expected); + await protocol.WriteStringAsync(expected, default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadStringAsync(); + var actual = await protocol.ReadStringAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); @@ -476,11 +476,11 @@ public async Task WriteReadBinary_Test(Type protocolType) { var protocol = tuple.Item2; - await protocol.WriteBinaryAsync(expected); + await protocol.WriteBinaryAsync(expected, default); stream?.Seek(0, SeekOrigin.Begin); - var actual = await protocol.ReadBinaryAsync(); + var actual = await protocol.ReadBinaryAsync(default); var result = _compareLogic.Compare(expected, actual); Assert.IsTrue(result.AreEqual, result.DifferencesString); diff --git a/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs b/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs index e5aeaa6c74a..b192210544c 100644 --- a/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs +++ b/lib/netstd/Thrift/Processor/TMultiplexedProcessor.cs @@ -40,10 +40,7 @@ public async Task ProcessAsync(TProtocol iprot, TProtocol oprot) public async Task ProcessAsync(TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); try { @@ -129,14 +126,10 @@ public StoredMessageProtocol(TProtocol protocol, TMessage messageBegin) _msgBegin = messageBegin; } - public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) + public override ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - return _msgBegin; + cancellationToken.ThrowIfCancellationRequested(); + return new ValueTask(_msgBegin); } } } diff --git a/lib/netstd/Thrift/Protocol/Entities/TStruct.cs b/lib/netstd/Thrift/Protocol/Entities/TStruct.cs index e04167e475a..d87608799c1 100644 --- a/lib/netstd/Thrift/Protocol/Entities/TStruct.cs +++ b/lib/netstd/Thrift/Protocol/Entities/TStruct.cs @@ -18,13 +18,13 @@ namespace Thrift.Protocol.Entities { // ReSharper disable once InconsistentNaming - public struct TStruct + public readonly struct TStruct { public TStruct(string name) { Name = name; } - public string Name { get; set; } + public string Name { get; } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs index a00c5c162bb..28b7d297839 100644 --- a/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TBinaryProtocol.cs @@ -38,9 +38,6 @@ public class TBinaryProtocol : TProtocol // The value of 128 is arbitrarily chosen, the required minimum size must be sizeof(long) private byte[] PreAllocatedBuffer = new byte[128]; - private static readonly TStruct AnonymousStruct = new TStruct(string.Empty); - private static readonly TField StopField = new TField() { Type = TType.Stop }; - public TBinaryProtocol(TTransport trans) : this(trans, false, true) { @@ -55,10 +52,7 @@ public TBinaryProtocol(TTransport trans, bool strictRead, bool strictWrite) public override async Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); if (StrictWrite) { @@ -75,65 +69,47 @@ public override async Task WriteMessageBeginAsync(TMessage message, Cancellation } } - public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + public override Task WriteMessageEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } - public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + public override Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } - public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + public override Task WriteStructEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } - + cancellationToken.ThrowIfCancellationRequested(); await WriteByteAsync((sbyte) field.Type, cancellationToken); await WriteI16Async(field.ID, cancellationToken); } - public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + public override Task WriteFieldEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); await WriteByteAsync((sbyte) TType.Stop, cancellationToken); } public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); PreAllocatedBuffer[0] = (byte)map.KeyType; PreAllocatedBuffer[1] = (byte)map.ValueType; @@ -142,69 +118,47 @@ public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancel await WriteI32Async(map.Count, cancellationToken); } - public override async Task WriteMapEndAsync(CancellationToken cancellationToken) - + public override Task WriteMapEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async Task WriteListBeginAsync(TList list, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } - + cancellationToken.ThrowIfCancellationRequested(); await WriteByteAsync((sbyte) list.ElementType, cancellationToken); await WriteI32Async(list.Count, cancellationToken); } - public override async Task WriteListEndAsync(CancellationToken cancellationToken) + public override Task WriteListEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } - + cancellationToken.ThrowIfCancellationRequested(); await WriteByteAsync((sbyte) set.ElementType, cancellationToken); await WriteI32Async(set.Count, cancellationToken); } - public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + public override Task WriteSetEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } - + cancellationToken.ThrowIfCancellationRequested(); await WriteByteAsync(b ? (sbyte) 1 : (sbyte) 0, cancellationToken); } public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); PreAllocatedBuffer[0] = (byte)b; @@ -212,10 +166,8 @@ public override async Task WriteByteAsync(sbyte b, CancellationToken cancellatio } public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); + BinaryPrimitives.WriteInt16BigEndian(PreAllocatedBuffer, i16); await Trans.WriteAsync(PreAllocatedBuffer, 0, 2, cancellationToken); @@ -223,10 +175,7 @@ public override async Task WriteI16Async(short i16, CancellationToken cancellati public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); BinaryPrimitives.WriteInt32BigEndian(PreAllocatedBuffer, i32); @@ -236,10 +185,7 @@ public override async Task WriteI32Async(int i32, CancellationToken cancellation public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); BinaryPrimitives.WriteInt64BigEndian(PreAllocatedBuffer, i64); @@ -248,10 +194,7 @@ public override async Task WriteI64Async(long i64, CancellationToken cancellatio public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); await WriteI64Async(BitConverter.DoubleToInt64Bits(d), cancellationToken); } @@ -259,10 +202,7 @@ public override async Task WriteDoubleAsync(double d, CancellationToken cancella public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); await WriteI32Async(bytes.Length, cancellationToken); await Trans.WriteAsync(bytes, 0, bytes.Length, cancellationToken); @@ -270,10 +210,7 @@ public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken canc public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); var message = new TMessage(); var size = await ReadI32Async(cancellationToken); @@ -303,39 +240,27 @@ public override async ValueTask ReadMessageBeginAsync(CancellationToke return message; } - public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + public override Task ReadMessageEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } - public override async ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) + public override ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } - - return AnonymousStruct; + cancellationToken.ThrowIfCancellationRequested(); + return new ValueTask(AnonymousStruct); } - public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + public override Task ReadStructEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - + cancellationToken.ThrowIfCancellationRequested(); var type = (TType)await ReadByteAsync(cancellationToken); if (type == TType.Stop) @@ -349,21 +274,16 @@ public override async ValueTask ReadFieldBeginAsync(CancellationToken ca }; } - public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + public override Task ReadFieldEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - + cancellationToken.ThrowIfCancellationRequested(); + var map = new TMap { KeyType = (TType) await ReadByteAsync(cancellationToken), @@ -374,20 +294,15 @@ public override async ValueTask ReadMapBeginAsync(CancellationToken cancel return map; } - public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + public override Task ReadMapEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); var list = new TList { @@ -398,20 +313,15 @@ public override async ValueTask ReadListBeginAsync(CancellationToken canc return list; } - public override async Task ReadListEndAsync(CancellationToken cancellationToken) + public override Task ReadListEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); var set = new TSet { @@ -422,30 +332,22 @@ public override async ValueTask ReadSetBeginAsync(CancellationToken cancel return set; } - public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + public override Task ReadSetEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async ValueTask ReadBoolAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); return await ReadByteAsync(cancellationToken) == 1; } public override async ValueTask ReadByteAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 1, cancellationToken); return (sbyte)PreAllocatedBuffer[0]; @@ -453,10 +355,7 @@ public override async ValueTask ReadByteAsync(CancellationToken cancellat public override async ValueTask ReadI16Async(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 2, cancellationToken); var result = BinaryPrimitives.ReadInt16BigEndian(PreAllocatedBuffer); @@ -465,10 +364,7 @@ public override async ValueTask ReadI16Async(CancellationToken cancellati public override async ValueTask ReadI32Async(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 4, cancellationToken); @@ -479,10 +375,7 @@ public override async ValueTask ReadI32Async(CancellationToken cancellation public override async ValueTask ReadI64Async(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken); return BinaryPrimitives.ReadInt64BigEndian(PreAllocatedBuffer); @@ -490,10 +383,7 @@ public override async ValueTask ReadI64Async(CancellationToken cancellatio public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); var d = await ReadI64Async(cancellationToken); return BitConverter.Int64BitsToDouble(d); @@ -501,10 +391,7 @@ public override async ValueTask ReadDoubleAsync(CancellationToken cancel public override async ValueTask ReadBinaryAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); var size = await ReadI32Async(cancellationToken); Transport.CheckReadBytesAvailable(size); @@ -515,10 +402,7 @@ public override async ValueTask ReadBinaryAsync(CancellationToken cancel public override async ValueTask ReadStringAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); var size = await ReadI32Async(cancellationToken); return size > 0 ? await ReadStringBodyAsync(size, cancellationToken) : string.Empty; @@ -526,10 +410,7 @@ public override async ValueTask ReadStringAsync(CancellationToken cancel private async ValueTask ReadStringBodyAsync(int size, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); if (size <= PreAllocatedBuffer.Length) { diff --git a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs index bb531f42eda..066b327227c 100644 --- a/lib/netstd/Thrift/Protocol/TCompactProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TCompactProtocol.cs @@ -39,8 +39,6 @@ public class TCompactProtocol : TProtocol private const byte TypeMask = 0xE0; // 1110 0000 private const byte TypeBits = 0x07; // 0000 0111 private const int TypeShiftAmount = 5; - private static readonly TStruct AnonymousStruct = new TStruct(string.Empty); - private static readonly TField StopField = new TField(string.Empty, TType.Stop, 0); private const byte NoTypeOverride = 0xFF; @@ -134,12 +132,10 @@ public override async Task WriteMessageBeginAsync(TMessage message, Cancellation await WriteStringAsync(message.Name, cancellationToken); } - public override async Task WriteMessageEndAsync(CancellationToken cancellationToken) + public override Task WriteMessageEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } /// @@ -147,25 +143,23 @@ public override async Task WriteMessageEndAsync(CancellationToken cancellationTo /// use it as an opportunity to put special placeholder markers on the field /// stack so we can get the field id deltas correct. /// - public override async Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) + public override Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); _lastField.Push(_lastFieldId); _lastFieldId = 0; + + return Task.CompletedTask; } - public override async Task WriteStructEndAsync(CancellationToken cancellationToken) + public override Task WriteStructEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); _lastFieldId = _lastField.Pop(); + + return Task.CompletedTask; } private async Task WriteFieldBeginInternalAsync(TField field, byte fieldType, CancellationToken cancellationToken) @@ -208,20 +202,15 @@ public override async Task WriteFieldBeginAsync(TField field, CancellationToken } } - public override async Task WriteFieldEndAsync(CancellationToken cancellationToken) + public override Task WriteFieldEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); PreAllocatedBuffer[0] = Types.Stop; await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); @@ -229,10 +218,7 @@ public override async Task WriteFieldStopAsync(CancellationToken cancellationTok protected async Task WriteCollectionBeginAsync(TType elemType, int size, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); /* Abstract method for writing the start of lists and sets. List and sets on @@ -259,38 +245,28 @@ public override async Task WriteListBeginAsync(TList list, CancellationToken can await WriteCollectionBeginAsync(list.ElementType, list.Count, cancellationToken); } - public override async Task WriteListEndAsync(CancellationToken cancellationToken) + public override Task WriteListEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); await WriteCollectionBeginAsync(set.ElementType, set.Count, cancellationToken); } - public override async Task WriteSetEndAsync(CancellationToken cancellationToken) + public override Task WriteSetEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async Task WriteBoolAsync(bool b, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); /* Write a boolean value. Potentially, this could be a boolean field, in @@ -316,10 +292,7 @@ public override async Task WriteBoolAsync(bool b, CancellationToken cancellation public override async Task WriteByteAsync(sbyte b, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); PreAllocatedBuffer[0] = (byte)b; await Trans.WriteAsync(PreAllocatedBuffer, 0, 1, cancellationToken); @@ -327,10 +300,7 @@ public override async Task WriteByteAsync(sbyte b, CancellationToken cancellatio public override async Task WriteI16Async(short i16, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); Int32ToVarInt(IntToZigzag(i16), ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); @@ -357,10 +327,7 @@ private static void Int32ToVarInt(uint n, ref VarInt varint) public override async Task WriteI32Async(int i32, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); Int32ToVarInt(IntToZigzag(i32), ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); @@ -386,10 +353,7 @@ static private void Int64ToVarInt(ulong n, ref VarInt varint) public override async Task WriteI64Async(long i64, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); Int64ToVarInt(LongToZigzag(i64), ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); @@ -397,20 +361,15 @@ public override async Task WriteI64Async(long i64, CancellationToken cancellatio public override async Task WriteDoubleAsync(double d, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); + BinaryPrimitives.WriteInt64LittleEndian(PreAllocatedBuffer, BitConverter.DoubleToInt64Bits(d)); await Trans.WriteAsync(PreAllocatedBuffer, 0, 8, cancellationToken); } public override async Task WriteStringAsync(string str, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); var buf = ArrayPool.Shared.Rent(Encoding.UTF8.GetByteCount(str)); try @@ -429,10 +388,7 @@ public override async Task WriteStringAsync(string str, CancellationToken cancel public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } + cancellationToken.ThrowIfCancellationRequested(); Int32ToVarInt((uint) bytes.Length, ref PreAllocatedVarInt); await Trans.WriteAsync(PreAllocatedVarInt.bytes, 0, PreAllocatedVarInt.count, cancellationToken); @@ -441,11 +397,8 @@ public override async Task WriteBinaryAsync(byte[] bytes, CancellationToken canc public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return; - } - + cancellationToken.ThrowIfCancellationRequested(); + if (map.Count == 0) { PreAllocatedBuffer[0] = 0; @@ -461,20 +414,15 @@ public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancel } } - public override async Task WriteMapEndAsync(CancellationToken cancellationToken) + public override Task WriteMapEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); var protocolId = (byte) await ReadByteAsync(cancellationToken); if (protocolId != ProtocolId) @@ -497,35 +445,25 @@ public override async ValueTask ReadMessageBeginAsync(CancellationToke return new TMessage(messageName, (TMessageType) type, seqid); } - public override async Task ReadMessageEndAsync(CancellationToken cancellationToken) + public override Task ReadMessageEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } - public override async ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) + public override ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } - - // some magic is here ) + cancellationToken.ThrowIfCancellationRequested(); _lastField.Push(_lastFieldId); _lastFieldId = 0; - return AnonymousStruct; + return new ValueTask(AnonymousStruct); } - public override async Task ReadStructEndAsync(CancellationToken cancellationToken) + public override Task ReadStructEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); /* Doesn't actually consume any wire data, just removes the last field for @@ -534,6 +472,8 @@ this struct from the field stack. // consume the last field we Read off the wire. _lastFieldId = _lastField.Pop(); + + return Task.CompletedTask; } public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) @@ -576,20 +516,15 @@ public override async ValueTask ReadFieldBeginAsync(CancellationToken ca return field; } - public override async Task ReadFieldEndAsync(CancellationToken cancellationToken) + public override Task ReadFieldEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async ValueTask ReadMapBeginAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); /* Read a map header off the wire. If the size is zero, skip Reading the key @@ -604,12 +539,10 @@ and value exType. This means that 0-length maps will yield TMaps without the return map; } - public override async Task ReadMapEndAsync(CancellationToken cancellationToken) + public override Task ReadMapEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async ValueTask ReadSetBeginAsync(CancellationToken cancellationToken) @@ -658,40 +591,28 @@ public override async ValueTask ReadByteAsync(CancellationToken cancellat public override async ValueTask ReadI16Async(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); return (short) ZigzagToInt(await ReadVarInt32Async(cancellationToken)); } public override async ValueTask ReadI32Async(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); return ZigzagToInt(await ReadVarInt32Async(cancellationToken)); } public override async ValueTask ReadI64Async(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); return ZigzagToLong(await ReadVarInt64Async(cancellationToken)); } public override async ValueTask ReadDoubleAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); await Trans.ReadAllAsync(PreAllocatedBuffer, 0, 8, cancellationToken); @@ -746,10 +667,7 @@ public override async ValueTask ReadBinaryAsync(CancellationToken cancel public override async ValueTask ReadListBeginAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); /* Read a list header off the wire. If the list size is 0-14, the size will @@ -771,20 +689,16 @@ true size. return list; } - public override async Task ReadListEndAsync(CancellationToken cancellationToken) + public override Task ReadListEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } - public override async Task ReadSetEndAsync(CancellationToken cancellationToken) + public override Task ReadSetEndAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } private static byte GetCompactType(TType ttype) @@ -796,10 +710,7 @@ private static byte GetCompactType(TType ttype) private async ValueTask ReadVarInt32Async(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); /* Read an i32 from the wire as a varint. The MSB of each byte is set @@ -825,10 +736,7 @@ Read an i32 from the wire as a varint. The MSB of each byte is set private async ValueTask ReadVarInt64Async(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); /* Read an i64 from the wire as a proper varint. The MSB of each byte is set diff --git a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs index 3b2ed06cbc9..2f1ccdb8de8 100644 --- a/lib/netstd/Thrift/Protocol/TJSONProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TJSONProtocol.cs @@ -127,7 +127,7 @@ private async Task WriteJsonStringAsync(byte[] bytes, CancellationToken cancella } else { - await Trans.WriteAsync(bytes.ToArray(), i, 1, cancellationToken); + await Trans.WriteAsync(bytes, i, 1, cancellationToken); } } else @@ -315,12 +315,10 @@ public override async Task WriteFieldEndAsync(CancellationToken cancellationToke await WriteJsonObjectEndAsync(cancellationToken); } - public override async Task WriteFieldStopAsync(CancellationToken cancellationToken) + public override Task WriteFieldStopAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override async Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken) @@ -679,7 +677,8 @@ public override async Task ReadMessageEndAsync(CancellationToken cancellationTok public override async ValueTask ReadStructBeginAsync(CancellationToken cancellationToken) { await ReadJsonObjectStartAsync(cancellationToken); - return new TStruct(); + + return AnonymousStruct; } public override async Task ReadStructEndAsync(CancellationToken cancellationToken) @@ -689,18 +688,19 @@ public override async Task ReadStructEndAsync(CancellationToken cancellationToke public override async ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken) { - var field = new TField(); var ch = await Reader.PeekAsync(cancellationToken); if (ch == TJSONProtocolConstants.RightBrace[0]) { - field.Type = TType.Stop; + return StopField; } - else + + var field = new TField() { - field.ID = (short) await ReadJsonIntegerAsync(cancellationToken); - await ReadJsonObjectStartAsync(cancellationToken); - field.Type = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); - } + ID = (short)await ReadJsonIntegerAsync(cancellationToken) + }; + + await ReadJsonObjectStartAsync(cancellationToken); + field.Type = TJSONProtocolHelper.GetTypeIdForTypeName(await ReadJsonStringAsync(false, cancellationToken)); return field; } @@ -845,20 +845,16 @@ public JSONBaseContext(TJsonProtocol proto) Proto = proto; } - public virtual async Task WriteConditionalDelimiterAsync(CancellationToken cancellationToken) + public virtual Task WriteConditionalDelimiterAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } - public virtual async Task ReadConditionalDelimiterAsync(CancellationToken cancellationToken) + public virtual Task ReadConditionalDelimiterAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public virtual bool EscapeNumbers() @@ -978,10 +974,7 @@ public LookaheadReader(TJsonProtocol proto) ///
public async ValueTask ReadAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); if (_hasData) { @@ -1001,10 +994,7 @@ public async ValueTask ReadAsync(CancellationToken cancellationToken) /// public async ValueTask PeekAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); if (!_hasData) { diff --git a/lib/netstd/Thrift/Protocol/TProtocol.cs b/lib/netstd/Thrift/Protocol/TProtocol.cs index 5275c9cd18c..5b1bec16b53 100644 --- a/lib/netstd/Thrift/Protocol/TProtocol.cs +++ b/lib/netstd/Thrift/Protocol/TProtocol.cs @@ -32,6 +32,10 @@ public abstract class TProtocol : IDisposable protected TTransport Trans; + protected static readonly TStruct AnonymousStruct = new TStruct(string.Empty); + protected static readonly TField StopField = new TField() { Type = TType.Stop }; + + protected TProtocol(TTransport trans) { Trans = trans; @@ -98,299 +102,94 @@ protected void CheckReadBytesAvailable(TMap map) public abstract int GetMinSerializedSize(TType type); - public virtual async Task WriteMessageBeginAsync(TMessage message) - { - await WriteMessageBeginAsync(message, CancellationToken.None); - } - - public abstract Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken); - - public virtual async Task WriteMessageEndAsync() - { - await WriteMessageEndAsync(CancellationToken.None); - } - - public abstract Task WriteMessageEndAsync(CancellationToken cancellationToken); - - public virtual async Task WriteStructBeginAsync(TStruct @struct) - { - await WriteStructBeginAsync(@struct, CancellationToken.None); - } - - public abstract Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken); - - public virtual async Task WriteStructEndAsync() - { - await WriteStructEndAsync(CancellationToken.None); - } - - public abstract Task WriteStructEndAsync(CancellationToken cancellationToken); - - public virtual async Task WriteFieldBeginAsync(TField field) - { - await WriteFieldBeginAsync(field, CancellationToken.None); - } - - public abstract Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken); - - public virtual async Task WriteFieldEndAsync() - { - await WriteFieldEndAsync(CancellationToken.None); - } - - public abstract Task WriteFieldEndAsync(CancellationToken cancellationToken); - - public virtual async Task WriteFieldStopAsync() - { - await WriteFieldStopAsync(CancellationToken.None); - } - - public abstract Task WriteFieldStopAsync(CancellationToken cancellationToken); - - public virtual async Task WriteMapBeginAsync(TMap map) - { - await WriteMapBeginAsync(map, CancellationToken.None); - } - - public abstract Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken); - - public virtual async Task WriteMapEndAsync() - { - await WriteMapEndAsync(CancellationToken.None); - } - - public abstract Task WriteMapEndAsync(CancellationToken cancellationToken); - - public virtual async Task WriteListBeginAsync(TList list) - { - await WriteListBeginAsync(list, CancellationToken.None); - } - - public abstract Task WriteListBeginAsync(TList list, CancellationToken cancellationToken); - - public virtual async Task WriteListEndAsync() - { - await WriteListEndAsync(CancellationToken.None); - } - - public abstract Task WriteListEndAsync(CancellationToken cancellationToken); - - public virtual async Task WriteSetBeginAsync(TSet set) - { - await WriteSetBeginAsync(set, CancellationToken.None); - } + public abstract Task WriteMessageBeginAsync(TMessage message, CancellationToken cancellationToken = default); - public abstract Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken); + public abstract Task WriteMessageEndAsync(CancellationToken cancellationToken = default); - public virtual async Task WriteSetEndAsync() - { - await WriteSetEndAsync(CancellationToken.None); - } + public abstract Task WriteStructBeginAsync(TStruct @struct, CancellationToken cancellationToken = default); - public abstract Task WriteSetEndAsync(CancellationToken cancellationToken); + public abstract Task WriteStructEndAsync(CancellationToken cancellationToken = default); - public virtual async Task WriteBoolAsync(bool b) - { - await WriteBoolAsync(b, CancellationToken.None); - } + public abstract Task WriteFieldBeginAsync(TField field, CancellationToken cancellationToken = default); + + public abstract Task WriteFieldEndAsync(CancellationToken cancellationToken = default); + + public abstract Task WriteFieldStopAsync(CancellationToken cancellationToken = default); - public abstract Task WriteBoolAsync(bool b, CancellationToken cancellationToken); + public abstract Task WriteMapBeginAsync(TMap map, CancellationToken cancellationToken = default); - public virtual async Task WriteByteAsync(sbyte b) - { - await WriteByteAsync(b, CancellationToken.None); - } + public abstract Task WriteMapEndAsync(CancellationToken cancellationToken = default); - public abstract Task WriteByteAsync(sbyte b, CancellationToken cancellationToken); + public abstract Task WriteListBeginAsync(TList list, CancellationToken cancellationToken = default); - public virtual async Task WriteI16Async(short i16) - { - await WriteI16Async(i16, CancellationToken.None); - } + public abstract Task WriteListEndAsync(CancellationToken cancellationToken = default); - public abstract Task WriteI16Async(short i16, CancellationToken cancellationToken); + public abstract Task WriteSetBeginAsync(TSet set, CancellationToken cancellationToken = default); - public virtual async Task WriteI32Async(int i32) - { - await WriteI32Async(i32, CancellationToken.None); - } + public abstract Task WriteSetEndAsync(CancellationToken cancellationToken = default); - public abstract Task WriteI32Async(int i32, CancellationToken cancellationToken); + public abstract Task WriteBoolAsync(bool b, CancellationToken cancellationToken = default); - public virtual async Task WriteI64Async(long i64) - { - await WriteI64Async(i64, CancellationToken.None); - } + public abstract Task WriteByteAsync(sbyte b, CancellationToken cancellationToken = default); - public abstract Task WriteI64Async(long i64, CancellationToken cancellationToken); + public abstract Task WriteI16Async(short i16, CancellationToken cancellationToken = default); - public virtual async Task WriteDoubleAsync(double d) - { - await WriteDoubleAsync(d, CancellationToken.None); - } + public abstract Task WriteI32Async(int i32, CancellationToken cancellationToken = default); - public abstract Task WriteDoubleAsync(double d, CancellationToken cancellationToken); + public abstract Task WriteI64Async(long i64, CancellationToken cancellationToken = default); - public virtual async Task WriteStringAsync(string s) - { - await WriteStringAsync(s, CancellationToken.None); - } + public abstract Task WriteDoubleAsync(double d, CancellationToken cancellationToken = default); - public virtual async Task WriteStringAsync(string s, CancellationToken cancellationToken) + public virtual async Task WriteStringAsync(string s, CancellationToken cancellationToken = default) { var bytes = Encoding.UTF8.GetBytes(s); await WriteBinaryAsync(bytes, cancellationToken); } - public virtual async Task WriteBinaryAsync(byte[] bytes) - { - await WriteBinaryAsync(bytes, CancellationToken.None); - } - - public abstract Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken); - - public virtual async ValueTask ReadMessageBeginAsync() - { - return await ReadMessageBeginAsync(CancellationToken.None); - } - - public abstract ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken); - - public virtual async Task ReadMessageEndAsync() - { - await ReadMessageEndAsync(CancellationToken.None); - } + public abstract Task WriteBinaryAsync(byte[] bytes, CancellationToken cancellationToken = default); - public abstract Task ReadMessageEndAsync(CancellationToken cancellationToken); - - public virtual async ValueTask ReadStructBeginAsync() - { - return await ReadStructBeginAsync(CancellationToken.None); - } + public abstract ValueTask ReadMessageBeginAsync(CancellationToken cancellationToken = default); - public abstract ValueTask ReadStructBeginAsync(CancellationToken cancellationToken); + public abstract Task ReadMessageEndAsync(CancellationToken cancellationToken = default); - public virtual async Task ReadStructEndAsync() - { - await ReadStructEndAsync(CancellationToken.None); - } + public abstract ValueTask ReadStructBeginAsync(CancellationToken cancellationToken = default); - public abstract Task ReadStructEndAsync(CancellationToken cancellationToken); + public abstract Task ReadStructEndAsync(CancellationToken cancellationToken = default); - public virtual async ValueTask ReadFieldBeginAsync() - { - return await ReadFieldBeginAsync(CancellationToken.None); - } + public abstract ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken = default); - public abstract ValueTask ReadFieldBeginAsync(CancellationToken cancellationToken); + public abstract Task ReadFieldEndAsync(CancellationToken cancellationToken = default); - public virtual async Task ReadFieldEndAsync() - { - await ReadFieldEndAsync(CancellationToken.None); - } + public abstract ValueTask ReadMapBeginAsync(CancellationToken cancellationToken = default); - public abstract Task ReadFieldEndAsync(CancellationToken cancellationToken); + public abstract Task ReadMapEndAsync(CancellationToken cancellationToken = default); - public virtual async ValueTask ReadMapBeginAsync() - { - return await ReadMapBeginAsync(CancellationToken.None); - } + public abstract ValueTask ReadListBeginAsync(CancellationToken cancellationToken = default); - public abstract ValueTask ReadMapBeginAsync(CancellationToken cancellationToken); + public abstract Task ReadListEndAsync(CancellationToken cancellationToken = default); - public virtual async Task ReadMapEndAsync() - { - await ReadMapEndAsync(CancellationToken.None); - } + public abstract ValueTask ReadSetBeginAsync(CancellationToken cancellationToken = default); - public abstract Task ReadMapEndAsync(CancellationToken cancellationToken); + public abstract Task ReadSetEndAsync(CancellationToken cancellationToken = default); - public virtual async ValueTask ReadListBeginAsync() - { - return await ReadListBeginAsync(CancellationToken.None); - } + public abstract ValueTask ReadBoolAsync(CancellationToken cancellationToken = default); - public abstract ValueTask ReadListBeginAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadByteAsync(CancellationToken cancellationToken = default); - public virtual async Task ReadListEndAsync() - { - await ReadListEndAsync(CancellationToken.None); - } + public abstract ValueTask ReadI16Async(CancellationToken cancellationToken = default); - public abstract Task ReadListEndAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadI32Async(CancellationToken cancellationToken = default); - public virtual async ValueTask ReadSetBeginAsync() - { - return await ReadSetBeginAsync(CancellationToken.None); - } + public abstract ValueTask ReadI64Async(CancellationToken cancellationToken = default); - public abstract ValueTask ReadSetBeginAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadDoubleAsync(CancellationToken cancellationToken = default); - public virtual async Task ReadSetEndAsync() - { - await ReadSetEndAsync(CancellationToken.None); - } - - public abstract Task ReadSetEndAsync(CancellationToken cancellationToken); - - public virtual async ValueTask ReadBoolAsync() - { - return await ReadBoolAsync(CancellationToken.None); - } - - public abstract ValueTask ReadBoolAsync(CancellationToken cancellationToken); - - public virtual async ValueTask ReadByteAsync() - { - return await ReadByteAsync(CancellationToken.None); - } - - public abstract ValueTask ReadByteAsync(CancellationToken cancellationToken); - - public virtual async ValueTask ReadI16Async() - { - return await ReadI16Async(CancellationToken.None); - } - - public abstract ValueTask ReadI16Async(CancellationToken cancellationToken); - - public virtual async ValueTask ReadI32Async() - { - return await ReadI32Async(CancellationToken.None); - } - - public abstract ValueTask ReadI32Async(CancellationToken cancellationToken); - - public virtual async ValueTask ReadI64Async() - { - return await ReadI64Async(CancellationToken.None); - } - - public abstract ValueTask ReadI64Async(CancellationToken cancellationToken); - - public virtual async ValueTask ReadDoubleAsync() - { - return await ReadDoubleAsync(CancellationToken.None); - } - - public abstract ValueTask ReadDoubleAsync(CancellationToken cancellationToken); - - public virtual async ValueTask ReadStringAsync() - { - return await ReadStringAsync(CancellationToken.None); - } - - public virtual async ValueTask ReadStringAsync(CancellationToken cancellationToken) + public virtual async ValueTask ReadStringAsync(CancellationToken cancellationToken = default) { var buf = await ReadBinaryAsync(cancellationToken); return Encoding.UTF8.GetString(buf, 0, buf.Length); } - public virtual async ValueTask ReadBinaryAsync() - { - return await ReadBinaryAsync(CancellationToken.None); - } - - public abstract ValueTask ReadBinaryAsync(CancellationToken cancellationToken); + public abstract ValueTask ReadBinaryAsync(CancellationToken cancellationToken = default); } } diff --git a/lib/netstd/Thrift/Protocol/Utilities/TProtocolUtil.cs b/lib/netstd/Thrift/Protocol/Utilities/TProtocolUtil.cs index 18f92d8161e..832e46e6c09 100644 --- a/lib/netstd/Thrift/Protocol/Utilities/TProtocolUtil.cs +++ b/lib/netstd/Thrift/Protocol/Utilities/TProtocolUtil.cs @@ -26,10 +26,7 @@ public static class TProtocolUtil { public static async Task SkipAsync(TProtocol protocol, TType type, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); protocol.IncrementRecursionDepth(); try diff --git a/lib/netstd/Thrift/Server/TServer.cs b/lib/netstd/Thrift/Server/TServer.cs index f40f2b7e7b9..3fd0bc5312a 100644 --- a/lib/netstd/Thrift/Server/TServer.cs +++ b/lib/netstd/Thrift/Server/TServer.cs @@ -76,12 +76,10 @@ public virtual void Start() // do nothing } - public virtual async Task ServeAsync(CancellationToken cancellationToken) + public virtual Task ServeAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } } } diff --git a/lib/netstd/Thrift/TApplicationException.cs b/lib/netstd/Thrift/TApplicationException.cs index 67ac2f8c756..514db9a086b 100644 --- a/lib/netstd/Thrift/TApplicationException.cs +++ b/lib/netstd/Thrift/TApplicationException.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -112,10 +112,7 @@ public static async ValueTask ReadAsync(TProtocol inputPr public async Task WriteAsync(TProtocol outputProtocol, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); const string messageTypeFieldName = "message"; const string exTypeFieldName = "exType"; @@ -147,4 +144,4 @@ public async Task WriteAsync(TProtocol outputProtocol, CancellationToken cancell await outputProtocol.WriteStructEndAsync(cancellationToken); } } -} \ No newline at end of file +} diff --git a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs index 0790cc8822e..46071cd4aaa 100644 --- a/lib/netstd/Thrift/Transport/Client/THttpTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/THttpTransport.cs @@ -68,12 +68,10 @@ public THttpTransport(Uri uri, TConfiguration config, IEnumerable ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - return await Task.FromCanceled(cancellationToken); + cancellationToken.ThrowIfCancellationRequested(); if (_inputStream == null) throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No request has been sent"); @@ -130,10 +127,7 @@ public override async ValueTask ReadAsync(byte[] buffer, int offset, int le public override async Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); await _outputStream.WriteAsync(buffer, offset, length, cancellationToken); } diff --git a/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs index 290e50cc5ea..797de4e576a 100644 --- a/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TMemoryBufferTransport.cs @@ -81,12 +81,10 @@ public void SetLength(int value) public override bool IsOpen => true; - public override async Task OpenAsync(CancellationToken cancellationToken) + public override Task OpenAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override void Close() @@ -143,13 +141,11 @@ public override Task WriteAsync(byte[] buffer, int offset, int count, Cancellati return Task.CompletedTask; } - public override async Task FlushAsync(CancellationToken cancellationToken) + public override Task FlushAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); ResetConsumedMessageSize(); + return Task.CompletedTask; } public byte[] GetBuffer() diff --git a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs index 8dab6a063c1..815983ea82c 100644 --- a/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TNamedPipeTransport.cs @@ -101,13 +101,12 @@ public override async Task WriteAsync(byte[] buffer, int offset, int length, Can } } - public override async Task FlushAsync(CancellationToken cancellationToken) + public override Task FlushAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + ResetConsumedMessageSize(); + return Task.CompletedTask; } diff --git a/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs b/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs index 612d3daa426..5e3245b8c40 100644 --- a/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TSocketTransport.cs @@ -106,10 +106,7 @@ public override bool IsOpen public override async Task OpenAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); if (IsOpen) { diff --git a/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs b/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs index ccadad025e3..b397460d7db 100644 --- a/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TStreamTransport.cs @@ -51,12 +51,10 @@ protected Stream InputStream { public override bool IsOpen => true; - public override async Task OpenAsync(CancellationToken cancellationToken) + public override Task OpenAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override void Close() diff --git a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs index 4b82cbd22d5..aea0f865ae9 100644 --- a/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TNamedPipeServerTransport.cs @@ -256,12 +256,10 @@ public ServerTransport(NamedPipeServerStream stream, TConfiguration config) public override bool IsOpen => PipeStream != null && PipeStream.IsConnected; - public override async Task OpenAsync(CancellationToken cancellationToken) + public override Task OpenAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); + return Task.CompletedTask; } public override void Close() @@ -306,14 +304,12 @@ public override async Task WriteAsync(byte[] buffer, int offset, int length, Can } } - public override async Task FlushAsync(CancellationToken cancellationToken) + public override Task FlushAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); ResetConsumedMessageSize(); + return Task.CompletedTask; } protected override void Dispose(bool disposing) diff --git a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs index 6656b641a81..281c7ffe50d 100644 --- a/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TServerSocketTransport.cs @@ -77,10 +77,7 @@ public override bool IsClientPending() protected override async ValueTask AcceptImplementationAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); if (_server == null) { diff --git a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs index 9f74562521d..79d2b1137e5 100644 --- a/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Server/TTlsServerSocketTransport.cs @@ -104,10 +104,7 @@ public override bool IsClientPending() protected override async ValueTask AcceptImplementationAsync(CancellationToken cancellationToken) { - if (cancellationToken.IsCancellationRequested) - { - return await Task.FromCanceled(cancellationToken); - } + cancellationToken.ThrowIfCancellationRequested(); if (_server == null) { diff --git a/lib/netstd/Thrift/Transport/TTransport.cs b/lib/netstd/Thrift/Transport/TTransport.cs index dedd51dc520..3f4245aa2ce 100644 --- a/lib/netstd/Thrift/Transport/TTransport.cs +++ b/lib/netstd/Thrift/Transport/TTransport.cs @@ -73,12 +73,8 @@ public async ValueTask PeekAsync(CancellationToken cancellationToken) return true; } - public virtual async Task OpenAsync() - { - await OpenAsync(CancellationToken.None); - } - public abstract Task OpenAsync(CancellationToken cancellationToken); + public abstract Task OpenAsync(CancellationToken cancellationToken = default); public abstract void Close(); @@ -107,25 +103,14 @@ protected static void ValidateBufferArgs(byte[] buffer, int offset, int length) #endif } - public virtual async ValueTask ReadAsync(byte[] buffer, int offset, int length) - { - return await ReadAsync(buffer, offset, length, CancellationToken.None); - } public abstract ValueTask ReadAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); - public virtual async ValueTask ReadAllAsync(byte[] buffer, int offset, int length) - { - return await ReadAllAsync(buffer, offset, length, CancellationToken.None); - } - public virtual async ValueTask ReadAllAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken) { - ValidateBufferArgs(buffer, offset, length); - - if (cancellationToken.IsCancellationRequested) - return await Task.FromCanceled(cancellationToken); + cancellationToken.ThrowIfCancellationRequested(); + ValidateBufferArgs(buffer, offset, length); if (length <= 0) return 0; @@ -164,11 +149,6 @@ public virtual async ValueTask ReadAllAsync(byte[] buffer, int offset, int } } - public virtual async Task WriteAsync(byte[] buffer) - { - await WriteAsync(buffer, CancellationToken.None); - } - public virtual async Task WriteAsync(byte[] buffer, CancellationToken cancellationToken) { await WriteAsync(buffer, 0, buffer.Length, CancellationToken.None); @@ -181,10 +161,6 @@ public virtual async Task WriteAsync(byte[] buffer, int offset, int length) public abstract Task WriteAsync(byte[] buffer, int offset, int length, CancellationToken cancellationToken); - public virtual async Task FlushAsync() - { - await FlushAsync(CancellationToken.None); - } public abstract Task FlushAsync(CancellationToken cancellationToken); From 1ab096c80af1a2bca73aef78675de914a1834fd9 Mon Sep 17 00:00:00 2001 From: penenin Date: Mon, 18 May 2020 12:27:31 -0700 Subject: [PATCH 598/756] THRIFT-5185: Support for using WebSockets as a server transport Client: cpp --- lib/cpp/CMakeLists.txt | 2 + lib/cpp/Makefile.am | 7 +- lib/cpp/src/thrift/portable_endian.h | 131 ++++++ lib/cpp/src/thrift/transport/THttpServer.cpp | 16 +- lib/cpp/src/thrift/transport/THttpServer.h | 1 + .../src/thrift/transport/TWebSocketServer.cpp | 52 +++ .../src/thrift/transport/TWebSocketServer.h | 416 ++++++++++++++++++ lib/nodejs/test/client.js | 5 + lib/nodejs/test/server.js | 3 + test/cpp/src/TestServer.cpp | 10 +- test/known_failures_Linux.json | 64 +++ test/tests.json | 6 +- 12 files changed, 702 insertions(+), 11 deletions(-) create mode 100644 lib/cpp/src/thrift/portable_endian.h create mode 100644 lib/cpp/src/thrift/transport/TWebSocketServer.cpp create mode 100644 lib/cpp/src/thrift/transport/TWebSocketServer.h diff --git a/lib/cpp/CMakeLists.txt b/lib/cpp/CMakeLists.txt index d705bb3d7a4..29caad4756f 100755 --- a/lib/cpp/CMakeLists.txt +++ b/lib/cpp/CMakeLists.txt @@ -57,6 +57,8 @@ set( thriftcpp_SOURCES src/thrift/transport/TServerSocket.cpp src/thrift/transport/TTransportUtils.cpp src/thrift/transport/TBufferTransports.cpp + src/thrift/transport/TWebSocketServer.h + src/thrift/transport/TWebSocketServer.cpp src/thrift/server/TConnectedClient.cpp src/thrift/server/TServerFramework.cpp src/thrift/server/TSimpleServer.cpp diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index 9b5fb4c1262..f699f832fd5 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -87,6 +87,7 @@ libthrift_la_SOURCES = src/thrift/TApplicationException.cpp \ src/thrift/transport/TNonblockingSSLServerSocket.cpp \ src/thrift/transport/TTransportUtils.cpp \ src/thrift/transport/TBufferTransports.cpp \ + src/thrift/transport/TWebSocketServer.cpp \ src/thrift/server/TConnectedClient.cpp \ src/thrift/server/TServer.cpp \ src/thrift/server/TServerFramework.cpp \ @@ -140,7 +141,8 @@ include_thrift_HEADERS = \ src/thrift/TApplicationException.h \ src/thrift/TLogging.h \ src/thrift/TToString.h \ - src/thrift/TBase.h + src/thrift/TBase.h \ + src/thrift/portable_endian.h include_concurrencydir = $(include_thriftdir)/concurrency include_concurrency_HEADERS = \ @@ -198,7 +200,8 @@ include_transport_HEADERS = \ src/thrift/transport/TTransportUtils.h \ src/thrift/transport/TBufferTransports.h \ src/thrift/transport/TShortReadTransport.h \ - src/thrift/transport/TZlibTransport.h + src/thrift/transport/TZlibTransport.h \ + src/thrift/transport/TWebSocketServer.h include_serverdir = $(include_thriftdir)/server include_server_HEADERS = \ diff --git a/lib/cpp/src/thrift/portable_endian.h b/lib/cpp/src/thrift/portable_endian.h new file mode 100644 index 00000000000..e07010e09fa --- /dev/null +++ b/lib/cpp/src/thrift/portable_endian.h @@ -0,0 +1,131 @@ +// +// endian.h +// +// https://gist.github.com/panzi/6856583 +// +// I, Mathias Panzenböck, place this file hereby into the public domain. Use +// it at your own risk for whatever you like. In case there are +// jurisdictions that don't support putting things in the public domain you +// can also consider it to be "dual licensed" under the BSD, MIT and Apache +// licenses, if you want to. This code is trivial anyway. Consider it an +// example on how to get the endian conversion functions on different +// platforms. + +#ifndef PORTABLE_ENDIAN_H__ +#define PORTABLE_ENDIAN_H__ + +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) + +# define __WINDOWS__ + +#endif + +#if defined(__linux__) || defined(__CYGWIN__) + +# include + +#elif defined(__APPLE__) + +# include + +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) + +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) + +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#elif defined(__OpenBSD__) + +# include + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) + +# include + +# define be16toh(x) betoh16(x) +# define le16toh(x) letoh16(x) + +# define be32toh(x) betoh32(x) +# define le32toh(x) letoh32(x) + +# define be64toh(x) betoh64(x) +# define le64toh(x) letoh64(x) + +#elif defined(__WINDOWS__) + +# include + +# if BYTE_ORDER == LITTLE_ENDIAN + +# define htobe16(x) htons(x) +# define htole16(x) (x) +# define be16toh(x) ntohs(x) +# define le16toh(x) (x) + +# define htobe32(x) htonl(x) +# define htole32(x) (x) +# define be32toh(x) ntohl(x) +# define le32toh(x) (x) + +# if defined(__MINGW32__) +# define htobe64(x) __builtin_bswap64(x) +# define htole64(x) (x) +# define be64toh(x) __builtin_bswap64(x) +# define le64toh(x) (x) +# else +# define htobe64(x) htonll(x) +# define htole64(x) (x) +# define be64toh(x) ntohll(x) +# define le64toh(x) (x) +# endif + +# elif BYTE_ORDER == BIG_ENDIAN + + /* that would be xbox 360 */ +# define htobe16(x) (x) +# define htole16(x) __builtin_bswap16(x) +# define be16toh(x) (x) +# define le16toh(x) __builtin_bswap16(x) + +# define htobe32(x) (x) +# define htole32(x) __builtin_bswap32(x) +# define be32toh(x) (x) +# define le32toh(x) __builtin_bswap32(x) + +# define htobe64(x) (x) +# define htole64(x) __builtin_bswap64(x) +# define be64toh(x) (x) +# define le64toh(x) __builtin_bswap64(x) + +# else + +# error byte order not supported + +# endif + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#else + +# error platform not supported + +#endif + +#endif diff --git a/lib/cpp/src/thrift/transport/THttpServer.cpp b/lib/cpp/src/thrift/transport/THttpServer.cpp index 94ac681e737..98518fd55ed 100644 --- a/lib/cpp/src/thrift/transport/THttpServer.cpp +++ b/lib/cpp/src/thrift/transport/THttpServer.cpp @@ -124,12 +124,7 @@ void THttpServer::flush() { writeBuffer_.getBuffer(&buf, &len); // Construct the HTTP header - std::ostringstream h; - h << "HTTP/1.1 200 OK" << CRLF << "Date: " << getTimeRFC1123() << CRLF << "Server: Thrift/" - << PACKAGE_VERSION << CRLF << "Access-Control-Allow-Origin: *" << CRLF - << "Content-Type: application/x-thrift" << CRLF << "Content-Length: " << len << CRLF - << "Connection: Keep-Alive" << CRLF << CRLF; - string header = h.str(); + string header = getHeader(len); // Write the header, then the data, then flush // cast should be fine, because none of "header" is under attacker control @@ -142,6 +137,15 @@ void THttpServer::flush() { readHeaders_ = true; } +std::string THttpServer::getHeader(uint32_t len) { + std::ostringstream h; + h << "HTTP/1.1 200 OK" << CRLF << "Date: " << getTimeRFC1123() << CRLF << "Server: Thrift/" + << PACKAGE_VERSION << CRLF << "Access-Control-Allow-Origin: *" << CRLF + << "Content-Type: application/x-thrift" << CRLF << "Content-Length: " << len << CRLF + << "Connection: Keep-Alive" << CRLF << CRLF; + return h.str(); +} + std::string THttpServer::getTimeRFC1123() { static const char* Days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static const char* Months[] diff --git a/lib/cpp/src/thrift/transport/THttpServer.h b/lib/cpp/src/thrift/transport/THttpServer.h index 0e83399d110..d2196911c8c 100644 --- a/lib/cpp/src/thrift/transport/THttpServer.h +++ b/lib/cpp/src/thrift/transport/THttpServer.h @@ -35,6 +35,7 @@ class THttpServer : public THttpTransport { void flush() override; protected: + virtual std::string getHeader(uint32_t len); void readHeaders(); void parseHeader(char* header) override; bool parseStatusLine(char* status) override; diff --git a/lib/cpp/src/thrift/transport/TWebSocketServer.cpp b/lib/cpp/src/thrift/transport/TWebSocketServer.cpp new file mode 100644 index 00000000000..9822a7faec8 --- /dev/null +++ b/lib/cpp/src/thrift/transport/TWebSocketServer.cpp @@ -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. + */ + +#include +#include +#include + +#include +#include + +#include + +using std::string; + +namespace apache { +namespace thrift { +namespace transport { + +std::string base64Encode(unsigned char* data, int length) { + std::unique_ptr> base64(BIO_new(BIO_f_base64()), + [](BIO* b) { BIO_free_all(b); }); + BIO_set_flags(base64.get(), BIO_FLAGS_BASE64_NO_NL); + + BIO* dest = BIO_new(BIO_s_mem()); + BIO_push(base64.get(), dest); + BIO_write(base64.get(), data, length); + int ret = BIO_flush(base64.get()); + THRIFT_UNUSED_VARIABLE(ret); + + char* encoded; + length = BIO_get_mem_data(dest, &encoded); + return std::string(encoded, length); +} +} // namespace transport +} // namespace thrift +} // namespace apache diff --git a/lib/cpp/src/thrift/transport/TWebSocketServer.h b/lib/cpp/src/thrift/transport/TWebSocketServer.h new file mode 100644 index 00000000000..8edc286fe67 --- /dev/null +++ b/lib/cpp/src/thrift/transport/TWebSocketServer.h @@ -0,0 +1,416 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TWEBSOCKETSERVER_H_ +#define _THRIFT_TRANSPORT_TWEBSOCKETSERVER_H_ 1 + +#include + +#include +#include +#include + +#include + +#include +#include +#include +#if defined(_MSC_VER) || defined(__MINGW32__) +#include +#define THRIFT_strncasecmp(str1, str2, len) _strnicmp(str1, str2, len) +#define THRIFT_strcasestr(haystack, needle) StrStrIA(haystack, needle) +#else +#define THRIFT_strncasecmp(str1, str2, len) strncasecmp(str1, str2, len) +#define THRIFT_strcasestr(haystack, needle) strcasestr(haystack, needle) +#endif +#if defined(__CYGWIN__) +#include +#endif + +using std::string; + +namespace apache { +namespace thrift { +namespace transport { + +std::string base64Encode(unsigned char* data, int length); + +template +class TWebSocketServer : public THttpServer { +public: + TWebSocketServer(std::shared_ptr transport) + : THttpServer(transport) { + resetHandshake(); + } + + ~TWebSocketServer() override = default; + + uint32_t readAll_virt(uint8_t* buf, uint32_t len) override { + // If we do not have a good handshake, the client will attempt one. + if (!handshakeComplete()) { + resetHandshake(); + THttpServer::read(buf, len); + // If we did not get everything we expected, the handshake failed + // and we need to send a 400 response back. + if (!handshakeComplete()) { + sendBadRequest(); + return 0; + } + // Otherwise, send back the 101 response. + THttpServer::flush(); + } + + uint32_t want = len; + auto have = readBuffer_.available_read(); + + // If we have some data in the buffer, copy it out and return it. + // We have to return it without attempting to read more, since we aren't + // guaranteed that the underlying transport actually has more data, so + // attempting to read from it could block. + if (have > 0 && have >= want) { + return readBuffer_.read(buf, want); + } + + // Read another frame. + if (!readFrame()) { + // EOF. No frame available. + return 0; + } + + // Hand over whatever we have. + uint32_t give = (std::min)(want, readBuffer_.available_read()); + return readBuffer_.read(buf, give); + } + + void flush() override { + writeFrameHeader(); + uint8_t* buffer; + uint32_t length; + writeBuffer_.getBuffer(&buffer, &length); + transport_->write(buffer, length); + transport_->flush(); + writeBuffer_.resetBuffer(); + } + +protected: + std::string getHeader(uint32_t len) override { + THRIFT_UNUSED_VARIABLE(len); + std::ostringstream h; + h << "HTTP/1.1 101 Switching Protocols" << CRLF << "Server: Thrift/" << PACKAGE_VERSION << CRLF + << "Upgrade: websocket" << CRLF << "Connection: Upgrade" << CRLF + << "Sec-WebSocket-Accept: " << acceptKey_ << CRLF << CRLF; + return h.str(); + } + + void parseHeader(char* header) override { + char* colon = strchr(header, ':'); + if (colon == nullptr) { + return; + } + size_t sz = colon - header; + char* value = colon + 1; + + if (THRIFT_strncasecmp(header, "Upgrade", sz) == 0) { + if (THRIFT_strcasestr(value, "websocket") != nullptr) { + upgrade_ = true; + } + } else if (THRIFT_strncasecmp(header, "Connection", sz) == 0) { + if (THRIFT_strcasestr(value, "Upgrade") != nullptr) { + connection_ = true; + } + } else if (THRIFT_strncasecmp(header, "Sec-WebSocket-Key", sz) == 0) { + std::string toHash = value + 1; + toHash += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; + unsigned char hash[20]; + SHA1((const unsigned char*)toHash.c_str(), toHash.length(), hash); + acceptKey_ = base64Encode(hash, 20); + secWebSocketKey_ = true; + } else if (THRIFT_strncasecmp(header, "Sec-WebSocket-Version", sz) == 0) { + if (THRIFT_strcasestr(value, "13") != nullptr) { + secWebSocketVersion_ = true; + } + } + } + + bool parseStatusLine(char* status) override { + char* method = status; + + char* path = strchr(method, ' '); + if (path == nullptr) { + throw TTransportException(string("Bad Status: ") + status); + } + + *path = '\0'; + while (*(++path) == ' ') { + }; + + char* http = strchr(path, ' '); + if (http == nullptr) { + throw TTransportException(string("Bad Status: ") + status); + } + *http = '\0'; + + if (strcmp(method, "GET") == 0) { + // GET method ok, looking for content. + return true; + } + throw TTransportException(string("Bad Status (unsupported method): ") + status); + } + +private: + enum class CloseCode : uint16_t { + NormalClosure = 1000, + GoingAway = 1001, + ProtocolError = 1002, + UnsupportedDataType = 1003, + NoStatusCode = 1005, + AbnormalClosure = 1006, + InvalidData = 1007, + PolicyViolation = 1008, + MessageTooBig = 1009, + ExtensionExpected = 1010, + UnexpectedError = 1011, + NotSecure = 1015 + }; + + enum class Opcode : uint8_t { + Continuation = 0x0, + Text = 0x1, + Binary = 0x2, + Close = 0x8, + Ping = 0x9, + Pong = 0xA + }; + + void failConnection(CloseCode reason) { + writeFrameHeader(Opcode::Close); + auto buffer = htobe16(static_cast(reason)); + transport_->write(reinterpret_cast(&buffer), 2); + transport_->flush(); + transport_->close(); + } + + bool handshakeComplete() { + return upgrade_ && connection_ && secWebSocketKey_ && secWebSocketVersion_; + } + + void pong() { + writeFrameHeader(Opcode::Pong); + uint8_t* buffer; + uint32_t size; + readBuffer_.getBuffer(&buffer, &size); + transport_->write(buffer, size); + transport_->flush(); + } + + bool readFrame() { + uint8_t headerBuffer[8]; + + auto read = transport_->read(headerBuffer, 2); + if (read < 2) { + return false; + } + // Since Thrift has its own message end marker and we read frame by frame, + // it doesn't really matter if the frame is marked as FIN. + // Capture it only for debugging only. + auto fin = (headerBuffer[0] & 0x80) != 0; + THRIFT_UNUSED_VARIABLE(fin); + + // RSV1, RSV2, RSV3 + if ((headerBuffer[0] & 0x70) != 0) { + failConnection(CloseCode::ProtocolError); + throw TTransportException(TTransportException::CORRUPTED_DATA, + "Reserved bits must be zeroes"); + } + + auto opcode = (Opcode)(headerBuffer[0] & 0x0F); + + // Mask + if ((headerBuffer[1] & 0x80) == 0) { + failConnection(CloseCode::ProtocolError); + throw TTransportException(TTransportException::CORRUPTED_DATA, + "Messages from the client must be masked"); + } + + // Read the length + uint64_t payloadLength = headerBuffer[1] & 0x7F; + if (payloadLength == 126) { + read = transport_->read(headerBuffer, 2); + if (read < 2) { + return false; + } + payloadLength = be16toh(*reinterpret_cast(headerBuffer)); + } else if (payloadLength == 127) { + read = transport_->read(headerBuffer, 8); + if (read < 8) { + return false; + } + payloadLength = be64toh(*reinterpret_cast(headerBuffer)); + if ((payloadLength & 0x8000000000000000) != 0) { + failConnection(CloseCode::ProtocolError); + throw TTransportException( + TTransportException::CORRUPTED_DATA, + "The most significant bit of the payload length must be zero"); + } + } + + // size_t is smaller than a ulong on a 32-bit system + if (payloadLength > UINT32_MAX) { + failConnection(CloseCode::MessageTooBig); + return false; + } + + auto length = static_cast(payloadLength); + + if (length > 0) { + // Read the masking key + read = transport_->read(headerBuffer, 4); + if (read < 4) { + return false; + } + + readBuffer_.resetBuffer(length); + uint8_t* buffer = readBuffer_.getWritePtr(length); + read = transport_->read(buffer, length); + readBuffer_.wroteBytes(read); + if (read < length) { + return false; + } + + // Unmask the data + for (size_t i = 0; i < length; i++) { + buffer[i] ^= headerBuffer[i % 4]; + } + + T_DEBUG("FIN=%d, Opcode=%X, length=%d, payload=%s", fin, opcode, length, + binary ? readBuffer_.toHexString() : cast(string) readBuffer_); + } + + switch (opcode) { + case Opcode::Close: + if (length >= 2) { + uint8_t buffer[2]; + readBuffer_.read(buffer, 2); + CloseCode closeCode = static_cast(be16toh(*reinterpret_cast(buffer))); + THRIFT_UNUSED_VARIABLE(closeCode); + string closeReason = readBuffer_.readAsString(length - 2); + T_DEBUG("Connection closed: %d %s", closeCode, closeReason); + } + transport_->close(); + return false; + case Opcode::Ping: + pong(); + return readFrame(); + default: + return true; + } + } + + void resetHandshake() { + connection_ = false; + secWebSocketKey_ = false; + secWebSocketVersion_ = false; + upgrade_ = false; + } + + void sendBadRequest() { + std::ostringstream h; + h << "HTTP/1.1 400 Bad Request" << CRLF << "Server: Thrift/" << PACKAGE_VERSION << CRLF << CRLF; + std::string header = h.str(); + transport_->write(reinterpret_cast(header.data()), static_cast(header.length())); + transport_->flush(); + transport_->close(); + } + + void writeFrameHeader(Opcode opcode = Opcode::Continuation) { + uint32_t headerSize = 1; + uint32_t length = writeBuffer_.available_read(); + if (length < 126) { + ++headerSize; + } else if (length < 65536) { + headerSize += 3; + } else { + headerSize += 9; + } + // The server does not mask the response + + uint8_t* header = static_cast(alloca(headerSize)); + if (opcode == Opcode::Continuation) { + opcode = binary ? Opcode::Binary : Opcode::Text; + } + header[0] = static_cast(opcode) | 0x80; + if (length < 126) { + header[1] = static_cast(length); + } else if (length < 65536) { + header[1] = 126; + *reinterpret_cast(header + 2) = htobe16(length); + } else { + header[1] = 127; + *reinterpret_cast(header + 2) = htobe64(length); + } + + transport_->write(header, headerSize); + } + + // Add constant here to avoid a linker error on Windows + constexpr static const char* CRLF = "\r\n"; + std::string acceptKey_; + bool connection_; + bool secWebSocketKey_; + bool secWebSocketVersion_; + bool upgrade_; +}; + +/** + * Wraps a transport into binary WebSocket protocol + */ +class TBinaryWebSocketServerTransportFactory : public TTransportFactory { +public: + TBinaryWebSocketServerTransportFactory() = default; + + ~TBinaryWebSocketServerTransportFactory() override = default; + + /** + * Wraps the transport into a buffered one. + */ + std::shared_ptr getTransport(std::shared_ptr trans) override { + return std::shared_ptr(new TWebSocketServer(trans)); + } +}; + +/** + * Wraps a transport into text WebSocket protocol + */ +class TTextWebSocketServerTransportFactory : public TTransportFactory { +public: + TTextWebSocketServerTransportFactory() = default; + + ~TTextWebSocketServerTransportFactory() override = default; + + /** + * Wraps the transport into a buffered one. + */ + std::shared_ptr getTransport(std::shared_ptr trans) override { + return std::shared_ptr(new TWebSocketServer(trans)); + } +}; +} // namespace transport +} // namespace thrift +} // namespace apache +#endif diff --git a/lib/nodejs/test/client.js b/lib/nodejs/test/client.js index 49e3a5ec935..31ea06e2f0d 100644 --- a/lib/nodejs/test/client.js +++ b/lib/nodejs/test/client.js @@ -69,6 +69,11 @@ if (program.transport === "http") { type = "http"; } +if (program.transport === "websocket") { + program.transport = "buffered"; + type = "websocket"; +} + const options = { transport: helpers.transports[program.transport], protocol: helpers.protocols[program.protocol] diff --git a/lib/nodejs/test/server.js b/lib/nodejs/test/server.js index 7402094bc51..677839aea2b 100644 --- a/lib/nodejs/test/server.js +++ b/lib/nodejs/test/server.js @@ -61,6 +61,9 @@ let type = program.type; if (program.transport === "http") { program.transport = "buffered"; type = "http"; +} else if (program.transport === "websocket") { + program.transport = "buffered"; + type = "websocket"; } let options = { diff --git a/test/cpp/src/TestServer.cpp b/test/cpp/src/TestServer.cpp index 8fdab8653d1..65317f89c13 100644 --- a/test/cpp/src/TestServer.cpp +++ b/test/cpp/src/TestServer.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "SecondService.h" @@ -588,7 +589,7 @@ int main(int argc, char** argv) { ("domain-socket", po::value(&domain_socket) ->default_value(domain_socket), "Unix Domain Socket (e.g. /tmp/ThriftTest.thrift)") ("abstract-namespace", "Create the domain socket in the Abstract Namespace (no connection with filesystem pathnames)") ("server-type", po::value(&server_type)->default_value(server_type), "type of server, \"simple\", \"thread-pool\", \"threaded\", or \"nonblocking\"") - ("transport", po::value(&transport_type)->default_value(transport_type), "transport: buffered, framed, http, zlib") + ("transport", po::value(&transport_type)->default_value(transport_type), "transport: buffered, framed, http, websocket, zlib") ("protocol", po::value(&protocol_type)->default_value(protocol_type), "protocol: binary, compact, header, json, multi, multic, multih, multij") ("ssl", "Encrypted Transport using SSL") ("zlib", "Wrapped Transport using Zlib") @@ -635,6 +636,7 @@ int main(int argc, char** argv) { if (transport_type == "buffered") { } else if (transport_type == "framed") { } else if (transport_type == "http") { + } else if (transport_type == "websocket") { } else if (transport_type == "zlib") { // crosstester will pass zlib as a flag and a transport right now... } else { @@ -728,6 +730,12 @@ int main(int argc, char** argv) { if (transport_type == "http" && server_type != "nonblocking") { transportFactory = std::make_shared(); + } else if (transport_type == "websocket" && server_type != "nonblocking") { + if (protocol_type == "json" || protocol_type == "multij") { + transportFactory = std::make_shared(); + } else { + transportFactory = std::make_shared(); + } } else if (transport_type == "framed") { transportFactory = std::make_shared(); } else { diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json index 49ec2222846..5b78803d821 100644 --- a/test/known_failures_Linux.json +++ b/test/known_failures_Linux.json @@ -21,6 +21,42 @@ "cl-rs_multi-binary_framed-ip", "cl-rs_multi_buffered-ip", "cl-rs_multi_framed-ip", + "cpp-cpp_binary_websocket-domain", + "cpp-cpp_binary_websocket-ip", + "cpp-cpp_binary_websocket-ip-ssl", + "cpp-cpp_compact_websocket-domain", + "cpp-cpp_compact_websocket-ip", + "cpp-cpp_compact_websocket-ip-ssl", + "cpp-cpp_header_websocket-domain", + "cpp-cpp_header_websocket-ip", + "cpp-cpp_header_websocket-ip-ssl", + "cpp-cpp_json_websocket-domain", + "cpp-cpp_json_websocket-ip", + "cpp-cpp_json_websocket-ip-ssl", + "cpp-cpp_multi-binary_websocket-domain", + "cpp-cpp_multi-binary_websocket-ip", + "cpp-cpp_multi-binary_websocket-ip-ssl", + "cpp-cpp_multi_websocket-domain", + "cpp-cpp_multi_websocket-ip", + "cpp-cpp_multi_websocket-ip-ssl", + "cpp-cpp_multic-compact_websocket-domain", + "cpp-cpp_multic-compact_websocket-ip", + "cpp-cpp_multic-compact_websocket-ip-ssl", + "cpp-cpp_multic_websocket-domain", + "cpp-cpp_multic_websocket-ip", + "cpp-cpp_multic_websocket-ip-ssl", + "cpp-cpp_multih-header_websocket-domain", + "cpp-cpp_multih-header_websocket-ip", + "cpp-cpp_multih-header_websocket-ip-ssl", + "cpp-cpp_multih_websocket-domain", + "cpp-cpp_multih_websocket-ip", + "cpp-cpp_multih_websocket-ip-ssl", + "cpp-cpp_multij-json_websocket-domain", + "cpp-cpp_multij-json_websocket-ip", + "cpp-cpp_multij-json_websocket-ip-ssl", + "cpp-cpp_multij_websocket-domain", + "cpp-cpp_multij_websocket-ip", + "cpp-cpp_multij_websocket-ip-ssl", "cpp-dart_binary_http-ip", "cpp-dart_compact_http-ip", "cpp-dart_json_http-ip", @@ -72,27 +108,39 @@ "cpp-nodejs_binary_http-domain", "cpp-nodejs_binary_http-ip", "cpp-nodejs_binary_http-ip-ssl", + "cpp-nodejs_binary_websocket-domain", "cpp-nodejs_compact_http-domain", "cpp-nodejs_compact_http-ip", "cpp-nodejs_compact_http-ip-ssl", + "cpp-nodejs_compact_websocket-domain", "cpp-nodejs_header_http-domain", "cpp-nodejs_header_http-ip", "cpp-nodejs_header_http-ip-ssl", + "cpp-nodejs_header_websocket-domain", + "cpp-nodejs_header_websocket-ip", + "cpp-nodejs_header_websocket-ip-ssl", "cpp-nodejs_json_http-domain", "cpp-nodejs_json_http-ip", "cpp-nodejs_json_http-ip-ssl", + "cpp-nodejs_json_websocket-domain", "cpp-nodejs_multi-binary_http-domain", "cpp-nodejs_multi-binary_http-ip", "cpp-nodejs_multi-binary_http-ip-ssl", + "cpp-nodejs_multi-binary_websocket-domain", "cpp-nodejs_multic-compact_http-domain", "cpp-nodejs_multic-compact_http-ip", "cpp-nodejs_multic-compact_http-ip-ssl", + "cpp-nodejs_multic-compact_websocket-domain", "cpp-nodejs_multih-header_http-domain", "cpp-nodejs_multih-header_http-ip", "cpp-nodejs_multih-header_http-ip-ssl", + "cpp-nodejs_multih-header_websocket-domain", + "cpp-nodejs_multih-header_websocket-ip", + "cpp-nodejs_multih-header_websocket-ip-ssl", "cpp-nodejs_multij-json_http-domain", "cpp-nodejs_multij-json_http-ip", "cpp-nodejs_multij-json_http-ip-ssl", + "cpp-nodejs_multij-json_websocket-domain", "cpp-php_binary-accel_buffered-ip", "cpp-php_binary-accel_framed-ip", "cpp-php_json_buffered-ip", @@ -500,16 +548,28 @@ "nodejs-cpp_binary_http-domain", "nodejs-cpp_binary_http-ip", "nodejs-cpp_binary_http-ip-ssl", + "nodejs-cpp_binary_websocket-domain", + "nodejs-cpp_binary_websocket-ip", + "nodejs-cpp_binary_websocket-ip-ssl", "nodejs-cpp_compact_http-domain", "nodejs-cpp_compact_http-ip", "nodejs-cpp_compact_http-ip-ssl", + "nodejs-cpp_compact_websocket-domain", + "nodejs-cpp_compact_websocket-ip", + "nodejs-cpp_compact_websocket-ip-ssl", "nodejs-cpp_header_http-domain", "nodejs-cpp_header_http-ip", "nodejs-cpp_header_http-ip-ssl", + "nodejs-cpp_header_websocket-domain", + "nodejs-cpp_header_websocket-ip", + "nodejs-cpp_header_websocket-ip-ssl", "nodejs-cpp_json_buffered-ip-ssl", "nodejs-cpp_json_http-domain", "nodejs-cpp_json_http-ip", "nodejs-cpp_json_http-ip-ssl", + "nodejs-cpp_json_websocket-domain", + "nodejs-cpp_json_websocket-ip", + "nodejs-cpp_json_websocket-ip-ssl", "nodejs-d_binary_http-ip", "nodejs-d_binary_http-ip-ssl", "nodejs-d_compact_http-ip", @@ -549,6 +609,10 @@ "nodejs-netstd_json_buffered-ip-ssl", "nodejs-netstd_json_framed-ip", "nodejs-netstd_json_framed-ip-ssl", + "nodejs-nodejs_binary_websocket-domain", + "nodejs-nodejs_compact_websocket-domain", + "nodejs-nodejs_header_websocket-domain", + "nodejs-nodejs_json_websocket-domain", "nodejs-php_binary-accel_buffered-ip", "nodejs-php_binary-accel_framed-ip", "nodejs-php_json_buffered-ip", diff --git a/test/tests.json b/test/tests.json index 42e5d6aab15..a8dbef7d4c7 100644 --- a/test/tests.json +++ b/test/tests.json @@ -193,7 +193,8 @@ "transports": [ "buffered", "framed", - "http" + "http", + "websocket" ], "sockets": [ "ip", @@ -366,7 +367,8 @@ "buffered", "http", "framed", - "zlib" + "zlib", + "websocket" ], "sockets": [ "ip", From 506e311c381677928ab68fd62e441deb24f2f7c3 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sun, 17 May 2020 22:48:51 +0200 Subject: [PATCH 599/756] FIX: CI error at ./test/py/TestServer.py:178:26: F507 '...' % ... has 1 placeholder(s) but 6 substitution(s) FIX: CI error at ./test/crossrunner/compat.py:11:21: E741 ambiguous variable name 'l' Patch: Jens Geyer This closes #2147 --- test/crossrunner/compat.py | 6 +++--- test/py/TestServer.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/crossrunner/compat.py b/test/crossrunner/compat.py index f1ca91bb35f..932a48cd6ad 100644 --- a/test/crossrunner/compat.py +++ b/test/crossrunner/compat.py @@ -8,9 +8,9 @@ def path_join(*args): bin_args = map(lambda a: a.decode(_ENCODE), args) return os.path.join(*bin_args).encode(_ENCODE) - def str_join(s, l): - bin_args = map(lambda a: a.decode(_ENCODE), l) - b = s.decode(_ENCODE) + def str_join(left, right): + bin_args = map(lambda a: a.decode(_ENCODE), right) + b = left.decode(_ENCODE) return b.join(bin_args).encode(_ENCODE) logfile_open = open diff --git a/test/py/TestServer.py b/test/py/TestServer.py index 4d90f8f9172..81ae1ad62ee 100755 --- a/test/py/TestServer.py +++ b/test/py/TestServer.py @@ -175,7 +175,7 @@ def testInsanity(self, argument): def testMulti(self, arg0, arg1, arg2, arg3, arg4, arg5): if options.verbose > 1: - logging.info('testMulti(%s)' % [arg0, arg1, arg2, arg3, arg4, arg5]) + logging.info('testMulti(%s, %s, %s, %s, %s, %s)' % (arg0, arg1, arg2, arg3, arg4, arg5)) return Xtruct(string_thing='Hello2', byte_thing=arg0, i32_thing=arg1, i64_thing=arg2) From 1edf32926d980573d23a292ae72e96db92ac43c1 Mon Sep 17 00:00:00 2001 From: Jano Svitok Date: Fri, 28 Feb 2020 12:44:59 +0100 Subject: [PATCH 600/756] THRIFT-5125: Swift server does not work using present code Client: Swift Patch: Jano Svitok This closes #2038 --- lib/swift/Sources/TSocketServer.swift | 42 ++++++++------ .../ThriftTests/TSocketServerTests.swift | 55 +++++++++++++++++++ 2 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 lib/swift/Tests/ThriftTests/TSocketServerTests.swift diff --git a/lib/swift/Sources/TSocketServer.swift b/lib/swift/Sources/TSocketServer.swift index 5d0dd494100..d70020ec31b 100644 --- a/lib/swift/Sources/TSocketServer.swift +++ b/lib/swift/Sources/TSocketServer.swift @@ -31,21 +31,17 @@ public let TSocketServerClientConnectionFinished = "TSocketServerClientConnectio public let TSocketServerProcessorKey = "TSocketServerProcessor" public let TSocketServerTransportKey = "TSocketServerTransport" -class TSocketServer { +open class TSocketServer { var socketFileHandle: FileHandle var processingQueue = DispatchQueue(label: "TSocketServer.processing", qos: .background, attributes: .concurrent) - var serviceHandler: Service let processor: Processor public init(port: Int, - service: Service, inProtocol: InProtocol.Type, outProtocol: OutProtocol.Type, processor: Processor) throws { - // set service handler - self.serviceHandler = service self.processor = processor // create a socket @@ -61,16 +57,16 @@ class TSocketServer.size)) - + let inPort = in_port_t(UInt16(truncatingIfNeeded: port).bigEndian) #if os(Linux) var addr = sockaddr_in(sin_family: sa_family_t(AF_INET), - sin_port: in_port_t(port.bigEndian), + sin_port: inPort, sin_addr: in_addr(s_addr: in_addr_t(0)), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0)) #else var addr = sockaddr_in(sin_len: UInt8(MemoryLayout.size), sin_family: sa_family_t(AF_INET), - sin_port: in_port_t(port.bigEndian), + sin_port: inPort, sin_addr: in_addr(s_addr: in_addr_t(0)), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0)) #endif @@ -82,7 +78,7 @@ class TSocketServer.size) let cfaddr = address.withUnsafeBytes { - CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, $0.bindMemory(to: UInt8.self).baseAddress!, address.count, nil) + CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, $0.bindMemory(to: UInt8.self).baseAddress!, address.count, kCFAllocatorNull) } if CFSocketSetAddress(sock, cfaddr) != CFSocketError.success { //kCFSocketSuccess { CFSocketInvalidate(sock) @@ -106,7 +102,8 @@ class TSocketServer TTransport { + return TFileHandleTransport(fileHandle: fileHandle) + } + func handleClientConnection(_ clientSocket: FileHandle) { + let transport = createTransport(fileHandle: clientSocket) let inProtocol = InProtocol(on: transport) let outProtocol = OutProtocol(on: transport) do { - try processor.process(on: inProtocol, outProtocol: outProtocol) + while true { + try processor.process(on: inProtocol, outProtocol: outProtocol) + } } catch let error { print("Error processign request: \(error)") } @@ -147,3 +151,9 @@ class TSocketServer: TSocketServer { + open override func createTransport(fileHandle: FileHandle) -> TTransport { + return TFramedTransport(transport: super.createTransport(fileHandle: fileHandle)) + } +} diff --git a/lib/swift/Tests/ThriftTests/TSocketServerTests.swift b/lib/swift/Tests/ThriftTests/TSocketServerTests.swift new file mode 100644 index 00000000000..a00ebbc4bcb --- /dev/null +++ b/lib/swift/Tests/ThriftTests/TSocketServerTests.swift @@ -0,0 +1,55 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +import XCTest +import Foundation +@testable import Thrift + +private protocol CalculatorService { } + +private class Calculator: CalculatorService { } + +private class CalculatorProcessor: TProcessor { + private let service: CalculatorService + + init(service: CalculatorService) { + self.service = service + } + + var processCalled = false + func process(on inProtocol: TProtocol, outProtocol: TProtocol) throws { + processCalled = true + } +} + +class TSocketServerTests: XCTestCase { + func testInit() throws { + let service: CalculatorService = Calculator() + let processor: CalculatorProcessor = CalculatorProcessor(service: service) + let _: TSocketServer = + try TSocketServer(port: 9090, inProtocol: TBinaryProtocol.self, outProtocol: TBinaryProtocol.self, processor: processor) + } + + static var allTests : [(String, (TSocketServerTests) -> () throws -> Void)] { + return [ + ("testInit", testInit), + ] + } + +} From a082592d439d6aa578507ff52198038e5e08006d Mon Sep 17 00:00:00 2001 From: Jano Svitok Date: Fri, 6 Mar 2020 08:44:10 +0100 Subject: [PATCH 601/756] THRIFT-5128 Swift TFramedTransport does not work using present code Client: Swift Patch: Jano Svitok This closes #2047 --- .../src/thrift/generate/t_swift_generator.cc | 10 +- lib/swift/Sources/TFramedTransport.swift | 8 +- .../ThriftTests/TBinaryProtocolTests.swift | 5 +- .../ThriftTests/TFramedTransportTests.swift | 179 ++++++++++++++++++ .../TMultiplexedProcessorTests.swift | 13 ++ lib/swift/Tests/ThriftTests/ThriftTests.swift | 4 - 6 files changed, 204 insertions(+), 15 deletions(-) create mode 100644 lib/swift/Tests/ThriftTests/TFramedTransportTests.swift diff --git a/compiler/cpp/src/thrift/generate/t_swift_generator.cc b/compiler/cpp/src/thrift/generate/t_swift_generator.cc index ac63ea07d60..f291ee42826 100644 --- a/compiler/cpp/src/thrift/generate/t_swift_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_swift_generator.cc @@ -2423,7 +2423,8 @@ void t_swift_generator::generate_swift_service_server_implementation(ostream& ou if (!tfunction->is_oneway()) { out << indent() << "try outProtocol.writeMessageBegin(name: \"" << tfunction->get_name() << "\", type: .reply, sequenceID: sequenceID)" << endl << indent() << "try result.write(to: outProtocol)" << endl - << indent() << "try outProtocol.writeMessageEnd()" << endl; + << indent() << "try outProtocol.writeMessageEnd()" << endl + << indent() << "try outProtocol.transport.flush()" << endl; } } else { for (x_iter = xfields.begin(); x_iter != xfields.end(); ++x_iter) { @@ -2476,7 +2477,8 @@ void t_swift_generator::generate_swift_service_server_implementation(ostream& ou if (!gen_cocoa_) { out << indent() << "catch let error as TApplicationError"; block_open(out); - out << indent() << "try outProtocol.writeException(messageName: messageName, sequenceID: sequenceID, ex: error)" << endl; + out << indent() << "try outProtocol.writeException(messageName: messageName, sequenceID: sequenceID, ex: error)" << endl + << indent() << "try outProtocol.transport.flush()" << endl; block_close(out); block_close(out); out << indent() << "else"; @@ -2484,8 +2486,8 @@ void t_swift_generator::generate_swift_service_server_implementation(ostream& ou out << indent() << "try inProtocol.skip(type: .struct)" << endl << indent() << "try inProtocol.readMessageEnd()" << endl << indent() << "let ex = TApplicationError(error: .unknownMethod(methodName: messageName))" << endl - << indent() << "try outProtocol.writeException(messageName: messageName, " - << "sequenceID: sequenceID, ex: ex)" << endl; + << indent() << "try outProtocol.writeException(messageName: messageName, sequenceID: sequenceID, ex: ex)" << endl + << indent() << "try outProtocol.transport.flush()" << endl; } else { out << indent() << "catch let error as NSError"; block_open(out); diff --git a/lib/swift/Sources/TFramedTransport.swift b/lib/swift/Sources/TFramedTransport.swift index 59855eb9cb7..9f75b5efc8a 100644 --- a/lib/swift/Sources/TFramedTransport.swift +++ b/lib/swift/Sources/TFramedTransport.swift @@ -65,7 +65,9 @@ public class TFramedTransport: TTransport { throw TTransportError(error: .sizeLimit(limit: maxSize, got: toRead)) } - return try transport.readAll(size: toRead) + let data = try transport.readAll(size: toRead) + remainingBytes -= data.count + return data } public func flush() throws { @@ -73,10 +75,6 @@ public class TFramedTransport: TTransport { let buff = writeBuffer writeBuffer = Data() - if buff.count - TFramedTransport.headerSize < 0 { - throw TTransportError(error: .unknown) - } - let frameSize = encodeFrameSize(size: UInt32(buff.count)) try transport.write(data: frameSize) diff --git a/lib/swift/Tests/ThriftTests/TBinaryProtocolTests.swift b/lib/swift/Tests/ThriftTests/TBinaryProtocolTests.swift index 56a557261ab..a50db4e54b7 100644 --- a/lib/swift/Tests/ThriftTests/TBinaryProtocolTests.swift +++ b/lib/swift/Tests/ThriftTests/TBinaryProtocolTests.swift @@ -116,7 +116,6 @@ class TBinaryProtocolTests: XCTestCase { do { try writeVal.write(to: proto) try? transport.flush() - } catch let error { XCTAssertFalse(true, "Caught Error attempting to write \(error)") } @@ -129,6 +128,7 @@ class TBinaryProtocolTests: XCTestCase { XCTAssertFalse(true, "Caught Error attempting to read \(error)") } } + func testUnsafeBitcastUpdate() { let value: Double = 3.14159 let val: Int64 = 31415926 @@ -162,7 +162,8 @@ class TBinaryProtocolTests: XCTestCase { ("testBoolWriteRead", testBoolWriteRead), ("testStringWriteRead", testStringWriteRead), ("testDataWriteRead", testDataWriteRead), - ("testStructWriteRead", testStructWriteRead) + ("testStructWriteRead", testStructWriteRead), + ("testUnsafeBitcastUpdate", testUnsafeBitcastUpdate) ] } } diff --git a/lib/swift/Tests/ThriftTests/TFramedTransportTests.swift b/lib/swift/Tests/ThriftTests/TFramedTransportTests.swift new file mode 100644 index 00000000000..d830cee9378 --- /dev/null +++ b/lib/swift/Tests/ThriftTests/TFramedTransportTests.swift @@ -0,0 +1,179 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +import XCTest +import Foundation +@testable import Thrift + +/// Testig TFramedTransport +/// +class TFramedTransportTests: XCTestCase { + var underlyingTransport: TMemoryBufferTransport = TMemoryBufferTransport(flushHandler: { + $0.reset(readBuffer: $1) + }) + + var proto: TBinaryProtocol! + var transport: TFramedTransport! + + override func setUp() { + super.setUp() + transport = TFramedTransport(transport:underlyingTransport) + proto = TBinaryProtocol(on: transport) + underlyingTransport.reset() + } + + override func tearDown() { + super.tearDown() + underlyingTransport.reset() + } + func testInt8WriteRead() { + let writeVal: UInt8 = 250 + try? proto.write(writeVal) + try? transport.flush() + + let readVal: UInt8 = (try? proto.read()) ?? 0 + XCTAssertEqual(writeVal, readVal, "Error with UInt8, wrote \(writeVal) but read \(readVal)") + } + + func testInt16WriteRead() { + + let writeVal: Int16 = 12312 + try? proto.write(writeVal) + try? transport.flush() + + let readVal: Int16 = (try? proto.read()) ?? 0 + XCTAssertEqual(writeVal, readVal, "Error with Int16, wrote \(writeVal) but read \(readVal)") + } + + func testInt32WriteRead() { + let writeVal: Int32 = 2029234 + try? proto.write(writeVal) + try? transport.flush() + + let readVal: Int32 = (try? proto.read()) ?? 0 + XCTAssertEqual(writeVal, readVal, "Error with Int32, wrote \(writeVal) but read \(readVal)") + } + + func testInt64WriteRead() { + let writeVal: Int64 = 234234981374134 + try? proto.write(writeVal) + try? transport.flush() + + let readVal: Int64 = (try? proto.read()) ?? 0 + XCTAssertEqual(writeVal, readVal, "Error with Int64, wrote \(writeVal) but read \(readVal)") + } + + func testDoubleWriteRead() { + let writeVal: Double = 3.1415926 + try? proto.write(writeVal) + try? transport.flush() + + let readVal: Double = (try? proto.read()) ?? 0.0 + XCTAssertEqual(writeVal, readVal, "Error with Double, wrote \(writeVal) but read \(readVal)") + } + + func testBoolWriteRead() { + let writeVal: Bool = true + try? proto.write(writeVal) + try? transport.flush() + + let readVal: Bool = (try? proto.read()) ?? false + XCTAssertEqual(writeVal, readVal, "Error with Bool, wrote \(writeVal) but read \(readVal)") + } + + func testStringWriteRead() { + let writeVal: String = "Hello World" + try? proto.write(writeVal) + try? transport.flush() + + let readVal: String! + do { + readVal = try proto.read() + } catch let error { + XCTAssertFalse(true, "Error reading \(error)") + return + } + + XCTAssertEqual(writeVal, readVal, "Error with String, wrote \(writeVal) but read \(readVal)") + } + + func testDataWriteRead() { + let writeVal: Data = "Data World".data(using: .utf8)! + try? proto.write(writeVal) + try? transport.flush() + + let readVal: Data = (try? proto.read()) ?? "Goodbye World".data(using: .utf8)! + XCTAssertEqual(writeVal, readVal, "Error with Data, wrote \(writeVal) but read \(readVal)") + } + + func testStructWriteRead() { + let msg = "Test Protocol Error" + let writeVal = TApplicationError(error: .protocolError, message: msg) + do { + try writeVal.write(to: proto) + try? transport.flush() + } catch let error { + XCTAssertFalse(true, "Caught Error attempting to write \(error)") + } + + do { + let readVal = try TApplicationError.read(from: proto) + XCTAssertEqual(readVal.error.thriftErrorCode, writeVal.error.thriftErrorCode, "Error case mismatch, expected \(readVal.error) got \(writeVal.error)") + XCTAssertEqual(readVal.message, writeVal.message, "Error message mismatch, expected \(readVal.message) got \(writeVal.message)") + } catch let error { + XCTAssertFalse(true, "Caught Error attempting to read \(error)") + } + } + + func testUnsafeBitcastUpdate() { + let value: Double = 3.14159 + let val: Int64 = 31415926 + let uval: UInt64 = 31415926 + + let i64 = Int64(bitPattern: value.bitPattern) + let ubc = unsafeBitCast(value, to: Int64.self) + + XCTAssertEqual(i64, ubc, "Bitcast Double-> i64 Values don't match") + + let dbl = Double(bitPattern: UInt64(val)) + let ubdb = unsafeBitCast(val, to: Double.self) + + XCTAssertEqual(dbl, ubdb, "Bitcast i64 -> Double Values don't match") + + let db2 = Double(bitPattern: uval) + let usbc2 = unsafeBitCast(uval, to: Double.self) + + XCTAssertEqual(db2, usbc2, "Bitcast u64 -> Double Values don't match") + } + + static var allTests : [(String, (TFramedTransportTests) -> () throws -> Void)] { + return [ + ("testInt8WriteRead", testInt8WriteRead), + ("testInt16WriteRead", testInt16WriteRead), + ("testInt32WriteRead", testInt32WriteRead), + ("testInt64WriteRead", testInt64WriteRead), + ("testDoubleWriteRead", testDoubleWriteRead), + ("testBoolWriteRead", testBoolWriteRead), + ("testStringWriteRead", testStringWriteRead), + ("testDataWriteRead", testDataWriteRead), + ("testStructWriteRead", testStructWriteRead), + ("testUnsafeBitcastUpdate", testUnsafeBitcastUpdate) + ] + } +} diff --git a/lib/swift/Tests/ThriftTests/TMultiplexedProcessorTests.swift b/lib/swift/Tests/ThriftTests/TMultiplexedProcessorTests.swift index 559ff0b22cd..a68c081eb4d 100644 --- a/lib/swift/Tests/ThriftTests/TMultiplexedProcessorTests.swift +++ b/lib/swift/Tests/ThriftTests/TMultiplexedProcessorTests.swift @@ -138,4 +138,17 @@ class TMultiplexedProcessorTests: XCTestCase { try transport.flush() try sut.process(on: proto, outProtocol: proto) } + + static var allTests : [(String, (TMultiplexedProcessorTests) -> () throws -> Void)] { + return [ + ("testExceptionMessageThrowsError", testExceptionMessageThrowsError), + ("testReplyMessageThrowsError", testReplyMessageThrowsError), + ("testMissingDefaultProcessorThrowsError", testMissingDefaultProcessorThrowsError), + ("testUsesDefaultProcessorForNonMultiplexedMessage", testUsesDefaultProcessorForNonMultiplexedMessage), + ("testUsesProcessorForMultiplexedMessage", testUsesProcessorForMultiplexedMessage), + ("testMissingProcessorForMultiplexedMessageThrowsError", testMissingProcessorForMultiplexedMessageThrowsError), + ("testCallMessageDoesNotThrowError", testCallMessageDoesNotThrowError), + ("testOneWayMessageDoesNotThrowError", testOneWayMessageDoesNotThrowError) + ] + } } diff --git a/lib/swift/Tests/ThriftTests/ThriftTests.swift b/lib/swift/Tests/ThriftTests/ThriftTests.swift index 37f3cf68927..226862e2b08 100644 --- a/lib/swift/Tests/ThriftTests/ThriftTests.swift +++ b/lib/swift/Tests/ThriftTests/ThriftTests.swift @@ -6,10 +6,6 @@ class ThriftTests: XCTestCase { XCTAssertEqual(Thrift().version, "0.14.0") } - func test_in_addr_extension() { - - } - static var allTests : [(String, (ThriftTests) -> () throws -> Void)] { return [ ("testVersion", testVersion), From 4fd001c878e748a09713235725d8ad41de6ea6a1 Mon Sep 17 00:00:00 2001 From: Jano Svitok Date: Fri, 13 Mar 2020 01:28:03 +0100 Subject: [PATCH 602/756] THRIFT-5138 Swift keywords may be used as identifiers if escaped Client: Swift Patch: Jano Svitok This closes #2059 --- compiler/cpp/src/thrift/generate/t_generator.h | 15 ++++++++++++--- .../cpp/src/thrift/generate/t_py_generator.cc | 2 ++ .../cpp/src/thrift/generate/t_swift_generator.cc | 8 +++++++- compiler/cpp/test/CMakeLists.txt | 4 +++- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_generator.h b/compiler/cpp/src/thrift/generate/t_generator.h index cb9d076b50a..f82463d0c14 100644 --- a/compiler/cpp/src/thrift/generate/t_generator.h +++ b/compiler/cpp/src/thrift/generate/t_generator.h @@ -42,8 +42,9 @@ */ class t_generator { public: - t_generator(t_program* program) - : keywords_(lang_keywords()){ + t_generator(t_program* program) { + update_keywords(); + tmp_ = 0; indent_ = 0; program_ = program; @@ -99,16 +100,24 @@ class t_generator { /** * Check if all identifiers are valid for the target language + * See update_keywords() */ virtual void validate_input() const; protected: virtual std::set lang_keywords() const; + /** + * Call this from constructor if you implement lang_keywords() + */ + void update_keywords() { + keywords_ = lang_keywords(); + } + /** * A list of reserved words that cannot be used as identifiers. */ - const std::set keywords_; + std::set keywords_; virtual void validate_id(const std::string& id) const; diff --git a/compiler/cpp/src/thrift/generate/t_py_generator.cc b/compiler/cpp/src/thrift/generate/t_py_generator.cc index e93bbe17dcc..4be2fcc0461 100644 --- a/compiler/cpp/src/thrift/generate/t_py_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_py_generator.cc @@ -52,6 +52,8 @@ class t_py_generator : public t_generator { const std::map& parsed_options, const std::string& option_string) : t_generator (program) { + update_keywords(); + std::map::const_iterator iter; gen_newstyle_ = true; diff --git a/compiler/cpp/src/thrift/generate/t_swift_generator.cc b/compiler/cpp/src/thrift/generate/t_swift_generator.cc index f291ee42826..91181f6812c 100644 --- a/compiler/cpp/src/thrift/generate/t_swift_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_swift_generator.cc @@ -50,6 +50,8 @@ class t_swift_generator : public t_oop_generator { const map& parsed_options, const string& option_string) : t_oop_generator(program) { + update_keywords(); + (void)option_string; map::const_iterator iter; @@ -288,6 +290,10 @@ class t_swift_generator : public t_oop_generator { bool gen_cocoa_; bool promise_kit_; +protected: + std::set lang_keywords() const override { + return {}; + } }; /** @@ -1210,7 +1216,7 @@ void t_swift_generator::generate_swift_struct_reader(ostream& out, if (field_is_optional(*f_iter)) { continue; } - indent(out) << "try proto.validateValue(" << (*f_iter)->get_name() << ", " + indent(out) << "try proto.validateValue(" << maybe_escape_identifier((*f_iter)->get_name()) << ", " << "named: \"" << (*f_iter)->get_name() << "\")" << endl; } } diff --git a/compiler/cpp/test/CMakeLists.txt b/compiler/cpp/test/CMakeLists.txt index 4ce1e49ea19..b80f06000b4 100644 --- a/compiler/cpp/test/CMakeLists.txt +++ b/compiler/cpp/test/CMakeLists.txt @@ -18,7 +18,9 @@ # file(GLOB KEYWORD_SAMPLES "${CMAKE_CURRENT_SOURCE_DIR}/keyword-samples/*.thrift") -foreach(LANG ${thrift_compiler_LANGS}) +set(KEYWORD_LANGS ${thrift_compiler_LANGS}) +LIST(REMOVE_ITEM KEYWORD_LANGS swift) # in Swift you can escape reserved words +foreach(LANG ${KEYWORD_LANGS}) foreach(SAMPLE ${KEYWORD_SAMPLES}) get_filename_component(FILENAME ${SAMPLE} NAME_WE) add_test(NAME "${LANG}_${FILENAME}" From 7de1f5d7f394b49624e7278937d7ff665bfc642a Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 20 May 2020 00:55:10 +0200 Subject: [PATCH 603/756] Added breaking change notice for "THRIFT-5138 Swift keywords may be used as identifiers if escaped" because it is labelled as such in JIRA --- CHANGES.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0c0f84cf6d9..175d07fca70 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,13 +4,14 @@ ### Breaking Changes -- [THRIFT-5116](https://issues.apache.org/jira/browse/THRIFT-5116) - Upgrade NodeJS to 10.x -- [THRIFT-4990](https://issues.apache.org/jira/browse/THRIFT-4990) - Upgrade to .NET Core 3.1 (LTS) - [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base - [THRIFT-4982](https://issues.apache.org/jira/browse/THRIFT-4982) - Remove deprecated csharp bindings from the code base +- [THRIFT-4990](https://issues.apache.org/jira/browse/THRIFT-4990) - Upgrade to .NET Core 3.1 (LTS) - [THRIFT-5006](https://issues.apache.org/jira/browse/THRIFT-5006) - Implement DEFAULT_MAX_LENGTH at TFramedTransport - [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - In Go library TDeserializer.Transport is now typed \*TMemoryBuffer instead of TTransport - [THRIFT-5072](https://issues.apache.org/jira/browse/THRIFT-5072) - Haskell generator fails to distinguish between multiple enum types with conflicting enum identifiers +- [THRIFT-5116](https://issues.apache.org/jira/browse/THRIFT-5116) - Upgrade NodeJS to 10.x +- [THRIFT-5138](https://issues.apache.org/jira/browse/THRIFT-5138) - Swift generator does not escape keywords properly - [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - In Go library TProcessor interface now includes ProcessorMap and AddToProcessorMap functions. ### Java @@ -20,8 +21,8 @@ ### Go - [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - Add TSerializerPool and TDeserializerPool, which are thread-safe versions of TSerializer and TDeserializer. -- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - Add ProcessorMiddleware function type and WrapProcessor function to support wrapping a TProcessor with middleware functions. - [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - Add ClientMiddleware function type and WrapClient function to support wrapping a TClient with middleware functions. +- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - Add ProcessorMiddleware function type and WrapProcessor function to support wrapping a TProcessor with middleware functions. ## 0.13.0 From f8103c69eaaa23fe7fff4d8413240063b9ec56d2 Mon Sep 17 00:00:00 2001 From: David Mollitor Date: Wed, 20 May 2020 09:26:31 -0400 Subject: [PATCH 604/756] THRIFT-5202: TNonblockingMultiFetchClient Use SLF4J Parameterized Logging Client: java Patch: David Mollitor This closes #2137 Use SLF4J API to log full Exception details. Use SLF4J parameterized logging instead of String format. --- .../thrift/TNonblockingMultiFetchClient.java | 58 +++++++------------ 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/lib/java/src/org/apache/thrift/TNonblockingMultiFetchClient.java b/lib/java/src/org/apache/thrift/TNonblockingMultiFetchClient.java index 382d978db44..9cf873cacbf 100644 --- a/lib/java/src/org/apache/thrift/TNonblockingMultiFetchClient.java +++ b/lib/java/src/org/apache/thrift/TNonblockingMultiFetchClient.java @@ -77,8 +77,7 @@ public class TNonblockingMultiFetchClient { private static final Logger LOGGER = LoggerFactory.getLogger( - TNonblockingMultiFetchClient.class.getName() - ); + TNonblockingMultiFetchClient.class); // if the size of the response msg exceeds this limit (in byte), we will // not read the msg @@ -163,18 +162,18 @@ public synchronized ByteBuffer[] fetch() { executor.execute(task); try { task.get(fetchTimeoutSeconds, TimeUnit.SECONDS); - } catch(InterruptedException ie) { + } catch (InterruptedException ie) { // attempt to cancel execution of the task. task.cancel(true); - LOGGER.error("interrupted during fetch: "+ie.toString()); - } catch(ExecutionException ee) { + LOGGER.error("Interrupted during fetch", ie); + } catch (ExecutionException ee) { // attempt to cancel execution of the task. task.cancel(true); - LOGGER.error("exception during fetch: "+ee.toString()); - } catch(TimeoutException te) { + LOGGER.error("Exception during fetch", ee); + } catch (TimeoutException te) { // attempt to cancel execution of the task. task.cancel(true); - LOGGER.error("timeout for fetch: "+te.toString()); + LOGGER.error("Timeout for fetch", te); } executor.shutdownNow(); @@ -215,8 +214,8 @@ public void run() { try { selector = Selector.open(); - } catch (IOException e) { - LOGGER.error("selector opens error: "+e.toString()); + } catch (IOException ioe) { + LOGGER.error("Selector opens error", ioe); return; } @@ -239,10 +238,8 @@ public void run() { // 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); + stats.incNumConnectErrorServers(); + LOGGER.error("Set up socket to server {} error", server, e); // free resource if (s != null) { try {s.close();} catch (Exception ex) {} @@ -264,7 +261,7 @@ public void run() { try{ selector.select(); } catch (Exception e) { - LOGGER.error("selector selects error: "+e.toString()); + LOGGER.error("Selector selects error", e); continue; } @@ -284,10 +281,7 @@ public void run() { 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); + LOGGER.error("Socket {} connects to server {} error", index, servers.get(index), e); } } @@ -299,10 +293,7 @@ public void run() { 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); + LOGGER.error("Socket {} writes to server {} error", index, servers.get(index), e); } } } @@ -325,10 +316,8 @@ public void run() { 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); + LOGGER.error("Read an invalid frame size {} from {}. Does the server use TFramedTransport?", + frameSize[index], servers.get(index)); sChannel.close(); continue; } @@ -339,11 +328,8 @@ public void run() { 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); + LOGGER.error("Read frame size {} from {}, total buffer size would exceed limit {}", + frameSize[index], servers.get(index), maxRecvBufBytesPerServer); sChannel.close(); continue; } @@ -366,10 +352,8 @@ public void run() { } } } 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); + LOGGER.error("Socket {} reads from server {} error", + index, servers.get(index), e); } } } @@ -392,7 +376,7 @@ public void close() { selector.close(); } } catch (IOException e) { - LOGGER.error("free resource error: "+e.toString()); + LOGGER.error("Free resource error", e); } } } From dd34c5281344d0f1c10b2f7daddfb032bc6e5cb3 Mon Sep 17 00:00:00 2001 From: rel1ve Date: Wed, 11 Mar 2020 22:17:57 +0800 Subject: [PATCH 605/756] When I use --with-zlib args for cross-compiling, it failed without "$(ZLIB_LDFLAGS)". build system Patch: rel1ve This closes #2056 --- lib/cpp/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index f699f832fd5..bcc6a09f98e 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -126,7 +126,7 @@ libthriftnb_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftz_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftqt5_la_CXXFLAGS = $(AM_CXXFLAGS) libthriftnb_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) -libthriftz_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(ZLIB_LIBS) +libthriftz_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(ZLIB_LDFLAGS) $(ZLIB_LIBS) libthriftqt5_la_LDFLAGS = -release $(VERSION) $(BOOST_LDFLAGS) $(QT5_LIBS) include_thriftdir = $(includedir)/thrift From 528c22f59d3a35934f4f4308746a78d833b759e8 Mon Sep 17 00:00:00 2001 From: David Mollitor Date: Mon, 11 May 2020 10:57:00 -0400 Subject: [PATCH 606/756] THRIFT-5201: Use Apache Parent Pom for Thrift Maven Plugin Client: Java Patch: David Mollitor This closes #2136 --- contrib/thrift-maven-plugin/pom.xml | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/contrib/thrift-maven-plugin/pom.xml b/contrib/thrift-maven-plugin/pom.xml index 4179b1d914c..b1816225740 100644 --- a/contrib/thrift-maven-plugin/pom.xml +++ b/contrib/thrift-maven-plugin/pom.xml @@ -23,26 +23,34 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 + + org.apache + apache + 23 + org.apache.thrift thrift-maven-plugin maven-plugin thrift-maven-plugin 1.0.0 + + + 1.8 + 1.8 + ${basedir}/../.. + ${thrift.root}/compiler/cpp/thrift + ${thrift.root}/test + + org.apache.maven.plugins maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - org.apache.maven.plugins maven-surefire-plugin - 2.14.1 ${thrift.compiler} @@ -52,7 +60,6 @@ org.apache.maven.plugins maven-antrun-plugin - 1.8 generate-jar-for-test @@ -104,10 +111,4 @@ test - - ${basedir}/../.. - ${thrift.root}/compiler/cpp/thrift - ${thrift.root}/test - UTF-8 - From 348790deaf633f368a147c413e0f17eb7373a973 Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Mon, 23 Mar 2020 16:48:35 +0800 Subject: [PATCH 607/756] THRIFT-5147: Add uninstall function Patch: Zezeng Wang This closes #2066 --- CMakeLists.txt | 3 +++ README.md | 12 ++++++---- build/cmake/uninstall.cmake | 47 +++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 build/cmake/uninstall.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 18e52f638fb..127ceaf2660 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,4 +135,7 @@ if(BUILD_HASKELL) endif() endif() +# Create the uninstall target +add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${PROJECT_SOURCE_DIR}/build/cmake/uninstall.cmake") + PRINT_CONFIG_SUMMARY() diff --git a/README.md b/README.md index ff573215fd1..011b75a23ba 100644 --- a/README.md +++ b/README.md @@ -163,11 +163,15 @@ where the Python modules are installed, set the PY_PREFIX variable. Make thrift: - make + make From the top directory, become superuser and do: - make install + make install + +Uninstall thrift: + + make uninstall Note that some language packages must be installed manually using build tools better suited to those languages (at the time of this writing, this applies @@ -190,7 +194,7 @@ Testing There are a large number of client library tests that can all be run from the top-level directory. - make -k check + make -k check This will make all of the libraries (as necessary), and run through the unit tests defined in each of the client libraries. If a single @@ -199,7 +203,7 @@ at the end. To run the cross-language test suite, please run: - make cross + make cross This will run a set of tests that use different language clients and servers. diff --git a/build/cmake/uninstall.cmake b/build/cmake/uninstall.cmake new file mode 100644 index 00000000000..3842a83df55 --- /dev/null +++ b/build/cmake/uninstall.cmake @@ -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. +# + +cmake_minimum_required(VERSION 3.4) + +set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt") + +if(NOT EXISTS ${MANIFEST}) + message(FATAL_ERROR "Cannot find install mainfest: ${MANIFEST}") +endif() + +file(STRINGS ${MANIFEST} files) +foreach(file ${files}) + if(EXISTS ${file} OR IS_SYMLINK ${file}) + message(STATUS "Removing: ${file}") + + execute_process( + COMMAND ${CMAKE_COMMAND} -E remove ${file} + RESULT_VARIABLE result + OUTPUT_QUIET + ERROR_VARIABLE stderr + ERROR_STRIP_TRAILING_WHITESPACE + ) + + if(NOT ${result} EQUAL 0) + message(FATAL_ERROR "${stderr}") + endif() + else() + message(STATUS "Does-not-exist: ${file}") + endif() +endforeach(file) From eb8e8437a59fe7c0ca522be53a69f4e34bedc4f1 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 22 May 2020 01:11:11 +0200 Subject: [PATCH 608/756] addition to THRIFT-5185: Support for using WebSockets as a server transport to satisfy https://www.apache.org/legal/src-headers.html#3party --- LICENSE | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/LICENSE b/LICENSE index 3b6d7d74cc9..7bf24c93e76 100644 --- a/LICENSE +++ b/LICENSE @@ -236,4 +236,20 @@ For the lib/nodejs/lib/thrift/json_parse.js: */ (By Douglas Crockford ) + +-------------------------------------------------- +For lib/cpp/src/thrift/portable_endian.h + +// endian.h +// +// https://gist.github.com/panzi/6856583 +// +// I, Mathias Panzenböck, place this file hereby into the public domain. Use +// it at your own risk for whatever you like. In case there are +// jurisdictions that don't support putting things in the public domain you +// can also consider it to be "dual licensed" under the BSD, MIT and Apache +// licenses, if you want to. This code is trivial anyway. Consider it an +// example on how to get the endian conversion functions on different +// platforms. + -------------------------------------------------- From e6d7d13c35f5c9fe57889d7e77b0ba63910b1052 Mon Sep 17 00:00:00 2001 From: James Lacey Date: Fri, 22 May 2020 08:46:26 -0700 Subject: [PATCH 609/756] THRIFT-5215: Remove portable_endian.h Client: cpp Patch: James Lacey This closes #2152 --- LICENSE | 15 -- lib/cpp/Makefile.am | 3 +- lib/cpp/src/thrift/portable_endian.h | 131 ------------------ .../src/thrift/transport/TWebSocketServer.h | 15 +- 4 files changed, 8 insertions(+), 156 deletions(-) delete mode 100644 lib/cpp/src/thrift/portable_endian.h diff --git a/LICENSE b/LICENSE index 7bf24c93e76..a66fb6196b5 100644 --- a/LICENSE +++ b/LICENSE @@ -238,18 +238,3 @@ For the lib/nodejs/lib/thrift/json_parse.js: (By Douglas Crockford ) -------------------------------------------------- -For lib/cpp/src/thrift/portable_endian.h - -// endian.h -// -// https://gist.github.com/panzi/6856583 -// -// I, Mathias Panzenböck, place this file hereby into the public domain. Use -// it at your own risk for whatever you like. In case there are -// jurisdictions that don't support putting things in the public domain you -// can also consider it to be "dual licensed" under the BSD, MIT and Apache -// licenses, if you want to. This code is trivial anyway. Consider it an -// example on how to get the endian conversion functions on different -// platforms. - --------------------------------------------------- diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am index bcc6a09f98e..c73a17d7580 100755 --- a/lib/cpp/Makefile.am +++ b/lib/cpp/Makefile.am @@ -141,8 +141,7 @@ include_thrift_HEADERS = \ src/thrift/TApplicationException.h \ src/thrift/TLogging.h \ src/thrift/TToString.h \ - src/thrift/TBase.h \ - src/thrift/portable_endian.h + src/thrift/TBase.h include_concurrencydir = $(include_thriftdir)/concurrency include_concurrency_HEADERS = \ diff --git a/lib/cpp/src/thrift/portable_endian.h b/lib/cpp/src/thrift/portable_endian.h deleted file mode 100644 index e07010e09fa..00000000000 --- a/lib/cpp/src/thrift/portable_endian.h +++ /dev/null @@ -1,131 +0,0 @@ -// -// endian.h -// -// https://gist.github.com/panzi/6856583 -// -// I, Mathias Panzenböck, place this file hereby into the public domain. Use -// it at your own risk for whatever you like. In case there are -// jurisdictions that don't support putting things in the public domain you -// can also consider it to be "dual licensed" under the BSD, MIT and Apache -// licenses, if you want to. This code is trivial anyway. Consider it an -// example on how to get the endian conversion functions on different -// platforms. - -#ifndef PORTABLE_ENDIAN_H__ -#define PORTABLE_ENDIAN_H__ - -#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) - -# define __WINDOWS__ - -#endif - -#if defined(__linux__) || defined(__CYGWIN__) - -# include - -#elif defined(__APPLE__) - -# include - -# define htobe16(x) OSSwapHostToBigInt16(x) -# define htole16(x) OSSwapHostToLittleInt16(x) -# define be16toh(x) OSSwapBigToHostInt16(x) -# define le16toh(x) OSSwapLittleToHostInt16(x) - -# define htobe32(x) OSSwapHostToBigInt32(x) -# define htole32(x) OSSwapHostToLittleInt32(x) -# define be32toh(x) OSSwapBigToHostInt32(x) -# define le32toh(x) OSSwapLittleToHostInt32(x) - -# define htobe64(x) OSSwapHostToBigInt64(x) -# define htole64(x) OSSwapHostToLittleInt64(x) -# define be64toh(x) OSSwapBigToHostInt64(x) -# define le64toh(x) OSSwapLittleToHostInt64(x) - -# define __BYTE_ORDER BYTE_ORDER -# define __BIG_ENDIAN BIG_ENDIAN -# define __LITTLE_ENDIAN LITTLE_ENDIAN -# define __PDP_ENDIAN PDP_ENDIAN - -#elif defined(__OpenBSD__) - -# include - -#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) - -# include - -# define be16toh(x) betoh16(x) -# define le16toh(x) letoh16(x) - -# define be32toh(x) betoh32(x) -# define le32toh(x) letoh32(x) - -# define be64toh(x) betoh64(x) -# define le64toh(x) letoh64(x) - -#elif defined(__WINDOWS__) - -# include - -# if BYTE_ORDER == LITTLE_ENDIAN - -# define htobe16(x) htons(x) -# define htole16(x) (x) -# define be16toh(x) ntohs(x) -# define le16toh(x) (x) - -# define htobe32(x) htonl(x) -# define htole32(x) (x) -# define be32toh(x) ntohl(x) -# define le32toh(x) (x) - -# if defined(__MINGW32__) -# define htobe64(x) __builtin_bswap64(x) -# define htole64(x) (x) -# define be64toh(x) __builtin_bswap64(x) -# define le64toh(x) (x) -# else -# define htobe64(x) htonll(x) -# define htole64(x) (x) -# define be64toh(x) ntohll(x) -# define le64toh(x) (x) -# endif - -# elif BYTE_ORDER == BIG_ENDIAN - - /* that would be xbox 360 */ -# define htobe16(x) (x) -# define htole16(x) __builtin_bswap16(x) -# define be16toh(x) (x) -# define le16toh(x) __builtin_bswap16(x) - -# define htobe32(x) (x) -# define htole32(x) __builtin_bswap32(x) -# define be32toh(x) (x) -# define le32toh(x) __builtin_bswap32(x) - -# define htobe64(x) (x) -# define htole64(x) __builtin_bswap64(x) -# define be64toh(x) (x) -# define le64toh(x) __builtin_bswap64(x) - -# else - -# error byte order not supported - -# endif - -# define __BYTE_ORDER BYTE_ORDER -# define __BIG_ENDIAN BIG_ENDIAN -# define __LITTLE_ENDIAN LITTLE_ENDIAN -# define __PDP_ENDIAN PDP_ENDIAN - -#else - -# error platform not supported - -#endif - -#endif diff --git a/lib/cpp/src/thrift/transport/TWebSocketServer.h b/lib/cpp/src/thrift/transport/TWebSocketServer.h index 8edc286fe67..2e94c839d35 100644 --- a/lib/cpp/src/thrift/transport/TWebSocketServer.h +++ b/lib/cpp/src/thrift/transport/TWebSocketServer.h @@ -20,8 +20,6 @@ #ifndef _THRIFT_TRANSPORT_TWEBSOCKETSERVER_H_ #define _THRIFT_TRANSPORT_TWEBSOCKETSERVER_H_ 1 -#include - #include #include #include @@ -29,6 +27,7 @@ #include #include +#include #include #include #if defined(_MSC_VER) || defined(__MINGW32__) @@ -200,7 +199,7 @@ class TWebSocketServer : public THttpServer { void failConnection(CloseCode reason) { writeFrameHeader(Opcode::Close); - auto buffer = htobe16(static_cast(reason)); + auto buffer = htons(static_cast(reason)); transport_->write(reinterpret_cast(&buffer), 2); transport_->flush(); transport_->close(); @@ -255,13 +254,13 @@ class TWebSocketServer : public THttpServer { if (read < 2) { return false; } - payloadLength = be16toh(*reinterpret_cast(headerBuffer)); + payloadLength = ntohs(*reinterpret_cast(headerBuffer)); } else if (payloadLength == 127) { read = transport_->read(headerBuffer, 8); if (read < 8) { return false; } - payloadLength = be64toh(*reinterpret_cast(headerBuffer)); + payloadLength = THRIFT_ntohll(*reinterpret_cast(headerBuffer)); if ((payloadLength & 0x8000000000000000) != 0) { failConnection(CloseCode::ProtocolError); throw TTransportException( @@ -307,7 +306,7 @@ class TWebSocketServer : public THttpServer { if (length >= 2) { uint8_t buffer[2]; readBuffer_.read(buffer, 2); - CloseCode closeCode = static_cast(be16toh(*reinterpret_cast(buffer))); + CloseCode closeCode = static_cast(ntohs(*reinterpret_cast(buffer))); THRIFT_UNUSED_VARIABLE(closeCode); string closeReason = readBuffer_.readAsString(length - 2); T_DEBUG("Connection closed: %d %s", closeCode, closeReason); @@ -359,10 +358,10 @@ class TWebSocketServer : public THttpServer { header[1] = static_cast(length); } else if (length < 65536) { header[1] = 126; - *reinterpret_cast(header + 2) = htobe16(length); + *reinterpret_cast(header + 2) = htons(length); } else { header[1] = 127; - *reinterpret_cast(header + 2) = htobe64(length); + *reinterpret_cast(header + 2) = THRIFT_htonll(length); } transport_->write(header, headerSize); From 797fe252e0df18a24aa025d00d1d53c288ef2d4f Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Wed, 20 May 2020 15:20:07 +0800 Subject: [PATCH 610/756] Supplement TNonblockingServer.py testcase Client: py Patch: Zezeng Wang This closes #2150 --- lib/py/CMakeLists.txt | 2 + lib/py/Makefile.am | 4 + .../test/test_thrift_file/TestServer.thrift | 23 ++++ lib/py/test/thrift_TNonblockingServer.py | 101 ++++++++++++++++++ 4 files changed, 130 insertions(+) create mode 100644 lib/py/test/test_thrift_file/TestServer.thrift create mode 100644 lib/py/test/thrift_TNonblockingServer.py diff --git a/lib/py/CMakeLists.txt b/lib/py/CMakeLists.txt index d56c7099bc6..9c4368b6b9e 100644 --- a/lib/py/CMakeLists.txt +++ b/lib/py/CMakeLists.txt @@ -20,6 +20,7 @@ include_directories(${PYTHON_INCLUDE_DIRS}) add_custom_target(python_build ALL + COMMAND ${THRIFT_COMPILER} --gen py test/test_thrift_file/TestServer.thrift COMMAND ${PYTHON_EXECUTABLE} setup.py build WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Building Python library" @@ -32,4 +33,5 @@ if(BUILD_TESTING) add_test(PythonThriftTBinaryProtocol ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_TBinaryProtocol.py) add_test(PythonThriftTZlibTransport ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_TZlibTransport.py) add_test(PythonThriftProtocol ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_TCompactProtocol.py) + add_test(PythonThriftTNonblockingServer ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/test/thrift_TNonblockingServer.py) endif() diff --git a/lib/py/Makefile.am b/lib/py/Makefile.am index 1d450ee10d0..c6c5ff38c2c 100644 --- a/lib/py/Makefile.am +++ b/lib/py/Makefile.am @@ -29,6 +29,7 @@ py3-test: py3-build $(PYTHON3) test/thrift_TBinaryProtocol.py $(PYTHON3) test/thrift_TZlibTransport.py $(PYTHON3) test/thrift_TCompactProtocol.py + $(PYTHON3) test/thrift_TNonblockingServer.py else py3-build: py3-test: @@ -36,6 +37,7 @@ endif all-local: py3-build $(PYTHON) setup.py build + ${THRIFT} --gen py test/test_thrift_file/TestServer.thrift # We're ignoring prefix here because site-packages seems to be # the equivalent of /usr/local/lib in Python land. @@ -51,10 +53,12 @@ check-local: all py3-test $(PYTHON) test/thrift_TBinaryProtocol.py $(PYTHON) test/thrift_TZlibTransport.py $(PYTHON) test/thrift_TCompactProtocol.py + $(PYTHON) test/thrift_TNonblockingServer.py clean-local: $(RM) -r build + $(RM) -r gen-py find . -type f \( -iname "*.pyc" \) | xargs rm -f find . -type d \( -iname "__pycache__" -or -iname "_trial_temp" \) | xargs rm -rf diff --git a/lib/py/test/test_thrift_file/TestServer.thrift b/lib/py/test/test_thrift_file/TestServer.thrift new file mode 100644 index 00000000000..0de8856a0a8 --- /dev/null +++ b/lib/py/test/test_thrift_file/TestServer.thrift @@ -0,0 +1,23 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + + +service TestServer{ + string add_and_get_msg(1:string msg) +} diff --git a/lib/py/test/thrift_TNonblockingServer.py b/lib/py/test/thrift_TNonblockingServer.py new file mode 100644 index 00000000000..7220879ac5d --- /dev/null +++ b/lib/py/test/thrift_TNonblockingServer.py @@ -0,0 +1,101 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +import os +import sys +import threading +import unittest +import time + +gen_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "gen-py") +sys.path.append(gen_path) +import _import_local_thrift # noqa +from TestServer import TestServer +from thrift.transport import TSocket, TTransport +from thrift.protocol import TBinaryProtocol +from thrift.server import TNonblockingServer + + +class Handler: + + def add_and_get_msg(self, msg): + return msg + + +class Server: + + def __init__(self): + handler = Handler() + processor = TestServer.Processor(handler) + transport = TSocket.TServerSocket("127.0.0.1", 30030) + self.server = TNonblockingServer.TNonblockingServer(processor, transport) + + def start_server(self): + print("-------start server ------\n") + self.server.serve() + print("------stop server -----\n") + + def close_server(self): + self.server.stop() + self.server.close() + + +class Client: + + def start_client(self): + transport = TSocket.TSocket("127.0.0.1", 30030) + trans = TTransport.TFramedTransport(transport) + protocol = TBinaryProtocol.TBinaryProtocol(trans) + client = TestServer.Client(protocol) + trans.open() + self.msg = client.add_and_get_msg("hello thrift") + + def get_message(self): + try: + msg = self.msg + return msg + except AttributeError as e: + raise e + print("self.msg not exit\n") + + +class TestNonblockingServer(unittest.TestCase): + + def test_normalconnection(self): + serve = Server() + client = Client() + + serve_thread = threading.Thread(target=serve.start_server) + client_thread = threading.Thread(target=client.start_client) + serve_thread.start() + time.sleep(10) + client_thread.start() + client_thread.join(0.5) + try: + msg = client.get_message() + self.assertEqual("hello thrift", msg) + except AssertionError as e: + raise e + print("assert failure") + finally: + serve.close_server() + + +if __name__ == '__main__': + unittest.main() From 0198542201a6bd7e09ebd5a8b1ac14d3cb2b2bb7 Mon Sep 17 00:00:00 2001 From: Eric Chen Date: Fri, 22 May 2020 22:05:11 -0700 Subject: [PATCH 611/756] THRIFT-5195: Handle Thrift union type sending for Swift Client: Swift Patch: Eric Chen This closes #2154 --- lib/swift/Sources/TStruct.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/swift/Sources/TStruct.swift b/lib/swift/Sources/TStruct.swift index f1208334609..d0a1a4bcd21 100644 --- a/lib/swift/Sources/TStruct.swift +++ b/lib/swift/Sources/TStruct.swift @@ -62,7 +62,7 @@ public extension TStruct { for (propName, propValue) in mirror.children { guard let propName = propName else { continue } - if let tval = unwrap(any: propValue) as? TSerializable, let id = Self.fieldIds[propName] { + if let tval = unwrap(any: propValue, parent: mirror) as? TSerializable, let id = Self.fieldIds[propName] { try block(propName, tval, id) } } @@ -78,10 +78,10 @@ public extension TStruct { /// - parameter any: Any instance to attempt to unwrap /// /// - returns: Unwrapped Any as Optional - private func unwrap(any: Any) -> Any? { + private func unwrap(any: Any, parent: Mirror) -> Any? { let mi = Mirror(reflecting: any) - if mi.displayStyle != .optional { return any } + if parent.displayStyle != .enum && mi.displayStyle != .optional { return any } if mi.children.count == 0 { return nil } let (_, some) = mi.children.first! From d28f39fbc7bb9607a150544dd8f73f027c898c9b Mon Sep 17 00:00:00 2001 From: Eric Chen Date: Tue, 19 May 2020 02:48:43 -0700 Subject: [PATCH 612/756] THRIFT-5129: Fix swift TSocketTransport on Mac Client: Swift Patch: Eric Chen This closes #2149 --- lib/swift/Sources/TSocketTransport.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/swift/Sources/TSocketTransport.swift b/lib/swift/Sources/TSocketTransport.swift index 57f62155ed7..640612b7349 100644 --- a/lib/swift/Sources/TSocketTransport.swift +++ b/lib/swift/Sources/TSocketTransport.swift @@ -159,7 +159,7 @@ public class TSocketTransport : TTransport { var addr = sockaddr_in(sin_len: UInt8(MemoryLayout.size), sin_family: sa_family_t(AF_INET), sin_port: in_port_t(htons(UInt16(port))), - sin_addr: in_addr(s_addr: in_addr_t(0)), + sin_addr: hostAddr, sin_zero: (0, 0, 0, 0, 0, 0, 0, 0)) #endif From 05023e81b264f249affdacad4ebae788b3ada85c Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Tue, 26 May 2020 15:31:20 -0700 Subject: [PATCH 613/756] THRIFT-5214: Connectivity check on go's TSocket Client: go Implement connectivity check on go's TSocket and TSSLSocket for non-Windows systems. The implementation is inspired by https://github.blog/2020-05-20-three-bugs-in-the-go-mysql-driver/ --- lib/go/thrift/socket.go | 23 ++--- lib/go/thrift/socket_conn.go | 111 ++++++++++++++++++++++ lib/go/thrift/socket_conn_test.go | 125 +++++++++++++++++++++++++ lib/go/thrift/socket_unix_conn.go | 73 +++++++++++++++ lib/go/thrift/socket_unix_conn_test.go | 105 +++++++++++++++++++++ lib/go/thrift/socket_windows_conn.go | 34 +++++++ lib/go/thrift/ssl_socket.go | 37 +++++--- 7 files changed, 483 insertions(+), 25 deletions(-) create mode 100644 lib/go/thrift/socket_conn.go create mode 100644 lib/go/thrift/socket_conn_test.go create mode 100644 lib/go/thrift/socket_unix_conn.go create mode 100644 lib/go/thrift/socket_unix_conn_test.go create mode 100644 lib/go/thrift/socket_windows_conn.go diff --git a/lib/go/thrift/socket.go b/lib/go/thrift/socket.go index 558818a9a76..7c765f56c8a 100644 --- a/lib/go/thrift/socket.go +++ b/lib/go/thrift/socket.go @@ -26,7 +26,7 @@ import ( ) type TSocket struct { - conn net.Conn + conn *socketConn addr net.Addr connectTimeout time.Duration socketTimeout time.Duration @@ -58,7 +58,7 @@ func NewTSocketFromAddrTimeout(addr net.Addr, connTimeout time.Duration, soTimeo // Creates a TSocket from an existing net.Conn func NewTSocketFromConnTimeout(conn net.Conn, connTimeout time.Duration) *TSocket { - return &TSocket{conn: conn, addr: conn.RemoteAddr(), connectTimeout: connTimeout, socketTimeout: connTimeout} + return &TSocket{conn: wrapSocketConn(conn), addr: conn.RemoteAddr(), connectTimeout: connTimeout, socketTimeout: connTimeout} } // Sets the connect timeout @@ -89,7 +89,7 @@ func (p *TSocket) pushDeadline(read, write bool) { // Connects the socket, creating a new socket object if necessary. func (p *TSocket) Open() error { - if p.IsOpen() { + if p.conn.isValid() { return NewTTransportException(ALREADY_OPEN, "Socket already connected.") } if p.addr == nil { @@ -102,7 +102,11 @@ func (p *TSocket) Open() error { return NewTTransportException(NOT_OPEN, "Cannot open bad address.") } var err error - if p.conn, err = net.DialTimeout(p.addr.Network(), p.addr.String(), p.connectTimeout); err != nil { + if p.conn, err = createSocketConnFromReturn(net.DialTimeout( + p.addr.Network(), + p.addr.String(), + p.connectTimeout, + )); err != nil { return NewTTransportException(NOT_OPEN, err.Error()) } return nil @@ -115,10 +119,7 @@ func (p *TSocket) Conn() net.Conn { // Returns true if the connection is open func (p *TSocket) IsOpen() bool { - if p.conn == nil { - return false - } - return true + return p.conn.IsOpen() } // Closes the socket. @@ -140,7 +141,7 @@ func (p *TSocket) Addr() net.Addr { } func (p *TSocket) Read(buf []byte) (int, error) { - if !p.IsOpen() { + if !p.conn.isValid() { return 0, NewTTransportException(NOT_OPEN, "Connection not open") } p.pushDeadline(true, false) @@ -149,7 +150,7 @@ func (p *TSocket) Read(buf []byte) (int, error) { } func (p *TSocket) Write(buf []byte) (int, error) { - if !p.IsOpen() { + if !p.conn.isValid() { return 0, NewTTransportException(NOT_OPEN, "Connection not open") } p.pushDeadline(false, true) @@ -161,7 +162,7 @@ func (p *TSocket) Flush(ctx context.Context) error { } func (p *TSocket) Interrupt() error { - if !p.IsOpen() { + if !p.conn.isValid() { return nil } return p.conn.Close() diff --git a/lib/go/thrift/socket_conn.go b/lib/go/thrift/socket_conn.go new file mode 100644 index 00000000000..b0f7b3e69b3 --- /dev/null +++ b/lib/go/thrift/socket_conn.go @@ -0,0 +1,111 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "bytes" + "io" + "net" +) + +// socketConn is a wrapped net.Conn that tries to do connectivity check. +type socketConn struct { + net.Conn + + buf bytes.Buffer +} + +var _ net.Conn = (*socketConn)(nil) + +// createSocketConnFromReturn is a language sugar to help create socketConn from +// return values of functions like net.Dial, tls.Dial, net.Listener.Accept, etc. +func createSocketConnFromReturn(conn net.Conn, err error) (*socketConn, error) { + if err != nil { + return nil, err + } + return &socketConn{ + Conn: conn, + }, nil +} + +// wrapSocketConn wraps an existing net.Conn into *socketConn. +func wrapSocketConn(conn net.Conn) *socketConn { + // In case conn is already wrapped, + // return it as-is and avoid double wrapping. + if sc, ok := conn.(*socketConn); ok { + return sc + } + + return &socketConn{ + Conn: conn, + } +} + +// isValid checks whether there's a valid connection. +// +// It's nil safe, and returns false if sc itself is nil, or if the underlying +// connection is nil. +// +// It's the same as the previous implementation of TSocket.IsOpen and +// TSSLSocket.IsOpen before we added connectivity check. +func (sc *socketConn) isValid() bool { + return sc != nil && sc.Conn != nil +} + +// IsOpen checks whether the connection is open. +// +// It's nil safe, and returns false if sc itself is nil, or if the underlying +// connection is nil. +// +// Otherwise, it tries to do a connectivity check and returns the result. +func (sc *socketConn) IsOpen() bool { + if !sc.isValid() { + return false + } + return sc.checkConn() == nil +} + +// Read implements io.Reader. +// +// On Windows, it behaves the same as the underlying net.Conn.Read. +// +// On non-Windows, it treats len(p) == 0 as a connectivity check instead of +// readability check, which means instead of blocking until there's something to +// read (readability check), or always return (0, nil) (the default behavior of +// go's stdlib implementation on non-Windows), it never blocks, and will return +// an error if the connection is lost. +func (sc *socketConn) Read(p []byte) (n int, err error) { + if len(p) == 0 { + return 0, sc.read0() + } + + n, err = sc.buf.Read(p) + if err != nil && err != io.EOF { + return + } + if n == len(p) { + return n, nil + } + // Continue reading from the wire. + var newRead int + newRead, err = sc.Conn.Read(p[n:]) + n += newRead + return +} diff --git a/lib/go/thrift/socket_conn_test.go b/lib/go/thrift/socket_conn_test.go new file mode 100644 index 00000000000..ab924620c78 --- /dev/null +++ b/lib/go/thrift/socket_conn_test.go @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "io" + "net" + "strings" + "testing" + "time" +) + +type serverSocketConnCallback func(testing.TB, *socketConn) + +func serverSocketConn(tb testing.TB, f serverSocketConnCallback) (net.Listener, error) { + tb.Helper() + + ln, err := net.Listen("tcp", "localhost:0") + if err != nil { + return nil, err + } + go func() { + for { + sc, err := createSocketConnFromReturn(ln.Accept()) + if err != nil { + // This is usually caused by Listener being + // closed, not really an error. + return + } + go f(tb, sc) + } + }() + return ln, nil +} + +func writeFully(tb testing.TB, w io.Writer, s string) bool { + tb.Helper() + + n, err := io.Copy(w, strings.NewReader(s)) + if err != nil { + tb.Errorf("Failed to write %q: %v", s, err) + return false + } + if int(n) < len(s) { + tb.Errorf("Only wrote %d out of %q", n, s) + return false + } + return true +} + +func TestSocketConn(t *testing.T) { + const ( + interval = time.Millisecond * 10 + first = "hello" + second = "world" + ) + + ln, err := serverSocketConn( + t, + func(tb testing.TB, sc *socketConn) { + defer sc.Close() + + if !writeFully(tb, sc, first) { + return + } + time.Sleep(interval) + writeFully(tb, sc, second) + }, + ) + if err != nil { + t.Fatal(err) + } + defer ln.Close() + + sc, err := createSocketConnFromReturn(net.Dial("tcp", ln.Addr().String())) + if err != nil { + t.Fatal(err) + } + buf := make([]byte, 1024) + + n, err := sc.Read(buf) + if err != nil { + t.Fatal(err) + } + read := string(buf[:n]) + if read != first { + t.Errorf("Expected read %q, got %q", first, read) + } + + n, err = sc.Read(buf) + if err != nil { + t.Fatal(err) + } + read = string(buf[:n]) + if read != second { + t.Errorf("Expected read %q, got %q", second, read) + } +} + +func TestSocketConnNilSafe(t *testing.T) { + sc := (*socketConn)(nil) + if sc.isValid() { + t.Error("Expected false for nil.isValid(), got true") + } + if sc.IsOpen() { + t.Error("Expected false for nil.IsOpen(), got true") + } +} diff --git a/lib/go/thrift/socket_unix_conn.go b/lib/go/thrift/socket_unix_conn.go new file mode 100644 index 00000000000..f18e0e67038 --- /dev/null +++ b/lib/go/thrift/socket_unix_conn.go @@ -0,0 +1,73 @@ +// +build !windows + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "io" + "syscall" +) + +func (sc *socketConn) read0() error { + return sc.checkConn() +} + +func (sc *socketConn) checkConn() error { + syscallConn, ok := sc.Conn.(syscall.Conn) + if !ok { + // No way to check, return nil + return nil + } + rc, err := syscallConn.SyscallConn() + if err != nil { + return err + } + + var n int + var buf [1]byte + + if readErr := rc.Read(func(fd uintptr) bool { + n, err = syscall.Read(int(fd), buf[:]) + return true + }); readErr != nil { + return readErr + } + + if err == syscall.EAGAIN || err == syscall.EWOULDBLOCK { + // This means the connection is still open but we don't have + // anything to read right now. + return nil + } + + if n > 0 { + // We got 1 byte, + // put it to sc's buf for the next real read to use. + sc.buf.Write(buf[:]) + return nil + } + + if err != nil { + return err + } + + // At this point, it means the other side already closed the connection. + return io.EOF +} diff --git a/lib/go/thrift/socket_unix_conn_test.go b/lib/go/thrift/socket_unix_conn_test.go new file mode 100644 index 00000000000..3563a259c13 --- /dev/null +++ b/lib/go/thrift/socket_unix_conn_test.go @@ -0,0 +1,105 @@ +// +build !windows + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "io" + "net" + "testing" + "time" +) + +func TestSocketConnUnix(t *testing.T) { + const ( + interval = time.Millisecond * 10 + first = "hello" + second = "world" + ) + + ln, err := serverSocketConn( + t, + func(tb testing.TB, sc *socketConn) { + defer sc.Close() + + time.Sleep(interval) + if !writeFully(tb, sc, first) { + return + } + time.Sleep(interval) + writeFully(tb, sc, second) + }, + ) + if err != nil { + t.Fatal(err) + } + defer ln.Close() + + sc, err := createSocketConnFromReturn(net.Dial("tcp", ln.Addr().String())) + if err != nil { + t.Fatal(err) + } + buf := make([]byte, 1024) + + if !sc.IsOpen() { + t.Error("Expected sc to report open, got false") + } + n, err := sc.Read(buf) + if err != nil { + t.Fatal(err) + } + read := string(buf[:n]) + if read != first { + t.Errorf("Expected read %q, got %q", first, read) + } + + if !sc.IsOpen() { + t.Error("Expected sc to report open, got false") + } + // Do connection check again twice after server already wrote new data, + // make sure we correctly buffered the read bytes + time.Sleep(interval * 10) + if !sc.IsOpen() { + t.Error("Expected sc to report open, got false") + } + if !sc.IsOpen() { + t.Error("Expected sc to report open, got false") + } + if sc.buf.Len() == 0 { + t.Error("Expected sc to buffer read bytes, got empty buffer") + } + n, err = sc.Read(buf) + if err != nil { + t.Fatal(err) + } + read = string(buf[:n]) + if read != second { + t.Errorf("Expected read %q, got %q", second, read) + } + + // Now it's supposed to be closed on the server side + if err := sc.read0(); err != io.EOF { + t.Errorf("Expected to get EOF on read0, got %v", err) + } + if sc.IsOpen() { + t.Error("Expected sc to report not open, got true") + } +} diff --git a/lib/go/thrift/socket_windows_conn.go b/lib/go/thrift/socket_windows_conn.go new file mode 100644 index 00000000000..679838c3b64 --- /dev/null +++ b/lib/go/thrift/socket_windows_conn.go @@ -0,0 +1,34 @@ +// +build windows + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +func (sc *socketConn) read0() error { + // On windows, we fallback to the default behavior of reading 0 bytes. + var p []byte + _, err := sc.Conn.Read(p) + return err +} + +func (sc *socketConn) checkConn() error { + // On windows, we always return nil for this check. + return nil +} diff --git a/lib/go/thrift/ssl_socket.go b/lib/go/thrift/ssl_socket.go index 45bf38a289b..661111cdd50 100644 --- a/lib/go/thrift/ssl_socket.go +++ b/lib/go/thrift/ssl_socket.go @@ -27,7 +27,7 @@ import ( ) type TSSLSocket struct { - conn net.Conn + conn *socketConn // hostPort contains host:port (e.g. "asdf.com:12345"). The field is // only valid if addr is nil. hostPort string @@ -62,7 +62,7 @@ func NewTSSLSocketFromAddrTimeout(addr net.Addr, cfg *tls.Config, timeout time.D // Creates a TSSLSocket from an existing net.Conn func NewTSSLSocketFromConnTimeout(conn net.Conn, cfg *tls.Config, timeout time.Duration) *TSSLSocket { - return &TSSLSocket{conn: conn, addr: conn.RemoteAddr(), timeout: timeout, cfg: cfg} + return &TSSLSocket{conn: wrapSocketConn(conn), addr: conn.RemoteAddr(), timeout: timeout, cfg: cfg} } // Sets the socket timeout @@ -91,12 +91,18 @@ func (p *TSSLSocket) Open() error { // If we have a hostname, we need to pass the hostname to tls.Dial for // certificate hostname checks. if p.hostPort != "" { - if p.conn, err = tls.DialWithDialer(&net.Dialer{ - Timeout: p.timeout}, "tcp", p.hostPort, p.cfg); err != nil { + if p.conn, err = createSocketConnFromReturn(tls.DialWithDialer( + &net.Dialer{ + Timeout: p.timeout, + }, + "tcp", + p.hostPort, + p.cfg, + )); err != nil { return NewTTransportException(NOT_OPEN, err.Error()) } } else { - if p.IsOpen() { + if p.conn.isValid() { return NewTTransportException(ALREADY_OPEN, "Socket already connected.") } if p.addr == nil { @@ -108,8 +114,14 @@ func (p *TSSLSocket) Open() error { if len(p.addr.String()) == 0 { return NewTTransportException(NOT_OPEN, "Cannot open bad address.") } - if p.conn, err = tls.DialWithDialer(&net.Dialer{ - Timeout: p.timeout}, p.addr.Network(), p.addr.String(), p.cfg); err != nil { + if p.conn, err = createSocketConnFromReturn(tls.DialWithDialer( + &net.Dialer{ + Timeout: p.timeout, + }, + p.addr.Network(), + p.addr.String(), + p.cfg, + )); err != nil { return NewTTransportException(NOT_OPEN, err.Error()) } } @@ -123,10 +135,7 @@ func (p *TSSLSocket) Conn() net.Conn { // Returns true if the connection is open func (p *TSSLSocket) IsOpen() bool { - if p.conn == nil { - return false - } - return true + return p.conn.IsOpen() } // Closes the socket. @@ -143,7 +152,7 @@ func (p *TSSLSocket) Close() error { } func (p *TSSLSocket) Read(buf []byte) (int, error) { - if !p.IsOpen() { + if !p.conn.isValid() { return 0, NewTTransportException(NOT_OPEN, "Connection not open") } p.pushDeadline(true, false) @@ -152,7 +161,7 @@ func (p *TSSLSocket) Read(buf []byte) (int, error) { } func (p *TSSLSocket) Write(buf []byte) (int, error) { - if !p.IsOpen() { + if !p.conn.isValid() { return 0, NewTTransportException(NOT_OPEN, "Connection not open") } p.pushDeadline(false, true) @@ -164,7 +173,7 @@ func (p *TSSLSocket) Flush(ctx context.Context) error { } func (p *TSSLSocket) Interrupt() error { - if !p.IsOpen() { + if !p.conn.isValid() { return nil } return p.conn.Close() From affea7bee468d4abc751fbbd1c2692ba5c7ac0e4 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 22 May 2020 17:28:30 +0200 Subject: [PATCH 614/756] THRIFT-5216 generate DeepCopy methods Client: netstd Patch: Jens Geyer This closes #2155 --- .../src/thrift/generate/t_netstd_generator.cc | 511 +++++++++++++-- .../src/thrift/generate/t_netstd_generator.h | 17 +- lib/netstd/Makefile.am | 12 +- ...rift.PublicInterfaces.Compile.Tests.csproj | 9 +- .../optional_required_default.thrift | 143 +++++ .../Collections/TCollectionsTests.cs | 195 +++++- .../Tests/Thrift.Tests/DataModel/DeepCopy.cs | 603 ++++++++++++++++++ .../Tests/Thrift.Tests/Thrift.Tests.csproj | 3 +- lib/netstd/Thrift/Collections/TCollections.cs | 21 +- lib/netstd/Thrift/Collections/THashSet.cs | 4 +- lib/netstd/Thrift/Protocol/TBase.cs | 5 +- .../ToString.cs} | 4 +- 12 files changed, 1435 insertions(+), 92 deletions(-) create mode 100644 lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift create mode 100644 lib/netstd/Tests/Thrift.Tests/DataModel/DeepCopy.cs rename lib/netstd/Thrift/{Collections/ToStringExtension.cs => Protocol/ToString.cs} (96%) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index 8b6389f1689..e83723cbe5d 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -51,6 +51,7 @@ t_netstd_generator::t_netstd_generator(t_program* program, const mapfirst.compare("union") == 0) - { + if (iter->first.compare("union") == 0) { union_ = true; } - else if (iter->first.compare("serial") == 0) - { + else if (iter->first.compare("serial") == 0) { serialize_ = true; wcf_namespace_ = iter->second; // since there can be only one namespace } - else if (iter->first.compare("wcf") == 0) - { + else if (iter->first.compare("wcf") == 0) { wcf_ = true; wcf_namespace_ = iter->second; } - else if (iter->first.compare("pascal") == 0) - { + else if (iter->first.compare("pascal") == 0) { use_pascal_case_properties = true; } + else if (iter->first.compare("no_deepcopy") == 0) { + suppress_deepcopy = true; + } else { throw "unknown option netstd:" + iter->first; } @@ -132,12 +132,19 @@ static bool field_has_default(t_field* tfield) { return tfield->get_value() != N static bool field_is_required(t_field* tfield) { return tfield->get_req() == t_field::T_REQUIRED; } -static bool type_can_be_null(t_type* ttype) +static t_type* resolve_typedef(t_type* ttype) { while (ttype->is_typedef()) { ttype = static_cast(ttype)->get_type(); } + return ttype; +} + + +static bool type_can_be_null(t_type* ttype) +{ + ttype = resolve_typedef(ttype); return ttype->is_container() || ttype->is_struct() || ttype->is_xception() || ttype->is_string(); } @@ -184,10 +191,11 @@ void t_netstd_generator::init_generator() } pverbose(".NET Standard options:\n"); - pverbose("- union ...... %s\n", (is_union_enabled() ? "ON" : "off")); - pverbose("- serialize .. %s\n", (is_serialize_enabled() ? "ON" : "off")); - pverbose("- wcf ........ %s\n", (is_wcf_enabled() ? "ON" : "off")); - pverbose("- pascal ..... %s\n", (use_pascal_case_properties ? "ON" : "off")); + pverbose("- union ......... %s\n", (is_union_enabled() ? "ON" : "off")); + pverbose("- serialize ..... %s\n", (is_serialize_enabled() ? "ON" : "off")); + pverbose("- wcf ........... %s\n", (is_wcf_enabled() ? "ON" : "off")); + pverbose("- pascal ........ %s\n", (use_pascal_case_properties ? "ON" : "off")); + pverbose("- no_deepcopy ... %s\n", (suppress_deepcopy ? "ON" : "off")); } string t_netstd_generator::normalize_name(string name) @@ -350,6 +358,7 @@ string t_netstd_generator::netstd_type_usings() const "using System.Collections.Generic;\n" "using System.Text;\n" "using System.IO;\n" + "using System.Linq;\n" "using System.Threading;\n" "using System.Threading.Tasks;\n" "using Thrift;\n" @@ -486,6 +495,7 @@ void t_netstd_generator::print_const_def_value(ostream& out, string name, t_type const map& val = value->get_map(); vector::const_iterator f_iter; map::const_iterator v_iter; + collect_extensions_types(static_cast(type)); prepare_member_name_mapping(static_cast(type)); for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) @@ -569,10 +579,8 @@ bool t_netstd_generator::print_const_value(ostream& out, string name, t_type* ty { out << indent(); bool need_static_construction = !in_static; - while (type->is_typedef()) - { - type = static_cast(type)->get_type(); - } + + type = resolve_typedef( type); if (!defval || needtype) { @@ -622,7 +630,11 @@ string t_netstd_generator::render_const_value(ostream& out, string name, t_type* switch (tbase) { case t_base_type::TYPE_STRING: - render << '"' << get_escaped_string(value) << '"'; + if (type->is_binary()) { + render << "System.Text.Encoding.UTF8.GetBytes(\"" << get_escaped_string(value) << "\")"; + } else { + render << '"' << get_escaped_string(value) << '"'; + } break; case t_base_type::TYPE_BOOL: render << ((value->get_integer() > 0) ? "true" : "false"); @@ -661,8 +673,194 @@ string t_netstd_generator::render_const_value(ostream& out, string name, t_type* return render.str(); } +void t_netstd_generator::collect_extensions_types(t_struct* tstruct) +{ + const vector& members = tstruct->get_members(); + vector::const_iterator m_iter; + + // make private members with public Properties + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) + { + collect_extensions_types((*m_iter)->get_type()); + } +} + +void t_netstd_generator::collect_extensions_types(t_type* ttype) +{ + ttype = resolve_typedef( ttype); + string key = type_name(ttype); + + if (ttype->is_struct() || ttype->is_xception()) + { + if( checked_extension_types.find(key) == checked_extension_types.end()) + { + checked_extension_types[key] = ttype; // prevent recursion + + t_struct* tstruct = static_cast(ttype); + collect_extensions_types(tstruct); + } + return; + } + + if (ttype->is_map() || ttype->is_set() || ttype->is_list()) + { + if( collected_extension_types.find(key) == collected_extension_types.end()) + { + collected_extension_types[key] = ttype; // prevent recursion + + if( ttype->is_map()) + { + t_map* tmap = static_cast(ttype); + collect_extensions_types(tmap->get_key_type()); + collect_extensions_types(tmap->get_val_type()); + } + else if (ttype->is_set()) + { + t_set* tset = static_cast(ttype); + collect_extensions_types(tset->get_elem_type()); + } + else if (ttype->is_list()) + { + t_list* tlist = static_cast(ttype); + collect_extensions_types(tlist->get_elem_type()); + } + } + + return; + } +} + +void t_netstd_generator::generate_extensions_file() +{ + if (collected_extension_types.empty()) + { + return; + } + + string f_exts_name = namespace_dir_ + '/' + program_name_ + ".Extensions.cs"; + ofstream_with_content_based_conditional_update f_exts; + f_exts.open(f_exts_name.c_str()); + + generate_extensions(f_exts, collected_extension_types); + + f_exts.close(); +} + +void t_netstd_generator::generate_extensions(ostream& out, map types) +{ + if (types.empty()) + { + return; + } + + reset_indent(); + out << autogen_comment() << netstd_type_usings() << endl; + + start_netstd_namespace(out); + + out << indent() << "public static class " << make_valid_csharp_identifier(program_name_) << "Extensions" << endl; + scope_up(out); + + bool needs_typecast = false; + std::map::const_iterator iter; + for( iter = types.begin(); iter != types.end(); ++iter) + { + out << indent() << "public static bool Equals(this " << iter->first << " instance, object that)" << endl; + scope_up(out); + out << indent() << "if (!(that is " << iter->first << " other)) return false;" << endl; + out << indent() << "if (ReferenceEquals(instance, other)) return true;" << endl; + out << endl; + out << indent() << "return TCollections.Equals(instance, other);" << endl; + scope_down(out); + out << endl << endl; + + out << indent() << "public static int GetHashCode(this " << iter->first << " instance)" << endl; + scope_up(out); + out << indent() << "return TCollections.GetHashCode(instance);" << endl; + scope_down(out); + out << endl << endl; + + if(! suppress_deepcopy) { + out << indent() << "public static " << iter->first << " " << DEEP_COPY_METHOD_NAME << "(this " << iter->first << " source)" << endl; + scope_up(out); + out << indent() << "if (source == null)" << endl; + indent_up(); + out << indent() << "return null;" << endl << endl; + indent_down(); + + string tmp_instance = tmp("tmp"); + out << indent() << "var " << tmp_instance << " = new " << iter->first << "(source.Count);" << endl; + if( iter->second->is_map()) + { + t_map* tmap = static_cast(iter->second); + string copy_key = get_deep_copy_method_call(tmap->get_key_type(), needs_typecast); + string copy_val = get_deep_copy_method_call(tmap->get_val_type(), needs_typecast); + bool null_key = type_can_be_null(tmap->get_key_type()); + bool null_val = type_can_be_null(tmap->get_val_type()); + + out << indent() << "foreach (var pair in source)" << endl; + indent_up(); + out << indent() << tmp_instance << ".Add("; + if( null_key) + { + out << "(pair.Key != null) ? pair.Key" << copy_key << " : null"; + } else { + out << "pair.Key" << copy_key; + } + out << ", "; + if( null_val) + { + out << "(pair.Value != null) ? pair.Value" << copy_val << " : null"; + } else { + out << "pair.Value" << copy_val; + } + out << ");" << endl; + indent_down(); + + } else if( iter->second->is_set() || iter->second->is_list()) { + string copy_elm; + bool null_elm = false; + if (iter->second->is_set()) + { + t_set* tset = static_cast(iter->second); + copy_elm = get_deep_copy_method_call(tset->get_elem_type(), needs_typecast); + null_elm = type_can_be_null(tset->get_elem_type()); + } + else // list + { + t_list* tlist = static_cast(iter->second); + copy_elm = get_deep_copy_method_call(tlist->get_elem_type(), needs_typecast); + null_elm = type_can_be_null(tlist->get_elem_type()); + } + + out << indent() << "foreach (var elem in source)" << endl; + indent_up(); + out << indent() << tmp_instance << ".Add("; + if( null_elm) + { + out << "(elem != null) ? elem" << copy_elm << " : null"; + } else { + out << "elem" << copy_elm; + } + out << ");" << endl; + indent_down(); + } + + out << indent() << "return " << tmp_instance << ";" << endl; + scope_down(out); + out << endl << endl; + } + } + + + scope_down(out); + end_netstd_namespace(out); +} + void t_netstd_generator::generate_struct(t_struct* tstruct) { + collect_extensions_types(tstruct); + if (is_union_enabled() && tstruct->is_union()) { generate_netstd_union(tstruct); @@ -707,6 +905,7 @@ void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struc out << endl; generate_netstd_doc(out, tstruct); + collect_extensions_types(tstruct); prepare_member_name_mapping(tstruct); if ((is_serialize_enabled() || is_wcf_enabled()) && !is_exception) @@ -753,7 +952,7 @@ void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struc if (is_required) { has_required_fields = true; - } + } else { has_non_required_fields = true; @@ -828,10 +1027,8 @@ void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struc for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { t_type* t = (*m_iter)->get_type(); - while (t->is_typedef()) - { - t = static_cast(t)->get_type(); - } + t = resolve_typedef(t); + if ((*m_iter)->get_value() != NULL) { if (field_is_required((*m_iter))) @@ -849,6 +1046,7 @@ void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struc indent_down(); out << indent() << "}" << endl << endl; + // if we have required fields, we add that CTOR too if (has_required_fields) { out << indent() << "public " << sharp_struct_name << "("; @@ -884,6 +1082,9 @@ void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struc out << indent() << "}" << endl << endl; } + // DeepCopy() + generate_netstd_deepcopy_method(out, tstruct, sharp_struct_name); + generate_netstd_struct_reader(out, tstruct); if (is_result) { @@ -913,6 +1114,7 @@ void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struc } } + void t_netstd_generator::generate_netstd_wcffault(ostream& out, t_struct* tstruct) { out << endl; @@ -947,6 +1149,57 @@ void t_netstd_generator::generate_netstd_wcffault(ostream& out, t_struct* tstruc out << indent() << "}" << endl << endl; } +void t_netstd_generator::generate_netstd_deepcopy_method(ostream& out, t_struct* tstruct, std::string sharp_struct_name) +{ + if( suppress_deepcopy) { + return; // feature disabled + } + + const vector& members = tstruct->get_members(); + vector::const_iterator m_iter; + + out << indent() << "public " << sharp_struct_name << " " << DEEP_COPY_METHOD_NAME << "()" << endl; + out << indent() << "{" << endl; + indent_up(); + + // return directly if there are only required fields + string tmp_instance = tmp("tmp"); + out << indent() << "var " << tmp_instance << " = new " << sharp_struct_name << "();" << endl; + + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { + bool needs_typecast = false; + t_type* ttype = (*m_iter)->get_type(); + string copy_op = get_deep_copy_method_call(ttype, needs_typecast); + + bool have_indent = false; + if (!field_is_required(*m_iter)) { + out << indent() << "if( this.__isset." << normalize_name((*m_iter)->get_name()) << ")" << endl; + indent_up(); + have_indent = true; + } + else if( type_can_be_null(ttype)) { + out << indent() << "if( this." << prop_name(*m_iter) << " != null)" << endl; + indent_up(); + have_indent = true; + } + + out << indent() << tmp_instance << "." << prop_name(*m_iter) << " = "; + if( needs_typecast) { + out << "(" << type_name(ttype) << ")"; + } + out << "this." << prop_name(*m_iter) << copy_op << ";" << endl; + + if (have_indent) { + indent_down(); + } + } + + out << indent() << "return " << tmp_instance << ";" << endl; + + indent_down(); + out << indent() << "}" << endl << endl; +} + void t_netstd_generator::generate_netstd_struct_reader(ostream& out, t_struct* tstruct) { out << indent() << "public async Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken)" << endl @@ -1298,8 +1551,8 @@ void t_netstd_generator::generate_netstd_union_definition(ostream& out, t_struct // Let's define the class first start_netstd_namespace(out); - out << indent() << "public abstract partial class " << tunion->get_name() << " : TUnionBase" << endl - << indent() << "{" << endl; + out << indent() << "public abstract partial class " << tunion->get_name() << " : TUnionBase" << endl; + out << indent() << "{" << endl; indent_up(); out << indent() << "public abstract Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken);" << endl @@ -1312,13 +1565,106 @@ void t_netstd_generator::generate_netstd_union_definition(ostream& out, t_struct indent_down(); out << indent() << "}" << endl << endl; - out << indent() << "public class ___undefined : " << tunion->get_name() << endl - << indent() << "{" << endl; + const vector& fields = tunion->get_members(); + vector::const_iterator f_iter; + + out << indent() << "public override bool Equals(object that)" << endl; + scope_up(out); + out << indent() << "if (!(that is " << tunion->get_name() << " other)) return false;" << endl; + out << indent() << "if (ReferenceEquals(this, other)) return true;" << endl; + out << endl; + out << indent() << "if(this.Isset != other.Isset) return false;" << endl; + out << endl; + out << indent() << "switch (Isset)" << endl; + scope_up(out); + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + bool needs_typecast = false; + string copy_op = get_deep_copy_method_call((*f_iter)->get_type(), needs_typecast); + out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; + indent_up(); + out << indent() << "return Equals(As_" << (*f_iter)->get_name() << ", other.As_" << (*f_iter)->get_name() << ");" << endl; + indent_down(); + } + out << indent() << "default:" << endl; + indent_up(); + out << indent() << "return true;" << endl; + indent_down(); + indent_down(); + scope_down(out); + scope_down(out); + out << endl; + + out << indent() << "public override int GetHashCode()" << endl; + out << indent() << "{" << endl; + indent_up(); + out << indent() << "switch (Isset)" << endl; + out << indent() << "{" << endl; + indent_up(); + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + bool needs_typecast = false; + string copy_op = get_deep_copy_method_call((*f_iter)->get_type(), needs_typecast); + out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; + indent_up(); + out << indent() << "return As_" << (*f_iter)->get_name() << ".GetHashCode();" << endl; + indent_down(); + } + out << indent() << "default:" << endl; + indent_up(); + out << indent() << "return (new ___undefined()).GetHashCode();" << endl; + indent_down(); + indent_down(); + out << indent() << "}" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + + if( ! suppress_deepcopy) { + out << indent() << "public " << tunion->get_name() << " DeepCopy()" << endl; + out << indent() << "{" << endl; + indent_up(); + out << indent() << "switch (Isset)" << endl; + out << indent() << "{" << endl; + indent_up(); + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) + { + bool needs_typecast = false; + string copy_op = get_deep_copy_method_call((*f_iter)->get_type(), needs_typecast); + out << indent() << "case " << (*f_iter)->get_key() << ":" << endl; + indent_up(); + out << indent() << "return new " << (*f_iter)->get_name() << "(As_" << (*f_iter)->get_name() << copy_op << ");" << endl; + indent_down(); + } + out << indent() << "default:" << endl; + indent_up(); + out << indent() << "return new ___undefined();" << endl; + indent_down(); + indent_down(); + out << indent() << "}" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + } + + out << indent() << "public class ___undefined : " << tunion->get_name() << endl; + out << indent() << "{" << endl; indent_up(); out << indent() << "public override object Data { get { return null; } }" << endl << indent() << "public ___undefined() : base(0) {}" << endl << endl; + + if( ! suppress_deepcopy) { + out << indent() << "public new ___undefined DeepCopy()" << endl; + out << indent() << "{" << endl; + indent_up(); + out << indent() << "return new ___undefined();" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + } + t_struct undefined_struct(program_,"___undefined"); + generate_netstd_struct_equals(out, &undefined_struct); + generate_netstd_struct_hashcode(out, &undefined_struct); + out << indent() << "public override Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl << indent() << "{" << endl; indent_up(); @@ -1328,9 +1674,6 @@ void t_netstd_generator::generate_netstd_union_definition(ostream& out, t_struct indent_down(); out << indent() << "}" << endl << endl; - const vector& fields = tunion->get_members(); - vector::const_iterator f_iter; - for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { generate_netstd_union_class(out, tunion, (*f_iter)); @@ -1360,8 +1703,8 @@ void t_netstd_generator::generate_netstd_union_class(ostream& out, t_struct* tun << endl; - out << indent() << "public class " << tfield->get_name() << " : " << tunion->get_name() << endl - << indent() << "{" << endl; + out << indent() << "public class " << tfield->get_name() << " : " << tunion->get_name() << endl; + out << indent() << "{" << endl; indent_up(); out << indent() << "private " << type_name(tfield->get_type()) << " _data;" << endl @@ -1373,6 +1716,34 @@ void t_netstd_generator::generate_netstd_union_class(ostream& out, t_struct* tun indent_down(); out << indent() << "}" << endl; + if( ! suppress_deepcopy) { + out << indent() << "public new " << tfield->get_name() << " DeepCopy()" << endl; + out << indent() << "{" << endl; + indent_up(); + bool needs_typecast = false; + string copy_op = get_deep_copy_method_call(tfield->get_type(), needs_typecast); + out << indent() << "return new " << tfield->get_name() << "(_data" << copy_op << ");" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + } + + out << indent() << "public override bool Equals(object that)" << endl; + out << indent() << "{" << endl; + indent_up(); + out << indent() << "if (!(that is " << tunion->get_name() << " other)) return false;" << endl; + out << indent() << "if (ReferenceEquals(this, other)) return true;" << endl; + out << endl; + out << indent() << "return Equals( _data, other.As_" << tfield->get_name() << ");" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + + out << indent() << "public override int GetHashCode()" << endl; + out << indent() << "{" << endl; + indent_up(); + out << indent() << "return _data.GetHashCode();" << endl; + indent_down(); + out << indent() << "}" << endl << endl; + out << indent() << "public override async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) {" << endl; indent_up(); @@ -1403,6 +1774,7 @@ void t_netstd_generator::generate_netstd_union_class(ostream& out, t_struct* tun out << indent() << "oprot.DecrementRecursionDepth();" << endl; indent_down(); out << indent() << "}" << endl; + indent_down(); out << indent() << "}" << endl; indent_down(); out << indent() << "}" << endl << endl; @@ -1544,6 +1916,9 @@ void t_netstd_generator::generate_service(t_service* tservice) f_service.close(); indent_validate(ic, "generate_service."); + + // right at the end, after everything else + generate_extensions_file(); } void t_netstd_generator::generate_service_interface(ostream& out, t_service* tservice) @@ -1602,6 +1977,7 @@ void t_netstd_generator::generate_service_helpers(ostream& out, t_service* tserv for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { t_struct* ts = (*f_iter)->get_arglist(); + collect_extensions_types(ts); generate_netstd_struct_definition(out, ts, false, true); generate_function_helpers(out, *f_iter); } @@ -1659,6 +2035,7 @@ void t_netstd_generator::generate_service_client(ostream& out, t_service* tservi indent_up(); t_struct* arg_struct = (*functions_iterator)->get_arglist(); + collect_extensions_types(arg_struct); prepare_member_name_mapping(arg_struct); const vector& fields = arg_struct->get_members(); vector::const_iterator fld_iter; @@ -1682,6 +2059,7 @@ void t_netstd_generator::generate_service_client(ostream& out, t_service* tservi string resultname = (*functions_iterator)->get_name() + "Result"; t_struct noargs(program_); t_struct* xs = (*functions_iterator)->get_xceptions(); + collect_extensions_types(xs); prepare_member_name_mapping(xs, xs->get_members(), resultname); out << indent() << endl @@ -1894,6 +2272,7 @@ void t_netstd_generator::generate_function_helpers(ostream& out, t_function* tfu result.append(*f_iter); } + collect_extensions_types(&result); generate_netstd_struct_definition(out, &result, false, true, true); } @@ -1944,6 +2323,7 @@ void t_netstd_generator::generate_process_function_async(ostream& out, t_service out << "await _iAsync." << normalize_name(tfunction->get_name()) << "Async("; bool first = true; + collect_extensions_types(arg_struct); prepare_member_name_mapping(arg_struct); for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { @@ -1970,6 +2350,7 @@ void t_netstd_generator::generate_process_function_async(ostream& out, t_service vector::const_iterator x_iter; + collect_extensions_types(xs); prepare_member_name_mapping(xs, xs->get_members(), resultname); if (xceptions.size() > 0) { @@ -2114,10 +2495,7 @@ void t_netstd_generator::generate_netstd_union_reader(ostream& out, t_struct* tu void t_netstd_generator::generate_deserialize_field(ostream& out, t_field* tfield, string prefix, bool is_propertyless) { t_type* type = tfield->get_type(); - while (type->is_typedef()) - { - type = static_cast(type)->get_type(); - } + type = resolve_typedef( type); if (type->is_void()) { @@ -2326,10 +2704,7 @@ void t_netstd_generator::generate_deserialize_list_element(ostream& out, t_list* void t_netstd_generator::generate_serialize_field(ostream& out, t_field* tfield, string prefix, bool is_propertyless) { t_type* type = tfield->get_type(); - while (type->is_typedef()) - { - type = static_cast(type)->get_type(); - } + type = resolve_typedef( type); string name = prefix + (is_propertyless ? "" : prop_name(tfield)); @@ -2718,10 +3093,7 @@ string t_netstd_generator::prop_name(t_field* tfield, bool suppress_mapping) { string t_netstd_generator::type_name(t_type* ttype) { - while (ttype->is_typedef()) - { - ttype = static_cast(ttype)->get_type(); - } + ttype = resolve_typedef(ttype); if (ttype->is_base_type()) { @@ -2768,11 +3140,10 @@ string t_netstd_generator::base_type_name(t_base_type* tbase) case t_base_type::TYPE_VOID: return "void"; case t_base_type::TYPE_STRING: + if (tbase->is_binary()) { - if (tbase->is_binary()) - { - return "byte[]"; - } + return "byte[]"; + } else { return "string"; } case t_base_type::TYPE_BOOL: @@ -2792,16 +3163,46 @@ string t_netstd_generator::base_type_name(t_base_type* tbase) } } +string t_netstd_generator::get_deep_copy_method_call(t_type* ttype, bool& needs_typecast) +{ + ttype = resolve_typedef(ttype); + + needs_typecast = false; + if (ttype->is_base_type()) + { + t_base_type::t_base tbase = static_cast(ttype)->get_base(); + switch (tbase) + { + case t_base_type::TYPE_STRING: + if (ttype->is_binary()) + { + return ".ToArray()"; + } else { + return ""; // simple assignment will do, strings are immutable in C# + } + break; + default: + return ""; // simple assignment will do + } + } + else if (ttype->is_enum()) + { + return ""; // simple assignment will do + } + else + { + needs_typecast = (! ttype->is_container()); + return "." + DEEP_COPY_METHOD_NAME + "()"; + } +} + string t_netstd_generator::declare_field(t_field* tfield, bool init, string prefix) { string result = type_name(tfield->get_type()) + " " + prefix + tfield->get_name(); if (init) { t_type* ttype = tfield->get_type(); - while (ttype->is_typedef()) - { - ttype = static_cast(ttype)->get_type(); - } + ttype = resolve_typedef(ttype); if (ttype->is_base_type() && field_has_default(tfield)) { std::ofstream dummy; @@ -2897,10 +3298,7 @@ string t_netstd_generator::argument_list(t_struct* tstruct) string t_netstd_generator::type_to_enum(t_type* type) { - while (type->is_typedef()) - { - type = static_cast(type)->get_type(); - } + type = resolve_typedef( type); if (type->is_base_type()) { @@ -3051,4 +3449,5 @@ THRIFT_REGISTER_GENERATOR( " serial: Add serialization support to generated classes.\n" " union: Use new union typing, which includes a static read function for union types.\n" " pascal: Generate Pascal Case property names according to Microsoft naming convention.\n" + " no_deepcopy: Suppress generation of DeepCopy() method.\n" ) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.h b/compiler/cpp/src/thrift/generate/t_netstd_generator.h index 30082e8d730..ccbd902356e 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.h +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.h @@ -45,6 +45,8 @@ using std::vector; static const string endl = "\n"; // avoid ostream << std::endl flushes +static const string DEEP_COPY_METHOD_NAME = "DeepCopy"; + class t_netstd_generator : public t_oop_generator { @@ -60,7 +62,6 @@ class t_netstd_generator : public t_oop_generator t_netstd_generator(t_program* program, const map& parsed_options, const string& option_string); bool is_wcf_enabled() const; - bool is_nullable_enabled() const; bool is_hashcode_enabled() const; bool is_serialize_enabled() const; bool is_union_enabled() const; @@ -78,6 +79,9 @@ class t_netstd_generator : public t_oop_generator void generate_xception(t_struct* txception); void generate_service(t_service* tservice); + // additional files + void generate_extensions_file(); + void generate_property(ostream& out, t_field* tfield, bool isPublic, bool generateIsset); void generate_netstd_property(ostream& out, t_field* tfield, bool isPublic, bool includeIsset = true, string fieldPrefix = ""); bool print_const_value(ostream& out, string name, t_type* type, t_const_value* value, bool in_static, bool defval = false, bool needtype = false); @@ -90,6 +94,7 @@ class t_netstd_generator : public t_oop_generator void generate_netstd_union_definition(ostream& out, t_struct* tunion); void generate_netstd_union_class(ostream& out, t_struct* tunion, t_field* tfield); void generate_netstd_wcffault(ostream& out, t_struct* tstruct); + void generate_netstd_deepcopy_method(ostream& out, t_struct* tstruct, std::string sharp_struct_name); void generate_netstd_struct_reader(ostream& out, t_struct* tstruct); void generate_netstd_struct_result_writer(ostream& out, t_struct* tstruct); void generate_netstd_struct_writer(ostream& out, t_struct* tstruct); @@ -141,17 +146,19 @@ class t_netstd_generator : public t_oop_generator string namespace_name_; string namespace_dir_; - bool nullable_; bool union_; bool hashcode_; bool serialize_; bool wcf_; bool use_pascal_case_properties; + bool suppress_deepcopy; string wcf_namespace_; map netstd_keywords; vector member_mapping_scopes; - + map collected_extension_types; + map checked_extension_types; + void init_keywords(); string normalize_name(string name); string make_valid_csharp_identifier(string const& fromName); @@ -159,5 +166,9 @@ class t_netstd_generator : public t_oop_generator void prepare_member_name_mapping(void* scope, const vector& members, const string& structname); void cleanup_member_name_mapping(void* scope); string get_mapped_member_name(string oldname); + string get_deep_copy_method_call(t_type* ttype, bool& needs_typecast); + void collect_extensions_types(t_struct* tstruct); + void collect_extensions_types(t_type* ttype); + void generate_extensions(ostream& out, map types); void reset_indent(); }; diff --git a/lib/netstd/Makefile.am b/lib/netstd/Makefile.am index 503a1761367..abb680cc403 100644 --- a/lib/netstd/Makefile.am +++ b/lib/netstd/Makefile.am @@ -23,12 +23,21 @@ all-local: $(DOTNETCORE) build -c Release check-local: + $(DOTNETCORE) test Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj $(DOTNETCORE) test Tests/Thrift.Tests/Thrift.Tests.csproj $(DOTNETCORE) test Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj clean-local: $(RM) -r Thrift/bin $(RM) -r Thrift/obj + $(RM) -r Benchmarks/Thrift.Benchmarks/bin + $(RM) -r Benchmarks/Thrift.Benchmarks/obj + $(RM) -r Tests/Thrift.Tests/bin + $(RM) -r Tests/Thrift.Tests/obj + $(RM) -r Tests/Thrift.IntegrationTests/bin + $(RM) -r Tests/Thrift.IntegrationTests/obj + $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/bin + $(RM) -r Tests/Thrift.PublicInterfaces.Compile.Tests/obj EXTRA_DIST = \ README.md \ @@ -36,6 +45,7 @@ EXTRA_DIST = \ Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj \ Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj \ Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs \ + Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift \ Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift \ Tests/Thrift.Tests/Thrift.Tests.csproj \ Tests/Thrift.Tests/Protocols \ @@ -55,4 +65,4 @@ EXTRA_DIST = \ build.sh \ runtests.cmd \ runtests.sh - \ No newline at end of file + diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj index d2db348d873..1938ddc9473 100644 --- a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj @@ -42,13 +42,16 @@ - + + + + - + - + diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift new file mode 100644 index 00000000000..1f6c7ee5ead --- /dev/null +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift @@ -0,0 +1,143 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +// Testcase for THRIFT-5216 generate DeepCopy methods + +namespace netstd OptReqDefTest + +enum Distance +{ + foo = 0, + bar = 1, + baz = 2 +} + +struct RaceDetails +{ + // this is really the max field index used here, intentionally placed at the beginning + 666: required Distance triplesix + + // without default values + + 1: optional Distance opt_one + 2: optional double opt_two + 3: optional i16 opt_three + 4: optional string opt_four + 5: optional binary opt_five + 6: optional list opt_six + 7: optional set opt_seven + 8: optional map opt_eight + + 11: required Distance req_one + 12: required double req_two + 13: required i16 req_three + 14: required string req_four + 15: required binary req_five + 16: required list req_six + 17: required set req_seven + 18: required map req_eight + + 21: Distance def_one + 22: double def_two + 23: i16 def_three + 24: string def_four + 25: binary def_five + 26: list def_six + 27: set def_seven + 28: map def_eight + + // having default values + + 31: optional Distance opt_one_with_value = Distance.bar + 32: optional double opt_two_with_value = 2.22 + 33: optional i16 opt_three_with_value = 3 + 34: optional string opt_four_with_value = "four" + 35: optional binary opt_five_with_value = "five\t" + 36: optional list opt_six_with_value = [6] + 37: optional set opt_seven_with_value = [7] + 38: optional map opt_eight_with_value = { 8 : 8 } + + 41: required Distance req_one_with_value = Distance.bar + 42: required double req_two_with_value = 2.22 + 43: required i16 req_three_with_value = 3 + 44: required string req_four_with_value = "four" + 45: required binary req_five_with_value = "five" + 46: required list req_six_with_value = [6] + 47: required set req_seven_with_value = [7] + 48: required map req_eight_with_value = { 8 : 8 } + + 51: Distance def_one_with_value = Distance.bar + 52: double def_two_with_value = 2.22 + 53: i16 def_three_with_value = 3 + 54: string def_four_with_value = "four" + 55: binary def_five_with_value = "five" + 56: list def_six_with_value = [6] + 57: set def_seven_with_value = [7] + 58: map def_eight_with_value = { 8 : 8 } + + 90: optional bool last_of_the_mohicans + + // some more complicated ones, including recursion + + 300: required list far_list + 301: optional set far_set + 302: map far_map + + 310: required set> far_set_list + 311: optional list>> far_list_map_set + 312: map far_map_dist_to_rds + + 320: required RaceDetails req_nested + 321: optional RaceDetails opt_nested + 322: RaceDetails def_nested + + 330: required jack req_union + 331: optional jack opt_union + 332: jack def_union +} + +union jack { + 1: list stars + 2: list stripes + + 310: set> far_set_list + 311: list>> far_list_map_set + 312: map far_map_dist_to_rds + + 320: jack nested_union + 321: RaceDetails nested_struct + + 401: optional Distance opt_one + 402: optional double opt_two + 403: optional i16 opt_three + 404: optional string opt_four + 405: optional binary opt_five + 406: optional list opt_six + 407: optional set opt_seven + 408: optional map opt_eight +} + +typedef RaceDetails RaceDetails2 +typedef list RDs + +exception CrashBoomBang { + 1 : i32 MyErrorCode +} + +service foobar { + set>> DoItNow( 1 : list>> rd, 2: i32 mitDefault = 42) throws (1: CrashBoomBang cbb) +} + diff --git a/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs b/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs index 1be99b48fd6..061032ae0a3 100644 --- a/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs +++ b/lib/netstd/Tests/Thrift.Tests/Collections/TCollectionsTests.cs @@ -1,4 +1,4 @@ -// Licensed to the Apache Software Foundation(ASF) under one +// Licensed to the Apache Software Foundation(ASF) under one // or more contributor license agreements.See the NOTICE file // distributed with this work for additional information // regarding copyright ownership.The ASF licenses this file @@ -17,6 +17,8 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography.Xml; using System.Text; using Microsoft.VisualStudio.TestTools.UnitTesting; using Thrift.Collections; @@ -30,54 +32,209 @@ public class TCollectionsTests //TODO: Add tests for IEnumerable with objects and primitive values inside [TestMethod] - public void TCollection_Equals_Primitive_Test() + public void TCollection_List_Equals_Primitive_Test() { var collection1 = new List {1,2,3}; var collection2 = new List {1,2,3}; - - var result = TCollections.Equals(collection1, collection2); - - Assert.IsTrue(result); + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsTrue(collection1.SequenceEqual(collection2)); } [TestMethod] - public void TCollection_Equals_Primitive_Different_Test() + public void TCollection_List_Equals_Primitive_Different_Test() { var collection1 = new List { 1, 2, 3 }; var collection2 = new List { 1, 2 }; + Assert.IsFalse(TCollections.Equals(collection1, collection2)); + Assert.IsFalse(collection1.SequenceEqual(collection2)); - var result = TCollections.Equals(collection1, collection2); - - Assert.IsFalse(result); + collection2.Add(4); + Assert.IsFalse(TCollections.Equals(collection1, collection2)); + Assert.IsFalse(collection1.SequenceEqual(collection2)); } [TestMethod] - public void TCollection_Equals_Objects_Test() + public void TCollection_List_Equals_Objects_Test() { var collection1 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; var collection2 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsTrue(collection1.SequenceEqual(collection2)); + } - var result = TCollections.Equals(collection1, collection2); - - // references to different collections - Assert.IsFalse(result); + [TestMethod] + public void TCollection_List_List_Equals_Objects_Test() + { + var collection1 = new List> { new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } }; + var collection2 = new List> { new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } }; + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsFalse(collection1.SequenceEqual(collection2)); // SequenceEqual() calls Equals() of the inner list instead of SequenceEqual() } [TestMethod] - public void TCollection_Equals_OneAndTheSameObject_Test() + public void TCollection_List_Equals_OneAndTheSameObject_Test() { var collection1 = new List { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; var collection2 = collection1; + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsTrue(collection1.SequenceEqual(collection2)); + } - var result = TCollections.Equals(collection1, collection2); + [TestMethod] + public void TCollection_Set_Equals_Primitive_Test() + { + var collection1 = new THashSet {1,2,3}; + var collection2 = new THashSet {1,2,3}; + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsTrue(collection1.SequenceEqual(collection2)); + } - // references to one and the same collection - Assert.IsTrue(result); + [TestMethod] + public void TCollection_Set_Equals_Primitive_Different_Test() + { + var collection1 = new THashSet { 1, 2, 3 }; + var collection2 = new THashSet { 1, 2 }; + Assert.IsFalse(TCollections.Equals(collection1, collection2)); + Assert.IsFalse(collection1.SequenceEqual(collection2)); + + collection2.Add(4); + Assert.IsFalse(TCollections.Equals(collection1, collection2)); + Assert.IsFalse(collection1.SequenceEqual(collection2)); } + [TestMethod] + public void TCollection_Set_Equals_Objects_Test() + { + var collection1 = new THashSet { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; + var collection2 = new THashSet { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsTrue(collection1.SequenceEqual(collection2)); + } + + [TestMethod] + public void TCollection_Set_Set_Equals_Objects_Test() + { + var collection1 = new THashSet> { new THashSet { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } }; + var collection2 = new THashSet> { new THashSet { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } } }; + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsFalse(collection1.SequenceEqual(collection2)); // SequenceEqual() calls Equals() of the inner list instead of SequenceEqual() + } + + [TestMethod] + public void TCollection_Set_Equals_OneAndTheSameObject_Test() + { + var collection1 = new THashSet { new ExampleClass { X = 1 }, new ExampleClass { X = 2 } }; + var collection2 = collection1; // references to one and the same collection + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsTrue(collection1.SequenceEqual(collection2)); + } + + + [TestMethod] + public void TCollection_Map_Equals_Primitive_Test() + { + var collection1 = new Dictionary { [1] = 1, [2] = 2, [3] = 3 }; + var collection2 = new Dictionary { [1] = 1, [2] = 2, [3] = 3 }; + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsTrue(collection1.SequenceEqual(collection2)); + } + + [TestMethod] + public void TCollection_Map_Equals_Primitive_Different_Test() + { + var collection1 = new Dictionary { [1] = 1, [2] = 2, [3] = 3 }; + var collection2 = new Dictionary { [1] = 1, [2] = 2 }; + Assert.IsFalse(TCollections.Equals(collection1, collection2)); + Assert.IsFalse(collection1.SequenceEqual(collection2)); + + collection2[3] = 3; + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsTrue(collection1.SequenceEqual(collection2)); + + collection2[3] = 4; + Assert.IsFalse(TCollections.Equals(collection1, collection2)); + } + + [TestMethod] + public void TCollection_Map_Equals_Objects_Test() + { + var collection1 = new Dictionary + { + [1] = new ExampleClass { X = 1 }, + [-1] = new ExampleClass { X = 2 } + }; + var collection2 = new Dictionary + { + [1] = new ExampleClass { X = 1 }, + [-1] = new ExampleClass { X = 2 } + }; + + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsTrue(collection1.SequenceEqual(collection2)); + } + + [TestMethod] + public void TCollection_Map_Map_Equals_Objects_Test() + { + var collection1 = new Dictionary> + { + [0] = new Dictionary + { + [1] = new ExampleClass { X = 1 }, + [-1] = new ExampleClass { X = 2 } + } + }; + var collection2 = new Dictionary> + { + [0] = new Dictionary + { + [1] = new ExampleClass { X = 1 }, + [-1] = new ExampleClass { X = 2 } + } + }; + + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsFalse(collection1.SequenceEqual(collection2)); // SequenceEqual() calls Equals() of the inner list instead of SequenceEqual() + } + + [TestMethod] + public void TCollection_Map_Equals_OneAndTheSameObject_Test() + { + var collection1 = new Dictionary + { + [1] = new ExampleClass { X = 1 }, + [-1] = new ExampleClass { X = 2 } + }; + var collection2 = collection1; + Assert.IsTrue(TCollections.Equals(collection1, collection2)); + Assert.IsTrue(collection1.SequenceEqual(collection2)); + } + + private class ExampleClass { public int X { get; set; } + + // all Thrift-generated classes override Equals(), we do just the same + public override bool Equals(object that) + { + if (!(that is ExampleClass other)) return false; + if (ReferenceEquals(this, other)) return true; + + return this.X == other.X; + } + + // overriding Equals() requires GetHashCode() as well + public override int GetHashCode() + { + int hashcode = 157; + unchecked + { + hashcode = (hashcode * 397) + X.GetHashCode(); + } + return hashcode; + } } } } + diff --git a/lib/netstd/Tests/Thrift.Tests/DataModel/DeepCopy.cs b/lib/netstd/Tests/Thrift.Tests/DataModel/DeepCopy.cs new file mode 100644 index 00000000000..f717b4ddaa0 --- /dev/null +++ b/lib/netstd/Tests/Thrift.Tests/DataModel/DeepCopy.cs @@ -0,0 +1,603 @@ +// Licensed to the Apache Software Foundation(ASF) under one +// or more contributor license agreements.See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership.The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using OptReqDefTest; +using Thrift.Collections; + +namespace Thrift.Tests.DataModel +{ + // ReSharper disable once InconsistentNaming + [TestClass] + public class DeepCopyTests + { + [TestMethod] + public void Test_Complex_DeepCopy() + { + var first = InitializeInstance(new RaceDetails()); + VerifyIdenticalContent(first, InitializeInstance(new RaceDetails())); + + var second = first.DeepCopy(); + VerifyIdenticalContent(first, second); + ModifyInstance(second,0); + VerifyDifferentContent(first, second); + VerifyIdenticalContent(first, InitializeInstance(new RaceDetails())); + + var third = second.DeepCopy(); + VerifyIdenticalContent(second, third); + ModifyInstance(third,0); + VerifyDifferentContent(second, third); + VerifyIdenticalContent(first, InitializeInstance(new RaceDetails())); + } + + private RaceDetails MakeNestedRaceDetails(int nesting) + { + if (++nesting > 1) + return null; + + var instance = new RaceDetails(); + InitializeInstance(instance,nesting); + return instance; + } + + private jack MakeNestedUnion(int nesting) + { + if (++nesting > 1) + return null; + + var details = new RaceDetails(); + InitializeInstance(details,nesting); + return new jack.nested_struct(details); + } + + + private RaceDetails InitializeInstance(RaceDetails instance, int nesting = 0) + { + // at init, we intentionally leave all non-required fields unset + Assert.IsFalse(instance.__isset.opt_one); + Assert.IsFalse(instance.__isset.opt_two); + Assert.IsFalse(instance.__isset.opt_three); + Assert.IsFalse(instance.__isset.opt_four); + Assert.IsFalse(instance.__isset.opt_five); + Assert.IsFalse(instance.__isset.opt_six); + Assert.IsFalse(instance.__isset.opt_seven); + Assert.IsFalse(instance.__isset.opt_eight); + + // set all required to null/default + instance.Req_one = default; + instance.Req_two = default; + instance.Req_three = default; + instance.Req_four = default; + instance.Req_five = default; + instance.Req_six = default; + instance.Req_seven = default;; + instance.Req_eight = default; + + // leave non-required fields unset again + Assert.IsFalse(instance.__isset.def_one); + Assert.IsFalse(instance.__isset.def_two); + Assert.IsFalse(instance.__isset.def_three); + Assert.IsFalse(instance.__isset.def_four); + Assert.IsFalse(instance.__isset.def_five); + Assert.IsFalse(instance.__isset.def_six); + Assert.IsFalse(instance.__isset.def_seven); + Assert.IsFalse(instance.__isset.def_eight); + + // these should have IDL defaults set + + Assert.IsTrue(instance.__isset.opt_one_with_value); + Assert.IsTrue(instance.__isset.opt_two_with_value); + Assert.IsTrue(instance.__isset.opt_three_with_value); + Assert.IsTrue(instance.__isset.opt_four_with_value); + Assert.IsTrue(instance.__isset.opt_five_with_value); + Assert.IsTrue(instance.__isset.opt_six_with_value); + Assert.IsTrue(instance.__isset.opt_seven_with_value); + Assert.IsTrue(instance.__isset.opt_eight_with_value); + + Assert.AreEqual(instance.Req_one_with_value, (Distance)1); + Assert.AreEqual(instance.Req_two_with_value, 2.22); + Assert.AreEqual(instance.Req_three_with_value, 3); + Assert.AreEqual(instance.Req_four_with_value, "four"); + Assert.AreEqual("five", Encoding.UTF8.GetString(instance.Req_five_with_value)); + + Assert.IsTrue(instance.Req_six_with_value.Count == 1); + Assert.AreEqual(instance.Req_six_with_value[0], 6 ); + + Assert.IsTrue(instance.Req_seven_with_value.Count == 1); + Assert.IsTrue(instance.Req_seven_with_value.Contains(7)); + + Assert.IsTrue(instance.Req_eight_with_value.Count == 1); + Assert.IsTrue(instance.Req_eight_with_value[8] == 8); + + Assert.IsTrue(instance.__isset.def_one_with_value); + Assert.IsTrue(instance.__isset.def_two_with_value); + Assert.IsTrue(instance.__isset.def_three_with_value); + Assert.IsTrue(instance.__isset.def_four_with_value); + Assert.IsTrue(instance.__isset.def_five_with_value); + Assert.IsTrue(instance.__isset.def_six_with_value); + Assert.IsTrue(instance.__isset.def_seven_with_value); + Assert.IsTrue(instance.__isset.def_eight_with_value); + + instance.Last_of_the_mohicans = true; + + if (nesting < 2) + { + instance.Far_list = new List() { Distance.foo, Distance.bar, Distance.baz }; + instance.Far_set = new THashSet() { Distance.foo, Distance.bar, Distance.baz }; + instance.Far_map = new Dictionary() { [Distance.foo] = Distance.foo, [Distance.bar] = Distance.bar, [Distance.baz] = Distance.baz }; + + instance.Far_set_list = new THashSet>() { new List() { Distance.foo } }; + instance.Far_list_map_set = new List>>() { new Dictionary>() { [1] = new THashSet() { Distance.baz } } }; + instance.Far_map_dist_to_rds = new Dictionary>() { [Distance.bar] = new List() { MakeNestedRaceDetails(nesting) } }; + + instance.Req_nested = MakeNestedRaceDetails(nesting); + Assert.IsFalse(instance.__isset.opt_nested); + Assert.IsFalse(instance.__isset.def_nested); + + instance.Req_union = MakeNestedUnion(nesting); + Assert.IsFalse(instance.__isset.opt_union); + Assert.IsFalse(instance.__isset.def_union); + } + + instance.Triplesix = (Distance)666; + + return instance; + } + + private void ModifyInstance(RaceDetails instance, int level) + { + if ((instance == null) || (++level > 4)) + return; + + instance.Opt_one = ModifyValue(instance.Opt_one); + instance.Opt_two = ModifyValue(instance.Opt_two); + instance.Opt_three = ModifyValue(instance.Opt_three); + instance.Opt_four = ModifyValue(instance.Opt_four); + instance.Opt_five = ModifyValue(instance.Opt_five); + instance.Opt_six = ModifyValue(instance.Opt_six); + instance.Opt_seven = ModifyValue(instance.Opt_seven); + instance.Opt_eight = ModifyValue(instance.Opt_eight); + + instance.Req_one = ModifyValue(instance.Req_one); + instance.Req_two = ModifyValue(instance.Req_two); + instance.Req_three = ModifyValue(instance.Req_three); + instance.Req_four = ModifyValue(instance.Req_four); + instance.Req_five = ModifyValue(instance.Req_five); + instance.Req_six = ModifyValue(instance.Req_six); + instance.Req_seven = ModifyValue(instance.Req_seven); + instance.Req_eight = ModifyValue(instance.Req_eight); + + instance.Def_one = ModifyValue(instance.Def_one); + instance.Def_two = ModifyValue(instance.Def_two); + instance.Def_three = ModifyValue(instance.Def_three); + instance.Def_four = ModifyValue(instance.Def_four); + instance.Def_five = ModifyValue(instance.Def_five); + instance.Def_six = ModifyValue(instance.Def_six); + instance.Def_seven = ModifyValue(instance.Def_seven); + instance.Def_eight = ModifyValue(instance.Def_eight); + + instance.Opt_one_with_value = ModifyValue(instance.Opt_one_with_value); + instance.Opt_two_with_value = ModifyValue(instance.Opt_two_with_value); + instance.Opt_three_with_value = ModifyValue(instance.Opt_three_with_value); + instance.Opt_four_with_value = ModifyValue(instance.Opt_four_with_value); + instance.Opt_five_with_value = ModifyValue(instance.Opt_five_with_value); + instance.Opt_six_with_value = ModifyValue(instance.Opt_six_with_value); + instance.Opt_seven_with_value = ModifyValue(instance.Opt_seven_with_value); + instance.Opt_eight_with_value = ModifyValue(instance.Opt_eight_with_value); + + instance.Req_one_with_value = ModifyValue(instance.Req_one_with_value); + instance.Req_two_with_value = ModifyValue(instance.Req_two_with_value); + instance.Req_three_with_value = ModifyValue(instance.Req_three_with_value); + instance.Req_four_with_value = ModifyValue(instance.Req_four_with_value); + instance.Req_five_with_value = ModifyValue(instance.Req_five_with_value); + instance.Req_six_with_value = ModifyValue(instance.Req_six_with_value); + instance.Req_seven_with_value = ModifyValue(instance.Req_seven_with_value); + instance.Req_eight_with_value = ModifyValue(instance.Req_eight_with_value); + + instance.Def_one_with_value = ModifyValue(instance.Def_one_with_value); + instance.Def_two_with_value = ModifyValue(instance.Def_two_with_value); + instance.Def_three_with_value = ModifyValue(instance.Def_three_with_value); + instance.Def_four_with_value = ModifyValue(instance.Def_four_with_value); + instance.Def_five_with_value = ModifyValue(instance.Def_five_with_value); + instance.Def_six_with_value = ModifyValue(instance.Def_six_with_value); + instance.Def_seven_with_value = ModifyValue(instance.Def_seven_with_value); + instance.Def_eight_with_value = ModifyValue(instance.Def_eight_with_value); + + instance.Last_of_the_mohicans = ModifyValue(instance.Last_of_the_mohicans); + + instance.Far_list = ModifyValue(instance.Far_list); + instance.Far_set = ModifyValue(instance.Far_set); + instance.Far_map = ModifyValue(instance.Far_map); + + instance.Far_set_list = ModifyValue(instance.Far_set_list); + instance.Far_list_map_set = ModifyValue(instance.Far_list_map_set); + instance.Far_map_dist_to_rds = ModifyValue(instance.Far_map_dist_to_rds, level); + + instance.Req_nested = ModifyValue(instance.Req_nested, level); + instance.Opt_nested = ModifyValue(instance.Opt_nested, level); + instance.Def_nested = ModifyValue(instance.Def_nested, level); + + instance.Req_union = ModifyValue(instance.Req_union, level); + instance.Opt_union = ModifyValue(instance.Opt_union, level); + instance.Def_union = ModifyValue(instance.Def_union, level); + + instance.Triplesix = ModifyValue(instance.Triplesix); + } + + private jack ModifyValue(jack value, int level) + { + if (++level > 4) + return value; + + if (value == null) + value = MakeNestedUnion(0); + Debug.Assert(value.As_nested_struct != null); + ModifyInstance(value.As_nested_struct, level); + return value; + } + + private RaceDetails ModifyValue(RaceDetails value, int level) + { + if (++level > 4) + return value; + + if (value == null) + value = new RaceDetails(); + ModifyInstance(value,level); + return value; + } + + private Dictionary> ModifyValue(Dictionary> value, int level) + { + if (value == null) + value = new Dictionary>(); + + if (++level > 4) + return value; + + var details = new RaceDetails(); + InitializeInstance(details); + value[Distance.foo] = new List() { details }; + + if (value.TryGetValue(Distance.bar, out var list) && (list.Count > 0)) + { + ModifyInstance(list[0], level); + list.Add(null); + } + + value[Distance.baz] = null; + + return value; + } + + private List>> ModifyValue(List>> value) + { + if (value == null) + value = new List>>(); + + if (value.Count == 0) + value.Add(new Dictionary>()); + else + value.Add(null); + + sbyte key = (sbyte)(value[0].Count + 10); + if (value[0].Count == 0) + value[0].Add(key, new THashSet()); + else + value[0].Add(key, null); + + foreach (var entry in value) + { + if (entry != null) + { + foreach (var pair in entry) + { + if (pair.Value != null) + { + if (pair.Value.Contains(Distance.baz)) + pair.Value.Remove(Distance.baz); + else + pair.Value.Add(Distance.baz); + } + } + } + } + + return value; + } + + private THashSet> ModifyValue(THashSet> value) + { + if (value == null) + value = new THashSet>(); + + if (value.Count == 0) + value.Add(new List()); + else + value.Add(null); + + foreach (var entry in value) + if( entry != null) + entry.Add(Distance.baz); + + return value; + } + + private Dictionary ModifyValue(Dictionary value) + { + if (value == null) + value = new Dictionary(); + value[Distance.foo] = value.ContainsKey(Distance.foo) ? ++value[Distance.foo] : Distance.foo; + value[Distance.bar] = value.ContainsKey(Distance.bar) ? ++value[Distance.bar] : Distance.bar; + value[Distance.baz] = value.ContainsKey(Distance.baz) ? ++value[Distance.baz] : Distance.baz; + return value; + } + + private THashSet ModifyValue(THashSet value) + { + if (value == null) + value = new THashSet(); + + if (value.Contains(Distance.foo)) + value.Remove(Distance.foo); + else + value.Add(Distance.foo); + + if (value.Contains(Distance.bar)) + value.Remove(Distance.bar); + else + value.Add(Distance.bar); + + if (value.Contains(Distance.baz)) + value.Remove(Distance.baz); + else + value.Add(Distance.baz); + + return value; + } + + private List ModifyValue(List value) + { + if (value == null) + value = new List(); + value.Add(Distance.foo); + value.Add(Distance.bar); + value.Add(Distance.baz); + return value; + } + + private bool ModifyValue(bool value) + { + return !value; + } + + private Dictionary ModifyValue(Dictionary value) + { + if (value == null) + value = new Dictionary(); + value.Add((sbyte)(value.Count + 10), (short)value.Count); + return value; + } + + private THashSet ModifyValue(THashSet value) + { + if (value == null) + value = new THashSet(); + value.Add(value.Count+100); + return value; + } + + private List ModifyValue(List value) + { + if (value == null) + value = new List(); + value.Add(value.Count); + return value; + } + + private byte[] ModifyValue(byte[] value) + { + if (value == null) + value = new byte[1] { 0 }; + if (value.Length > 0) + value[0] = (value[0] < 0xFF) ? ++value[0] : (byte)0; + return value; + } + + private string ModifyValue(string value) + { + return value + "1"; + } + + private double ModifyValue(double value) + { + return value + 1.1; + } + + private short ModifyValue(short value) + { + return ++value; + } + + private Distance ModifyValue(Distance value) + { + return ++value; + } + + private void VerifyDifferentContent(RaceDetails first, RaceDetails second) + { + Assert.AreNotEqual(first, second); + + Assert.AreNotEqual(first.Opt_two, second.Opt_two); + Assert.AreNotEqual(first.Opt_three, second.Opt_three); + Assert.AreNotEqual(first.Opt_four, second.Opt_four); + Assert.IsFalse(TCollections.Equals(first.Opt_five, second.Opt_five)); + Assert.IsFalse(TCollections.Equals(first.Opt_six, second.Opt_six)); + Assert.IsFalse(TCollections.Equals(first.Opt_seven, second.Opt_seven)); + Assert.IsFalse(TCollections.Equals(first.Opt_eight, second.Opt_eight)); + + Assert.AreNotEqual(first.Req_one, second.Req_one); + Assert.AreNotEqual(first.Req_two, second.Req_two); + Assert.AreNotEqual(first.Req_three, second.Req_three); + Assert.AreNotEqual(first.Req_four, second.Req_four); + Assert.IsFalse(TCollections.Equals(first.Req_five, second.Req_five)); + Assert.IsFalse(TCollections.Equals(first.Req_six, second.Req_six)); + Assert.IsFalse(TCollections.Equals(first.Req_seven, second.Req_seven)); + Assert.IsFalse(TCollections.Equals(first.Req_eight, second.Req_eight)); + + Assert.AreNotEqual(first.Def_one, second.Def_one); + Assert.AreNotEqual(first.Def_two, second.Def_two); + Assert.AreNotEqual(first.Def_three, second.Def_three); + Assert.AreNotEqual(first.Def_four, second.Def_four); + Assert.IsFalse(TCollections.Equals(first.Def_five, second.Def_five)); + Assert.IsFalse(TCollections.Equals(first.Def_six, second.Def_six)); + Assert.IsFalse(TCollections.Equals(first.Def_seven, second.Def_seven)); + Assert.IsFalse(TCollections.Equals(first.Def_eight, second.Def_eight)); + + Assert.AreNotEqual(first.Opt_one_with_value, second.Opt_one_with_value); + Assert.AreNotEqual(first.Opt_two_with_value, second.Opt_two_with_value); + Assert.AreNotEqual(first.Opt_three_with_value, second.Opt_three_with_value); + Assert.AreNotEqual(first.Opt_four_with_value, second.Opt_four_with_value); + Assert.IsFalse(TCollections.Equals(first.Opt_five_with_value, second.Opt_five_with_value)); + Assert.IsFalse(TCollections.Equals(first.Opt_six_with_value, second.Opt_six_with_value)); + Assert.IsFalse(TCollections.Equals(first.Opt_seven_with_value, second.Opt_seven_with_value)); + Assert.IsFalse(TCollections.Equals(first.Opt_eight_with_value, second.Opt_eight_with_value)); + + Assert.AreNotEqual(first.Req_one_with_value, second.Req_one_with_value); + Assert.AreNotEqual(first.Req_two_with_value, second.Req_two_with_value); + Assert.AreNotEqual(first.Req_three_with_value, second.Req_three_with_value); + Assert.AreNotEqual(first.Req_four_with_value, second.Req_four_with_value); + Assert.IsFalse(TCollections.Equals(first.Req_five_with_value, second.Req_five_with_value)); + Assert.IsFalse(TCollections.Equals(first.Req_six_with_value, second.Req_six_with_value)); + Assert.IsFalse(TCollections.Equals(first.Req_seven_with_value, second.Req_seven_with_value)); + Assert.IsFalse(TCollections.Equals(first.Req_eight_with_value, second.Req_eight_with_value)); + + Assert.AreNotEqual(first.Def_one_with_value, second.Def_one_with_value); + Assert.AreNotEqual(first.Def_two_with_value, second.Def_two_with_value); + Assert.AreNotEqual(first.Def_three_with_value, second.Def_three_with_value); + Assert.AreNotEqual(first.Def_four_with_value, second.Def_four_with_value); + Assert.IsFalse(TCollections.Equals(first.Def_five_with_value, second.Def_five_with_value)); + Assert.IsFalse(TCollections.Equals(first.Def_six_with_value, second.Def_six_with_value)); + Assert.IsFalse(TCollections.Equals(first.Def_seven_with_value, second.Def_seven_with_value)); + Assert.IsFalse(TCollections.Equals(first.Def_eight_with_value, second.Def_eight_with_value)); + + Assert.AreNotEqual(first.Last_of_the_mohicans, second.Last_of_the_mohicans); + + Assert.IsFalse(TCollections.Equals(first.Far_list, second.Far_list)); + Assert.IsFalse(TCollections.Equals(first.Far_set, second.Far_set)); + Assert.IsFalse(TCollections.Equals(first.Far_map, second.Far_map)); + + Assert.IsFalse(TCollections.Equals(first.Far_set_list, second.Far_set_list)); + Assert.IsFalse(TCollections.Equals(first.Far_list_map_set, second.Far_list_map_set)); + Assert.IsFalse(TCollections.Equals(first.Far_map_dist_to_rds, second.Far_map_dist_to_rds)); + + Assert.AreNotEqual(first.Req_nested, second.Req_nested); + Assert.AreNotEqual(first.Opt_nested, second.Opt_nested); + Assert.AreNotEqual(first.Def_nested, second.Def_nested); + + Assert.AreNotEqual(first.Req_union, second.Req_union); + Assert.AreNotEqual(first.Opt_union, second.Opt_union); + Assert.AreNotEqual(first.Def_union, second.Def_union); + + Assert.AreNotEqual(first.Triplesix, second.Triplesix); + } + + private void VerifyIdenticalContent(RaceDetails first, RaceDetails second) + { + Assert.AreEqual(first, second); + + Assert.AreEqual(first.Opt_two, second.Opt_two); + Assert.AreEqual(first.Opt_three, second.Opt_three); + Assert.AreEqual(first.Opt_four, second.Opt_four); + Assert.IsTrue(TCollections.Equals(first.Opt_five, second.Opt_five)); + Assert.IsTrue(TCollections.Equals(first.Opt_six, second.Opt_six)); + Assert.IsTrue(TCollections.Equals(first.Opt_seven, second.Opt_seven)); + Assert.IsTrue(TCollections.Equals(first.Opt_eight, second.Opt_eight)); + + Assert.AreEqual(first.Req_one, second.Req_one); + Assert.AreEqual(first.Req_two, second.Req_two); + Assert.AreEqual(first.Req_three, second.Req_three); + Assert.AreEqual(first.Req_four, second.Req_four); + Assert.IsTrue(TCollections.Equals(first.Req_five, second.Req_five)); + Assert.IsTrue(TCollections.Equals(first.Req_six, second.Req_six)); + Assert.IsTrue(TCollections.Equals(first.Req_seven, second.Req_seven)); + Assert.IsTrue(TCollections.Equals(first.Req_eight, second.Req_eight)); + + Assert.AreEqual(first.Def_one, second.Def_one); + Assert.AreEqual(first.Def_two, second.Def_two); + Assert.AreEqual(first.Def_three, second.Def_three); + Assert.AreEqual(first.Def_four, second.Def_four); + Assert.IsTrue(TCollections.Equals(first.Def_five, second.Def_five)); + Assert.IsTrue(TCollections.Equals(first.Def_six, second.Def_six)); + Assert.IsTrue(TCollections.Equals(first.Def_seven, second.Def_seven)); + Assert.IsTrue(TCollections.Equals(first.Def_eight, second.Def_eight)); + + Assert.AreEqual(first.Opt_one_with_value, second.Opt_one_with_value); + Assert.AreEqual(first.Opt_two_with_value, second.Opt_two_with_value); + Assert.AreEqual(first.Opt_three_with_value, second.Opt_three_with_value); + Assert.AreEqual(first.Opt_four_with_value, second.Opt_four_with_value); + Assert.IsTrue(TCollections.Equals(first.Opt_five_with_value, second.Opt_five_with_value)); + Assert.IsTrue(TCollections.Equals(first.Opt_six_with_value, second.Opt_six_with_value)); + Assert.IsTrue(TCollections.Equals(first.Opt_seven_with_value, second.Opt_seven_with_value)); + Assert.IsTrue(TCollections.Equals(first.Opt_eight_with_value, second.Opt_eight_with_value)); + + Assert.AreEqual(first.Req_one_with_value, second.Req_one_with_value); + Assert.AreEqual(first.Req_two_with_value, second.Req_two_with_value); + Assert.AreEqual(first.Req_three_with_value, second.Req_three_with_value); + Assert.AreEqual(first.Req_four_with_value, second.Req_four_with_value); + Assert.IsTrue(TCollections.Equals(first.Req_five_with_value, second.Req_five_with_value)); + Assert.IsTrue(TCollections.Equals(first.Req_six_with_value, second.Req_six_with_value)); + Assert.IsTrue(TCollections.Equals(first.Req_seven_with_value, second.Req_seven_with_value)); + Assert.IsTrue(TCollections.Equals(first.Req_eight_with_value, second.Req_eight_with_value)); + + Assert.AreEqual(first.Def_one_with_value, second.Def_one_with_value); + Assert.AreEqual(first.Def_two_with_value, second.Def_two_with_value); + Assert.AreEqual(first.Def_three_with_value, second.Def_three_with_value); + Assert.AreEqual(first.Def_four_with_value, second.Def_four_with_value); + Assert.IsTrue(TCollections.Equals(first.Def_five_with_value, second.Def_five_with_value)); + Assert.IsTrue(TCollections.Equals(first.Def_six_with_value, second.Def_six_with_value)); + Assert.IsTrue(TCollections.Equals(first.Def_seven_with_value, second.Def_seven_with_value)); + Assert.IsTrue(TCollections.Equals(first.Def_eight_with_value, second.Def_eight_with_value)); + + Assert.AreEqual(first.Last_of_the_mohicans, second.Last_of_the_mohicans); + + Assert.IsTrue(TCollections.Equals(first.Far_list, second.Far_list)); + Assert.IsTrue(TCollections.Equals(first.Far_set, second.Far_set)); + Assert.IsTrue(TCollections.Equals(first.Far_map, second.Far_map)); + + Assert.IsTrue(TCollections.Equals(first.Far_set_list, second.Far_set_list)); + Assert.IsTrue(TCollections.Equals(first.Far_list_map_set, second.Far_list_map_set)); + Assert.IsTrue(TCollections.Equals(first.Far_map_dist_to_rds, second.Far_map_dist_to_rds)); + + Assert.AreEqual(first.Req_nested, second.Req_nested); + Assert.AreEqual(first.Opt_nested, second.Opt_nested); + Assert.AreEqual(first.Def_nested, second.Def_nested); + + Assert.AreEqual(first.Req_union, second.Req_union); + Assert.AreEqual(first.Opt_union, second.Opt_union); + Assert.AreEqual(first.Def_union, second.Def_union); + + Assert.AreEqual(first.Triplesix, second.Triplesix); + } + + } +} diff --git a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj index 20fdfe492f9..4b39e7d4b3e 100644 --- a/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj +++ b/lib/netstd/Tests/Thrift.Tests/Thrift.Tests.csproj @@ -1,4 +1,4 @@ - + -This documents describes the wire encoding for RPC using the older Thrift *binary protocol*. +This document describes the wire encoding for RPC using the older Thrift *binary protocol*. The information here is _mostly_ based on the Java implementation in the Apache thrift library (version 0.9.1 and -0.9.3). Other implementation however, should behave the same. +0.9.3). Other implementation, however, should behave the same. For background on Thrift see the [Thrift whitepaper (pdf)](https://thrift.apache.org/static/files/thrift-20070401.pdf). @@ -150,7 +150,7 @@ determine how to decode the field value. Note that the field name is not encoded so field renames in the IDL do not affect forward and backward compatibility. The default Java implementation (Apache Thrift 0.9.1) has undefined behavior when it tries to decode a field that has -another field-type then what is expected. Theoretically this could be detected at the cost of some additional checking. +another field-type than what is expected. Theoretically, this could be detected at the cost of some additional checking. Other implementation may perform this check and then either ignore the field, or return a protocol exception. A *Union* is encoded exactly the same as a struct with the additional restriction that at most 1 field may be encoded. @@ -213,7 +213,7 @@ Where: The element-type values are the same as field-types. The full list is included in the struct section above. -The maximum list/set size is configurable. By default there is no limit (meaning the limit is the maximum int32 value: +The maximum list/set size is configurable. By default, there is no limit (meaning the limit is the maximum int32 value: 2147483647). ## Map diff --git a/doc/specs/thrift-protocol-spec.md b/doc/specs/thrift-protocol-spec.md index 0c1a61cb26b..080487e1bd8 100644 --- a/doc/specs/thrift-protocol-spec.md +++ b/doc/specs/thrift-protocol-spec.md @@ -33,7 +33,7 @@ implementation, but this document specifies the minimum required structure. There are some "dumb" terminals like STRING and INT that take the place of an actual encoding specification. -They key point to notice is that ALL messages are just one wrapped +The key point to notice is that ALL messages are just one wrapped ``. Depending upon the message type, the `` can be interpreted as the argument list to a function, the return value of a function, or an exception. diff --git a/doc/specs/thrift-rpc.md b/doc/specs/thrift-rpc.md index d45c06f3041..fbff3b6a1db 100644 --- a/doc/specs/thrift-rpc.md +++ b/doc/specs/thrift-rpc.md @@ -24,15 +24,15 @@ under the License. -------------------------------------------------------------------- --> -This document describes the high level message exchange between the Thrift RPC client and server. +This document describes the high-level message exchange between the Thrift RPC client and server. See [thrift-binary-protocol.md] and [thrift-compact-protocol.md] for a description of how the exchanges are encoded on the wire. -In addition, this document compares the binary protocol with the compact protocol. Finally it describes the framed vs. +In addition, this document compares the binary protocol with the compact protocol. Finally, it describes the framed vs. unframed transport. The information here is _mostly_ based on the Java implementation in the Apache thrift library (version 0.9.1 and -0.9.3). Other implementation however, should behave the same. +0.9.3). Other implementation, however, should behave the same. For background on Thrift see the [Thrift whitepaper (pdf)](https://thrift.apache.org/static/files/thrift-20070401.pdf). @@ -93,14 +93,14 @@ in the Thrift IDL file, or some other part of the Thrift stack throws an excepti not encode or decode a message or struct. In the Java implementation (0.9.3) there is different behavior for the synchronous and asynchronous server. In the async -server all exceptions are send as a `TApplicationException` (see 'Response struct' below). In the synchronous Java +server all exceptions are sent as a `TApplicationException` (see 'Response struct' below). In the synchronous Java implementation only (undeclared) exceptions that extend `TException` are send as a `TApplicationException`. Unchecked exceptions lead to an immediate close of the connection. Type `Oneway` is only used starting from Apache Thrift 0.9.3. Earlier versions do _not_ send TMessages of type `Oneway`, even for service methods defined with the `oneway` modifier. -When client sends a request with type `Oneway`, the server must _not_ send a response (steps 3 and 4 are skipped). Note +When the client sends a request with type `Oneway`, the server must _not_ send a response (steps 3 and 4 are skipped). Note that the Thrift IDL enforces a return type of `void` and does not allow exceptions for oneway services. ## Request struct @@ -151,7 +151,7 @@ always slightly faster. ## Compatibility A server could automatically determine whether a client talks the binary protocol or the compact protocol by -investigating the first byte. If the value is `1000 0001` or `0000 0000` (assuming a name shorter then ±16 MB) it is the +investigating the first byte. If the value is `1000 0001` or `0000 0000` (assuming a name shorter than ±16 MB) it is the binary protocol. When the value is `1000 0010` it is talking the compact protocol. ## Framed vs. unframed transport From 7ddbcc07ec98349da59bb023d0fed8db37097c18 Mon Sep 17 00:00:00 2001 From: Allen George Date: Sun, 8 Nov 2020 09:51:19 -0500 Subject: [PATCH 707/756] THRIFT-5306: Rust code and generated code no longer has clippy warnings (Rust 1.40) Client: rs NOTE: Also properly update the min/max supported Rust versions --- .gitignore | 1 + LANGUAGES.md | 2 +- .../cpp/src/thrift/generate/t_rs_generator.cc | 25 ++++---- lib/rs/Cargo.toml | 2 +- lib/rs/README.md | 2 +- lib/rs/src/errors.rs | 20 +++---- lib/rs/src/lib.rs | 8 --- lib/rs/src/protocol/binary.rs | 22 +++---- lib/rs/src/protocol/compact.rs | 52 ++++++++++------- lib/rs/src/protocol/mod.rs | 20 +++---- lib/rs/src/protocol/multiplexed.rs | 2 +- lib/rs/src/protocol/stored.rs | 2 +- lib/rs/src/server/multiplexed.rs | 8 ++- lib/rs/src/server/threaded.rs | 2 + lib/rs/src/transport/buffered.rs | 10 ++-- lib/rs/src/transport/mem.rs | 4 +- lib/rs/test/Cargo.toml | 4 +- lib/rs/test/src/bin/kitchen_sink_client.rs | 8 +-- lib/rs/test/src/bin/kitchen_sink_server.rs | 6 +- lib/rs/test/src/lib.rs | 2 - test/rs/Cargo.toml | 4 +- test/rs/src/bin/test_client.rs | 58 +++++++++---------- test/rs/src/bin/test_server.rs | 19 +++--- test/rs/src/lib.rs | 6 +- tutorial/rs/Cargo.toml | 2 - tutorial/rs/README.md | 25 ++------ tutorial/rs/src/bin/tutorial_client.rs | 3 +- tutorial/rs/src/bin/tutorial_server.rs | 7 +-- 28 files changed, 146 insertions(+), 180 deletions(-) diff --git a/.gitignore b/.gitignore index 58e2582a7ce..76d9e502b96 100644 --- a/.gitignore +++ b/.gitignore @@ -288,6 +288,7 @@ project.lock.json /lib/rs/test/src/midlayer.rs /lib/rs/test/src/recursive.rs /lib/rs/test/src/ultimate.rs +/lib/rs/test/src/identifiers.rs /lib/rs/*.iml /lib/rs/**/*.iml /lib/swift/.build diff --git a/LANGUAGES.md b/LANGUAGES.md index 3173ec3f5b0..4ea86f78d68 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -314,7 +314,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Rust 0.11.0 Yes -1.35.01.35.0 +1.40.01.xx.x YesYes Yes YesYesYes diff --git a/compiler/cpp/src/thrift/generate/t_rs_generator.cc b/compiler/cpp/src/thrift/generate/t_rs_generator.cc index 506e0901fef..f55b7e0db6b 100644 --- a/compiler/cpp/src/thrift/generate/t_rs_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_rs_generator.cc @@ -554,7 +554,6 @@ void t_rs_generator::render_attributes_and_includes() { f_gen_ << endl; // add standard includes - f_gen_ << "use thrift::OrderedFloat;" << endl; f_gen_ << "use std::cell::RefCell;" << endl; f_gen_ << "use std::collections::{BTreeMap, BTreeSet};" << endl; f_gen_ << "use std::convert::{From, TryFrom};" << endl; @@ -564,6 +563,7 @@ void t_rs_generator::render_attributes_and_includes() { f_gen_ << "use std::fmt::{Display, Formatter};" << endl; f_gen_ << "use std::rc::Rc;" << endl; f_gen_ << endl; + f_gen_ << "use thrift::OrderedFloat;" << endl; f_gen_ << "use thrift::{ApplicationError, ApplicationErrorKind, ProtocolError, ProtocolErrorKind, TThriftClient};" << endl; f_gen_ << "use thrift::protocol::{TFieldIdentifier, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType, TInputProtocol, TOutputProtocol, TSetIdentifier, TStructIdentifier, TType};" << endl; f_gen_ << "use thrift::protocol::field_id;" << endl; @@ -706,7 +706,7 @@ void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bo f_gen_ << tvalue->get_integer(); break; case t_base_type::TYPE_DOUBLE: - f_gen_ << "OrderedFloat::from(" << tvalue->get_double() << " as f64)"; + f_gen_ << "OrderedFloat::from(" << tvalue->get_double() << "_f64)"; break; default: throw "cannot generate const value for " + t_base_type::t_base_name(tbase_type->get_base()); @@ -901,12 +901,16 @@ void t_rs_generator::render_enum_impl(const string& enum_name) { f_gen_ << "impl " << enum_name << " {" << endl; indent_up(); + // taking enum as 'self' here because Thrift enums + // are represented as Rust enums with integer values + // it's cheaper to copy the integer as opposed to + // taking a reference to the enum f_gen_ << indent() - << "pub fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" + << "pub fn write_to_out_protocol(self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" << endl; indent_up(); - f_gen_ << indent() << "o_prot.write_i32(*self as i32)" << endl; + f_gen_ << indent() << "o_prot.write_i32(self as i32)" << endl; indent_down(); f_gen_ << indent() << "}" << endl; @@ -1230,7 +1234,7 @@ void t_rs_generator::render_struct_constructor( << endl; indent_up(); - if (members.size() == 0) { + if (members.empty()) { f_gen_ << indent() << struct_name << " {}" << endl; } else { f_gen_ << indent() << struct_name << " {" << endl; @@ -1244,7 +1248,7 @@ void t_rs_generator::render_struct_constructor( if (is_optional(member_req)) { f_gen_ << indent() << member_name << ": " << member_name << ".into()," << endl; } else { - f_gen_ << indent() << member_name << ": " << member_name << "," << endl; + f_gen_ << indent() << member_name << "," << endl; } } @@ -1504,19 +1508,14 @@ void t_rs_generator::render_struct_field_sync_write( indent_up(); f_gen_ << indent() << "o_prot.write_field_begin(&" << field_ident_string << ")?;" << endl; render_type_sync_write("fld_var", true, field_type); - f_gen_ << indent() << "o_prot.write_field_end()?;" << endl; - f_gen_ << indent() << "()" << endl; // FIXME: remove this extraneous '()' + f_gen_ << indent() << "o_prot.write_field_end()?" << endl; indent_down(); - f_gen_ << indent() << "} else {" << endl; // FIXME: remove else branch - indent_up(); /* FIXME: rethink how I deal with OPT_IN_REQ_OUT if (req == t_field::T_OPT_IN_REQ_OUT) { f_gen_ << indent() << "let field_ident = " << field_ident_string << ";" << endl; f_gen_ << indent() << "o_prot.write_field_begin(&field_ident)?;" << endl; f_gen_ << indent() << "o_prot.write_field_end()?;" << endl; }*/ - f_gen_ << indent() << "()" << endl; - indent_down(); f_gen_ << indent() << "}" << endl; } else { f_gen_ << indent() << "o_prot.write_field_begin(&" << field_ident_string << ")?;" << endl; @@ -2308,7 +2307,7 @@ void t_rs_generator::render_sync_send(t_function* tfunc) { for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); string member_name(rust_field_name(member)); - struct_definition << member_name << ": " << member_name << ", "; + struct_definition << member_name << ", "; } string struct_fields = struct_definition.str(); if (struct_fields.size() > 0) { diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml index 674a4c31713..182cd8d86aa 100644 --- a/lib/rs/Cargo.toml +++ b/lib/rs/Cargo.toml @@ -12,8 +12,8 @@ exclude = ["Makefile*", "test/**", "*.iml"] keywords = ["thrift"] [dependencies] -ordered-float = "1.0" byteorder = "1.3" integer-encoding = ">=1.1.4" # https://issues.apache.org/jira/browse/THRIFT-5131 log = "0.4" +ordered-float = "1.0" threadpool = "1.7" diff --git a/lib/rs/README.md b/lib/rs/README.md index 1b608b261f0..555d219d2ff 100644 --- a/lib/rs/README.md +++ b/lib/rs/README.md @@ -48,7 +48,7 @@ Breaking changes are minimized. When they are made they will be outlined below w ##### Thrift 0.14.0 -* **[THRIFT-5158]** - Rust library and generator now support Rust 2018 only +* **[THRIFT-5158]** - Rust library and generator now support Rust 2018 only. Required rust 1.40.0 or higher The Rust `thrift` library was updated to Rust 2018 via `cargo fix --edition`. All test code in the repo was updated as well. The code generator was also updated diff --git a/lib/rs/src/errors.rs b/lib/rs/src/errors.rs index 2167875d4aa..41a055eca18 100644 --- a/lib/rs/src/errors.rs +++ b/lib/rs/src/errors.rs @@ -236,8 +236,8 @@ impl Error { i.read_struct_end()?; Ok(ApplicationError { - kind: kind, - message: message, + kind, + message, }) } @@ -283,7 +283,7 @@ impl error::Error for Error { } impl Debug for Error { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { Error::Transport(ref e) => Debug::fmt(e, f), Error::Protocol(ref e) => Debug::fmt(e, f), @@ -294,7 +294,7 @@ impl Debug for Error { } impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { Error::Transport(ref e) => Display::fmt(e, f), Error::Protocol(ref e) => Display::fmt(e, f), @@ -362,7 +362,7 @@ impl TransportError { /// Create a new `TransportError`. pub fn new>(kind: TransportErrorKind, message: S) -> TransportError { TransportError { - kind: kind, + kind, message: message.into(), } } @@ -404,7 +404,7 @@ impl TransportError { } impl Display for TransportError { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.description()) } } @@ -490,7 +490,7 @@ impl ProtocolError { /// Create a new `ProtocolError`. pub fn new>(kind: ProtocolErrorKind, message: S) -> ProtocolError { ProtocolError { - kind: kind, + kind, message: message.into(), } } @@ -534,7 +534,7 @@ impl ProtocolError { } impl Display for ProtocolError { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.description()) } } @@ -581,7 +581,7 @@ impl ApplicationError { /// Create a new `ApplicationError`. pub fn new>(kind: ApplicationErrorKind, message: S) -> ApplicationError { ApplicationError { - kind: kind, + kind, message: message.into(), } } @@ -638,7 +638,7 @@ impl ApplicationError { } impl Display for ApplicationError { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!(f, "{}", self.description()) } } diff --git a/lib/rs/src/lib.rs b/lib/rs/src/lib.rs index b762e05770d..f71c3e88a7d 100644 --- a/lib/rs/src/lib.rs +++ b/lib/rs/src/lib.rs @@ -49,14 +49,6 @@ #![doc(test(attr(allow(unused_variables), deny(warnings))))] #![deny(bare_trait_objects)] -extern crate byteorder; -extern crate ordered_float; -extern crate integer_encoding; -extern crate threadpool; - -#[macro_use] -extern crate log; - // NOTE: this macro has to be defined before any modules. See: // https://danielkeep.github.io/quick-intro-to-macros.html#some-more-gotchas diff --git a/lib/rs/src/protocol/binary.rs b/lib/rs/src/protocol/binary.rs index 0ef65e54ba5..22b496c07d3 100644 --- a/lib/rs/src/protocol/binary.rs +++ b/lib/rs/src/protocol/binary.rs @@ -26,7 +26,7 @@ use super::{TOutputProtocol, TOutputProtocolFactory, TSetIdentifier, TStructIden use crate::transport::{TReadTransport, TWriteTransport}; use crate::{ProtocolError, ProtocolErrorKind}; -const BINARY_PROTOCOL_VERSION_1: u32 = 0x80010000; +const BINARY_PROTOCOL_VERSION_1: u32 = 0x8001_0000; /// Read messages encoded in the Thrift simple binary encoding. /// @@ -69,8 +69,8 @@ where /// version number in the protocol header. pub fn new(transport: T, strict: bool) -> TBinaryInputProtocol { TBinaryInputProtocol { - strict: strict, - transport: transport, + strict, + transport, } } } @@ -79,7 +79,7 @@ impl TInputProtocol for TBinaryInputProtocol where T: TReadTransport, { - #[cfg_attr(feature = "cargo-clippy", allow(collapsible_if))] + #[allow(clippy::collapsible_if)] fn read_message_begin(&mut self) -> crate::Result { let mut first_bytes = vec![0; 4]; self.transport.read_exact(&mut first_bytes[..])?; @@ -295,8 +295,8 @@ where /// protocol version number in the protocol header. pub fn new(transport: T, strict: bool) -> TBinaryOutputProtocol { TBinaryOutputProtocol { - strict: strict, - transport: transport, + strict, + transport, } } } @@ -520,7 +520,7 @@ mod tests { let ident = TMessageIdentifier::new("test", TMessageType::Call, 1); assert!(o_prot.write_message_begin(&ident).is_ok()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 16] = [ 0x80, 0x01, @@ -550,7 +550,7 @@ mod tests { let ident = TMessageIdentifier::new("test", TMessageType::Call, 1); assert!(o_prot.write_message_begin(&ident).is_ok()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 13] = [ 0x00, 0x00, @@ -577,7 +577,7 @@ mod tests { let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10); assert!(o_prot.write_message_begin(&ident).is_ok()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 16] = [ 0x80, 0x01, @@ -607,7 +607,7 @@ mod tests { let ident = TMessageIdentifier::new("test", TMessageType::Reply, 10); assert!(o_prot.write_message_begin(&ident).is_ok()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 13] = [ 0x00, 0x00, @@ -892,7 +892,7 @@ mod tests { fn must_round_trip_bytes() { let (mut i_prot, mut o_prot) = test_objects(true); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let bytes: [u8; 25] = [ 0x20, 0xFD, diff --git a/lib/rs/src/protocol/compact.rs b/lib/rs/src/protocol/compact.rs index f33c0202aff..6fa364fa0af 100644 --- a/lib/rs/src/protocol/compact.rs +++ b/lib/rs/src/protocol/compact.rs @@ -76,7 +76,7 @@ where last_read_field_id: 0, read_field_id_stack: Vec::new(), pending_read_bool_value: None, - transport: transport, + transport, } } @@ -193,7 +193,7 @@ where Ok(TFieldIdentifier { name: None, - field_type: field_type, + field_type, id: Some(self.last_read_field_id), }) } @@ -371,7 +371,7 @@ where last_write_field_id: 0, write_field_id_stack: Vec::new(), pending_write_bool_field_identifier: None, - transport: transport, + transport, } } @@ -673,7 +673,7 @@ mod tests { 431 ))); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 8] = [ 0x82, /* protocol ID */ 0x21, /* message type | protocol version */ @@ -695,10 +695,10 @@ mod tests { assert_success!(o_prot.write_message_begin(&TMessageIdentifier::new( "bar", TMessageType::Reply, - 991828 + 991_828 ))); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 9] = [ 0x82, /* protocol ID */ 0x41, /* message type | protocol version */ @@ -743,7 +743,7 @@ mod tests { fn must_round_trip_message_begin() { let (mut i_prot, mut o_prot) = test_objects(); - let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1283948); + let ident = TMessageIdentifier::new("service_call", TMessageType::Call, 1_283_948); assert_success!(o_prot.write_message_begin(&ident)); @@ -787,7 +787,7 @@ mod tests { assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 5] = [ 0x03, /* field type */ 0x00, /* first field id */ @@ -902,7 +902,7 @@ mod tests { assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 4] = [ 0x15, /* field delta (1) | field type */ 0x1A, /* field delta (1) | field type */ @@ -1015,7 +1015,7 @@ mod tests { assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 8] = [ 0x05, /* field type */ 0x00, /* first field id */ @@ -1139,7 +1139,7 @@ mod tests { assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 10] = [ 0x16, /* field delta (1) | field type */ 0x85, /* field delta (8) | field type */ @@ -1156,6 +1156,7 @@ mod tests { assert_eq_written_bytes!(o_prot, expected); } + #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_struct_with_mix_of_long_and_delta_fields() { let (mut i_prot, mut o_prot) = test_objects(); @@ -1304,7 +1305,7 @@ mod tests { assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 7] = [ 0x16, /* field delta (1) | field type */ 0x85, /* field delta (8) | field type */ @@ -1318,6 +1319,7 @@ mod tests { assert_eq_written_bytes!(o_prot, expected); } + #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_nested_structs_0() { // last field of the containing struct is a delta @@ -1477,7 +1479,7 @@ mod tests { assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 7] = [ 0x16, /* field delta (1) | field type */ 0x85, /* field delta (8) | field type */ @@ -1491,6 +1493,7 @@ mod tests { assert_eq_written_bytes!(o_prot, expected); } + #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_nested_structs_1() { // last field of the containing struct is a delta @@ -1650,7 +1653,7 @@ mod tests { assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 7] = [ 0x16, /* field delta (1) | field type */ 0x08, /* field type */ @@ -1664,6 +1667,7 @@ mod tests { assert_eq_written_bytes!(o_prot, expected); } + #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_nested_structs_2() { let (mut i_prot, mut o_prot) = test_objects(); @@ -1820,7 +1824,7 @@ mod tests { assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 8] = [ 0x16, /* field delta (1) | field type */ 0x08, /* field type */ @@ -1835,6 +1839,7 @@ mod tests { assert_eq_written_bytes!(o_prot, expected); } + #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_nested_structs_3() { // last field of the containing struct is a full write @@ -1986,7 +1991,7 @@ mod tests { assert_success!(o_prot.write_field_stop()); assert_success!(o_prot.write_struct_end()); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 7] = [ 0x11, /* field delta (1) | true */ 0x82, /* field delta (8) | false */ @@ -2000,6 +2005,7 @@ mod tests { assert_eq_written_bytes!(o_prot, expected); } + #[allow(clippy::cognitive_complexity)] #[test] fn must_round_trip_bool_field() { let (mut i_prot, mut o_prot) = test_objects(); @@ -2245,7 +2251,7 @@ mod tests { fn must_round_trip_large_sized_set_begin() { let (mut i_prot, mut o_prot) = test_objects(); - let ident = TSetIdentifier::new(TType::Map, 3928429); + let ident = TSetIdentifier::new(TType::Map, 3_928_429); assert_success!(o_prot.write_set_begin(&ident)); @@ -2312,7 +2318,7 @@ mod tests { fn must_round_trip_map_begin() { let (mut i_prot, mut o_prot) = test_objects(); - let ident = TMapIdentifier::new(TType::Map, TType::List, 1928349); + let ident = TMapIdentifier::new(TType::Map, TType::List, 1_928_349); assert_success!(o_prot.write_map_begin(&ident)); @@ -2403,11 +2409,13 @@ mod tests { fn must_read_write_double() { let (mut i_prot, mut o_prot) = test_objects(); - let double = 3.141592653589793238462643; + #[allow(clippy::approx_constant)] + let double = 3.141_592_653_589_793; o_prot.write_double(double).unwrap(); copy_write_buffer_to_read_buffer!(o_prot); - assert_eq!(i_prot.read_double().unwrap(), double); + let read_double = i_prot.read_double().unwrap(); + assert!(read_double - double < std::f64::EPSILON); } #[test] @@ -2415,11 +2423,11 @@ mod tests { let (_, mut o_prot) = test_objects(); let expected = [24, 45, 68, 84, 251, 33, 9, 64]; - let double = 3.141592653589793238462643; + #[allow(clippy::approx_constant)] + let double = 3.141_592_653_589_793; o_prot.write_double(double).unwrap(); assert_eq_written_bytes!(o_prot, expected); - } fn assert_no_write(mut write_fn: F) diff --git a/lib/rs/src/protocol/mod.rs b/lib/rs/src/protocol/mod.rs index b0e9118ce3f..f9c1f724c88 100644 --- a/lib/rs/src/protocol/mod.rs +++ b/lib/rs/src/protocol/mod.rs @@ -610,8 +610,8 @@ impl TMessageIdentifier { ) -> TMessageIdentifier { TMessageIdentifier { name: name.into(), - message_type: message_type, - sequence_number: sequence_number, + message_type, + sequence_number, } } } @@ -660,7 +660,7 @@ impl TFieldIdentifier { { TFieldIdentifier { name: name.into().map(|n| n.into()), - field_type: field_type, + field_type, id: id.into(), } } @@ -680,8 +680,8 @@ impl TListIdentifier { /// `element_type`. pub fn new(element_type: TType, size: i32) -> TListIdentifier { TListIdentifier { - element_type: element_type, - size: size, + element_type, + size, } } } @@ -700,8 +700,8 @@ impl TSetIdentifier { /// `element_type`. pub fn new(element_type: TType, size: i32) -> TSetIdentifier { TSetIdentifier { - element_type: element_type, - size: size, + element_type, + size, } } } @@ -728,7 +728,7 @@ impl TMapIdentifier { TMapIdentifier { key_type: key_type.into(), value_type: value_type.into(), - size: size, + size, } } } @@ -747,7 +747,7 @@ pub enum TMessageType { } impl Display for TMessageType { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { TMessageType::Call => write!(f, "Call"), TMessageType::Reply => write!(f, "Reply"), @@ -822,7 +822,7 @@ pub enum TType { } impl Display for TType { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match *self { TType::Stop => write!(f, "STOP"), TType::Void => write!(f, "void"), diff --git a/lib/rs/src/protocol/multiplexed.rs b/lib/rs/src/protocol/multiplexed.rs index 9c3ba7c204c..83498fbdd0c 100644 --- a/lib/rs/src/protocol/multiplexed.rs +++ b/lib/rs/src/protocol/multiplexed.rs @@ -203,7 +203,7 @@ mod tests { let ident = TMessageIdentifier::new("bar", TMessageType::Call, 2); assert_success!(o_prot.write_message_begin(&ident)); - #[cfg_attr(rustfmt, rustfmt::skip)] + #[rustfmt::skip] let expected: [u8; 19] = [ 0x80, 0x01, /* protocol identifier */ diff --git a/lib/rs/src/protocol/stored.rs b/lib/rs/src/protocol/stored.rs index c5e02fea018..179ae07b00d 100644 --- a/lib/rs/src/protocol/stored.rs +++ b/lib/rs/src/protocol/stored.rs @@ -92,7 +92,7 @@ impl<'a> TStoredInputProtocol<'a> { pub fn new( wrapped: &mut dyn TInputProtocol, message_ident: TMessageIdentifier, - ) -> TStoredInputProtocol { + ) -> TStoredInputProtocol<'_> { TStoredInputProtocol { inner: wrapped, message_ident: message_ident.into(), diff --git a/lib/rs/src/server/multiplexed.rs b/lib/rs/src/server/multiplexed.rs index 3d688fa20c9..4f41f244784 100644 --- a/lib/rs/src/server/multiplexed.rs +++ b/lib/rs/src/server/multiplexed.rs @@ -15,6 +15,8 @@ // specific language governing permissions and limitations // under the License. +use log::debug; + use std::collections::HashMap; use std::convert::Into; use std::fmt; @@ -25,7 +27,7 @@ use crate::protocol::{TInputProtocol, TMessageIdentifier, TOutputProtocol, TStor use super::{handle_process_result, TProcessor}; -const MISSING_SEPARATOR_AND_NO_DEFAULT: &'static str = +const MISSING_SEPARATOR_AND_NO_DEFAULT: &str = "missing service separator and no default processor set"; type ThreadSafeProcessor = Box; @@ -70,7 +72,7 @@ impl TMultiplexedProcessor { /// Returns success if a new entry was inserted. Returns an error if: /// * A processor exists for `service_name` /// * You attempt to register a processor as default, and an existing default exists - #[cfg_attr(feature = "cargo-clippy", allow(map_entry))] + #[allow(clippy::map_entry)] pub fn register>( &mut self, service_name: S, @@ -145,7 +147,7 @@ impl TProcessor for TMultiplexedProcessor { } impl Debug for TMultiplexedProcessor { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let stored = self.stored.lock().unwrap(); write!( f, diff --git a/lib/rs/src/server/threaded.rs b/lib/rs/src/server/threaded.rs index 8373c469c59..64bf8bbe5e1 100644 --- a/lib/rs/src/server/threaded.rs +++ b/lib/rs/src/server/threaded.rs @@ -15,6 +15,8 @@ // specific language governing permissions and limitations // under the License. +use log::warn; + use std::net::{TcpListener, TcpStream, ToSocketAddrs}; use std::sync::Arc; use threadpool::ThreadPool; diff --git a/lib/rs/src/transport/buffered.rs b/lib/rs/src/transport/buffered.rs index 914a19b6f9a..ebdcdc29218 100644 --- a/lib/rs/src/transport/buffered.rs +++ b/lib/rs/src/transport/buffered.rs @@ -200,7 +200,7 @@ where TBufferedWriteTransport { buf: Vec::with_capacity(write_capacity), cap: write_capacity, - channel: channel, + channel, } } } @@ -347,8 +347,8 @@ mod tests { // fill the underlying transport's byte buffer let mut readable_bytes = [0u8; 10]; - for i in 0..10 { - readable_bytes[i] = i as u8; + for (i, b) in readable_bytes.iter_mut().enumerate() { + *b = i as u8; } t.chan.set_readable_bytes(&readable_bytes); @@ -365,8 +365,8 @@ mod tests { assert_eq!(&buf, &[0, 1, 2, 3, 4, 5, 6, 7]); // let's clear out the buffer and try read again - for i in 0..8 { - buf[i] = 0; + for b in &mut buf{ + *b = 0; } let read_result = t.read(&mut buf); diff --git a/lib/rs/src/transport/mem.rs b/lib/rs/src/transport/mem.rs index 68fb2652ef5..fe1c5434699 100644 --- a/lib/rs/src/transport/mem.rs +++ b/lib/rs/src/transport/mem.rs @@ -153,7 +153,9 @@ impl TIoChannel for TBufferChannel { WriteHalf { handle: TBufferChannel { read: self.read.clone(), - write: self.write.clone(), + // NOTE: not cloning here, since this is the last statement + // in this method and `write` can take ownership of `self.write` + write: self.write, }, }, )) diff --git a/lib/rs/test/Cargo.toml b/lib/rs/test/Cargo.toml index decc985d8cd..9341bd56383 100644 --- a/lib/rs/test/Cargo.toml +++ b/lib/rs/test/Cargo.toml @@ -7,9 +7,7 @@ authors = ["Apache Thrift Developers "] publish = false [dependencies] -clap = "<2.28.0" -ordered-float = "1.0" -try_from = "0.3" +clap = "2.33" [dependencies.thrift] path = "../" diff --git a/lib/rs/test/src/bin/kitchen_sink_client.rs b/lib/rs/test/src/bin/kitchen_sink_client.rs index a7779203dfd..74197de7f0b 100644 --- a/lib/rs/test/src/bin/kitchen_sink_client.rs +++ b/lib/rs/test/src/bin/kitchen_sink_client.rs @@ -15,11 +15,7 @@ // specific language governing permissions and limitations // under the License. -#[macro_use] -extern crate clap; - -extern crate kitchen_sink; -extern crate thrift; +use clap::{clap_app, value_t}; use std::convert::Into; @@ -28,6 +24,8 @@ use kitchen_sink::midlayer::{MealServiceSyncClient, TMealServiceSyncClient}; use kitchen_sink::recursive; use kitchen_sink::recursive::{CoRec, CoRec2, RecList, RecTree, TTestServiceSyncClient}; use kitchen_sink::ultimate::{FullMealServiceSyncClient, TFullMealServiceSyncClient}; + +use thrift; use thrift::protocol::{ TBinaryInputProtocol, TBinaryOutputProtocol, TCompactInputProtocol, TCompactOutputProtocol, TInputProtocol, TOutputProtocol, diff --git a/lib/rs/test/src/bin/kitchen_sink_server.rs b/lib/rs/test/src/bin/kitchen_sink_server.rs index c53e887f9b1..6df39e4bc6c 100644 --- a/lib/rs/test/src/bin/kitchen_sink_server.rs +++ b/lib/rs/test/src/bin/kitchen_sink_server.rs @@ -15,11 +15,9 @@ // specific language governing permissions and limitations // under the License. -#[macro_use] -extern crate clap; -extern crate kitchen_sink; -extern crate thrift; +use clap::{clap_app, value_t}; +use thrift; use thrift::protocol::{ TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory, TCompactInputProtocolFactory, TCompactOutputProtocolFactory, TInputProtocolFactory, TOutputProtocolFactory, diff --git a/lib/rs/test/src/lib.rs b/lib/rs/test/src/lib.rs index 9debdca5477..91fd0272848 100644 --- a/lib/rs/test/src/lib.rs +++ b/lib/rs/test/src/lib.rs @@ -15,8 +15,6 @@ // specific language governing permissions and limitations // under the License. -extern crate thrift; - pub mod base_one; pub mod base_two; pub mod midlayer; diff --git a/test/rs/Cargo.toml b/test/rs/Cargo.toml index deffd21789a..8a85d7c7e92 100644 --- a/test/rs/Cargo.toml +++ b/test/rs/Cargo.toml @@ -8,10 +8,8 @@ publish = false [dependencies] clap = "2.33" -env_logger = "0.4.0" +env_logger = "0.8" log = "0.4" -ordered-float = "1.0" -try_from = "0.3" [dependencies.thrift] path = "../../lib/rs" diff --git a/test/rs/src/bin/test_client.rs b/test/rs/src/bin/test_client.rs index 3206deb441d..6cbc238ae41 100644 --- a/test/rs/src/bin/test_client.rs +++ b/test/rs/src/bin/test_client.rs @@ -15,20 +15,15 @@ // specific language governing permissions and limitations // under the License. -#[macro_use] -extern crate log; -extern crate env_logger; +use env_logger; +use log::*; +use clap::{clap_app, value_t}; -#[macro_use] -extern crate clap; -extern crate ordered_float; -extern crate thrift; -extern crate thrift_test; // huh. I have to do this to use my lib - -use ordered_float::OrderedFloat; use std::collections::{BTreeMap, BTreeSet}; use std::fmt::Debug; +use thrift; +use thrift::OrderedFloat; use thrift::protocol::{TBinaryInputProtocol, TBinaryOutputProtocol, TCompactInputProtocol, TCompactOutputProtocol, TInputProtocol, TMultiplexedOutputProtocol, TOutputProtocol}; @@ -38,7 +33,7 @@ use thrift::transport::{ReadHalf, TBufferedReadTransport, TBufferedWriteTranspor use thrift_test::*; fn main() { - env_logger::init().expect("logger setup failed"); + env_logger::init(); debug!("initialized logger - running cross-test client"); @@ -167,7 +162,7 @@ fn tcp_channel( type BuildThriftTestClient = ThriftTestSyncClient, Box>; type BuiltSecondServiceClient = SecondServiceSyncClient, Box>; -#[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))] +#[allow(clippy::cognitive_complexity)] fn make_thrift_calls( thrift_test_client: &mut BuildThriftTestClient, second_service_client: &mut Option, @@ -191,7 +186,7 @@ fn make_thrift_calls( verify_expected_result(thrift_test_client.test_byte(42), 42)?; info!("testi32"); - verify_expected_result(thrift_test_client.test_i32(1159348374), 1159348374)?; + verify_expected_result(thrift_test_client.test_i32(1_159_348_374), 1_159_348_374)?; info!("testi64"); // try!(verify_expected_result(thrift_test_client.test_i64(-8651829879438294565), @@ -231,14 +226,14 @@ fn make_thrift_calls( let x_snd = Xtruct { string_thing: Some("foo".to_owned()), byte_thing: Some(12), - i32_thing: Some(219129), - i64_thing: Some(12938492818), + i32_thing: Some(219_129), + i64_thing: Some(12_938_492_818), }; let x_cmp = Xtruct { string_thing: Some("foo".to_owned()), byte_thing: Some(12), - i32_thing: Some(219129), - i64_thing: Some(12938492818), + i32_thing: Some(219_129), + i64_thing: Some(12_938_492_818), }; verify_expected_result(thrift_test_client.test_struct(x_snd), x_cmp)?; } @@ -264,11 +259,11 @@ fn make_thrift_calls( Xtruct { string_thing: Some("foo".to_owned()), byte_thing: Some(1), - i32_thing: Some(324382098), - i64_thing: Some(12938492818), + i32_thing: Some(324_382_098), + i64_thing: Some(12_938_492_818), }, ), - i32_thing: Some(293481098), + i32_thing: Some(293_481_098), }; let x_cmp = Xtruct2 { byte_thing: Some(32), @@ -276,11 +271,11 @@ fn make_thrift_calls( Xtruct { string_thing: Some("foo".to_owned()), byte_thing: Some(1), - i32_thing: Some(324382098), - i64_thing: Some(12938492818), + i32_thing: Some(324_382_098), + i64_thing: Some(12_938_492_818), }, ), - i32_thing: Some(293481098), + i32_thing: Some(293_481_098), }; verify_expected_result(thrift_test_client.test_nest(x_snd), x_cmp)?; } @@ -314,12 +309,12 @@ fn make_thrift_calls( info!("testSet"); { let mut s_snd: BTreeSet = BTreeSet::new(); - s_snd.insert(293481); + s_snd.insert(293_481); s_snd.insert(23); s_snd.insert(3234); let mut s_cmp: BTreeSet = BTreeSet::new(); - s_cmp.insert(293481); + s_cmp.insert(293_481); s_cmp.insert(23); s_cmp.insert(3234); @@ -386,12 +381,12 @@ fn make_thrift_calls( let s_cmp = Xtruct { string_thing: Some("Hello2".to_owned()), byte_thing: Some(1), - i32_thing: Some(-123948), - i64_thing: Some(-19234123981), + i32_thing: Some(-123_948), + i64_thing: Some(-19_234_123_981), }; verify_expected_result( - thrift_test_client.test_multi(1, -123948, -19234123981, m_snd, Numberz::Eight, 81), + thrift_test_client.test_multi(1, -123_948, -19_234_123_981, m_snd, Numberz::Eight, 81), s_cmp, )?; } @@ -429,8 +424,8 @@ fn make_thrift_calls( Xtruct { string_thing: Some("baz".to_owned()), byte_thing: Some(0), - i32_thing: Some(3948539), - i64_thing: Some(-12938492), + i32_thing: Some(3_948_539), + i64_thing: Some(-12_938_492), }, ); @@ -453,7 +448,7 @@ fn make_thrift_calls( s_cmp.insert(1 as UserId, s_cmp_nested_1); s_cmp.insert(2 as UserId, s_cmp_nested_2); - verify_expected_result(thrift_test_client.test_insanity(insanity.clone()), s_cmp)?; + verify_expected_result(thrift_test_client.test_insanity(insanity), s_cmp)?; } info!("testException - remote throws Xception"); @@ -583,7 +578,6 @@ fn make_thrift_calls( thrift_test_client.test_void() } -#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] fn verify_expected_result( actual: Result, expected: T, diff --git a/test/rs/src/bin/test_server.rs b/test/rs/src/bin/test_server.rs index e57cc14cb1f..74be12d488d 100644 --- a/test/rs/src/bin/test_server.rs +++ b/test/rs/src/bin/test_server.rs @@ -15,21 +15,16 @@ // specific language governing permissions and limitations // under the License. -#[macro_use] -extern crate log; -extern crate env_logger; +use env_logger; +use log::*; +use clap::{clap_app, value_t}; -#[macro_use] -extern crate clap; -extern crate ordered_float; -extern crate thrift; -extern crate thrift_test; - -use ordered_float::OrderedFloat; use std::collections::{BTreeMap, BTreeSet}; use std::thread; use std::time::Duration; +use thrift; +use thrift::OrderedFloat; use thrift::protocol::{TBinaryInputProtocolFactory, TBinaryOutputProtocolFactory, TCompactInputProtocolFactory, TCompactOutputProtocolFactory, TInputProtocolFactory, TOutputProtocolFactory}; @@ -40,7 +35,7 @@ use thrift::transport::{TBufferedReadTransportFactory, TBufferedWriteTransportFa use thrift_test::*; fn main() { - env_logger::init().expect("logger setup failed"); + env_logger::init(); debug!("initialized logger - running cross-test server"); @@ -274,7 +269,7 @@ impl ThriftTestSyncHandler for ThriftTestSyncHandlerImpl { info!("testInsanity({:?})", argument); let mut map_0: BTreeMap = BTreeMap::new(); map_0.insert(Numberz::Two, argument.clone()); - map_0.insert(Numberz::Three, argument.clone()); + map_0.insert(Numberz::Three, argument); let mut map_1: BTreeMap = BTreeMap::new(); let insanity = Insanity { diff --git a/test/rs/src/lib.rs b/test/rs/src/lib.rs index 10523f0a5e4..3c7cfc09e80 100644 --- a/test/rs/src/lib.rs +++ b/test/rs/src/lib.rs @@ -15,9 +15,9 @@ // specific language governing permissions and limitations // under the License. -extern crate ordered_float; -extern crate thrift; -extern crate try_from; + + + mod thrift_test; pub use crate::thrift_test::*; diff --git a/tutorial/rs/Cargo.toml b/tutorial/rs/Cargo.toml index d8e2a9a8de9..5e21d51a6ed 100644 --- a/tutorial/rs/Cargo.toml +++ b/tutorial/rs/Cargo.toml @@ -9,8 +9,6 @@ publish = false [dependencies] clap = "2.33" -ordered-float = "1.0" -try_from = "0.3" [dependencies.thrift] path = "../../lib/rs" diff --git a/tutorial/rs/README.md b/tutorial/rs/README.md index 166854beaff..97b1490fe5d 100644 --- a/tutorial/rs/README.md +++ b/tutorial/rs/README.md @@ -4,37 +4,22 @@ 1. Get the [Thrift compiler](https://thrift.apache.org). -2. Add the following crates to your `Cargo.toml`. +2. Add the thrift crate to your `Cargo.toml`. ```toml thrift = "x.y.z" # x.y.z is the version of the thrift compiler -ordered-float = "0.3.0" -try_from = "0.2.0" ``` -3. Add the same crates to your `lib.rs` or `main.rs`. - -```rust -extern crate ordered_float; -extern crate thrift; -extern crate try_from; -``` - -4. Generate Rust sources for your IDL (for example, `Tutorial.thrift`). +3. Generate Rust sources for your IDL (for example, `Tutorial.thrift`). ```shell thrift -out my_rust_program/src --gen rs -r Tutorial.thrift ``` -5. Use the generated source in your code. +4. Use the generated source in your code. ```rust -// add extern crates here, or in your lib.rs -extern crate ordered_float; -extern crate thrift; -extern crate try_from; - -// generated Rust module +// generated Rust module from Thrift IDL mod tutorial; use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol}; @@ -120,7 +105,7 @@ each generated file. ### Results and Errors The Thrift runtime library defines a `thrift::Result` and a `thrift::Error` type, -both of which are used throught the runtime library and in all generated code. +both of which are used throughout the runtime library and in all generated code. Conversions are defined from `std::io::Error`, `str` and `String` into `thrift::Error`. diff --git a/tutorial/rs/src/bin/tutorial_client.rs b/tutorial/rs/src/bin/tutorial_client.rs index 90a26d811c0..f7de23f0666 100644 --- a/tutorial/rs/src/bin/tutorial_client.rs +++ b/tutorial/rs/src/bin/tutorial_client.rs @@ -15,8 +15,7 @@ // specific language governing permissions and limitations // under the License. -#[macro_use] -extern crate clap; +use clap::{clap_app, value_t}; use thrift::protocol::{TCompactInputProtocol, TCompactOutputProtocol}; use thrift::transport::{ diff --git a/tutorial/rs/src/bin/tutorial_server.rs b/tutorial/rs/src/bin/tutorial_server.rs index e4d1d2ecba4..fbccb69c973 100644 --- a/tutorial/rs/src/bin/tutorial_server.rs +++ b/tutorial/rs/src/bin/tutorial_server.rs @@ -15,18 +15,17 @@ // specific language governing permissions and limitations // under the License. -#[macro_use] -extern crate clap; - use std::collections::HashMap; use std::convert::{From, Into}; use std::default::Default; use std::sync::Mutex; +use clap::{clap_app, value_t}; + use thrift::protocol::{TCompactInputProtocolFactory, TCompactOutputProtocolFactory}; use thrift::server::TServer; - use thrift::transport::{TFramedReadTransportFactory, TFramedWriteTransportFactory}; + use thrift_tutorial::shared::{SharedServiceSyncHandler, SharedStruct}; use thrift_tutorial::tutorial::{CalculatorSyncHandler, CalculatorSyncProcessor}; use thrift_tutorial::tutorial::{InvalidOperation, Operation, Work}; From 47e4923a9967b6ba3bbb5377809075c1940ecfc1 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Tue, 7 Apr 2020 18:43:46 +0200 Subject: [PATCH 708/756] Minor whitespace changes for netstd Patch: Mario Emmenlauer Client: netstd This closes #2282 --- test/netstd/Client/TestClient.cs | 31 +++++++++++++++---------------- tutorial/netstd/Client/Program.cs | 4 ++-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/test/netstd/Client/TestClient.cs b/test/netstd/Client/TestClient.cs index 3eab8654500..ec90250559c 100644 --- a/test/netstd/Client/TestClient.cs +++ b/test/netstd/Client/TestClient.cs @@ -51,7 +51,6 @@ internal enum LayeredChoice Framed } - internal enum TransportChoice { Socket, @@ -340,7 +339,7 @@ public void Execute() Console.WriteLine("*** FAILED ***"); Console.WriteLine("Connect failed: " + ex.Message); ReturnCode |= ErrorUnknown; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); continue; } catch (Exception ex) @@ -348,7 +347,7 @@ public void Execute() Console.WriteLine("*** FAILED ***"); Console.WriteLine("Connect failed: " + ex.Message); ReturnCode |= ErrorUnknown; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); continue; } @@ -359,7 +358,7 @@ public void Execute() catch (Exception ex) { Console.WriteLine("*** FAILED ***"); - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); ReturnCode |= ErrorUnknown; } } @@ -370,7 +369,7 @@ public void Execute() catch (Exception ex) { Console.WriteLine("Error while closing transport"); - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); } done = true; } @@ -404,8 +403,8 @@ public static int Execute(List args) catch (Exception ex) { Console.WriteLine("*** FAILED ***"); - Console.WriteLine("Error while parsing arguments"); - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine("Error while parsing arguments"); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); return ErrorUnknown; } @@ -429,7 +428,7 @@ public static int Execute(List args) { Console.WriteLine("*** FAILED ***"); Console.WriteLine("Unexpected error"); - Console.WriteLine(outerEx.Message + " ST: " + outerEx.StackTrace); + Console.WriteLine(outerEx.Message + "\n" + outerEx.StackTrace); return ErrorUnknown; } } @@ -607,11 +606,11 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) { Console.WriteLine("*** FAILED ***"); returnCode |= ErrorBaseTypes; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); } } - // CrazyNesting + // CrazyNesting Console.WriteLine("Test CrazyNesting"); var one = new CrazyNesting(); var two = new CrazyNesting(); @@ -951,7 +950,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) { Console.WriteLine("*** FAILED ***"); returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); } try { @@ -968,7 +967,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) { Console.WriteLine("*** FAILED ***"); returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); } try { @@ -980,7 +979,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) { Console.WriteLine("*** FAILED ***"); returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); } try @@ -1002,7 +1001,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) { Console.WriteLine("*** FAILED ***"); returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); } try { @@ -1023,7 +1022,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) { Console.WriteLine("*** FAILED ***"); returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); } try { @@ -1038,7 +1037,7 @@ public static async Task ExecuteClientTestAsync(ThriftTest.Client client) { Console.WriteLine("*** FAILED ***"); returnCode |= ErrorExceptions; - Console.WriteLine(ex.Message + " ST: " + ex.StackTrace); + Console.WriteLine(ex.Message + "\n" + ex.StackTrace); } Console.WriteLine("Test Oneway(1)"); diff --git a/tutorial/netstd/Client/Program.cs b/tutorial/netstd/Client/Program.cs index eefccf7036e..abbba702e82 100644 --- a/tutorial/netstd/Client/Program.cs +++ b/tutorial/netstd/Client/Program.cs @@ -17,6 +17,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Net; @@ -25,14 +26,13 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.DependencyInjection; using Thrift; using Thrift.Protocol; using Thrift.Transport; using Thrift.Transport.Client; using tutorial; using shared; -using Microsoft.Extensions.DependencyInjection; -using System.Diagnostics; namespace Client { From 6e6bb84be9d8ace4be9744d5637fbb59f58db463 Mon Sep 17 00:00:00 2001 From: David Mollitor Date: Fri, 2 Oct 2020 21:10:50 +0200 Subject: [PATCH 709/756] THRIFT-5288: Move Support for ByteBuffer into TTransport Client: Java Patch: David Mollitor This closes #2254 --- .../apache/thrift/async/TAsyncMethodCall.java | 16 ++++---- .../thrift/protocol/TCompactProtocol.java | 20 +++++----- .../server/AbstractNonblockingServer.java | 8 ++-- .../thrift/transport/TNonblockingSocket.java | 23 ++++++----- .../transport/TNonblockingTransport.java | 4 -- .../apache/thrift/transport/TTransport.java | 39 +++++++++++++++++++ .../thrift/transport/sasl/FrameWriter.java | 5 ++- .../sasl/NonblockingSaslHandler.java | 9 ++--- .../transport/sasl/TestDataFrameWriter.java | 2 +- 9 files changed, 81 insertions(+), 45 deletions(-) diff --git a/lib/java/src/org/apache/thrift/async/TAsyncMethodCall.java b/lib/java/src/org/apache/thrift/async/TAsyncMethodCall.java index d5c608d8756..a119f23e0bc 100644 --- a/lib/java/src/org/apache/thrift/async/TAsyncMethodCall.java +++ b/lib/java/src/org/apache/thrift/async/TAsyncMethodCall.java @@ -217,9 +217,9 @@ protected void onError(Exception e) { state = State.ERROR; } - private void doReadingResponseBody(SelectionKey key) throws IOException { + private void doReadingResponseBody(SelectionKey key) throws TTransportException { if (transport.read(frameBuffer) < 0) { - throw new IOException("Read call frame failed"); + throw new TTransportException(TTransportException.END_OF_FILE, "Read call frame failed"); } if (frameBuffer.remaining() == 0) { cleanUpAndFireCallback(key); @@ -241,9 +241,9 @@ private void cleanUpAndFireCallback(SelectionKey key) { } } - private void doReadingResponseSize() throws IOException { + private void doReadingResponseSize() throws TTransportException { if (transport.read(sizeBuffer) < 0) { - throw new IOException("Read call frame size failed"); + throw new TTransportException(TTransportException.END_OF_FILE, "Read call frame size failed"); } if (sizeBuffer.remaining() == 0) { state = State.READING_RESPONSE_BODY; @@ -251,9 +251,9 @@ private void doReadingResponseSize() throws IOException { } } - private void doWritingRequestBody(SelectionKey key) throws IOException { + private void doWritingRequestBody(SelectionKey key) throws TTransportException { if (transport.write(frameBuffer) < 0) { - throw new IOException("Write call frame failed"); + throw new TTransportException(TTransportException.END_OF_FILE, "Write call frame failed"); } if (frameBuffer.remaining() == 0) { if (isOneway) { @@ -266,9 +266,9 @@ private void doWritingRequestBody(SelectionKey key) throws IOException { } } - private void doWritingRequestSize() throws IOException { + private void doWritingRequestSize() throws TTransportException { if (transport.write(sizeBuffer) < 0) { - throw new IOException("Write call frame size failed"); + throw new TTransportException(TTransportException.END_OF_FILE, "Write call frame size failed"); } if (sizeBuffer.remaining() == 0) { state = State.WRITING_REQUEST_BODY; diff --git a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java index 0dfcf25d12c..4f4e21f50a1 100644 --- a/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java +++ b/lib/java/src/org/apache/thrift/protocol/TCompactProtocol.java @@ -363,20 +363,17 @@ public void writeDouble(double dub) throws TException { */ public void writeString(String str) throws TException { byte[] bytes = str.getBytes(StandardCharsets.UTF_8); - writeBinary(bytes, 0, bytes.length); + writeVarint32(bytes.length); + trans_.write(bytes, 0, bytes.length); } /** * 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); + ByteBuffer bb = bin.asReadOnlyBuffer(); + writeVarint32(bb.remaining()); + trans_.write(bb); } // @@ -694,12 +691,13 @@ public String readString() throws TException { } /** - * Read a byte[] from the wire. + * Read a ByteBuffer from the wire. */ public ByteBuffer readBinary() throws TException { int length = readVarint32(); - - if (length == 0) return EMPTY_BUFFER; + if (length == 0) { + return EMPTY_BUFFER; + } getTransport().checkReadBytesAvailable(length); if (trans_.getBytesRemainingInBuffer() >= length) { ByteBuffer bb = ByteBuffer.wrap(trans_.getBuffer(), trans_.getBufferPosition(), length); diff --git a/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java b/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java index 4aae803f2a5..f91e8254fa3 100644 --- a/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java +++ b/lib/java/src/org/apache/thrift/server/AbstractNonblockingServer.java @@ -414,8 +414,8 @@ public boolean write() { if (trans_.write(buffer_) < 0) { return false; } - } catch (IOException e) { - LOGGER.warn("Got an IOException during write!", e); + } catch (TTransportException e) { + LOGGER.warn("Got an Exception during write", e); return false; } @@ -543,8 +543,8 @@ public void invoke() { private boolean internalRead() { try { return trans_.read(buffer_) >= 0; - } catch (IOException e) { - LOGGER.warn("Got an IOException in internalRead!", e); + } catch (TTransportException e) { + LOGGER.warn("Got an Exception in internalRead", e); return false; } } diff --git a/lib/java/src/org/apache/thrift/transport/TNonblockingSocket.java b/lib/java/src/org/apache/thrift/transport/TNonblockingSocket.java index 76ed02cbb32..13c8586480f 100644 --- a/lib/java/src/org/apache/thrift/transport/TNonblockingSocket.java +++ b/lib/java/src/org/apache/thrift/transport/TNonblockingSocket.java @@ -144,11 +144,14 @@ public void open() throws TTransportException { /** * Perform a nonblocking read into buffer. */ - public int read(ByteBuffer buffer) throws IOException { - return socketChannel_.read(buffer); + public int read(ByteBuffer buffer) throws TTransportException { + try { + return socketChannel_.read(buffer); + } catch (IOException iox) { + throw new TTransportException(TTransportException.UNKNOWN, iox); + } } - /** * Reads from the underlying input stream if not null. */ @@ -167,8 +170,12 @@ public int read(byte[] buf, int off, int len) throws TTransportException { /** * Perform a nonblocking write of the data in buffer; */ - public int write(ByteBuffer buffer) throws IOException { - return socketChannel_.write(buffer); + public int write(ByteBuffer buffer) throws TTransportException { + try { + return socketChannel_.write(buffer); + } catch (IOException iox) { + throw new TTransportException(TTransportException.UNKNOWN, iox); + } } /** @@ -179,11 +186,7 @@ public void write(byte[] buf, int off, int len) throws TTransportException { 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); - } + write(ByteBuffer.wrap(buf, off, len)); } /** diff --git a/lib/java/src/org/apache/thrift/transport/TNonblockingTransport.java b/lib/java/src/org/apache/thrift/transport/TNonblockingTransport.java index 255595d6c1a..30ec9d25c05 100644 --- a/lib/java/src/org/apache/thrift/transport/TNonblockingTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TNonblockingTransport.java @@ -23,7 +23,6 @@ import java.io.IOException; import java.net.SocketAddress; -import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; @@ -47,7 +46,4 @@ public TNonblockingTransport(TConfiguration config) throws TTransportException { 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/lib/java/src/org/apache/thrift/transport/TTransport.java b/lib/java/src/org/apache/thrift/transport/TTransport.java index 5645f7fa17f..ee070243dea 100644 --- a/lib/java/src/org/apache/thrift/transport/TTransport.java +++ b/lib/java/src/org/apache/thrift/transport/TTransport.java @@ -22,6 +22,7 @@ import org.apache.thrift.TConfiguration; import java.io.Closeable; +import java.nio.ByteBuffer; /** * Generic class that encapsulates the I/O layer. This is basically a thin @@ -59,6 +60,26 @@ public abstract void open() */ public abstract void close(); + /** + * Reads a sequence of bytes from this channel into the given buffer. An + * attempt is made to read up to the number of bytes remaining in the buffer, + * that is, dst.remaining(), at the moment this method is invoked. Upon return + * the buffer's position will move forward the number of bytes read; its limit + * will not have changed. Subclasses are encouraged to provide a more + * efficient implementation of this method. + * + * @param dst The buffer into which bytes are to be transferred + * @return The number of bytes read, possibly zero, or -1 if the channel has + * reached end-of-stream + * @throws TTransportException if there was an error reading data + */ + public int read(ByteBuffer dst) throws TTransportException { + byte[] arr = new byte[dst.remaining()]; + int n = read(arr, 0, arr.length); + dst.put(arr, 0, n); + return n; + } + /** * Reads up to len bytes into buffer buf, starting at offset off. * @@ -120,6 +141,24 @@ public void write(byte[] buf) throws TTransportException { public abstract void write(byte[] buf, int off, int len) throws TTransportException; + /** + * Writes a sequence of bytes to the buffer. An attempt is made to write all + * remaining bytes in the buffer, that is, src.remaining(), at the moment this + * method is invoked. Upon return the buffer's position will updated; its limit + * will not have changed. Subclasses are encouraged to provide a more efficient + * implementation of this method. + * + * @param src The buffer from which bytes are to be retrieved + * @return The number of bytes written, possibly zero + * @throws TTransportException if there was an error writing data + */ + public int write(ByteBuffer src) throws TTransportException { + byte[] arr = new byte[src.remaining()]; + src.get(arr); + write(arr, 0, arr.length); + return arr.length; + } + /** * Flush any pending data out of a transport buffer. * diff --git a/lib/java/src/org/apache/thrift/transport/sasl/FrameWriter.java b/lib/java/src/org/apache/thrift/transport/sasl/FrameWriter.java index e5feba01f21..4357f13e161 100644 --- a/lib/java/src/org/apache/thrift/transport/sasl/FrameWriter.java +++ b/lib/java/src/org/apache/thrift/transport/sasl/FrameWriter.java @@ -23,6 +23,7 @@ import java.nio.ByteBuffer; import org.apache.thrift.transport.TNonblockingTransport; +import org.apache.thrift.transport.TTransportException; /** * Write frame (header and payload) to transport in a nonblocking way. @@ -99,9 +100,9 @@ protected abstract ByteBuffer buildFrame(byte[] header, int headerOffset, int he /** * Nonblocking write to the underlying transport. * - * @throws IOException + * @throws TTransportException */ - public void write(TNonblockingTransport transport) throws IOException { + public void write(TNonblockingTransport transport) throws TTransportException { transport.write(frameBytes); } diff --git a/lib/java/src/org/apache/thrift/transport/sasl/NonblockingSaslHandler.java b/lib/java/src/org/apache/thrift/transport/sasl/NonblockingSaslHandler.java index 45571469b11..d73c3ec18db 100644 --- a/lib/java/src/org/apache/thrift/transport/sasl/NonblockingSaslHandler.java +++ b/lib/java/src/org/apache/thrift/transport/sasl/NonblockingSaslHandler.java @@ -19,7 +19,6 @@ package org.apache.thrift.transport.sasl; -import java.io.IOException; import java.nio.channels.SelectionKey; import java.nio.charset.StandardCharsets; @@ -364,7 +363,7 @@ private void handleWritingSaslChallenge() { saslChallenge.clear(); nextPhase = Phase.READING_SASL_RESPONSE; } - } catch (IOException e) { + } catch (TTransportException e) { fail(e); } } @@ -378,7 +377,7 @@ private void handleWritingSuccessMessage() { saslResponse = null; nextPhase = Phase.READING_REQUEST; } - } catch (IOException e) { + } catch (TTransportException e) { fail(e); } } @@ -389,7 +388,7 @@ private void handleWritingFailureMessage() { if (saslChallenge.isComplete()) { nextPhase = Phase.CLOSING; } - } catch (IOException e) { + } catch (TTransportException e) { fail(e); } } @@ -401,7 +400,7 @@ private void handleWritingResponse() { responseWriter.clear(); nextPhase = Phase.READING_REQUEST; } - } catch (IOException e) { + } catch (TTransportException e) { fail(e); } } diff --git a/lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameWriter.java b/lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameWriter.java index d2425939f29..60fe5c96b2a 100644 --- a/lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameWriter.java +++ b/lib/java/test/org/apache/thrift/transport/sasl/TestDataFrameWriter.java @@ -72,7 +72,7 @@ public void testProvidePayloadToIncompleteFrame() { } @Test - public void testWrite() throws IOException { + public void testWrite() throws Exception { DataFrameWriter frameWriter = new DataFrameWriter(); frameWriter.withOnlyPayload(BYTES); // Slow socket which writes one byte per call. From 384a29616eb01854f85b353cd30d57cb5b83c4fc Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Sat, 24 Oct 2020 09:49:54 +0800 Subject: [PATCH 710/756] FixDownLoadErrorInCi --- build/appveyor/MSYS-appveyor-install.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/appveyor/MSYS-appveyor-install.bat b/build/appveyor/MSYS-appveyor-install.bat index a818df30513..6357f23689f 100644 --- a/build/appveyor/MSYS-appveyor-install.bat +++ b/build/appveyor/MSYS-appveyor-install.bat @@ -26,7 +26,7 @@ CALL cl_setenv.bat || EXIT /B CALL cl_showenv.bat || EXIT /B :: We're going to keep boost at a version cmake understands -SET BOOSTPKG=mingw-w64-x86_64-boost-1.64.0-3-any.pkg.tar.xz +SET BOOSTPKG=mingw-w64-x86_64-boost-1.71.0-1-any.pkg.tar.xz SET IGNORE=--ignore mingw-w64-x86_64-boost SET PACKAGES=^ From a8770a9dd2f8d50cd0e67e18d7da69c45e5bd606 Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Sat, 24 Oct 2020 09:53:53 +0800 Subject: [PATCH 711/756] rollback --- build/appveyor/MSYS-appveyor-install.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/appveyor/MSYS-appveyor-install.bat b/build/appveyor/MSYS-appveyor-install.bat index 6357f23689f..a818df30513 100644 --- a/build/appveyor/MSYS-appveyor-install.bat +++ b/build/appveyor/MSYS-appveyor-install.bat @@ -26,7 +26,7 @@ CALL cl_setenv.bat || EXIT /B CALL cl_showenv.bat || EXIT /B :: We're going to keep boost at a version cmake understands -SET BOOSTPKG=mingw-w64-x86_64-boost-1.71.0-1-any.pkg.tar.xz +SET BOOSTPKG=mingw-w64-x86_64-boost-1.64.0-3-any.pkg.tar.xz SET IGNORE=--ignore mingw-w64-x86_64-boost SET PACKAGES=^ From b6c886c940ff307a824b876c995676a894edb032 Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Sat, 24 Oct 2020 10:01:35 +0800 Subject: [PATCH 712/756] FixDownLoadErrorInAppveyorCi --- build/appveyor/MING-appveyor-install.bat | 4 ++++ build/appveyor/MSYS-appveyor-install.bat | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/build/appveyor/MING-appveyor-install.bat b/build/appveyor/MING-appveyor-install.bat index 4b5d730fb28..31b9bd763cd 100644 --- a/build/appveyor/MING-appveyor-install.bat +++ b/build/appveyor/MING-appveyor-install.bat @@ -25,6 +25,9 @@ CALL cl_banner_install.bat || EXIT /B CALL cl_setenv.bat || EXIT /B CALL cl_showenv.bat || EXIT /B +SET BOOSTPKG=mingw-w64-x86_64-boost-1.71.0-1-any.pkg.tar.xz +SET IGNORE=--ignore mingw-w64-x86_64-boost + SET PACKAGES=^ --needed -S bison flex make ^ mingw-w64-%MINGWPLAT%-boost ^ @@ -49,3 +52,4 @@ SET PACKAGES=^ :: %BASH% -lc "pacman --noconfirm -Su %IGNORE%" || EXIT /B :: %BASH% -lc "pacman --noconfirm %PACKAGES%" || EXIT /B +%BASH% -lc "wget http://repo.msys2.org/mingw/x86_64/%BOOSTPKG% && pacman -- noconfirm --needed -U %BOOSTPKG% && rm %BOOKSTPKG%" || EXIT /B diff --git a/build/appveyor/MSYS-appveyor-install.bat b/build/appveyor/MSYS-appveyor-install.bat index a818df30513..6357f23689f 100644 --- a/build/appveyor/MSYS-appveyor-install.bat +++ b/build/appveyor/MSYS-appveyor-install.bat @@ -26,7 +26,7 @@ CALL cl_setenv.bat || EXIT /B CALL cl_showenv.bat || EXIT /B :: We're going to keep boost at a version cmake understands -SET BOOSTPKG=mingw-w64-x86_64-boost-1.64.0-3-any.pkg.tar.xz +SET BOOSTPKG=mingw-w64-x86_64-boost-1.71.0-1-any.pkg.tar.xz SET IGNORE=--ignore mingw-w64-x86_64-boost SET PACKAGES=^ From c8dab1f37a74cc52090ba4ce018a0d552dcc637d Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Mon, 26 Oct 2020 10:50:28 +0800 Subject: [PATCH 713/756] try update the package to download the software --- build/appveyor/MING-appveyor-install.bat | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/appveyor/MING-appveyor-install.bat b/build/appveyor/MING-appveyor-install.bat index 31b9bd763cd..d06e0308c07 100644 --- a/build/appveyor/MING-appveyor-install.bat +++ b/build/appveyor/MING-appveyor-install.bat @@ -51,5 +51,6 @@ SET PACKAGES=^ :: %BASH% -lc "pacman --noconfirm -Syu %IGNORE%" || EXIT /B :: %BASH% -lc "pacman --noconfirm -Su %IGNORE%" || EXIT /B :: +%BASH% -lc "pacman -Scc" || EXIT /B +%BASH% -lc "pacman -Syyu" || EXIT /B %BASH% -lc "pacman --noconfirm %PACKAGES%" || EXIT /B -%BASH% -lc "wget http://repo.msys2.org/mingw/x86_64/%BOOSTPKG% && pacman -- noconfirm --needed -U %BOOSTPKG% && rm %BOOKSTPKG%" || EXIT /B From 966da2992f8ed8e52bbbb84f266ceb5b9c159480 Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Mon, 26 Oct 2020 11:49:46 +0800 Subject: [PATCH 714/756] upgrade msys try get the soft --- build/appveyor/MING-appveyor-install.bat | 17 ++++++++++------- build/appveyor/MSYS-appveyor-install.bat | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/build/appveyor/MING-appveyor-install.bat b/build/appveyor/MING-appveyor-install.bat index d06e0308c07..4d49d4089aa 100644 --- a/build/appveyor/MING-appveyor-install.bat +++ b/build/appveyor/MING-appveyor-install.bat @@ -25,9 +25,6 @@ CALL cl_banner_install.bat || EXIT /B CALL cl_setenv.bat || EXIT /B CALL cl_showenv.bat || EXIT /B -SET BOOSTPKG=mingw-w64-x86_64-boost-1.71.0-1-any.pkg.tar.xz -SET IGNORE=--ignore mingw-w64-x86_64-boost - SET PACKAGES=^ --needed -S bison flex make ^ mingw-w64-%MINGWPLAT%-boost ^ @@ -50,7 +47,13 @@ SET PACKAGES=^ :: Upgrade things :: %BASH% -lc "pacman --noconfirm -Syu %IGNORE%" || EXIT /B :: %BASH% -lc "pacman --noconfirm -Su %IGNORE%" || EXIT /B -:: -%BASH% -lc "pacman -Scc" || EXIT /B -%BASH% -lc "pacman -Syyu" || EXIT /B -%BASH% -lc "pacman --noconfirm %PACKAGES%" || EXIT /B + +:: Updata the new key +%BASH% -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" || EXIT /B +%BASH% -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" || EXIT /B +%BASH% -lc "pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" || EXIT /B +%BASH% -lc "pacman --noconfirm -U --config <(echo) msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" || EXIT /B +:: Upgrade things +%BASH% -lc "pacman --noconfirm -Sy" || EXIT /B +%BASH% -lc "pacman --noconfirm -Sydd pacman" || EXIT /B +%BASH% -lc "pacman --noconfirm %PACKAGES%" || EXIT /B diff --git a/build/appveyor/MSYS-appveyor-install.bat b/build/appveyor/MSYS-appveyor-install.bat index 6357f23689f..a818df30513 100644 --- a/build/appveyor/MSYS-appveyor-install.bat +++ b/build/appveyor/MSYS-appveyor-install.bat @@ -26,7 +26,7 @@ CALL cl_setenv.bat || EXIT /B CALL cl_showenv.bat || EXIT /B :: We're going to keep boost at a version cmake understands -SET BOOSTPKG=mingw-w64-x86_64-boost-1.71.0-1-any.pkg.tar.xz +SET BOOSTPKG=mingw-w64-x86_64-boost-1.64.0-3-any.pkg.tar.xz SET IGNORE=--ignore mingw-w64-x86_64-boost SET PACKAGES=^ From 1506661e92df5568c9e537bd68cd1c59dc55f38a Mon Sep 17 00:00:00 2001 From: Konstantin Pozdniakov Date: Sat, 21 Nov 2020 10:13:29 +0100 Subject: [PATCH 715/756] Log errors in processor via standard logger #2284 Client: netstd Patch: Konstantin Pozdniakov & Jens Geyer This closes #2284 --- .../src/thrift/generate/t_netstd_generator.cc | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index f1198e5e623..96963ee2b74 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -361,6 +361,7 @@ string t_netstd_generator::netstd_type_usings() const "using System.Linq;\n" "using System.Threading;\n" "using System.Threading.Tasks;\n" + "using Microsoft.Extensions.Logging;\n" "using Thrift;\n" "using Thrift.Collections;\n"; @@ -2134,8 +2135,9 @@ void t_netstd_generator::generate_service_server(ostream& out, t_service* tservi indent_up(); out << indent() << "private readonly IAsync _iAsync;" << endl + << indent() << "private readonly ILogger _logger;" << endl << endl - << indent() << "public AsyncProcessor(IAsync iAsync)"; + << indent() << "public AsyncProcessor(IAsync iAsync, ILogger logger = default)"; if (!extends.empty()) { @@ -2147,6 +2149,7 @@ void t_netstd_generator::generate_service_server(ostream& out, t_service* tservi indent_up(); out << indent() << "_iAsync = iAsync ?? throw new ArgumentNullException(nameof(iAsync));" << endl; + out << indent() << "_logger = logger;" << endl; for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) { string function_name = (*f_iter)->get_name(); @@ -2380,8 +2383,15 @@ void t_netstd_generator::generate_process_function_async(ostream& out, t_service << indent() << "{" << endl; indent_up(); - out << indent() << "Console.Error.WriteLine(\"Error occurred in processor:\");" << endl - << indent() << "Console.Error.WriteLine(ex.ToString());" << endl; + out << indent() << "var sErr = $\"Error occurred in {GetType().FullName}: {ex.Message}\";" << endl; + out << indent() << "if(_logger != null)" << endl; + indent_up(); + out << indent() << "_logger.LogError(ex, sErr);" << endl; + indent_down(); + out << indent() << "else" << endl; + indent_up(); + out << indent() << "Console.WriteLine(sErr);" << endl; + indent_down(); if (tfunction->is_oneway()) { From 828ffa8963efe14efd70e1c5c0688bab9f6714db Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 21 Nov 2020 15:15:32 +0100 Subject: [PATCH 716/756] silenced few warnings Client: netstd Patch: Jens Geyer --- test/netstd/Server/TestServer.cs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/test/netstd/Server/TestServer.cs b/test/netstd/Server/TestServer.cs index 68461dc9c05..5c99099de6f 100644 --- a/test/netstd/Server/TestServer.cs +++ b/test/netstd/Server/TestServer.cs @@ -34,6 +34,8 @@ using Thrift.Transport; using Thrift.Transport.Server; +#pragma warning disable IDE0063 // using can be simplified, we don't + namespace ThriftTest { internal enum ProtocolChoice @@ -594,21 +596,13 @@ public static int Execute(List args) break; } - // Protocol (mandatory) - TProtocolFactory proto; - switch (param.protocol) + TProtocolFactory proto = param.protocol switch { - case ProtocolChoice.Compact: - proto = new TCompactProtocol.Factory(); - break; - case ProtocolChoice.Json: - proto = new TJsonProtocol.Factory(); - break; - case ProtocolChoice.Binary: - default: - proto = new TBinaryProtocol.Factory(); - break; - } + ProtocolChoice.Compact => new TCompactProtocol.Factory(), + ProtocolChoice.Json => new TJsonProtocol.Factory(), + ProtocolChoice.Binary => new TBinaryProtocol.Factory(), + _ => new TBinaryProtocol.Factory(), + }; // Processor var testHandler = new TestHandlerAsync(); From 71e972c9708b0b41e7e51ed681a7edd71721ec3e Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Sat, 21 Nov 2020 15:26:40 +0100 Subject: [PATCH 717/756] FIX: Log errors in processor via standard logger -> errors to write into Console.Error as before --- compiler/cpp/src/thrift/generate/t_netstd_generator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index 96963ee2b74..8232760e409 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -2390,7 +2390,7 @@ void t_netstd_generator::generate_process_function_async(ostream& out, t_service indent_down(); out << indent() << "else" << endl; indent_up(); - out << indent() << "Console.WriteLine(sErr);" << endl; + out << indent() << "Console.Error.WriteLine(sErr);" << endl; indent_down(); if (tfunction->is_oneway()) From b72b674efc5114b733e0b7ae7ba68ce3933fa051 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Thu, 19 Nov 2020 10:49:33 +0100 Subject: [PATCH 718/756] Removed symbolic link tutorial/cl/ensure-externals.sh --- tutorial/cl/Makefile.am | 4 ++-- tutorial/cl/ensure-externals.sh | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) delete mode 120000 tutorial/cl/ensure-externals.sh diff --git a/tutorial/cl/Makefile.am b/tutorial/cl/Makefile.am index 2b2013a3c99..2d15b08eb8f 100755 --- a/tutorial/cl/Makefile.am +++ b/tutorial/cl/Makefile.am @@ -16,8 +16,8 @@ # specific language governing permissions and limitations # under the License. -setup-local-lisp-env: ensure-externals.sh - bash ensure-externals.sh +setup-local-lisp-env: ../../lib/cl/ensure-externals.sh + bash ../../lib/cl/ensure-externals.sh gen-cl: $(top_srcdir)/tutorial/tutorial.thrift $(THRIFT) --gen cl -r $< diff --git a/tutorial/cl/ensure-externals.sh b/tutorial/cl/ensure-externals.sh deleted file mode 120000 index 5ae8c5657c6..00000000000 --- a/tutorial/cl/ensure-externals.sh +++ /dev/null @@ -1 +0,0 @@ -../../lib/cl/ensure-externals.sh \ No newline at end of file From c981cf8891cab7277ddb083282c27549da5a9dda Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Tue, 1 Dec 2020 22:36:31 +0100 Subject: [PATCH 719/756] THRIFT-5317 netstd compiler does not escape keywords Client: netstd Patch: Jens Geyer --- compiler/cpp/src/thrift/generate/t_netstd_generator.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index 8232760e409..45e658e8263 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -1066,7 +1066,7 @@ void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struc { out << ", "; } - out << type_name((*m_iter)->get_type()) << " " << (*m_iter)->get_name(); + out << type_name((*m_iter)->get_type()) << " " << normalize_name((*m_iter)->get_name()); } } out << ") : this()" << endl @@ -1077,7 +1077,7 @@ void t_netstd_generator::generate_netstd_struct_definition(ostream& out, t_struc { if (field_is_required(*m_iter)) { - out << indent() << "this." << prop_name(*m_iter) << " = " << (*m_iter)->get_name() << ";" << endl; + out << indent() << "this." << prop_name(*m_iter) << " = " << normalize_name((*m_iter)->get_name()) << ";" << endl; } } From c0619235bdaaaf16941abbf8ba77a84a06708178 Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Wed, 8 Apr 2020 14:39:58 +0200 Subject: [PATCH 720/756] Make ~TException() virtual Client: cpp Patch: Mario Emmenlauer This closes #2281 --- lib/cpp/src/thrift/Thrift.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cpp/src/thrift/Thrift.h b/lib/cpp/src/thrift/Thrift.h index 6cb24e660e1..d5066ee7107 100644 --- a/lib/cpp/src/thrift/Thrift.h +++ b/lib/cpp/src/thrift/Thrift.h @@ -79,7 +79,7 @@ class TException : public std::exception { TException(const std::string& message) : message_(message) {} - ~TException() noexcept override = default; + virtual ~TException() noexcept override = default; const char* what() const noexcept override { if (message_.empty()) { From 66777ad21551d5d2f213fe06b53336988fe29136 Mon Sep 17 00:00:00 2001 From: Sergey Yelin Date: Fri, 4 Dec 2020 13:17:00 +0300 Subject: [PATCH 721/756] Fix Erlang CI: Add gen-erl into test's path Client: erl Patch: Sergey Yelin This closes #2290 --- lib/erl/rebar.config | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/erl/rebar.config b/lib/erl/rebar.config index 1b32947a5a3..ab2c255c6b4 100644 --- a/lib/erl/rebar.config +++ b/lib/erl/rebar.config @@ -1,3 +1,11 @@ {erl_opts, [{platform_define, "^R.*", otp16_or_less}, debug_info]}. -{profiles, [{test, [{deps, [meck]}]}]}. +{profiles, [ + {test, [ + {deps, [meck]}, + {eunit_tests, [ + {dir, "test"}, + {dir, "test/gen-erl"} + ]} + ]} +]}. From 12f6c31c8df739ccff271c8b81345d9a630c8921 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 4 Dec 2020 01:18:54 +0100 Subject: [PATCH 722/756] THRIFT-5320: Usage of "Task" as IDL identifier generates uncompileable code Client: netstd Patch: Jens Geyer This closes #2289 --- .../src/thrift/generate/t_netstd_generator.cc | 18 ++++----- ...rift.PublicInterfaces.Compile.Tests.csproj | 3 ++ .../Thrift5320.enum.thrift | 25 ++++++++++++ .../Thrift5320.exception.thrift | 27 +++++++++++++ .../Thrift5320.struct.thrift | 26 ++++++++++++ .../Thrift5320.thrift | 40 +++++++++++++++++++ 6 files changed, 130 insertions(+), 9 deletions(-) create mode 100644 lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.enum.thrift create mode 100644 lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.exception.thrift create mode 100644 lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.struct.thrift create mode 100644 lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.thrift diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index 45e658e8263..ea477828704 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -1198,7 +1198,7 @@ void t_netstd_generator::generate_netstd_deepcopy_method(ostream& out, t_struct* void t_netstd_generator::generate_netstd_struct_reader(ostream& out, t_struct* tstruct) { - out << indent() << "public async Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken)" << endl + out << indent() << "public async global::System.Threading.Tasks.Task ReadAsync(TProtocol iprot, CancellationToken cancellationToken)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "iprot.IncrementRecursionDepth();" << endl @@ -1340,7 +1340,7 @@ void t_netstd_generator::generate_null_check_end(ostream& out, t_field* tfield) void t_netstd_generator::generate_netstd_struct_writer(ostream& out, t_struct* tstruct) { - out << indent() << "public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl + out << indent() << "public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl << indent() << "{" << endl; indent_up(); @@ -1390,7 +1390,7 @@ void t_netstd_generator::generate_netstd_struct_writer(ostream& out, t_struct* t void t_netstd_generator::generate_netstd_struct_result_writer(ostream& out, t_struct* tstruct) { - out << indent() << "public async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl + out << indent() << "public async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl << indent() << "{" << endl; indent_up(); @@ -1549,7 +1549,7 @@ void t_netstd_generator::generate_netstd_union_definition(ostream& out, t_struct out << indent() << "{" << endl; indent_up(); - out << indent() << "public abstract Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken);" << endl + out << indent() << "public abstract global::System.Threading.Tasks.Task WriteAsync(TProtocol tProtocol, CancellationToken cancellationToken);" << endl << indent() << "public readonly int Isset;" << endl << indent() << "public abstract object Data { get; }" << endl << indent() << "protected " << tunion->get_name() << "(int isset)" << endl @@ -1659,7 +1659,7 @@ void t_netstd_generator::generate_netstd_union_definition(ostream& out, t_struct generate_netstd_struct_equals(out, &undefined_struct); generate_netstd_struct_hashcode(out, &undefined_struct); - out << indent() << "public override Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl + out << indent() << "public override global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken)" << endl << indent() << "{" << endl; indent_up(); out << indent() << "throw new TProtocolException( TProtocolException.INVALID_DATA, \"Cannot persist an union type which is not set.\");" << endl; @@ -1738,7 +1738,7 @@ void t_netstd_generator::generate_netstd_union_class(ostream& out, t_struct* tun indent_down(); out << indent() << "}" << endl << endl; - out << indent() << "public override async Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) {" << endl; + out << indent() << "public override async global::System.Threading.Tasks.Task WriteAsync(TProtocol oprot, CancellationToken cancellationToken) {" << endl; indent_up(); out << indent() << "oprot.IncrementRecursionDepth();" << endl @@ -2162,7 +2162,7 @@ void t_netstd_generator::generate_service_server(ostream& out, t_service* tservi if (extends.empty()) { - out << indent() << "protected delegate Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken);" << endl; + out << indent() << "protected delegate global::System.Threading.Tasks.Task ProcessFunction(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken);" << endl; } if (extends.empty()) @@ -2271,7 +2271,7 @@ void t_netstd_generator::generate_function_helpers(ostream& out, t_function* tfu void t_netstd_generator::generate_process_function_async(ostream& out, t_service* tservice, t_function* tfunction) { (void)tservice; - out << indent() << "public async Task " << tfunction->get_name() + out << indent() << "public async global::System.Threading.Tasks.Task " << tfunction->get_name() << "_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken)" << endl << indent() << "{" << endl; indent_up(); @@ -3262,7 +3262,7 @@ string t_netstd_generator::function_signature(t_function* tfunction, string pref string t_netstd_generator::function_signature_async(t_function* tfunction, string prefix) { t_type* ttype = tfunction->get_returntype(); - string task = "Task"; + string task = "global::System.Threading.Tasks.Task"; if (!ttype->is_void()) { task += "<" + type_name(ttype) + ">"; diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj index 95c85afc0a1..c43c71cd720 100644 --- a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj @@ -55,6 +55,9 @@ + + + diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.enum.thrift b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.enum.thrift new file mode 100644 index 00000000000..d4392d6a83a --- /dev/null +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.enum.thrift @@ -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. + +// Testcase for THRIFT-5320 Usage of "Task" as IDL identifier generates uncompileable code + +namespace * Thrift5320.enums + +enum Task { + Zero, + More +} + diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.exception.thrift b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.exception.thrift new file mode 100644 index 00000000000..b6b8cdab150 --- /dev/null +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.exception.thrift @@ -0,0 +1,27 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +// Testcase for THRIFT-5320 Usage of "Task" as IDL identifier generates uncompileable code + +namespace * Thrift5320.exceptions + + + +exception Task { + 1: Task left + 2: Task right +} + diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.struct.thrift b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.struct.thrift new file mode 100644 index 00000000000..771c487023f --- /dev/null +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.struct.thrift @@ -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. + +// Testcase for THRIFT-5320 Usage of "Task" as IDL identifier generates uncompileable code + +namespace * Thrift5320.structs + + +struct Task { + 1: Task left + 2: Task right +} + diff --git a/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.thrift b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.thrift new file mode 100644 index 00000000000..f677973b02f --- /dev/null +++ b/lib/netstd/Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift5320.thrift @@ -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. + +// Testcase for THRIFT-5320 Usage of "Task" as IDL identifier generates uncompileable code + +namespace * Thrift5320.Task + +include "Thrift5320.enum.thrift" +include "Thrift5320.exception.thrift" +include "Thrift5320.struct.thrift" + +enum Foobar { + Task = 0 +} + + +service Task { + Thrift5320.enum.Task Task( + 1 : Thrift5320.struct.Task foo, + 2: Foobar bar + ) throws ( + 1: Thrift5320.exception.Task error + ) +} + + + From fb4b5aa17b0542f6f75d9744ecfe904f57431331 Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Sat, 31 Oct 2020 14:39:13 +0800 Subject: [PATCH 723/756] Fix Missed check in c_glib for frame max message size check --- .../c_glib/transport/thrift_framed_transport.c | 13 +++++++++++++ .../c_glib/transport/thrift_framed_transport.h | 1 + 2 files changed, 14 insertions(+) diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c b/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c index f7b819260e6..3cbb245e07c 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.c @@ -96,6 +96,14 @@ thrift_framed_transport_read_frame (ThriftTransport *transport, guchar *tmpdata; sz = ntohl (sz); + if (sz > t->max_frame_size) + { + g_set_error (error, + THRIFT_TRANSPORT_ERROR, + THRIFT_TRANSPORT_ERROR_MAX_MESSAGE_SIZE_REACHED, + "Recived an oversized frame,"); + return result; + } /* create a buffer to hold the data and read that much data */ tmpdata = g_new0 (guchar, sz); @@ -277,6 +285,7 @@ thrift_framed_transport_init (ThriftFramedTransport *transport) transport->transport = NULL; transport->r_buf = g_byte_array_new (); transport->w_buf = g_byte_array_new (); + transport->max_frame_size = DEFAULT_MAX_FRAME_SIZE; } /* destructor */ @@ -354,6 +363,10 @@ thrift_framed_transport_set_property (GObject *object, guint property_id, break; case PROP_THRIFT_FRAMED_TRANSPORT_CONFIGURATION: tt->configuration = g_value_dup_object (value); + if (tt->configuration != NULL) + { + transport->max_frame_size = tt->configuration->maxFrameSize_; + } break; case PROP_THRIFT_FRAMED_TRANSPORT_REMAINING_MESSAGE_SIZE: tt->remainingMessageSize_ = g_value_get_long (value); diff --git a/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.h b/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.h index a1020611a1f..245cd21c4fe 100644 --- a/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.h +++ b/lib/c_glib/src/thrift/c_glib/transport/thrift_framed_transport.h @@ -53,6 +53,7 @@ struct _ThriftFramedTransport ThriftTransport *transport; /* private */ + guint32 max_frame_size; GByteArray *r_buf; GByteArray *w_buf; guint32 r_buf_size; From 10f2556733b8ee34f2c3695f09c1dff717fdafc8 Mon Sep 17 00:00:00 2001 From: rglarix Date: Wed, 7 Oct 2020 18:34:51 +0200 Subject: [PATCH 724/756] THRIFT-5295 makeThread and ThreadFactory extensible Client: cpp Patch: Riccardo Ghetta This closes #2260 Signed-off-by: rglarix --- lib/cpp/src/thrift/concurrency/Thread.h | 17 ++++++++++++----- lib/cpp/src/thrift/concurrency/ThreadFactory.h | 6 +++--- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/cpp/src/thrift/concurrency/Thread.h b/lib/cpp/src/thrift/concurrency/Thread.h index ed43754dfd5..344d2ca31a3 100644 --- a/lib/cpp/src/thrift/concurrency/Thread.h +++ b/lib/cpp/src/thrift/concurrency/Thread.h @@ -67,10 +67,11 @@ class Runnable { * * @see apache::thrift::concurrency::ThreadFactory) */ -class Thread final : public std::enable_shared_from_this { +class Thread : public std::enable_shared_from_this { public: typedef std::thread::id id_t; + typedef void (*thread_funct_t)(std::shared_ptr ); enum STATE { uninitialized, starting, started, stopping, stopped }; @@ -84,7 +85,7 @@ class Thread final : public std::enable_shared_from_this { this->_runnable = runnable; } - ~Thread() { + virtual ~Thread() { if (!detached_ && thread_->joinable()) { try { join(); @@ -117,7 +118,7 @@ class Thread final : public std::enable_shared_from_this { * configuration then invokes the run method of the Runnable object bound * to this thread. */ - void start() { + virtual void start() { if (getState() != uninitialized) { return; } @@ -126,7 +127,7 @@ class Thread final : public std::enable_shared_from_this { setState(starting); Synchronized sync(monitor_); - thread_ = std::unique_ptr(new std::thread(threadMain, selfRef)); + thread_ = std::unique_ptr(new std::thread(getThreadFunc(), selfRef)); if (detached_) thread_->detach(); @@ -142,7 +143,7 @@ class Thread final : public std::enable_shared_from_this { * until this thread completes. If the target thread is not joinable, then * nothing happens. */ - void join() { + virtual void join() { if (!detached_ && state_ != uninitialized) { thread_->join(); } @@ -158,6 +159,12 @@ class Thread final : public std::enable_shared_from_this { */ std::shared_ptr runnable() const { return _runnable; } +protected: + + virtual thread_funct_t getThreadFunc() const { + return threadMain; + } + private: std::shared_ptr _runnable; std::unique_ptr thread_; diff --git a/lib/cpp/src/thrift/concurrency/ThreadFactory.h b/lib/cpp/src/thrift/concurrency/ThreadFactory.h index a1547a6e07a..9db832e321b 100644 --- a/lib/cpp/src/thrift/concurrency/ThreadFactory.h +++ b/lib/cpp/src/thrift/concurrency/ThreadFactory.h @@ -31,7 +31,7 @@ namespace concurrency { * Factory to create thread object and bind them to Runnable * object for execution */ -class ThreadFactory final { +class ThreadFactory { public: /** * All threads created by a factory are reference-counted @@ -43,7 +43,7 @@ class ThreadFactory final { */ ThreadFactory(bool detached = true) : detached_(detached) { } - ~ThreadFactory() = default; + virtual ~ThreadFactory() = default; /** * Gets current detached mode @@ -58,7 +58,7 @@ class ThreadFactory final { /** * Create a new thread. */ - std::shared_ptr newThread(std::shared_ptr runnable) const; + virtual std::shared_ptr newThread(std::shared_ptr runnable) const; /** * Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread From 494a845dd972fc0e68f6937e27ae74efd444b848 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Wed, 9 Dec 2020 21:56:21 +0100 Subject: [PATCH 725/756] THRIFT-5198 Fix certain Visual Studio hints in generated netstd code Client: netstd Patch: Jens Geyer --- compiler/cpp/src/thrift/generate/t_netstd_generator.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index ea477828704..b90f71a3d6c 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -333,7 +333,10 @@ void t_netstd_generator::reset_indent() { void t_netstd_generator::start_netstd_namespace(ostream& out) { - out << "#pragma warning disable IDE1006 // parts of the code use IDL spelling" << endl; + out << "#pragma warning disable IDE0079 // remove unnecessary pragmas" << endl + << "#pragma warning disable IDE1006 // parts of the code use IDL spelling" << endl + << endl; + if (!namespace_name_.empty()) { out << "namespace " << namespace_name_ << endl; @@ -347,7 +350,6 @@ void t_netstd_generator::end_netstd_namespace(ostream& out) { scope_down(out); } - out << "#pragma warning restore IDE1006" << endl; } string t_netstd_generator::netstd_type_usings() const From 70792f2191e5e7345bf08f766638e166d5937f32 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Tue, 8 Dec 2020 13:46:28 +0100 Subject: [PATCH 726/756] Add useful links in Rust client's metadata Client: Rust Patch: Dirkjan Ochtman This closes #2291 --- lib/rs/Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml index 182cd8d86aa..4f2b4c82c25 100644 --- a/lib/rs/Cargo.toml +++ b/lib/rs/Cargo.toml @@ -6,7 +6,8 @@ version = "0.14.0" license = "Apache-2.0" authors = ["Apache Thrift Developers "] homepage = "http://thrift.apache.org" -documentation = "https://thrift.apache.org" +documentation = "https://docs.rs/thrift" +repository = "https://github.com/apache/thrift/tree/master/lib/rs" readme = "README.md" exclude = ["Makefile*", "test/**", "*.iml"] keywords = ["thrift"] From 4461728f18542eba5d211f9fc412557aab61c491 Mon Sep 17 00:00:00 2001 From: Morozov Date: Tue, 15 Dec 2020 10:35:57 +0300 Subject: [PATCH 727/756] THRIFT-5324: reset http client buffer after flush THttpClient did not reset its internal buffer when HTTP client returned an error, leaving the whole or partially read message in the buffer. Now we reset the buffer in defer. Client: go --- lib/go/thrift/http_client.go | 8 +++++ lib/go/thrift/http_client_test.go | 60 ++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/lib/go/thrift/http_client.go b/lib/go/thrift/http_client.go index 1924a1ae268..19c63a98512 100644 --- a/lib/go/thrift/http_client.go +++ b/lib/go/thrift/http_client.go @@ -197,6 +197,14 @@ func (p *THttpClient) Flush(ctx context.Context) error { // Close any previous response body to avoid leaking connections. p.closeResponse() + // Request might not have been fully read by http client. + // Reset so we don't send the remains on next call. + defer func() { + if p.requestBuffer != nil { + p.requestBuffer.Reset() + } + }() + req, err := http.NewRequest("POST", p.url.String(), p.requestBuffer) if err != nil { return NewTTransportExceptionFromError(err) diff --git a/lib/go/thrift/http_client_test.go b/lib/go/thrift/http_client_test.go index a7977a38595..eba366815ca 100644 --- a/lib/go/thrift/http_client_test.go +++ b/lib/go/thrift/http_client_test.go @@ -20,6 +20,8 @@ package thrift import ( + "bytes" + "context" "net/http" "testing" ) @@ -32,14 +34,14 @@ func TestHttpClient(t *testing.T) { trans, err := NewTHttpPostClient("http://" + addr.String()) if err != nil { l.Close() - t.Fatalf("Unable to connect to %s: %s", addr.String(), err) + t.Fatalf("Unable to connect to %s: %v", addr.String(), err) } TransportTest(t, trans, trans) t.Run("nilBuffer", func(t *testing.T) { _ = trans.Close() if _, err = trans.Write([]byte{1, 2, 3, 4}); err == nil { - t.Fatalf("writing to a closed transport did not result in an error") + t.Fatal("writing to a closed transport did not result in an error") } }) } @@ -52,7 +54,7 @@ func TestHttpClientHeaders(t *testing.T) { trans, err := NewTHttpPostClient("http://" + addr.String()) if err != nil { l.Close() - t.Fatalf("Unable to connect to %s: %s", addr.String(), err) + t.Fatalf("Unable to connect to %s: %v", addr.String(), err) } TransportHeaderTest(t, trans, trans) } @@ -72,7 +74,7 @@ func TestHttpCustomClient(t *testing.T) { }) if err != nil { l.Close() - t.Fatalf("Unable to connect to %s: %s", addr.String(), err) + t.Fatalf("Unable to connect to %s: %v", addr.String(), err) } TransportHeaderTest(t, trans, trans) @@ -94,7 +96,7 @@ func TestHttpCustomClientPackageScope(t *testing.T) { trans, err := NewTHttpPostClient("http://" + addr.String()) if err != nil { l.Close() - t.Fatalf("Unable to connect to %s: %s", addr.String(), err) + t.Fatalf("Unable to connect to %s: %v", addr.String(), err) } TransportHeaderTest(t, trans, trans) @@ -103,6 +105,54 @@ func TestHttpCustomClientPackageScope(t *testing.T) { } } +func TestHTTPClientFlushesRequestBufferOnErrors(t *testing.T) { + var ( + write1 = []byte("write 1") + write2 = []byte("write 2") + ) + + l, addr := HttpClientSetupForTest(t) + if l != nil { + defer l.Close() + } + trans, err := NewTHttpPostClient("http://" + addr.String()) + if err != nil { + t.Fatalf("Unable to connect to %s: %v", addr.String(), err) + } + defer trans.Close() + + _, err = trans.Write(write1) + if err != nil { + t.Fatalf("Failed to write to transport: %v", err) + } + ctx, cancel := context.WithCancel(context.Background()) + cancel() + err = trans.Flush(ctx) + if err == nil { + t.Fatal("Expected flush error") + } + + _, err = trans.Write(write2) + if err != nil { + t.Fatalf("Failed to write to transport: %v", err) + } + err = trans.Flush(context.Background()) + if err != nil { + t.Fatalf("Failed to flush: %v", err) + } + + data := make([]byte, 1024) + n, err := trans.Read(data) + if err != nil { + t.Fatalf("Failed to read: %v", err) + } + + data = data[:n] + if !bytes.Equal(data, write2) { + t.Fatalf("Received unexpected data: %q, expected: %q", data, write2) + } +} + type customHttpTransport struct { hit bool } From e872b350ab0cfd2402340b8ca82b02dc299db69e Mon Sep 17 00:00:00 2001 From: Jeffrey Han Date: Thu, 24 Sep 2020 10:41:12 -0700 Subject: [PATCH 728/756] THRIFT-5282: Add IPv6 client support to Lua library Client: lua Patch: Jeffrey Han This closes #2243 --- lib/lua/src/luasocket.c | 28 ++++++++---------- lib/lua/src/socket.h | 3 ++ lib/lua/src/usocket.c | 63 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 16 deletions(-) diff --git a/lib/lua/src/luasocket.c b/lib/lua/src/luasocket.c index d48351077bc..6f63d3dbfa1 100644 --- a/lib/lua/src/luasocket.c +++ b/lib/lua/src/luasocket.c @@ -344,22 +344,18 @@ static int l_socket_create_and_connect(lua_State *L) { // Create and connect loop for timeout milliseconds end = __gettime() + timeout/1000; do { - // Create the socket - err = tcp_create(&sock); - if (!err) { - // Connect - err = tcp_connect(&sock, host, port, timeout); - if (err) { - tcp_destroy(&sock); - usleep(100000); // sleep for 100ms - } else { - p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); - settype(L, -2, SOCKET_CLIENT); - socket_setnonblocking(&sock); - tcp->sock = sock; - tcp->timeout = timeout; - return 1; // Return userdata - } + // Create and connect the socket + err = tcp_create_and_connect(&sock, host, port, timeout); + if (err) { + tcp_destroy(&sock); + usleep(100000); // sleep for 100ms + } else { + p_tcp tcp = (p_tcp) lua_newuserdata(L, sizeof(t_tcp)); + settype(L, -2, SOCKET_CLIENT); + socket_setnonblocking(&sock); + tcp->sock = sock; + tcp->timeout = timeout; + return 1; // Return userdata } } while (err && __gettime() < end); diff --git a/lib/lua/src/socket.h b/lib/lua/src/socket.h index afb827e4739..c09eabc1af3 100644 --- a/lib/lua/src/socket.h +++ b/lib/lua/src/socket.h @@ -75,4 +75,7 @@ const char * tcp_accept(p_socket sock, p_socket client, int timeout); const char * tcp_connect(p_socket sock, const char *host, unsigned short port, int timeout); +const char * tcp_create_and_connect(p_socket sock, const char *host, + unsigned short port, int timeout); + #endif diff --git a/lib/lua/src/usocket.c b/lib/lua/src/usocket.c index 7c77651ad8a..21c0bac9e92 100644 --- a/lib/lua/src/usocket.c +++ b/lib/lua/src/usocket.c @@ -283,6 +283,7 @@ T_ERRCODE socket_setblocking(p_socket sock) { return strerror(err) const char * tcp_create(p_socket sock) { + // TODO support IPv6 int err = socket_create(sock, AF_INET, SOCK_STREAM, 0); ERRORSTR_RETURN(err); } @@ -293,6 +294,7 @@ const char * tcp_destroy(p_socket sock) { } const char * tcp_bind(p_socket sock, const char *host, unsigned short port) { + // TODO support IPv6 int err; struct hostent *h; struct sockaddr_in local; @@ -327,6 +329,7 @@ const char * tcp_connect(p_socket sock, const char *host, unsigned short port, int timeout) { + // TODO support IPv6 int err; struct hostent *h; struct sockaddr_in remote; @@ -346,6 +349,66 @@ const char * tcp_connect(p_socket sock, ERRORSTR_RETURN(err); } +const char * tcp_create_and_connect(p_socket sock, + const char *host, + unsigned short port, + int timeout) { + int err; + struct sockaddr_in sa4; + struct sockaddr_in6 sa6; + + memset(&sa4, 0, sizeof(sa4)); + sa4.sin_family = AF_INET; + sa4.sin_port = htons(port); + memset(&sa6, 0, sizeof(sa6)); + sa6.sin6_family = AF_INET6; + sa6.sin6_port = htons(port); + + if (inet_pton(AF_INET, host, &sa4.sin_addr)) { + socket_create(sock, AF_INET, SOCK_STREAM, 0); + err = socket_connect(sock, (p_sa) &sa4, sizeof(sa4), timeout); + ERRORSTR_RETURN(err); + } else if (inet_pton(AF_INET6, host, &sa6.sin6_addr)) { + socket_create(sock, AF_INET6, SOCK_STREAM, 0); + err = socket_connect(sock, (p_sa) &sa6, sizeof(sa6), timeout); + ERRORSTR_RETURN(err); + } else { + struct addrinfo hints, *servinfo, *rp; + char portStr[6]; + int rv; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + sprintf(portStr, "%u", port); + + if ((rv = getaddrinfo(host, portStr, &hints, &servinfo)) != 0) { + return gai_strerror(rv); + } + + err = TIMEOUT; + for (rp = servinfo; rp != NULL; rp = rp->ai_next) { + err = socket_create(sock, rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (err != SUCCESS) { + continue; + } + err = socket_connect(sock, (p_sa) rp->ai_addr, rp->ai_addrlen, timeout); + if (err == SUCCESS) { + break; + } + close(*sock); + } + freeaddrinfo(servinfo); + if (rp == NULL) { + *sock = -1; + return "Failed to connect"; + } else { + ERRORSTR_RETURN(err); + } + } +} + #define WRITE_STEP 8192 const char * tcp_send( p_socket sock, const char * data, size_t w_len, int timeout) { From 1e243a76b186142f551a3cb8419131a468ff54ff Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Wed, 24 Jun 2020 10:57:00 +0200 Subject: [PATCH 729/756] build/cmake/DefineOptions.cmake: Fixed the logic of BUILD_SHARED_LIBS --- build/cmake/DefineOptions.cmake | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build/cmake/DefineOptions.cmake b/build/cmake/DefineOptions.cmake index 8c7a4a9642a..e16e5649c78 100644 --- a/build/cmake/DefineOptions.cmake +++ b/build/cmake/DefineOptions.cmake @@ -132,7 +132,12 @@ CMAKE_DEPENDENT_OPTION(BUILD_HASKELL "Build GHC library" ON # Common library options # https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html # Default on Windows is static, shared mode library support needs work... -CMAKE_DEPENDENT_OPTION(BUILD_SHARED_LIBS "Build shared libraries" OFF "WIN32" ON) +if(WIN32) + set(DEFAULT_BUILD_SHARED_LIBS ON) +else() + set(DEFAULT_BUILD_SHARED_LIBS OFF) +endif() +option(BUILD_SHARED_LIBS "Build shared libraries" ${DEFAULT_BUILD_SHARED_LIBS}) if (WITH_SHARED_LIB) message(WARNING "WITH_SHARED_LIB is deprecated; use -DBUILD_SHARED_LIBS=ON instead") From dda80547b10d698784713eb62a04f6f42eae107b Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Tue, 15 Dec 2020 17:56:15 -0800 Subject: [PATCH 730/756] THRIFT-5324: Create new req buffer for every http request Client: go The fix in https://github.com/apache/thrift/pull/2293 doesn't work for go1.10.8 due to the possibility of data races. This exposes a bigger, underlying issue regarding the ownership of the request buffer in THttpClient between THttpClient itself and the http request it creates. Instead of reset and reuse the same buffer, always give up the ownership of it and create a new buffer after each Flush call. --- lib/go/thrift/http_client.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/lib/go/thrift/http_client.go b/lib/go/thrift/http_client.go index 19c63a98512..26e52b387d7 100644 --- a/lib/go/thrift/http_client.go +++ b/lib/go/thrift/http_client.go @@ -197,15 +197,11 @@ func (p *THttpClient) Flush(ctx context.Context) error { // Close any previous response body to avoid leaking connections. p.closeResponse() - // Request might not have been fully read by http client. - // Reset so we don't send the remains on next call. - defer func() { - if p.requestBuffer != nil { - p.requestBuffer.Reset() - } - }() - - req, err := http.NewRequest("POST", p.url.String(), p.requestBuffer) + // Give up the ownership of the current request buffer to http request, + // and create a new buffer for the next request. + buf := p.requestBuffer + p.requestBuffer = new(bytes.Buffer) + req, err := http.NewRequest("POST", p.url.String(), buf) if err != nil { return NewTTransportExceptionFromError(err) } From 37c2ceb737cb40377346c63a05f407da1c119ba0 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Thu, 10 Dec 2020 14:42:37 -0800 Subject: [PATCH 731/756] THRIFT-5322: Guard against large string/binary lengths in Go Client: go In TBinaryProtocol.ReadString, TBinaryProtocol.ReadBinary, TCompactProtocol.ReadString, and TCompactProtocol.ReadBinary, use safeReadBytes to prevent from large allocation on malformed sizes. $ go test -bench=SafeReadBytes -benchmem BenchmarkSafeReadBytes/normal-12 625057 1789 ns/op 2176 B/op 5 allocs/op BenchmarkSafeReadBytes/max-askedSize-12 545271 2236 ns/op 14464 B/op 7 allocs/op PASS --- lib/go/thrift/binary_protocol.go | 56 ++++------ lib/go/thrift/binary_protocol_test.go | 153 ++++++++++++++++++++++++++ lib/go/thrift/compact_protocol.go | 17 ++- 3 files changed, 184 insertions(+), 42 deletions(-) diff --git a/lib/go/thrift/binary_protocol.go b/lib/go/thrift/binary_protocol.go index c87d23a1bb1..58956f67320 100644 --- a/lib/go/thrift/binary_protocol.go +++ b/lib/go/thrift/binary_protocol.go @@ -432,6 +432,15 @@ func (p *TBinaryProtocol) ReadString(ctx context.Context) (value string, err err err = invalidDataLength return } + if size == 0 { + return "", nil + } + if size < int32(len(p.buffer)) { + // Avoid allocation on small reads + buf := p.buffer[:size] + read, e := io.ReadFull(p.trans, buf) + return string(buf[:read]), NewTProtocolException(e) + } return p.readStringBody(size) } @@ -445,9 +454,7 @@ func (p *TBinaryProtocol) ReadBinary(ctx context.Context) ([]byte, error) { return nil, invalidDataLength } - isize := int(size) - buf := make([]byte, isize) - _, err := io.ReadFull(p.trans, buf) + buf, err := safeReadBytes(size, p.trans) return buf, NewTProtocolException(err) } @@ -479,38 +486,21 @@ func (p *TBinaryProtocol) readAll(ctx context.Context, buf []byte) (err error) { return NewTProtocolException(err) } -const readLimit = 32768 - func (p *TBinaryProtocol) readStringBody(size int32) (value string, err error) { - if size < 0 { - return "", nil - } - - var ( - buf bytes.Buffer - e error - b []byte - ) + buf, err := safeReadBytes(size, p.trans) + return string(buf), NewTProtocolException(err) +} - switch { - case int(size) <= len(p.buffer): - b = p.buffer[:size] // avoids allocation for small reads - case int(size) < readLimit: - b = make([]byte, size) - default: - b = make([]byte, readLimit) +// This function is shared between TBinaryProtocol and TCompactProtocol. +// +// It tries to read size bytes from trans, in a way that prevents large +// allocations when size is insanely large (mostly caused by malformed message). +func safeReadBytes(size int32, trans io.Reader) ([]byte, error) { + if size < 0 { + return nil, nil } - for size > 0 { - _, e = io.ReadFull(p.trans, b) - buf.Write(b) - if e != nil { - break - } - size -= readLimit - if size < readLimit && size > 0 { - b = b[:size] - } - } - return buf.String(), NewTProtocolException(e) + buf := new(bytes.Buffer) + _, err := io.CopyN(buf, trans, int64(size)) + return buf.Bytes(), err } diff --git a/lib/go/thrift/binary_protocol_test.go b/lib/go/thrift/binary_protocol_test.go index 0462cc79dee..88bfd26b7ea 100644 --- a/lib/go/thrift/binary_protocol_test.go +++ b/lib/go/thrift/binary_protocol_test.go @@ -20,9 +20,162 @@ package thrift import ( + "bytes" + "math" + "strings" "testing" ) func TestReadWriteBinaryProtocol(t *testing.T) { ReadWriteProtocolTest(t, NewTBinaryProtocolFactoryDefault()) } + +const ( + safeReadBytesSource = ` +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer sit amet +tincidunt nibh. Phasellus vel convallis libero, sit amet posuere quam. Nullam +blandit velit at nibh fringilla, sed egestas erat dapibus. Sed hendrerit +tincidunt accumsan. Curabitur consectetur bibendum dui nec hendrerit. Fusce quis +turpis nec magna efficitur volutpat a ut nibh. Vestibulum odio risus, tristique +a nisi et, congue mattis mi. Vivamus a nunc justo. Mauris molestie sagittis +magna, hendrerit auctor lectus egestas non. Phasellus pretium, odio sit amet +bibendum feugiat, velit nunc luctus erat, ac bibendum mi dui molestie nulla. +Nullam fermentum magna eu elit vehicula tincidunt. Etiam ornare laoreet +dignissim. Ut sed nunc ac neque vulputate fermentum. Morbi volutpat dapibus +magna, at porttitor quam facilisis a. Donec eget fermentum risus. Aliquam erat +volutpat. + +Phasellus molestie id ante vel iaculis. Fusce eget quam nec quam viverra laoreet +vitae a dui. Mauris blandit blandit dui, iaculis interdum diam mollis at. Morbi +vel sem et. +` + safeReadBytesSourceLen = len(safeReadBytesSource) +) + +func TestSafeReadBytes(t *testing.T) { + srcData := []byte(safeReadBytesSource) + + for _, c := range []struct { + label string + askedSize int32 + dataSize int + }{ + { + label: "normal", + askedSize: 100, + dataSize: 100, + }, + { + label: "max-askedSize", + askedSize: math.MaxInt32, + dataSize: safeReadBytesSourceLen, + }, + } { + t.Run(c.label, func(t *testing.T) { + data := bytes.NewReader(srcData[:c.dataSize]) + buf, err := safeReadBytes(c.askedSize, data) + if len(buf) != c.dataSize { + t.Errorf( + "Expected to read %d bytes, got %d", + c.dataSize, + len(buf), + ) + } + if !strings.HasPrefix(safeReadBytesSource, string(buf)) { + t.Errorf("Unexpected read data: %q", buf) + } + if int32(c.dataSize) < c.askedSize { + // We expect error in this case + if err == nil { + t.Errorf( + "Expected error when dataSize %d < askedSize %d, got nil", + c.dataSize, + c.askedSize, + ) + } + } else { + // We expect no error in this case + if err != nil { + t.Errorf( + "Expected no error when dataSize %d >= askedSize %d, got: %v", + c.dataSize, + c.askedSize, + err, + ) + } + } + }) + } +} + +func generateSafeReadBytesBenchmark(askedSize int32, dataSize int) func(b *testing.B) { + return func(b *testing.B) { + data := make([]byte, dataSize) + b.ResetTimer() + for i := 0; i < b.N; i++ { + safeReadBytes(askedSize, bytes.NewReader(data)) + } + } +} + +func TestSafeReadBytesAlloc(t *testing.T) { + if testing.Short() { + // NOTE: Since this test runs a benchmark test, it takes at + // least 1 second. + // + // In general we try to avoid unit tests taking that long to run, + // but it's to verify a security issue so we made an exception + // here: + // https://issues.apache.org/jira/browse/THRIFT-5322 + t.Skip("skipping test in short mode.") + } + + const ( + askedSize = int32(math.MaxInt32) + dataSize = 4096 + ) + + // The purpose of this test is that in the case a string header says + // that it has a string askedSize bytes long, the implementation should + // not just allocate askedSize bytes upfront. So when there're actually + // not enough data to be read (dataSize), the actual allocated bytes + // should be somewhere between dataSize and askedSize. + // + // Different approachs could have different memory overheads, so this + // target is arbitrary in nature. But when dataSize is small enough + // compare to askedSize, half the askedSize is a good and safe target. + const target = int64(askedSize) / 2 + + bm := testing.Benchmark(generateSafeReadBytesBenchmark(askedSize, dataSize)) + actual := bm.AllocedBytesPerOp() + if actual > target { + t.Errorf( + "Expected allocated bytes per op to be <= %d, got %d", + target, + actual, + ) + } else { + t.Logf("Allocated bytes: %d B/op", actual) + } +} + +func BenchmarkSafeReadBytes(b *testing.B) { + for _, c := range []struct { + label string + askedSize int32 + dataSize int + }{ + { + label: "normal", + askedSize: 100, + dataSize: 100, + }, + { + label: "max-askedSize", + askedSize: math.MaxInt32, + dataSize: 4096, + }, + } { + b.Run(c.label, generateSafeReadBytesBenchmark(c.askedSize, c.dataSize)) + } +} diff --git a/lib/go/thrift/compact_protocol.go b/lib/go/thrift/compact_protocol.go index a0161959c8c..424906d616b 100644 --- a/lib/go/thrift/compact_protocol.go +++ b/lib/go/thrift/compact_protocol.go @@ -579,17 +579,17 @@ func (p *TCompactProtocol) ReadString(ctx context.Context) (value string, err er if length < 0 { return "", invalidDataLength } - if length == 0 { return "", nil } - var buf []byte - if length <= int32(len(p.buffer)) { - buf = p.buffer[0:length] - } else { - buf = make([]byte, length) + if length < int32(len(p.buffer)) { + // Avoid allocation on small reads + buf := p.buffer[:length] + read, e := io.ReadFull(p.trans, buf) + return string(buf[:read]), NewTProtocolException(e) } - _, e = io.ReadFull(p.trans, buf) + + buf, e := safeReadBytes(length, p.trans) return string(buf), NewTProtocolException(e) } @@ -606,8 +606,7 @@ func (p *TCompactProtocol) ReadBinary(ctx context.Context) (value []byte, err er return nil, invalidDataLength } - buf := make([]byte, length) - _, e = io.ReadFull(p.trans, buf) + buf, e := safeReadBytes(length, p.trans) return buf, NewTProtocolException(e) } From 3b9259d88b6ceb13bb6b8c6afe676fed707dcd4e Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Thu, 19 Nov 2020 10:24:25 +0100 Subject: [PATCH 732/756] TServerSocket.cpp::isOpen(): Check that a domain socket file already exists --- .../src/thrift/transport/TServerSocket.cpp | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/lib/cpp/src/thrift/transport/TServerSocket.cpp b/lib/cpp/src/thrift/transport/TServerSocket.cpp index 0a47b3fe0f4..0c32b106e8f 100644 --- a/lib/cpp/src/thrift/transport/TServerSocket.cpp +++ b/lib/cpp/src/thrift/transport/TServerSocket.cpp @@ -43,6 +43,9 @@ #ifdef HAVE_UNISTD_H #include #endif +#ifdef HAVE_SYS_STAT_H +#include +#endif #include #include @@ -62,6 +65,16 @@ #endif // _WIN32 #endif +#ifdef _WIN32 +// Including Windows.h can conflict with Winsock2 usage, and also +// adds problematic macros like min() and max(). Try to work around: +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN +#include +#undef NOMINMAX +#undef WIN32_LEAN_AND_MEAN +#endif + template inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) { return reinterpret_cast(v); @@ -174,6 +187,25 @@ bool TServerSocket::isOpen() const { if (!listening_) return false; + if (!path_.empty() && (path_[0] != '\0')) { + // On some platforms the domain socket file may not be instantly + // available yet, i.e. the Windows file system can be slow. Therefore + // we should check that the domain socket file actually exists. +#ifdef _MSC_VER + // Currently there is a bug in ClangCl on Windows so the stat() call + // does not work. Workaround is a Windows-specific call if file exists: + DWORD const f_attrib = GetFileAttributesA(path_.c_str()); + if (f_attrib == INVALID_FILE_ATTRIBUTES) { +#else + struct THRIFT_STAT path_info; + if (::THRIFT_STAT(path_.c_str(), &path_info) < 0) { +#endif + const std::string vError = "TServerSocket::isOpen(): The domain socket path '" + path_ + "' does not exist (yet)."; + GlobalOutput.perror(vError.c_str(), THRIFT_GET_SOCKET_ERROR); + return false; + } + } + return true; } From 13662dd7be9aa3ffdbbc49bd1c3b77c4549569bd Mon Sep 17 00:00:00 2001 From: Jeffrey Han Date: Thu, 17 Dec 2020 13:12:10 -0800 Subject: [PATCH 733/756] THRIFT-5325: Fix Lua library writeStructEnd() in TCompactProtocol Client: lua Patch: Jeffrey Han This closes #2297 --- lib/lua/TCompactProtocol.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/lua/TCompactProtocol.lua b/lib/lua/TCompactProtocol.lua index 0ebccac7a96..8ec7b3a2c0c 100644 --- a/lib/lua/TCompactProtocol.lua +++ b/lib/lua/TCompactProtocol.lua @@ -124,8 +124,8 @@ function TCompactProtocol:writeStructBegin(name) end function TCompactProtocol:writeStructEnd() - self.lastFieldId = self.lastField[self.lastFieldIndex] self.lastFieldIndex = self.lastFieldIndex - 1 + self.lastFieldId = self.lastField[self.lastFieldIndex] end function TCompactProtocol:writeFieldBegin(name, ttype, id) From 1c35d6ba954bc441e9e603599965e0121eb5132d Mon Sep 17 00:00:00 2001 From: Neil Williams Date: Mon, 4 Jan 2021 11:27:01 -0800 Subject: [PATCH 734/756] THRIFT-5331: Py: make THeader subprotocol configurable (#2302) Client: py This allows clients to choose which subprotocol (TBinary/TCompact) to frame with headers. The server will already accept either protocol and reply correctly. --- lib/py/src/protocol/THeaderProtocol.py | 17 ++++++++++++----- lib/py/src/transport/THeaderTransport.py | 4 ++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/lib/py/src/protocol/THeaderProtocol.py b/lib/py/src/protocol/THeaderProtocol.py index 13982e898f2..4b58e639da2 100644 --- a/lib/py/src/protocol/THeaderProtocol.py +++ b/lib/py/src/protocol/THeaderProtocol.py @@ -35,7 +35,9 @@ class THeaderProtocol(TProtocolBase): THeaderProtocol frames other Thrift protocols and adds support for optional out-of-band headers. The currently supported subprotocols are - TBinaryProtocol and TCompactProtocol. + TBinaryProtocol and TCompactProtocol. When used as a client, the + subprotocol to frame can be chosen with the `default_protocol` parameter to + the constructor. It's also possible to apply transforms to the encoded message payload. The only transform currently supported is to gzip. @@ -53,14 +55,14 @@ class THeaderProtocol(TProtocolBase): """ - def __init__(self, transport, allowed_client_types): + def __init__(self, transport, allowed_client_types, default_protocol=THeaderSubprotocolID.BINARY): # much of the actual work for THeaderProtocol happens down in # THeaderTransport since we need to do low-level shenanigans to detect # if the client is sending us headers or one of the headerless formats # we support. this wraps the real transport with the one that does all # the magic. if not isinstance(transport, THeaderTransport): - transport = THeaderTransport(transport, allowed_client_types) + transport = THeaderTransport(transport, allowed_client_types, default_protocol) super(THeaderProtocol, self).__init__(transport) self._set_protocol() @@ -218,8 +220,13 @@ def readBinary(self): class THeaderProtocolFactory(TProtocolFactory): - def __init__(self, allowed_client_types=(THeaderClientType.HEADERS,)): + def __init__( + self, + allowed_client_types=(THeaderClientType.HEADERS,), + default_protocol=THeaderSubprotocolID.BINARY, + ): self.allowed_client_types = allowed_client_types + self.default_protocol = default_protocol def getProtocol(self, trans): - return THeaderProtocol(trans, self.allowed_client_types) + return THeaderProtocol(trans, self.allowed_client_types, self.default_protocol) diff --git a/lib/py/src/transport/THeaderTransport.py b/lib/py/src/transport/THeaderTransport.py index c0d56401229..7c9827ba3a9 100644 --- a/lib/py/src/transport/THeaderTransport.py +++ b/lib/py/src/transport/THeaderTransport.py @@ -87,7 +87,7 @@ def _writeString(trans, value): class THeaderTransport(TTransportBase, CReadableTransport): - def __init__(self, transport, allowed_client_types): + def __init__(self, transport, allowed_client_types, default_protocol=THeaderSubprotocolID.BINARY): self._transport = transport self._client_type = THeaderClientType.HEADERS self._allowed_client_types = allowed_client_types @@ -101,7 +101,7 @@ def __init__(self, transport, allowed_client_types): self.flags = 0 self.sequence_id = 0 - self._protocol_id = THeaderSubprotocolID.BINARY + self._protocol_id = default_protocol self._max_frame_size = HARD_MAX_FRAME_SIZE def isOpen(self): From c4e899a6d64aa97430ec9f7608d38db2095f6159 Mon Sep 17 00:00:00 2001 From: zeshuai007 <51382517@qq.com> Date: Tue, 5 Jan 2021 16:51:10 +0800 Subject: [PATCH 735/756] try fix appveyor ci --- build/appveyor/MING-appveyor-install.bat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/appveyor/MING-appveyor-install.bat b/build/appveyor/MING-appveyor-install.bat index 4d49d4089aa..862cb1c051f 100644 --- a/build/appveyor/MING-appveyor-install.bat +++ b/build/appveyor/MING-appveyor-install.bat @@ -55,5 +55,5 @@ SET PACKAGES=^ %BASH% -lc "pacman --noconfirm -U --config <(echo) msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" || EXIT /B :: Upgrade things %BASH% -lc "pacman --noconfirm -Sy" || EXIT /B -%BASH% -lc "pacman --noconfirm -Sydd pacman" || EXIT /B +%BASH% -lc "pacman --noconfirm -Udd https://repo.msys2.org/msys/x86_64/pacman-5.2.2-5-x86_64.pkg.tar.xz" || EXIT /B %BASH% -lc "pacman --noconfirm %PACKAGES%" || EXIT /B From c4d1c0d80067986dbee124887bcb402ee1c6538e Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Wed, 16 Dec 2020 17:10:48 -0800 Subject: [PATCH 736/756] THRIFT-5322: Implement TConfiguration in Go library Client: go Define TConfiguration following the spec, and also move the following configurations scattered around different TTransport/TProtocol into it: - connect and socket timeouts for TSocket and TSSLSocket - tls config for TSSLSocket - max frame size for TFramedTransport - strict read and strict write for TBinaryProtocol - proto id for THeaderTransport Also add TConfiguration support for the following and their factories: - THeaderTransport and THeaderProtocol - TBinaryProtocol - TCompactProtocol - TFramedTransport - TSocket - TSSLSocket Also define TConfigurationSetter interface for easier TConfiguration propagation between wrapped TTransports/TProtocols , and add implementations to the following for propagation (they don't use anything from TConfiguration themselves): - StreamTransport - TBufferedTransport - TDebugProtocol - TJSONProtocol - TSimpleJSONProtocol - TZlibTransport TConfigurationSetter are not implemented by the factories of the "propagation only" TTransports/TProtocols, if they have a factory. For those use cases, TTransportFactoryConf and TProtocolFactoryConf are provided to wrap a factory with the ability to propagate TConfiguration. Also add simple sanity check for TBinaryProtocol and TCompactProtocol's ReadString and ReadBinary functions. Currently it only report error if the header length is larger than MaxMessageSize configured in TConfiguration, for simplicity. --- CHANGES.md | 1 + lib/go/thrift/binary_protocol.go | 75 ++++- lib/go/thrift/buffered_transport.go | 7 + lib/go/thrift/compact_protocol.go | 61 +++- lib/go/thrift/configuration.go | 378 +++++++++++++++++++++++++ lib/go/thrift/configuration_test.go | 338 ++++++++++++++++++++++ lib/go/thrift/debug_protocol.go | 8 + lib/go/thrift/framed_transport.go | 74 ++++- lib/go/thrift/header_protocol.go | 93 +++--- lib/go/thrift/header_protocol_test.go | 8 +- lib/go/thrift/header_transport.go | 103 ++++--- lib/go/thrift/header_transport_test.go | 24 +- lib/go/thrift/iostream_transport.go | 8 + lib/go/thrift/json_protocol.go | 2 + lib/go/thrift/simple_json_protocol.go | 7 + lib/go/thrift/socket.go | 103 +++++-- lib/go/thrift/ssl_socket.go | 119 +++++--- lib/go/thrift/zlib_transport.go | 7 + 18 files changed, 1234 insertions(+), 182 deletions(-) create mode 100644 lib/go/thrift/configuration.go create mode 100644 lib/go/thrift/configuration_test.go diff --git a/CHANGES.md b/CHANGES.md index 65ed07f5066..663c4c18c92 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -29,6 +29,7 @@ - [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - Add ProcessorMiddleware function type and WrapProcessor function to support wrapping a TProcessor with middleware functions. - [THRIFT-5233](https://issues.apache.org/jira/browse/THRIFT-5233) - Add context deadline check to ReadMessageBegin in TBinaryProtocol, TCompactProtocol, and THeaderProtocol. - [THRIFT-5240](https://issues.apache.org/jira/browse/THRIFT-5240) - The context passed into server handler implementations will be canceled when we detected that the client closed the connection. +- [THRIFT-5322](https://issues.apache.org/jira/browse/THRIFT-5322) - Add support to TConfiguration, and also fix a bug that could cause excessive memory usage when reading malformed messages from TCompactProtocol. ## 0.13.0 diff --git a/lib/go/thrift/binary_protocol.go b/lib/go/thrift/binary_protocol.go index 58956f67320..45c880d32f8 100644 --- a/lib/go/thrift/binary_protocol.go +++ b/lib/go/thrift/binary_protocol.go @@ -32,22 +32,37 @@ import ( type TBinaryProtocol struct { trans TRichTransport origTransport TTransport - strictRead bool - strictWrite bool + cfg *TConfiguration buffer [64]byte } type TBinaryProtocolFactory struct { - strictRead bool - strictWrite bool + cfg *TConfiguration } +// Deprecated: Use NewTBinaryProtocolConf instead. func NewTBinaryProtocolTransport(t TTransport) *TBinaryProtocol { - return NewTBinaryProtocol(t, false, true) + return NewTBinaryProtocolConf(t, &TConfiguration{ + noPropagation: true, + }) } +// Deprecated: Use NewTBinaryProtocolConf instead. func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProtocol { - p := &TBinaryProtocol{origTransport: t, strictRead: strictRead, strictWrite: strictWrite} + return NewTBinaryProtocolConf(t, &TConfiguration{ + TBinaryStrictRead: &strictRead, + TBinaryStrictWrite: &strictWrite, + + noPropagation: true, + }) +} + +func NewTBinaryProtocolConf(t TTransport, conf *TConfiguration) *TBinaryProtocol { + PropagateTConfiguration(t, conf) + p := &TBinaryProtocol{ + origTransport: t, + cfg: conf, + } if et, ok := t.(TRichTransport); ok { p.trans = et } else { @@ -56,16 +71,35 @@ func NewTBinaryProtocol(t TTransport, strictRead, strictWrite bool) *TBinaryProt return p } +// Deprecated: Use NewTBinaryProtocolFactoryConf instead. func NewTBinaryProtocolFactoryDefault() *TBinaryProtocolFactory { - return NewTBinaryProtocolFactory(false, true) + return NewTBinaryProtocolFactoryConf(&TConfiguration{ + noPropagation: true, + }) } +// Deprecated: Use NewTBinaryProtocolFactoryConf instead. func NewTBinaryProtocolFactory(strictRead, strictWrite bool) *TBinaryProtocolFactory { - return &TBinaryProtocolFactory{strictRead: strictRead, strictWrite: strictWrite} + return NewTBinaryProtocolFactoryConf(&TConfiguration{ + TBinaryStrictRead: &strictRead, + TBinaryStrictWrite: &strictWrite, + + noPropagation: true, + }) +} + +func NewTBinaryProtocolFactoryConf(conf *TConfiguration) *TBinaryProtocolFactory { + return &TBinaryProtocolFactory{ + cfg: conf, + } } func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol { - return NewTBinaryProtocol(t, p.strictRead, p.strictWrite) + return NewTBinaryProtocolConf(t, p.cfg) +} + +func (p *TBinaryProtocolFactory) SetTConfiguration(conf *TConfiguration) { + p.cfg = conf } /** @@ -73,7 +107,7 @@ func (p *TBinaryProtocolFactory) GetProtocol(t TTransport) TProtocol { */ func (p *TBinaryProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqId int32) error { - if p.strictWrite { + if p.cfg.GetTBinaryStrictWrite() { version := uint32(VERSION_1) | uint32(typeId) e := p.WriteI32(ctx, int32(version)) if e != nil { @@ -253,7 +287,7 @@ func (p *TBinaryProtocol) ReadMessageBegin(ctx context.Context) (name string, ty } return name, typeId, seqId, nil } - if p.strictRead { + if p.cfg.GetTBinaryStrictRead() { return name, typeId, seqId, NewTProtocolExceptionWithType(BAD_VERSION, fmt.Errorf("Missing version in ReadMessageBegin")) } name, e2 := p.readStringBody(size) @@ -428,6 +462,10 @@ func (p *TBinaryProtocol) ReadString(ctx context.Context) (value string, err err if e != nil { return "", e } + err = checkSizeForProtocol(size, p.cfg) + if err != nil { + return + } if size < 0 { err = invalidDataLength return @@ -450,8 +488,8 @@ func (p *TBinaryProtocol) ReadBinary(ctx context.Context) ([]byte, error) { if e != nil { return nil, e } - if size < 0 { - return nil, invalidDataLength + if err := checkSizeForProtocol(size, p.cfg); err != nil { + return nil, err } buf, err := safeReadBytes(size, p.trans) @@ -491,6 +529,17 @@ func (p *TBinaryProtocol) readStringBody(size int32) (value string, err error) { return string(buf), NewTProtocolException(err) } +func (p *TBinaryProtocol) SetTConfiguration(conf *TConfiguration) { + PropagateTConfiguration(p.trans, conf) + PropagateTConfiguration(p.origTransport, conf) + p.cfg = conf +} + +var ( + _ TConfigurationSetter = (*TBinaryProtocolFactory)(nil) + _ TConfigurationSetter = (*TBinaryProtocol)(nil) +) + // This function is shared between TBinaryProtocol and TCompactProtocol. // // It tries to read size bytes from trans, in a way that prevents large diff --git a/lib/go/thrift/buffered_transport.go b/lib/go/thrift/buffered_transport.go index 96702061b2f..aa551b4ab37 100644 --- a/lib/go/thrift/buffered_transport.go +++ b/lib/go/thrift/buffered_transport.go @@ -90,3 +90,10 @@ func (p *TBufferedTransport) Flush(ctx context.Context) error { func (p *TBufferedTransport) RemainingBytes() (num_bytes uint64) { return p.tp.RemainingBytes() } + +// SetTConfiguration implements TConfigurationSetter for propagation. +func (p *TBufferedTransport) SetTConfiguration(conf *TConfiguration) { + PropagateTConfiguration(p.tp, conf) +} + +var _ TConfigurationSetter = (*TBufferedTransport)(nil) diff --git a/lib/go/thrift/compact_protocol.go b/lib/go/thrift/compact_protocol.go index 424906d616b..25e6d0ccd6e 100644 --- a/lib/go/thrift/compact_protocol.go +++ b/lib/go/thrift/compact_protocol.go @@ -75,20 +75,37 @@ func init() { } } -type TCompactProtocolFactory struct{} +type TCompactProtocolFactory struct { + cfg *TConfiguration +} +// Deprecated: Use NewTCompactProtocolFactoryConf instead. func NewTCompactProtocolFactory() *TCompactProtocolFactory { - return &TCompactProtocolFactory{} + return NewTCompactProtocolFactoryConf(&TConfiguration{ + noPropagation: true, + }) +} + +func NewTCompactProtocolFactoryConf(conf *TConfiguration) *TCompactProtocolFactory { + return &TCompactProtocolFactory{ + cfg: conf, + } } func (p *TCompactProtocolFactory) GetProtocol(trans TTransport) TProtocol { - return NewTCompactProtocol(trans) + return NewTCompactProtocolConf(trans, p.cfg) +} + +func (p *TCompactProtocolFactory) SetTConfiguration(conf *TConfiguration) { + p.cfg = conf } type TCompactProtocol struct { trans TRichTransport origTransport TTransport + cfg *TConfiguration + // Used to keep track of the last field for the current and previous structs, // so we can do the delta stuff. lastField []int @@ -107,9 +124,19 @@ type TCompactProtocol struct { buffer [64]byte } -// Create a TCompactProtocol given a TTransport +// Deprecated: Use NewTCompactProtocolConf instead. func NewTCompactProtocol(trans TTransport) *TCompactProtocol { - p := &TCompactProtocol{origTransport: trans, lastField: []int{}} + return NewTCompactProtocolConf(trans, &TConfiguration{ + noPropagation: true, + }) +} + +func NewTCompactProtocolConf(trans TTransport, conf *TConfiguration) *TCompactProtocol { + PropagateTConfiguration(trans, conf) + p := &TCompactProtocol{ + origTransport: trans, + cfg: conf, + } if et, ok := trans.(TRichTransport); ok { p.trans = et } else { @@ -117,7 +144,6 @@ func NewTCompactProtocol(trans TTransport) *TCompactProtocol { } return p - } // @@ -576,8 +602,9 @@ func (p *TCompactProtocol) ReadString(ctx context.Context) (value string, err er if e != nil { return "", NewTProtocolException(e) } - if length < 0 { - return "", invalidDataLength + err = checkSizeForProtocol(length, p.cfg) + if err != nil { + return } if length == 0 { return "", nil @@ -599,12 +626,13 @@ func (p *TCompactProtocol) ReadBinary(ctx context.Context) (value []byte, err er if e != nil { return nil, NewTProtocolException(e) } + err = checkSizeForProtocol(length, p.cfg) + if err != nil { + return + } if length == 0 { return []byte{}, nil } - if length < 0 { - return nil, invalidDataLength - } buf, e := safeReadBytes(length, p.trans) return buf, NewTProtocolException(e) @@ -824,3 +852,14 @@ func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) { func (p *TCompactProtocol) getCompactType(t TType) tCompactType { return ttypeToCompactType[t] } + +func (p *TCompactProtocol) SetTConfiguration(conf *TConfiguration) { + PropagateTConfiguration(p.trans, conf) + PropagateTConfiguration(p.origTransport, conf) + p.cfg = conf +} + +var ( + _ TConfigurationSetter = (*TCompactProtocolFactory)(nil) + _ TConfigurationSetter = (*TCompactProtocol)(nil) +) diff --git a/lib/go/thrift/configuration.go b/lib/go/thrift/configuration.go new file mode 100644 index 00000000000..454d9f37748 --- /dev/null +++ b/lib/go/thrift/configuration.go @@ -0,0 +1,378 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "crypto/tls" + "fmt" + "time" +) + +// Default TConfiguration values. +const ( + DEFAULT_MAX_MESSAGE_SIZE = 100 * 1024 * 1024 + DEFAULT_MAX_FRAME_SIZE = 16384000 + + DEFAULT_TBINARY_STRICT_READ = false + DEFAULT_TBINARY_STRICT_WRITE = true + + DEFAULT_CONNECT_TIMEOUT = 0 + DEFAULT_SOCKET_TIMEOUT = 0 +) + +// TConfiguration defines some configurations shared between TTransport, +// TProtocol, TTransportFactory, TProtocolFactory, and other implementations. +// +// When constructing TConfiguration, you only need to specify the non-default +// fields. All zero values have sane default values. +// +// Not all configurations defined are applicable to all implementations. +// Implementations are free to ignore the configurations not applicable to them. +// +// All functions attached to this type are nil-safe. +// +// See [1] for spec. +// +// NOTE: When using TConfiguration, fill in all the configurations you want to +// set across the stack, not only the ones you want to set in the immediate +// TTransport/TProtocol. +// +// For example, say you want to migrate this old code into using TConfiguration: +// +// sccket := thrift.NewTSocketTimeout("host:port", time.Second) +// transFactory := thrift.NewTFramedTransportFactoryMaxLength( +// thrift.NewTTransportFactory(), +// 1024 * 1024 * 256, +// ) +// protoFactory := thrift.NewTBinaryProtocolFactory(true, true) +// +// This is the wrong way to do it because in the end the TConfiguration used by +// socket and transFactory will be overwritten by the one used by protoFactory +// because of TConfiguration propagation: +// +// // bad example, DO NOT USE +// sccket := thrift.NewTSocketConf("host:port", &thrift.TConfiguration{ +// ConnectTimeout: time.Second, +// SocketTimeout: time.Second, +// }) +// transFactory := thrift.NewTFramedTransportFactoryConf( +// thrift.NewTTransportFactory(), +// &thrift.TConfiguration{ +// MaxFrameSize: 1024 * 1024 * 256, +// }, +// ) +// protoFactory := thrift.NewTBinaryProtocolFactoryConf(&thrift.TConfiguration{ +// TBinaryStrictRead: thrift.BoolPtr(true), +// TBinaryStrictWrite: thrift.BoolPtr(true), +// }) +// +// This is the correct way to do it: +// +// conf := &thrift.TConfiguration{ +// ConnectTimeout: time.Second, +// SocketTimeout: time.Second, +// +// MaxFrameSize: 1024 * 1024 * 256, +// +// TBinaryStrictRead: thrift.BoolPtr(true), +// TBinaryStrictWrite: thrift.BoolPtr(true), +// } +// sccket := thrift.NewTSocketConf("host:port", conf) +// transFactory := thrift.NewTFramedTransportFactoryConf(thrift.NewTTransportFactory(), conf) +// protoFactory := thrift.NewTBinaryProtocolFactoryConf(conf) +// +// [1]: https://github.com/apache/thrift/blob/master/doc/specs/thrift-tconfiguration.md +type TConfiguration struct { + // If <= 0, DEFAULT_MAX_MESSAGE_SIZE will be used instead. + MaxMessageSize int32 + + // If <= 0, DEFAULT_MAX_FRAME_SIZE will be used instead. + // + // Also if MaxMessageSize < MaxFrameSize, + // MaxMessageSize will be used instead. + MaxFrameSize int32 + + // Connect and socket timeouts to be used by TSocket and TSSLSocket. + // + // 0 means no timeout. + // + // If <0, DEFAULT_CONNECT_TIMEOUT and DEFAULT_SOCKET_TIMEOUT will be + // used. + ConnectTimeout time.Duration + SocketTimeout time.Duration + + // TLS config to be used by TSSLSocket. + TLSConfig *tls.Config + + // Strict read/write configurations for TBinaryProtocol. + // + // BoolPtr helper function is available to use literal values. + TBinaryStrictRead *bool + TBinaryStrictWrite *bool + + // The wrapped protocol id to be used in THeader transport/protocol. + // + // THeaderProtocolIDPtr and THeaderProtocolIDPtrMust helper functions + // are provided to help filling this value. + THeaderProtocolID *THeaderProtocolID + + // Used internally by deprecated constructors, to avoid overriding + // underlying TTransport/TProtocol's cfg by accidental propagations. + // + // For external users this is always false. + noPropagation bool +} + +// GetMaxMessageSize returns the max message size an implementation should +// follow. +// +// It's nil-safe. DEFAULT_MAX_MESSAGE_SIZE will be returned if tc is nil. +func (tc *TConfiguration) GetMaxMessageSize() int32 { + if tc == nil || tc.MaxMessageSize <= 0 { + return DEFAULT_MAX_MESSAGE_SIZE + } + return tc.MaxMessageSize +} + +// GetMaxFrameSize returns the max frame size an implementation should follow. +// +// It's nil-safe. DEFAULT_MAX_FRAME_SIZE will be returned if tc is nil. +// +// If the configured max message size is smaller than the configured max frame +// size, the smaller one will be returned instead. +func (tc *TConfiguration) GetMaxFrameSize() int32 { + if tc == nil { + return DEFAULT_MAX_FRAME_SIZE + } + maxFrameSize := tc.MaxFrameSize + if maxFrameSize <= 0 { + maxFrameSize = DEFAULT_MAX_FRAME_SIZE + } + if maxMessageSize := tc.GetMaxMessageSize(); maxMessageSize < maxFrameSize { + return maxMessageSize + } + return maxFrameSize +} + +// GetConnectTimeout returns the connect timeout should be used by TSocket and +// TSSLSocket. +// +// It's nil-safe. If tc is nil, DEFAULT_CONNECT_TIMEOUT will be returned instead. +func (tc *TConfiguration) GetConnectTimeout() time.Duration { + if tc == nil || tc.ConnectTimeout < 0 { + return DEFAULT_CONNECT_TIMEOUT + } + return tc.ConnectTimeout +} + +// GetSocketTimeout returns the socket timeout should be used by TSocket and +// TSSLSocket. +// +// It's nil-safe. If tc is nil, DEFAULT_SOCKET_TIMEOUT will be returned instead. +func (tc *TConfiguration) GetSocketTimeout() time.Duration { + if tc == nil || tc.SocketTimeout < 0 { + return DEFAULT_SOCKET_TIMEOUT + } + return tc.SocketTimeout +} + +// GetTLSConfig returns the tls config should be used by TSSLSocket. +// +// It's nil-safe. If tc is nil, nil will be returned instead. +func (tc *TConfiguration) GetTLSConfig() *tls.Config { + if tc == nil { + return nil + } + return tc.TLSConfig +} + +// GetTBinaryStrictRead returns the strict read configuration TBinaryProtocol +// should follow. +// +// It's nil-safe. DEFAULT_TBINARY_STRICT_READ will be returned if either tc or +// tc.TBinaryStrictRead is nil. +func (tc *TConfiguration) GetTBinaryStrictRead() bool { + if tc == nil || tc.TBinaryStrictRead == nil { + return DEFAULT_TBINARY_STRICT_READ + } + return *tc.TBinaryStrictRead +} + +// GetTBinaryStrictWrite returns the strict read configuration TBinaryProtocol +// should follow. +// +// It's nil-safe. DEFAULT_TBINARY_STRICT_WRITE will be returned if either tc or +// tc.TBinaryStrictWrite is nil. +func (tc *TConfiguration) GetTBinaryStrictWrite() bool { + if tc == nil || tc.TBinaryStrictWrite == nil { + return DEFAULT_TBINARY_STRICT_WRITE + } + return *tc.TBinaryStrictWrite +} + +// GetTHeaderProtocolID returns the THeaderProtocolID should be used by +// THeaderProtocol clients (for servers, they always use the same one as the +// client instead). +// +// It's nil-safe. If either tc or tc.THeaderProtocolID is nil, +// THeaderProtocolDefault will be returned instead. +// THeaderProtocolDefault will also be returned if configured value is invalid. +func (tc *TConfiguration) GetTHeaderProtocolID() THeaderProtocolID { + if tc == nil || tc.THeaderProtocolID == nil { + return THeaderProtocolDefault + } + protoID := *tc.THeaderProtocolID + if err := protoID.Validate(); err != nil { + return THeaderProtocolDefault + } + return protoID +} + +// THeaderProtocolIDPtr validates and returns the pointer to id. +// +// If id is not a valid THeaderProtocolID, a pointer to THeaderProtocolDefault +// and the validation error will be returned. +func THeaderProtocolIDPtr(id THeaderProtocolID) (*THeaderProtocolID, error) { + err := id.Validate() + if err != nil { + id = THeaderProtocolDefault + } + return &id, err +} + +// THeaderProtocolIDPtrMust validates and returns the pointer to id. +// +// It's similar to THeaderProtocolIDPtr, but it panics on validation errors +// instead of returning them. +func THeaderProtocolIDPtrMust(id THeaderProtocolID) *THeaderProtocolID { + ptr, err := THeaderProtocolIDPtr(id) + if err != nil { + panic(err) + } + return ptr +} + +// TConfigurationSetter is an optional interface TProtocol, TTransport, +// TProtocolFactory, TTransportFactory, and other implementations can implement. +// +// It's intended to be called during intializations. +// The behavior of calling SetTConfiguration on a TTransport/TProtocol in the +// middle of a message is undefined: +// It may or may not change the behavior of the current processing message, +// and it may even cause the current message to fail. +// +// Note for implementations: SetTConfiguration might be called multiple times +// with the same value in quick successions due to the implementation of the +// propagation. Implementations should make SetTConfiguration as simple as +// possible (usually just overwrite the stored configuration and propagate it to +// the wrapped TTransports/TProtocols). +type TConfigurationSetter interface { + SetTConfiguration(*TConfiguration) +} + +// PropagateTConfiguration propagates cfg to impl if impl implements +// TConfigurationSetter and cfg is non-nil, otherwise it does nothing. +// +// NOTE: nil cfg is not propagated. If you want to propagate a TConfiguration +// with everything being default value, use &TConfiguration{} explicitly instead. +func PropagateTConfiguration(impl interface{}, cfg *TConfiguration) { + if cfg == nil || cfg.noPropagation { + return + } + + if setter, ok := impl.(TConfigurationSetter); ok { + setter.SetTConfiguration(cfg) + } +} + +func checkSizeForProtocol(size int32, cfg *TConfiguration) error { + if size < 0 { + return NewTProtocolExceptionWithType( + NEGATIVE_SIZE, + fmt.Errorf("negative size: %d", size), + ) + } + if size > cfg.GetMaxMessageSize() { + return NewTProtocolExceptionWithType( + SIZE_LIMIT, + fmt.Errorf("size exceeded max allowed: %d", size), + ) + } + return nil +} + +type tTransportFactoryConf struct { + delegate TTransportFactory + cfg *TConfiguration +} + +func (f *tTransportFactoryConf) GetTransport(orig TTransport) (TTransport, error) { + trans, err := f.delegate.GetTransport(orig) + if err == nil { + PropagateTConfiguration(orig, f.cfg) + PropagateTConfiguration(trans, f.cfg) + } + return trans, err +} + +func (f *tTransportFactoryConf) SetTConfiguration(cfg *TConfiguration) { + PropagateTConfiguration(f.delegate, f.cfg) + f.cfg = cfg +} + +// TTransportFactoryConf wraps a TTransportFactory to propagate +// TConfiguration on the factory's GetTransport calls. +func TTransportFactoryConf(delegate TTransportFactory, conf *TConfiguration) TTransportFactory { + return &tTransportFactoryConf{ + delegate: delegate, + cfg: conf, + } +} + +type tProtocolFactoryConf struct { + delegate TProtocolFactory + cfg *TConfiguration +} + +func (f *tProtocolFactoryConf) GetProtocol(trans TTransport) TProtocol { + proto := f.delegate.GetProtocol(trans) + PropagateTConfiguration(trans, f.cfg) + PropagateTConfiguration(proto, f.cfg) + return proto +} + +func (f *tProtocolFactoryConf) SetTConfiguration(cfg *TConfiguration) { + PropagateTConfiguration(f.delegate, f.cfg) + f.cfg = cfg +} + +// TProtocolFactoryConf wraps a TProtocolFactory to propagate +// TConfiguration on the factory's GetProtocol calls. +func TProtocolFactoryConf(delegate TProtocolFactory, conf *TConfiguration) TProtocolFactory { + return &tProtocolFactoryConf{ + delegate: delegate, + cfg: conf, + } +} + +var ( + _ TConfigurationSetter = (*tTransportFactoryConf)(nil) + _ TConfigurationSetter = (*tProtocolFactoryConf)(nil) +) diff --git a/lib/go/thrift/configuration_test.go b/lib/go/thrift/configuration_test.go new file mode 100644 index 00000000000..f7478423154 --- /dev/null +++ b/lib/go/thrift/configuration_test.go @@ -0,0 +1,338 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package thrift + +import ( + "crypto/tls" + "testing" + "time" +) + +func TestTConfiguration(t *testing.T) { + invalidProtoID := THeaderProtocolID(-1) + if invalidProtoID.Validate() == nil { + t.Fatalf("Expected %v to be an invalid THeaderProtocolID, it passes the validation", invalidProtoID) + } + + tlsConfig := &tls.Config{ + Time: time.Now, + } + + for _, c := range []struct { + label string + cfg *TConfiguration + expectedMessageSize int32 + expectedFrameSize int32 + expectedConnectTimeout time.Duration + expectedSocketTimeout time.Duration + expectedTLSConfig *tls.Config + expectedBinaryRead bool + expectedBinaryWrite bool + expectedProtoID THeaderProtocolID + }{ + { + label: "nil", + cfg: nil, + expectedMessageSize: DEFAULT_MAX_MESSAGE_SIZE, + expectedFrameSize: DEFAULT_MAX_FRAME_SIZE, + expectedConnectTimeout: DEFAULT_CONNECT_TIMEOUT, + expectedSocketTimeout: DEFAULT_SOCKET_TIMEOUT, + expectedTLSConfig: nil, + expectedBinaryRead: DEFAULT_TBINARY_STRICT_READ, + expectedBinaryWrite: DEFAULT_TBINARY_STRICT_WRITE, + expectedProtoID: THeaderProtocolDefault, + }, + { + label: "empty", + cfg: &TConfiguration{}, + expectedMessageSize: DEFAULT_MAX_MESSAGE_SIZE, + expectedFrameSize: DEFAULT_MAX_FRAME_SIZE, + expectedConnectTimeout: DEFAULT_CONNECT_TIMEOUT, + expectedSocketTimeout: DEFAULT_SOCKET_TIMEOUT, + expectedTLSConfig: nil, + expectedBinaryRead: DEFAULT_TBINARY_STRICT_READ, + expectedBinaryWrite: DEFAULT_TBINARY_STRICT_WRITE, + expectedProtoID: THeaderProtocolDefault, + }, + { + label: "normal", + cfg: &TConfiguration{ + MaxMessageSize: 1024, + MaxFrameSize: 1024, + ConnectTimeout: time.Millisecond, + SocketTimeout: time.Millisecond * 2, + TLSConfig: tlsConfig, + TBinaryStrictRead: BoolPtr(true), + TBinaryStrictWrite: BoolPtr(false), + THeaderProtocolID: THeaderProtocolIDPtrMust(THeaderProtocolCompact), + }, + expectedMessageSize: 1024, + expectedFrameSize: 1024, + expectedConnectTimeout: time.Millisecond, + expectedSocketTimeout: time.Millisecond * 2, + expectedTLSConfig: tlsConfig, + expectedBinaryRead: true, + expectedBinaryWrite: false, + expectedProtoID: THeaderProtocolCompact, + }, + { + label: "message p.maxLength { + if size < 0 || size > uint32(p.cfg.GetMaxFrameSize()) { return NewTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, fmt.Sprintf("Incorrect frame size (%d)", size)) } _, err := io.CopyN(&p.readBuf, p.reader, int64(size)) @@ -165,3 +210,14 @@ func (p *TFramedTransport) readFrame() error { func (p *TFramedTransport) RemainingBytes() (num_bytes uint64) { return uint64(p.readBuf.Len()) } + +// SetTConfiguration implements TConfigurationSetter. +func (p *TFramedTransport) SetTConfiguration(cfg *TConfiguration) { + PropagateTConfiguration(p.transport, cfg) + p.cfg = cfg +} + +var ( + _ TConfigurationSetter = (*tFramedTransportFactory)(nil) + _ TConfigurationSetter = (*TFramedTransport)(nil) +) diff --git a/lib/go/thrift/header_protocol.go b/lib/go/thrift/header_protocol.go index f86d558aaae..5ad48e43bd6 100644 --- a/lib/go/thrift/header_protocol.go +++ b/lib/go/thrift/header_protocol.go @@ -34,76 +34,65 @@ type THeaderProtocol struct { // Will be initialized on first read/write. protocol TProtocol + + cfg *TConfiguration +} + +// Deprecated: Use NewTHeaderProtocolConf instead. +func NewTHeaderProtocol(trans TTransport) *THeaderProtocol { + return newTHeaderProtocolConf(trans, &TConfiguration{ + noPropagation: true, + }) } -// NewTHeaderProtocol creates a new THeaderProtocol from the underlying -// transport with default protocol ID. +// NewTHeaderProtocolConf creates a new THeaderProtocol from the underlying +// transport with given TConfiguration. // // The passed in transport will be wrapped with THeaderTransport. // // Note that THeaderTransport handles frame and zlib by itself, // so the underlying transport should be a raw socket transports (TSocket or TSSLSocket), // instead of rich transports like TZlibTransport or TFramedTransport. -func NewTHeaderProtocol(trans TTransport) *THeaderProtocol { - p, err := newTHeaderProtocolWithProtocolID(trans, THeaderProtocolDefault) - if err != nil { - // Since we used THeaderProtocolDefault this should never happen, - // but put a sanity check here just in case. - panic(err) - } - return p +func NewTHeaderProtocolConf(trans TTransport, conf *TConfiguration) *THeaderProtocol { + return newTHeaderProtocolConf(trans, conf) } -func newTHeaderProtocolWithProtocolID(trans TTransport, protoID THeaderProtocolID) (*THeaderProtocol, error) { - t, err := NewTHeaderTransportWithProtocolID(trans, protoID) - if err != nil { - return nil, err - } - p, err := t.protocolID.GetProtocol(t) - if err != nil { - return nil, err - } +func newTHeaderProtocolConf(trans TTransport, cfg *TConfiguration) *THeaderProtocol { + t := NewTHeaderTransportConf(trans, cfg) + p, _ := t.cfg.GetTHeaderProtocolID().GetProtocol(t) + PropagateTConfiguration(p, cfg) return &THeaderProtocol{ transport: t, protocol: p, - }, nil + cfg: cfg, + } } type tHeaderProtocolFactory struct { - protoID THeaderProtocolID + cfg *TConfiguration } func (f tHeaderProtocolFactory) GetProtocol(trans TTransport) TProtocol { - p, err := newTHeaderProtocolWithProtocolID(trans, f.protoID) - if err != nil { - // Currently there's no way for external users to construct a - // valid factory with invalid protoID, so this should never - // happen. But put a sanity check here just in case in the - // future a bug made that possible. - panic(err) - } - return p + return newTHeaderProtocolConf(trans, f.cfg) } -// NewTHeaderProtocolFactory creates a factory for THeader with default protocol -// ID. -// -// It's a wrapper for NewTHeaderProtocol +func (f *tHeaderProtocolFactory) SetTConfiguration(cfg *TConfiguration) { + f.cfg = cfg +} + +// Deprecated: Use NewTHeaderProtocolFactoryConf instead. func NewTHeaderProtocolFactory() TProtocolFactory { - return tHeaderProtocolFactory{ - protoID: THeaderProtocolDefault, - } + return NewTHeaderProtocolFactoryConf(&TConfiguration{ + noPropagation: true, + }) } -// NewTHeaderProtocolFactoryWithProtocolID creates a factory for THeader with -// given protocol ID. -func NewTHeaderProtocolFactoryWithProtocolID(protoID THeaderProtocolID) (TProtocolFactory, error) { - if err := protoID.Validate(); err != nil { - return nil, err - } +// NewTHeaderProtocolFactoryConf creates a factory for THeader with given +// TConfiguration. +func NewTHeaderProtocolFactoryConf(conf *TConfiguration) TProtocolFactory { return tHeaderProtocolFactory{ - protoID: protoID, - }, nil + cfg: conf, + } } // Transport returns the underlying transport. @@ -142,6 +131,7 @@ func (p *THeaderProtocol) WriteMessageBegin(ctx context.Context, name string, ty if err != nil { return err } + PropagateTConfiguration(newProto, p.cfg) p.protocol = newProto p.transport.SequenceID = seqID return p.protocol.WriteMessageBegin(ctx, name, typeID, seqID) @@ -261,6 +251,7 @@ func (p *THeaderProtocol) ReadMessageBegin(ctx context.Context) (name string, ty } return } + PropagateTConfiguration(newProto, p.cfg) p.protocol = newProto return p.protocol.ReadMessageBegin(ctx) @@ -346,6 +337,13 @@ func (p *THeaderProtocol) Skip(ctx context.Context, fieldType TType) error { return p.protocol.Skip(ctx, fieldType) } +// SetTConfiguration implements TConfigurationSetter. +func (p *THeaderProtocol) SetTConfiguration(cfg *TConfiguration) { + PropagateTConfiguration(p.transport, cfg) + PropagateTConfiguration(p.protocol, cfg) + p.cfg = cfg +} + // GetResponseHeadersFromClient is a helper function to get the read THeaderMap // from the last response received from the given client. // @@ -359,3 +357,8 @@ func GetResponseHeadersFromClient(c TClient) THeaderMap { } return nil } + +var ( + _ TConfigurationSetter = (*tHeaderProtocolFactory)(nil) + _ TConfigurationSetter = (*THeaderProtocol)(nil) +) diff --git a/lib/go/thrift/header_protocol_test.go b/lib/go/thrift/header_protocol_test.go index f66ea6463e5..48a69bf23b0 100644 --- a/lib/go/thrift/header_protocol_test.go +++ b/lib/go/thrift/header_protocol_test.go @@ -34,11 +34,9 @@ func TestReadWriteHeaderProtocol(t *testing.T) { t.Run( "compact", func(t *testing.T) { - f, err := NewTHeaderProtocolFactoryWithProtocolID(THeaderProtocolCompact) - if err != nil { - t.Fatal(err) - } - ReadWriteProtocolTest(t, f) + ReadWriteProtocolTest(t, NewTHeaderProtocolFactoryConf(&TConfiguration{ + THeaderProtocolID: THeaderProtocolIDPtrMust(THeaderProtocolCompact), + })) }, ) } diff --git a/lib/go/thrift/header_transport.go b/lib/go/thrift/header_transport.go index 562d02fa4af..1e8e302447a 100644 --- a/lib/go/thrift/header_transport.go +++ b/lib/go/thrift/header_transport.go @@ -264,7 +264,7 @@ type THeaderTransport struct { writeTransforms []THeaderTransformID clientType clientType - protocolID THeaderProtocolID + cfg *TConfiguration // buffer is used in the following scenarios to avoid repetitive // allocations, while 4 is big enough for all those scenarios: @@ -276,51 +276,35 @@ type THeaderTransport struct { var _ TTransport = (*THeaderTransport)(nil) -// NewTHeaderTransport creates THeaderTransport from the underlying transport. -// -// Please note that THeaderTransport handles framing and zlib by itself, -// so the underlying transport should be the raw socket transports (TSocket or TSSLSocket), -// instead of rich transports like TZlibTransport or TFramedTransport. -// -// If trans is already a *THeaderTransport, it will be returned as is. +// Deprecated: Use NewTHeaderTransportConf instead. func NewTHeaderTransport(trans TTransport) *THeaderTransport { - if ht, ok := trans.(*THeaderTransport); ok { - return ht - } - return &THeaderTransport{ - transport: trans, - reader: bufio.NewReader(trans), - writeHeaders: make(THeaderMap), - protocolID: THeaderProtocolDefault, - } + return NewTHeaderTransportConf(trans, &TConfiguration{ + noPropagation: true, + }) } -// NewTHeaderTransportWithProtocolID creates THeaderTransport from the -// underlying transport, with given protocol ID set. +// NewTHeaderTransportConf creates THeaderTransport from the +// underlying transport, with given TConfiguration attached. // // If trans is already a *THeaderTransport, it will be returned as is, -// but with protocol ID overridden by the value passed in. -// -// If the passed in protocol ID is an invalid/unsupported one, -// this function returns error. +// but with TConfiguration overridden by the value passed in. // -// The protocol ID overridden is only useful for client transports. +// The protocol ID in TConfiguration is only useful for client transports. // For servers, // the protocol ID will be overridden again to the one set by the client, // to ensure that servers always speak the same dialect as the client. -func NewTHeaderTransportWithProtocolID(trans TTransport, protoID THeaderProtocolID) (*THeaderTransport, error) { - if err := protoID.Validate(); err != nil { - return nil, err - } +func NewTHeaderTransportConf(trans TTransport, conf *TConfiguration) *THeaderTransport { if ht, ok := trans.(*THeaderTransport); ok { - return ht, nil + ht.SetTConfiguration(conf) + return ht } + PropagateTConfiguration(trans, conf) return &THeaderTransport{ transport: trans, reader: bufio.NewReader(trans), writeHeaders: make(THeaderMap), - protocolID: protoID, - }, nil + cfg: conf, + } } // Open calls the underlying transport's Open function. @@ -375,7 +359,7 @@ func (t *THeaderTransport) ReadFrame(ctx context.Context) error { // At this point it should be a framed message, // sanity check on frameSize then discard the peeked part. - if frameSize > THeaderMaxFrameSize { + if frameSize > THeaderMaxFrameSize || frameSize > uint32(t.cfg.GetMaxFrameSize()) { return NewTProtocolExceptionWithType( SIZE_LIMIT, errors.New("frame too large"), @@ -451,6 +435,7 @@ func (t *THeaderTransport) parseHeaders(ctx context.Context, frameSize uint32) e return err } hp := NewTCompactProtocol(headerBuf) + hp.SetTConfiguration(t.cfg) // At this point the header is already read into headerBuf, // and t.frameBuffer starts from the actual payload. @@ -458,7 +443,17 @@ func (t *THeaderTransport) parseHeaders(ctx context.Context, frameSize uint32) e if err != nil { return err } - t.protocolID = THeaderProtocolID(protoID) + idPtr, err := THeaderProtocolIDPtr(THeaderProtocolID(protoID)) + if err != nil { + return err + } + if t.cfg == nil { + t.cfg = &TConfiguration{ + noPropagation: true, + } + } + t.cfg.THeaderProtocolID = idPtr + var transformCount int32 transformCount, err = hp.readVarint32() if err != nil { @@ -601,7 +596,8 @@ func (t *THeaderTransport) Flush(ctx context.Context) error { case clientHeaders: headers := NewTMemoryBuffer() hp := NewTCompactProtocol(headers) - if _, err := hp.writeVarint32(int32(t.protocolID)); err != nil { + hp.SetTConfiguration(t.cfg) + if _, err := hp.writeVarint32(int32(t.cfg.GetTHeaderProtocolID())); err != nil { return NewTTransportExceptionFromError(err) } if _, err := hp.writeVarint32(int32(len(t.writeTransforms))); err != nil { @@ -746,7 +742,7 @@ func (t *THeaderTransport) AddTransform(transform THeaderTransformID) error { func (t *THeaderTransport) Protocol() THeaderProtocolID { switch t.clientType { default: - return t.protocolID + return t.cfg.GetTHeaderProtocolID() case clientFramedBinary, clientUnframedBinary: return THeaderProtocolBinary case clientFramedCompact, clientUnframedCompact: @@ -763,17 +759,37 @@ func (t *THeaderTransport) isFramed() bool { } } +// SetTConfiguration implements TConfigurationSetter. +func (t *THeaderTransport) SetTConfiguration(cfg *TConfiguration) { + PropagateTConfiguration(t.transport, cfg) + t.cfg = cfg +} + // THeaderTransportFactory is a TTransportFactory implementation to create // THeaderTransport. +// +// It also implements TConfigurationSetter. type THeaderTransportFactory struct { // The underlying factory, could be nil. Factory TTransportFactory + + cfg *TConfiguration } -// NewTHeaderTransportFactory creates a new *THeaderTransportFactory. +// Deprecated: Use NewTHeaderTransportFactoryConf instead. func NewTHeaderTransportFactory(factory TTransportFactory) TTransportFactory { + return NewTHeaderTransportFactoryConf(factory, &TConfiguration{ + noPropagation: true, + }) +} + +// NewTHeaderTransportFactoryConf creates a new *THeaderTransportFactory with +// the given *TConfiguration. +func NewTHeaderTransportFactoryConf(factory TTransportFactory, conf *TConfiguration) TTransportFactory { return &THeaderTransportFactory{ Factory: factory, + + cfg: conf, } } @@ -784,7 +800,18 @@ func (f *THeaderTransportFactory) GetTransport(trans TTransport) (TTransport, er if err != nil { return nil, err } - return NewTHeaderTransport(t), nil + return NewTHeaderTransportConf(t, f.cfg), nil } - return NewTHeaderTransport(trans), nil + return NewTHeaderTransportConf(trans, f.cfg), nil } + +// SetTConfiguration implements TConfigurationSetter. +func (f *THeaderTransportFactory) SetTConfiguration(cfg *TConfiguration) { + PropagateTConfiguration(f.Factory, f.cfg) + f.cfg = cfg +} + +var ( + _ TConfigurationSetter = (*THeaderTransportFactory)(nil) + _ TConfigurationSetter = (*THeaderTransport)(nil) +) diff --git a/lib/go/thrift/header_transport_test.go b/lib/go/thrift/header_transport_test.go index 5b47680e8fa..41efb18988d 100644 --- a/lib/go/thrift/header_transport_test.go +++ b/lib/go/thrift/header_transport_test.go @@ -21,6 +21,7 @@ package thrift import ( "context" + "fmt" "io" "io/ioutil" "strings" @@ -31,10 +32,9 @@ import ( func testTHeaderHeadersReadWriteProtocolID(t *testing.T, protoID THeaderProtocolID) { trans := NewTMemoryBuffer() reader := NewTHeaderTransport(trans) - writer, err := NewTHeaderTransportWithProtocolID(trans, protoID) - if err != nil { - t.Fatal(err) - } + writer := NewTHeaderTransportConf(trans, &TConfiguration{ + THeaderProtocolID: &protoID, + }) const key1 = "key1" const value1 = "value1" @@ -265,3 +265,19 @@ func TestTHeaderTransportEndOfFrameHandling(t *testing.T) { t.Error(err) } } + +func BenchmarkTHeaderProtocolIDValidate(b *testing.B) { + for _, c := range []THeaderProtocolID{ + THeaderProtocolBinary, + THeaderProtocolCompact, + -1, + } { + b.Run(fmt.Sprintf("%2v", c), func(b *testing.B) { + b.RunParallel(func(pb *testing.PB) { + for pb.Next() { + c.Validate() + } + }) + }) + } +} diff --git a/lib/go/thrift/iostream_transport.go b/lib/go/thrift/iostream_transport.go index 0b1775d06cb..1c477990fea 100644 --- a/lib/go/thrift/iostream_transport.go +++ b/lib/go/thrift/iostream_transport.go @@ -212,3 +212,11 @@ func (p *StreamTransport) RemainingBytes() (num_bytes uint64) { const maxSize = ^uint64(0) return maxSize // the truth is, we just don't know unless framed is used } + +// SetTConfiguration implements TConfigurationSetter for propagation. +func (p *StreamTransport) SetTConfiguration(conf *TConfiguration) { + PropagateTConfiguration(p.Reader, conf) + PropagateTConfiguration(p.Writer, conf) +} + +var _ TConfigurationSetter = (*StreamTransport)(nil) diff --git a/lib/go/thrift/json_protocol.go b/lib/go/thrift/json_protocol.go index edc49cc1053..8e59d16cfda 100644 --- a/lib/go/thrift/json_protocol.go +++ b/lib/go/thrift/json_protocol.go @@ -587,3 +587,5 @@ func (p *TJSONProtocol) StringToTypeId(fieldType string) (TType, error) { e := fmt.Errorf("Unknown type identifier: %s", fieldType) return TType(STOP), NewTProtocolExceptionWithType(INVALID_DATA, e) } + +var _ TConfigurationSetter = (*TJSONProtocol)(nil) diff --git a/lib/go/thrift/simple_json_protocol.go b/lib/go/thrift/simple_json_protocol.go index e94b44bbbb7..d1a8154532d 100644 --- a/lib/go/thrift/simple_json_protocol.go +++ b/lib/go/thrift/simple_json_protocol.go @@ -1364,3 +1364,10 @@ func (p *TSimpleJSONProtocol) write(b []byte) (int, error) { } return n, err } + +// SetTConfiguration implements TConfigurationSetter for propagation. +func (p *TSimpleJSONProtocol) SetTConfiguration(conf *TConfiguration) { + PropagateTConfiguration(p.trans, conf) +} + +var _ TConfigurationSetter = (*TSimpleJSONProtocol)(nil) diff --git a/lib/go/thrift/socket.go b/lib/go/thrift/socket.go index af75dd1a980..e911bf16681 100644 --- a/lib/go/thrift/socket.go +++ b/lib/go/thrift/socket.go @@ -26,57 +26,116 @@ import ( ) type TSocket struct { - conn *socketConn - addr net.Addr + conn *socketConn + addr net.Addr + cfg *TConfiguration + connectTimeout time.Duration socketTimeout time.Duration } -// NewTSocket creates a net.Conn-backed TTransport, given a host and port -// -// Example: -// trans, err := thrift.NewTSocket("localhost:9090") +// Deprecated: Use NewTSocketConf instead. func NewTSocket(hostPort string) (*TSocket, error) { - return NewTSocketTimeout(hostPort, 0, 0) + return NewTSocketConf(hostPort, &TConfiguration{ + noPropagation: true, + }) } -// NewTSocketTimeout creates a net.Conn-backed TTransport, given a host and port -// it also accepts a timeout as a time.Duration -func NewTSocketTimeout(hostPort string, connTimeout time.Duration, soTimeout time.Duration) (*TSocket, error) { - //conn, err := net.DialTimeout(network, address, timeout) +// NewTSocketConf creates a net.Conn-backed TTransport, given a host and port. +// +// Example: +// +// trans, err := thrift.NewTSocketConf("localhost:9090", &TConfiguration{ +// ConnectTimeout: time.Second, // Use 0 for no timeout +// SocketTimeout: time.Second, // Use 0 for no timeout +// }) +func NewTSocketConf(hostPort string, conf *TConfiguration) (*TSocket, error) { addr, err := net.ResolveTCPAddr("tcp", hostPort) if err != nil { return nil, err } - return NewTSocketFromAddrTimeout(addr, connTimeout, soTimeout), nil + return NewTSocketFromAddrConf(addr, conf), nil +} + +// Deprecated: Use NewTSocketConf instead. +func NewTSocketTimeout(hostPort string, connTimeout time.Duration, soTimeout time.Duration) (*TSocket, error) { + return NewTSocketConf(hostPort, &TConfiguration{ + ConnectTimeout: connTimeout, + SocketTimeout: soTimeout, + + noPropagation: true, + }) +} + +// NewTSocketFromAddrConf creates a TSocket from a net.Addr +func NewTSocketFromAddrConf(addr net.Addr, conf *TConfiguration) *TSocket { + return &TSocket{ + addr: addr, + cfg: conf, + } } -// Creates a TSocket from a net.Addr +// Deprecated: Use NewTSocketFromAddrConf instead. func NewTSocketFromAddrTimeout(addr net.Addr, connTimeout time.Duration, soTimeout time.Duration) *TSocket { - return &TSocket{addr: addr, connectTimeout: connTimeout, socketTimeout: soTimeout} + return NewTSocketFromAddrConf(addr, &TConfiguration{ + ConnectTimeout: connTimeout, + SocketTimeout: soTimeout, + + noPropagation: true, + }) +} + +// NewTSocketFromConnConf creates a TSocket from an existing net.Conn. +func NewTSocketFromConnConf(conn net.Conn, conf *TConfiguration) *TSocket { + return &TSocket{ + conn: wrapSocketConn(conn), + addr: conn.RemoteAddr(), + cfg: conf, + } } -// Creates a TSocket from an existing net.Conn +// Deprecated: Use NewTSocketFromConnConf instead. func NewTSocketFromConnTimeout(conn net.Conn, socketTimeout time.Duration) *TSocket { - return &TSocket{conn: wrapSocketConn(conn), addr: conn.RemoteAddr(), socketTimeout: socketTimeout} + return NewTSocketFromConnConf(conn, &TConfiguration{ + SocketTimeout: socketTimeout, + + noPropagation: true, + }) +} + +// SetTConfiguration implements TConfigurationSetter. +// +// It can be used to set connect and socket timeouts. +func (p *TSocket) SetTConfiguration(conf *TConfiguration) { + p.cfg = conf } // Sets the connect timeout func (p *TSocket) SetConnTimeout(timeout time.Duration) error { - p.connectTimeout = timeout + if p.cfg == nil { + p.cfg = &TConfiguration{ + noPropagation: true, + } + } + p.cfg.ConnectTimeout = timeout return nil } // Sets the socket timeout func (p *TSocket) SetSocketTimeout(timeout time.Duration) error { - p.socketTimeout = timeout + if p.cfg == nil { + p.cfg = &TConfiguration{ + noPropagation: true, + } + } + p.cfg.SocketTimeout = timeout return nil } func (p *TSocket) pushDeadline(read, write bool) { var t time.Time - if p.socketTimeout > 0 { - t = time.Now().Add(time.Duration(p.socketTimeout)) + if timeout := p.cfg.GetSocketTimeout(); timeout > 0 { + t = time.Now().Add(time.Duration(timeout)) } if read && write { p.conn.SetDeadline(t) @@ -105,7 +164,7 @@ func (p *TSocket) Open() error { if p.conn, err = createSocketConnFromReturn(net.DialTimeout( p.addr.Network(), p.addr.String(), - p.connectTimeout, + p.cfg.GetConnectTimeout(), )); err != nil { return NewTTransportException(NOT_OPEN, err.Error()) } @@ -175,3 +234,5 @@ func (p *TSocket) RemainingBytes() (num_bytes uint64) { const maxSize = ^uint64(0) return maxSize // the truth is, we just don't know unless framed is used } + +var _ TConfigurationSetter = (*TSocket)(nil) diff --git a/lib/go/thrift/ssl_socket.go b/lib/go/thrift/ssl_socket.go index 15ae96f6030..6359a74ceb2 100644 --- a/lib/go/thrift/ssl_socket.go +++ b/lib/go/thrift/ssl_socket.go @@ -34,70 +34,115 @@ type TSSLSocket struct { // addr is nil when hostPort is not "", and is only used when the // TSSLSocket is constructed from a net.Addr. addr net.Addr - cfg *tls.Config - connectTimeout time.Duration - socketTimeout time.Duration + cfg *TConfiguration } -// NewTSSLSocket creates a net.Conn-backed TTransport, given a host and port and tls Configuration +// NewTSSLSocketConf creates a net.Conn-backed TTransport, given a host and port. // // Example: -// trans, err := thrift.NewTSSLSocket("localhost:9090", nil) +// +// trans, err := thrift.NewTSSLSocketConf("localhost:9090", nil, &TConfiguration{ +// ConnectTimeout: time.Second, // Use 0 for no timeout +// SocketTimeout: time.Second, // Use 0 for no timeout +// }) +func NewTSSLSocketConf(hostPort string, conf *TConfiguration) (*TSSLSocket, error) { + if cfg := conf.GetTLSConfig(); cfg != nil && cfg.MinVersion == 0 { + cfg.MinVersion = tls.VersionTLS10 + } + return &TSSLSocket{ + hostPort: hostPort, + cfg: conf, + }, nil +} + +// Deprecated: Use NewTSSLSocketConf instead. func NewTSSLSocket(hostPort string, cfg *tls.Config) (*TSSLSocket, error) { - return NewTSSLSocketTimeout(hostPort, cfg, 0, 0) + return NewTSSLSocketConf(hostPort, &TConfiguration{ + TLSConfig: cfg, + + noPropagation: true, + }) } -// NewTSSLSocketTimeout creates a net.Conn-backed TTransport, given a host and port -// it also accepts a tls Configuration and connect/socket timeouts as time.Duration +// Deprecated: Use NewTSSLSocketConf instead. func NewTSSLSocketTimeout(hostPort string, cfg *tls.Config, connectTimeout, socketTimeout time.Duration) (*TSSLSocket, error) { - if cfg.MinVersion == 0 { - cfg.MinVersion = tls.VersionTLS10 - } + return NewTSSLSocketConf(hostPort, &TConfiguration{ + ConnectTimeout: connectTimeout, + SocketTimeout: socketTimeout, + TLSConfig: cfg, + + noPropagation: true, + }) +} + +// NewTSSLSocketFromAddrConf creates a TSSLSocket from a net.Addr. +func NewTSSLSocketFromAddrConf(addr net.Addr, conf *TConfiguration) *TSSLSocket { return &TSSLSocket{ - hostPort: hostPort, - cfg: cfg, - connectTimeout: connectTimeout, - socketTimeout: socketTimeout, - }, nil + addr: addr, + cfg: conf, + } } -// Creates a TSSLSocket from a net.Addr +// Deprecated: Use NewTSSLSocketFromAddrConf instead. func NewTSSLSocketFromAddrTimeout(addr net.Addr, cfg *tls.Config, connectTimeout, socketTimeout time.Duration) *TSSLSocket { + return NewTSSLSocketFromAddrConf(addr, &TConfiguration{ + ConnectTimeout: connectTimeout, + SocketTimeout: socketTimeout, + TLSConfig: cfg, + + noPropagation: true, + }) +} + +// NewTSSLSocketFromConnConf creates a TSSLSocket from an existing net.Conn. +func NewTSSLSocketFromConnConf(conn net.Conn, conf *TConfiguration) *TSSLSocket { return &TSSLSocket{ - addr: addr, - cfg: cfg, - connectTimeout: connectTimeout, - socketTimeout: socketTimeout, + conn: wrapSocketConn(conn), + addr: conn.RemoteAddr(), + cfg: conf, } } -// Creates a TSSLSocket from an existing net.Conn +// Deprecated: Use NewTSSLSocketFromConnConf instead. func NewTSSLSocketFromConnTimeout(conn net.Conn, cfg *tls.Config, socketTimeout time.Duration) *TSSLSocket { - return &TSSLSocket{ - conn: wrapSocketConn(conn), - addr: conn.RemoteAddr(), - cfg: cfg, - socketTimeout: socketTimeout, - } + return NewTSSLSocketFromConnConf(conn, &TConfiguration{ + SocketTimeout: socketTimeout, + TLSConfig: cfg, + + noPropagation: true, + }) +} + +// SetTConfiguration implements TConfigurationSetter. +// +// It can be used to change connect and socket timeouts. +func (p *TSSLSocket) SetTConfiguration(conf *TConfiguration) { + p.cfg = conf } // Sets the connect timeout func (p *TSSLSocket) SetConnTimeout(timeout time.Duration) error { - p.connectTimeout = timeout + if p.cfg == nil { + p.cfg = &TConfiguration{} + } + p.cfg.ConnectTimeout = timeout return nil } // Sets the socket timeout func (p *TSSLSocket) SetSocketTimeout(timeout time.Duration) error { - p.socketTimeout = timeout + if p.cfg == nil { + p.cfg = &TConfiguration{} + } + p.cfg.SocketTimeout = timeout return nil } func (p *TSSLSocket) pushDeadline(read, write bool) { var t time.Time - if p.socketTimeout > 0 { - t = time.Now().Add(time.Duration(p.socketTimeout)) + if timeout := p.cfg.GetSocketTimeout(); timeout > 0 { + t = time.Now().Add(time.Duration(timeout)) } if read && write { p.conn.SetDeadline(t) @@ -116,11 +161,11 @@ func (p *TSSLSocket) Open() error { if p.hostPort != "" { if p.conn, err = createSocketConnFromReturn(tls.DialWithDialer( &net.Dialer{ - Timeout: p.connectTimeout, + Timeout: p.cfg.GetConnectTimeout(), }, "tcp", p.hostPort, - p.cfg, + p.cfg.GetTLSConfig(), )); err != nil { return NewTTransportException(NOT_OPEN, err.Error()) } @@ -139,11 +184,11 @@ func (p *TSSLSocket) Open() error { } if p.conn, err = createSocketConnFromReturn(tls.DialWithDialer( &net.Dialer{ - Timeout: p.connectTimeout, + Timeout: p.cfg.GetConnectTimeout(), }, p.addr.Network(), p.addr.String(), - p.cfg, + p.cfg.GetTLSConfig(), )); err != nil { return NewTTransportException(NOT_OPEN, err.Error()) } @@ -209,3 +254,5 @@ func (p *TSSLSocket) RemainingBytes() (num_bytes uint64) { const maxSize = ^uint64(0) return maxSize // the truth is, we just don't know unless framed is used } + +var _ TConfigurationSetter = (*TSSLSocket)(nil) diff --git a/lib/go/thrift/zlib_transport.go b/lib/go/thrift/zlib_transport.go index e7efdfb9e53..259943a627c 100644 --- a/lib/go/thrift/zlib_transport.go +++ b/lib/go/thrift/zlib_transport.go @@ -128,3 +128,10 @@ func (z *TZlibTransport) RemainingBytes() uint64 { func (z *TZlibTransport) Write(p []byte) (int, error) { return z.writer.Write(p) } + +// SetTConfiguration implements TConfigurationSetter for propagation. +func (z *TZlibTransport) SetTConfiguration(conf *TConfiguration) { + PropagateTConfiguration(z.transport, conf) +} + +var _ TConfigurationSetter = (*TZlibTransport)(nil) From d831230929bb332189c9509d07102e4be9e7f681 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Tue, 22 Dec 2020 09:53:58 -0800 Subject: [PATCH 737/756] THRIFT-5326: Expand TException interface in go library Client: go Add TExceptionType enum type, and add TExceptionType() TExceptionType function to TException definition. Also make TProtocolException unwrap-able. --- CHANGES.md | 1 + .../cpp/src/thrift/generate/t_go_generator.cc | 33 +++++--- lib/go/test/tests/thrifttest_handler.go | 2 +- lib/go/thrift/application_exception.go | 6 ++ lib/go/thrift/compact_protocol.go | 2 +- lib/go/thrift/exception.go | 81 +++++++++++++++++-- lib/go/thrift/multiplexed_protocol.go | 14 +++- lib/go/thrift/protocol_exception.go | 33 ++++++-- lib/go/thrift/simple_server.go | 18 ++++- lib/go/thrift/transport_exception.go | 6 ++ lib/go/thrift/transport_exception_test.go | 4 - 11 files changed, 162 insertions(+), 38 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 663c4c18c92..8e4d08edd95 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,7 @@ - [THRIFT-5233](https://issues.apache.org/jira/browse/THRIFT-5233) - go: Now all Read*, Write* and Skip functions in TProtocol accept context arg - [THRIFT-5152](https://issues.apache.org/jira/browse/THRIFT-5152) - go: TSocket and TSSLSocket now have separated connect timeout and socket timeout - c++: dropped support for Windows XP +- [THRIFT-5326](https://issues.apache.org/jira/browse/THRIFT-5326) - go: TException interface now has a new function: TExceptionType ### Java diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index 3bb2a5cf2dc..49d8bc11977 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -1493,8 +1493,15 @@ void t_go_generator::generate_go_struct_definition(ostream& out, if (is_exception) { out << indent() << "func (p *" << tstruct_name << ") Error() string {" << endl; - out << indent() << " return p.String()" << endl; + out << indent() << indent() << "return p.String()" << endl; out << indent() << "}" << endl << endl; + + out << indent() << "func (" << tstruct_name << ") TExceptionType() thrift.TExceptionType {" << endl; + out << indent() << indent() << "return thrift.TExceptionTypeCompiled" << endl; + out << indent() << "}" << endl << endl; + + out << indent() << "var _ thrift.TException = (*" << tstruct_name << ")(nil)" + << endl << endl; } } @@ -2700,8 +2707,8 @@ void t_go_generator::generate_service_server(t_service* tservice) { f_types_ << indent() << "func (p *" << serviceName << "Processor) Process(ctx context.Context, iprot, oprot thrift.TProtocol) (success bool, err " "thrift.TException) {" << endl; - f_types_ << indent() << " name, _, seqId, err := iprot.ReadMessageBegin(ctx)" << endl; - f_types_ << indent() << " if err != nil { return false, err }" << endl; + f_types_ << indent() << " name, _, seqId, err2 := iprot.ReadMessageBegin(ctx)" << endl; + f_types_ << indent() << " if err2 != nil { return false, thrift.WrapTException(err2) }" << endl; f_types_ << indent() << " if processor, ok := p.GetProcessorFunction(name); ok {" << endl; f_types_ << indent() << " return processor.Process(ctx, seqId, iprot, oprot)" << endl; f_types_ << indent() << " }" << endl; @@ -2767,11 +2774,12 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function* "thrift.TException) {" << endl; indent_up(); f_types_ << indent() << "args := " << argsname << "{}" << endl; - f_types_ << indent() << "if err = args." << read_method_name_ << "(ctx, iprot); err != nil {" << endl; + f_types_ << indent() << "var err2 error" << endl; + f_types_ << indent() << "if err2 = args." << read_method_name_ << "(ctx, iprot); err2 != nil {" << endl; f_types_ << indent() << " iprot.ReadMessageEnd(ctx)" << endl; if (!tfunction->is_oneway()) { f_types_ << indent() - << " x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())" + << " x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err2.Error())" << endl; f_types_ << indent() << " oprot.WriteMessageBegin(ctx, \"" << escape_string(tfunction->get_name()) << "\", thrift.EXCEPTION, seqId)" << endl; @@ -2779,7 +2787,7 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function* f_types_ << indent() << " oprot.WriteMessageEnd(ctx)" << endl; f_types_ << indent() << " oprot.Flush(ctx)" << endl; } - f_types_ << indent() << " return false, err" << endl; + f_types_ << indent() << " return false, thrift.WrapTException(err2)" << endl; f_types_ << indent() << "}" << endl; f_types_ << indent() << "iprot.ReadMessageEnd(ctx)" << endl << endl; @@ -2842,7 +2850,6 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function* f_types_ << indent() << "var retval " << type_to_go_type(tfunction->get_returntype()) << endl; } - f_types_ << indent() << "var err2 error" << endl; f_types_ << indent() << "if "; if (!tfunction->is_oneway()) { @@ -2892,7 +2899,7 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function* if (!tfunction->is_oneway()) { // Avoid writing the error to the wire if it's ErrAbandonRequest f_types_ << indent() << " if err2 == thrift.ErrAbandonRequest {" << endl; - f_types_ << indent() << " return false, err2" << endl; + f_types_ << indent() << " return false, thrift.WrapTException(err2)" << endl; f_types_ << indent() << " }" << endl; f_types_ << indent() << " x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, " @@ -2905,7 +2912,7 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function* f_types_ << indent() << " oprot.Flush(ctx)" << endl; } - f_types_ << indent() << " return true, err2" << endl; + f_types_ << indent() << " return true, thrift.WrapTException(err2)" << endl; if (!x_fields.empty()) { f_types_ << indent() << "}" << endl; @@ -2931,17 +2938,17 @@ void t_go_generator::generate_process_function(t_service* tservice, t_function* f_types_ << indent() << "if err2 = oprot.WriteMessageBegin(ctx, \"" << escape_string(tfunction->get_name()) << "\", thrift.REPLY, seqId); err2 != nil {" << endl; - f_types_ << indent() << " err = err2" << endl; + f_types_ << indent() << " err = thrift.WrapTException(err2)" << endl; f_types_ << indent() << "}" << endl; f_types_ << indent() << "if err2 = result." << write_method_name_ << "(ctx, oprot); err == nil && err2 != nil {" << endl; - f_types_ << indent() << " err = err2" << endl; + f_types_ << indent() << " err = thrift.WrapTException(err2)" << endl; f_types_ << indent() << "}" << endl; f_types_ << indent() << "if err2 = oprot.WriteMessageEnd(ctx); err == nil && err2 != nil {" << endl; - f_types_ << indent() << " err = err2" << endl; + f_types_ << indent() << " err = thrift.WrapTException(err2)" << endl; f_types_ << indent() << "}" << endl; f_types_ << indent() << "if err2 = oprot.Flush(ctx); err == nil && err2 != nil {" << endl; - f_types_ << indent() << " err = err2" << endl; + f_types_ << indent() << " err = thrift.WrapTException(err2)" << endl; f_types_ << indent() << "}" << endl; f_types_ << indent() << "if err != nil {" << endl; f_types_ << indent() << " return" << endl; diff --git a/lib/go/test/tests/thrifttest_handler.go b/lib/go/test/tests/thrifttest_handler.go index 31b9ee23eca..7b115ec4053 100644 --- a/lib/go/test/tests/thrifttest_handler.go +++ b/lib/go/test/tests/thrifttest_handler.go @@ -179,7 +179,7 @@ func (p *ThriftTestHandler) TestException(ctx context.Context, arg string) (err x.Message = arg return x } else if arg == "TException" { - return thrift.TException(errors.New(arg)) + return thrift.WrapTException(errors.New(arg)) } else { return nil } diff --git a/lib/go/thrift/application_exception.go b/lib/go/thrift/application_exception.go index 6de37ee73f7..32d5b0147a2 100644 --- a/lib/go/thrift/application_exception.go +++ b/lib/go/thrift/application_exception.go @@ -64,6 +64,12 @@ type tApplicationException struct { type_ int32 } +var _ TApplicationException = (*tApplicationException)(nil) + +func (tApplicationException) TExceptionType() TExceptionType { + return TExceptionTypeApplication +} + func (e tApplicationException) Error() string { if e.message != "" { return e.message diff --git a/lib/go/thrift/compact_protocol.go b/lib/go/thrift/compact_protocol.go index 25e6d0ccd6e..a49225dabfb 100644 --- a/lib/go/thrift/compact_protocol.go +++ b/lib/go/thrift/compact_protocol.go @@ -845,7 +845,7 @@ func (p *TCompactProtocol) getTType(t tCompactType) (TType, error) { case COMPACT_STRUCT: return STRUCT, nil } - return STOP, TException(fmt.Errorf("don't know what type: %v", t&0x0f)) + return STOP, NewTProtocolException(fmt.Errorf("don't know what type: %v", t&0x0f)) } // Given a TType value, find the appropriate TCompactProtocol.Types constant. diff --git a/lib/go/thrift/exception.go b/lib/go/thrift/exception.go index ea8d6f66114..b6885face9c 100644 --- a/lib/go/thrift/exception.go +++ b/lib/go/thrift/exception.go @@ -26,19 +26,86 @@ import ( // Generic Thrift exception type TException interface { error + + TExceptionType() TExceptionType } // Prepends additional information to an error without losing the Thrift exception interface func PrependError(prepend string, err error) error { - if t, ok := err.(TTransportException); ok { - return NewTTransportException(t.TypeId(), prepend+t.Error()) + msg := prepend + err.Error() + + if te, ok := err.(TException); ok { + switch te.TExceptionType() { + case TExceptionTypeTransport: + if t, ok := err.(TTransportException); ok { + return NewTTransportException(t.TypeId(), msg) + } + case TExceptionTypeProtocol: + if t, ok := err.(TProtocolException); ok { + return NewTProtocolExceptionWithType(t.TypeId(), errors.New(msg)) + } + case TExceptionTypeApplication: + if t, ok := err.(TApplicationException); ok { + return NewTApplicationException(t.TypeId(), msg) + } + } + + return wrappedTException{ + err: errors.New(msg), + tExceptionType: te.TExceptionType(), + } + } + + return errors.New(msg) +} + +// TExceptionType is an enum type to categorize different "subclasses" of TExceptions. +type TExceptionType byte + +// TExceptionType values +const ( + TExceptionTypeUnknown TExceptionType = iota + TExceptionTypeCompiled // TExceptions defined in thrift files and generated by thrift compiler + TExceptionTypeApplication // TApplicationExceptions + TExceptionTypeProtocol // TProtocolExceptions + TExceptionTypeTransport // TTransportExceptions +) + +// WrapTException wraps an error into TException. +// +// If err is nil or already TException, it's returned as-is. +// Otherwise it will be wraped into TException with TExceptionType() returning +// TExceptionTypeUnknown, and Unwrap() returning the original error. +func WrapTException(err error) TException { + if err == nil { + return nil } - if t, ok := err.(TProtocolException); ok { - return NewTProtocolExceptionWithType(t.TypeId(), errors.New(prepend+err.Error())) + + if te, ok := err.(TException); ok { + return te } - if t, ok := err.(TApplicationException); ok { - return NewTApplicationException(t.TypeId(), prepend+t.Error()) + + return wrappedTException{ + err: err, + tExceptionType: TExceptionTypeUnknown, } +} + +type wrappedTException struct { + err error + tExceptionType TExceptionType +} - return errors.New(prepend + err.Error()) +func (w wrappedTException) Error() string { + return w.err.Error() } + +func (w wrappedTException) TExceptionType() TExceptionType { + return w.tExceptionType +} + +func (w wrappedTException) Unwrap() error { + return w.err +} + +var _ TException = wrappedTException{} diff --git a/lib/go/thrift/multiplexed_protocol.go b/lib/go/thrift/multiplexed_protocol.go index 2f7997e7795..cacbf6bef3e 100644 --- a/lib/go/thrift/multiplexed_protocol.go +++ b/lib/go/thrift/multiplexed_protocol.go @@ -192,10 +192,10 @@ func (t *TMultiplexedProcessor) RegisterProcessor(name string, processor TProces func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol) (bool, TException) { name, typeId, seqid, err := in.ReadMessageBegin(ctx) if err != nil { - return false, err + return false, NewTProtocolException(err) } if typeId != CALL && typeId != ONEWAY { - return false, fmt.Errorf("Unexpected message type %v", typeId) + return false, NewTProtocolException(fmt.Errorf("Unexpected message type %v", typeId)) } //extract the service name v := strings.SplitN(name, MULTIPLEXED_SEPARATOR, 2) @@ -204,11 +204,17 @@ func (t *TMultiplexedProcessor) Process(ctx context.Context, in, out TProtocol) smb := NewStoredMessageProtocol(in, name, typeId, seqid) return t.DefaultProcessor.Process(ctx, smb, out) } - return false, fmt.Errorf("Service name not found in message name: %s. Did you forget to use a TMultiplexProtocol in your client?", name) + return false, NewTProtocolException(fmt.Errorf( + "Service name not found in message name: %s. Did you forget to use a TMultiplexProtocol in your client?", + name, + )) } actualProcessor, ok := t.serviceProcessorMap[v[0]] if !ok { - return false, fmt.Errorf("Service name not found: %s. Did you forget to call registerProcessor()?", v[0]) + return false, NewTProtocolException(fmt.Errorf( + "Service name not found: %s. Did you forget to call registerProcessor()?", + v[0], + )) } smb := NewStoredMessageProtocol(in, v[1], typeId, seqid) return actualProcessor.Process(ctx, smb, out) diff --git a/lib/go/thrift/protocol_exception.go b/lib/go/thrift/protocol_exception.go index 29ab75d9215..b088caf131c 100644 --- a/lib/go/thrift/protocol_exception.go +++ b/lib/go/thrift/protocol_exception.go @@ -40,8 +40,14 @@ const ( ) type tProtocolException struct { - typeId int - message string + typeId int + err error +} + +var _ TProtocolException = (*tProtocolException)(nil) + +func (tProtocolException) TExceptionType() TExceptionType { + return TExceptionTypeProtocol } func (p *tProtocolException) TypeId() int { @@ -49,11 +55,15 @@ func (p *tProtocolException) TypeId() int { } func (p *tProtocolException) String() string { - return p.message + return p.err.Error() } func (p *tProtocolException) Error() string { - return p.message + return p.err.Error() +} + +func (p *tProtocolException) Unwrap() error { + return p.err } func NewTProtocolException(err error) TProtocolException { @@ -64,14 +74,23 @@ func NewTProtocolException(err error) TProtocolException { return e } if _, ok := err.(base64.CorruptInputError); ok { - return &tProtocolException{INVALID_DATA, err.Error()} + return &tProtocolException{ + typeId: INVALID_DATA, + err: err, + } + } + return &tProtocolException{ + typeId: UNKNOWN_PROTOCOL_EXCEPTION, + err: err, } - return &tProtocolException{UNKNOWN_PROTOCOL_EXCEPTION, err.Error()} } func NewTProtocolExceptionWithType(errType int, err error) TProtocolException { if err == nil { return nil } - return &tProtocolException{errType, err.Error()} + return &tProtocolException{ + typeId: errType, + err: err, + } } diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go index e9fea86d243..ca0e61d0ea9 100644 --- a/lib/go/thrift/simple_server.go +++ b/lib/go/thrift/simple_server.go @@ -315,7 +315,9 @@ func (p *TSimpleServer) processRequests(client TTransport) (err error) { } ok, err := processor.Process(ctx, inputProtocol, outputProtocol) - if err == ErrAbandonRequest { + // Once we dropped support for pre-go1.13 this can be replaced by: + // errors.Is(err, ErrAbandonRequest) + if unwrapError(err) == ErrAbandonRequest { return client.Close() } if _, ok := err.(TTransportException); ok && err != nil { @@ -330,3 +332,17 @@ func (p *TSimpleServer) processRequests(client TTransport) (err error) { } return nil } + +type unwrapper interface { + Unwrap() error +} + +func unwrapError(err error) error { + for { + if u, ok := err.(unwrapper); ok { + err = u.Unwrap() + } else { + return err + } + } +} diff --git a/lib/go/thrift/transport_exception.go b/lib/go/thrift/transport_exception.go index 16193ee8661..cf2cc005908 100644 --- a/lib/go/thrift/transport_exception.go +++ b/lib/go/thrift/transport_exception.go @@ -48,6 +48,12 @@ type tTransportException struct { err error } +var _ TTransportException = (*tTransportException)(nil) + +func (tTransportException) TExceptionType() TExceptionType { + return TExceptionTypeTransport +} + func (p *tTransportException) TypeId() int { return p.typeId } diff --git a/lib/go/thrift/transport_exception_test.go b/lib/go/thrift/transport_exception_test.go index fb1dc2602aa..57386cb28ce 100644 --- a/lib/go/thrift/transport_exception_test.go +++ b/lib/go/thrift/transport_exception_test.go @@ -36,10 +36,6 @@ func (t *timeout) Error() string { return fmt.Sprintf("Timeout: %v", t.timedout) } -type unwrapper interface { - Unwrap() error -} - func TestTExceptionTimeout(t *testing.T) { timeout := &timeout{true} exception := NewTTransportExceptionFromError(timeout) From 7f9abb1cc0f4b2793a48f45ddfcf0d2b287cc50c Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Tue, 20 Oct 2020 15:44:42 +0200 Subject: [PATCH 738/756] build/cmake/DefinePlatformSpecifc.cmake: Ensure ClangCl on MSVC is recognized as MSVC (because it does not handle -Wall too well) --- build/cmake/DefinePlatformSpecifc.cmake | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/build/cmake/DefinePlatformSpecifc.cmake b/build/cmake/DefinePlatformSpecifc.cmake index f43f5032351..84409e6ff51 100644 --- a/build/cmake/DefinePlatformSpecifc.cmake +++ b/build/cmake/DefinePlatformSpecifc.cmake @@ -25,13 +25,7 @@ set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Set debug library postfix") # basic options foreach(lang IN ITEMS C CXX) - if(CMAKE_${lang}_COMPILER_ID STREQUAL "Clang") - set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wall") - set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -ferror-limit=1") - elseif(CMAKE_${lang}_COMPILER_ID STREQUAL "GNU") - set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wall -Wextra") - set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -fmax-errors=1") - elseif(CMAKE_${lang}_COMPILER_ID STREQUAL "MSVC") + if("CMAKE_${lang}_COMPILER_ID" STREQUAL "MSVC" OR "${CMAKE_${lang}_SIMULATE_ID}" STREQUAL "MSVC") set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} /MP") # parallel build set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} /W3") # warning level 3 include(CheckCXXCompilerFlag) @@ -45,6 +39,12 @@ foreach(lang IN ITEMS C CXX) set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} /execution-charset:utf-8") endif() add_definitions("-DUNICODE -D_UNICODE") + elseif("CMAKE_${lang}_COMPILER_ID" STREQUAL "Clang") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wall") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -ferror-limit=1") + elseif("CMAKE_${lang}_COMPILER_ID" STREQUAL "GNU") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -Wall -Wextra") + set(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} -fmax-errors=1") endif() endforeach() From 0e68e8c51b2924d211a47978c80c6753f45e8af3 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Tue, 19 Jan 2021 09:14:36 -0800 Subject: [PATCH 739/756] THRIFT-5326: Make PrependError more unwrap-able Client: go As a follow up to https://github.com/apache/thrift/pull/2298, make the error returned by PrependError unwrap-able in certain cases. --- lib/go/thrift/exception.go | 11 +++++---- lib/go/thrift/protocol_exception.go | 27 +++++++++++++-------- lib/go/thrift/transport_exception.go | 36 ++++++++++++++++++++-------- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/lib/go/thrift/exception.go b/lib/go/thrift/exception.go index b6885face9c..48364799570 100644 --- a/lib/go/thrift/exception.go +++ b/lib/go/thrift/exception.go @@ -38,11 +38,11 @@ func PrependError(prepend string, err error) error { switch te.TExceptionType() { case TExceptionTypeTransport: if t, ok := err.(TTransportException); ok { - return NewTTransportException(t.TypeId(), msg) + return prependTTransportException(prepend, t) } case TExceptionTypeProtocol: if t, ok := err.(TProtocolException); ok { - return NewTProtocolExceptionWithType(t.TypeId(), errors.New(msg)) + return prependTProtocolException(prepend, t) } case TExceptionTypeApplication: if t, ok := err.(TApplicationException); ok { @@ -51,7 +51,8 @@ func PrependError(prepend string, err error) error { } return wrappedTException{ - err: errors.New(msg), + err: err, + msg: msg, tExceptionType: te.TExceptionType(), } } @@ -87,17 +88,19 @@ func WrapTException(err error) TException { return wrappedTException{ err: err, + msg: err.Error(), tExceptionType: TExceptionTypeUnknown, } } type wrappedTException struct { err error + msg string tExceptionType TExceptionType } func (w wrappedTException) Error() string { - return w.err.Error() + return w.msg } func (w wrappedTException) TExceptionType() TExceptionType { diff --git a/lib/go/thrift/protocol_exception.go b/lib/go/thrift/protocol_exception.go index b088caf131c..c86a9ff47d0 100644 --- a/lib/go/thrift/protocol_exception.go +++ b/lib/go/thrift/protocol_exception.go @@ -42,6 +42,7 @@ const ( type tProtocolException struct { typeId int err error + msg string } var _ TProtocolException = (*tProtocolException)(nil) @@ -55,11 +56,11 @@ func (p *tProtocolException) TypeId() int { } func (p *tProtocolException) String() string { - return p.err.Error() + return p.msg } func (p *tProtocolException) Error() string { - return p.err.Error() + return p.msg } func (p *tProtocolException) Unwrap() error { @@ -70,19 +71,16 @@ func NewTProtocolException(err error) TProtocolException { if err == nil { return nil } + if e, ok := err.(TProtocolException); ok { return e } + if _, ok := err.(base64.CorruptInputError); ok { - return &tProtocolException{ - typeId: INVALID_DATA, - err: err, - } - } - return &tProtocolException{ - typeId: UNKNOWN_PROTOCOL_EXCEPTION, - err: err, + return NewTProtocolExceptionWithType(INVALID_DATA, err) } + + return NewTProtocolExceptionWithType(UNKNOWN_PROTOCOL_EXCEPTION, err) } func NewTProtocolExceptionWithType(errType int, err error) TProtocolException { @@ -92,5 +90,14 @@ func NewTProtocolExceptionWithType(errType int, err error) TProtocolException { return &tProtocolException{ typeId: errType, err: err, + msg: err.Error(), + } +} + +func prependTProtocolException(prepend string, err TProtocolException) TProtocolException { + return &tProtocolException{ + typeId: err.TypeId(), + err: err, + msg: prepend + err.Error(), } } diff --git a/lib/go/thrift/transport_exception.go b/lib/go/thrift/transport_exception.go index cf2cc005908..08f7ce229f2 100644 --- a/lib/go/thrift/transport_exception.go +++ b/lib/go/thrift/transport_exception.go @@ -46,6 +46,7 @@ const ( type tTransportException struct { typeId int err error + msg string } var _ TTransportException = (*tTransportException)(nil) @@ -59,7 +60,7 @@ func (p *tTransportException) TypeId() int { } func (p *tTransportException) Error() string { - return p.err.Error() + return p.msg } func (p *tTransportException) Err() error { @@ -75,7 +76,11 @@ func (p *tTransportException) Timeout() bool { } func NewTTransportException(t int, e string) TTransportException { - return &tTransportException{typeId: t, err: errors.New(e)} + return &tTransportException{ + typeId: t, + err: errors.New(e), + msg: e, + } } func NewTTransportExceptionFromError(e error) TTransportException { @@ -87,20 +92,31 @@ func NewTTransportExceptionFromError(e error) TTransportException { return t } - switch v := e.(type) { - case TTransportException: - return v - case timeoutable: - if v.Timeout() { - return &tTransportException{typeId: TIMED_OUT, err: e} + newTTransportException := func(typeID int, err error, prefix string) TTransportException { + return &tTransportException{ + typeId: typeID, + err: err, + msg: prefix + err.Error(), } } + if isTimeoutError(e) { + return newTTransportException(TIMED_OUT, e, "") + } + if e == io.EOF { - return &tTransportException{typeId: END_OF_FILE, err: e} + return newTTransportException(END_OF_FILE, e, "") } - return &tTransportException{typeId: UNKNOWN_TRANSPORT_EXCEPTION, err: e} + return newTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, e, "") +} + +func prependTTransportException(prepend string, e TTransportException) TTransportException { + return &tTransportException{ + typeId: e.TypeId(), + err: e, + msg: prepend + e.Error(), + } } // isTimeoutError returns true when err is a timeout error. From e27e82c46ba4d46c2c3267701191cdc26614f739 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Tue, 19 Jan 2021 11:07:58 -0800 Subject: [PATCH 740/756] THRIFT-5338: Raise minimal supported go version to 1.14.14 Client: go - Update Dockerfiles used by travis - Add go.mod file - Modify error handling code to take advantage of errors package updates in go1.13 --- LANGUAGES.md | 2 +- build/docker/README.md | 2 +- build/docker/ubuntu-bionic/Dockerfile | 4 +-- build/docker/ubuntu-disco/Dockerfile | 4 +-- build/docker/ubuntu-xenial/Dockerfile | 4 +-- lib/go/test/tests/client_error_test.go | 17 +++++++++++++ lib/go/thrift/exception.go | 6 +++-- lib/go/thrift/go.mod | 3 +++ lib/go/thrift/header_protocol.go | 5 ++-- lib/go/thrift/header_transport.go | 2 +- lib/go/thrift/http_client.go | 3 ++- lib/go/thrift/protocol_exception.go | 3 ++- lib/go/thrift/rich_transport.go | 7 ++++-- lib/go/thrift/simple_server.go | 30 ++++++----------------- lib/go/thrift/socket_unix_conn.go | 3 ++- lib/go/thrift/transport_exception.go | 25 ++++++++++--------- lib/go/thrift/transport_exception_test.go | 16 +++--------- 17 files changed, 71 insertions(+), 65 deletions(-) create mode 100644 lib/go/thrift/go.mod diff --git a/LANGUAGES.md b/LANGUAGES.md index 4ea86f78d68..08c431d38d9 100644 --- a/LANGUAGES.md +++ b/LANGUAGES.md @@ -160,7 +160,7 @@ Thrift's core protocol is TBinary, supported by all languages except for JavaScr Go 0.7.0 Yes -1.10.81.13.1 +1.14.141.15.7 YesYesYes YesYesYes YesYesYesYes diff --git a/build/docker/README.md b/build/docker/README.md index e3c2ec16971..08023a7b267 100644 --- a/build/docker/README.md +++ b/build/docker/README.md @@ -178,7 +178,7 @@ Last updated: October 1, 2017 | dart | 2.0.0 | 2.4.0 | | | delphi | | | Not in CI | | erlang | 18.3 | 22.0 | | -| go | 1.10.8 | 1.12.6 | | +| go | 1.14.14 | 1.15.7 | | | haskell | 7.10.3 | 8.0.2 | | | haxe | 3.2.1 | 3.4.4 | THRIFT-4352: avoid 3.4.2 | | java | 1.8.0_191 | 11.0.3 | | diff --git a/build/docker/ubuntu-bionic/Dockerfile b/build/docker/ubuntu-bionic/Dockerfile index 7deefcb8f31..c8ecd8ea9d3 100644 --- a/build/docker/ubuntu-bionic/Dockerfile +++ b/build/docker/ubuntu-bionic/Dockerfile @@ -140,9 +140,9 @@ RUN apt-get install -y --no-install-recommends \ libglib2.0-dev # golang -ENV GOLANG_VERSION 1.13.1 +ENV GOLANG_VERSION 1.15.7 ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz -ENV GOLANG_DOWNLOAD_SHA256 94f874037b82ea5353f4061e543681a0e79657f787437974214629af8407d124 +ENV GOLANG_DOWNLOAD_SHA256 0d142143794721bb63ce6c8a6180c4062bcf8ef4715e7d6d6609f3a8282629b3 RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ diff --git a/build/docker/ubuntu-disco/Dockerfile b/build/docker/ubuntu-disco/Dockerfile index cfa40413ede..531718c2a90 100644 --- a/build/docker/ubuntu-disco/Dockerfile +++ b/build/docker/ubuntu-disco/Dockerfile @@ -140,9 +140,9 @@ RUN apt-get install -y --no-install-recommends \ libglib2.0-dev # golang -ENV GOLANG_VERSION 1.12.6 +ENV GOLANG_VERSION 1.15.7 ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz -ENV GOLANG_DOWNLOAD_SHA256 dbcf71a3c1ea53b8d54ef1b48c85a39a6c9a935d01fc8291ff2b92028e59913c +ENV GOLANG_DOWNLOAD_SHA256 0d142143794721bb63ce6c8a6180c4062bcf8ef4715e7d6d6609f3a8282629b3 RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ diff --git a/build/docker/ubuntu-xenial/Dockerfile b/build/docker/ubuntu-xenial/Dockerfile index 535db419f4e..e554c53179c 100644 --- a/build/docker/ubuntu-xenial/Dockerfile +++ b/build/docker/ubuntu-xenial/Dockerfile @@ -137,9 +137,9 @@ RUN apt-get install -y --no-install-recommends \ libglib2.0-dev # golang -ENV GOLANG_VERSION 1.10.8 +ENV GOLANG_VERSION 1.14.14 ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz -ENV GOLANG_DOWNLOAD_SHA256 d8626fb6f9a3ab397d88c483b576be41fa81eefcec2fd18562c87626dbb3c39e +ENV GOLANG_DOWNLOAD_SHA256 6f1354c9040d65d1622b451f43c324c1e5197aa9242d00c5a117d0e2625f3e0d RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz && \ echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - && \ tar -C /usr/local -xzf golang.tar.gz && \ diff --git a/lib/go/test/tests/client_error_test.go b/lib/go/test/tests/client_error_test.go index a064163651f..8d720fff272 100644 --- a/lib/go/test/tests/client_error_test.go +++ b/lib/go/test/tests/client_error_test.go @@ -32,6 +32,23 @@ import ( // TestCase: Comprehensive call and reply workflow in the client. // Setup mock to fail at a certain position. Return true if position exists otherwise false. func prepareClientCallReply(protocol *MockTProtocol, failAt int, failWith error) bool { + // NOTE: here the number 50 is the same as the last number at the end of + // this function. If more function calls are added in the future, this + // number needs to be increased accordingly. + // + // It's needed for go 1.14+. Before go 1.14 we only call gomock + // controller's Finish function when this function returns true. + // Starting from go 1.14 the gomock will take advantage of + // testing.T.Cleanup interface, which means the Finish function will + // always be called by t.Cleanup, even if we return false here. + // As a result, in the case we need to return false by this function, + // we must return before calling any of the + // protocol.EXPECT().* functions. + const lastFailAt = 50 + if failAt > lastFailAt { + return false + } + var err error = nil if failAt == 0 { diff --git a/lib/go/thrift/exception.go b/lib/go/thrift/exception.go index 48364799570..53bf862ea5b 100644 --- a/lib/go/thrift/exception.go +++ b/lib/go/thrift/exception.go @@ -34,7 +34,8 @@ type TException interface { func PrependError(prepend string, err error) error { msg := prepend + err.Error() - if te, ok := err.(TException); ok { + var te TException + if errors.As(err, &te) { switch te.TExceptionType() { case TExceptionTypeTransport: if t, ok := err.(TTransportException); ok { @@ -45,7 +46,8 @@ func PrependError(prepend string, err error) error { return prependTProtocolException(prepend, t) } case TExceptionTypeApplication: - if t, ok := err.(TApplicationException); ok { + var t TApplicationException + if errors.As(err, &t) { return NewTApplicationException(t.TypeId(), msg) } } diff --git a/lib/go/thrift/go.mod b/lib/go/thrift/go.mod new file mode 100644 index 00000000000..430c255a862 --- /dev/null +++ b/lib/go/thrift/go.mod @@ -0,0 +1,3 @@ +module github.com/apache/thrift/lib/go/thrift + +go 1.14 diff --git a/lib/go/thrift/header_protocol.go b/lib/go/thrift/header_protocol.go index 5ad48e43bd6..35e0458051c 100644 --- a/lib/go/thrift/header_protocol.go +++ b/lib/go/thrift/header_protocol.go @@ -21,6 +21,7 @@ package thrift import ( "context" + "errors" ) // THeaderProtocol is a thrift protocol that implements THeader: @@ -233,8 +234,8 @@ func (p *THeaderProtocol) ReadMessageBegin(ctx context.Context) (name string, ty var newProto TProtocol newProto, err = p.transport.Protocol().GetProtocol(p.transport) if err != nil { - tAppExc, ok := err.(TApplicationException) - if !ok { + var tAppExc TApplicationException + if !errors.As(err, &tAppExc) { return } if e := p.protocol.WriteMessageBegin(ctx, "", EXCEPTION, seqID); e != nil { diff --git a/lib/go/thrift/header_transport.go b/lib/go/thrift/header_transport.go index 1e8e302447a..f1dc99ce3a5 100644 --- a/lib/go/thrift/header_transport.go +++ b/lib/go/thrift/header_transport.go @@ -488,7 +488,7 @@ func (t *THeaderTransport) parseHeaders(ctx context.Context, frameSize uint32) e headers := make(THeaderMap) for { infoType, err := hp.readVarint32() - if err == io.EOF { + if errors.Is(err, io.EOF) { break } if err != nil { diff --git a/lib/go/thrift/http_client.go b/lib/go/thrift/http_client.go index 26e52b387d7..15015864f0f 100644 --- a/lib/go/thrift/http_client.go +++ b/lib/go/thrift/http_client.go @@ -22,6 +22,7 @@ package thrift import ( "bytes" "context" + "errors" "io" "io/ioutil" "net/http" @@ -159,7 +160,7 @@ func (p *THttpClient) Read(buf []byte) (int, error) { return 0, NewTTransportException(NOT_OPEN, "Response buffer is empty, no request.") } n, err := p.response.Body.Read(buf) - if n > 0 && (err == nil || err == io.EOF) { + if n > 0 && (err == nil || errors.Is(err, io.EOF)) { return n, nil } return n, NewTTransportExceptionFromError(err) diff --git a/lib/go/thrift/protocol_exception.go b/lib/go/thrift/protocol_exception.go index c86a9ff47d0..9dcf4bfd94c 100644 --- a/lib/go/thrift/protocol_exception.go +++ b/lib/go/thrift/protocol_exception.go @@ -21,6 +21,7 @@ package thrift import ( "encoding/base64" + "errors" ) // Thrift Protocol exception @@ -76,7 +77,7 @@ func NewTProtocolException(err error) TProtocolException { return e } - if _, ok := err.(base64.CorruptInputError); ok { + if errors.As(err, new(base64.CorruptInputError)) { return NewTProtocolExceptionWithType(INVALID_DATA, err) } diff --git a/lib/go/thrift/rich_transport.go b/lib/go/thrift/rich_transport.go index 4025bebeaa4..83fdf29f5cb 100644 --- a/lib/go/thrift/rich_transport.go +++ b/lib/go/thrift/rich_transport.go @@ -19,7 +19,10 @@ package thrift -import "io" +import ( + "errors" + "io" +) type RichTransport struct { TTransport @@ -49,7 +52,7 @@ func (r *RichTransport) RemainingBytes() (num_bytes uint64) { func readByte(r io.Reader) (c byte, err error) { v := [1]byte{0} n, err := r.Read(v[0:1]) - if n > 0 && (err == nil || err == io.EOF) { + if n > 0 && (err == nil || errors.Is(err, io.EOF)) { return v[0], nil } if n > 0 && err != nil { diff --git a/lib/go/thrift/simple_server.go b/lib/go/thrift/simple_server.go index ca0e61d0ea9..563cbfc694a 100644 --- a/lib/go/thrift/simple_server.go +++ b/lib/go/thrift/simple_server.go @@ -243,12 +243,11 @@ func treatEOFErrorsAsNil(err error) error { if err == nil { return nil } - // err could be io.EOF wrapped with TProtocolException, - // so that err == io.EOF doesn't necessarily work in some cases. - if err.Error() == io.EOF.Error() { + if errors.Is(err, io.EOF) { return nil } - if err, ok := err.(TTransportException); ok && err.TypeId() == END_OF_FILE { + var te TTransportException + if errors.As(err, &te) && te.TypeId() == END_OF_FILE { return nil } return err @@ -315,15 +314,14 @@ func (p *TSimpleServer) processRequests(client TTransport) (err error) { } ok, err := processor.Process(ctx, inputProtocol, outputProtocol) - // Once we dropped support for pre-go1.13 this can be replaced by: - // errors.Is(err, ErrAbandonRequest) - if unwrapError(err) == ErrAbandonRequest { + if errors.Is(err, ErrAbandonRequest) { return client.Close() } - if _, ok := err.(TTransportException); ok && err != nil { + if errors.As(err, new(TTransportException)) && err != nil { return err } - if err, ok := err.(TApplicationException); ok && err.TypeId() == UNKNOWN_METHOD { + var tae TApplicationException + if errors.As(err, &tae) && tae.TypeId() == UNKNOWN_METHOD { continue } if !ok { @@ -332,17 +330,3 @@ func (p *TSimpleServer) processRequests(client TTransport) (err error) { } return nil } - -type unwrapper interface { - Unwrap() error -} - -func unwrapError(err error) error { - for { - if u, ok := err.(unwrapper); ok { - err = u.Unwrap() - } else { - return err - } - } -} diff --git a/lib/go/thrift/socket_unix_conn.go b/lib/go/thrift/socket_unix_conn.go index 98e5a04dd6c..f5fab3ab653 100644 --- a/lib/go/thrift/socket_unix_conn.go +++ b/lib/go/thrift/socket_unix_conn.go @@ -22,6 +22,7 @@ package thrift import ( + "errors" "io" "syscall" "time" @@ -67,7 +68,7 @@ func (sc *socketConn) checkConn() error { return nil } - if err == syscall.EAGAIN || err == syscall.EWOULDBLOCK { + if errors.Is(err, syscall.EAGAIN) || errors.Is(err, syscall.EWOULDBLOCK) { // This means the connection is still open but we don't have // anything to read right now. return nil diff --git a/lib/go/thrift/transport_exception.go b/lib/go/thrift/transport_exception.go index 08f7ce229f2..0a3f07646d3 100644 --- a/lib/go/thrift/transport_exception.go +++ b/lib/go/thrift/transport_exception.go @@ -92,23 +92,23 @@ func NewTTransportExceptionFromError(e error) TTransportException { return t } - newTTransportException := func(typeID int, err error, prefix string) TTransportException { - return &tTransportException{ - typeId: typeID, - err: err, - msg: prefix + err.Error(), - } + te := &tTransportException{ + typeId: UNKNOWN_TRANSPORT_EXCEPTION, + err: e, + msg: e.Error(), } if isTimeoutError(e) { - return newTTransportException(TIMED_OUT, e, "") + te.typeId = TIMED_OUT + return te } - if e == io.EOF { - return newTTransportException(END_OF_FILE, e, "") + if errors.Is(e, io.EOF) { + te.typeId = END_OF_FILE + return te } - return newTTransportException(UNKNOWN_TRANSPORT_EXCEPTION, e, "") + return te } func prependTTransportException(prepend string, e TTransportException) TTransportException { @@ -119,11 +119,12 @@ func prependTTransportException(prepend string, e TTransportException) TTranspor } } -// isTimeoutError returns true when err is a timeout error. +// isTimeoutError returns true when err is an error caused by timeout. // // Note that this also includes TTransportException wrapped timeout errors. func isTimeoutError(err error) bool { - if t, ok := err.(timeoutable); ok { + var t timeoutable + if errors.As(err, &t) { return t.Timeout() } return false diff --git a/lib/go/thrift/transport_exception_test.go b/lib/go/thrift/transport_exception_test.go index 57386cb28ce..0d79409e727 100644 --- a/lib/go/thrift/transport_exception_test.go +++ b/lib/go/thrift/transport_exception_test.go @@ -47,12 +47,8 @@ func TestTExceptionTimeout(t *testing.T) { t.Errorf("TypeId was not TIMED_OUT: expected %v, got %v", TIMED_OUT, exception.TypeId()) } - // NOTE: this can also be replaced by errors.Unwrap, but that requires - // go 1.13+. - if e, ok := exception.(unwrapper); !ok { - t.Error("Expected exception to be unwrappable, it is not.") - } else if e.Unwrap() != timeout { - t.Errorf("Unwrapped exception did not match: expected %v, got %v", timeout, e.Unwrap()) + if unwrapped := errors.Unwrap(exception); unwrapped != timeout { + t.Errorf("Unwrapped exception did not match: expected %v, got %v", timeout, unwrapped) } } @@ -66,12 +62,8 @@ func TestTExceptionEOF(t *testing.T) { t.Errorf("TypeId was not END_OF_FILE: expected %v, got %v", END_OF_FILE, exception.TypeId()) } - // NOTE: this can also be replaced by errors.Unwrap, but that requires - // go 1.13+. - if e, ok := exception.(unwrapper); !ok { - t.Error("Expected exception to be unwrappable, it is not.") - } else if e.Unwrap() != io.EOF { - t.Errorf("Unwrapped exception did not match: expected %v, got %v", io.EOF, e.Unwrap()) + if unwrapped := errors.Unwrap(exception); unwrapped != io.EOF { + t.Errorf("Unwrapped exception did not match: expected %v, got %v", io.EOF, unwrapped) } } From d9fcdd3dbafbe1a8296018d0d6c55d972f607a42 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Wed, 20 Jan 2021 09:17:04 -0800 Subject: [PATCH 741/756] THRIFT-5338: Remove lib/go/thrift/go.mod Client: go Having it under a subdirectory has some unexpected consequences, so remove it for now. Another PR will be open up later to add it back to the root directory. --- lib/go/thrift/go.mod | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 lib/go/thrift/go.mod diff --git a/lib/go/thrift/go.mod b/lib/go/thrift/go.mod deleted file mode 100644 index 430c255a862..00000000000 --- a/lib/go/thrift/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/apache/thrift/lib/go/thrift - -go 1.14 From 8dd04f4adfaea08699b1745c79f122bf9cbd6f07 Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Fri, 22 Jan 2021 15:41:41 -0800 Subject: [PATCH 742/756] THRIFT-5322: THeaderTransport protocol id fix Client: go This fixes a bug introduced in https://github.com/apache/thrift/pull/2296, that we mixed the preferred proto id and the detected proto id, which was a bad idea. This change separates them, so when we propagate TConfiguration, we only change the preferred one, which will only be used for new connections, and leave the detected one from existing connections untouched. Also add a test for it. --- lib/go/thrift/header_transport.go | 17 +++++------------ lib/go/thrift/header_transport_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/lib/go/thrift/header_transport.go b/lib/go/thrift/header_transport.go index f1dc99ce3a5..f5736df4276 100644 --- a/lib/go/thrift/header_transport.go +++ b/lib/go/thrift/header_transport.go @@ -264,6 +264,7 @@ type THeaderTransport struct { writeTransforms []THeaderTransformID clientType clientType + protocolID THeaderProtocolID cfg *TConfiguration // buffer is used in the following scenarios to avoid repetitive @@ -303,6 +304,7 @@ func NewTHeaderTransportConf(trans TTransport, conf *TConfiguration) *THeaderTra transport: trans, reader: bufio.NewReader(trans), writeHeaders: make(THeaderMap), + protocolID: conf.GetTHeaderProtocolID(), cfg: conf, } } @@ -443,16 +445,7 @@ func (t *THeaderTransport) parseHeaders(ctx context.Context, frameSize uint32) e if err != nil { return err } - idPtr, err := THeaderProtocolIDPtr(THeaderProtocolID(protoID)) - if err != nil { - return err - } - if t.cfg == nil { - t.cfg = &TConfiguration{ - noPropagation: true, - } - } - t.cfg.THeaderProtocolID = idPtr + t.protocolID = THeaderProtocolID(protoID) var transformCount int32 transformCount, err = hp.readVarint32() @@ -597,7 +590,7 @@ func (t *THeaderTransport) Flush(ctx context.Context) error { headers := NewTMemoryBuffer() hp := NewTCompactProtocol(headers) hp.SetTConfiguration(t.cfg) - if _, err := hp.writeVarint32(int32(t.cfg.GetTHeaderProtocolID())); err != nil { + if _, err := hp.writeVarint32(int32(t.protocolID)); err != nil { return NewTTransportExceptionFromError(err) } if _, err := hp.writeVarint32(int32(len(t.writeTransforms))); err != nil { @@ -742,7 +735,7 @@ func (t *THeaderTransport) AddTransform(transform THeaderTransformID) error { func (t *THeaderTransport) Protocol() THeaderProtocolID { switch t.clientType { default: - return t.cfg.GetTHeaderProtocolID() + return t.protocolID case clientFramedBinary, clientUnframedBinary: return THeaderProtocolBinary case clientFramedCompact, clientUnframedCompact: diff --git a/lib/go/thrift/header_transport_test.go b/lib/go/thrift/header_transport_test.go index 41efb18988d..65e69ee5a37 100644 --- a/lib/go/thrift/header_transport_test.go +++ b/lib/go/thrift/header_transport_test.go @@ -281,3 +281,27 @@ func BenchmarkTHeaderProtocolIDValidate(b *testing.B) { }) } } + +func TestSetTHeaderTransportProtocolID(t *testing.T) { + const expected = THeaderProtocolCompact + factory := NewTHeaderTransportFactoryConf(nil, &TConfiguration{ + THeaderProtocolID: THeaderProtocolIDPtrMust(expected), + }) + buf := NewTMemoryBuffer() + trans, err := factory.GetTransport(buf) + if err != nil { + t.Fatalf("Failed to get transport from factory: %v", err) + } + ht, ok := trans.(*THeaderTransport) + if !ok { + t.Fatalf("Transport is not *THeaderTransport: %#v", trans) + } + if actual := ht.Protocol(); actual != expected { + t.Errorf("Expected protocol id %v, got %v", expected, actual) + } + + ht.SetTConfiguration(&TConfiguration{}) + if actual := ht.Protocol(); actual != expected { + t.Errorf("Expected protocol id %v, got %v", expected, actual) + } +} From c2ddaf0766499ab522cb7c0ca011d579707fcb5f Mon Sep 17 00:00:00 2001 From: Yuxuan 'fishy' Wang Date: Fri, 22 Jan 2021 09:37:18 -0800 Subject: [PATCH 743/756] THRIFT-4914: Make TClient.Call to return the response meta Client: go Make a breaking change so that TClient.Call returns the response meta, currently only contains headers but could be expanded in the future, and make a compiler change to compiler generated clients to take advantage of that and provide access to response metadata to users. --- CHANGES.md | 2 + .../cpp/src/thrift/generate/t_go_generator.cc | 38 +++++++++++++++---- lib/go/thrift/client.go | 24 +++++++++--- .../thrift/example_client_middleware_test.go | 6 +-- lib/go/thrift/header_protocol.go | 14 ------- lib/go/thrift/middleware.go | 4 +- lib/go/thrift/middleware_test.go | 6 +-- 7 files changed, 60 insertions(+), 34 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8e4d08edd95..c6c08f29f56 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -18,6 +18,7 @@ - [THRIFT-5152](https://issues.apache.org/jira/browse/THRIFT-5152) - go: TSocket and TSSLSocket now have separated connect timeout and socket timeout - c++: dropped support for Windows XP - [THRIFT-5326](https://issues.apache.org/jira/browse/THRIFT-5326) - go: TException interface now has a new function: TExceptionType +- [THRIFT-4914](https://issues.apache.org/jira/browse/THRIFT-4914) - go: TClient.Call now returns ResponseMeta in addition to error ### Java @@ -31,6 +32,7 @@ - [THRIFT-5233](https://issues.apache.org/jira/browse/THRIFT-5233) - Add context deadline check to ReadMessageBegin in TBinaryProtocol, TCompactProtocol, and THeaderProtocol. - [THRIFT-5240](https://issues.apache.org/jira/browse/THRIFT-5240) - The context passed into server handler implementations will be canceled when we detected that the client closed the connection. - [THRIFT-5322](https://issues.apache.org/jira/browse/THRIFT-5322) - Add support to TConfiguration, and also fix a bug that could cause excessive memory usage when reading malformed messages from TCompactProtocol. +- [THRIFT-4914](https://issues.apache.org/jira/browse/THRIFT-4914) - Compiler generated service clients now provide a new function, LastResponseMeta_(), to get the response metadata (e.g. headers from THeader) from the last client call. ## 0.13.0 diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index 49d8bc11977..33cd12d4642 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -1493,11 +1493,15 @@ void t_go_generator::generate_go_struct_definition(ostream& out, if (is_exception) { out << indent() << "func (p *" << tstruct_name << ") Error() string {" << endl; - out << indent() << indent() << "return p.String()" << endl; + indent_up(); + out << indent() << "return p.String()" << endl; + indent_down(); out << indent() << "}" << endl << endl; out << indent() << "func (" << tstruct_name << ") TExceptionType() thrift.TExceptionType {" << endl; - out << indent() << indent() << "return thrift.TExceptionTypeCompiled" << endl; + indent_up(); + out << indent() << "return thrift.TExceptionTypeCompiled" << endl; + indent_down(); out << indent() << "}" << endl << endl; out << indent() << "var _ thrift.TException = (*" << tstruct_name << ")(nil)" @@ -1990,6 +1994,7 @@ void t_go_generator::generate_service_client(t_service* tservice) { f_types_ << indent() << "*" << extends_client << endl; } else { f_types_ << indent() << "c thrift.TClient" << endl; + f_types_ << indent() << "meta thrift.ResponseMeta" << endl; } indent_down(); @@ -2059,7 +2064,19 @@ void t_go_generator::generate_service_client(t_service* tservice) { indent_up(); f_types_ << indent() << "return p.c" << endl; indent_down(); - f_types_ << indent() << "}" << endl; + f_types_ << indent() << "}" << endl << endl; + + f_types_ << indent() << "func (p *" << serviceName << "Client) LastResponseMeta_() thrift.ResponseMeta {" << endl; + indent_up(); + f_types_ << indent() << "return p.meta" << endl; + indent_down(); + f_types_ << indent() << "}" << endl << endl; + + f_types_ << indent() << "func (p *" << serviceName << "Client) SetLastResponseMeta_(meta thrift.ResponseMeta) {" << endl; + indent_up(); + f_types_ << indent() << "p.meta = meta" << endl; + indent_down(); + f_types_ << indent() << "}" << endl << endl; } // Generate client method implementations @@ -2091,8 +2108,11 @@ void t_go_generator::generate_service_client(t_service* tservice) { std::string resultName = tmp("_result"); std::string resultType = publicize(method + "_result", true); f_types_ << indent() << "var " << resultName << " " << resultType << endl; - f_types_ << indent() << "if err = p.Client_().Call(ctx, \"" - << method << "\", &" << argsName << ", &" << resultName << "); err != nil {" << endl; + f_types_ << indent() << "var meta thrift.ResponseMeta" << endl; + f_types_ << indent() << "meta, err = p.Client_().Call(ctx, \"" + << method << "\", &" << argsName << ", &" << resultName << ")" << endl; + f_types_ << indent() << "p.SetLastResponseMeta_(meta)" << endl; + f_types_ << indent() << "if err != nil {" << endl; indent_up(); f_types_ << indent() << "return" << endl; @@ -2131,9 +2151,13 @@ void t_go_generator::generate_service_client(t_service* tservice) { f_types_ << indent() << "return nil" << endl; } } else { + // Since we don't have response meta for oneway calls, overwrite it with + // an empty one to avoid users getting the meta from last call and + // mistaken it as from the oneway call. + f_types_ << indent() << "p.SetLastResponseMeta_(thrift.ResponseMeta{})" << endl; // TODO: would be nice to not to duplicate the call generation - f_types_ << indent() << "if err := p.Client_().Call(ctx, \"" - << method << "\", &"<< argsName << ", nil); err != nil {" << endl; + f_types_ << indent() << "if _, err := p.Client_().Call(ctx, \"" + << method << "\", &"<< argsName << ", nil); err != nil {" << endl; indent_up(); f_types_ << indent() << "return err" << endl; diff --git a/lib/go/thrift/client.go b/lib/go/thrift/client.go index 1c5705d5522..ea2c01fdadb 100644 --- a/lib/go/thrift/client.go +++ b/lib/go/thrift/client.go @@ -5,8 +5,15 @@ import ( "fmt" ) +// ResponseMeta represents the metadata attached to the response. +type ResponseMeta struct { + // The headers in the response, if any. + // If the underlying transport/protocol is not THeader, this will always be nil. + Headers THeaderMap +} + type TClient interface { - Call(ctx context.Context, method string, args, result TStruct) error + Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) } type TStandardClient struct { @@ -78,18 +85,25 @@ func (p *TStandardClient) Recv(ctx context.Context, iprot TProtocol, seqId int32 return iprot.ReadMessageEnd(ctx) } -func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) error { +func (p *TStandardClient) Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { p.seqId++ seqId := p.seqId if err := p.Send(ctx, p.oprot, seqId, method, args); err != nil { - return err + return ResponseMeta{}, err } // method is oneway if result == nil { - return nil + return ResponseMeta{}, nil } - return p.Recv(ctx, p.iprot, seqId, method, result) + err := p.Recv(ctx, p.iprot, seqId, method, result) + var headers THeaderMap + if hp, ok := p.iprot.(*THeaderProtocol); ok { + headers = hp.transport.readHeaders + } + return ResponseMeta{ + Headers: headers, + }, err } diff --git a/lib/go/thrift/example_client_middleware_test.go b/lib/go/thrift/example_client_middleware_test.go index 8a29083c088..a68cdbc348b 100644 --- a/lib/go/thrift/example_client_middleware_test.go +++ b/lib/go/thrift/example_client_middleware_test.go @@ -45,16 +45,16 @@ func NewMyServiceClient(_ TClient) MyService { func simpleClientLoggingMiddleware(next TClient) TClient { return WrappedTClient{ - Wrapped: func(ctx context.Context, method string, args, result TStruct) error { + Wrapped: func(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { log.Printf("Before: %q", method) log.Printf("Args: %#v", args) - err := next.Call(ctx, method, args, result) + headers, err := next.Call(ctx, method, args, result) log.Printf("After: %q", method) log.Printf("Result: %#v", result) if err != nil { log.Printf("Error: %v", err) } - return err + return headers, err }, } } diff --git a/lib/go/thrift/header_protocol.go b/lib/go/thrift/header_protocol.go index 35e0458051c..878041f8df1 100644 --- a/lib/go/thrift/header_protocol.go +++ b/lib/go/thrift/header_protocol.go @@ -345,20 +345,6 @@ func (p *THeaderProtocol) SetTConfiguration(cfg *TConfiguration) { p.cfg = cfg } -// GetResponseHeadersFromClient is a helper function to get the read THeaderMap -// from the last response received from the given client. -// -// If the last response was not sent over THeader protocol, -// a nil map will be returned. -func GetResponseHeadersFromClient(c TClient) THeaderMap { - if sc, ok := c.(*TStandardClient); ok { - if hp, ok := sc.iprot.(*THeaderProtocol); ok { - return hp.transport.readHeaders - } - } - return nil -} - var ( _ TConfigurationSetter = (*tHeaderProtocolFactory)(nil) _ TConfigurationSetter = (*THeaderProtocol)(nil) diff --git a/lib/go/thrift/middleware.go b/lib/go/thrift/middleware.go index b575e16c42a..8a788df02be 100644 --- a/lib/go/thrift/middleware.go +++ b/lib/go/thrift/middleware.go @@ -78,11 +78,11 @@ type ClientMiddleware func(TClient) TClient // // This is provided to aid in developing ClientMiddleware. type WrappedTClient struct { - Wrapped func(ctx context.Context, method string, args, result TStruct) error + Wrapped func(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) } // Call implements the TClient interface by calling and returning c.Wrapped. -func (c WrappedTClient) Call(ctx context.Context, method string, args, result TStruct) error { +func (c WrappedTClient) Call(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { return c.Wrapped(ctx, method, args, result) } diff --git a/lib/go/thrift/middleware_test.go b/lib/go/thrift/middleware_test.go index 2a4d1f9574d..6c4058fe133 100644 --- a/lib/go/thrift/middleware_test.go +++ b/lib/go/thrift/middleware_test.go @@ -54,7 +54,7 @@ func testProcessorMiddleware(c *counter) ProcessorMiddleware { func testClientMiddleware(c *counter) ClientMiddleware { return func(next TClient) TClient { return WrappedTClient{ - Wrapped: func(ctx context.Context, method string, args, result TStruct) error { + Wrapped: func(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { c.incr() return next.Call(ctx, method, args, result) }, @@ -122,8 +122,8 @@ func TestWrapTMultiplexedProcessor(t *testing.T) { func TestWrapClient(t *testing.T) { client := WrappedTClient{ - Wrapped: func(ctx context.Context, method string, args, result TStruct) error { - return nil + Wrapped: func(ctx context.Context, method string, args, result TStruct) (ResponseMeta, error) { + return ResponseMeta{}, nil }, } c := newCounter(t) From bee96a1ff02d682c955707406f21164cd8d66552 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Fri, 1 Jan 2021 23:25:28 +0100 Subject: [PATCH 744/756] netstd fix IDE warning --- compiler/cpp/src/thrift/generate/t_netstd_generator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc index b90f71a3d6c..5048c0ef2b0 100644 --- a/compiler/cpp/src/thrift/generate/t_netstd_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_netstd_generator.cc @@ -1517,7 +1517,7 @@ void t_netstd_generator::generate_netstd_struct_tostring(ostream& out, t_struct* } } - out << indent() << "sb.Append(\")\");" << endl + out << indent() << "sb.Append(')');" << endl << indent() << "return sb.ToString();" << endl; indent_down(); out << indent() << "}" << endl; From 0f21e39c9ba1b20a50d035f01c14836885678d08 Mon Sep 17 00:00:00 2001 From: "vladimir.panivko" Date: Tue, 19 Jan 2021 10:04:11 +0200 Subject: [PATCH 745/756] THRIFT-5336 Add possibility to setup connection timeout in TCurlClient Patch: Vladimir Panivko Client: php This closes #2306 --- lib/php/lib/Transport/TCurlClient.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/php/lib/Transport/TCurlClient.php b/lib/php/lib/Transport/TCurlClient.php index f781da96963..2087433dd54 100644 --- a/lib/php/lib/Transport/TCurlClient.php +++ b/lib/php/lib/Transport/TCurlClient.php @@ -83,6 +83,13 @@ class TCurlClient extends TTransport */ protected $timeout_; + /** + * Connection timeout + * + * @var float + */ + protected $connectionTimeout_; + /** * http headers * @@ -109,6 +116,7 @@ public function __construct($host, $port = 80, $uri = '', $scheme = 'http') $this->request_ = ''; $this->response_ = null; $this->timeout_ = null; + $this->connectionTimeout_ = null; $this->headers_ = array(); } @@ -122,6 +130,16 @@ public function setTimeoutSecs($timeout) $this->timeout_ = $timeout; } + /** + * Set connection timeout + * + * @param float $connectionTimeout + */ + public function setConnectionTimeoutSecs($connectionTimeout) + { + $this->connectionTimeout_ = $connectionTimeout; + } + /** * Whether this transport is open. * @@ -237,6 +255,14 @@ public function flush() curl_setopt(self::$curlHandle, CURLOPT_TIMEOUT, $this->timeout_); } } + if ($this->connectionTimeout_ > 0) { + if ($this->connectionTimeout_ < 1.0) { + // Timestamps smaller than 1 second are ignored when CURLOPT_CONNECTTIMEOUT is used + curl_setopt(self::$curlHandle, CURLOPT_CONNECTTIMEOUT_MS, 1000 * $this->connectionTimeout_); + } else { + curl_setopt(self::$curlHandle, CURLOPT_CONNECTTIMEOUT, $this->connectionTimeout_); + } + } curl_setopt(self::$curlHandle, CURLOPT_POSTFIELDS, $this->request_); $this->request_ = ''; From 1f73455940c440cd9b4226c92e01ae0f0378705c Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 28 Jan 2021 08:48:24 +0100 Subject: [PATCH 746/756] THRIFT-5237 Implement MAX_MESSAGE_SIZE and consolidate limits into a TConfiguration class (cpp) Client: cpp Patch: Jens Geyer Fixes an issue introduced with that ticket --- lib/cpp/src/thrift/transport/TTransport.h | 6 ++-- lib/cpp/test/ThrifttReadCheckTests.cpp | 36 +++++++++++------------ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/cpp/src/thrift/transport/TTransport.h b/lib/cpp/src/thrift/transport/TTransport.h index 5f657f89b16..52b3a0a4d32 100644 --- a/lib/cpp/src/thrift/transport/TTransport.h +++ b/lib/cpp/src/thrift/transport/TTransport.h @@ -275,7 +275,7 @@ class TTransport { void checkReadBytesAvailable(long int numBytes) { if (remainingMessageSize_ < numBytes) - throw new TTransportException(TTransportException::END_OF_FILE, "MaxMessageSize reached"); + throw TTransportException(TTransportException::END_OF_FILE, "MaxMessageSize reached"); } protected: @@ -306,7 +306,7 @@ class TTransport { // update only: message size can shrink, but not grow if (newSize > knownMessageSize_) - throw new TTransportException(TTransportException::END_OF_FILE, "MaxMessageSize reached"); + throw TTransportException(TTransportException::END_OF_FILE, "MaxMessageSize reached"); knownMessageSize_ = newSize; remainingMessageSize_ = newSize; @@ -326,7 +326,7 @@ class TTransport { else { remainingMessageSize_ = 0; - throw new TTransportException(TTransportException::END_OF_FILE, "MaxMessageSize reached"); + throw TTransportException(TTransportException::END_OF_FILE, "MaxMessageSize reached"); } } }; diff --git a/lib/cpp/test/ThrifttReadCheckTests.cpp b/lib/cpp/test/ThrifttReadCheckTests.cpp index 4a594e6ca6d..eb4ca01b235 100644 --- a/lib/cpp/test/ThrifttReadCheckTests.cpp +++ b/lib/cpp/test/ThrifttReadCheckTests.cpp @@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(test_tmemorybuffer_read_check_exception) { TMemoryBuffer trans_in(config); memset(buffer, 0, sizeof(buffer)); - BOOST_CHECK_THROW(trans_in.read(buffer, sizeof(buffer)), TTransportException*); + BOOST_CHECK_THROW(trans_in.read(buffer, sizeof(buffer)), TTransportException); trans_in.close(); } @@ -85,13 +85,13 @@ BOOST_AUTO_TEST_CASE(test_tpipedtransport_read_check_exception) { uint8_t buffer[4]; underlying->write((uint8_t*)"abcd", 4); - BOOST_CHECK_THROW(trans->read(buffer, sizeof(buffer)), TTransportException*); - BOOST_CHECK_THROW(trans->readAll(buffer, sizeof(buffer)), TTransportException*); + BOOST_CHECK_THROW(trans->read(buffer, sizeof(buffer)), TTransportException); + BOOST_CHECK_THROW(trans->readAll(buffer, sizeof(buffer)), TTransportException); trans->readEnd(); pipe->resetBuffer(); underlying->write((uint8_t*)"ef", 2); - BOOST_CHECK_THROW(trans->read(buffer, sizeof(buffer)), TTransportException*); - BOOST_CHECK_THROW(trans->readAll(buffer, sizeof(buffer)), TTransportException*); + BOOST_CHECK_THROW(trans->read(buffer, sizeof(buffer)), TTransportException); + BOOST_CHECK_THROW(trans->readAll(buffer, sizeof(buffer)), TTransportException); trans->readEnd(); } @@ -104,7 +104,7 @@ BOOST_AUTO_TEST_CASE(test_tsimplefiletransport_read_check_exception) { TSimpleFileTransport trans_in("data",true, false, config); memset(buffer, 0, sizeof(buffer)); - BOOST_CHECK_THROW(trans_in.read(buffer, sizeof(buffer)), TTransportException*); + BOOST_CHECK_THROW(trans_in.read(buffer, sizeof(buffer)), TTransportException); trans_in.close(); remove("./data"); @@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(test_tfiletransport_read_check_exception) { TFileTransport trans_in("data", false, config); memset(buffer, 0, sizeof(buffer)); - BOOST_CHECK_THROW(trans_in.read(buffer, sizeof(buffer)), TTransportException*); + BOOST_CHECK_THROW(trans_in.read(buffer, sizeof(buffer)), TTransportException); remove("./data"); } @@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(test_tbufferedtransport_read_check_exception) { std::shared_ptr trans (new TBufferedTransport(buffer, config)); trans->write((const uint8_t*)arr, sizeof(arr)); - BOOST_CHECK_THROW(trans->read(arr, sizeof(arr)), TTransportException*); + BOOST_CHECK_THROW(trans->read(arr, sizeof(arr)), TTransportException); } BOOST_AUTO_TEST_CASE(test_tframedtransport_read_check_exception) { @@ -140,7 +140,7 @@ BOOST_AUTO_TEST_CASE(test_tframedtransport_read_check_exception) { std::shared_ptr trans (new TFramedTransport(buffer, config)); trans->write((const uint8_t*)arr, sizeof(arr)); - BOOST_CHECK_THROW(trans->read(arr, sizeof(arr)), TTransportException*); + BOOST_CHECK_THROW(trans->read(arr, sizeof(arr)), TTransportException); } BOOST_AUTO_TEST_CASE(test_tthriftbinaryprotocol_read_check_exception) { @@ -154,19 +154,19 @@ BOOST_AUTO_TEST_CASE(test_tthriftbinaryprotocol_read_check_exception) { TList list(T_I32, 8); protocol->writeListBegin(list.elemType_, list.size_); protocol->writeListEnd(); - BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException*); + BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException); protocol->readListEnd(); TSet set(T_I32, 8); protocol->writeSetBegin(set.elemType_, set.size_); protocol->writeSetEnd(); - BOOST_CHECK_THROW(protocol->readSetBegin(elemType, val), TTransportException*); + BOOST_CHECK_THROW(protocol->readSetBegin(elemType, val), TTransportException); protocol->readSetEnd(); TMap map(T_I32, T_I32, 8); protocol->writeMapBegin(map.keyType_, map.valueType_, map.size_); protocol->writeMapEnd(); - BOOST_CHECK_THROW(protocol->readMapBegin(elemType, elemType1, val), TTransportException*); + BOOST_CHECK_THROW(protocol->readMapBegin(elemType, elemType1, val), TTransportException); protocol->readMapEnd(); } @@ -181,19 +181,19 @@ BOOST_AUTO_TEST_CASE(test_tthriftcompactprotocol_read_check_exception) { TList list(T_I32, 8); protocol->writeListBegin(list.elemType_, list.size_); protocol->writeListEnd(); - BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException*); + BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException); protocol->readListEnd(); TSet set(T_I32, 8); protocol->writeSetBegin(set.elemType_, set.size_); protocol->writeSetEnd(); - BOOST_CHECK_THROW(protocol->readSetBegin(elemType, val), TTransportException*); + BOOST_CHECK_THROW(protocol->readSetBegin(elemType, val), TTransportException); protocol->readSetEnd(); TMap map(T_I32, T_I32, 8); protocol->writeMapBegin(map.keyType_, map.valueType_, map.size_); protocol->writeMapEnd(); - BOOST_CHECK_THROW(protocol->readMapBegin(elemType, elemType1, val), TTransportException*); + BOOST_CHECK_THROW(protocol->readMapBegin(elemType, elemType1, val), TTransportException); protocol->readMapEnd(); } @@ -208,19 +208,19 @@ BOOST_AUTO_TEST_CASE(test_tthriftjsonprotocol_read_check_exception) { TList list(T_I32, 8); protocol->writeListBegin(list.elemType_, list.size_); protocol->writeListEnd(); - BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException*); + BOOST_CHECK_THROW(protocol->readListBegin(elemType, val), TTransportException); protocol->readListEnd(); TSet set(T_I32, 8); protocol->writeSetBegin(set.elemType_, set.size_); protocol->writeSetEnd(); - BOOST_CHECK_THROW(protocol->readSetBegin(elemType, val), TTransportException*); + BOOST_CHECK_THROW(protocol->readSetBegin(elemType, val), TTransportException); protocol->readSetEnd(); TMap map(T_I32, T_I32, 8); protocol->writeMapBegin(map.keyType_, map.valueType_, map.size_); protocol->writeMapEnd(); - BOOST_CHECK_THROW(protocol->readMapBegin(elemType, elemType1, val), TTransportException*); + BOOST_CHECK_THROW(protocol->readMapBegin(elemType, elemType1, val), TTransportException); protocol->readMapEnd(); } From 4aaef75819aea3f79ec812393dbe13bb62bd6c45 Mon Sep 17 00:00:00 2001 From: wangtieju Date: Thu, 4 Feb 2021 11:26:44 +0800 Subject: [PATCH 747/756] THRIFT-5337 Go set fields write improvement Client: go There is a duplicate elements check for set in writeFields* function, and it compares elements using reflect.DeepEqual which is expensive. It's much faster that generates a *Equals* function for set elements and call it in duplicate elements check, especially for nested struct element. Closes #2307. --- .../cpp/src/thrift/generate/t_go_generator.cc | 199 +++++++++++++- lib/go/test/EqualsTest.thrift | 109 ++++++++ lib/go/test/Makefile.am | 7 +- lib/go/test/tests/equals_test.go | 243 ++++++++++++++++++ 4 files changed, 549 insertions(+), 9 deletions(-) create mode 100644 lib/go/test/EqualsTest.thrift create mode 100644 lib/go/test/tests/equals_test.go diff --git a/compiler/cpp/src/thrift/generate/t_go_generator.cc b/compiler/cpp/src/thrift/generate/t_go_generator.cc index 33cd12d4642..d9f9d51c5af 100644 --- a/compiler/cpp/src/thrift/generate/t_go_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_go_generator.cc @@ -152,6 +152,7 @@ class t_go_generator : public t_generator { const string& tstruct_name, bool is_result = false, bool uses_countsetfields = false); + void generate_go_struct_equals(std::ostream& out, t_struct* tstruct, const string& tstruct_name); void generate_go_function_helpers(t_function* tfunction); void get_publicized_name_and_def_value(t_field* tfield, string* OUT_pub_name, @@ -229,6 +230,12 @@ class t_go_generator : public t_generator { void generate_serialize_list_element(std::ostream& out, t_list* tlist, std::string iter); + void generate_go_equals(std::ostream& out, t_type* ttype, string tgt, string src); + + void generate_go_equals_struct(std::ostream& out, t_type* ttype, string tgt, string src); + + void generate_go_equals_container(std::ostream& out, t_type* ttype, string tgt, string src); + void generate_go_docstring(std::ostream& out, t_struct* tstruct); void generate_go_docstring(std::ostream& out, t_function* tfunction); @@ -307,6 +314,7 @@ class t_go_generator : public t_generator { std::set package_identifiers_set_; std::string read_method_name_; std::string write_method_name_; + std::string equals_method_name_; std::set commonInitialisms; @@ -724,6 +732,7 @@ void t_go_generator::init_generator() { read_method_name_ = "Read"; write_method_name_ = "Write"; } + equals_method_name_ = "Equals"; while (true) { // TODO: Do better error checking here. @@ -912,7 +921,6 @@ string t_go_generator::go_imports_begin(bool consts) { std::vector system_packages; system_packages.push_back("bytes"); system_packages.push_back("context"); - system_packages.push_back("reflect"); // If not writing constants, and there are enums, need extra imports. if (!consts && get_program()->get_enums().size() > 0) { system_packages.push_back("database/sql/driver"); @@ -937,7 +945,6 @@ string t_go_generator::go_imports_end() { "var _ = thrift.ZERO\n" "var _ = fmt.Printf\n" "var _ = context.Background\n" - "var _ = reflect.DeepEqual\n" "var _ = time.Now\n" "var _ = bytes.Equal\n\n"); } @@ -1482,6 +1489,9 @@ void t_go_generator::generate_go_struct_definition(ostream& out, generate_isset_helpers(out, tstruct, tstruct_name, is_result); generate_go_struct_reader(out, tstruct, tstruct_name, is_result); generate_go_struct_writer(out, tstruct, tstruct_name, is_result, num_setable > 0); + if (!is_result && !is_args) { + generate_go_struct_equals(out, tstruct, tstruct_name); + } out << indent() << "func (p *" << tstruct_name << ") String() string {" << endl; out << indent() << " if p == nil {" << endl; @@ -1851,6 +1861,61 @@ void t_go_generator::generate_go_struct_writer(ostream& out, } } +void t_go_generator::generate_go_struct_equals(ostream& out, + t_struct* tstruct, + const string& tstruct_name) { + string name(tstruct->get_name()); + const vector& fields = tstruct->get_sorted_members(); + vector::const_iterator f_iter; + indent(out) << "func (p *" << tstruct_name << ") " << equals_method_name_ << "(other *" + << tstruct_name << ") bool {" << endl; + indent_up(); + + string field_name; + string publicize_field_name; + out << indent() << "if p == other {" << endl; + indent_up(); + out << indent() << "return true" << endl; + indent_down(); + out << indent() << "} else if p == nil || other == nil {" << endl; + indent_up(); + out << indent() << "return false" << endl; + indent_down(); + out << indent() << "}" << endl; + + for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) { + field_name = (*f_iter)->get_name(); + t_type* field_type = (*f_iter)->get_type(); + publicize_field_name = publicize(field_name); + string goType = type_to_go_type_with_opt(field_type, is_pointer_field(*f_iter)); + + string tgt = "p." + publicize_field_name; + string src = "other." + publicize_field_name; + t_type* ttype = field_type->get_true_type(); + // Compare field contents + if (is_pointer_field(*f_iter) + && (ttype->is_base_type() || ttype->is_enum() || ttype->is_container())) { + string tgtv = "(*" + tgt + ")"; + string srcv = "(*" + src + ")"; + out << indent() << "if " << tgt << " != " << src << " {" << endl; + indent_up(); + out << indent() << "if " << tgt << " == nil || " << src << " == nil {" << endl; + indent_up(); + out << indent() << "return false" << endl; + indent_down(); + out << indent() << "}" << endl; + generate_go_equals(out, field_type, tgtv, srcv); + indent_down(); + out << indent() << "}" << endl; + } else { + generate_go_equals(out, field_type, tgt, src); + } + } + out << indent() << "return true" << endl; + indent_down(); + out << indent() << "}" << endl << endl; +} + /** * Generates a thrift service. * @@ -3389,15 +3454,30 @@ void t_go_generator::generate_serialize_container(ostream& out, } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; out << indent() << "for i := 0; iget_elem_type()); + out << indent() << "if func(tgt, src " << goType << ") bool {" << endl; + indent_up(); + generate_go_equals(out, tset->get_elem_type(), "tgt", "src"); + out << indent() << "return true" << endl; + indent_down(); + out << indent() << "}(" << wrapped_prefix << "[i], " << wrapped_prefix << "[j]) {" << endl; + indent_up(); + out << indent() + << "return thrift.PrependError(\"\", fmt.Errorf(\"%T error writing set field: slice is not " + "unique\", " + << wrapped_prefix << "))" << endl; + indent_down(); + out << indent() << "}" << endl; + indent_down(); + out << indent() << "}" << endl; + indent_down(); out << indent() << "}" << endl; out << indent() << "for _, v := range " << prefix << " {" << endl; indent_up(); @@ -3463,6 +3543,111 @@ void t_go_generator::generate_serialize_list_element(ostream& out, t_list* tlist generate_serialize_field(out, &efield, prefix); } +/** + * Compares any type + */ +void t_go_generator::generate_go_equals(ostream& out, t_type* ori_type, string tgt, string src) { + + t_type* ttype = get_true_type(ori_type); + // Do nothing for void types + if (ttype->is_void()) { + throw "compiler error: cannot generate equals for void type: " + tgt; + } + + if (ttype->is_struct() || ttype->is_xception()) { + generate_go_equals_struct(out, ttype, tgt, src); + } else if (ttype->is_container()) { + generate_go_equals_container(out, ttype, tgt, src); + } else if (ttype->is_base_type() || ttype->is_enum()) { + out << indent() << "if "; + if (ttype->is_base_type()) { + t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base(); + switch (tbase) { + case t_base_type::TYPE_VOID: + throw "compiler error: cannot equals void: " + tgt; + break; + + case t_base_type::TYPE_STRING: + if (ttype->is_binary()) { + out << "bytes.Compare(" << tgt << ", " << src << ") != 0"; + } else { + out << tgt << " != " << src; + } + break; + + case t_base_type::TYPE_BOOL: + case t_base_type::TYPE_I8: + case t_base_type::TYPE_I16: + case t_base_type::TYPE_I32: + case t_base_type::TYPE_I64: + case t_base_type::TYPE_DOUBLE: + out << tgt << " != " << src; + break; + + default: + throw "compiler error: no Go name for base type " + t_base_type::t_base_name(tbase); + } + } else if (ttype->is_enum()) { + out << tgt << " != " << src; + } + + out << " { return false }" << endl; + } else { + throw "compiler error: Invalid type in generate_go_equals '" + ttype->get_name() + "' for '" + + tgt + "'"; + } +} + +/** + * Compares the members of a struct + */ +void t_go_generator::generate_go_equals_struct(ostream& out, + t_type* ttype, + string tgt, + string src) { + (void)ttype; + out << indent() << "if !" << tgt << "." << equals_method_name_ << "(" << src + << ") { return false }" << endl; +} + +/** + * Compares any container type + */ +void t_go_generator::generate_go_equals_container(ostream& out, + t_type* ttype, + string tgt, + string src) { + out << indent() << "if len(" << tgt << ") != len(" << src << ") { return false }" << endl; + if (ttype->is_map()) { + t_map* tmap = (t_map*)ttype; + out << indent() << "for k, _tgt := range " << tgt << " {" << endl; + indent_up(); + string element_source = tmp("_src"); + out << indent() << element_source << " := " << src << "[k]" << endl; + generate_go_equals(out, tmap->get_val_type(), "_tgt", element_source); + indent_down(); + indent(out) << "}" << endl; + } else if (ttype->is_list() || ttype->is_set()) { + t_type* elem; + if (ttype->is_list()) { + t_list* temp = (t_list*)ttype; + elem = temp->get_elem_type(); + } else { + t_set* temp = (t_set*)ttype; + elem = temp->get_elem_type(); + } + out << indent() << "for i, _tgt := range " << tgt << " {" << endl; + indent_up(); + string element_source = tmp("_src"); + out << indent() << element_source << " := " << src << "[i]" << endl; + generate_go_equals(out, elem, "_tgt", element_source); + indent_down(); + indent(out) << "}" << endl; + } else { + throw "INVALID TYPE IN generate_go_equals_container '" + ttype->get_name(); + } +} + /** * Generates the docstring for a given struct. */ diff --git a/lib/go/test/EqualsTest.thrift b/lib/go/test/EqualsTest.thrift new file mode 100644 index 00000000000..c699232b4d2 --- /dev/null +++ b/lib/go/test/EqualsTest.thrift @@ -0,0 +1,109 @@ +typedef i8 mybyte +typedef string mystr +typedef binary mybin + +enum EnumFoo { + e1 + e2 +} + +struct BasicEqualsFoo { + 1: bool BoolFoo, + 2: optional bool OptBoolFoo, + 3: i8 I8Foo, + 4: optional i8 OptI8Foo, + 5: i16 I16Foo, + 6: optional i16 OptI16Foo, + 7: i32 I32Foo, + 8: optional i32 OptI32Foo, + 9: i64 I64Foo, + 10: optional i64 OptI64Foo, + 11: double DoubleFoo, + 12: optional double OptDoubleFoo, + 13: string StrFoo, + 14: optional string OptStrFoo, + 15: binary BinFoo, + 16: optional binary OptBinFoo, + 17: EnumFoo EnumFoo, + 18: optional EnumFoo OptEnumFoo, + 19: mybyte MyByteFoo, + 20: optional mybyte OptMyByteFoo, + 21: mystr MyStrFoo, + 22: optional mystr OptMyStrFoo, + 23: mybin MyBinFoo, + 24: optional mybin OptMyBinFoo, +} + +struct StructEqualsFoo { + 1: BasicEqualsFoo StructFoo, + 2: optional BasicEqualsFoo OptStructFoo, +} + +struct ListEqualsFoo { + 1: list I64ListFoo, + 2: optional list OptI64ListFoo, + 3: list StrListFoo, + 4: optional list OptStrListFoo, + 5: list BinListFoo, + 6: optional list OptBinListFoo, + 7: list StructListFoo, + 8: optional list OptStructListFoo, + 9: list> I64ListListFoo, + 10: optional list> OptI64ListListFoo, + 11: list> I64SetListFoo, + 12: optional list> OptI64SetListFoo, + 13: list> I64StringMapListFoo, + 14: optional list> OptI64StringMapListFoo, + 15: list MyByteListFoo, + 16: optional list OptMyByteListFoo, + 17: list MyStrListFoo, + 18: optional list OptMyStrListFoo, + 19: list MyBinListFoo, + 20: optional list OptMyBinListFoo, +} + +struct SetEqualsFoo { + 1: set I64SetFoo, + 2: optional set OptI64SetFoo, + 3: set StrSetFoo, + 4: optional set OptStrSetFoo, + 5: set BinSetFoo, + 6: optional set OptBinSetFoo, + 7: set StructSetFoo, + 8: optional set OptStructSetFoo, + 9: set> I64ListSetFoo, + 10: optional set> OptI64ListSetFoo, + 11: set> I64SetSetFoo, + 12: optional set> OptI64SetSetFoo, + 13: set> I64StringMapSetFoo, + 14: optional set> OptI64StringMapSetFoo, + 15: set MyByteSetFoo, + 16: optional set OptMyByteSetFoo, + 17: set MyStrSetFoo, + 18: optional set OptMyStrSetFoo, + 19: set MyBinSetFoo, + 20: optional set OptMyBinSetFoo, +} + +struct MapEqualsFoo { + 1: map I64StrMapFoo, + 2: optional map OptI64StrMapFoo, + 3: map StrI64MapFoo, + 4: optional map OptStrI64MapFoo, + 5: map StructBinMapFoo, + 6: optional map OptStructBinMapFoo, + 7: map BinStructMapFoo, + 8: optional map OptBinStructMapFoo, + 9: map> I64I64ListMapFoo, + 10: optional map> OptI64I64ListMapFoo, + 11: map> I64I64SetMapFoo, + 12: optional map> OptI64I64SetMapFoo, + 13: map> I64I64StringMapMapFoo, + 14: optional map> OptI64I64StringMapMapFoo, + 15: map MyStrMyBinMapFoo, + 16: optional map OptMyStrMyBinMapFoo, + 17: map Int64MyByteMapFoo, + 18: optional map OptInt64MyByteMapFoo, + 19: map MyByteInt64MapFoo, + 20: optional map OptMyByteInt64MapFoo, +} \ No newline at end of file diff --git a/lib/go/test/Makefile.am b/lib/go/test/Makefile.am index f5de26e6f29..4419577696d 100644 --- a/lib/go/test/Makefile.am +++ b/lib/go/test/Makefile.am @@ -73,6 +73,7 @@ gopath: $(THRIFT) $(THRIFTTEST) \ $(THRIFT) $(THRIFTARGS) ConflictNamespaceTestSuperThing.thrift $(THRIFT) $(THRIFTARGS) ConflictNamespaceServiceTest.thrift $(THRIFT) $(THRIFTARGS) -r DuplicateImportsTest.thrift + $(THRIFT) $(THRIFTARGS) EqualsTest.thrift GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock || true sed -i 's/\"context\"/\"golang.org\/x\/net\/context\"/g' gopath/src/github.com/golang/mock/gomock/controller.go || true GOPATH=`pwd`/gopath $(GO) get github.com/golang/mock/gomock @@ -97,7 +98,8 @@ check: gopath conflictnamespacetestsuperthing \ conflict/context/conflict_service-remote \ servicestest/container_test-remote \ - duplicateimportstest + duplicateimportstest \ + equalstest GOPATH=`pwd`/gopath $(GO) test thrift tests dontexportrwtest clean-local: @@ -132,4 +134,5 @@ EXTRA_DIST = \ ConflictNamespaceTestC.thrift \ ConflictNamespaceTestD.thrift \ ConflictNamespaceTestSuperThing.thrift \ - ConflictNamespaceServiceTest.thrift + ConflictNamespaceServiceTest.thrift \ + EqualsTest.thrift diff --git a/lib/go/test/tests/equals_test.go b/lib/go/test/tests/equals_test.go new file mode 100644 index 00000000000..3489efa0d50 --- /dev/null +++ b/lib/go/test/tests/equals_test.go @@ -0,0 +1,243 @@ +package tests + +import ( + "equalstest" + "strconv" + "testing" +) + +func TestEquals(t *testing.T) { + // test basic field + basicTgt, basicSrc := genBasicFoo(), genBasicFoo() + if !basicTgt.Equals(basicSrc) { + t.Error("BasicEqualsFoo.Equals() test failed") + } + basicSrc.EnumFoo = equalstest.EnumFoo_e2 + if basicTgt.Equals(basicSrc) { + t.Error("BasicEqualsFoo.Equals() test failed") + } + basicSrc = genBasicFoo() + basicSrc.OptBoolFoo = nil + if basicTgt.Equals(basicSrc) || basicSrc.Equals(basicTgt) { + t.Error("BasicEqualsFoo.Equals() test failed") + } + if !(&equalstest.BasicEqualsFoo{}).Equals(&equalstest.BasicEqualsFoo{}) { + t.Error("BasicEqualsFoo.Equals() test failed") + } + // test struct field + structTgt, structSrc := genStructFoo(), genStructFoo() + if !structTgt.Equals(structSrc) { + t.Error("StructEqualsFoo.Equals() test failed") + } + structSrc.OptStructFoo.EnumFoo = equalstest.EnumFoo_e2 + if structTgt.Equals(structSrc) { + t.Error("StructEqualsFoo.Equals() test failed") + } + structSrc = genStructFoo() + structSrc.OptStructFoo = nil + if structTgt.Equals(structSrc) || structSrc.Equals(structTgt) { + t.Error("StructEqualsFoo.Equals() test failed") + } + if !(&equalstest.StructEqualsFoo{}).Equals(&equalstest.StructEqualsFoo{}) { + t.Error("StructEqualsFoo.Equals() test failed") + } + // test list field + listTgt, listSrc := genListFoo(), genListFoo() + if !listTgt.Equals(listSrc) { + t.Error("ListEqualsFoo.Equals() test failed") + } + listSrc.OptI64StringMapListFoo[0][1] = "0" + if listTgt.Equals(listSrc) { + t.Error("ListEqualsFoo.Equals() test failed") + } + listSrc = genListFoo() + listSrc.OptI64StringMapListFoo = nil + if listTgt.Equals(listSrc) || listSrc.Equals(listTgt) { + t.Error("ListEqualsFoo.Equals() test failed") + } + if !(&equalstest.ListEqualsFoo{}).Equals(&equalstest.ListEqualsFoo{}) { + t.Error("ListEqualsFoo.Equals() test failed") + } + // test set field + setTgt, setSrc := genSetFoo(), genSetFoo() + if !setTgt.Equals(setSrc) { + t.Error("SetEqualsFoo.Equals() test failed") + } + setSrc.OptI64StringMapSetFoo[0][1] = "0" + if setTgt.Equals(setSrc) { + t.Error("SetEqualsFoo.Equals() test failed") + } + setSrc = genSetFoo() + setSrc.OptI64StringMapSetFoo = nil + if setTgt.Equals(setSrc) || setSrc.Equals(setTgt) { + t.Error("SetEqualsFoo.Equals() test failed") + } + if !(&equalstest.SetEqualsFoo{}).Equals(&equalstest.SetEqualsFoo{}) { + t.Error("SetEqualsFoo.Equals() test failed") + } + // test map field + mapTgt, mapSrc := genMapFoo(), genMapFoo() + if !mapTgt.Equals(mapSrc) { + t.Error("MapEqualsFoo.Equals() test failed") + } + mapSrc.OptI64I64StringMapMapFoo[1][1] = "0" + if mapTgt.Equals(mapSrc) { + t.Error("MapEqualsFoo.Equals() test failed") + } + mapSrc = genMapFoo() + mapSrc.OptI64I64StringMapMapFoo = nil + if mapTgt.Equals(mapSrc) || mapSrc.Equals(mapTgt) { + t.Error("MapEqualsFoo.Equals() test failed") + } + if !(&equalstest.MapEqualsFoo{}).Equals(&equalstest.MapEqualsFoo{}) { + t.Error("MapEqualsFoo.Equals() test failed") + } +} + +func genBasicFoo() *equalstest.BasicEqualsFoo { + return &equalstest.BasicEqualsFoo{ + BoolFoo: true, + OptBoolFoo: &(&struct{ x bool }{true}).x, + I8Foo: 1, + OptI8Foo: &(&struct{ x int8 }{1}).x, + I16Foo: 2, + OptI16Foo: &(&struct{ x int16 }{2}).x, + I32Foo: 3, + OptI32Foo: &(&struct{ x int32 }{3}).x, + I64Foo: 4, + OptI64Foo: &(&struct{ x int64 }{4}).x, + DoubleFoo: 5, + OptDoubleFoo: &(&struct{ x float64 }{5}).x, + StrFoo: "6", + OptStrFoo: &(&struct{ x string }{"6"}).x, + BinFoo: []byte("7"), + OptBinFoo: []byte("7"), + EnumFoo: equalstest.EnumFoo_e1, + OptEnumFoo: equalstest.EnumFooPtr(equalstest.EnumFoo_e1), + MyByteFoo: equalstest.Mybyte(8), + OptMyByteFoo: equalstest.MybytePtr(8), + MyStrFoo: equalstest.Mystr("9"), + OptMyStrFoo: equalstest.MystrPtr(equalstest.Mystr("9")), + MyBinFoo: equalstest.Mybin("10"), + OptMyBinFoo: equalstest.Mybin("10"), + } +} + +func genStructFoo() *equalstest.StructEqualsFoo { + return &equalstest.StructEqualsFoo{ + StructFoo: genBasicFoo(), + OptStructFoo: genBasicFoo(), + } +} + +func genListFoo() *equalstest.ListEqualsFoo { + return &equalstest.ListEqualsFoo{ + I64ListFoo: genInt64Slice(6), + OptI64ListFoo: genInt64Slice(6), + StrListFoo: genStringSlice(6), + OptStrListFoo: genStringSlice(6), + BinListFoo: genBytesSlice(6), + OptBinListFoo: genBytesSlice(6), + StructListFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}}, + OptStructListFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}}, + I64ListListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, + OptI64ListListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, + I64SetListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, + OptI64SetListFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, + I64StringMapListFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}}, + OptI64StringMapListFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}}, + MyByteListFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1}, + OptMyByteListFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1}, + MyStrListFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")}, + OptMyStrListFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")}, + MyBinListFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")}, + OptMyBinListFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")}, + } +} + +func genSetFoo() *equalstest.SetEqualsFoo { + return &equalstest.SetEqualsFoo{ + I64SetFoo: genInt64Slice(6), + OptI64SetFoo: genInt64Slice(6), + StrSetFoo: genStringSlice(6), + OptStrSetFoo: genStringSlice(6), + BinSetFoo: genBytesSlice(6), + OptBinSetFoo: genBytesSlice(6), + StructSetFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}}, + OptStructSetFoo: []*equalstest.BasicEqualsFoo{genBasicFoo(), {}}, + I64ListSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, + OptI64ListSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, + I64SetSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, + OptI64SetSetFoo: [][]int64{genInt64Slice(6), genInt64Slice(5), genInt64Slice(4), genInt64Slice(3), genInt64Slice(2), genInt64Slice(1)}, + I64StringMapSetFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}}, + OptI64StringMapSetFoo: []map[int64]string{{6: "6"}, {5: "5"}, {4: "4"}, {3: "3"}, {2: "2"}, {1: "1"}}, + MyByteSetFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1}, + OptMyByteSetFoo: []equalstest.Mybyte{6, 5, 4, 3, 2, 1}, + MyStrSetFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")}, + OptMyStrSetFoo: []equalstest.Mystr{equalstest.Mystr("6"), equalstest.Mystr("5"), equalstest.Mystr("4"), equalstest.Mystr("3"), equalstest.Mystr("2"), equalstest.Mystr("1")}, + MyBinSetFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")}, + OptMyBinSetFoo: []equalstest.Mybin{equalstest.Mybin("6"), equalstest.Mybin("5"), equalstest.Mybin("4"), equalstest.Mybin("3"), equalstest.Mybin("2"), equalstest.Mybin("1")}, + } +} + +var ( + structMapKey0 = genBasicFoo() + structMapKey1 = &equalstest.BasicEqualsFoo{} +) + +func genMapFoo() *equalstest.MapEqualsFoo { + return &equalstest.MapEqualsFoo{ + I64StrMapFoo: genInt64StringMap(6), + OptI64StrMapFoo: genInt64StringMap(6), + StrI64MapFoo: map[string]int64{"6": 6, "5": 5, "4": 4, "3": 3, "2": 2, "1": 1}, + OptStrI64MapFoo: map[string]int64{"6": 6, "5": 5, "4": 4, "3": 3, "2": 2, "1": 1}, + StructBinMapFoo: map[*equalstest.BasicEqualsFoo][]byte{structMapKey0: []byte("0"), structMapKey1: []byte("1")}, + OptStructBinMapFoo: map[*equalstest.BasicEqualsFoo][]byte{structMapKey0: []byte("0"), structMapKey1: []byte("1")}, + BinStructMapFoo: map[string]*equalstest.BasicEqualsFoo{"1": genBasicFoo(), "0": {}}, + OptBinStructMapFoo: map[string]*equalstest.BasicEqualsFoo{"1": genBasicFoo(), "0": {}}, + I64I64ListMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)}, + OptI64I64ListMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)}, + I64I64SetMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)}, + OptI64I64SetMapFoo: map[int64][]int64{6: genInt64Slice(6), 5: genInt64Slice(5), 4: genInt64Slice(4), 3: genInt64Slice(3), 2: genInt64Slice(2), 1: genInt64Slice(1)}, + I64I64StringMapMapFoo: map[int64]map[int64]string{6: genInt64StringMap(6), 5: genInt64StringMap(5), 4: genInt64StringMap(4), 3: genInt64StringMap(3), 2: genInt64StringMap(2), 1: genInt64StringMap(1)}, + OptI64I64StringMapMapFoo: map[int64]map[int64]string{6: genInt64StringMap(6), 5: genInt64StringMap(5), 4: genInt64StringMap(4), 3: genInt64StringMap(3), 2: genInt64StringMap(2), 1: genInt64StringMap(1)}, + MyStrMyBinMapFoo: map[equalstest.Mystr]equalstest.Mybin{equalstest.Mystr("1"): equalstest.Mybin("1"), equalstest.Mystr("0"): equalstest.Mybin("0")}, + OptMyStrMyBinMapFoo: map[equalstest.Mystr]equalstest.Mybin{equalstest.Mystr("1"): equalstest.Mybin("1"), equalstest.Mystr("0"): equalstest.Mybin("0")}, + Int64MyByteMapFoo: map[int64]equalstest.Mybyte{6: equalstest.Mybyte(6), 5: equalstest.Mybyte(5), 4: equalstest.Mybyte(4), 3: equalstest.Mybyte(3), 2: equalstest.Mybyte(2), 1: equalstest.Mybyte(1)}, + OptInt64MyByteMapFoo: map[int64]equalstest.Mybyte{6: equalstest.Mybyte(6), 5: equalstest.Mybyte(5), 4: equalstest.Mybyte(4), 3: equalstest.Mybyte(3), 2: equalstest.Mybyte(2), 1: equalstest.Mybyte(1)}, + MyByteInt64MapFoo: map[equalstest.Mybyte]int64{equalstest.Mybyte(6): 6, equalstest.Mybyte(5): 5, equalstest.Mybyte(4): 4, equalstest.Mybyte(3): 3, equalstest.Mybyte(2): 2, equalstest.Mybyte(1): 1}, + OptMyByteInt64MapFoo: map[equalstest.Mybyte]int64{equalstest.Mybyte(6): 6, equalstest.Mybyte(5): 5, equalstest.Mybyte(4): 4, equalstest.Mybyte(3): 3, equalstest.Mybyte(2): 2, equalstest.Mybyte(1): 1}, + } +} + +func genInt64Slice(length int) []int64 { + ret := make([]int64, length) + for i := 0; i < length; i++ { + ret[i] = int64(length - i) + } + return ret +} + +func genStringSlice(length int) []string { + ret := make([]string, length) + for i := 0; i < length; i++ { + ret[i] = strconv.Itoa(length - i) + } + return ret +} + +func genBytesSlice(length int) [][]byte { + ret := make([][]byte, length) + for i := 0; i < length; i++ { + ret[i] = []byte(strconv.Itoa(length - i)) + } + return ret +} + +func genInt64StringMap(length int) map[int64]string { + ret := make(map[int64]string, length) + for i := 0; i < length; i++ { + ret[int64(i)] = strconv.Itoa(i) + } + return ret +} From 55016bff2b19f2c5d3c85ae9985c49527ffffabb Mon Sep 17 00:00:00 2001 From: James Lacey Date: Tue, 2 Feb 2021 15:14:55 -0700 Subject: [PATCH 748/756] THRIFT-5343: TTlsSocketTransport does not resolve IPv4 addresses or validate hostnames correctly Client: netstd Patch: James Lacey This closes #2322 --- .../Thrift/Transport/Client/TTlsSocketTransport.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs index 0980526f23e..e3da6f4c264 100644 --- a/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs +++ b/lib/netstd/Thrift/Transport/Client/TTlsSocketTransport.cs @@ -38,6 +38,7 @@ public class TTlsSocketTransport : TStreamTransport private readonly LocalCertificateSelectionCallback _localCertificateSelectionCallback; private readonly int _port; private readonly SslProtocols _sslProtocols; + private readonly string _targetHost; private TcpClient _client; private SslStream _secureStream; private int _timeout; @@ -122,13 +123,13 @@ public TTlsSocketTransport(string host, int port, TConfiguration config, int tim { try { + _targetHost = host; + var entry = Dns.GetHostEntry(host); if (entry.AddressList.Length == 0) throw new TTransportException(TTransportException.ExceptionType.Unknown, "unable to resolve host name"); - var addr = entry.AddressList[0]; - - _host = new IPAddress(addr.GetAddressBytes(), addr.ScopeId); + _host = entry.AddressList[0]; _port = port; _timeout = timeout; _certificate = certificate; @@ -239,7 +240,7 @@ public async Task SetupTlsAsync() ? new X509CertificateCollection {_certificate} : new X509CertificateCollection(); - var targetHost = _host.ToString(); + var targetHost = _targetHost ?? _host.ToString(); await _secureStream.AuthenticateAsClientAsync(targetHost, certs, _sslProtocols, true); } } From ebc2ab558dce946b2a3134028b08ed59d49cd1e3 Mon Sep 17 00:00:00 2001 From: belugabehr <12578579+belugabehr@users.noreply.github.com> Date: Thu, 4 Feb 2021 09:14:11 -0500 Subject: [PATCH 749/756] THRIFT-5345: Allow the ServerContext to be Unwrapped Programmatically Client: Java Patch: David Mollitor --- .../apache/thrift/server/ServerContext.java | 29 +++++++++++++++++-- .../org/apache/thrift/test/TestServer.java | 22 ++++++++++++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/lib/java/src/org/apache/thrift/server/ServerContext.java b/lib/java/src/org/apache/thrift/server/ServerContext.java index 9b0b99eeaa0..b7c587f3788 100644 --- a/lib/java/src/org/apache/thrift/server/ServerContext.java +++ b/lib/java/src/org/apache/thrift/server/ServerContext.java @@ -18,9 +18,32 @@ */ /** - * Interface for storing server's connection context + * Interface for storing server's connection context. */ - package org.apache.thrift.server; -public interface ServerContext {} +public interface ServerContext { + + /** + * Returns an object that implements the given interface to allow access to + * application specific contexts. + * + * @param iface A Class defining an interface that the result must implement + * @return an object that implements the interface + * @throws RuntimeException If the context cannot be unwrapped to the provided + * class + */ + T unwrap(Class iface); + + /** + * Returns true if this server context is a wrapper for the provided + * application specific context interface argument or returns false otherwise. + * + * @param iface a Class defining the underlying context + * @return true if this implements the interface can be unwrapped to the + * provided class + * @throws RuntimeException if an error occurs while determining whether the + * provided class can be unwrapped from this context. + */ + boolean isWrapperFor(Class iface); +} diff --git a/lib/java/test/org/apache/thrift/test/TestServer.java b/lib/java/test/org/apache/thrift/test/TestServer.java index 02e8ad7f6d2..386f2b60bf4 100644 --- a/lib/java/test/org/apache/thrift/test/TestServer.java +++ b/lib/java/test/org/apache/thrift/test/TestServer.java @@ -81,6 +81,24 @@ public void setConnectionId(int connectionId) { this.connectionId = connectionId; } + @Override + public T unwrap(Class iface) { + try { + if (isWrapperFor(iface)) { + return iface.cast(this); + } else { + throw new RuntimeException("The context is not a wrapper for " + iface.getName()); + } + } catch (Exception e) { + throw new RuntimeException("The context is not a wrapper and does not implement the interface"); + } + } + + @Override + public boolean isWrapperFor(Class iface) { + return iface.isInstance(this); + } + } static class TestServerEventHandler implements TServerEventHandler { @@ -99,12 +117,12 @@ public ServerContext createContext(TProtocol input, TProtocol output) { } public void deleteContext(ServerContext serverContext, TProtocol input, TProtocol output) { - TestServerContext ctx = (TestServerContext)serverContext; + TestServerContext ctx = serverContext.unwrap(TestServerContext.class); System.out.println("TServerEventHandler.deleteContext - connection #"+ctx.getConnectionId()+" terminated"); } public void processContext(ServerContext serverContext, TTransport inputTransport, TTransport outputTransport) { - TestServerContext ctx = (TestServerContext)serverContext; + TestServerContext ctx = serverContext.unwrap(TestServerContext.class); System.out.println("TServerEventHandler.processContext - connection #"+ctx.getConnectionId()+" is ready to process next request"); } From 7ae1ec3f1eb3218f8b623232436bc986e3f1f5c8 Mon Sep 17 00:00:00 2001 From: David Mollitor Date: Fri, 23 Oct 2020 19:11:10 +0200 Subject: [PATCH 750/756] THRIFT-5297: Improve TThreadPoolServer Handling of Incoming Connections Client: Java Patch: David Mollitor This closes #2266 --- .../thrift/server/TThreadPoolServer.java | 180 ++++++------------ .../thrift/server/TestThreadPoolServer.java | 14 +- 2 files changed, 64 insertions(+), 130 deletions(-) diff --git a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java index 467b10d0977..01749b98aeb 100644 --- a/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java +++ b/lib/java/src/org/apache/thrift/server/TThreadPoolServer.java @@ -19,11 +19,11 @@ package org.apache.thrift.server; -import java.util.Random; -import java.util.WeakHashMap; +import java.util.Optional; import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -41,7 +41,7 @@ * a worker pool that deals with client connections in blocking way. */ public class TThreadPoolServer extends TServer { - private static final Logger LOGGER = LoggerFactory.getLogger(TThreadPoolServer.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(TThreadPoolServer.class); public static class Args extends AbstractServerArgs { public int minWorkerThreads = 5; @@ -49,10 +49,6 @@ public static class Args extends AbstractServerArgs { 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); @@ -78,27 +74,6 @@ public Args stopTimeoutUnit(TimeUnit 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; @@ -107,41 +82,32 @@ public Args executorService(ExecutorService executorService) { // Executor service for handling client connections private ExecutorService executorService_; - private WeakHashMap activeWorkers = new WeakHashMap<>(); 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); + return new ThreadPoolExecutor(args.minWorkerThreads, args.maxWorkerThreads, 60L, TimeUnit.SECONDS, + new SynchronousQueue<>(), new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r); + thread.setDaemon(true); + thread.setName("TThreadPoolServer WorkerProcess-%d"); + return thread; + } + }); } protected ExecutorService getExecutorService() { @@ -149,7 +115,7 @@ protected ExecutorService getExecutorService() { } protected boolean preServe() { - try { + try { serverTransport_.listen(); } catch (TTransportException ttx) { LOGGER.error("Error occurred during listening.", ttx); @@ -166,13 +132,16 @@ protected boolean preServe() { } public void serve() { - if (!preServe()) { - return; - } + if (!preServe()) { + return; + } + + execute(); + + executorService_.shutdownNow(); - execute(); if (!waitForShutdown()) { - LOGGER.error("Shutdown is not done after " + stopTimeoutVal + stopTimeoutUnit); + LOGGER.error("Shutdown is not done after " + stopTimeoutVal + stopTimeoutUnit); } setServing(false); @@ -182,51 +151,17 @@ protected void execute() { 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); - activeWorkers.put(wp, Boolean.TRUE); - 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; - } + try { + executorService_.execute(new WorkerProcess(client)); + } catch (RejectedExecutionException ree) { + if (!stopped_) { + LOGGER.warn("ThreadPool is saturated with incoming requests. Closing latest connection."); } + client.close(); } } catch (TTransportException ttx) { if (!stopped_) { - LOGGER.warn("Transport error occurred during acceptance of message.", ttx); + LOGGER.warn("Transport error occurred during acceptance of message", ttx); } } } @@ -241,8 +176,7 @@ protected boolean waitForShutdown() { long now = System.currentTimeMillis(); while (timeoutMS >= 0) { try { - executorService_.awaitTermination(timeoutMS, TimeUnit.MILLISECONDS); - return true; + return executorService_.awaitTermination(timeoutMS, TimeUnit.MILLISECONDS); } catch (InterruptedException ix) { long newnow = System.currentTimeMillis(); timeoutMS -= (newnow - now); @@ -255,10 +189,6 @@ protected boolean waitForShutdown() { public void stop() { stopped_ = true; serverTransport_.interrupt(); - executorService_.shutdown(); - for (WorkerProcess wp : activeWorkers.keySet()) { - wp.stop(); - } } private class WorkerProcess implements Runnable { @@ -287,7 +217,7 @@ public void run() { TProtocol inputProtocol = null; TProtocol outputProtocol = null; - TServerEventHandler eventHandler = null; + Optional eventHandler = Optional.empty(); ServerContext connectionContext = null; try { @@ -297,22 +227,25 @@ public void run() { 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) { + eventHandler = Optional.ofNullable(getEventHandler()); - if (eventHandler != null) { - eventHandler.processContext(connectionContext, inputTransport, outputTransport); - } + if (eventHandler.isPresent()) { + connectionContext = eventHandler.get().createContext(inputProtocol, outputProtocol); + } - if (stopped_) { - break; - } - processor.process(inputProtocol, outputProtocol); + while (true) { + if (Thread.currentThread().isInterrupted()) { + LOGGER.debug("WorkerProcess requested to shutdown"); + break; + } + if (eventHandler.isPresent()) { + eventHandler.get().processContext(connectionContext, inputTransport, outputTransport); + } + // This process cannot be interrupted by Interrupting the Thread. This + // will return once a message has been processed or the socket timeout + // has elapsed, at which point it will return and check the interrupt + // state of the thread. + processor.process(inputProtocol, outputProtocol); } } catch (Exception x) { LOGGER.debug("Error processing request", x); @@ -322,11 +255,11 @@ public void run() { // Ignore err-logging all transport-level/type exceptions if (!isIgnorableException(x)) { // Log the exception at error level and continue - LOGGER.error((x instanceof TException? "Thrift " : "") + "Error occurred during processing of message.", x); + LOGGER.error((x instanceof TException ? "Thrift " : "") + "Error occurred during processing of message.", x); } } finally { - if (eventHandler != null) { - eventHandler.deleteContext(connectionContext, inputProtocol, outputProtocol); + if (eventHandler.isPresent()) { + eventHandler.get().deleteContext(connectionContext, inputProtocol, outputProtocol); } if (inputTransport != null) { inputTransport.close(); @@ -344,10 +277,9 @@ private boolean isIgnorableException(Exception x) { TTransportException tTransportException = null; if (x instanceof TTransportException) { - tTransportException = (TTransportException)x; - } - else if (x.getCause() instanceof TTransportException) { - tTransportException = (TTransportException)x.getCause(); + tTransportException = (TTransportException) x; + } else if (x.getCause() instanceof TTransportException) { + tTransportException = (TTransportException) x.getCause(); } if (tTransportException != null) { @@ -359,9 +291,5 @@ else if (x.getCause() instanceof TTransportException) { } return false; } - - private void stop() { - client_.close(); - } } } diff --git a/lib/java/test/org/apache/thrift/server/TestThreadPoolServer.java b/lib/java/test/org/apache/thrift/server/TestThreadPoolServer.java index e81d8012f5e..4c84dc18d5d 100644 --- a/lib/java/test/org/apache/thrift/server/TestThreadPoolServer.java +++ b/lib/java/test/org/apache/thrift/server/TestThreadPoolServer.java @@ -36,7 +36,7 @@ public class TestThreadPoolServer { */ @Test public void testStopServerWithOpenClient() throws Exception { - TServerSocket serverSocket = new TServerSocket(0); + TServerSocket serverSocket = new TServerSocket(0, 3000); TThreadPoolServer server = buildServer(serverSocket); Thread serverThread = new Thread(() -> server.serve()); serverThread.start(); @@ -45,11 +45,17 @@ public void testStopServerWithOpenClient() throws Exception { Thread.sleep(1000); // There is a thread listening to the client Assert.assertEquals(1, ((ThreadPoolExecutor) server.getExecutorService()).getActiveCount()); + + // Trigger the server to stop, but it does not wait server.stop(); - server.waitForShutdown(); + Assert.assertTrue(server.waitForShutdown()); + // After server is stopped, the executor thread pool should be shut down - Assert.assertTrue("Server thread pool should be terminated.", server.getExecutorService().isTerminated()); - Assert.assertTrue("Client is still open.", client.isOpen()); + Assert.assertTrue("Server thread pool should be terminated", server.getExecutorService().isTerminated()); + + // TODO: The socket is actually closed (timeout) but the client code + // ignores the timeout Exception and maintains the socket open state + Assert.assertTrue("Client should be closed after server shutdown", client.isOpen()); } } From de523c79b38bfd74aed812532ad6557d704bc945 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 4 Feb 2021 17:41:23 +0100 Subject: [PATCH 751/756] Updated CHANGES to reflect Version 0.14.0 --- CHANGES.md | 304 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 298 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c6c08f29f56..b2d726cbda4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,16 @@ ## 0.14.0 +### Deprecated Languages + +- [THRIFT-5229](https://issues.apache.org/jira/browse/THRIFT-5229) - Deprecate ActionScript 3 support + +### Removed Languages + +- [THRIFT-4980](https://issues.apache.org/jira/browse/THRIFT-4980) - Remove deprecated C# and netcore bindings from the code base +- [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base +- [THRIFT-4982](https://issues.apache.org/jira/browse/THRIFT-4982) - Remove deprecated C# bindings from the code base + ### Breaking Changes - [THRIFT-4981](https://issues.apache.org/jira/browse/THRIFT-4981) - Remove deprecated netcore bindings from the code base @@ -20,19 +30,301 @@ - [THRIFT-5326](https://issues.apache.org/jira/browse/THRIFT-5326) - go: TException interface now has a new function: TExceptionType - [THRIFT-4914](https://issues.apache.org/jira/browse/THRIFT-4914) - go: TClient.Call now returns ResponseMeta in addition to error -### Java +### Known Open Issues (Blocker or Critical) -- [THRIFT-5022](https://issues.apache.org/jira/browse/THRIFT-5022) - TIOStreamTransport.isOpen returns true for one-sided transports (see THRIFT-2530). +- [THRIFT-3877](https://issues.apache.org/jira/browse/THRIFT-3877) - C++: library don't work with HTTP (csharp server, cpp client; need cross test enhancement) +- [THRIFT-5098](https://issues.apache.org/jira/browse/THRIFT-5098) - Deprecated: "The high level Network interface is no longer supported. Please use Network.Socket." and other Haskell issues +- [THRIFT-5245](https://issues.apache.org/jira/browse/THRIFT-5245) - NPE when the value of map's key is null +- [THRIFT-4687](https://issues.apache.org/jira/browse/THRIFT-4687) - Add thrift 0.12.0 to pypi and/or enable more maintainers + +### Build Process + +- [THRIFT-4976](https://issues.apache.org/jira/browse/THRIFT-4976) - Docker build: Test failure for `StalenessCheckTest` on MacOS +- [THRIFT-5087](https://issues.apache.org/jira/browse/THRIFT-5087) - test/test.py fails with "AssertionError: Python 3.3 or later is required for proper operation." +- [THRIFT-5097](https://issues.apache.org/jira/browse/THRIFT-5097) - Incorrect THRIFT_VERSION in ThriftConfig.cmake +- [THRIFT-5109](https://issues.apache.org/jira/browse/THRIFT-5109) - Misc CMake improvements +- [THRIFT-5147](https://issues.apache.org/jira/browse/THRIFT-5147) - Add uninstall function +- [THRIFT-5218](https://issues.apache.org/jira/browse/THRIFT-5218) - Automated Github release artifacts do not match checksums provided +- [THRIFT-5249](https://issues.apache.org/jira/browse/THRIFT-5249) - travis-ci : Failed to run FastbinaryTest.py + +### C glib + +- [THRIFT-4873](https://issues.apache.org/jira/browse/THRIFT-4873) - Memory leak in c_glib +- [THRIFT-5118](https://issues.apache.org/jira/browse/THRIFT-5118) - Fix memory leak when the handler method return a exception +- [THRIFT-5134](https://issues.apache.org/jira/browse/THRIFT-5134) - Fix memory leak when the handler method return FALSE +- [THRIFT-5144](https://issues.apache.org/jira/browse/THRIFT-5144) - Fix memory leak when generate deserialize list element +- [THRIFT-4272](https://issues.apache.org/jira/browse/THRIFT-4272) - warnings in glibc library +- [THRIFT-4952](https://issues.apache.org/jira/browse/THRIFT-4952) - Modified ssl_read feedback value break all the time error. +- [THRIFT-5076](https://issues.apache.org/jira/browse/THRIFT-5076) - Improve CMake OpenSSL usage +- [THRIFT-5094](https://issues.apache.org/jira/browse/THRIFT-5094) - Fix memory leak in thrift_server_set_property() +- [THRIFT-5101](https://issues.apache.org/jira/browse/THRIFT-5101) - Return NULL install of FALSE for thrift_server_socket_accept() +- [THRIFT-5102](https://issues.apache.org/jira/browse/THRIFT-5102) - Fix memory leak in thrift_simple_server_serve() +- [THRIFT-5136](https://issues.apache.org/jira/browse/THRIFT-5136) - Fix memory leak in thrift_multiplexed_processor_process_impl() +- [THRIFT-5221](https://issues.apache.org/jira/browse/THRIFT-5221) - Fix stack overflow when reading buffer +- [THRIFT-5237](https://issues.apache.org/jira/browse/THRIFT-5237) - Implement MAX_MESSAGE_SIZE and consolidate limits into a TConfiguration class +- [THRIFT-5255](https://issues.apache.org/jira/browse/THRIFT-5255) - Fix stack overflow in framed transport +- [THRIFT-5256](https://issues.apache.org/jira/browse/THRIFT-5256) - Fix some compile warnings +- [THRIFT-5268](https://issues.apache.org/jira/browse/THRIFT-5268) - Fix some file loss ')' in define + +### C++ + +- [THRIFT-1513](https://issues.apache.org/jira/browse/THRIFT-1513) - Thrift compiler generates inconsistent code with some complex values (causing g++ to error: "has no member named '__isset') +- [THRIFT-5168](https://issues.apache.org/jira/browse/THRIFT-5168) - Useless generated code when .thrift file only has service type +- [THRIFT-5179](https://issues.apache.org/jira/browse/THRIFT-5179) - Thrift compiler will generate wrong code if IDL struct's name is 'a' or 'b' +- [THRIFT-5200](https://issues.apache.org/jira/browse/THRIFT-5200) - Thrift compiler will generate incorrect code when add 'cob_style' option. +- [THRIFT-4282](https://issues.apache.org/jira/browse/THRIFT-4282) - StressTestNonBlocking is disabled in Appveyor as it is unstable on Windows in general +- [THRIFT-4682](https://issues.apache.org/jira/browse/THRIFT-4682) - C++ TBinaryProtocol crashes on port scan +- [THRIFT-4963](https://issues.apache.org/jira/browse/THRIFT-4963) - TNonblockingServer blocked int addTask(IOThread) and notify(workerThread) +- [THRIFT-5047](https://issues.apache.org/jira/browse/THRIFT-5047) - fix cmake support to build cpp server without OPENSSL +- [THRIFT-5076](https://issues.apache.org/jira/browse/THRIFT-5076) - Improve CMake OpenSSL usage +- [THRIFT-5078](https://issues.apache.org/jira/browse/THRIFT-5078) - Handle named pipe clients quickly disconnecting +- [THRIFT-5086](https://issues.apache.org/jira/browse/THRIFT-5086) - CMake target thrift::thrift has no INTERFACE_INCLUDE_DIRECTORIES property +- [THRIFT-5110](https://issues.apache.org/jira/browse/THRIFT-5110) - Added a number of required libs for using static OpenSSL +- [THRIFT-5114](https://issues.apache.org/jira/browse/THRIFT-5114) - Simplify the computation of the size of TMemoryBuffer +- [THRIFT-5177](https://issues.apache.org/jira/browse/THRIFT-5177) - getaddrinfo() should not be used for Unix sockets +- [THRIFT-5178](https://issues.apache.org/jira/browse/THRIFT-5178) - THttpClient should work without specifying host +- [THRIFT-5185](https://issues.apache.org/jira/browse/THRIFT-5185) - C++: Add WebSocket Server Transport +- [THRIFT-5186](https://issues.apache.org/jira/browse/THRIFT-5186) - AI_ADDRCONFIG: Thrift libraries crash with localhost-only network. +- [THRIFT-5215](https://issues.apache.org/jira/browse/THRIFT-5215) - C++: Remove portable_endian.h +- [THRIFT-5217](https://issues.apache.org/jira/browse/THRIFT-5217) - Deprecated boost header +- [THRIFT-5237](https://issues.apache.org/jira/browse/THRIFT-5237) - Implement MAX_MESSAGE_SIZE and consolidate limits into a TConfiguration class +- [THRIFT-5290](https://issues.apache.org/jira/browse/THRIFT-5290) - Adjusting cpp *.cproj msvcrt options according to LEGAL-538 +- [THRIFT-5295](https://issues.apache.org/jira/browse/THRIFT-5295) - Thread and ThreadFactory should be extensible +- [THRIFT-5344](https://issues.apache.org/jira/browse/THRIFT-5344) - TTransport may throw raw pointer exceptions + +### Compiler (General) + +- [THRIFT-4173](https://issues.apache.org/jira/browse/THRIFT-4173) - Go: thrift compiler generates wrong code for list of aliased type +- [THRIFT-4938](https://issues.apache.org/jira/browse/THRIFT-4938) - Issues with version.h treatment +- [THRIFT-4973](https://issues.apache.org/jira/browse/THRIFT-4973) - Add deprecation messages for csharp and netcore +- [THRIFT-4980](https://issues.apache.org/jira/browse/THRIFT-4980) - Remove deprecated C# and netcore bindings from the code base +- [THRIFT-4982](https://issues.apache.org/jira/browse/THRIFT-4982) - Remove deprecated C# bindings from the code baseï…‚ +- [THRIFT-5153](https://issues.apache.org/jira/browse/THRIFT-5153) - Deprecate byte +- [THRIFT-5225](https://issues.apache.org/jira/browse/THRIFT-5225) - Use nullptr instead of NULL +- [THRIFT-5302](https://issues.apache.org/jira/browse/THRIFT-5302) - Add recursive function name uniqueness check + +### D + +- [THRIFT-5059](https://issues.apache.org/jira/browse/THRIFT-5059) - Add cross tests for TZlibTransport in D +- [THRIFT-5156](https://issues.apache.org/jira/browse/THRIFT-5156) - D: Fix library compilation on Windows and compiler warnings +- [THRIFT-5166](https://issues.apache.org/jira/browse/THRIFT-5166) - Add WebSocket Server Transport +- [THRIFT-5184](https://issues.apache.org/jira/browse/THRIFT-5184) - D: WebSocket Server Transport Fix for Firefox + +### Delphi + +- [THRIFT-5044](https://issues.apache.org/jira/browse/THRIFT-5044) - Improve serialization support for TApplicationExceptions and custom exceptions +- [THRIFT-5154](https://issues.apache.org/jira/browse/THRIFT-5154) - Generate interface IDs (IID) for Windows platforms +- [THRIFT-5235](https://issues.apache.org/jira/browse/THRIFT-5235) - Add property setter for isset flags +- [THRIFT-5261](https://issues.apache.org/jira/browse/THRIFT-5261) - Support for deprecated methods (via annotation) +- [THRIFT-5004](https://issues.apache.org/jira/browse/THRIFT-5004) - Make exception implementations more consistent +- [THRIFT-5005](https://issues.apache.org/jira/browse/THRIFT-5005) - Refactoring of the Delphi libs +- [THRIFT-5006](https://issues.apache.org/jira/browse/THRIFT-5006) - Implement DEFAULT_MAX_LENGTH at TFramedTransport +- [THRIFT-5007](https://issues.apache.org/jira/browse/THRIFT-5007) - Implement MAX_MESSAGE_SIZE and remaining read bytes control +- [THRIFT-5009](https://issues.apache.org/jira/browse/THRIFT-5009) - Serializer implemtation lacks support for layered transports +- [THRIFT-5012](https://issues.apache.org/jira/browse/THRIFT-5012) - Centralize configuration aspects into a commonly used configuration object +- [THRIFT-5015](https://issues.apache.org/jira/browse/THRIFT-5015) - WinHTTP QueryDataAvailable cannot be used to retrieve total response size +- [THRIFT-5036](https://issues.apache.org/jira/browse/THRIFT-5036) - buffered transport over sockets may run into unexpected timeouts +- [THRIFT-5048](https://issues.apache.org/jira/browse/THRIFT-5048) - EnumUtils.ToString() throws for elements not known to the receiving end +- [THRIFT-5088](https://issues.apache.org/jira/browse/THRIFT-5088) - Memory leak in TEndpointTransportBase +- [THRIFT-5123](https://issues.apache.org/jira/browse/THRIFT-5123) - add possibility to query HTTP status code with WinHTTP +- [THRIFT-5146](https://issues.apache.org/jira/browse/THRIFT-5146) - Align Delphi to the test suite arguments rules (its "--switch=value", not "--switch value") +- [THRIFT-5186](https://issues.apache.org/jira/browse/THRIFT-5186) - AI_ADDRCONFIG: Thrift libraries crash with localhost-only network. +- [THRIFT-5188](https://issues.apache.org/jira/browse/THRIFT-5188) - Occasional ERROR_INSUFFICIENT_BUFFER at WinHttpQueryHeaders() +- [THRIFT-5251](https://issues.apache.org/jira/browse/THRIFT-5251) - StringUtils.ToString() raises an exception for enum values outside range +- [THRIFT-5304](https://issues.apache.org/jira/browse/THRIFT-5304) - TWinHTTPClientImpl may incorrectly report that the message size is reached + +### Documentation + +- [THRIFT-5037](https://issues.apache.org/jira/browse/THRIFT-5037) - Documentation for TConfiguration +- [THRIFT-5065](https://issues.apache.org/jira/browse/THRIFT-5065) - Fix broken links in the IDL document +- [THRIFT-5074](https://issues.apache.org/jira/browse/THRIFT-5074) - Cleanup test suite command line options ### Go +- [THRIFT-4914](https://issues.apache.org/jira/browse/THRIFT-4914) - Compiler generated service clients now provide a new function, LastResponseMeta_(), to get the response metadata (e.g. headers from THeader) from the last client call. +- [THRIFT-4984](https://issues.apache.org/jira/browse/THRIFT-4984) - Scary and spammy "error processing request: EOF" logs from TSimpleServer +- [THRIFT-4985](https://issues.apache.org/jira/browse/THRIFT-4985) - Clean up logging in go library +- [THRIFT-5002](https://issues.apache.org/jira/browse/THRIFT-5002) - remote client fails to compile when extending services +- [THRIFT-5019](https://issues.apache.org/jira/browse/THRIFT-5019) - Multiple import same namespace for go included files +- [THRIFT-5046](https://issues.apache.org/jira/browse/THRIFT-5046) - Custom tags remove db and json tags - [THRIFT-5069](https://issues.apache.org/jira/browse/THRIFT-5069) - Add TSerializerPool and TDeserializerPool, which are thread-safe versions of TSerializer and TDeserializer. -- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - Add ClientMiddleware function type and WrapClient function to support wrapping a TClient with middleware functions. -- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - Add ProcessorMiddleware function type and WrapProcessor function to support wrapping a TProcessor with middleware functions. -- [THRIFT-5233](https://issues.apache.org/jira/browse/THRIFT-5233) - Add context deadline check to ReadMessageBegin in TBinaryProtocol, TCompactProtocol, and THeaderProtocol. +- [THRIFT-5092](https://issues.apache.org/jira/browse/THRIFT-5092) - Panic on nil buffer writes +- [THRIFT-5152](https://issues.apache.org/jira/browse/THRIFT-5152) - Separate timeout in TSocket +- [THRIFT-5164](https://issues.apache.org/jira/browse/THRIFT-5164) - Go middleware support +- [THRIFT-5214](https://issues.apache.org/jira/browse/THRIFT-5214) - go: Implement connection check in TSocket +- [THRIFT-5233](https://issues.apache.org/jira/browse/THRIFT-5233) - I/O timeout handling in go library - [THRIFT-5240](https://issues.apache.org/jira/browse/THRIFT-5240) - The context passed into server handler implementations will be canceled when we detected that the client closed the connection. +- [THRIFT-5257](https://issues.apache.org/jira/browse/THRIFT-5257) - Go THeader implementation doesn't handle endOfFrame correctly +- [THRIFT-5270](https://issues.apache.org/jira/browse/THRIFT-5270) - Go library unit test is broken in go 1.15 +- [THRIFT-5278](https://issues.apache.org/jira/browse/THRIFT-5278) - Expose API to use THeader+TCompactProtocol in go library client code +- [THRIFT-5279](https://issues.apache.org/jira/browse/THRIFT-5279) - Cleanups/small optimizations for go's serializer/deserializer code +- [THRIFT-5294](https://issues.apache.org/jira/browse/THRIFT-5294) - Go: TSimpleJSONProtocol could panic on WriteMessageEnd without matching WriteMessageBegin - [THRIFT-5322](https://issues.apache.org/jira/browse/THRIFT-5322) - Add support to TConfiguration, and also fix a bug that could cause excessive memory usage when reading malformed messages from TCompactProtocol. -- [THRIFT-4914](https://issues.apache.org/jira/browse/THRIFT-4914) - Compiler generated service clients now provide a new function, LastResponseMeta_(), to get the response metadata (e.g. headers from THeader) from the last client call. +- [THRIFT-5338](https://issues.apache.org/jira/browse/THRIFT-5338) - Proposal: Raise minimal supported Go version with upcoming 0.14.0 release + +### Haskell + +- [THRIFT-5072](https://issues.apache.org/jira/browse/THRIFT-5072) - Haskell generator fails to distinguish between multiple enum types with conflicting enum identifiers +- [THRIFT-4959](https://issues.apache.org/jira/browse/THRIFT-4959) - cabal.exe: --enable-tests was specified, but tests can't be enabled in a remote package +- [THRIFT-5211](https://issues.apache.org/jira/browse/THRIFT-5211) - Handle incomplete reads correctly + +### Java + +- [THRIFT-4252](https://issues.apache.org/jira/browse/THRIFT-4252) - Cannot shutdown Java server when clients are still connected +- [THRIFT-4889](https://issues.apache.org/jira/browse/THRIFT-4889) - Add SASL support for non-blocking server +- [THRIFT-4937](https://issues.apache.org/jira/browse/THRIFT-4937) - Apache HttpCore 4.4.1 reached EoS +- [THRIFT-4949](https://issues.apache.org/jira/browse/THRIFT-4949) - improve HTTP/1 server test case +- [THRIFT-5008](https://issues.apache.org/jira/browse/THRIFT-5008) - Add a logger line in case of failing to dispose sasl +- [THRIFT-5013](https://issues.apache.org/jira/browse/THRIFT-5013) - Use Java Objects RequireNonNull +- [THRIFT-5016](https://issues.apache.org/jira/browse/THRIFT-5016) - Do Not Check 'other' For Null in Equals +- [THRIFT-5022](https://issues.apache.org/jira/browse/THRIFT-5022) - TIOStreamTransport.isOpen returns true for one-sided transports (see THRIFT-2530). +- [THRIFT-5031](https://issues.apache.org/jira/browse/THRIFT-5031) - Fix javadoc of TIOStreamTransport +- [THRIFT-5115](https://issues.apache.org/jira/browse/THRIFT-5115) - PR #2022 Updated gradle to 6.2 broke CI +- [THRIFT-5190](https://issues.apache.org/jira/browse/THRIFT-5190) - StringUtils haven't take `(offset + length) > bytes.length` into account +- [THRIFT-5197](https://issues.apache.org/jira/browse/THRIFT-5197) - TSSLTransportFactory Do Not Wrap NOT_OPEN Exception Type for Client +- [THRIFT-5201](https://issues.apache.org/jira/browse/THRIFT-5201) - Use Apache Parent Pom for Thrift Maven Plugin +- [THRIFT-5202](https://issues.apache.org/jira/browse/THRIFT-5202) - TNonblockingMultiFetchClient Use SLF4J Parameterized Logging +- [THRIFT-5203](https://issues.apache.org/jira/browse/THRIFT-5203) - Remove Unused toString Method in TSerializer +- [THRIFT-5237](https://issues.apache.org/jira/browse/THRIFT-5237) - Implement MAX_MESSAGE_SIZE and consolidate limits into a TConfiguration class +- [THRIFT-5247](https://issues.apache.org/jira/browse/THRIFT-5247) - Avoiding meaningless System.copy +- [THRIFT-5287](https://issues.apache.org/jira/browse/THRIFT-5287) - Log When Client Connections are Dropped +- [THRIFT-5288](https://issues.apache.org/jira/browse/THRIFT-5288) - Move Support for ByteBuffer into TTransport + +### JavaScript + +- [THRIFT-5234](https://issues.apache.org/jira/browse/THRIFT-5234) - Fix a number of js/ts generation issues + +### Lua + +- [THRIFT-5106](https://issues.apache.org/jira/browse/THRIFT-5106) - Fix various Lua library and compiler issues +- [THRIFT-5260](https://issues.apache.org/jira/browse/THRIFT-5260) - Fix the thrift compiler generate problematic lua code for the oneway method +- [THRIFT-4992](https://issues.apache.org/jira/browse/THRIFT-4992) - thrift lua TcompactProtocol bug fix #1881 +- [THRIFT-5262](https://issues.apache.org/jira/browse/THRIFT-5262) - Fix a encoding struct bug in the compact protocol implementation to lua +- [THRIFT-5282](https://issues.apache.org/jira/browse/THRIFT-5282) - Add IPv6 client support to Lua library +- [THRIFT-5286](https://issues.apache.org/jira/browse/THRIFT-5286) - Fix Lua library readBool() in TCompactProtocol +- [THRIFT-5325](https://issues.apache.org/jira/browse/THRIFT-5325) - Fix Lua library writeStructEnd() in TCompactProtocol + +### Markdown + +- [THRIFT-5289](https://issues.apache.org/jira/browse/THRIFT-5289) - Add markdown compiler + +### netstd + +- [THRIFT-5032](https://issues.apache.org/jira/browse/THRIFT-5032) - Allows PascalCase properties for netstd +- [THRIFT-5091](https://issues.apache.org/jira/browse/THRIFT-5091) - Netstd generator produces uncompileable code for struct names ending with "_result" or "_args" +- [THRIFT-5095](https://issues.apache.org/jira/browse/THRIFT-5095) - ToString() should print entire structure, not just the top-level data +- [THRIFT-5198](https://issues.apache.org/jira/browse/THRIFT-5198) - Fix certain Visual Studio hints in generated netstd code +- [THRIFT-5216](https://issues.apache.org/jira/browse/THRIFT-5216) - generate DeepCopy methods +- [THRIFT-5220](https://issues.apache.org/jira/browse/THRIFT-5220) - DeepCopy() extension methods not generated when the IDL contains no service +- [THRIFT-5238](https://issues.apache.org/jira/browse/THRIFT-5238) - GetHashCode can throw NullReferenceException +- [THRIFT-5253](https://issues.apache.org/jira/browse/THRIFT-5253) - using Result in result name generates wrong IAsync interface +- [THRIFT-5254](https://issues.apache.org/jira/browse/THRIFT-5254) - Member name cannot be Isset (unless it is an "required" member) +- [THRIFT-5316](https://issues.apache.org/jira/browse/THRIFT-5316) - Netstd compiler generates wrong ToString() method: .ToString(sb) +- [THRIFT-5317](https://issues.apache.org/jira/browse/THRIFT-5317) - netstd compiler does not escape keywords +- [THRIFT-5320](https://issues.apache.org/jira/browse/THRIFT-5320) - Usage of "Task" as IDL identifier generates uncompileable code +- [THRIFT-4990](https://issues.apache.org/jira/browse/THRIFT-4990) - Upgrade to .NET Core 3.1 (LTS) +- [THRIFT-5010](https://issues.apache.org/jira/browse/THRIFT-5010) - BinaryPrimitives.Read/WriteInt32BigEndian should be used to convert to/from network byte order +- [THRIFT-5020](https://issues.apache.org/jira/browse/THRIFT-5020) - Refactoring & minor fixes for netstd library +- [THRIFT-5021](https://issues.apache.org/jira/browse/THRIFT-5021) - Implement MAX_MESSAGE_SIZE and consolidate limits into a TConfiguration class +- [THRIFT-5026](https://issues.apache.org/jira/browse/THRIFT-5026) - TestClient/Server ignores first cmdline argument +- [THRIFT-5027](https://issues.apache.org/jira/browse/THRIFT-5027) - Implement remaining read bytes checks +- [THRIFT-5053](https://issues.apache.org/jira/browse/THRIFT-5053) - Fix the netstd tutorial console logging and README +- [THRIFT-5083](https://issues.apache.org/jira/browse/THRIFT-5083) - NetStd JSON Protocol left in incorrect state +- [THRIFT-5133](https://issues.apache.org/jira/browse/THRIFT-5133) - TCompactProtocol string allocation improvement +- [THRIFT-5172](https://issues.apache.org/jira/browse/THRIFT-5172) - NetStd TBaseClient open output transport multiple times +- [THRIFT-5210](https://issues.apache.org/jira/browse/THRIFT-5210) - further performance optimizations +- [THRIFT-5239](https://issues.apache.org/jira/browse/THRIFT-5239) - THttpTransport should support passing in an HttpClient +- [THRIFT-5252](https://issues.apache.org/jira/browse/THRIFT-5252) - Make CreateHttpClientHandler() method virtual +- [THRIFT-5275](https://issues.apache.org/jira/browse/THRIFT-5275) - Compilation error with Thrift when used in .Net Framework 4.6.1 or above +- [THRIFT-5343](https://issues.apache.org/jira/browse/THRIFT-5343) - TTlsSocketTransport does not resolve IPv4 addresses or validate hostnames correctly + +### Node.js + +- [THRIFT-3356](https://issues.apache.org/jira/browse/THRIFT-3356) - TypeError: 'undefined' is not a function (evaluating 'Error.captureStackTrace(this, this.constructor)') +- [THRIFT-4994](https://issues.apache.org/jira/browse/THRIFT-4994) - TWebSocketTransport false scope in forEach in browser +- [THRIFT-5003](https://issues.apache.org/jira/browse/THRIFT-5003) - Websocket Connection in Browsers with nodejs code +- [THRIFT-5116](https://issues.apache.org/jira/browse/THRIFT-5116) - Ubuntu xenial NodeJS 6.x is too old, 10.x required +- [THRIFT-5163](https://issues.apache.org/jira/browse/THRIFT-5163) - adds Q to exports for browserify + +### Perl + +- [THRIFT-5050](https://issues.apache.org/jira/browse/THRIFT-5050) - Fix MemoryBuffer.pm to raise a proper exception if no data is available +- [THRIFT-5066](https://issues.apache.org/jira/browse/THRIFT-5066) - Implement testBinary invocation in TestClient.pl + +### PHP + +- [THRIFT-4942](https://issues.apache.org/jira/browse/THRIFT-4942) - Set PHP struct generated field values as private with getters and setters +- [THRIFT-5082](https://issues.apache.org/jira/browse/THRIFT-5082) - Add a Class reference for PHP enum $_TSPEC +- [THRIFT-5103](https://issues.apache.org/jira/browse/THRIFT-5103) - PHP 7.4 THttpClient deprecated error +- [THRIFT-5130](https://issues.apache.org/jira/browse/THRIFT-5130) - Use Apcu instead of APC +- [THRIFT-5132](https://issues.apache.org/jira/browse/THRIFT-5132) - Warning in TSocket when using ssl connection +- [THRIFT-5199](https://issues.apache.org/jira/browse/THRIFT-5199) - Infinite loop in PHP TSocket::write when peer closes connection +- [THRIFT-5336](https://issues.apache.org/jira/browse/THRIFT-5336) - Add possibility to setup connection timeout in TCurlClient + +### Python + +- [THRIFT-2087](https://issues.apache.org/jira/browse/THRIFT-2087) - unicode decode errors +- [THRIFT-4002](https://issues.apache.org/jira/browse/THRIFT-4002) - Thrift exceptions are not hashable in Python 3 +- [THRIFT-5107](https://issues.apache.org/jira/browse/THRIFT-5107) - Travis build fails with missing Python 3.3 or newer? +- [THRIFT-5165](https://issues.apache.org/jira/browse/THRIFT-5165) - Python THttpClient saves cookie when Set-Cookie response header is present +- [THRIFT-5186](https://issues.apache.org/jira/browse/THRIFT-5186) - AI_ADDRCONFIG: Thrift libraries crash with localhost-only network. +- [THRIFT-5248](https://issues.apache.org/jira/browse/THRIFT-5248) - Python: Make TSocket.isOpen check if the other end is still connected +- [THRIFT-5303](https://issues.apache.org/jira/browse/THRIFT-5303) - Unicode decode errors in _fast_decode +- [THRIFT-5331](https://issues.apache.org/jira/browse/THRIFT-5331) - Python: allow THeaderProtocol to choose which subprotocol to use for outbound connections + +### Ruby + +- [THRIFT-5281](https://issues.apache.org/jira/browse/THRIFT-5281) - Some warning messages need to be fixed +- [THRIFT-4707](https://issues.apache.org/jira/browse/THRIFT-4707) - Enable maintainers to upload newer versions of Ruby Gem of Thrift +- [THRIFT-5061](https://issues.apache.org/jira/browse/THRIFT-5061) - Pin Ruby's rack version to 2.0.8 +- [THRIFT-5100](https://issues.apache.org/jira/browse/THRIFT-5100) - Gem::InstallError: byebug requires Ruby version >= 2.4.0. +- [THRIFT-5266](https://issues.apache.org/jira/browse/THRIFT-5266) - release ruby library thrift 0.13.0 + +### Rust + +- [THRIFT-4764](https://issues.apache.org/jira/browse/THRIFT-4764) - Rust frontend emits deprecated clippy suppression attributes +- [THRIFT-5071](https://issues.apache.org/jira/browse/THRIFT-5071) - Rust: rust tutorial can not be compiled with rust edition 2018 +- [THRIFT-5158](https://issues.apache.org/jira/browse/THRIFT-5158) - Update Rust Compiler to generate 2018 edition code only +- [THRIFT-5307](https://issues.apache.org/jira/browse/THRIFT-5307) - Rust generated code should compile cleanly with clippy +- [THRIFT-4915](https://issues.apache.org/jira/browse/THRIFT-4915) - Deserializing double into OrderedFloat always returns zero when using TCompactProtocol +- [THRIFT-4995](https://issues.apache.org/jira/browse/THRIFT-4995) - [Rust] Use `ToSocketAddrs` for expressing network addresses +- [THRIFT-5042](https://issues.apache.org/jira/browse/THRIFT-5042) - Fix failing cargo tests +- [THRIFT-5043](https://issues.apache.org/jira/browse/THRIFT-5043) - Make TBufferChannel clonable +- [THRIFT-5111](https://issues.apache.org/jira/browse/THRIFT-5111) - CI fails with error[E0721]: `await` is a keyword in the 2018 edition +- [THRIFT-5131](https://issues.apache.org/jira/browse/THRIFT-5131) - i64 maxint decoding panics with integer-encoding >= 1.1.0 +- [THRIFT-5306](https://issues.apache.org/jira/browse/THRIFT-5306) - Rust library, tutorial, test, cross-test code should not throw any clippy errors + +### Swift + +- [THRIFT-4989](https://issues.apache.org/jira/browse/THRIFT-4989) - Run time exception when using TCompactProtocol +- [THRIFT-5128](https://issues.apache.org/jira/browse/THRIFT-5128) - Swift TFramedTransport does not work using present code +- [THRIFT-5138](https://issues.apache.org/jira/browse/THRIFT-5138) - Swift generator does not escape keywords properly +- [THRIFT-5155](https://issues.apache.org/jira/browse/THRIFT-5155) - Swift 5.1 support +- [THRIFT-5070](https://issues.apache.org/jira/browse/THRIFT-5070) - Swift: Hashable.hashValue is deprecated as a protocol requirement +- [THRIFT-5084](https://issues.apache.org/jira/browse/THRIFT-5084) - Swift: Server-side support for Multiplexing Services +- [THRIFT-5121](https://issues.apache.org/jira/browse/THRIFT-5121) - Logic bug in TMultiplexedProcessor – Swift +- [THRIFT-5125](https://issues.apache.org/jira/browse/THRIFT-5125) - Swift server does not work using present code. +- [THRIFT-5129](https://issues.apache.org/jira/browse/THRIFT-5129) - Swift TSocketTransport cannot be used to connect to client +- [THRIFT-5150](https://issues.apache.org/jira/browse/THRIFT-5150) - TSet does not compile with Swift 5.2 + +### Test Suite + +- [THRIFT-4974](https://issues.apache.org/jira/browse/THRIFT-4974) - Add cross test for Python's Unix domain socket transport +- [THRIFT-5145](https://issues.apache.org/jira/browse/THRIFT-5145) - Streamline --pipe and --named-pipe options in the code base +- [THRIFT-5171](https://issues.apache.org/jira/browse/THRIFT-5171) - Fix maven-ant-tasks to use HTTPS instead of HTTP + +### TypeScript - Library + +- [THRIFT-5003](https://issues.apache.org/jira/browse/THRIFT-5003) - Websocket Connection in Browsers with nodejs code + +### Tutorial + +- [THRIFT-4972](https://issues.apache.org/jira/browse/THRIFT-4972) - Add Makefile.am to the Perl tutorial +- [THRIFT-4975](https://issues.apache.org/jira/browse/THRIFT-4975) - Add Makefile.am to the PHP tutorial +- [THRIFT-5051](https://issues.apache.org/jira/browse/THRIFT-5051) - Fix Python tutorials to address THRIFT-4002 +- [THRIFT-5052](https://issues.apache.org/jira/browse/THRIFT-5052) - Make the Go tutorial executable to the end +- [THRIFT-5122](https://issues.apache.org/jira/browse/THRIFT-5122) - Fix memory leak in c_glib tutorial server + ## 0.13.0 From 518163afbd7c4f6733d12fa6f2de3db612fda947 Mon Sep 17 00:00:00 2001 From: Ting Sun <11710108@mail.sustech.edu.cn> Date: Sun, 24 Jan 2021 00:18:46 +0800 Subject: [PATCH 752/756] Update README.md Patch: Ting Sun This closes #2317 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a5af5aba78b..a22f222cfcb 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ From the top directory, do: ./configure You may need to specify the location of the boost files explicitly. -If you installed boost in /usr/local, you would run configure as follows: +If you installed boost in `/usr/local`, you would run configure as follows: ./configure --with-boost=/usr/local @@ -157,7 +157,7 @@ Run ./configure --help to see other configuration options Please be aware that the Python library will ignore the --prefix option and just install wherever Python's distutils puts it (usually along -the lines of /usr/lib/pythonX.Y/site-packages/). If you need to control +the lines of `/usr/lib/pythonX.Y/site-packages/`). If you need to control where the Python modules are installed, set the PY_PREFIX variable. (DESTDIR is respected for Python and C++.) From ebfa771a26e406da947f72ae8d87602c892435cc Mon Sep 17 00:00:00 2001 From: Christopher Tubbs Date: Thu, 4 Feb 2021 14:13:24 -0500 Subject: [PATCH 753/756] THRIFT-5274: Enforce Java 8 compatibility Client: Java Patch: Christopher Tubbs This closes #2325 * Enforce Java 8 compatibility using the new `--release` flag introduced in JDK9, so that all generated bytecode follows Java 8 strict compatibility, even when building with newer JDK versions (9 or later) (this fixes NoSuchMethodError with ByteBuffer, and other potential incompatibilities in bytecode generation that would make the code unable to run on a Java 8 JRE) * Also strictly enforce the JDK version used to build the project by ensuring it is at least version 1.8, and will fail fast when building the Java libraries if this condition is not met. --- lib/java/build.gradle | 5 +++++ lib/java/gradle/sourceConfiguration.gradle | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/lib/java/build.gradle b/lib/java/build.gradle index 9184f7b97e3..57a8e1e26f5 100644 --- a/lib/java/build.gradle +++ b/lib/java/build.gradle @@ -19,6 +19,11 @@ // Using the legacy plugin classpath for Clover so it can be loaded optionally buildscript { + // strictly enforce the minimum version of Java required to build and fail fast + if (JavaVersion.current() < JavaVersion.VERSION_1_8) { + throw new GradleException("The java version used is ${JavaVersion.current()}, but must be at least ${JavaVersion.VERSION_1_8}") + } + repositories { mavenCentral() google() diff --git a/lib/java/gradle/sourceConfiguration.gradle b/lib/java/gradle/sourceConfiguration.gradle index 07c2a7f1f77..d15c1179f30 100644 --- a/lib/java/gradle/sourceConfiguration.gradle +++ b/lib/java/gradle/sourceConfiguration.gradle @@ -46,6 +46,9 @@ sourceSets { // ---------------------------------------------------------------------------- // Compiler configuration details +// These two properties are still needed on JDK8, and possibly used directly by +// plugins. However, the '--release' option added below makes these two +// properties redundant when building with JDK9 or later. sourceCompatibility = '1.8' targetCompatibility = '1.8' @@ -53,6 +56,10 @@ tasks.withType(JavaCompile) { options.encoding = 'UTF-8' options.debug = true options.deprecation = true + // the following is to build with Java 8 specifications, even when building with JDK9 or later + if (JavaVersion.current() > JavaVersion.VERSION_1_8) { + options.compilerArgs.addAll(['--release', '8']) + } // options.compilerArgs.addAll('-Xlint:unchecked') } From 705f37783343ebc5aaee0e504c31ea4abe149cd5 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 4 Feb 2021 17:06:38 +0100 Subject: [PATCH 754/756] Version 0.14.0 --- debian/changelog | 6 ++++++ doap.rdf | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/debian/changelog b/debian/changelog index f91921a5592..8fd900c7395 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +thrift (0.14.0) stable; urgency=low + + * update to 0.14.0 + + -- Apache Thrift Developers Thu, 04 Feb 2021 17:00:00 -0500 + thrift (0.13.0) stable; urgency=low * update to 0.13.0 diff --git a/doap.rdf b/doap.rdf index 77b9113247a..6094de72821 100755 --- a/doap.rdf +++ b/doap.rdf @@ -57,6 +57,11 @@ + + Apache Thrift + 2021-02-04 + 0.14.0 + Apache Thrift 2019-10-11 From 0be1b7d7580f90cfdc3206f7fd7cf4306dcf5817 Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 4 Feb 2021 22:20:37 +0100 Subject: [PATCH 755/756] Version 0.14.0 --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index b2d726cbda4..eddc05fd90e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -187,6 +187,7 @@ - [THRIFT-5203](https://issues.apache.org/jira/browse/THRIFT-5203) - Remove Unused toString Method in TSerializer - [THRIFT-5237](https://issues.apache.org/jira/browse/THRIFT-5237) - Implement MAX_MESSAGE_SIZE and consolidate limits into a TConfiguration class - [THRIFT-5247](https://issues.apache.org/jira/browse/THRIFT-5247) - Avoiding meaningless System.copy +- [THRIFT-5274](https://issues.apache.org/jira/browse/THRIFT-5274) - Thrift 0.13.0 does not work with JDK8 - [THRIFT-5287](https://issues.apache.org/jira/browse/THRIFT-5287) - Log When Client Connections are Dropped - [THRIFT-5288](https://issues.apache.org/jira/browse/THRIFT-5288) - Move Support for ByteBuffer into TTransport From 8411e189b0af09e5baad34031555870cf692c1ad Mon Sep 17 00:00:00 2001 From: Jens Geyer Date: Thu, 4 Feb 2021 22:41:50 +0100 Subject: [PATCH 756/756] Version 0.14.0 --- .gitignore | 18 +++ Makefile.am | 7 + compiler/cpp/Makefile.am | 1 + compiler/cpp/src/Makefile.am | 5 + .../thrift-t_php_generator.o-a60a38e9 | 0 lib/go/test/Makefile.am | 32 ++-- lib/netstd/Makefile.am | 24 +-- lib/nodets/.gitignore | 1 - lib/ocaml/.gitignore | 11 -- lib/perl/Makefile.am | 2 + lib/php/Makefile.am | 142 ++++++++++-------- lib/rs/Makefile.am | 5 +- lib/ts/.gitignore | 2 - test/Makefile.am | 3 + test/go/Makefile.am | 3 +- test/netstd/Client/.gitignore | 2 - test/netstd/Server/.gitignore | 2 - tutorial/cl/Makefile.am | 3 +- tutorial/netstd/.gitignore | 1 - tutorial/netstd/Interfaces/.gitignore | 3 - tutorial/php/Makefile.am | 3 +- 21 files changed, 155 insertions(+), 115 deletions(-) delete mode 100644 compiler/cpp/src/thrift/generate/thrift-t_php_generator.o-a60a38e9 delete mode 100644 lib/nodets/.gitignore delete mode 100644 lib/ocaml/.gitignore delete mode 100644 lib/ts/.gitignore delete mode 100644 test/netstd/Client/.gitignore delete mode 100644 test/netstd/Server/.gitignore delete mode 100644 tutorial/netstd/.gitignore delete mode 100644 tutorial/netstd/Interfaces/.gitignore diff --git a/.gitignore b/.gitignore index 76d9e502b96..cf73c4c2f0f 100644 --- a/.gitignore +++ b/.gitignore @@ -278,6 +278,18 @@ project.lock.json /lib/go/src /lib/go/test/gopath/ /lib/go/test/ThriftTest.thrift +/lib/nodets/test-compiled/ +/lib/ocaml/_build/ +/lib/ocaml/_tags +/lib/ocaml/configure +/lib/ocaml/setup.data +/lib/ocaml/setup.ml +/lib/ocaml/myocamlbuild.ml +/lib/ocaml/*/META +/lib/ocaml/*/*.mllib +/lib/ocaml/*/*.mldylib +/lib/ocaml/Makefile +/lib/ocaml/OCamlMakefile /lib/rs/target/ /lib/rs/Cargo.lock /lib/rs/test/Cargo.lock @@ -292,6 +304,8 @@ project.lock.json /lib/rs/*.iml /lib/rs/**/*.iml /lib/swift/.build +/lib/ts/test/build/ +/lib/ts/test/gen-* /libtool /ltmain.sh /missing @@ -343,6 +357,8 @@ project.lock.json /test/netstd/*.vspx /test/netstd/*.vsp /test/netstd/*.diagsession +/test/netstd/Client/ThriftTest +/test/netstd/Server/ThriftTest /test/netstd/Thrift /test/php/php_ext_dir/ /test/rs/Cargo.lock @@ -399,5 +415,7 @@ project.lock.json /tutorial/rs/bin /tutorial/rs/target /tutorial/rs/Cargo.lock +/tutorial/netstd/Interfaces/shared +/tutorial/netstd/Interfaces/tutorial /ylwrap diff --git a/Makefile.am b/Makefile.am index f9d59ef4451..c5d9c41dba1 100755 --- a/Makefile.am +++ b/Makefile.am @@ -132,9 +132,15 @@ style-local: codespell --write-changes --skip=$(skipped_files) --disable-colors EXTRA_DIST = \ + .asf.yaml \ .clang-format \ .dockerignore \ .editorconfig \ + .eslintignore \ + .eslintrc.json \ + .flake8 \ + .gitattributes \ + .gitignore \ .travis.yml \ .rustfmt.toml \ ApacheThrift.nuspec \ @@ -156,6 +162,7 @@ EXTRA_DIST = \ LICENSE \ NOTICE \ package.json \ + package-lock.json \ phpcs.xml.dist \ README.md \ sonar-project.properties \ diff --git a/compiler/cpp/Makefile.am b/compiler/cpp/Makefile.am index 16514ca815d..05c9121716b 100644 --- a/compiler/cpp/Makefile.am +++ b/compiler/cpp/Makefile.am @@ -115,6 +115,7 @@ EXTRA_DIST = \ README.md \ CMakeLists.txt \ test \ + tests \ $(WINDOWS_DIST) #clean-local: diff --git a/compiler/cpp/src/Makefile.am b/compiler/cpp/src/Makefile.am index 0297708e1e5..5111fd55038 100644 --- a/compiler/cpp/src/Makefile.am +++ b/compiler/cpp/src/Makefile.am @@ -37,3 +37,8 @@ thrift_libparse_a_SOURCES = thrift/thrifty.yy \ clean-local: $(RM) thrift/thriftl.cc thrift/thrifty.cc thrift/thrifty.h thrift/thrifty.hh + + +EXTRA_DIST = \ + thrift/logging.cc \ + thrift/windows/config.h diff --git a/compiler/cpp/src/thrift/generate/thrift-t_php_generator.o-a60a38e9 b/compiler/cpp/src/thrift/generate/thrift-t_php_generator.o-a60a38e9 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/lib/go/test/Makefile.am b/lib/go/test/Makefile.am index 4419577696d..2f748c6fa59 100644 --- a/lib/go/test/Makefile.am +++ b/lib/go/test/Makefile.am @@ -111,28 +111,30 @@ client: stubs EXTRA_DIST = \ dontexportrwtest \ tests \ + common \ BinaryKeyTest.thrift \ + ConflictNamespaceServiceTest.thrift \ + ConflictNamespaceTestA.thrift \ + ConflictNamespaceTestB.thrift \ + ConflictNamespaceTestC.thrift \ + ConflictNamespaceTestD.thrift \ + ConflictNamespaceTestSuperThing.thrift \ + DontExportRWTest.thrift \ + DuplicateImportsTest.thrift \ + ErrorTest.thrift \ + EqualsTest.thrift \ GoTagTest.thrift \ + IgnoreInitialismsTest.thrift \ IncludesTest.thrift \ + InitialismsTest.thrift \ MultiplexedProtocolTest.thrift \ NamespacedTest.thrift \ + NamesTest.thrift \ OnewayTest.thrift \ OptionalFieldsTest.thrift \ - RequiredFieldTest.thrift \ RefAnnotationFieldsTest.thrift \ - UnionDefaultValueTest.thrift \ - UnionBinaryTest.thrift \ + RequiredFieldTest.thrift \ ServicesTest.thrift \ TypedefFieldTest.thrift \ - ErrorTest.thrift \ - NamesTest.thrift \ - InitialismsTest.thrift \ - DontExportRWTest.thrift \ - IgnoreInitialismsTest.thrift \ - ConflictNamespaceTestA.thrift \ - ConflictNamespaceTestB.thrift \ - ConflictNamespaceTestC.thrift \ - ConflictNamespaceTestD.thrift \ - ConflictNamespaceTestSuperThing.thrift \ - ConflictNamespaceServiceTest.thrift \ - EqualsTest.thrift + UnionBinaryTest.thrift \ + UnionDefaultValueTest.thrift diff --git a/lib/netstd/Makefile.am b/lib/netstd/Makefile.am index abb680cc403..f1a87a24260 100644 --- a/lib/netstd/Makefile.am +++ b/lib/netstd/Makefile.am @@ -41,25 +41,31 @@ clean-local: EXTRA_DIST = \ README.md \ + Directory.Build.props \ + Benchmarks/Thrift.Benchmarks \ Tests/Thrift.IntegrationTests/Protocols \ Tests/Thrift.IntegrationTests/Thrift.IntegrationTests.csproj \ - Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj \ - Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs \ - Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift \ + Tests/Thrift.PublicInterfaces.Compile.Tests \ Tests/Thrift.PublicInterfaces.Compile.Tests/CassandraTest.thrift \ - Tests/Thrift.Tests/Thrift.Tests.csproj \ - Tests/Thrift.Tests/Protocols \ + Tests/Thrift.PublicInterfaces.Compile.Tests/optional_required_default.thrift \ + Tests/Thrift.PublicInterfaces.Compile.Tests/Properties/AssemblyInfo.cs \ + Tests/Thrift.PublicInterfaces.Compile.Tests/Thrift.PublicInterfaces.Compile.Tests.csproj \ Tests/Thrift.Tests/Collections \ - Thrift/TApplicationException.cs \ - Thrift/TBaseClient.cs \ - Thrift/TException.cs \ - Thrift/Thrift.csproj \ + Tests/Thrift.Tests/DataModel \ + Tests/Thrift.Tests/Protocols \ + Tests/Thrift.Tests/Thrift.Tests.csproj \ Thrift/Collections \ Thrift/Processor \ Thrift/Properties \ Thrift/Protocol \ Thrift/Server \ + Thrift/TApplicationException.cs \ + Thrift/TBaseClient.cs \ + Thrift/TConfiguration.cs \ + Thrift/TException.cs \ + Thrift/Thrift.csproj \ Thrift/Transport \ + Thrift/*.snk \ Thrift.sln \ build.cmd \ build.sh \ diff --git a/lib/nodets/.gitignore b/lib/nodets/.gitignore deleted file mode 100644 index c7aba89242d..00000000000 --- a/lib/nodets/.gitignore +++ /dev/null @@ -1 +0,0 @@ -test-compiled/ diff --git a/lib/ocaml/.gitignore b/lib/ocaml/.gitignore deleted file mode 100644 index 0d9a6af4677..00000000000 --- a/lib/ocaml/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -_build/ -_tags -configure -setup.data -setup.ml -myocamlbuild.ml -*/META -*/*.mllib -*/*.mldylib -Makefile -OCamlMakefile diff --git a/lib/perl/Makefile.am b/lib/perl/Makefile.am index abae1e77fe4..84009bd160a 100644 --- a/lib/perl/Makefile.am +++ b/lib/perl/Makefile.am @@ -40,6 +40,7 @@ EXTRA_DIST = \ coding_standards.md \ build-cpan-dist.sh \ Makefile.PL \ + MANIFEST.SKIP \ test.pl \ lib/Thrift.pm \ lib/Thrift.pm \ @@ -63,6 +64,7 @@ EXTRA_DIST = \ lib/Thrift/UnixSocket.pm \ lib/Thrift/Type.pm \ lib/Thrift/Transport.pm \ + tools/FixupDist.pl \ README.md THRIFT = @top_builddir@/compiler/cpp/thrift diff --git a/lib/php/Makefile.am b/lib/php/Makefile.am index ce353f0e6b3..1857d034b49 100755 --- a/lib/php/Makefile.am +++ b/lib/php/Makefile.am @@ -40,113 +40,125 @@ endif phpdir = $(PHP_PREFIX)/ php_DATA = \ - lib/TMultiplexedProcessor.php + lib/TMultiplexedProcessor.php phpbasedir = $(phpdir)/Base phpbase_DATA = \ - lib/Base/TBase.php + lib/Base/TBase.php phpclassloaderdir = $(phpdir)/ClassLoader phpclassloader_DATA = \ - lib/ClassLoader/ThriftClassLoader.php + lib/ClassLoader/ThriftClassLoader.php phpexceptiondir = $(phpdir)/Exception phpexception_DATA = \ - lib/Exception/TApplicationException.php \ - lib/Exception/TException.php \ - lib/Exception/TProtocolException.php \ - lib/Exception/TTransportException.php + lib/Exception/TApplicationException.php \ + lib/Exception/TException.php \ + lib/Exception/TProtocolException.php \ + lib/Exception/TTransportException.php phpfactorydir = $(phpdir)/Factory phpfactory_DATA = \ - lib/Factory/TBinaryProtocolFactory.php \ - lib/Factory/TCompactProtocolFactory.php \ - lib/Factory/TJSONProtocolFactory.php \ - lib/Factory/TProtocolFactory.php \ - lib/Factory/TStringFuncFactory.php \ - lib/Factory/TTransportFactory.php + lib/Factory/TBinaryProtocolFactory.php \ + lib/Factory/TCompactProtocolFactory.php \ + lib/Factory/TJSONProtocolFactory.php \ + lib/Factory/TProtocolFactory.php \ + lib/Factory/TStringFuncFactory.php \ + lib/Factory/TTransportFactory.php phpprotocoldir = $(phpdir)/Protocol phpprotocol_DATA = \ - lib/Protocol/TBinaryProtocolAccelerated.php \ - lib/Protocol/TBinaryProtocol.php \ - lib/Protocol/TCompactProtocol.php \ - lib/Protocol/TJSONProtocol.php \ - lib/Protocol/TMultiplexedProtocol.php \ - lib/Protocol/TProtocol.php \ - lib/Protocol/TProtocolDecorator.php \ - lib/Protocol/TSimpleJSONProtocol.php + lib/Protocol/TBinaryProtocolAccelerated.php \ + lib/Protocol/TBinaryProtocol.php \ + lib/Protocol/TCompactProtocol.php \ + lib/Protocol/TJSONProtocol.php \ + lib/Protocol/TMultiplexedProtocol.php \ + lib/Protocol/TProtocol.php \ + lib/Protocol/TProtocolDecorator.php \ + lib/Protocol/TSimpleJSONProtocol.php phpprotocoljsondir = $(phpprotocoldir)/JSON phpprotocoljson_DATA = \ - lib/Protocol/JSON/BaseContext.php \ - lib/Protocol/JSON/ListContext.php \ - lib/Protocol/JSON/LookaheadReader.php \ - lib/Protocol/JSON/PairContext.php + lib/Protocol/JSON/BaseContext.php \ + lib/Protocol/JSON/ListContext.php \ + lib/Protocol/JSON/LookaheadReader.php \ + lib/Protocol/JSON/PairContext.php phpprotocolsimplejsondir = $(phpprotocoldir)/SimpleJSON phpprotocolsimplejson_DATA = \ - lib/Protocol/SimpleJSON/CollectionMapKeyException.php \ - lib/Protocol/SimpleJSON/Context.php \ - lib/Protocol/SimpleJSON/ListContext.php \ - lib/Protocol/SimpleJSON/MapContext.php \ - lib/Protocol/SimpleJSON/StructContext.php + lib/Protocol/SimpleJSON/CollectionMapKeyException.php \ + lib/Protocol/SimpleJSON/Context.php \ + lib/Protocol/SimpleJSON/ListContext.php \ + lib/Protocol/SimpleJSON/MapContext.php \ + lib/Protocol/SimpleJSON/StructContext.php phpserializerdir = $(phpdir)/Serializer phpserializer_DATA = \ - lib/Serializer/TBinarySerializer.php + lib/Serializer/TBinarySerializer.php phpserverdir = $(phpdir)/Server phpserver_DATA = \ - lib/Server/TServerSocket.php \ - lib/Server/TForkingServer.php \ - lib/Server/TServer.php \ - lib/Server/TServerTransport.php \ - lib/Server/TSimpleServer.php + lib/Server/TServerSocket.php \ + lib/Server/TForkingServer.php \ + lib/Server/TServer.php \ + lib/Server/TServerTransport.php \ + lib/Server/TSimpleServer.php phpstringfuncdir = $(phpdir)/StringFunc phpstringfunc_DATA = \ - lib/StringFunc/Mbstring.php \ - lib/StringFunc/Core.php \ - lib/StringFunc/TStringFunc.php + lib/StringFunc/Mbstring.php \ + lib/StringFunc/Core.php \ + lib/StringFunc/TStringFunc.php phptransportdir = $(phpdir)/Transport phptransport_DATA = \ - lib/Transport/TBufferedTransport.php \ - lib/Transport/TCurlClient.php \ - lib/Transport/TFramedTransport.php \ - lib/Transport/THttpClient.php \ - lib/Transport/TMemoryBuffer.php \ - lib/Transport/TNullTransport.php \ - lib/Transport/TPhpStream.php \ - lib/Transport/TSocket.php \ - lib/Transport/TSocketPool.php \ - lib/Transport/TTransport.php + lib/Transport/TBufferedTransport.php \ + lib/Transport/TCurlClient.php \ + lib/Transport/TFramedTransport.php \ + lib/Transport/THttpClient.php \ + lib/Transport/TMemoryBuffer.php \ + lib/Transport/TNullTransport.php \ + lib/Transport/TPhpStream.php \ + lib/Transport/TSocket.php \ + lib/Transport/TSocketPool.php \ + lib/Transport/TTransport.php phptypedir = $(phpdir)/Type phptype_DATA = \ - lib/Type/TMessageType.php \ - lib/Type/TType.php \ - lib/Type/TConstant.php + lib/Type/TMessageType.php \ + lib/Type/TType.php \ + lib/Type/TConstant.php clean-local: if [ -f src/ext/thrift_protocol/Makefile ]; then cd src/ext/thrift_protocol/ && $(MAKE) clean; fi EXTRA_DIST = \ - lib \ - src/autoload.php \ - src/ext/thrift_protocol/config.m4 \ - src/ext/thrift_protocol/config.w32 \ - src/ext/thrift_protocol/php_thrift_protocol.cpp \ - src/ext/thrift_protocol/php_thrift_protocol.h \ - src/Thrift.php \ - src/TStringUtils.php \ - coding_standards.md \ - thrift_protocol.ini \ - README.apache.md \ - README.md + lib \ + src/autoload.php \ + src/ext/thrift_protocol/config.m4 \ + src/ext/thrift_protocol/config.w32 \ + src/ext/thrift_protocol/php_thrift_protocol.cpp \ + src/ext/thrift_protocol/php_thrift_protocol.h \ + src/Thrift.php \ + src/TStringUtils.php \ + coding_standards.md \ + thrift_protocol.ini \ + README.apache.md \ + README.md \ + test/Fixtures.php \ + test/TestValidators.thrift \ + test/JsonSerialize/JsonSerializeTest.php \ + test/Protocol/BinarySerializerTest.php \ + test/Protocol/TJSONProtocolFixtures.php \ + test/Protocol/TJSONProtocolTest.php \ + test/Protocol/TSimpleJSONProtocolFixtures.php \ + test/Protocol/TSimpleJSONProtocolTest.php \ + test/Validator/BaseValidatorTest.php \ + test/Validator/ValidatorTest.php \ + test/Validator/ValidatorTestOop.php + MAINTAINERCLEANFILES = \ - Makefile.in + Makefile.in diff --git a/lib/rs/Makefile.am b/lib/rs/Makefile.am index 0a34120a3b9..6d74348ebe3 100644 --- a/lib/rs/Makefile.am +++ b/lib/rs/Makefile.am @@ -43,4 +43,7 @@ clean-local: EXTRA_DIST = \ src \ Cargo.toml \ - README.md + README.md \ + release.sh \ + RELEASING.md + diff --git a/lib/ts/.gitignore b/lib/ts/.gitignore deleted file mode 100644 index 24f250ed05e..00000000000 --- a/lib/ts/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -test/build/ -test/gen-* diff --git a/test/Makefile.am b/test/Makefile.am index f1c808ed6d5..4ef12e06a71 100755 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -150,6 +150,7 @@ EXTRA_DIST = \ EnumTest.thrift \ FullCamelTest.thrift \ Include.thrift \ + Identifiers.thrift \ Int64Test.thrift \ JavaBeansTest.thrift \ JavaBinaryDefault.thrift \ @@ -166,7 +167,9 @@ EXTRA_DIST = \ StressTest.thrift \ ThriftTest.thrift \ TypedefTest.thrift \ + Types.thrift \ UnsafeTypes.thrift \ + Service.thrift \ SpecificNameTest.thrift \ known_failures_Linux.json \ test.py \ diff --git a/test/go/Makefile.am b/test/go/Makefile.am index 3cf6a70ee59..eae153c2944 100644 --- a/test/go/Makefile.am +++ b/test/go/Makefile.am @@ -62,4 +62,5 @@ genmock: gopath EXTRA_DIST = \ src/bin \ - src/common + src/common \ + genmock.sh diff --git a/test/netstd/Client/.gitignore b/test/netstd/Client/.gitignore deleted file mode 100644 index 67d55106a4b..00000000000 --- a/test/netstd/Client/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# ignore for autogenerated files -/ThriftTest diff --git a/test/netstd/Server/.gitignore b/test/netstd/Server/.gitignore deleted file mode 100644 index 67d55106a4b..00000000000 --- a/test/netstd/Server/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# ignore for autogenerated files -/ThriftTest diff --git a/tutorial/cl/Makefile.am b/tutorial/cl/Makefile.am index 2d15b08eb8f..70c5e0730a5 100755 --- a/tutorial/cl/Makefile.am +++ b/tutorial/cl/Makefile.am @@ -62,4 +62,5 @@ EXTRA_DIST = \ shared-implementation.lisp \ thrift-tutorial.asd \ make-tutorial-server.lisp \ - make-tutorial-client.lisp + make-tutorial-client.lisp \ + load-locally.lisp diff --git a/tutorial/netstd/.gitignore b/tutorial/netstd/.gitignore deleted file mode 100644 index 9938bb237a0..00000000000 --- a/tutorial/netstd/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!**/*.pfx \ No newline at end of file diff --git a/tutorial/netstd/Interfaces/.gitignore b/tutorial/netstd/Interfaces/.gitignore deleted file mode 100644 index 2e7446e33e7..00000000000 --- a/tutorial/netstd/Interfaces/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# ignore for autogenerated files -/shared -/tutorial diff --git a/tutorial/php/Makefile.am b/tutorial/php/Makefile.am index 65f48795140..3d30ad999e6 100755 --- a/tutorial/php/Makefile.am +++ b/tutorial/php/Makefile.am @@ -33,4 +33,5 @@ clean-local: EXTRA_DIST = \ PhpServer.php \ - PhpClient.php + PhpClient.php \ + runserver.py